A personal tutor for Claude Code. It mines your own session history, finds one concept you leaned on but probably don't fully understand, and teaches it back to you — as a self-contained, interactive HTML lesson you open in your browser.
Every run picks a fresh concept (it keeps a ledger so it never repeats itself), grounds the lesson in what you actually did, and builds a small library of black-and-white, beautifully typeset lessons over time.
Lesson generation runs entirely on your machine — it reads your transcripts under ~/.claude/, writes HTML to ~/.claude/daily-lessons/, and uploads nothing. The optional per-lesson chat answers through your local claude CLI, so it makes the same network calls any Claude Code session does — under your own account, no API key, and nothing more.
Inside Claude Code:
/plugin marketplace add Khrafts/daily-lessons
/plugin install daily-lesson@daily-lessons
That's it. The /daily-lesson command is now available.
Prefer the menu? Run
/plugin, pick Browse marketplaces → daily-lessons → daily-lesson → Install.
/daily-lesson # teach me something from my most recent day of work
/daily-lesson 2026-06-03 # target a specific day (YYYY-MM-DD)
/daily-lesson back # skip the most recent day, start one day earlier
/daily-lesson deep # one-off: write just this lesson in a chosen mode
/lesson-mode # show the current lecture mode and the menu
/lesson-mode tutorial # set the default mode for future lessons
When it finishes it prints the lesson title, a teaser, and the path to the HTML file — then offers to open it in your browser.
- One concept per run, chosen from things you used but treated as a black box — a copied command, a config you didn't question, a spot where you trial-and-errored.
- Pitched at your stack. It infers your languages, frameworks, and domain from the sessions themselves, so the worked example is in your world (Solidity, Rust, TypeScript, Go, Python — whatever you actually work in).
- An interactive HTML lesson — copy-able code blocks, collapsible pitfalls, reveal-on-click self-check questions, Fraunces + JetBrains Mono typography. Rendered from a frozen canonical template, so the design is identical on every install.
- A growing library at
~/.claude/daily-lessons/index.html, newest first. - A chat on every lesson. An Ask about this lesson button on each page —
ask follow-ups and get answers grounded in that lesson, powered by your own
claudeCLI.
Each lesson covers: what it is → why it mattered in your session → the mental model → a worked example → common pitfalls → go-deeper pointers + a self-check.
The same lesson can be written in different modes. They share the six sections, the frozen HTML, and the one-concept-from-your-real-session soul — only the tone and the depth of exposure change, so you read in the register you actually want.
| Mode | What it reads like | Depth |
|---|---|---|
| Grounded ⭐ | A senior colleague at a whiteboard — teaches the concept and cites your real session as evidence, honestly attributed. | standard (~600–900w) |
| Tutorial | A calm, blog-style explainer; your session is the silent reason the topic was picked, not a story you star in. | standard (~650–950w) |
| Deep Dive | A reference chapter — full derivation, edge cases, two worked examples; for when you want to truly master it. | long (~1000–1500w) |
| Briefing | A terse staff-engineer memo — maximum signal per word, the concept and the episode as facts, zero ornament. | compact (~350–600w) |
/lesson-mode # show your current mode and the menu
/lesson-mode deep # set the default for future lessons
/daily-lesson briefing # …or use a mode just once, without changing the default
Grounded is the default — it's the safest voice for a daily habit: it keeps the lesson tied to your day without dramatising it. Tutorial drops the session framing entirely if you'd rather read a clean concept explainer; Deep Dive and Briefing flex the depth.
Two guarantees bind every mode, the default included:
- Never obscure — whatever the tone, the concept is defined plainly and leads every section; voice is seasoning on a clear explanation, never a substitute.
- Honest attribution — a lesson says "you" only for what you genuinely did or decided. Work the agent or tooling did is named in the third person, so a lesson never credits you with a command the agent ran.
Your choice is saved in ~/.claude/daily-lessons/config.json; mode definitions
are canon in references/lesson-modes.md (edit there to retune a mode).
Already have a lesson and want it in a different voice? Recast it — the same concept, re-written in another mode, persisted as a sibling you open just like the original:
/lesson-recast tutorial # recast your most recent lesson into Tutorial
/lesson-recast deep erc7201 # recast a specific lesson (by slug/title words) into Deep Dive
Recasting reads the existing lesson — it does not re-scan your sessions — re-voices it in the new mode, and saves it next to the original. The library then groups both under one concept with a tone switcher, so "ERC-7201 → Grounded · Tutorial" are one click apart. The original is never overwritten, and since the attribution rule still applies, recasting a pre-modes lesson is also a clean way to fix one that mis-credited you with the agent's work.
Or do it right from the lesson page. When a lesson is open through the local
server, a Tone bar sits under the title: the tones you already have are
chips you click to switch between them, and the tones you don't yet have are
+ buttons that generate that version on the spot (via your local claude)
and open it when it's ready. Each tone is its own page, so each keeps its own
chat history and all the usual lesson features — switching tones never loses a
conversation. (The bar only appears when the page is served by the local
server; over file:// there's nothing to generate against.) Generating a tone
asks for a quick confirmation first (with a "don't ask again" you can re-enable
from the bar), since it runs your local claude and counts against your usage.
Like the chat button, the Tone bar is injected at serve time, so lessons created
before lecture modes gain it automatically when viewed through the server.
Every lesson page has an Ask about this lesson button, and it works with
zero setup: /daily-lesson opens each new lesson through a tiny local
server, so the chat is live the moment the page loads — no extra command to run.
Start a conversation about a lesson, close the tab, come back days later and
continue it where you left off. Continuity is real: each chat resumes the
same claude session (--resume), and the transcript is saved to chats.json
next to the lessons.
Each lesson can hold more than one conversation. Start a new chat without losing the old ones — the drawer's history lets you browse a lesson's past chats and switch between them, each with its own thread and session. Want more room to read? Expand widens the drawer into a centered reading column, and it remembers the choice.
Answers come from the local claude CLI — your existing login and
subscription, no API key. Still local-first: the only network calls are the
ones claude itself makes, exactly like any other session.
Want the whole library in one place, or need to bring the server back after a reboot? Run:
/lesson-chat # ensure the server is up, open the library
/lesson-chat 9000 # same, on a different port
It serves your library at http://127.0.0.1:8787 (loopback only — nothing is
exposed to the network). The launcher is idempotent and version-aware: it reuses
a running server when it matches the installed plugin version, and after a plugin
update the next lesson you open automatically replaces any still-running older
server — no manual restart needed. Lessons opened directly via file:// show the
button too — if the server is running, the button deep-links into the served
page; if not, it tells you how to start it. Lessons rendered before this feature
gain the chat button automatically when viewed through the server.
~/.claude/projects/ # your session transcripts (read-only input)
~/.claude/daily-lessons/
├── index.json # the ledger (dedup source of truth)
├── index.html # the library landing page
├── config.json # preferences (e.g. your lecture mode)
├── chats.json # per-lesson chat transcripts + session ids
└── lessons/
└── YYYY-MM-DD-<slug>.html # one self-contained lesson per run
The ledger's concept_key is the dedup key, so repeated runs always teach
something new and the same-day re-run lands on a different concept.
Every lesson is rendered from frozen templates bundled in the plugin, so the typography, layout, and interactions are identical on every install — the design is canon, not re-improvised each run:
assets/lesson-shell.html # lesson page: <head>, CSS, JS, metadata bar, footer
assets/library-shell.html # the library landing page
assets/library-row.html # one library row
scripts/render_lesson.py # slots your content into the shells (token replacement)
references/lesson-format.md # the body component contract the command follows
The command authors only the content (a metadata blob + the article body) and
hands it to render_lesson.py, which assembles the page. Want a different look?
Edit the assets/ shells — that's the whole point of the split. After editing,
re-skin the existing library with:
python3 scripts/render_lesson.py --rebuild-library
(Existing lesson pages are written once at creation; re-render them to re-skin those too.)
- Claude Code with plugin support.
python3(3.8+) — runs the renderer. Pre-installed on macOS and most Linux distros.- A shell with
jqavailable (used to parse the.jsonltranscripts). Pre-installed on most setups; on macOS,brew install jq. - The
claudeCLI on your PATH — chat only. Already true if you're running this as a plugin. - Some actual Claude Code history to learn from. Fresh installs with no sessions yet will be told there's nothing to teach.
Everything happens on your machine. The command reads your local transcripts and
writes local HTML; nothing is uploaded. Chat answers are generated by your local
claude CLI under your own account, and transcripts stay in chats.json on
disk. The lesson author is instructed to teach
the general concept and never echo secrets, keys, tokens, addresses, or
proprietary code from your sessions. (The generated HTML does pull Google Fonts
and highlight.js from CDNs for styling, and degrades gracefully if you're
offline.)
/plugin uninstall daily-lesson@daily-lessons
Your existing lessons under ~/.claude/daily-lessons/ are left untouched —
delete that folder by hand if you want them gone.
MIT — see LICENSE.