CLI Reference
All management goes through a single entry point:
node scripts/lessons.mjs <subcommand> [options]
Or via npm scripts:
npm run lessons -- <subcommand> [options]
add
Add a new lesson to the store.
node scripts/lessons.mjs add [options]
Options
| Option | Description |
|---|---|
| (none) | Reads a JSON lesson object from stdin |
--interactive / -i | Interactive mode — prompts for all fields |
--json '<json>' | Inline JSON string |
--file <path> | Read lesson from a JSON file |
Interactive mode
Prompts for: summary, problem, solution, type, tool(s), trigger, tags, priority, confidence.
node scripts/lessons.mjs add --interactive
Stdin mode
With no flags, add reads a JSON lesson object from stdin:
echo '{"summary": "...", "problem": "...", "solution": "..."}' | node scripts/lessons.mjs add
JSON mode
node scripts/lessons.mjs add --json '{
"summary": "git stash drops untracked files silently",
"problem": "git stash only stashes tracked modified files — untracked files are silently left behind",
"solution": "Use git stash -u (--include-untracked) to include untracked files",
"trigger": "git stash",
"tags": ["tool:git", "severity:data-loss"],
"priority": 9
}'
From file
node scripts/lessons.mjs add --file lesson.json
Validation
All modes enforce:
summary,problem,solutioneach ≥ 20 characters- No unfilled template placeholders
summarymust not end with...- Trigger must not be a prose gerund
- Jaccard similarity vs existing lessons < 0.5
Validation failures exit non-zero with a descriptive message.
After add
The manifest is rebuilt automatically after a successful add.
build
Rebuild lesson-manifest.json from the database.
node scripts/lessons.mjs build
Required after:
- Direct edits to
data/lessons.db(viaeditsubcommand) - Changing
minConfidenceorminPriorityindata/config.json
Not required after config-only changes to injection budget or scan settings.
list
List all lessons with metadata.
node scripts/lessons.mjs list [options]
Options
| Option | Description |
|---|---|
| (none) | Formatted table |
--json | JSON array |
--status <status> | Filter by status: active, candidate, archived, needs-review |
--tag <tag> | Filter by tag (e.g. tool:git) |
Examples
node scripts/lessons.mjs list
node scripts/lessons.mjs list --json
node scripts/lessons.mjs list --status active
node scripts/lessons.mjs list --tag severity:data-loss
edit
Edit a lesson field by ID.
node scripts/lessons.mjs edit --id <id> --patch '<json>'
Options
| Option | Description |
|---|---|
--id <id> | Lesson ID (ULID) or slug |
--patch '<json>' | JSON object of fields to update |
Example
node scripts/lessons.mjs edit --id pytest-tty-hanging-k9m2 --patch '{"priority": 9}'
The manifest is rebuilt automatically after a successful edit.
review
Interactive review of Tier 2 heuristic candidates.
node scripts/lessons.mjs review [options]
Options
| Option | Description |
|---|---|
| (none) | Review all pending candidates |
--limit <n> | Review at most N candidates |
For each Tier 2 candidate, the CLI shows the raw error context and prompts for:
- Summary
- Whether the mistake is real and reusable
- Trigger pattern
- Priority and tags
Accepted candidates are promoted to the lesson store and the manifest is rebuilt.
scan
Incrementally scan session logs for lesson candidates.
node scripts/lessons.mjs scan [subcommand] [options]
Options (base)
| Option | Description |
|---|---|
--auto | Non-interactive mode (used by background hook) |
--full | Reset byte offsets; re-scan all files from the start |
--dry-run | Show what would be found; don't write candidates |
--tier1-only | Only scan for structured #lesson tags (Tier 1) |
--tier2-only | Only run heuristic detection (Tier 2) |
--structural | Also run Tier 3 structural/insight detection |
--structural-full | Tier 3 full re-scan (ignore saved offsets) |
--deep | Also run Tier 4 LLM deep scan (requires API key) |
--deep-full | Tier 4 full re-scan (ignore saved offsets) |
--max-sessions <n> | Limit Tier 4 deep scan to the N most recent sessions |
--path <dir> | Scan a specific directory instead of the default (~/.claude/projects/) |
--verbose | Print per-file progress and candidate details |
--path (or the LESSONS_SCAN_PATH env var, checked when --path isn't given) is
currently the only way to change where scan looks — config.json's scanPaths field
is not read by this subcommand.
Subcommands
scan aggregate
Show ranked candidates from the DB as JSON (formerly scan candidates, which is now a deprecated alias that prints a rename notice and calls this):
node scripts/lessons.mjs scan aggregate
To promote a candidate found this way, use promote --ids <id> (see below) — scan promote <index> has been removed.
promote
Promote candidates to active and/or archive lessons. Requires --ids, --archive, or both.
node scripts/lessons.mjs promote [options]
Options
| Option | Description |
|---|---|
--ids <id,...> | Comma-separated candidate IDs to promote to active |
--archive "<id>:reason" | Archive a lesson with a reason (repeatable) |
--patch '<json>' | JSON object of fields to apply to promoted lessons |
Examples
# Promote a candidate to active
node scripts/lessons.mjs promote --ids 01JQSEED00000000000000001
# Archive a lesson
node scripts/lessons.mjs promote --archive "01JQSEED00000000000000001:resolved in npm 10"
# Both in one call
node scripts/lessons.mjs promote --ids id1,id2 --archive "id3:duplicate"
There is no --restore flag on promote — use restore to bring an archived lesson back.
restore
Restore archived lessons back to active.
node scripts/lessons.mjs restore --ids <id,...>
onboard
Interactive onboarding flow for new installations.
node scripts/lessons.mjs onboard
Walks through verifying the installation, reviewing the seed lesson store, and configuring scan paths.
doctor
Check the health of the installation: manifest freshness, config validity, hook wiring.
node scripts/lessons.mjs doctor
Exits non-zero with a diagnostic message if any check fails.
preflight
Run a quick sanity check before a session (manifest exists, no schema errors, hook files present).
node scripts/lessons.mjs preflight
purge
Archive all candidates below a confidence threshold.
node scripts/lessons.mjs purge --below-conf <threshold>
Options
| Option | Description |
|---|---|
--below-conf <n> | Required. Archive candidates with confidence < n (0–1) |
--dry-run | Show what would be archived without writing |
Example
node scripts/lessons.mjs purge --below-conf 0.6
windows
List or archive pending Tier 3 structural/semantic windows (from lexical pattern detection),
stored in the pending_semantic_windows table.
node scripts/lessons.mjs windows [options]
Options
| Option | Description |
|---|---|
| (none) | List all pending windows |
--type <lesson|insight> | Filter the listing by window type |
--show <id> | Print the full text of one pending window |
--archive <id,...> | Mark one or more windows as processed |
--archive-nearest <id> | Mark all pending windows nearest to a given lesson ID as processed |
Example
node scripts/lessons.mjs windows
node scripts/lessons.mjs windows --show 01JQSEED00000000000000001
node scripts/lessons.mjs windows --archive 01JQSEED00000000000000001
Configuration
There is no config CLI subcommand. Edit data/config.json directly, or use the
conversational /lessons:config slash command, which reads and writes the same file. See
Configuration for the full field reference. Changes to
minConfidence or minPriority require a manifest rebuild (node scripts/lessons.mjs build).
npm scripts
| Script | Equivalent |
|---|---|
npm run lessons | node scripts/lessons.mjs |
npm run build | node scripts/lessons.mjs build |
npm run scan | node scripts/lessons.mjs scan |
npm test | All tests |
npm run test:unit | Unit tests only |
npm run test:integration | Integration tests only |
npm run test:e2e | E2E tests only |
npm run test:coverage | Tests with coverage |
npm run lint | ESLint (report) |
npm run lint:fix | ESLint (auto-fix) |
npm run format | Prettier (write) |
npm run format:check | Prettier (check) |
npm run typecheck | TypeScript check |