Notebook

The kb notebook

A repo-local knowledge base written and read by agents — durable notes kept honest by the index, recalled automatically when a later task matches. Why it's built this way →

The notebook, in depth

A repo-local knowledge base, written and read by agents, living in .coldstart/notebook/. It's the one place semantics belong: authored by the agent that just did the work, kept honest by the index, and recalled when a later task matches. No human writes or grooms it.

What a note is

File note

What a file is for — a single summary, or per-symbol facets for hub files.

Flow note

A cross-file story: ordered steps and the invariants that hold across them.

Lesson

A trap, rule, bug-cause, rationale, or a confirmed absence.

Every note carries anchors — the concrete file paths and symbols its claims rest on. Anchors are what make a note checkable rather than a floating assertion.

Where notes reach the agent

  • Summary lines on find results — a past agent's verified overview, right where the file ranks. fresh means the file is byte-identical to when the summary was verified.
  • Recall at prompt time — injected straight into the agent's context as a compact block before it acts. Matching notes arrive automatically; nothing matches means nothing injected.
  • kb search / kb lookup — search the notebook and exact-address lookup before editing a file.

Why it can be trusted

Freshness is mechanical (content-hash, re-checked on every read — a drifted note renders evidence changed instead of passing as fact), writes go through a dedup gate, and concurrent sessions never silently lose or merge a note. Full mechanics: how the notebook works →

On token savingsBecause the next agent recalls a verified note instead of re-deriving it, repeated tasks re-spend far fewer tokens orienting. In head-to-head benchmarks on real applications: −64% tokens on Arches (Python/Django, 27-query sweep) and −31% tokens on JMRI (Java, 25-query sweep). Cost scales with turns, not output size.

Language-agnostic. The freshness machinery is content-hash based, so the notebook works on any codebase — including languages the navigation index doesn't parse.

When capture happens

Capture is trigger-timed, not every-turn — the hook scores what the session actually read or edited (search hits and path mentions never count) and asks at natural boundaries, when a burst of work settles or a commit lands. The ask is non-blocking: it arrives with your next prompt as a worklist of the files the session touched, each annotated with its existing note's state, and is also written durably to .coldstart/notebook/.worklist-<session>-<agent>.md so a long session can re-read it after the one-shot delivery scrolls away. Missed files simply reappear on the next trigger; a warmed-up repo (notes already fresh) asks less over time.

/capture-notes — capture on demand

Sometimes you know a moment is worth recording before the automatic score crosses — a hard-won insight, a confirmed absence, a decision that didn't touch many files. /capture-notes fires the capture flow immediately, with the same worklist and gate. It never forces a write.

coldstart init wires it for your client: Claude Code and Cursor get a /capture-notes slash command; Codex gets a capture-notes skill. All three run the same one-liner, so it also works by hand:

capture on demand
$ node <install>/hooks/kb-elicit.mjs --manual # prints the capture checklist for this session

.coldstartignore — files that never get notes

coldstart init scaffolds .coldstart/.coldstartignore (gitignore syntax). Built-in defaults are *.json, lockfiles, dist//build//coverage/, minified files, binaries and images, and .env* (notes are committed; secrets must never enter them). Every collaborator gets that baseline; lines you add extend it on your machine.

.coldstart/.coldstartignore
# add your own *.generated.ts docs/ # re-include a built-in default !tsconfig.json

Ignored files are filtered at the root — they never appear in a capture worklist. Logic-bearing configs (vite.config.ts, CI workflows, routes.rb) are deliberately not ignored by default: they carry exactly the gotchas notes exist for.

coldstart kb lookup notebook
coldstart kb lookup <path> [symbol]
Everything known at one exact address. Run it before editing a file to pull the note (and per-symbol facets) that apply to exactly that path.
coldstart kb lookup
$ coldstart kb lookup src/models.py Tile
coldstart kb write notebook · the gate
coldstart kb write <spec.json | array.json | -> [--into <id> | --new]
The write gate. A two-phase, dedup-first path: the note's concept is checked against existing notes before anything is written.
  • Batch is the capture path. The spec file may be a JSON array of notes, written in one call: well-formed notes land, malformed ones are reported together, and the call ends naming any worked file still without a note.
  • A single new flow/lesson exits 3 with candidate matches. Resolve it with --into <id> (merge) or --new (declare it new).
  • Reads a spec file, or - to stream from stdin.
  • Correct a note: {"op":"retract","id":"<id>","target":{"kind":"note"}} removes it, or target one part with target:{kind:"anchor"|"alias"…, key:"…"}.
  • Freshly-coined ids are created exclusively — a same-moment duplicate becomes two notes, never a silent merge.
Agent-facingThis is the command the capture hook drives. You rarely type it by hand.
coldstart kb commit notebook · human-only
coldstart kb commit
The one sanctioned git path for the notebook. Commits only the .raw logs and skeleton — never your feature code, and notes never ride along in a feature commit.
Never an agent actionkb commit is CLI/human-only and is not exposed as an MCP tool. Publishing notes to git is a human decision.
coldstart kb view notebook · human-only
coldstart kb view [--no-open]
Generate a single self-contained HTML browser of the whole notebook and open it in your default browser. No server — one file, freshness stamped at generation time.
coldstart kb view
$ coldstart kb view kb view: wrote .coldstart/notebook/index.html — opening in browser
--no-openWrite index.html but don't launch the browser.

Once generated, the keeper re-renders it whenever notes change, so a browser reload shows the latest — you don't re-run the command.

coldstart kb status / lint / repair / repair-aliases / render notebook
kb statusNotebook health: note counts and per-note freshness at a glance.
kb lintCheck the notebook for structural problems (broken anchors, malformed notes).
kb repairList the notes that are written but unfindable — missing fields a note can't be retrieved without (search aliases, anchor symbols, a flow's verified paths). It prints a worklist and changes nothing: your agent opens each note and the code it names and completes it with an ordinary kb write.
kb repair-aliasesNotes whose identityAliases may no longer describe the file/flow (stale words from an earlier write) — not notes missing aliases entirely. Shows each note's current aliases, 10 per page, and changes nothing itself.
kb renderRegenerate the derived Markdown notes from the .raw logs.
kb initNotebook-only setup. Redundant if you ran coldstart init, which already does this.
kb migrateUpgrade an older notebook's on-disk format.

Sharing with a team

The notebook is private by default.coldstart/ is gitignored. Opt in to sharing and the whole team's agents contribute to one growing corpus.

share the notebook
$ coldstart init --commit-notebook # make .raw committable $ coldstart kb commit # publish notes to git

Once committed, the .raw logs travel with the repo and union-merge across branches and machines — parallel branches of notes reconcile without conflicts. Every teammate's agent both reads from and writes to the same notebook, so the corpus grows at the speed of the whole team.