Tool

Remember codebase discoveries across agent sessions

capn-hook is persistent memory for coding agents - it saves which files answer a question, so the next session skips re-exploring the codebase.

Works with claudecodexgithub

91
Spark score
out of 100
Updated 27 days ago
Version 0.2.2
Models
claude

Add to Favorites

Why it matters

Eliminate redundant codebase exploration by giving coding agents persistent memory that recalls where things live, automatically invalidating saved answers when files change so agents spend 77% fewer tokens on repeat questions.

Outcomes

What it gets done

01

Recall file locations for previously-answered codebase questions instantly

02

Save hard-won discoveries with backing files and content fingerprints

03

Auto-delete stale answers when any backing file changes or disappears

04

Inject ask-first charting contract into Claude Code and Codex sessions

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/cyrusnuevodia-capn-hook | bash

Overview

Capn Hook

capn-hook is persistent memory for coding agents that saves which files answer a hard-won codebase question, letting a future session recall the answer in one command instead of re-exploring, while auto-deleting any answer whose backing files have since changed - measured at 77% fewer tokens on repeat questions across five production codebases. Use it on codebases where Claude Code or Codex repeatedly re-discovers the same file locations across sessions; it depends on the agent voluntarily following its injected ask-then-chart instruction, and offers no benefit for one-off, single-session work.

What it does

capn-hook is persistent memory for coding agents: when an agent spends real time figuring out where something lives in a codebase, capn saves the files that answer the question, so the next session gets the answer back in one command instead of re-exploring from scratch - and the moment the underlying files change, the saved answer deletes itself automatically. In an evaluation across 60 real developer questions on 5 production codebases (Dub, Polar, PostHog, Twenty, Documenso), an agent recalling from capn used 77% fewer tokens than one exploring cold, with every answer correct in both arms and the right recall hit on all 60 questions - the project reports a charting session paying for itself in about 1.6 recalls.

capn init installs a session-start hook for Claude Code and Codex that injects one short instruction (capn context): ask capn before searching the codebase, and save a discovery after it was hard-won. That's the entire integration - no wrapper, no middleware, no forced behavior; the model reads the instruction and decides when to use it. The workflow is three commands: capn ask "<question>" returns JSONL with the exact files that answer a question on a hit, or exits 1 with a stderr nudge to explore on a miss (a miss costs seconds, re-exploring costs minutes); capn chart "<question>" --files a,b --details "..." records a small, focused, answerable question plus the files that answer it, hashing (sha256) each backing file at save time; and staleness is handled automatically - if any backing file changes or disappears, the entry is deleted before it can ever answer incorrectly. The commands are deliberately named chart and unchart, not add and update, because entries are never edited: an answer is either still true (its files are unchanged) or worthless, and the worst case of an incorrectly-deleted entry is simply the agent re-exploring, which is exactly what would happen without capn.

Each chart is a single local Markdown file (.capn/entries/<id>.md) with YAML frontmatter (file hashes, timestamp) and plain-text content, human-readable and browsable, not just tool-consumable. A derived reverse index (.capn/map.json) maps file paths to current hashes and affected entry ids, rebuildable from entry frontmatter if it's missing or corrupted. Recall runs on QMD, defaulting to hybrid semantic search (downloading embedding models on first use, roughly 300MB up to ~2GB for the full pipeline) or a fully deterministic, zero-download BM25 keyword-search mode via capn init --no-embedding. The whole .capn/ directory is gitignored by default - it's local, disposable agent memory, safe to delete and rebuild by re-exploring.

When to use - and when NOT to

Use capn-hook on any codebase where a coding agent (Claude Code or Codex today) repeatedly has to rediscover the same "where does X live" answers across sessions - large or unfamiliar codebases, or projects with a lot of repeat AI-assisted work, are where the token savings compound. It's a fit for teams that want that memory to stay local, gitignored, and disposable rather than shared or persisted centrally.

It's not useful for one-off, single-session work where there's no "next time" to benefit from a cached answer, and it doesn't help with questions whose answers aren't tied to specific files (the mechanism is entirely file-hash-based staleness detection). It also depends on the agent actually following the injected instruction to ask-before-search and chart-after-discovery - there's no forced enforcement, so an agent that ignores the hint simply gets no benefit, not an error.

Inputs and outputs

Install and initialize per project:

npm install -g capn-hook
cd /path/to/your/project
capn init            # .capn/, capn's QMD index, Claude Code hooks, and Codex hooks
capn init --git      # also install a post-commit hook that prunes

Input is a natural-language question (capn ask) or a question plus its backing file paths and optional detail notes (capn chart). Output is JSONL search hits on capn ask (or exit code 1 with a stderr nudge on a miss), and a new Markdown chart entry on capn chart. Additional commands: capn unchart <id> (delete one entry), capn bust <path> (delete every entry backed by one file), capn prune (delete every entry whose files changed or vanished), and capn list (print all charted entries, human-readable).

Integrations

capn-hook integrates with Claude Code (.claude/settings.json, SessionStart hook) and Codex (.codex/hooks.json, SessionStart hook) out of the box, both injecting the same capn context instruction; the core CLI and chart format are agent-agnostic, so other agents can integrate by calling the same CLI directly. Recall search runs through QMD, in-process against capn's own isolated SQLite index (.capn/qmd/index.sqlite) - it never sees or shares data with a host qmd install you might already use separately.

Who it's for

Developers running Claude Code or Codex against large or actively-explored codebases who want their agent to stop paying the same token and time cost to rediscover the same "where does this live" answers across sessions, especially teams that want that memory kept local, disposable, and automatically self-invalidating rather than manually maintained. It is licensed under MIT.

Source README

๐Ÿงข๐Ÿช cap'n hook

Don't grep the same mystery twice.

Persistent 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.

77% fewer tokens on repeat questions

Across 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.

How the eval was run, full numbers, and raw evidence โ†’ ยท Who capn is for โ†’ ยท Use cases โ†’

The problem

Coding agents forget everything between sessions. The route from "where are payment webhooks handled?" to "src/api/webhooks.ts, handlers in src/billing/handlers/" costs real time and tokens - and evaporates when the session ends. Tomorrow's session pays for the same discovery again.

How it works

capn init installs 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) is the entire integration - no wrapper, no middleware, no forced behavior. The model reads it and decides.

From there the loop is three moves:

1. Ask before searching.

capn ask "where are payment webhooks handled?"

A 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.

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:

capn chart "where are payment webhooks handled?" \
  --files src/api/webhooks.ts,src/billing/handlers/stripe.ts \
  --details "Router starts near line 40; Stripe handler owns signature checks."

Each backing file is fingerprinted (sha256) at save time.

Good charts are atomic, not giant context dumps. Split separable facts into separate charts, but include multiple files when they jointly answer one focused question.

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 and unchart, not add and update: 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.

Worst case, an entry is deleted and the agent re-explores - which is exactly what it would have done without capn.

Install

npm install -g capn-hook
# or
bun install -g capn-hook

cd /path/to/your/project
capn init            # .capn/, capn's QMD index, Claude Code hooks, and Codex hooks
capn init --git      # also install a post-commit hook that prunes

The published CLI ships as JavaScript and runs under Bun when Bun is available, falling back to Node.js.

Prefer to delegate? Tell your coding agent to fetch and follow INSTALL.md - it's written for the agent to execute, not for you to copy by hand.

Agent File Hook Command Effect
Claude Code .claude/settings.json SessionStart /usr/bin/env capn context Inject the ask-first charting contract
Codex .codex/hooks.json SessionStart /usr/bin/env capn context Inject the ask-first charting contract

Recall runs on QMD: semantic (hybrid) search by default, plain keyword (BM25) search with capn init --no-embedding. 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 can take a few seconds once they're present; the BM25 path downloads nothing and is fully deterministic.

Already use qmd yourself? capn's index is its own sqlite under .capn/ - your collections never see it, and it never sees yours.

Commands

Command Description
capn init [--git] [--embedding|--no-embedding] Set up .capn/, capn's QMD index, hooks, and the .capn/ gitignore line
capn context Print the ask-first charting contract (used by the SessionStart hook)
capn ask "<question>" Print JSONL hits for relevant charted answers after pruning stale entries first
capn chart "<question>" --files <a,b> [--details "<extra context>"] Record a discovery, hashing each backing file
capn unchart <id> Manually delete one chart entry
capn bust <path> Delete every chart entry backed by one file
capn prune Delete every chart entry whose files changed or vanished
capn list Print charted entries, human-readable

The chart

.capn/entries/<id>.md - 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 gitignores .capn/, so this memory stays local to the working copy.

---
capn: 1
id: 9f3a1c2e
at: 2026-07-03T18:00:00.000Z
files:
  src/api/webhooks.ts: 2f4c0b9c3e0a0c7b5d5d7f8f0a6e2d1c4b8a6f1e2d3c4b5a6978877665544332
---

# Where are payment webhooks handled?

Router starts near line 40; Stripe handler owns signature checks.

.capn/map.json - 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.

{
  "src/api/webhooks.ts": {
    "hash": "2f4c0b9c3e0a0c7b5d5d7f8f0a6e2d1c4b8a6f1e2d3c4b5a6978877665544332",
    "entries": ["9f3a1c2e"]
  }
}

.capn/config.json stores local project options such as {"embedding": true}. .capn/qmd/index.sqlite is generated by the QMD SDK, with normal sqlite -wal/-shm siblings beside it; the markdown under .capn/entries/ remains the durable source of truth, and capn init can rebuild the index.

The whole .capn/ directory is local agent memory and is gitignored by capn init. Chart entries are episodic memory about the codebase: local, disposable, and safe to rebuild by re-exploring.

Design principles

  • Chart or unchart, never update. Staleness is decided by content hashes, not judgment calls.
  • Answers are never stale. capn ask removes 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, isolated from any host qmd install. No daemon, no server - nothing to keep running.

FAQ

Common questions

Discussion

Questions & comments ยท 0

Sign In Sign in to leave a comment.