Lessons
AI tools, hooks, skills, and prompts I actually use day to day — each with a what/why/how write-up
npx -y skills add kev-hu/ai-toolkit --skill lessonsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Review the current session and propose updates to LESSONS.md
SKILL.md
9.8 KB, as published. Nobody here has run it
Update LESSONS.md
Review the conversation for hard-earned lessons and update LESSONS.md directly.
Philosophy
How lessons are placed and loaded — the reasoning the steps below apply:
- Keep the root file cross-cutting. The root LESSONS.md loads every session, everywhere, so it should hold only what applies everywhere. Push area-specific lessons down into the subtree they govern.
- Nest for progressive disclosure, only when it earns its keep. A co-located LESSONS.md in a subdirectory loads on-demand — just when you're working there. Split one out only when its lessons are substantial and usually out-of-scope (rule of thumb: ~3+ entries you'd rarely load elsewhere). A lone area-specific lesson stays a scoped entry, not a new file.
- Nearest wins. When a nested file and the root would conflict, the more-specific file takes precedence in its subtree — but keep root cross-cutting so this rarely arises.
Steps
- Read context files — read LESSONS.md (if it exists), and also CLAUDE.md/AGENTS.md if they exist. These are your redundancy references. If LESSONS.md doesn't exist, bootstrap it:
- Placement (see Philosophy) — default to the repo/vault root. Only co-locate in a subdirectory (e.g.
tools/zep/) when that area's lessons are substantial and usually out-of-scope elsewhere, and the repo already uses co-located lessons; a single area-specific lesson belongs in the root file, not its own nested file. Create it from the bundled template atassets/lessons-template.md(relative to this skill), replacing{Context}with the repo/vault (or subdirectory) name. - Wire discovery — a new LESSONS.md is invisible until a CLAUDE.md loads it. How to place the pointer depends on load mechanics: CLAUDE.md files at or above cwd load in full at launch (imports expand with them); CLAUDE.md files in subdirectories load on-demand, only when Claude reads a file in that subtree. So:
- Repo-root LESSONS.md → add
@LESSONS.mdon its own line in the root CLAUDE.md (under a "Memory" or context section). Loads every session. - Nested/co-located LESSONS.md → choose the load behavior deliberately:
- Scope-gated (default for area-specific lessons) — add
@LESSONS.mdto a co-locatedsubdir/CLAUDE.mdbeside it. Loads only when working in that subtree, so unrelated sessions don't pay the context cost. Correct when the lesson only matters once you're already editing that area. - Always-on — add
@subdir/LESSONS.md(relative path pointing down) to the root CLAUDE.md. Loads every session regardless. Use when the lesson must be present before deciding whether/how to touch that subdir — scope-gating would load it too late.
- Scope-gated (default for area-specific lessons) — add
- AGENTS.md (only if no CLAUDE.md governs that scope) →
@importis unsupported, so add a prose line instead:Read \LESSONS.md` before working in this area.`
- Repo-root LESSONS.md → add
- Also add the nested file to the root LESSONS.md's index if one exists.
- Placement (see Philosophy) — default to the repo/vault root. Only co-locate in a subdirectory (e.g.
- Review the conversation for insights worth capturing — focus on bugs hit, errors debugged, non-obvious behavior discovered, and persistent model behaviors that cost the user correction time.
- Filter each candidate through the intake gate (see below). Most sessions produce 0-2 entries. That's fine.
- Check section density before appending — if a section already has 5+ entries, the new one should be sharper than the weakest existing entry, or it shouldn't go in.
- Scan for counter increments — dispatch a subagent to review existing LESSONS.md entries against the conversation. The subagent returns a list of entries whose counters should increment (because they prevented a mistake or were actively useful this session). Do NOT decrement counters.
- Apply and commit each op atomically — one op = one commit, applied sequentially: make the edit (new entry, counter bump, in-place edit, or removal), commit it per the Commit protocol below, then move to the next op. Before committing the final op, also update the 'Last updated' date and increment the session number at the bottom so they ride in the last commit. The user reviews via
git log -p— each op is independently revertable.
Commit protocol — the context ledger
Every op is its own scoped commit, and the subject line is a ledger row. Grammar:
context(lessons): add <bold tag> — <condensed insight>
context(lessons): bump <bold tag> N→M
context(lessons): edit <bold tag> — <what changed>
context(lessons): cut <bold tag> — <why>
context(lessons): bootstrap <path>
-
Key = the entry's bold tag, verbatim. Truncate a long tag but keep its greppable head — the tag is how a future
git log --grepfinds the entry's trajectory. -
Stage only the file the op touched (
git add LESSONS.md, or the real nested path liketools/zep/LESSONS.md) — nevergit add -A; other dirty files belong to other uncommitted work. On bootstrap, also stage the CLAUDE.md/AGENTS.md you added the discovery pointer to. -
Skip entirely on a no-op — no edits, no commits, no registry write.
-
After the last commit, register the repo in the machine-wide ledger index, so cross-repo queries can find every repo that has ever committed context:
mkdir -p ~/.claude/context-ledger r=$(git rev-parse --show-toplevel) grep -qxF "$r" ~/.claude/context-ledger/repos 2>/dev/null || echo "$r" >> ~/.claude/context-ledger/repos
Reading the ledger
The grammar makes git log the query surface for context evolution:
-
This repo's full context history:
git log --oneline --grep '^context(' -
One entry's life story (born → bumped → edited → cut):
git log --oneline --grep '<bold tag substring>' -
Which lessons are earning their keep:
git log --oneline --grep '): bump' -
Machine-wide, across every registered repo:
while read -r r; do echo "== $r"; git -C "$r" log --oneline --grep '^context('; done < ~/.claude/context-ledger/repos -
Pre-grammar history (older freeform
lessons:/taste:subjects) needs the compat pattern:git log --oneline -E --grep '^(context\(|lessons|taste)'
Entry format
Every entry follows this format:
- (0) **tool/context** — Natural language insight. What to do.
- Counter
(N)— starts at0. Incremented when the entry actively helps during a session. Higher counts = proven value. Never decremented — if an entry is wrong, edit or remove it. - Bold tool/context — the tool, API, or context this applies to. Scannable and greppable.
- Insight + action — what goes wrong or what to do, expressed naturally.
Intake gate
Before adding any entry, run through these filters in order. Short-circuit as soon as one matches:
-
Already captured? Is this in CLAUDE.md or elsewhere in LESSONS.md? → skip
-
Self-descriptive error? Would the error message itself tell you what's wrong? → skip
-
Easily found? Can you find the answer in <1 min of searching? (Lower this bar for niche/new tools with poor documentation.) → skip
-
Real cost? Did this actually cost time? This includes:
- Silent failures, misleading errors, wrong-path-first situations
- Persistent model behaviors the user has to repeatedly correct
- Conventions where the obvious approach consistently leads astray
"Huh, that's interesting" moments don't pass. Repeated "no, do it this way" corrections do.
Where does this belong?
Not every insight belongs in LESSONS.md. Before adding, check:
| If the insight is about... | It belongs in... |
|---|---|
| A specific gotcha, failure mode, or behavioral correction | LESSONS.md — this is what it's for |
| Repo architecture, structure, or commands | CLAUDE.md — describes what the repo is |
| General advice any model already knows | Nowhere — skip it |
If you notice an existing LESSONS.md entry that's really a CLAUDE.md entry (architecture, commands), you can move it as part of your update.
What makes a good entry
A good entry identifies:
- A specific tool, API, or context (not "be careful with Docker")
- A specific problem — a failure mode, a persistent wrong behavior, or a convention that prevents drift (not "it can break")
- A specific action — a fix, workaround, or "always do X instead of Y" (not "check the docs")
Examples
Good entries:
(0) **apify CLI** — apify actors call silently drops unquoted JSON input args. Always wrap in single quotes.(0) **jq vs python3** — Use jq for JSON computation in skills, not python3. No interpreter startup, no imports, handles counts/medians/ratios/grouping natively.(0) **sys.path** — Python scripts using from scripts.module import fail when run directly. Add sys.path.insert(0, str(Path(__file__).parent.parent)) at top.
Bad entries (would not pass intake gate):
"Be careful with API rate limits"— too vague, no specific tool or fix."Always test before deploying"— generic advice any model knows."Docker containers need port mapping"— self-descriptive, easily Googled.
Rules
- If nothing from the session passes the intake gate, say so — don't force entries just because the skill was invoked.
- Quality over quantity — one sharp entry beats three vague ones.
- When updating an existing entry, just edit it in place. Don't keep the old version as a
(was: ...)comment —git logserves that purpose. - You can consolidate or remove existing entries if they're outdated, redundant, or no longer true.
Optional: mirroring to a cross-session ledger
If you also keep a separate cross-session learnings store (outside this repo), mirror newly-added entries there too — it's a useful second surface for "have I seen this before" queries across projects. Not required for this skill to work.