My coding agents keep a record of what they decided and why, not just what they built
Claude Code and Cursor run on different machines for different kinds of work, and both lose their session's reasoning the moment it ends. Three hooks write it to a shared Obsidian vault instead, decisions, plans, spikes, and a devlog, and one of them refuses to let a session close if enough changed and nothing got recorded.
A session with a coding agent ends and whatever it figured out along the way goes with it. The code survives, since it’s on disk. The reasoning behind the code doesn’t: why this table got a composite index instead of two separate ones, why the retry logic gave up after three attempts instead of five, which approach got tried first and thrown out. Open a new session next week on the same project and the agent starts from the code alone, with no memory of any of that.
Claude Code has a memory system for this, and it’s genuinely good at what it does. Cursor has nothing like it. I run the two on different machines for different kinds of work, Claude Code where I vibecode, Cursor on a separate box for the work I want to sit with, so it was never a question of getting one tool’s session context into the other’s. What I wanted was a record of the reasoning that outlives any single machine: an Obsidian vault, synced with the self-hosted obsidian-livesync plugin, that both machines write into and that also lands on my phone for a quick read when I’m nowhere near either one.
Three hooks doing what a prompt can’t
Telling an agent in its system prompt to “keep a devlog” doesn’t work reliably. It’s one more instruction competing with the task itself, and the task wins almost every time, because the task is enforced by the point of the session and the devlog instruction is enforced by nothing. What actually holds is three separate hooks in the harness, each firing at a different point in the session, backing each other up.
The first hook, session-start-wiki.sh, runs when a session opens and hands the agent the last three devlog entries plus an index of every project in the wiki, so it starts already knowing what happened last time instead of re-deriving it from the code. The context it injects is one fixed block: WIKI: project={slug} vault={wiki_vault}, followed by an instruction to write plans, decisions, spikes, and devlog entries as it works.
The second, wiki-nudge.sh, checks in every fifth turn. If no wiki file has been touched yet this session, it injects a reminder pointing at the exact devlog path to write to and the index file that has to be updated alongside it, and it repeats on the same schedule until something gets written.
The third is the one that actually forces the issue. stop-wiki-enforce.sh runs when the session is about to end, counts how many Write, Edit, or NotebookEdit calls happened in the transcript, and if three or more code changes went by with no devlog or index update to match, it blocks the stop outright. In Claude Code that’s a {"decision": "block"} response the hook returns; in Cursor, which doesn’t expose a transcript path the same way, it falls back to checking whether anything in the wiki directory changed in the last two hours. Either way the session doesn’t get to close clean. The reason for it gets re-fed as the next prompt, and the agent has to either write the entry or explain why this particular session didn’t need one.
A fourth hook applies the same idea to a different failure mode. Long sessions get compacted to fit the context window, and anything unwritten before that happens disappears the same way it would at session end. pre-compact.sh fires right before that compression runs and gives the agent one explicit last chance to write down any plans, decisions, spikes, or concepts from the session, since compaction is the point where the context actually goes away.
What actually gets written
The wiki has a fixed shape: wiki/projects/<slug>/ holds an overview.md, a devlog.md, and subfolders for decisions/, plans/, and spikes/, plus a top-level index.md that lists every project. Each page type has its own template. A decision page has to name the alternatives that were on the table alongside the one that won. A spike page states the question it was answering before it gets to the finding. The devlog format is the strictest: a dated heading, two to four bullets, written as plain fact rather than a “here’s what we did this session” narration, with no name attached and no hedged phrasing softening what happened. That strictness is what keeps a year of entries readable in one sitting rather than turning into the same throat-clearing paragraph with a new date stamped on it.
The hooks themselves are identical on both sides. session-start-wiki.sh, wiki-nudge.sh, and stop-wiki-enforce.sh are deployed to ~/.claude/ and ~/.cursor/ unchanged, same triggers, same thresholds, and only the JSON shape of the block response differs because the two tools expect different formats. The harness’s own docs never claim Cursor needs this more because it lacks a native memory system; that’s my own read of the setup, not a documented rationale. I think it holds up anyway. Claude Code’s memory already softens the cost of a missed devlog entry, where Cursor has no such fallback, so the same devlog is doing more of the actual work for Cursor sessions than for Claude Code ones.
This doesn’t replace what Claude Code’s memory does. That system decides on its own what’s worth keeping and recalls it without me asking, where the wiki only surfaces the specific file a hook decided to inject. What the wiki adds is a shared, greppable record that exists independent of either tool, readable on a phone as easily as on either machine, in a text editor, or in a completely different tool six months from now, because it’s a stack of plain markdown files with a template, sitting on disk, that I could read at 2am with nothing running at all.
The harness’s own README states the philosophy bluntly: “The human never writes the wiki. The LLM writes and maintains all of it.” That line only holds because the enforcement backs it up. Without the stop hook it would just be an aspiration; with it, a session that closes on three or more real changes has to have written the record of them first.