{"slug": "show-hn-capn-hook-for-coding-agents-don-t-grep-the-same-mystery-twice", "title": "Show HN: Capn-hook for coding agents – don't grep the same mystery twice", "summary": "Developer CyrusNuevoDia released Capn-hook, an open-source tool that gives coding agents persistent memory by saving file locations for previously answered questions and automatically deleting stale answers when source files change. In evaluations across five production codebases, agents using Capn-hook used 77% fewer tokens than cold-start exploration while maintaining 100% answer accuracy, reducing token costs and session time for recurring developer queries.", "body_md": "*Don't grep the same mystery twice.*\n\nPersistent memory for coding agents. When your agent spends ten minutes figuring out where something lives in your codebase, capn saves the files that answer the question. The next session gets them back in one command instead of re-exploring — and the moment the underlying files change, the saved answer deletes itself.\n\nAcross 60 real developer questions on 5 production codebases (Dub, Polar, PostHog, Twenty, Documenso), an agent recalling from capn used **77% fewer tokens** than an agent exploring cold — every answer correct in both arms, the right chart recalled on all 60 questions, and a charting session paying for itself in ~1.6 recalls.\n\n[How the eval was run, full numbers, and raw evidence →](/CyrusNuevoDia/capn-hook/blob/main/eval/RESULTS.md) · [Who capn is for →](/CyrusNuevoDia/capn-hook/blob/main/docs/audience.md) · [Use cases →](/CyrusNuevoDia/capn-hook/blob/main/docs/use-cases.md)\n\nCoding agents forget everything between sessions. The route from \"where are payment webhooks handled?\" to \"`src/api/webhooks.ts`\n\n, handlers in `src/billing/handlers/`\n\n\" costs real time and tokens — and evaporates when the session ends. Tomorrow's session pays for the same discovery again.\n\n`capn init`\n\ninstalls a session-start hook for Claude Code and Codex. Every new session, the agent sees one short note: **before searching the codebase, ask capn; after a hard-won discovery, save it.** That note (`capn context`\n\n) is the entire integration — no wrapper, no middleware, no forced behavior. The model reads it and decides.\n\nFrom there the loop is three moves:\n\n**1. Ask before searching.**\n\n```\ncapn ask \"where are payment webhooks handled?\"\n```\n\nA hit returns JSONL with the exact files that answer the question, skipping the whole search. A miss exits 1 with a nudge on stderr to explore and chart what it finds — a miss costs seconds; re-exploring costs minutes.\n\n**2. Save what was expensive to learn.** When the agent works out an answer the hard way, it records a small, answerable question and the files that answer it, with optional details for extras like line numbers or gotchas:\n\n```\ncapn chart \"where are payment webhooks handled?\" \\\n  --files src/api/webhooks.ts,src/billing/handlers/stripe.ts \\\n  --details \"Router starts near line 40; Stripe handler owns signature checks.\"\n```\n\nEach backing file is fingerprinted (sha256) at save time.\n\nGood charts are atomic, not giant context dumps. Split separable facts into separate charts, but include multiple files when they jointly answer one focused question.\n\n**3. Stale answers delete themselves.** If any backing file changes or disappears, the entry is removed before it can ever answer again. Saved answers are never edited — an answer is either still true (its files haven't changed) or it's worthless. That's why the commands are `chart`\n\nand `unchart`\n\n, not `add`\n\nand `update`\n\n: capn treats your codebase like a coastline. The agent charts what it has explored; when the coastline shifts, the old chart gets thrown out and the agent re-charts on the next encounter.\n\nWorst case, an entry is deleted and the agent re-explores — which is exactly what it would have done without capn.\n\n```\nnpm install -g capn-hook\n# or\nbun install -g capn-hook\n\ncd /path/to/your/project\ncapn init            # .capn/, capn's QMD index, Claude Code hooks, and Codex hooks\ncapn init --git      # also install a post-commit hook that prunes\n```\n\nThe published CLI ships as JavaScript and runs under Bun when Bun is available, falling back to Node.js.\n\nPrefer to delegate? Tell your coding agent to fetch and follow [INSTALL.md](https://github.com/CyrusNuevoDia/capn-hook/blob/main/INSTALL.md) — it's written for the agent to execute, not for you to copy by hand.\n\n| Agent | File | Hook | Command | Effect |\n|---|---|---|---|---|\n| Claude Code | `.claude/settings.json` |\nSessionStart | `/usr/bin/env capn context` |\nInject the ask-first charting contract |\n| Codex | `.codex/hooks.json` |\nSessionStart | `/usr/bin/env capn context` |\nInject the ask-first charting contract |\n\nRecall runs on [QMD](https://github.com/tobi/qmd): semantic (hybrid) search by default, plain keyword (BM25) search with `capn init --no-embedding`\n\n. The default path downloads embedding models on first use (about 300MB up front, up to ~2GB for the full hybrid pipeline) and a cold `capn ask`\n\ncan take a few seconds once they're present; the BM25 path downloads nothing and is fully deterministic.\n\nAlready use qmd yourself? capn's index is its own sqlite under `.capn/`\n\n— your collections never see it, and it never sees yours.\n\n| Command | Description |\n|---|---|\n`capn init [--git] [--embedding|--no-embedding]` |\nSet up `.capn/` , capn's QMD index, hooks, and the `.capn/` gitignore line |\n`capn context` |\nPrint the ask-first charting contract (used by the SessionStart hook) |\n`capn ask \"<question>\"` |\nPrint JSONL hits for relevant charted answers after pruning stale entries first |\n`capn chart \"<question>\" --files <a,b> [--details \"<extra context>\"]` |\nRecord a discovery, hashing each backing file |\n`capn unchart <id>` |\nManually delete one chart entry |\n`capn bust <path>` |\nDelete every chart entry backed by one file |\n`capn prune` |\nDelete every chart entry whose files changed or vanished |\n`capn list` |\nPrint charted entries, human-readable |\n\n`.capn/entries/<id>.md`\n\n— one local markdown file per question. Entries are plain text you can open and read; the chart is browsable by humans, not just tools. `capn init`\n\ngitignores `.capn/`\n\n, so this memory stays local to the working copy.\n\n```\n---\ncapn: 1\nid: 9f3a1c2e\nat: 2026-07-03T18:00:00.000Z\nfiles:\n  src/api/webhooks.ts: 2f4c0b9c3e0a0c7b5d5d7f8f0a6e2d1c4b8a6f1e2d3c4b5a6978877665544332\n---\n\n# Where are payment webhooks handled?\n\nRouter starts near line 40; Stripe handler owns signature checks.\n```\n\n`.capn/map.json`\n\n— a derived reverse index from file path to current hash and entry ids. If it is missing or corrupt, capn rebuilds it from entry frontmatter.\n\n```\n{\n  \"src/api/webhooks.ts\": {\n    \"hash\": \"2f4c0b9c3e0a0c7b5d5d7f8f0a6e2d1c4b8a6f1e2d3c4b5a6978877665544332\",\n    \"entries\": [\"9f3a1c2e\"]\n  }\n}\n```\n\n`.capn/config.json`\n\nstores local project options such as `{\"embedding\": true}`\n\n. `.capn/qmd/index.sqlite`\n\nis generated by the QMD SDK, with normal sqlite `-wal`\n\n/`-shm`\n\nsiblings beside it; the markdown under `.capn/entries/`\n\nremains the durable source of truth, and `capn init`\n\ncan rebuild the index.\n\nThe whole `.capn/`\n\ndirectory is local agent memory and is gitignored by `capn init`\n\n. Chart entries are episodic memory about the codebase: local, disposable, and safe to rebuild by re-exploring.\n\n**Chart or unchart, never update.** Staleness is decided by content hashes, not judgment calls.**Answers are never stale.**`capn ask`\n\nremoves invalid entries before returning anything.**The chart is disposable.** Any entry can be deleted at any time; the worst case is the agent re-explores, which is exactly the status quo.**Agent-agnostic core.** The CLI and chart format know nothing about Claude Code; the hooks are a thin adapter. Other agents integrate by calling the same CLI.**Local-first recall.** QMD runs in-process through the SDK against`.capn/qmd/index.sqlite`\n\n, isolated from any host qmd install. No daemon, no server — nothing to keep running.\n\nMIT", "url": "https://wpnews.pro/news/show-hn-capn-hook-for-coding-agents-don-t-grep-the-same-mystery-twice", "canonical_source": "https://github.com/cyrusNuevoDia/capn-hook", "published_at": "2026-07-12 21:17:27+00:00", "updated_at": "2026-07-12 21:35:07.470792+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "artificial-intelligence"], "entities": ["CyrusNuevoDia", "Capn-hook", "Claude Code", "Codex", "Dub", "Polar", "PostHog", "Twenty"], "alternates": {"html": "https://wpnews.pro/news/show-hn-capn-hook-for-coding-agents-don-t-grep-the-same-mystery-twice", "markdown": "https://wpnews.pro/news/show-hn-capn-hook-for-coding-agents-don-t-grep-the-same-mystery-twice.md", "text": "https://wpnews.pro/news/show-hn-capn-hook-for-coding-agents-don-t-grep-the-same-mystery-twice.txt", "jsonld": "https://wpnews.pro/news/show-hn-capn-hook-for-coding-agents-don-t-grep-the-same-mystery-twice.jsonld"}}