Librarian
This makes the codex useful. The codex is stored knowledge; the librarian is what walks it and turns "make the import faster" into "the bottleneck is in loader.py:40-72, here's the one change." You stay at high abstraction. The librarian holds the map and reads it for you, then grows it with whatever the walk surfaced.
Try It Now
In a repo that has a codex (run /codex-bootstrap first if it doesn't), ask:
/librarian why is the startup slow?
You'll get a 3-line readback (what it heard, which knowledge nodes are involved, one concrete proposal) before anything changes.
When to fire
Both must be true:
- The request names a goal, behavior, or fix ("make the bot X", "tighten Y", "why did Z happen").
- It does NOT name a specific file/function/line/test.
If the request is concrete ("edit server.ts:120"), skip this skill and just do the edit. If there is no docs/codex/ yet, run /codex-bootstrap first, then come back.
Where the codex lives
docs/codex/INDEX.json- term/alias -> node lookup.docs/codex/nodes/<id>.md- the knowledge nodes.docs/codex/domains.yaml- the domain taxonomy.docs/codex/PRINCIPLES.md- the user's decision rules (consulted in decision mode).docs/GLOSSARY.md- vocabulary not yet promoted to nodes.tools/codex_verify.py- the drift detector.
The protocol
Step 0 - low-stakes bypass
If the request is a pure lookup or definition that wants a short answer and touches no money/deploy/destructive action ("what does X mean", "which file handles Y"), just answer it. No readback ceremony. Skip to a plain reply.
Step 1 - classify
Concrete (names file/function/line)? Exit, just do the edit. Otherwise continue.
Step 2 - walk
Read in this order, skipping anything missing: docs/GLOSSARY.md, then docs/codex/INDEX.json.
Pull 1 to 5 candidate terms (the nouns and goal-verbs) from the request. For each term:
- Hit in INDEX.json (by id or alias): load
nodes/<id>.md. Runpython3 tools/codex_verify.py --node <id>. If it reports DRIFT, record the flag (don't trust stale info). Collect the node'srelated:ids as second-order candidates; include one only if it plausibly feels the blast radius. - Miss but the term is in GLOSSARY.md: draft a new node for it (see Step 5).
- Miss everywhere: flag "unknown: " and read the code directly to answer.
Load just the ## What and ## When-to-touch of each node by default; read ## Where + code_refs only when the proposal will touch those files.
Step 3 - synthesize (the readback)
Produce exactly three lines:
Hearing: <one sentence in the user's own words, the latent goal>
Impacts: [node-id, node-id (DRIFT), node-id (2nd)]
Proposal: <one concrete sentence> [Verified | Inferred | Target]
Label meaning: Verified = every code_ref in the impacted nodes was fresh (verifier matched). Inferred = one or more impacted concepts were drafted, not confirmed against code. Target = the proposal describes a desired state, not current behavior.
Keep Hearing in the user's vocabulary; node names belong only in Impacts. Cap Impacts at ~6 nodes.
Step 4 - confirm or act
- If the proposal is reversible AND Verified AND not money/deploy/destructive: state the readback, do it, report what you did.
- If the proposal is Inferred, Target, irreversible, money-moving, deploys, or any walked node drifted: stop after the readback and ask the user to confirm before acting.
Step 5 - grow the codex (post-execution)
This is what makes the codex compound. After acting:
- New concept surfaced that isn't a node? Draft
docs/codex/nodes/<id>.mdusing the node format (in the codex-bootstrapper skill or any existing node as a template). New nodes shipconfidence: verified. - Run
python3 tools/codex_verify.py --rebuild-indexif any node was added. - If a term was found only by reading code (a "miss everywhere" that should have been a node), that's the signal to add it now. A walk that reads but never writes leaves value on the table.
- [2026-06-30] Convex sync is automatic, not a manual step. A
skill_codex_sync.pyPostToolUse hook (matcherSkill) fires the moment this skill's tool call returns and pushes any node it just wrote to the Chiron Convex DB (sync_to_convex.py --since-mtime 900) plus a session-state upsert + handoff/lineage-pointer refresh (session_capture.py <session_id>). This closes the gap where localdocs/codex/writes could sit unsynced for up to 24h waiting on the decisions-sync heartbeat. Nothing to do here; if Convex ever looks stale after a walk, that's a wiring check (settings.json), not a missing step in this protocol.
Decision mode
When the user asks for a recommendation ("which is best?", "should I X or Y?") or the walk surfaces 2+ real paths:
- Walk as normal (Step 2).
- Enumerate 2-3 genuine options (never a strawman; if only one path makes sense, say so and exit decision mode).
- Read
docs/codex/PRINCIPLES.md. Pull the principles that apply by domain or topic. - Score each option on cost, complexity, reversibility, and principle alignment.
- Pick ONE. The rationale MUST cite a principle by name. "Cleaner" or "feels right" doesn't clear the bar. If no principle resolves the tie, surface the conflict and ask.
Readback becomes four lines:
Hearing: <latent goal>
Impacts: [node-ids]
Options: A) <action> - <tradeoff> B) <action> - <tradeoff>
Decision: <letter> - <rationale citing a principle> [Verified|Inferred|Target]
If PRINCIPLES.md is empty or absent, say so and lean on plain judgment for that one call. Don't fabricate a principle to justify a pick.
Drift handling
When the verifier reports DRIFT on a node:
- Read the file at the node's
path:linesto see what changed. - If it's a rename/move: update the node's
code_refsand re-run the verifier. - If the concept genuinely changed or vanished: flag it to the user, don't silently rewrite. The codex's integrity depends on a human ratifying semantic changes.
Never propose action from a node with unresolved drift.
Anti-patterns
- Walking the codex for a request that already names a file/line. Just edit it.
- A readback that cites nodes you didn't actually verify. Run the verifier before labeling Verified.
- Manufacturing fake options in decision mode.
- Reading the codex but never writing back what the walk surfaced. The growth IS the product.
- Fabricating principles when PRINCIPLES.md is empty. Surface the gap instead.