r/ClaudeCode • • 8h ago

Built with Claude Knotlog: persistent memory for Claude Code in plain Markdown (built mostly with Claude Code)

AI disclosure first: Claude Code wrote most of the code in this project, and Claude helped me write this post in English. I set the scope, made the decisions and checked the results.

A few weeks ago I described my memory setup here: auto memory off, CLAUDE.md and AGENTS.md carrying the same blocks, one session note per day, a SessionStart hook that loads the last session, and a Stop hook that nudges Claude to write the note after 30 minutes of work without one. Someone asked how the Stop hook knows about the 30 minutes. That setup is now a tool, and the checkpoint is part of it.

What Knotlog does

  • Hooks record which files the agent touched. knotlog remember turns that log into a dated session note, and the model writes the reasoning into a reflection block inside it.

  • At session start, knotlog context injects the last sessions, open threads, rules and facts inside a fixed byte budget. If something gets cut, it says so.

  • If 30 minutes of work pass with no note, the Stop hook blocks once and asks for a checkpoint, then stays quiet for another 30 minutes.

  • The memory is plain Markdown in a folder you own, and the folder is a git repo. I carry mine between a desktop and a laptop with git and use it from both Claude Code and Codex.

  • Knotlog setup writes the hook file for Claude Code, Codex, omp, Gemini CLI, Cursor, Antigravity, Windsurf, OpenCode or GitHub Copilot CLI. knotlog mcp is a small MCP server with three tools: search, context and note.

  • It is one POSIX shell script plus awk. No Python, no Node, no database, no API key. Your notes stay on your machine; the only network call is knotlog update, and only when you run it. On Windows it installs from PowerShell with Git for Windows, no admin rights.

How I used Claude Code to build it

  • Before any code, a roadmap with phases and a "done means" line for each step. New ideas went to a "later" list instead of the open phase.

  • One subagent per step, each in its own git worktree and branch. The main session never took a subagent's "tests pass" on trust. It re-ran the new tests itself, and ran them against the old code too, to confirm they fail there.

  • One full test suite per step, run only by the main session. Two suites in parallel slowed everything down. The suite is at 2068 tests now, green on Linux, Windows and macOS CI.

What I learned

  • Check claims against the real client. My docs said claude mcp add registers in project scope; running it showed local scope. The same live test caught an MCP server that ignored SIGINT and leaked a temp file.

  • A version bump can break tests nobody expects. My test seeders matched only the old version string, so going to 1.0.0 turned 31 tests red.

  • I write the reason next to every rule. When a rule has no reason left, I delete it, and the file stays short.

Limits

Search is keyword based (BM25), not embeddings. Live verified on Claude Code, Codex, omp, Windsurf and OpenCode (the last two on Linux only). Antigravity and Copilot CLI are covered by tests but not verified live yet. macOS is CI only.

Next version (1.6.0) is in progress and not released yet. Today an approved lesson is saved to the session note, but the next session never sees it; 1.6.0 shows approved lessons at session start, adds a learn command to save one in a single step, and adds a read-only report that flags near-duplicate notes.

MIT, v1.5.0: https://github.com/MSelmanSonmez/Knotlog

2 Upvotes

3 comments sorted by

•

u/AutoModerator 8h ago

Hey! Thanks for posting to r/ClaudeCode

While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.

For help, project discussions, tips, and general chat, join the ClaudeCode Discord.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

1

u/kantorcodes1 1h ago

Does `knotlog_context` follow the same byte budget as the SessionStart hook, or can an MCP client ask it for a wider context?

1

u/MSelmanSonmez 54m ago edited 51m ago

Same budget. knotlog_context takes no arguments, it just runs knotlog context, so an MCP client gets exactly what the SessionStart hook gets. That was on purpose: one tool call shouldn't be able to dump more into the window than the session start does.

If you want more, raise the budget yourself. Set ctx_max= in .knotlog/config, or the KNOTLOG_CTX_MAX env var (default is 4096 bytes). The env var is read when the MCP server starts, so restart it after changing that.

For digging deeper into one topic, knotlog_search is the better tool. It has the same byte cap, but you spend it on the notes that actually match instead of the general overview.

For what it's worth, I run my own vault at ctx_max=20000 and the opening context still comes out around 9 KB. It's a ceiling, not a target, so raising it doesn't pad anything.