librarian
Review the librarian's pending memory promotion proposals and lesson candidates queued from past sessions.
Skill by onlooker-community
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/onlooker-community-librarian
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: writing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/librarian
What's inside
- Skill name
librarian- Description
- Review the librarian's pending memory promotion proposals and lesson candidates queued from past sessions. Walk pending entries with the user one at a time, surfacing provenance and conflict state, and route each to accept (writes the typed memory file and updates MEMORY.md), reject (writes a body-hash tombstone so the same content won't re-propose), or defer (leave in the queue). Lesson candidates route separately to confirm (with a visibility), pass, or defer, with unconfirm to take back a confirmation before the jury sees it. Use when the user types `/librarian`, `/librarian review`, `/librarian triage`, `/librarian status`, `/librarian list`, `/librarian lessons`, `/librarian lessons review`, or `/librarian lessons judge`, or asks to review librarian proposals or lesson candidates.
- License
- MIT
- Instructions
- 177 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Librarian: Promotion Queue Review
You are operating the **Librarian** review surface — the user-facing control for promoting per-session artifacts (decisions, dead-ends, open questions captured by Archivist) into the user's durable typed memory store.
Auto-promotion of MEMORY.md proposals is intentionally off, full stop — nothing in this skill or the worker ever writes to `~/.claude/projects/<encoded>/memory/` unattended. Librarian queues proposals; the user (with your help) confirms each one. Every accept writes a real file there, so every accept matters.
Lessons are a separate queue with a separate default. By default this walk is also how a lesson gets confirmed and judged — nobody moves without you. But when a project turns on `lesson_auto.enabled`, the detached worker (never this skill) may itself assert a parked candidate's version-independence and dispatch its jury, with no human present — see ADR-004. That path never touches MEMORY.md, never bypasses this walk's `pass`/`veto` verbs, and only ever produces a *held* lesson behind a veto window (`/librarian lessons queue`, `/librarian lessons veto`) — but it is real auto-promotion of a lesson's scope assertion, and the sentence above about memory proposals must not be read as also covering it.
## Parse the request
Read the user's argument after `/librarian`:
- no argument, or `review`, `triage`, `walk` → **walk the queue** (default)
- `list` → print the pending table and stop
- `status` → print one-line counts and stop
- a proposal id (starts with a ULID-shaped string) → jump straight to **show** for that id
- `lessons`, `lessons review` → **walk the lesson queue** (see below)
- `lessons list` / `lessons status` → print and stop (`lessons list --confirmed` lists confirmed lessons instead of pending ones)
- `lessons judge` → **run the jury over confirmed candidates** (see below)
- `lessons queue` → print held lessons and stop
- `lessons veto <id> [reason]` → kill a held lesson before it ships
- `lessons promote <id>` → run `librarian_cli lessons promote <id>` once, report its output, and stop. This is how a lesson judged but not promoted gets its pool entry or declined row; the SessionStart line names this verb when one is stranded
If the user passes a free-form intent ("clear out the queue", "what's pending?"), map it to `review` or `list` as appropriate.
## Run the control surface
Source the plugin helpers and invoke `librarian_cli`. Run this in a single bash call when you need state:
```bash
set -uo pipefail
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
export CLAUDE_PLUGIN_ROOT="$PLUGIN_ROOT"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-config.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/onlooker-project-key.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-storage.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-emit.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-lesson-storage.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-lesson-validate.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-lesson-review.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-lesson-rubric.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-lesson-judge.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-author-key.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-lesson-promote.sh"
source "$CLAUDE_PLUGIN_ROOT/scripts/lib/librarian-cli.sh"
# action is one of: list | show <id> | accept <id> | reject <id> [reason] | defer <id> | status
# or: lessons <list [--confirmed]|show <id>|confirm <id> <visibility> [--justification TEXT]|pass <id> [reason]|unconfirm <id>|defer <id>|status>
librarian_cli "<action>" "<args...>"
```
`librarian_cli` resolves the project key from the current working directory automatically and routes writes to the typed memory store under `${CLAUDE_CONFIG_DIR}/projects/${CLAUDE_PROJECT_ENCODED}/memory/` (falling back to `$HOME/.claude` when Claude Code exports no config dir) (deriving the encoded path from `cwd` when the env var is unset).
## The review walkthrough
For `review` (the default), loop:
1. Call `librarian_cli list`. If the output says `No pending proposals.`, tell the user the queue is clear and stop.
2. Take the first pending id from the table. Call `librarian_cli show <id>` to render the proposal's provenance, classifier confidence, conflict state, and full body.
3. Present the proposal to the user in plain English. Lead with the title and the proposed memory **type** (user / feedback / project / reference) — those determine where it lands in the user's memory store. If the **conflict_state** is anything other than `none` (typically `near_duplicate` or `contradicts_existing`), call this out explicitly and recommend a careful read before accepting.
4. Ask the user how to route it: **accept**, **reject** (optionally with a reason), **defer** (revisit next session), or **skip** (move on without recording a decision).
5. Route the answer:
- **accept** → `librarian_cli accept <id>`. Confirm the resulting path Librarian printed and move to the next proposal.
- **reject** → `librarian_cli reject <id> "<reason>"`. The reason is optional but valuable — it's recorded on the proposal and the tombstone is keyed on body hash so the same content won't be re-proposed.
- **defer** → `librarian_cli defer <id>`. The proposal stays pending; mention it'll resurface next session.
- **skip** → don't call the CLI for this id, move to the next proposal.
6. After each routed decision, fetch the next pending id (the previous one will have flipped status, so `list` reorders naturally) and repeat. When `list` returns no rows, finish with `librarian_cli status` so the user sees the final counts.
For `list` and `status`, just call `librarian_cli <action>` once and render the output.
## The lesson walkthrough
Lesson candidates are a separate queue from memory proposals — confirming one is a step toward publishing beyond this machine, not writing a local file, so it gets its own walk rather than folding into the loop above.
For `lessons` / `lessons review` (default for the `lessons` route), loop:
1. Call `librarian_cli lessons list`. If the output says `No pending lessons.`, tell the user the queue is clear and stop.
2. Take the first pending id. Call `librarian_cli lessons show <id>` to render it.
3. Present the candidate to the user in plain English, showing: `claim`, `rationale`, `evidence.resolution`, `applies_to.stack`, `scope.versions` (or the scope kind if unversioned), and the source artifact id. If `show` prints a `refused:` line, the unattended path was asked to justify this candidate as version-independent and declined. Show the user that reason verbatim, as the model's objection rather than a verdict: it is why the candidate is still waiting for them, and they may disagree with it. `(no reason given)` means the model refused without saying why. If `show` prints a `held:` line, the user deferred or unconfirmed this candidate earlier; say so, since it is why the unattended path has not touched it.
4. Ask the user how to route it: **confirm** (with a visibility), **pass** (optionally with a reason), or **defer**.
5. Route the answer:
- **confirm** → `librarian_cli lessons confirm <id> <visibility> [--justification TEXT]`. Confirming **requires** a visibility (`private`, `org`, or `public`) — never call confirm without one. `--justification` rewrites the scope to `version_independent` and requires `org` or `public` visibility: a `private` lesson runs no jury, so its justification would go unchecked. If the user wants version-independence at `private`, tell them why it's refused rather than silently dropping the justification.
- **A parked candidate** (`show` reports `scope: {"kind":"unscoped"}`, and `list` marks the row "needs scope") has no version scope at all: the transform could not bind one and left it to the user. Confirming it **requires** a justification — why the lesson holds regardless of version — and therefore `org` or `public`, because a `private` lesson runs no jury and the justification would go unchecked. Do not offer `private` for one. Ask for the justification in the user's own words and never write it for them: it is the assertion a jury will judge, and inventing it puts words in their mouth that leave this machine.
- **pass** → `librarian_cli lessons pass <id> "<reason>"`. The reason is optional.
- **defer** → `librarian_cli lessons defer <id>`. The candidate stays pending; mention it'll resurface next session, and that the unattended path will leave it alone until they decide.
6. After each routed decision, fetch the next pending id and repeat. When `list` returns no rows, finish with `librarian_cli lessons status` so the user sees the final count.
A confirm made at the wrong visibility isn't stuck that way — `librarian_cli lessons unconfirm <id>` takes it back, returning the lesson to pending so the user can confirm it again at the right visibility. It only works on a `confirmed` lesson: a `passed` lesson stays passed, because that decision already has its own record and unconfirm won't touch it.
**Which decisions hold when the unattended path is on.** With `lesson_auto.enabled`, a scan can confirm a parked candidate on a model's justification. `defer` and `unconfirm` both hold a candidate against that: it stays pending for the user and the unattended path skips it. A later `confirm` by the user clears the hold. `pass` is the durable "never share this". A held candidate is still the user's to decide; nothing releases it automatically.
Finding the lesson is its own step, because `lessons list` shows only the pending queue and a confirmed lesson is by definition not in it. The user regretting a confirm is usually back in a later session with the claim in mind and no id, so start from `librarian_cli lessons list --confirmed`, which prints the same `<id> <claim>` rows for everything confirmed and not yet judged. Then `librarian_cli lessons show <id>` — its `visibility` line is what tells you which tier the lesson currently sits at, and whether unconfirming is what the user actually wants.
For `lessons list`, `lessons list --confirmed`, and `lessons status`, just call `librarian_cli lessons <action>` once and render the output.
For `lessons judge`, run the jury over confirmed candidates:
1. Call `librarian_cli lessons list --confirmed --json`. Each row carries `id`,
`visibility`, and the full `candidate`. If the array is empty, tell the user
there is nothing awaiting judgment and stop.
2. **Report the batch before spending anything.** Say how many candidates are
confirmed and how many are `public`, and ask whether to proceed. This is the
most expensive step in the pipeline. If the user declines, stop — nothing is
written and every candidate stays `confirmed`.
3. For each candidate, in order:
- **If `visibility` is `private`, dispatch no judges at all.** Call
`librarian_cli lessons judge <id> '[]'` and move on. Private lessons run no
jury; that is what makes cost scale with intent rather than artifact volume.
- Otherwise spawn **both** `tribunal-judge-standard` and
`tribunal-judge-adversarial` with the Task tool. Give each the candidate's
`claim`, `rationale`, `evidence.resolution`, and `applies_to`, plus the
rubric criteria for that lesson **verbatim** from
`librarian_cli lessons rubric <id>`. That prints each criterion
with its weight, floor and definition. Pass the **id**, not the
visibility: a lesson the unattended path asserted (`asserted_by: model`)
is checked against a stricter rubric that adds `disclosure` even at
`org`, and `lessons rubric <id>` is what resolves the rubric the verdict
will actually be recorded against. Pass the definitions, not just
the names: given the bare word, judges read **disclosure** asFrom onlooker-community/ecosystem, MIT.
More from onlooker-community/ecosystem
- 0.565score
lineage
onlooker-community
Answer "why does this line exist?" — trace a file, or a specific line, back to the change, prompt, agent, and session that produced it.
SkillAFreshness: AClaude Code +9 - 0.565score
cartographer
onlooker-community
Audit CLAUDE.md, AGENTS.md, and .claude/rules/ instruction files for contradictions, stale references, dead rules, scope collisions, and entities no…
SkillAFreshness: AClaude Code +9 - 0.565score
counsel
onlooker-community
Run the weekly observability synthesis on demand and render the coaching brief in the conversation.
SkillAFreshness: AClaude Code +9 - 0.565score
tribunal
onlooker-community
Run a task under multi-agent quality gates.
SkillAFreshness: AClaude Code +9 - 0.565score
warden
onlooker-community
Inspect and control the Warden content gate.
SkillAFreshness: AClaude Code +9 - 0.560score
writing-tests
onlooker-community
How to write tests in the Onlooker ecosystem repo — bats integration tests for hooks and the node:test schema suite.
SkillAFreshness: AClaude Code +9 - 0.555score
list-prompt-rules
onlooker-community
List all prompt rules (global + project) with their pattern, guidance, and per-session fire status.
SkillAFreshness: AClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 24, 2026 (5 days ago)
- Last release
- Oct 24, 2026 (5 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/onlooker-community/ecosystem
- Website
- onlooker.dev
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from onlooker-community
- 0.565score
lineage
onlooker-community
Answer "why does this line exist?" — trace a file, or a specific line, back to the change, prompt, agent, and session that produced it.
SkillAFreshness: AClaude Code +9 - 0.565score
cartographer
onlooker-community
Audit CLAUDE.md, AGENTS.md, and .claude/rules/ instruction files for contradictions, stale references, dead rules, scope collisions, and entities no…
SkillAFreshness: AClaude Code +9 - 0.565score
counsel
onlooker-community
Run the weekly observability synthesis on demand and render the coaching brief in the conversation.
SkillAFreshness: AClaude Code +9 - 0.565score
tribunal
onlooker-community
Run a task under multi-agent quality gates.
SkillAFreshness: AClaude Code +9 - 0.565score
warden
onlooker-community
Inspect and control the Warden content gate.
SkillAFreshness: AClaude Code +9 - 0.560score
writing-tests
onlooker-community
How to write tests in the Onlooker ecosystem repo — bats integration tests for hooks and the node:test schema suite.
SkillAFreshness: AClaude Code +9
Cite this page
librarian skill. Agent Mart. https://agentmart.dev/skills/onlooker-community-librarian (last updated 2026-10-24)