new-lesson
Skill1 starsChanged 2 months agoMITView on GitHub
Use when adding one or more lessons (or a whole module/level) to Claude Code Dojo. Scaffolds the MDX with frontmatter-first metadata, auto-assigns the dotted id, registers the module/level in structure.ts, regenerates curriculum.ts, and stubs snippet/prompt keys only where you opt in — then guides filling in content.
2 other projects use a version of this.
Adopted by
Most recently taken up by
- nextflow-io/trainingtheir own version, first seen Oct 8, 2026
- luk-s12/legiontheir own version, first seen Aug 31, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- nextflow-io/training★ 277same name
- luk-s12/legion★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository3 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- new-languageSkill
- refresh-lessonsSkill
The file
We split this skill into the rules it gives an agent
9 rules. About 0 are common, 4 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 12
Frontmatter is the source of truth: Every lesson's metadata (id, order, prerequisites, teaches, volatility, etc.) lives in the MDX …
- Very specific: line 40
Always fetch the relevant official docs first (start from the docs map at https://code.claude.com/docs/en/claude_code_docs_map) so the …
- Very specific: line 56
interactivewas deliberately omitted: when the lesson's chart didn't exist yet (the validator only accepts a registered chart id). - Distinctive: line 69
Every core and resolver lesson in the curriculum carries a Structure line (right after its "Covers" paragraph) stating exactly how the …
- Distinctive: line 152
Read it before writing, not after.
- Very specific: line 206
Verify: npm run check-snippets — this is now the full content check (frontmatter validation + snippet/prompt coverage).
- Distinctive: line 216
When the report comes back, do not apply anything blindly.
- Distinctive: line 221
Keep only the flags that genuinely need a fix.
- Very specific: line 242
Write it to a temp JSON file in the Outline shape (see scripts/authoring/scaffold.ts):
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Add a lesson (or module/level)
The deterministic scaffolding lives in scripts/authoring/ and is run via the CLI.
You supply the judgment (ids are auto-assigned, but titles, prose, frontmatter
metadata, and snippet code are yours); the CLI does the wiring.
Frontmatter is the source of truth. Every lesson's metadata (id, order,
prerequisites, teaches, volatility, etc.) lives in the MDX frontmatter.
src/content/curriculum.ts is generated from it — never hand-edit
curriculum.ts. The CLI runs npm run gen:curriculum for you automatically
after scaffolding; if you ever change frontmatter by hand afterwards, rerun
npm run gen:curriculum yourself.
Part 0 — before writing anything
The curriculum spec (curriculum-design/claude-code-craft-curriculum_v10.md) is
the source of truth for each lesson's metadata: its per-lesson table already
lists the volatility, docsSources, and the lesson's Structure line. Start
from those — don't invent them from scratch.
For each lesson:
docsSources: the official docs URL(s) the content is verified against. Every lesson needs sources — there is no exception forstablelessons. The curriculum already lists sources for each lesson; use those as the starting set, fetch them, and add more as you find them necessary while writing. (The content check enforcesdocsSourceson every lesson exceptcheckpoint/milestonerecap lessons, which teach no feature surface.)volatility: the curriculum already specifies this per lesson; use it as the default. But after fetching the docs, if the real surface is more or less volatile than the curriculum tagged it, override it with the volatility the docs warrant (pass a new--volatility).verifiedAgainstDocsAt: the ISO date (YYYY-MM-DD) you checked those docs. Defaults to today if you omit--verified-at.
Always fetch the relevant official docs first (start from the docs map at
https://code.claude.com/docs/en/claude_code_docs_map) so the content you write
is accurate as of today, not as of training data. If a lesson's content
conflicts with current docs, the docs win.
Authoring a pre-scaffolded stub
A lesson may already exist as a frontmatter-only @@TODO@@ skeleton, scaffolded
in a batch ahead of time (the whole Intermediate level was). Its frontmatter is
provisional — do not trust it as verified. Before writing the body:
docsSourcesURLs were inferred from the curriculum's.mdfilenames (claude-directory.md→/en/claude-directory) and have never been fetched. Fetch each one. A URL that 404s or redirects is wrong: find the real page and fix the frontmatter, since these render as the lesson's "Official docs" footer.interactivewas deliberately omitted when the lesson's chart didn't exist yet (the validator only accepts a registered chart id). Check the curriculum's Interactive row: if it names a chart, author and register it now, then add theinteractiveblock and the<ChartEmbed>.verifiedAgainstDocsAtis the scaffold date, not a verification. Set it to the day you actually check the docs.volatilitycame from the curriculum; re-judge it against the real docs surface, per the rule above.
Rerun npm run gen:curriculum after any frontmatter change.
Follow the lesson's Structure line
Every core and resolver lesson in the curriculum carries a Structure line (right after its "Covers" paragraph) stating exactly how the section menu applies to that lesson. Follow it — it overrides the generic full-menu skeleton the scaffolder writes.
Core lessons name one of four profiles plus lesson-specific deltas:
- Full — the default menu, complete or near-complete (heavyweight feature lessons). Full — compact keeps every section but brief; Full — extended goes beyond the menu where the topic demands it.
- Concept — mental-model lessons: problem, concept, how-it-works, interactive, FAQ, where-next. Do not invent use-case scenarios, when-not-to-use, or pitfalls where they don't naturally arise.
- Brief — deliberately short: problem and concept merged, one compact pass of mechanics, a comparison table or single example, where-next. No walkthrough required.
- Custom — the body follows its own shape (reference catalog, cookbook, pattern blocks, guided tour, symptom→response playbook), as the line describes.
Resolver lessons carry Structure lines too: most use all five resolver sections, but Edge cases may be dropped or folded for two-option comparisons, and resolvers without a dedicated chart replace the decision tree with an inline if/then decision ladder.
overview lessons (the single-lesson orientation module that opens
Intermediate and Advanced, e.g. I0.1, A0.1) do not carry Structure lines.
Their shape is fixed by curriculum §1.8, and the scaffolder writes it: You are
here → The gap → The map (the level's interactive stack chart, the
centerpiece) → How it fits together → Suggested route → What you'll build.
They teach no mechanics and contain no Try It and no pitfalls; every feature
claim stays at one-line-identity depth (the modules own the mechanics). They
still take docsSources (typically features-overview.md) and references.
The scaffolder writes the default skeleton regardless of profile — reshape it to match the Structure line: delete sections the profile drops rather than padding them, and reorder or merge as the line directs. The always-required elements still hold under every profile: answer every "Must answer" question, include when-not-to-use + a cost note for feature lessons, a Try It whenever there is anything hands-on, and "Where next" cross-links plus the "Official docs" footer.
Single lesson
- Decide
levelid,modulecode, lessonslug(kebab-case) andtitle. Propose them if the user hasn't; confirm before writing. The dottedid(e.g.B2.3) is auto-assigned from the module's next freeorder— you never pass it. Scaffold:
npx tsx scripts/authoring/cli.ts lesson \ --level beginner --module B2 --slug review-changes \ --title "Reviewing Changes" --type core--typeis one ofoverview | core | resolver | workflow | checkpoint | milestone— it picks which section skeleton gets written (see below).Optional flags (exactly as the CLI parses them):
--level-title,--module-title,--module-slug— only needed the first time you introduce a new level or module (see "New levels/modules" below).--estimated-minutes <n>--volatility stable|evolving|volatile--verified-at YYYY-MM-DD(defaults to today)--prerequisites B2.2— comma-separated dotted ids that must resolve; rendered as a "Prerequisites" strip at the top of the lesson, so set them intentionally (user-facing navigation, not just validator metadata)--teaches diff-review— comma-separated concept tags--references B2.1— comma-separated dotted ids that must resolve; rendered as the "Where next" footer at the bottom of the lesson--docs-sources <url>— comma-separated; set on every lesson (see Part 0). The content check hard-fails when it's missing on any lesson exceptcheckpoint/milestonerecap lessons.--interactive diagram:spec-id— comma-separatedkind:specpairs; eachspecmust exist in the chart registry (src/content/charts/index.ts). Charts can be linear card-flows or branching flowcharts (flowrows for decision trees/loops) — seesrc/content/charts/README.md; both are authored the same way: define aChartDef, register it inindex.ts+chartIds.ts, and embed with<ChartEmbed id="…" />.--snippets a,b/--prompts c— opt-in only (see below); omit them entirely if the lesson doesn't need language-specific examples
- Fill content:
- Follow the lesson style guide:
docs/lesson-style-guide.md. It is the canonical, up-to-date home for the prose rules and the content mechanics. Read it before writing, not after. The prose rules cover emphasis and significance (zero em-dashes, no self-referential emphasis, no inflated significance, no aphorism formulas, no promotional language), sentence shapes (no flourish clauses, negative parallelisms, staccato runs,-ingpile-ons, copula avoidance, subjectless fragments, false ranges, forced rule of three), word choice (the AI-vocabulary and filler lists, no over-hedging, stable terminology, no rhetorical openers such as "honestly"), structure and framing (no meta-narration or signposting, no fragmented headers, say each point once, no generic closing paragraph, no chatbot artifacts, no diff-anchored framing, never speculate past the docs), and formatting (sparing bold, sentence-case author headings, no prose emoji, straight quotes). The mechanics are fence discipline, no bare dotted ids outside<LessonLink>, and every inline external URL indocsSources. Simulated file and terminal content inside fences is exempt from all of the prose rules; so is frontmatter and the template's canonical##headings. Run the grep commands in the guide before calling a lesson done, and read the prose for the judgment rules; thelesson-stylesubagent checks a lesson against this guide and reports what it flags. - The scaffolder writes the anatomy for the chosen
--typeas headings with@@TODO@@guidance comments describing what belongs in each section (e.g.coregets "The problem" → "The concept" → "How it works" → "Walkthrough" → "Use-case scenarios" → "When to use / when not to use" → "Pitfalls" → "Try It" → "FAQ" → "Where next";resolvergets "The confusion" → "Side-by-side" → "Decision tree" → "Scenario walkthroughs" → "Edge cases";workflow,checkpoint, andmilestonehave their own shapes). Replace every@@TODO@@comment with real prose, following its guidance. - Use a
```promptfence for anything the learner types into Claude (natural-language prompts,@-mentions,!shell passthrough). It renders as a prominent "Prompt:" card, visually distinct from a```bashfence (a command run in their own shell) and a```textfence (terminal or UI output they only read, such as a permission dialog). Getting this right is what tells the learner where to put the thing they are looking at. Every fence gets a copy button automatically. - Inline fenced code (
```bash,```javascript, …) is the default for examples — write it directly in the MDX body. Only reach for<Snippet id="…" />/<TryPrompt id="…" />at a spot that is genuinely language-specific (the same walkthrough needs different code per language pack). Pass--snippets/--promptsat scaffold time to stub those ids in the default pack, then write the real code there and add idiomatic versions to the other packs (e.g.python.ts). - Cross-reference other lessons inline with
<LessonLink>—<LessonLink id="B2.3" />renders the target lesson's title, or wrap custom text:<LessonLink id="B2.3">as we saw earlier</LessonLink>. The id must resolve (check-snippetsfails on unknown ids). Never leave a bare dotted id as plain text in prose; the style guide covers that rule, the id-as-label forms, and the grep to catch stragglers. - Inline links that leave the platform (official docs, pricing,
anthropic.com, any
http(s)://URL) are just normal markdown links[text](url); the MDXarenderer opens them in a new tab and appends the↗marker, so don't hand-rolltarget/rel. Every such URL must also be in the lesson'sdocsSources(see the style guide); add it to frontmatter and rerunnpm run gen:curriculumif you linked it inline first. Internal navigation uses<LessonLink>, not a raw link.
- Follow the lesson style guide:
- Verify:
npm run check-snippets— this is now the full content check (frontmatter validation + snippet/prompt coverage). Resolve everyERRORbefore finishing; warnings (fallback gaps, leftover@@TODO@@stubs) are fine to leave for a later pass. Style-check the finished lesson. Once the content is written and
check-snippetsis green, automatically dispatch thelesson-stylesubagent at the lesson (by dotted id or slug). It is read-only and returns a flag-only report againstdocs/lesson-style-guide.md. A lesson is not done until it has been through this check.When the report comes back, do not apply anything blindly. Analyze each flag and decide whether it is a real violation or a false positive:
CLEARflags are usually genuine;REVIEWflags are judgment calls — weigh each in context. Prose rules do not apply to simulated file/terminal content inside fences, so discard flags that misfire there.- Keep only the flags that genuinely need a fix; drop the rest, and be ready to say why you dropped them.
Then verify with the user before editing. Show the flags you judged valid and the specific change you propose for each, and get their go-ahead. Only after they approve do you make the edits, then re-run
npm run check-snippets(andnpm run gen:curriculumif you touched frontmatter). Never apply style edits without user confirmation.
New levels/modules
Levels and modules are hand-authored containers, not generated. Either:
- edit
src/content/structure.tsdirectly (add aLevelDef/ModuleDefentry), or - pass
--level-title/--module-title/--module-slugon the firstcli.ts lessoncall that references a new level id or module code — the scaffolder creates the container for you.
Whole module or level (batch)
- Draft the full outline and get the user's approval before writing anything.
- Write it to a temp JSON file in the
Outlineshape (seescripts/authoring/scaffold.ts):
Each lesson entry takes the same fields as the CLI flags above ({ "levels": [ { "id": "advanced", "title": "Advanced", "modules": [ { "code": "A7", "slug": "worktrees", "title": "Worktrees", "lessons": [ { "slug": "why-worktrees", "title": "Why Worktrees", "type": "core", "volatility": "stable", "verifiedAgainstDocsAt": "2026-07-03" } ] } ] } ] }slug,title,type,estimatedMinutes,volatility,verifiedAgainstDocsAt,prerequisites,teaches,references,docsSources,interactive,snippets,prompts) — dottedids are auto-assigned in file order as each lesson is scaffolded. - Scaffold the skeleton:
npx tsx scripts/authoring/cli.ts outline --file <path>— this also runsgen:curriculumat the end. - Fill lessons incrementally (as above).
npm run check-snippetsreports what remains; leftover@@TODO@@stubs are warnings, not errors, so a skeleton can be committed and finished over several passes. Run the step-5 style-check on each lesson as you finish it (dispatchlesson-style, analyze, verify with the user, then apply) — a lesson counts as done only after it passes that check.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

