cd /news/ai-tools/claude-code-skill-turn-a-session-s-f… · home topics ai-tools article
[ARTICLE · art-17422] src=gist.github.com pub= topic=ai-tools verified=true sentiment=· neutral

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.

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.

read6 min publishedMay 29, 2026
name html-report
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.

Produce 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.

Check for ~/.claude/html-report-config.json

.

If it exists, readoutput_dir

from it and use that for the rest of this run. Do not prompt. - If it does NOT exist, ask the user ONCE, in one short sentence:"First run — where should reports be written? (default:

./reports/

in your current directory)"Accept their answer. Acceptable forms:

  • Empty / "default" → use literal string ./reports

(resolved against cwd at write time, so reports land next to whatever project you're in) - Absolute path (e.g. /Users/x/Documents/reports

) → use as-is ~

-prefixed (e.g.~/reports

) → expand~

to$HOME

Save the answer:

mkdir -p ~/.claude
printf '{"output_dir": "%s"}\n' "$CHOSEN" > ~/.claude/html-report-config.json

Confirm in one sentence: "Saved. Reports will go to

<path>

. Re-run to change:rm ~/.claude/html-report-config.json

." - Empty / "default" → use literal string

Then proceed to Step 1. Create the resolved output dir with mkdir -p

if it doesn't exist.

Base: <YYYY-MM-DD>-<kebab-topic>

where:

  • Date is today (system date). <kebab-topic>

comes from$ARGUMENTS

if provided, else inferred from the dominant topic of the session in 1–4 kebab words (e.g.auth-migration-research

,db-migration-tutorial

,vendor-eval

).

If the resulting <base>.md

already exists in the output dir, append -2

, -3

, etc. until unique.

Final paths:

MD="$OUTPUT_DIR/<base>.md"

HTML="$OUTPUT_DIR/<base>.html"

Write $MD

. Required structure:

Frontmatter:

---
title: <Human-readable title>
date: <YYYY-MM-DD today>
type: report
tags: [report, <other-relevant-tags>]
---

Body: all session content in rich Markdown. Use:

  • Headings ( #

,##

,###

) —##

defines top-level sections used by Step 3. - Tables for schemas, configs, comparisons.

  • Fenced code blocks with language tags ( ```` go`

,```` python`

,```` bash`

). - Callouts using GitHub/Obsidian syntax: > [!note]

,> [!warning]

,> [!tip]

,> [!info]

,> [!danger]

,> [!success]

. - Task lists: - [ ]

/- [x]

for open questions or follow-ups. - Mermaid diagrams in ```` mermaid`

fences. - Inline emphasis ( **bold**

,*italic*

,code

).

No raw HTML inside the Markdown unless absolutely needed.

Why this is the way it is:the most common failure mode is the agent stalling on a single hugeWrite

. 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 ONEEdit

per 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.

State your two choices in one plain sentence and move on. Examples:

  • "Using teal palette, single-column layout."
  • "Using amber palette, sidebar layout (16 sections)."

Palette (pick exactly one keyword): teal

(research/data) · amber

(RFC/decision) · red-amber

(audit) · green

(tutorial) · neutral

(reference).

Layout (pick exactly one keyword):

single-column

— default. Max-width 900px, no sidebar, no scroll-spy.sidebar

— ONLY if section countN ≥ 12

. Static sidebar TOC, no scroll-spy JS.

Do not invent additional palettes, layouts, or "decorations" (back-to-top buttons, scroll-spy, SVG charts, etc.). Content is the product, not styling.

N=$(grep -c '^## ' "$MD")
echo "N=$N"

If N > 25

, tell the user once: "Report has $N sections — HTML fill will take ~$N turns. Continuing." Then proceed without waiting.

The skeleton must be a complete valid HTML file with these — and ONLY these — pieces:

<!DOCTYPE html>

,<html>

,<head>

with one inline<style>

block. CSS budget: ~2 KB. Include only:- Body font, base typography, max-width container (or sidebar grid if layout=sidebar

). h1

/h2

/h3

styling.table

(striped + padding),pre

/code

styling,pre.mermaid-source

styling.- 5 callout classes — .callout-note

(blue),.callout-tip

(green),.callout-warning

(amber),.callout-danger

(red),.callout-info

(purple). Each: colored left border + tinted background. .tasks li::before

for task-list checkboxes.

  • Body font, base typography, max-width container (or sidebar grid if
  • Hero header: title (from frontmatter) and date as plain text.
  • Main container. Exactly N placeholder lines, in order:
<!-- SECTION-0 --><!-- /SECTION-0 -->
<!-- SECTION-1 --><!-- /SECTION-1 -->
...
  • Closing tags.

FORBIDDEN in the skeleton: <script>

tags of any kind, IntersectionObserver / scroll-spy code, back-to-top buttons, sidebar TOC pre-populated with section titles, fancy responsive grids, @media

queries beyond a single max-width fallback, any external CSS/JS link.

If your skeleton draft exceeds 8 KB, delete CSS rules until it fits.

HARD RULES — do not violate:

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

per 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 placeholdernew_string

: 3 KB.<!-- SECTION-i.1 --><!-- /SECTION-i.1 -->

to 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.

grep -c '<!-- SECTION-' "$HTML"

The number must decrement by exactly 1 after each successful Edit. If it does not, stop and inspect — do NOT keep sending Edits.

For each i

from 0

to N-1

, in its OWN turn:

  • Locate the i

-th##

heading in the markdown; capture everything until the next##

or EOF. - Render to HTML following 3.5 (compact reference).

  • ONE Edit

:old_string

:<!-- SECTION-i --><!-- /SECTION-i -->

(literal, substitutei

)new_string

:<section id="sec-i"><h2>Heading text</h2>…rendered…</section>

(≤ 3 KB)

  • Run 3.4.1 checkpoint.
  • End the turn.

Tables<table>

(CSS already handles striping + padding).Code blocks<pre><code class="lang-X">…</code></pre>

.MUST escape<

>

&

to<

>

&

. NO syntax-highlighting library, NO regex tokenizer — CSS-only styling.Callouts> [!type]

<div class="callout callout-type">…</div>

. Map: note→note, tip→tip, info→info, warning→warning, danger→danger, success→tip.Mermaid```` mermaid`

<pre class="mermaid-source">📊 Mermaid — paste into mermaid.live to render\n\n<ESCAPED source>\n</pre>

. Never try to render visually.Task lists- [ ]

/- [x]

<ul class="tasks"><li class="task-open">…</li><li class="task-done">…</li></ul>

.- No raw Markdown ( **bold**

,###

, etc.) in the HTML output — render everything.

Don't restart. Run:

grep -nE '<!-- SECTION-[0-9]+ -->' "$HTML"

Resume from the lowest remaining i

using 3.4.2. The skeleton is already correct.

remaining=$(grep -c '<!-- SECTION-' "$HTML")
size=$(wc -c < "$HTML")
echo "remaining=$remaining size=$size"

remaining

MUST be 0

. size

should land in 20 000–200 000 bytes. If non-zero, return to 3.4.2 — do NOT rewrite the skeleton.

Output to the user (concise):

  • Markdown path
  • HTML path
  • One-line open <html-path>

command they can paste

Do not include any other commentary unless the user asked questions.

── more in #ai-tools 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/claude-code-skill-tu…] indexed:0 read:6min 2026-05-29 ·