Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .claude/skills/write-chapter/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ Re-read each file with adversarial eyes and fix every instance of:
- A violation of the Appendix B conventions.
- Anything that would fail under `bun run` (syntax, type, import errors, missing await).
- Placeholders, TODOs, or incomplete logic.
- Non-ASCII punctuation.
- Non-ASCII punctuation outside a fenced diagram (prose and code stay ASCII; box-drawing and arrows are fine inside a ``` diagram).
- A diagram whose connectors do not line up under the node they descend from, or a vertical with no arrowhead - render the page and eyeball the diagram, never trust the raw source.
- Golfed/compressed code: any line that stacks multiple statements, sequences side effects with the comma operator, or inlines a multi-step expression to save a line. Re-expand to one statement per line (a multi-line `async function` over a dense one-line arrow), even if that grows the file - up to the 100-line hard cap. A correct-but-dense one-liner is a defect here, not a pass.

For cutoff-sensitive APIs (extended thinking, citations source schema, fine-tuning), verify the exact shape against current Anthropic docs; if you cannot verify, list the file under Review flags in the PR rather than guess.
Expand All @@ -114,7 +115,7 @@ For cutoff-sensitive APIs (extended thinking, citations source schema, fine-tuni
- Auth and runtime env vars are introduced and explained once, in Chapter 1: `ANTHROPIC_API_KEY` (sent as `x-api-key`, Anthropic direct), `ANTHROPIC_AUTH_TOKEN` (sent as `Authorization: Bearer`, used by some compatible providers), and `ANTHROPIC_BASE_URL` (which endpoint to call). Later chapters assume them; only mention an env var a sample actually uses.
- TypeScript style: prefer `type` over `interface`; never use `unknown` or index signatures; reuse SDK-exported types (`Anthropic.MessageParam`, `Anthropic.Tool`, `Anthropic.ToolUseBlock`, etc.).
- Loop idioms: for an unbounded produce-then-consume loop (long-polling an API, draining an event stream), prefer an async generator - `async function* poll()` that `yield`s, consumed with `for await (const x of poll())` - which separates transport from handling and matches the `for await...of` style used elsewhere. Where a generator does not fit, use `while (true)`. Never use `for (;;)`.
- ASCII punctuation only: `-`, `->`, `...`. No em dashes, no smart quotes. (This governs punctuation; emoji are allowed in chapter prose per the visual-aids rule, but code and example files stay ASCII-only.)
- ASCII punctuation in prose and code: `-`, `->`, `...`. No em dashes, no smart quotes. (This governs punctuation; emoji are allowed in chapter prose per the visual-aids rule, but code and example files stay ASCII-only.) The one exception: inside a fenced diagram (a ``` block) you MAY use Unicode box-drawing and arrow characters for a cleaner picture - the commit hook permits non-ASCII inside fences, while everything outside a fence stays ASCII.
- Each example is standalone and runnable on its own. Begin each file with a short header comment giving the run command (for example: `// bun run examples/05-tools/define-tool.ts`).
- Chapters are rendered by VitePress and published to GitHub Pages. In chapter prose, show a sample's full source with a VitePress snippet import (`<<< @/examples/NN-slug/file.ts`) on its own line, NOT by pasting the code into a fenced block - this keeps the rendered docs in lockstep with the runnable file. Inline fenced blocks are only for short illustrative fragments. The runnable file under `examples/` is the single source of truth; prose must not contradict it. After editing chapters, the site builds with `bun x vitepress@2.0.0-alpha.17 build`.
- Do NOT add Markdown links to chapters or pages that do not exist yet (for example a "next chapter" pointer like `[Chapter 2](./02-streaming.md)`). VitePress fails the build on dead links - refer to a not-yet-written chapter as plain text, and only turn it into a link once that page exists.
Expand All @@ -127,7 +128,7 @@ For cutoff-sensitive APIs (extended thinking, citations source schema, fine-tuni
- One-home rule: teach each fact once - in the prose OR a code comment, never both (example comments render inline via the snippet import, so a duplicated explanation shows up twice on the same page).
- Teach only what this chapter reaches: enum/option lists (for example `stop_reason` values) include only values a sample exercises, plus one short deferral clause for the rest.
- Going-deeper asides: secondary material (extra providers, full configs, full taxonomies) goes in a `::: details` block (or a `::: tip`/`::: info` callout), never a main-line H2. The main line must read complete if every aside is collapsed.
- Visual aids, used sparingly (seasoning, not structure): VitePress callout containers (`::: tip`, `::: info`, `::: warning`, `::: details`) for asides; AT MOST one small ASCII diagram per chapter, and only where a picture genuinely beats a sentence; a small Markdown table when comparing a short list of options (for example env vars or model tiers).
- Visual aids, used sparingly (seasoning, not structure): VitePress callout containers (`::: tip`, `::: info`, `::: warning`, `::: details`) for asides; AT MOST one small diagram per chapter, only where a picture genuinely beats a sentence - draw it with Unicode box-drawing inside a ``` fence (cleaner than ASCII `|`/`v`/`->` art, which is also fine), make the connectors line up under the node they descend from, give every descending line an arrowhead, and render the page to eyeball it; a small Markdown table when comparing a short list of options (for example env vars or model tiers).
- Config lives in the repo, not the prose: no `package.json`/`tsconfig.json` JSON dumps in a chapter - one sentence plus the run command, and note the repo already ships the scaffold so a follow-along reader can just run the file.
- Example code budget: keep each sample focused and single-concept; verbose, explicit code is welcome - favor clarity over brevity. Aim for <=70 lines (HARD CAP 100, `wc -l`) with comment:code ratio <=0.40 (a comment line's first token is `//` or `#`; an end-of-line comment counts as code). The header comment is the run command and nothing else. No numbered `// 1) ... // 2) ...` blocks over `console.log` groups, and no reference tables inside code files.
- Readability outranks the line count - never golf a sample to hit the budget. One statement per line: do NOT join multiple statements with `;` on one line, do NOT use the comma operator to sequence side effects (`(last = now), edit(...)`), and do NOT inline a multi-step expression (for example `(await fetch(...)).json()` with method/headers/body options) purely to save a line. A normal multi-line `async function` helper beats a dense one-line arrow. The standalone-file rule means each Telegram/`fetch` sample re-pastes its own helper, and verbose, explicit style is encouraged - that is exactly why the budget is generous (up to 100 lines) for samples that need it. If a sample still cannot fit while staying readable, cut its scope (or, when writing the issue, split it into two samples) - compression is never the answer.
Expand Down