Learning system interface: stats, search, graduate, clear learnings. Backed by learning.db (SQLite + FTS5).
npx skills add https://github.com/notque/vexjoy-agent --skill retro
This skill wraps scripts/learning-db.py into a user-friendly interface for the learning system. The learning database is the single source of truth—all queries go through the Python CLI, never maintaining a parallel file store.
Parse the user's argument to determine the subcommand. Default to status if no argument given.
| Argument | Subcommand |
|----------|------------|
| (none), status | status |
| list | list |
| search TERM | search |
| graduate | graduate |
| what-didnt-work | what-didnt-work |
| clear | clear |
Key constraint: Always present results in readable tables/sections, not raw JSON. When showing stats, suggest next actions (search, graduate).
Show learning system health summary.
Step 1: Get stats.
python3 ~/.claude/scripts/learning-db.py stats
Step 2: Present status report. Present high-confidence counts with the category breakdown; error spam inflates per-row confidence (pruning 5119 noise rows dropped high-conf 4201→564, 2026-06-12).
LEARNING SYSTEM STATUS
======================
Entries: [total] ([high-conf] high confidence)
Categories: [breakdown by category]
Graduated: [N] entries embedded in agents/skills
Injection:
Hook: session-context.py (SessionStart, ADR-147 dream system)
Method: pre-built payload from nightly auto-dream cycle + learning.db high-confidence patterns
Next actions:
/retro list — see all entries
/retro search TERM — find specific knowledge
/retro graduate — embed mature entries into agents
Display all accumulated knowledge.
Key constraint: Output must use the Python CLI as the single source of truth. Do not maintain parallel markdown files. Present results in readable grouped format, not raw JSON.
Step 1: Query all entries.
python3 ~/.claude/scripts/learning-db.py query
Step 2: Present grouped by category:
LEARNING DATABASE
=================
## [Category] ([N] entries)
- [topic/key] (conf: [N], [Nx] observations): [first line of value]
...
Optional flags:
--category design — filter to one category--min-confidence 0.7 — only high-confidence entriesFull-text search across all learnings.
Step 1: Run FTS5 search.
python3 ~/.claude/scripts/learning-db.py search "TERM"
Step 2: Present results ranked by relevance:
SEARCH: "TERM"
==============
[N] results:
1. [topic/key] (conf: [N], category: [cat])
[value excerpt]
2. ...
Evaluate learning.db entries and embed mature ones into agents/skills.
Key constraints:
--auto flag, confirm intent).error and effectiveness—those are injection-only (useful in context but not suitable as permanent agent instructions).Step 1: Get graduation candidates from the DB.
python3 ~/.claude/scripts/learning-db.py query --category design --category gotcha
Step 2: For each entry, evaluate graduation readiness.
For each candidate, the LLM:
| Question | Pass | Fail |
|----------|------|------|
| Is this specific and actionable? | "sync.Mutex for multi-field state machines" | "Use proper concurrency" |
| Is this universally applicable? | Applies across the domain | Only applied in one feature |
| Would it be wrong as a prescriptive rule? | Safe as default | Has important exceptions |
| Does the target already contain this? | Not present | Already equivalent |
Step 3: Present graduation plan to user.
GRADUATION CANDIDATES (N of M entries)
1. [topic/key] → [target file] (add anti-pattern)
Proposed: "### AP-N: [title]\n[description]"
ALREADY APPLIED (N entries — mark graduated only)
- [topic/key] — already in [file]
NOT READY (N entries — keep injecting)
- [topic/key] — [reason]
Approve? (y/n/pick numbers)
Step 4: On user approval, apply changes.
Use the Edit tool to insert graduated content into target agent/skill files.
After embedding, mark the entry as graduated:
python3 ~/.claude/scripts/learning-db.py graduate TOPIC KEY "target:file/path"
Graduated entries stop being injected (the injector filters graduated_to IS NULL).
Step 5: Report.
GRADUATED:
[key] → [target file] (section: [section])
Entries marked. They will no longer be injected via the hook
since they are now part of the agent's permanent knowledge.
Remove noise from learning.db: cross-domain rows (via filtered prune) or
old low-confidence rows (via stale-prune). Wraps the existing
learning-db.py prune / stale-prune CLI — no new deletion code path.
Key constraints:
--apply/--confirm on the first invocation of a session, regardless of how the user phrased the request ("clear the voice noise", "prune this", "clean up learnings").--apply or --confirm.learning.db. Do not use it to satisfy a code-level bug fix task that explicitly excludes data mutation — check the task's constraints before running --apply/--confirm.Step 1: Determine the clear mode from the user's argument.
| User intent | Mode | Underlying command |
|---|---|---|
| "clear category X" / "clear topic X" / has --category, --topic, --max-confidence, or --older-than | filtered | learning-db.py prune |
| "clear stale" / "clear old" / no filter given | stale | learning-db.py stale-prune |
Step 2: Run the dry-run (always, unconditionally, first).
# Filtered mode
python3 ~/.claude/scripts/learning-db.py prune --category CATEGORY [--topic TOPIC] [--max-confidence N] [--older-than DAYS] --dry-run
# Stale mode
python3 ~/.claude/scripts/learning-db.py stale-prune --dry-run [--min-age-days DAYS]
Step 3: Present the dry-run result and stop.
RETRO CLEAR — DRY RUN
======================
Mode: [filtered | stale]
Filter: [category=X, topic=Y, ...] or [min-age-days=N]
Matched: [N] entries
- [topic/key] (conf: [N], age: [N]d)
...
This is a preview — nothing was deleted. Reply "apply" (or "confirm") to
actually remove these entries, or refine the filter and re-run.
Step 4: Only after the user explicitly confirms in this turn, re-run with --apply (filtered) or --confirm (stale):
python3 ~/.claude/scripts/learning-db.py prune --category CATEGORY ... --apply
# or
python3 ~/.claude/scripts/learning-db.py stale-prune --confirm [--min-age-days DAYS]
Step 5: Report the outcome.
CLEARED: [N] entries removed ([mode] mode, filter: [...])
Total learnings: [before] -> [after]
Graduated entries and routing/effectiveness rows are always protected from prune (see scripts/tests/test_learning_db_prune.py). stale-prune archives to learning_archive rather than hard-deleting, and likewise skips graduated rows.
Print the negative-results registry, the list of experiments that lost. Read it before re-running an experiment so a known-dead path is not retried.
The registry is a doc, not a DB table: docs/what-didnt-work.md is capture, store, and query target. This subcommand reads and prints it, then offers an optional one-line mirror into learning.db for FTS search.
Step 1: Read and print the registry.
Use the Read tool on docs/what-didnt-work.md and present it. Group by the dated ## YYYY-MM-DD headings; show each entry's Decision verdict (rejected / deferred / revisit-if) up front so a scan answers "did we already reject this?".
NEGATIVE RESULTS (docs/what-didnt-work.md)
==========================================
## [date] [experiment]
Decision: [rejected | deferred | revisit-if <condition>]
What happened: [one line]
...
If the file is missing, report that no negative results are recorded yet and point the user at the format in CONTRIBUTING.md.
Step 2 (optional): Mirror one line into learning.db for full-text search.
The doc stays canonical. The mirror is one pointer row, not a parallel store. Run only when the user wants the entry FTS-searchable via /retro search:
python3 ~/.claude/scripts/learning-db.py learn --topic negative-results \
"YYYY-MM-DD <experiment>: <decision> - see docs/what-didnt-work.md"
Batching learn calls: run learning-db.py learn calls individually or chained with &&, then confirm via learning-db.py search. A single failing command in a plain multi-line Bash batch silently drops the rest (observed 2026-06-12).
This reuses the existing learn command (no new code). Confirm with either:
# Topic listing (exact, includes the hyphen):
python3 ~/.claude/scripts/learning-db.py query --topic negative-results
# Or FTS (use a space, not the hyphen; the tokenizer splits hyphens):
python3 ~/.claude/scripts/learning-db.py search "negative results"
User says: "/retro"
Actions: Run learning-db.py stats, show entry counts, injection health.
User says: "/retro list"
Actions: Run learning-db.py query, display grouped by category.
User says: "/retro search routing"
Actions: Run learning-db.py search "routing", display ranked results.
User says: "/retro graduate"
Actions: Query design/gotcha entries, evaluate each against graduation criteria, propose edits to target agents/skills, apply approved changes, mark graduated.
User says: "/retro clear category voice"
Actions: Run learning-db.py prune --category voice --dry-run, present the matched count and sample rows, stop and wait for explicit confirmation. Only on "apply"/"confirm" from the user, re-run with --apply and report before/after totals.
Cause: Database not initialized yet
Solution: Report that no learnings exist yet. Hooks auto-populate during normal work.
Cause: No design/gotcha entries, or all already graduated
Solution: Report the stats and suggest recording more learnings via normal work.
~/.claude/scripts/learning-db.py — Python CLI for all database operations, including prune and stale-prune (wrapped by the clear subcommand)hooks/session-context.py — Hook that injects the pre-built dream payload and high-confidence patterns at session start (ADR-147, supersedes retro-knowledge-injector.py)hooks/pretool-learning-injector.py — PreToolUse hook that queries learning.db for tool-error hints; scoped to error/gotcha/debug categories (ADR: pretool-injector-scoping)scripts/learning.db — SQLite database with FTS5 search indexdocs/what-didnt-work.md: Negative-results registry. Printed by the what-didnt-work subcommand; the doc is the canonical store.Efficient database search tool for bioRxiv preprint server. Use this skill when searching for life sciences preprints by keywords, authors, date ranges, or categories, retrieving paper metadata, downloading PDFs, or conducting literature reviews.
Access BRENDA enzyme database via SOAP API. Retrieve kinetic parameters (Km, kcat), reaction equations, organism data, and substrate-specific enzyme information for biochemical research and metabolic pathway analysis.
Access ClinPGx pharmacogenomics data (successor to PharmGKB). Query gene-drug interactions, CPIC guidelines, allele functions, for precision medicine and genotype-guided dosing decisions.
Query NCBI ClinVar for variant clinical significance. Search by gene/position, interpret pathogenicity classifications, access via E-utilities API or FTP, annotate VCFs, for genomic medicine.
Access COSMIC cancer mutation database. Query somatic mutations, Cancer Gene Census, mutational signatures, gene fusions, for cancer research and precision oncology. Requires authentication.
Query Ensembl genome database REST API for 250+ species. Gene lookups, sequence retrieval, variant analysis, comparative genomics, orthologs, VEP predictions, for genomic research.
Query openFDA API for drugs, devices, adverse events, recalls, regulatory submissions (510k, PMA), substance identification (UNII), for FDA regulatory data analysis and safety research.
Query NCBI Gene via E-utilities/Datasets API. Search by symbol/ID, retrieve gene info (RefSeqs, GO, locations, phenotypes), batch lookups, for gene annotation and functional analysis.
Take notque/retro from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.