# Librarian

> Walk the project codex to translate an abstract request ("make X faster", "why does Y happen") into a concrete, code-grounded proposal before acting, checking nodes for drift and growing the codex with what it learns. Triggers on "/librarian" or any abstract goal-shaped request in a codex repo. Skip when the user names an exact file/function to edit.

- Skill: `citability/librarian` (Agent Skill)
- Install (CLI): `npx skillmds@latest add citability/librarian`
- Raw SKILL.md: https://api.skillmd.com/api/skills/citability/librarian/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Citability (https://skillmd.com/u/citability)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/citability/librarian

---


# 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:

1. The request names a goal, behavior, or fix ("make the bot X", "tighten Y", "why did Z happen").
2. 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`. Run `python3 tools/codex_verify.py --node <id>`. If it reports DRIFT, record the flag (don't trust stale info). Collect the node's `related:` 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: <term>" 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>.md` using the node format (in the codex-bootstrapper skill or any existing node as a template). New nodes ship `confidence: verified`.
- Run `python3 tools/codex_verify.py --rebuild-index` if 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.py`
  PostToolUse hook (matcher `Skill`) 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 local `docs/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:

1. Walk as normal (Step 2).
2. Enumerate 2-3 genuine options (never a strawman; if only one path makes sense, say so and exit decision mode).
3. Read `docs/codex/PRINCIPLES.md`. Pull the principles that apply by domain or topic.
4. Score each option on cost, complexity, reversibility, and principle alignment.
5. 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:

1. Read the file at the node's `path:lines` to see what changed.
2. If it's a rename/move: update the node's `code_refs` and re-run the verifier.
3. 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.

