Sunday, August 30, 2026

Cursor sessions that survive the chat — tracking work with Obsidian MCP

A Cursor chat is a terrible filing cabinet. It is excellent while it is open. It is gone when you start the next one — or when a Cloud Agent finishes a wave on a different machine. I wanted session memory I can open next week: what we did, which commit we left on, what we decided, and what is still open. That is what obsidian-mcp writes.

Holographic coder connected to floating session notes
The bet: session notes should be files, not a vendor memory API.

The server is local MCP over stdio. Cursor (or Copilot) calls tools. The tools read and write ordinary Markdown in an Obsidian vault. Obsidian does not need to be running. There is no community plugin and no hosted memory database. If I can open the file in a text editor, the memory is real.

What I actually keep

Each project gets one folder under AI Memory/Projects/<slug>/:

Project State.md          # current objective, in-progress, next steps
Sessions/YYYY-MM-DD.md    # timestamped sections for that day
Decisions/YYYY-MM-DD-*.md # one file per durable choice

Project State is the hot brief — what this repo is for right now. It is replaced when status changes. It is not a diary.

Sessions are the diary. capture_work_session appends a timestamped section to today. If I pass the repo path, the note records branch, short SHA, dirty flag, and a short file list. Full diffs never go in. I do not want a second copy of git.

Decisions are the “why.” Architecture choices that the next agent should not re-litigate. Same slug on the same day gets -2, never an overwrite.

This morning’s vault looks like this — a real session note for embabel-v1-learning, not a mock:

Obsidian vault showing AI Memory projects and the 2026-08-30 embabel-v1-learning session
Obsidian on the same files the MCP server wrote: summary, git SHA deadd6b, PRs #2–#10, the 1.0+1.5 branch decision.

The sidebar is the map: blog-updater, cdk-cost-killer, embabel-v1-learning, obsidian-mcp, and the rest of the lab. I do not keep one giant note. I keep one project folder and let the dated session files accumulate. When I open Cursor on that repo tomorrow, the first useful call is not “read the whole vault.” It is get_project_context for that slug — Project State plus the newest sessions and decisions.

The loop I run in Cursor

Cursor connected to an Obsidian vault through MCP stdio
Cursor (or Copilot) talks MCP stdio. The vault is the source of truth.

  1. Before substantial workget_project_context. Continuing a feature, debugging a known area, or answering “why is it like this?” Empty sections if the project is new. Never the entire vault.
  2. After meaningful workcapture_work_session with a short summary, changes, decisions, and next steps. Pass repository_path so the git snapshot lands in the same note.
  3. When a choice should stickrecord_decision. Example from that screenshot: keep Embabel 1.0 and 1.5 on one main; study from the cheat sheet, not a second cookbook.
  4. When overall status movesupdate_project_state. Concise. Current tense.

Lookup is local: search_memory over that project’s files, read_note for one vault-relative path, append_daily_note for a line that belongs on today’s Daily/YYYY-MM-DD.md instead of a project folder.

Retrieve context, implement, capture session, update project state
Retrieve → implement → capture → update state. Skip the capture when the change was a typo.

What I refuse to remember

The Cursor rule that ships with the installer is the product as much as the tools. Typo fixes, formatting-only edits, and one-line mechanical changes are not memory. If every keystroke becomes a session section, I will stop reading the vault — and so will the next agent.

Secrets never land in the vault on purpose. Values that look like keys, tokens, JWTs, or password= assignments are replaced with [redacted-secret] before write. I also never persist .env contents, database credentials, or customer data. Summarize the incident; do not paste the token.

Paths are confined to OBSIDIAN_VAULT_PATH. Absolute note paths, ../ traversal, and symlink escapes are rejected. This is not a general filesystem API. Writes are atomic.

Wire it once

export OBSIDIAN_VAULT_PATH="$HOME/Documents/ObsidianVault"
uv sync

./scripts/install-project.sh \
  --project /path/to/your-app \
  --vault "$OBSIDIAN_VAULT_PATH"

The installer merges .cursor/mcp.json (it does not wipe unrelated servers) and drops the Cursor rule plus Copilot instructions so both assistants use the same habits. Point the env var at a real vault directory. The server does not auto-load .env files.

I already have a product-shaped write-up of the seven tools. This post is the part I needed after the first week of using it: the vault is how I keep Cursor sessions and ongoing work in one place I can see. Open Obsidian when you want the graph. Leave it closed when you just need the assistant to remember the last SHA.

Source: github.com/jmjava/obsidian-mcp

No comments: