Documentation

coldstart, command by command.

coldstart is one binary with two front doors — a CLI (the fast path for any shell-capable agent) and an MCP server (for no-shell clients), with byte-identical output. This page covers the stable core surface; for exhaustive flags, versioned changes, and internals, see the README and docs on GitHub — the source of truth.

The shape of itTwo operations answer navigation — find (which files?) and gs (what is this file, who uses it?) — and the kb family is the notebook: durable, agent-written notes kept honest by the index. That's the whole surface.

Install & setup

Requires Node.js 18+. Install globally, then run init once per project.

your-project
$ npm install -g @cstart/coldstart $ cd your-project $ coldstart init # coldstart.md + client wiring + notebook + hooks + warm-up

init asks two things — the experience (cli, recommended, or mcp) and the client (claude / cursor / codex / other) — then writes the coldstart guidance into the client's own rules file — imported via coldstart.md for Claude Code, inlined directly into .cursor/rules/coldstart.mdc (Cursor) and AGENTS.md (Codex) — and wires the client. It also creates the notebook and, for Claude Code / Codex / Cursor, registers the navigation and notebook hooks. Pass --experience / --client to skip the prompts; the client is never auto-detected.

--experience cli|mcpThe surface to wire. cli is the fast path; mcp also writes an MCP server entry.
--client NAMEclaude, cursor, codex, or other. Determines which config files get wired.
--commit-notebookOpt in to committing the notebook .raw logs so the team can share it. Private by default — see Sharing.

Upgrading: npm install -g @cstart/coldstart@latest, then re-run coldstart init in each project. A version stamp in the keeper's lockfile shuts the old background process down on the next lookup; a fresh one spawns from the new binary.

Removing: coldstart unwire reverses init — it strips coldstart's per-repo wiring (hook entries, the coldstart.md import, the AGENTS.md block, the MCP entry, owned files) without touching your own content in shared files. The notebook is kept by default; --purge also deletes it. Run it per project, then npm uninstall -g @cstart/coldstart.

Codex hook trust: Codex gates hooks behind a trust review, so the notebook/navigation hooks init writes will not fire until you approve them (untrusted hooks are skipped silently) — init cannot pre-trust them (no supported non-interactive path; see openai/codex#21615). When Codex shows "Hooks need review", choose "Trust all and continue". If your Codex app doesn't surface that prompt, launch codex from a terminal in the repo — it appears at startup there; trust persists (keyed by each hook's hash) across surfaces. Re-approve after any coldstart update changes a hook. For automated codex exec runs, pass --dangerously-bypass-hook-trust instead. Project trust (trust_level = "trusted" in config.toml) is a separate gate and does not trust hooks.

The intended flow

findgsRead. Orient with two cheap calls before spending a token reading. Notebook summaries ride along on find, so the orientation step often answers itself.

  • find a concept → ranked candidate files, each with the evidence for why it ranked.
  • gs the best file → its symbols, importers, and per-symbol callers, in one call.
  • Read only the method body you actually need — not the whole file.
Navigation
coldstart find navigation
coldstart find <term> [term…] [flags]
Which files are about this? Ranks files by how many of your query terms each covers — filenames, path segments, exported symbols, plus a repo-wide name-reference pass — and shows why each ranked: which terms it defines vs. imports.
coldstart find
$ coldstart find auth session cookie src/auth/service.ts 3/3 defines auth, session, cookie Summary [fresh] Signs and verifies session cookies. src/middleware/session.ts 2/3 imports session, cookie

Pass every salient identifier from your task — the symbol, the domain noun, the rare token you half-remember — not one distilled keyword. find ranks by coverage and shows where the terms cluster, so often that's enough to answer without opening anything. Its reference pass runs on ripgrep, so it competes with raw grep on speed.

--path GLOBScope to matching paths. Comma-combine; prefix ! to exclude.
--testsInclude test files (excluded by default).
--viaShow name-reference relations — where the terms are referenced, not just declared.
--jsonMachine-readable output.
When find says "no indexed file contains any of […]"Those identifiers aren't in the repo. Don't grep spelling variants — trust the negative.
coldstart gs navigation
coldstart gs <file> [flags]
What is this file, and who uses it? Returns the file's top-level symbols (with line ranges), its 1-hop internal imports, who imports it, and per-symbol cross-file callers — in one call. This is the answer to "who calls this?", not a grep.
coldstart gs
$ coldstart gs src/auth/service.ts symbols signCookie L12 · verify L34 · rotate L61 callers verify ← middleware/session.ts, routes/login.ts imported by 4 files
--symbol a,bDeliver the named method bodies inline — skip a separate Read.
--match TERMFilter a god-file to one area. a|b = OR, /regex/ = regex.
--view VOne of symbols / imports / importers / callers. Default returns all.
--jsonMachine-readable output.
ScopeCallers are one-hop and file-scoped. Named function/constant calls resolve cross-file; member-expression calls (this.method(), api.method()) don't. Chase further hops by running gs on the caller file.
Notebook

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, so the agent can rely on it without re-reading.
  • Recall at prompt time (optional hook) — notes whose titles, aliases, or anchors match the prompt surface as a compact, hard-capped block. Nothing matches → nothing injected.
  • kb search / kb lookup — a search engine over the notebook, and an exact-address lookup before editing a file.

Why it can be trusted

  • Freshness is mechanical. Every anchor is stamped with a content hash at write time; the index re-checks it as the code changes. A drifted note renders evidence changed and the guidance says re-verify — stale knowledge degrades into a labeled hypothesis, not a confident lie.
  • The log is the truth. Notes live in an append-only .raw event log; the Markdown notes are derived and regenerated mechanically. A note is a pure fold of its log.
  • Writes go through a gate. A new note's concept is searched against existing notes first — the agent must merge into a match or declare it new. Duplicates are caught at write time.
  • Concurrent sessions are safe. Per-note append-only logs, exclusive creation of new ids, lossless union-merge of shared notes, atomic renders — concurrent writers never silently merge or lose a note.
  • Corrections happen in-session. An agent that finds a note wrong while the evidence is in context is told to fix or retract it right then.
On token savingsBecause the next agent recalls a verified note instead of re-deriving it, repeated tasks re-spend far fewer tokens orienting. We're holding published benchmark figures until they're reproducible enough to stand behind — the mechanism is the point: recall a fact once written, don't pay to re-derive it.

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

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 | -> [--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.
  • First call exits 3 with candidate matches. Resolve it with --into <id> (merge into an existing note) or --new (declare it genuinely new).
  • Reads a spec file, or - to stream the spec from stdin.
  • Freshly-coined ids are created exclusively — a same-moment duplicate becomes two visible notes, never a silent merge.
Agent-facingThis is the command the capture hook drives at the end of a session. 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, generated fresh, 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.
For the humanAgents use kb search / lookup; this is the view for a person who wants to browse what the agents have been keeping. The generated file self-registers in the notebook's .gitignore.
coldstart kb status / lint / 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 renderRegenerate the derived Markdown notes from the .raw logs.
kb initNotebook-only setup — skeleton + hooks. 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, not one person.

Bigger notebooks, fasterThe corpus grows exactly where the codebase gets worked. On a shared repo, that's every engineer's sessions feeding one knowledge base — and because each note stays anchored to the code, growth stays true instead of rotting.
Under the hood

How the index stays fresh

coldstart is one keeper, thin readers. A single background keeper watches the repo and keeps an on-disk cache current; the readers (find, gs, the MCP server) are stateless and never build. There is no cache TTL — the index is never discarded for being old, it's kept correct.

keeper — coldstart --daemon watches repo → patch/rebuild → saves cache · serves nothing on-disk cache coldstart findreads cache, prints coldstart gsreads cache, prints MCP serverreads cache, stdio
WHILE RUNNING

Patched as you type

Edits debounce (400 ms), then patch incrementally (~2–5 ms/file) or trigger a background rebuild. Re-saved in atomic generations — a reader never loads a half-written mix.

ON START

Reconciled, not rebuilt

Stat-checks every file against its fingerprint plus a git diff, and patches exactly what changed. A branch switch that used to force a full rebuild is now typically a few seconds.

AS A BACKSTOP

Linted & audited

Every patch is checked against index invariants (a violation auto-rebuilds), and a rotating fingerprint audit after each save catches watcher-missed drift.

Full internalsThe exact pipeline (walk → parse → resolve → graph → cache) and per-language resolver notes live in ARCHITECTURE.md on GitHub.

Lifecycle commands

coldstart statusKeepers on this machine: alive? fresh? last patch/rebuild/save? repairs?
coldstart restartKill the current repo's keeper (respawns on next lookup). --root DIR targets another repo; --all kills every keeper.
coldstart indexBuild + save the cache once, up front (single-writer prep).
When anything feels stalecoldstart restart — a fresh keeper reconciles on start, so it comes back correct, not just alive. If something looks structurally wrong, TROUBLESHOOTING.md on GitHub has recovery steps.

MCP tools

For no-shell clients (like Claude Desktop), the same engine is exposed as MCP tools with byte-identical output to the CLI.

find · gsThe two navigation operations.
kb_search · kb_lookupRead the notebook.
kb_write · kb_statusWrite to and inspect the notebook — the MCP server is a writer for kb_write.
Not exposedkb commit and kb view stay CLI/human-only — publishing to git and opening a browser are never agent actions.

Bring your own semantics

coldstart has no embeddings, no generated summaries, no semantic layer computed at index time — on purpose. The semantic layer is the agent. Every consumer is already a frontier model; pre-computing meaning at index time only duplicates that, worse and stale. So the index keeps what's cheap to keep exact — paths, symbols, exports, the import/call graph — and returns why each file ranked. The notebook applies the same rule to memory: it stores and freshness-checks the meaning agents author, and computes none of its own.

Read the argumentThe full case is in PHILOSOPHY.md on GitHub.

Supported languages

Tree-sitter for the parsed set; the notebook's content-hash freshness works on all of them — notes on a Swift repo are as trustworthy as notes on a TypeScript one (they just lack symbol-level freshness).

TypeScriptJavaScriptJSX / TSX VueSvelteAstroAngularJS PythonRuby (Rails)GoRust JavaKotlinC#PHP (Laravel)C++ Groovy / GradleGraphQLYAMLTOMLXML.env

Not indexed: Swift, Dart — no extension mapping; these files aren't walked or parsed. The notebook still works on them.