# Kami Agent Guide ## Project Kami is a document-generation skill and template system: self-contained editorial HTML templates rendered to PDF / PPTX / PNG, plus reference specs, demo assets, and a packaged skill archive. `SKILL.md` is the runtime manual for producing a document. This file is the maintenance guide for changing the repository itself, and it records the traps that a fresh read of the code does not reveal. ## Layout One repository, three top-level roles, and the install tools only ever copy the first: - `skills/kami/` is the skill and the only thing users install: `SKILL.md`, `CHEATSHEET.md`, `VERSION`, `LICENSE`, `references/`, `scripts/`, and the light `assets/` (templates, diagrams, logo, the two small font files). `npx skills add tw93/kami` copies exactly this directory; `bash scripts/package-skill.sh` zips it as `kami/` for Claude Desktop; `plugins/kami/skills/kami/` is a generated copy of it inside the Claude and Codex plugin. Ignored render output lives in `skills/kami/assets/examples/`. Every skill-relative path in `SKILL.md` resolves inside this directory, so nothing here may reach up into the repo. - `site/` is kami.tw93.fun. The Vercel project's Root Directory is `site` (project setting, not a file), so only this tree deploys and `site/vercel.json` is the only Vercel config. It carries the pages, `styles.css`, `llms.txt`, `robots.txt`, `sitemap.xml`, `vercel.json`, `.well-known/`, `feeds/`, and the heavy showcase and demo assets. Skill facts it shows (`SKILL.md`, the discovery files) are generated into it, never hand-copied. `/SKILL.md` and `/kami-skill.md` send `X-Robots-Tag: noindex`: agents can still fetch the markdown, and search engines should not score that file as an HTML page. - The root holds repository tooling only: `scripts/` (`build_metadata.py`, `package-skill.sh`, `release_gate.py`, `draft-release-notes.py`, `tests/`), `assets/fonts/` (the commercial TTFs; run `bash skills/kami/scripts/ensure-fonts.sh` once after cloning to copy them into the skill's ignored `assets/fonts/`, otherwise templates fall back to jsDelivr), `evals/` (the end-to-end skill eval suite, see Evals below), `docs/`, and `.github/`. Run skill-side commands from `skills/kami/` (`cd skills/kami && python3 scripts/build.py --check`); the paths below are written from that directory unless they start with `scripts/build_metadata.py`, `scripts/package-skill.sh`, `scripts/release_gate.py`, or `scripts/tests/`, which live at the root. Paths under `site/`, `plugins/`, `docs/`, `.github/`, `.claude-plugin/`, and `.agents/` are also relative to the repository root. ## Repository Map Only the entries whose role is not obvious from the filename: - `SKILL.md` - skill routing plus the document-side build and verify commands. `CHEATSHEET.md` - quick design reference. Both ship inside the package. - `references/design.md`, `writing.md`, `production.md`, `diagrams.md` - full specs. `production.md` Part 4 is the single source of truth for render failures, their verified causes, and their fixes; add pitfalls there, not here. `docs/release.md` - release notes, release flow, demo screenshot regeneration. `anti-patterns.md`, `resume-writing.md`, `mermaid.md`, `deck-preflight.md`, `brand-profile.md` and `brand.example.md` - scoped guides. - `references/tokens.json` (color tokens, drift-checked by `scripts/tokens.py`), `references/mermaid-theme.json` (Kami to beautiful-mermaid theme, kept in sync with `tokens.json`), `references/checks_thresholds.json` (rhythm / density / orphan / visual thresholds read by `checks.py` and `visual.py`). These are live inputs to gates: editing a number changes what passes. - `references/schemas/` - one JSON Schema subset per document type. The `$comment` fields carry the per-field quality bar distilled from `writing.md`, so schema edits and `writing.md` edits move together. - `scripts/shared.py` - the canonical registries (`HTML_TEMPLATES`, `SCREEN_TEMPLATES`, `PPTX_TEMPLATES`, `MARP_TEMPLATES`, `DIAGRAM_TEMPLATES`) and each template's `build_max_pages`. `build.py` derives its internal build targets from them; Marp stays discovery-only because it uses an external CLI. Add or remove a template or diagram here, never in a per-script dict. - `scripts/render.py` - the single render entry (`render_pdf`, `build_slides`, PDF metadata stamping). `build.py`, `verify.py`, and `mcp_server.py` all call it; never open a second WeasyPrint call site. - `scripts/diagram_geometry.py` checks annotated architecture SVG through the existing lint entry points. Keep geometry in the actual rect/line/polyline attributes, never a second JSON source. Mark node rectangles, edge shafts and label masks; leave boundary frames and arrowheads unmarked. Static mask checks do not replace rendered text-fit and arrowhead inspection. - `scripts/deliver.py` - `build.py --deliver`, the one command `SKILL.md` gives an agent to finish a document: every document gate in a fixed order, the render, page images, and a single READY / NOT READY verdict. It owns the order; the individual `--check-*` flags stay for debugging one gate. Template family comes from content IR `type`, else from stylesheet overlap with the registered templates. `deliver(args, result)` also fills a dict with the same outcome for the MCP `kami_deliver` tool; `mcp_server.DELIVER_GATE_RULES` maps every deliver gate to a `kami_check` rule or declares it deliver-only, and `test_mcp` fails on a new gate that is in neither. - `scripts/chart.py` - `build.py --chart` / `--check-charts`: data spec to SVG for bar, line, hbar, donut, candlestick, and waterfall. Chart geometry lives only here; each SVG embeds its spec in `data-kami-spec` and the drift gate regenerates and compares the marks. The five chart files in `assets/diagrams/` are its output for their demo data: change a chart's look in `chart.py` and regenerate them, never edit their SVG by hand (`--check` fails on drift). - `scripts/brand_extract.py` - drafts a brand profile from a public website (colors, fonts, logo candidates, one contrast-checked accent). It fetches only the page and same-site stylesheets and never writes into `~/.config/kami/`. - `scripts/html_visibility.py` - shared static HTML/CSS visibility analysis for `content.py` coverage and `checks.py` residue checks. Keep its conservative coverage and residue modes distinct; it does not implement browser layout. - `scripts/tests/test_build.py` - the stable test entry point; sibling `test_*.py` modules group tests by responsibility, with counters and fixtures in `support.py`. `scripts/tests/corpus//{flag,pass}/` is the labelled corpus for the PDF gates (orphans, density, resume balance), rendered and judged by `test_corpus.py`. Before changing a value in `checks_thresholds.json`, run it and read the per-gate `CORPUS:` line; a fixture that flips is the cost of the change, not noise. - `scripts/mermaid_normalize.py` - re-themes a beautiful-mermaid SVG to the Kami palette and makes it WeasyPrint-safe. Pure Python, no Node, ships in the package. - `scripts/mcp_server.py` - zero-dependency MCP stdio server exposing `kami_templates` / `kami_doctor` / `kami_render` / `kami_check` / `kami_deliver` / `kami_screenshot`, so an MCP-capable agent can diagnose, render, and verify without reading `SKILL.md`. Register with `claude mcp add kami -- python3 /skills/kami/scripts/mcp_server.py`. - `scripts/math_render.py`, `scripts/mathjax_svg.js`, `scripts/ensure_mathjax.sh`, `scripts/mathjax-runtime/` - strict LaTeX to MathJax SVG; `render.py` imports `math_render`. This is the only Node dependency (Node 20 or 22+, refused otherwise), installed on demand by `ensure_mathjax.sh` from the tracked `package-lock.json`; all four ship in the package allowlist. - `scripts/site_facts.py` - public-site fact drift checks (install commands, version, template and diagram counts across `site/index*.html`, the root `README.md`, `site/llms.txt`), wired into `build.py --check`; it resolves those files through `shared.REPO_ROOT` / `shared.SITE_ROOT` and skips itself in an installed skill. - `scripts/check-update.sh` - quiet daily update check invoked from `SKILL.md`; writes a local cache marker, then resolves the latest published GitHub Release at most once per day. It uploads no user document or task content and stays silent on failure. - `site/assets/showcase/` - README and public-site screenshots only. `site/assets/demos/` - README showcase demos. Neither is part of the skill. - `assets/diagrams/src/*.mmd` - Mermaid source of the sequence / class / er diagrams. `assets/templates/marp/` - the Markdown-first Marp deck variant. - `dist/` is ignored. The release archive is built by `release.yml` from `skills/kami` and uploaded as a release asset; nothing tracks it. - `plugins/kami/`, `.claude-plugin/marketplace.json`, `.agents/plugins/marketplace.json`, and the site's discovery files are **generated**; see Generated Mirrors below. - Public site surface under `site/`: `index.html` plus `index-zh|en|ja|ko|tw.html`, the English-only prose pages `developers|about|contact|privacy.html`, `styles.css`, `llms.txt`, `robots.txt`, `sitemap.xml`, `vercel.json`. `styles.css` is Kami's own site shell (language switcher, gallery, responsive behavior, `.hero.doc` / `.prose` for the prose pages); generic template rules never belong there. - Agent-facing site surface, also under `site/`: `index.md` (Markdown twin of the homepage; `vercel.json` *redirects* `/` here for `Accept: text/markdown` and `/?mode=agent`, because Vercel applies `rewrites` only after the filesystem and `/` always matches `index.html`), `developers|about|contact|privacy.md`, `developers/llms.txt`, and the generated `.well-known/agent-skills/index.json`, `.well-known/mcp/server-card.json`, `feeds/catalog.jsonld`, `schemamap.xml`, `kami-skill.md` (served at `/SKILL.md` through a rewrite; it must not be named `SKILL.md`, or the skills CLI installs the site). Every new prose page needs its `.md` twin, a `rewrites` entry for the extensionless URL, and a `sitemap.xml` row. The `has`-conditioned redirects and the `Link` headers are only observable on a deploy: verify them with `curl -sI` against the preview URL, never locally. - `.github/workflows/check.yml` (PR/push CI) and `release.yml` (tag-triggered build and asset upload). Reference docs are English-first and never forked per language. Inline CJK examples are fine where the rule itself is about CJK typography (term annotation, punctuation, spacing); language-specific output differences (CN/EN/KO) live in templates, not in duplicated reference files. ## Commands `python3 scripts/build.py --help` prints the authoritative flag list and the module map. Read it instead of trusting any copy; hand-maintained lists here have gone stale before. The commands it does not cover: ```bash # from the repository root python3 scripts/build_metadata.py # regenerate plugins/kami, marketplaces, site discovery files python3 scripts/build_metadata.py --check # drift check for the same bash scripts/package-skill.sh dist/kami.zip # build the Claude Desktop archive from skills/kami python3 scripts/tests/test_build.py # full test suite python3 scripts/draft-release-notes.py V1.4.0..HEAD --version V1.4.1 --title "Steadier Hand" claude plugin eval . --runs 2 --ablation none -j 4 --keep-temp --trust-plugin --no-publish \ --threshold 0 --judge-model sonnet --allow-tools Bash Write Edit # end-to-end skill evals python3 evals/score.py # deterministic gates over the newest eval run # from skills/kami bash scripts/ensure-fonts.sh # recover missing or truncated CJK fonts python3 scripts/mcp_server.py # MCP stdio server (render / check / screenshot) python3 scripts/mermaid_normalize.py raw.svg -o clean.svg ``` ## Working Rules - `SKILL.md` is loaded whole on every trigger, so it carries routing, the execution contract, hard prohibitions, `--deliver`, and the feedback protocol, nothing else. Type-specific procedure (page density, resume recruiter pass, landing site mode, charts, illustrations) lives in the reference the tier table already sends the agent to. Before adding a paragraph to `SKILL.md`, name the eval case it fixes; before removing one, run the suite and compare against the last baseline. - Style changes must update `references/design.md` and the matching template tokens. - A CSS snippet in a reference doc is a shipped artifact, not prose: an agent copies it before it reads a template. Every fenced `css` / `html` block is scanned by `--check-docs` (inside `--check`) with the template rule set, and every `var()` it names must resolve to a registered token or one a shipped template defines. Teach from a component a template actually has; a recipe for assembling a new container is how a document ends up carrying three unrelated emphasis languages. Tag a deliberate counter-example inline with `/* avoid */` so the scan reads it as the lesson rather than the violation. - A change touching template tokens, shared CSS gestures, or `references/design.md` visual rules must rebuild the affected demo outputs (`site/assets/demos/*.pdf` / `*.png`) in the same change, not as a later cleanup. Demos inline their CSS by copy, so they silently keep the old style otherwise. Report the sweep: rebuilt N demos, K unaffected. The off-palette guard in `scripts/lint.py` scans `site/assets/demos/*.html` for stale hexes as a backstop, but it cannot see rendered PDFs or PNGs. Repository scans must reject an empty expected demo set; installed skills may skip the site because it is outside their distribution boundary. Test both modes with a known violating demo whenever repository paths change. - Templates intentionally inline their CSS rather than share a `_kami.css` partial: each template must stay a single self-contained HTML file the user can copy-paste with no build step. Fix CSS drift by applying the same change across the affected templates, never by introducing a build-time include. - For document or template tasks, lock the output contract before editing: language, template, output format, page or length target, visual acceptance check, and verification command. - Prefer the nearest existing template and deterministic verifier. Do not add a template, shared CSS layer, dependency, script flag, or optional mode unless the current request cannot be satisfied without it. A new template copies the nearest existing one, stays aligned with `references/design.md`, and adds demo coverage; a new document type also needs a schema in `references/schemas/`. - Slides default to WeasyPrint HTML-to-PDF templates unless the user explicitly needs editable PPTX output. - Mermaid diagrams: never embed raw beautiful-mermaid SVG into a PDF-bound template. WeasyPrint cannot resolve `color-mix()`, render ``, or fetch a runtime web font, so always pipe through `scripts/mermaid_normalize.py` first (`--check` enforces this). `xychart-beta` is browser-only because it styles through `