Go look at ~/.claude/projects/. There’s a JSONL file for every session you’ve ever had. Every turn, every tool call, every file touched, every response. All of it, append-only, going back to your first session. Ours goes back to January — 57MB, 1,026 sessions, 76,000 turns. Just sitting there the whole time. We didn’t get tipped off. We just looked. The format is clean too. Each line is a JSON object — role, timestamp, content, tool calls, everything structured. It’s not logs in the “good luck parsing this” sense. It’s a complete episodic record. If you had a three hour session last Tuesday where you figured out something important, that conversation exists in full fidelity on your drive right now. You just have no way to get back to it. So we built an indexer. SQLite+FTS5, temporal edges between turns, MCP server on top. From inside any Claude Code session now: search_sessions(“remember when we fixed that auth bug last month”) recall_session(“a8f2c441”) thread_recall(root_id, depth=8) That last one does a BFS traversal through the temporal edge graph to reconstruct a thread across session boundaries. The “I told you this two weeks ago” problem just disappears. The data was never gone — nobody had built the recall layer on top of it yet. We also support importing conversations.json from the claude.ai data export, so your web chat history lives in the same index as your CLI sessions. The other half is compaction. Everyone who uses Claude Code seriously has felt this — context fills up, compaction fires, and you’re suddenly explaining your whole project again to something that should already know. We wired the full hook chain to stop that from happening. The thing nobody writes down is that transcript_path in the PreCompact payload isn’t always populated at hook fire time. You build your whole save logic around it, ship it, and then hit silent failures you can’t explain. We did exactly that. The fix is that Stop needs to write a checkpoint on every single turn, not just at session end. Then when PreCompact fires it always has something fresh to fall back to no matter what. Then SessionStart reads the source field — “compact” means compaction just fired, “resume” means the app restarted, “startup” is a fresh session, “clear” is intentional. Each gets different behavior. None of this is documented anywhere, you just have to figure it out. The net result: compaction stops being a hard reset. It’s a cache miss. We’ve also been in the middle of the upstream conversation at anthropics/claude-code#47023 — seven independent memory projects, all built by different people, all independently hitting the exact same walls and arriving at the exact same hook requirements. Bella, NEXO Brain, Cozempic, world-model-mcp. None of us were coordinating. We all just needed the same things. The formal hook spec is getting worked out there if you want to follow it. Repo: https://github.com/Haustorium12/continuity-v2 — MIT, hooks take about five minutes, MCP server is one Python file. Happy to answer questions. submitted by /u/haustorium12
Originally posted by u/haustorium12 on r/ClaudeCode
