{"slug": "claude-code-skill-turn-a-session-s-findings-into-a-self-contained-html-report-md", "title": "Claude Code skill: turn a session's findings into a self-contained HTML report (with Markdown source). Drop into ~/.claude/skills/html-report/SKILL.md.", "summary": "A developer created a Claude Code skill that automatically generates self-contained HTML reports (with Markdown source) from session findings. The skill, named \"html-report,\" produces a Markdown file as the canonical source and a rendered HTML version as a single-file artifact, both written to a user-configured output directory. The tool supports structured content including tables, code blocks, callouts, task lists, and Mermaid diagrams, with a choice of color palettes and layouts based on the report's purpose and section count.", "body_md": "| name | html-report |\n|---|---|\n| description | Take all documentation, discoveries, and structured knowledge gathered in the current conversation and produce a self-contained HTML report (plus its Markdown source). Use when the user says \"/html-report\", asks to \"generate a report\", \"write this up as a report\", \"save this session as a report\", or wants a shareable artifact summarizing what was figured out in the session. |\n\nProduce a report pair — **Markdown first** (canonical source), then **HTML rendered from it** (self-contained, single file, no external assets). Files are written side-by-side into the user's configured output directory.\n\nCheck for `~/.claude/html-report-config.json`\n\n.\n\n-\n**If it exists**, read`output_dir`\n\nfrom it and use that for the rest of this run. Do not prompt. -\n**If it does NOT exist**, ask the user ONCE, in one short sentence:\"First run — where should reports be written? (default:\n\n`./reports/`\n\nin your current directory)\"Accept their answer. Acceptable forms:\n\n- Empty / \"default\" → use literal string\n`./reports`\n\n(resolved against cwd at write time, so reports land next to whatever project you're in) - Absolute path (e.g.\n`/Users/x/Documents/reports`\n\n) → use as-is `~`\n\n-prefixed (e.g.`~/reports`\n\n) → expand`~`\n\nto`$HOME`\n\nSave the answer:\n\n```\nmkdir -p ~/.claude\nprintf '{\"output_dir\": \"%s\"}\\n' \"$CHOSEN\" > ~/.claude/html-report-config.json\n```\n\nConfirm in one sentence: \"Saved. Reports will go to\n\n`<path>`\n\n. Re-run to change:`rm ~/.claude/html-report-config.json`\n\n.\" - Empty / \"default\" → use literal string\n\nThen proceed to Step 1. Create the resolved output dir with `mkdir -p`\n\nif it doesn't exist.\n\nBase: `<YYYY-MM-DD>-<kebab-topic>`\n\nwhere:\n\n- Date is today (system date).\n`<kebab-topic>`\n\ncomes from`$ARGUMENTS`\n\nif provided, else inferred from the dominant topic of the session in 1–4 kebab words (e.g.`auth-migration-research`\n\n,`db-migration-tutorial`\n\n,`vendor-eval`\n\n).\n\nIf the resulting `<base>.md`\n\nalready exists in the output dir, append `-2`\n\n, `-3`\n\n, etc. until unique.\n\nFinal paths:\n\n`MD=\"$OUTPUT_DIR/<base>.md\"`\n\n`HTML=\"$OUTPUT_DIR/<base>.html\"`\n\nWrite `$MD`\n\n. Required structure:\n\n**Frontmatter:**\n\n```\n---\ntitle: <Human-readable title>\ndate: <YYYY-MM-DD today>\ntype: report\ntags: [report, <other-relevant-tags>]\n---\n```\n\n**Body:** all session content in rich Markdown. Use:\n\n- Headings (\n`#`\n\n,`##`\n\n,`###`\n\n) —`##`\n\ndefines top-level sections used by Step 3. - Tables for schemas, configs, comparisons.\n- Fenced code blocks with language tags (\n```` go`\n\n,```` python`\n\n,```` bash`\n\n). - Callouts using GitHub/Obsidian syntax:\n`> [!note]`\n\n,`> [!warning]`\n\n,`> [!tip]`\n\n,`> [!info]`\n\n,`> [!danger]`\n\n,`> [!success]`\n\n. - Task lists:\n`- [ ]`\n\n/`- [x]`\n\nfor open questions or follow-ups. - Mermaid diagrams in\n```` mermaid`\n\nfences. - Inline emphasis (\n`**bold**`\n\n,`*italic*`\n\n,``code``\n\n).\n\nNo raw HTML inside the Markdown unless absolutely needed.\n\nWhy this is the way it is:the most common failure mode is the agent stalling on a single huge`Write`\n\n. Writing the full HTML at once exceeds the output token cap (~20K tokens) and hangs. Fix: write a small skeleton once, then fill sections incrementally with ONE`Edit`\n\nper turn.If you catch yourself \"designing\" the layout, picking colors from a menu, or batching Edits \"for speed\" — STOP. That's the stuck-state path.\n\nState your two choices in one plain sentence and move on. Examples:\n\n- \"Using teal palette, single-column layout.\"\n- \"Using amber palette, sidebar layout (16 sections).\"\n\n**Palette** (pick exactly one keyword): `teal`\n\n(research/data) · `amber`\n\n(RFC/decision) · `red-amber`\n\n(audit) · `green`\n\n(tutorial) · `neutral`\n\n(reference).\n\n**Layout** (pick exactly one keyword):\n\n`single-column`\n\n— default. Max-width 900px, no sidebar, no scroll-spy.`sidebar`\n\n— ONLY if section count`N ≥ 12`\n\n. Static sidebar TOC, no scroll-spy JS.\n\nDo not invent additional palettes, layouts, or \"decorations\" (back-to-top buttons, scroll-spy, SVG charts, etc.). **Content is the product, not styling.**\n\n```\nN=$(grep -c '^## ' \"$MD\")\necho \"N=$N\"\n```\n\nIf `N > 25`\n\n, tell the user once: \"Report has $N sections — HTML fill will take ~$N turns. Continuing.\" Then proceed without waiting.\n\nThe skeleton must be a complete valid HTML file with these — and ONLY these — pieces:\n\n`<!DOCTYPE html>`\n\n,`<html>`\n\n,`<head>`\n\nwith one inline`<style>`\n\nblock. CSS budget: ~2 KB. Include only:- Body font, base typography, max-width container (or sidebar grid if\n`layout=sidebar`\n\n). `h1`\n\n/`h2`\n\n/`h3`\n\nstyling.`table`\n\n(striped + padding),`pre`\n\n/`code`\n\nstyling,`pre.mermaid-source`\n\nstyling.- 5 callout classes —\n`.callout-note`\n\n(blue),`.callout-tip`\n\n(green),`.callout-warning`\n\n(amber),`.callout-danger`\n\n(red),`.callout-info`\n\n(purple). Each: colored left border + tinted background. `.tasks li::before`\n\nfor task-list checkboxes.\n\n- Body font, base typography, max-width container (or sidebar grid if\n- Hero header: title (from frontmatter) and date as plain text.\n- Main container.\n**Exactly N placeholder lines**, in order:\n\n``` php\n<!-- SECTION-0 --><!-- /SECTION-0 -->\n<!-- SECTION-1 --><!-- /SECTION-1 -->\n...\n```\n\n- Closing tags.\n\n**FORBIDDEN in the skeleton:** `<script>`\n\ntags of any kind, IntersectionObserver / scroll-spy code, back-to-top buttons, sidebar TOC pre-populated with section titles, fancy responsive grids, `@media`\n\nqueries beyond a single max-width fallback, any external CSS/JS link.\n\nIf your skeleton draft exceeds 8 KB, delete CSS rules until it fits.\n\n**HARD RULES — do not violate:**\n\n**ONE** Sequential is the whole point. If you're tempted to batch 2-3 Edits \"to save time,\" that IS the stuck state — stop and send one.`Edit`\n\nper response. Never two. Never parallel.**Cap per Edit** If a section's rendered HTML would exceed 3 KB, render only the first H3 subsection and append an inner placeholder`new_string`\n\n: 3 KB.`<!-- SECTION-i.1 --><!-- /SECTION-i.1 -->`\n\nto fill next turn.**After every Edit, run the checkpoint**(3.4.1) BEFORE doing anything else. Do not chain into the next section in the same turn.** Keep text output to ≤ 1 short sentence per turn**(\"Filled section 3.\"). No narration, no re-explaining the plan, no progress tables.\n\n```\ngrep -c '<!-- SECTION-' \"$HTML\"\n```\n\nThe number must decrement by exactly 1 after each successful Edit. If it does not, stop and inspect — do NOT keep sending Edits.\n\nFor each `i`\n\nfrom `0`\n\nto `N-1`\n\n, in its OWN turn:\n\n- Locate the\n`i`\n\n-th`##`\n\nheading in the markdown; capture everything until the next`##`\n\nor EOF. - Render to HTML following 3.5 (compact reference).\n- ONE\n`Edit`\n\n:`old_string`\n\n:`<!-- SECTION-i --><!-- /SECTION-i -->`\n\n(literal, substitute`i`\n\n)`new_string`\n\n:`<section id=\"sec-i\"><h2>Heading text</h2>…rendered…</section>`\n\n(≤ 3 KB)\n\n- Run 3.4.1 checkpoint.\n- End the turn.\n\n**Tables**→`<table>`\n\n(CSS already handles striping + padding).**Code blocks**→`<pre><code class=\"lang-X\">…</code></pre>`\n\n.**MUST** escape`<`\n\n`>`\n\n`&`\n\nto`<`\n\n`>`\n\n`&`\n\n. NO syntax-highlighting library, NO regex tokenizer — CSS-only styling.**Callouts**`> [!type]`\n\n→`<div class=\"callout callout-type\">…</div>`\n\n. Map: note→note, tip→tip, info→info, warning→warning, danger→danger, success→tip.**Mermaid**```` mermaid`\n\n→`<pre class=\"mermaid-source\">📊 Mermaid — paste into mermaid.live to render\\n\\n<ESCAPED source>\\n</pre>`\n\n. Never try to render visually.**Task lists**`- [ ]`\n\n/`- [x]`\n\n→`<ul class=\"tasks\"><li class=\"task-open\">…</li><li class=\"task-done\">…</li></ul>`\n\n.- No raw Markdown (\n`**bold**`\n\n,`###`\n\n, etc.) in the HTML output — render everything.\n\nDon't restart. Run:\n\n``` php\ngrep -nE '<!-- SECTION-[0-9]+ -->' \"$HTML\"\n```\n\nResume from the lowest remaining `i`\n\nusing 3.4.2. The skeleton is already correct.\n\n```\nremaining=$(grep -c '<!-- SECTION-' \"$HTML\")\nsize=$(wc -c < \"$HTML\")\necho \"remaining=$remaining size=$size\"\n```\n\n`remaining`\n\nMUST be `0`\n\n. `size`\n\nshould land in 20 000–200 000 bytes. If non-zero, return to 3.4.2 — do NOT rewrite the skeleton.\n\nOutput to the user (concise):\n\n- Markdown path\n- HTML path\n- One-line\n`open <html-path>`\n\ncommand they can paste\n\nDo not include any other commentary unless the user asked questions.", "url": "https://wpnews.pro/news/claude-code-skill-turn-a-session-s-findings-into-a-self-contained-html-report-md", "canonical_source": "https://gist.github.com/laurokirsch/26b70c436238e2c4b739edb3ef4ca7e3", "published_at": "2026-05-29 09:20:21+00:00", "updated_at": "2026-05-29 09:43:29.052919+00:00", "lang": "en", "topics": ["ai-tools", "ai-products", "ai-agents", "generative-ai", "large-language-models"], "entities": ["Claude Code", "SKILL.md", "Markdown", "HTML"], "alternates": {"html": "https://wpnews.pro/news/claude-code-skill-turn-a-session-s-findings-into-a-self-contained-html-report-md", "markdown": "https://wpnews.pro/news/claude-code-skill-turn-a-session-s-findings-into-a-self-contained-html-report-md.md", "text": "https://wpnews.pro/news/claude-code-skill-turn-a-session-s-findings-into-a-self-contained-html-report-md.txt", "jsonld": "https://wpnews.pro/news/claude-code-skill-turn-a-session-s-findings-into-a-self-contained-html-report-md.jsonld"}}