lessons-learned intercepts every tool call during a Claude Code session. Before Claude runs a command or edits a file, matching lessons inject as context warnings — right when they're needed. Each corrected mistake gets stored and prevents the next occurrence.
Claude Code sessions are stateless. Every mistake corrected in one session is forgotten by the next. Over long agentic work, the same classes of errors recur — wasting tokens, time, and trust. There's no mechanism to carry hard-won corrections forward.
lessons-learned intercepts every tool call via Claude Code hooks. Before Claude runs a command or edits a file, matching lessons inject as context warnings. Guards can block dangerous commands outright. Directives re-inject at 30/52/70% context usage to fight context rot.
Each corrected mistake prevents future repetitions. The lesson store compounds over time, shaped by your actual workflow. Lessons persist across sessions, projects, and agents. Context rot reversal — knowledge that outlasts any single conversation.
The complete data model — how session JSONL files become candidates, lessons, and runtime injections. Click any node to inspect its properties. Edges show data flow and relationships.
Data flow summary:
Session JSONL files (written by Claude Code) are scanned at each session start by
session-start-scan.mjs. The four scanning tiers (structured → heuristic → structural → LLM)
extract candidates and write them to data/lessons.db (SQLite).
The lessons promote CLI command moves candidates to active status.
lessons build compiles active lessons into data/lesson-manifest.json
— the runtime-only file loaded by every PreToolUse hook call.
data/config.json embeds its settings into the manifest at build time.
data/scan-state.json tracks byte offsets so each scan is incremental.
Swimlane showing the full event sequence across four actors. Claude Code fires hooks automatically — no manual invocation needed. Hover nodes for details.
Hook wiring: All hooks are declared in hooks/hooks.json and
registered with Claude Code automatically on plugin install. The matcher field
is a regex tested against the session event type (e.g., startup|resume|clear|compact)
or tool name (e.g., Read|Edit|Write|Bash|Glob). Multiple hooks can match the
same event — they run sequentially.
Every lesson begins as a candidate extracted by the scanner and follows a
review-promote workflow before injection. Click any state to inspect it.
Raw candidate extracted by scanner. Not yet validated or reviewed. Stored in lessons.db with status='candidate'.
Status meanings:
candidate — extracted, not validated.
reviewed — passed lessons review validation gates.
active — compiled into manifest and injected at PreToolUse.
disabled — soft-disabled; still in DB but excluded from manifest.
archived — permanently removed; retained for history only.
Use lessons promote --ids to advance status; lessons edit --patch '{"disabled":true}' to soft-disable.
Every tool call (Read, Edit, Write, Bash, Glob) passes through this 6-stage pipeline in under 10ms. Stages run sequentially from hook entry to inject-or-block. Click any node to see what it does and what it reads/writes.
Press Play to walk through the injection pipeline step by step. Click any node for full properties.
matchLessons()
in core/match.mjs
evaluates each lesson in the manifest against the current tool call in this order:
Before injection, lessons are filtered through three dedup layers to prevent the same lesson from firing repeatedly in a session, even across parallel subagents.
LESSONS_SEEN — a comma-separated list of seen slugs passed between hook
invocations as an environment variable. Fast within a single agent chain.
$TMPDIR/lessons-{hash}-seen.txt — persists the seen set across subagents
and multiple hook invocations in the same session.
$TMPDIR/lessons-{hash}-seen.d/{slug} — atomic O_EXCL file creation.
Prevents duplicate injection when two agents race to inject the same lesson concurrently.
At every session start, a background process scans prior JSONL logs through four tiers of
increasing depth. Each tier writes candidates to lessons.db. Click stages to animate.
Complete reference for every hook wired in
hooks/hooks.json.
Timeouts, matchers, and exact behavior for each hook file.
Zero config required. The plugin wires itself into Claude Code via hooks.json automatically. All scanning is incremental; lesson injection adds under 10ms per tool call.