From vision-powers
Converts any markdown document into a diagram-enriched visual HTML report. Useful for turning READMEs, ADRs, and specs into illustrated reports.
How this skill is triggered — by the user, by Claude, or both
Slash command
/vision-powers:doc-visual [md-file-path] [--format html|md] [--lang code] [--local (force a local file instead of publishing)][md-file-path] [--format html|md] [--lang code] [--local (force a local file instead of publishing)]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Read a markdown document and write a visual report with diagrams that match each section's meaning. Output is HTML (default) or markdown. You write the output directly — no templates, no intermediate JSON, no agent chains.
Read a markdown document and write a visual report with diagrams that match each section's meaning. Output is HTML (default) or markdown. You write the output directly — no templates, no intermediate JSON, no agent chains.
The previous version of this skill passed text through a pipeline of agents — each one only saw the output of the stage before it. By the time the report was assembled, the original content had been compressed into summaries of summaries. That's the failure mode you're replacing. You see the original document in full. That's the core advantage. If you find yourself writing "this section discusses X" instead of explaining X — that's compression, and it's the exact failure this redesign exists to fix.
Argument = single markdown file path. Directories, URLs, stdin not supported.
.md, .markdown, .txt)| Flag | Values | Default |
|---|---|---|
--format | html / md | html |
--lang | ISO code | auto-detected from document |
--local | switch | off — capable HTML publishes to an Artifact by default |
--artifact | switch | retained no-op alias (already the default on capable HTML) |
The report language must match the source document's language.
Channel is decided by the shared contract, not re-derived here — read
${CLAUDE_PLUGIN_ROOT}/references/design-system/channel-decision.md (SSOT, restates ADR 0009) for the
(Format × capable) → channel table, flag semantics, and the optimistic-try-then-regenerate rule.
The short version: capable HTML publishes to a claude.ai Artifact by default; --local forces the
local design-system + Mermaid file; md and non-capable sessions stay local.
--local forces local (analytical charts, zoom/pan) and also triggers on natural-language equivalents
— "keep it local", "don't publish", "just the local file" — in whatever language the user writes.
--artifact is the retained alias for the now-default behavior and still triggers on "as an artifact",
"publish as a link", "share as a URL"; if --local and --artifact are both signalled, --local wins.
Config precedence. Explicit this-turn signal > config > default. Before falling back to the
default, check stored preferences once: node ${CLAUDE_PLUGIN_ROOT}/scripts/config.js get (prints the
config as JSON, or {}). A default_format value replaces the html default. For the channel: an
absent artifact key means artifact-first (the default), artifact: false is a persistent
force-local (the config twin of --local), and artifact: true is explicit artifact-first. Anything
the user actually says this turn — a literal flag or a natural-language equivalent — always overrides
config; config only fills in when the request is silent on format/channel.
When the target format is md, whether you ask before publishing depends on how the request arrived:
--format md --artifact, exact tokens): that's a deliberate,
informed choice — publish the md file as-is, never ask. See "Markdown format — Artifact channel" below.--artifact token) while the target
format is md: check the md content for a ```mermaid fenced block first. None found → publish
as-is, same as the explicit path (nothing would be lost either way, so there's nothing to ask
about). Found one or more → the natural-language phrasing never committed to losing diagram
rendering, so ask once before publishing (see "Markdown format — Artifact channel").You write the output yourself. No template files, no assembly scripts, no intermediate formats.
HTML channel routing (default = Artifact). For --format html the channel is decided by
${CLAUDE_PLUGIN_ROOT}/references/design-system/channel-decision.md: on a capable account the
default is the Artifact channel — go straight to "HTML format — Artifact channel" below. Write the
local design-system + Mermaid file (the section directly under this one) only when --local is in
play, or as the non-capable regenerate fallback after a publish attempt fails (see "Publish"). md
is unaffected — it stays local either way.
--local / non-capable fallback)A self-contained single file — <!DOCTYPE html> to </html>:
<style> block with all CSS<script> for Mermaid CDN import and initialization<pre class="mermaid"> blocksThis is the default for --format html (ADR 0009). Same content decisions (modes,
section-to-diagram mapping, component menu, anti-slop-tells) as the local design-system format above
— only the page's shape and delivery mechanism change, because the page ships inside Claude Code's
official Artifacts feature instead of as a local file.
Before writing anything, load the built-in artifact-design skill (Skill tool, skill name
artifact-design). This is a tool contract MUST, not a suggestion — it's what conditions the model
for the CSP sandbox this page will run in, and skipping it is how a page ends up broken on publish.
Then write the page as a fragment, not a full document:
<!DOCTYPE>, <html>, <head>, or <body> tags — content only, starting from your first real
element. The Artifact tool wraps the file in that skeleton at publish time.<title> directly in the content — it names the artifact in the browser tab. Keep
it stable across every republish of the same document in this session.<script>, no Google Fonts <link>, no hotlinked images. Diagrams that would normally be
<pre class="mermaid"> become inline SVG or HTML+CSS layouts instead (follow the artifact-design
skill's guidance on this) — same diagram-type decision from diagram-type-selection.md, different
rendering technique. mermaid-patterns.md's CDN setup and classDef rules don't apply here.@media (prefers-color-scheme: dark) as the default signal, plus
:root[data-theme="dark"] / :root[data-theme="light"] overrides — the artifact viewer's theme
toggle stamps data-theme on the root and it must win in both directions.Save the fragment to ${CLAUDE_PLUGIN_DATA}/reports/{doc-basename}-doc-visual.artifact.html — a
distinct filename from the default channel's output, so the two never collide or overwrite each
other for the same source document.
Re-running this skill on the same input within the same conversation reuses that same path.
Publishing to the same file_path again redeploys to the same URL instead of minting a new one, so
keep the <title> and favicon identical across those republishes (the tool reads a changed
favicon as a different page). If ${output-path}.artifact.json already exists from an earlier
publish this session, read it first and reuse its title/favicon verbatim rather than choosing
new ones.
--format md)Insert directly into the response body, and save the same content to
${CLAUDE_PLUGIN_DATA}/reports/{doc-basename}-doc-visual.md — the chat text is the delivery, the
file is the record that lets report-manager list and refine this report later:
```mermaid blocks<script> — pure markdown--format md --artifact)Write the same content as the default markdown path above — same structure, same fenced
```mermaid blocks, nothing rewritten for the channel. There's no CSS or script to break under
the Artifact viewer's CSP, so unlike the HTML channel this variant needs no fragment rewrite, no
built-in artifact-design skill load, and no content-only gate — the md content is already correct
by the same standard the default md path holds itself to.
The one channel-specific fact to act on: claude.ai's markdown renderer does not render Mermaid
(confirmed by a direct publish-and-view test, 2026-07-05) — a mermaid fence displays as a plain
monospace code block, not a diagram. Decide what to do about that using the branch from "Format
detection" above:
Explicit (--format md --artifact typed literally): publish as-is, never ask. If the content
has any Mermaid blocks, add one line next to the URL noting they'll show as code, with the
rendered-diagram alternative — e.g. "Diagrams appear as code on this channel — for rendered
diagrams, use --format html --artifact" (in whatever language you're already replying in).
Ambiguous (natural-language artifact intent, target format md) and no Mermaid present:
publish as-is, same as explicit — there's no diagram fidelity at stake, so nothing to ask about.
Ambiguous and Mermaid is present: ask once with AskUserQuestion before publishing anything:
--format html --artifact (diagrams render — recommended)Act on whichever the user picks. Don't ask again in the same conversation once they've answered.
Publish steps: save the md content to
${CLAUDE_PLUGIN_DATA}/reports/{doc-basename}-doc-visual.artifact.md (reuse the same path on a
same-session re-run, same as the HTML variant), then follow "Publish (Artifact channel — default for
HTML)" below — the Artifact tool call, sidecar write, and fallback behavior are identical regardless
of format.
Decide which mode fits the source document:
| Mode | When | Diagrams | Text depth |
|---|---|---|---|
| explainer | Tutorials, guides, narrative docs | Illustrate concepts | Full prose — preserve all substance |
| structural | ADRs, specs, API docs, config references | Map relationships | Structured — tables, definition lists, code blocks |
If the document mixes both (e.g., a spec with a narrative intro), use structural as the base and apply explainer treatment to narrative sections.
For each section in the source document, decide whether a diagram adds value. Not every section needs one — if a table or list says it better, use that.
Read ${CLAUDE_PLUGIN_ROOT}/references/design-system/diagram-type-selection.md to choose the right type from the 13-type menu. The mapping priority section tells you which keywords suggest which types.
When no diagram fits, skip it. A section with good prose and no diagram beats a section with a forced diagram.
These are the building blocks. Mix them as the content demands:
| Component | When to use |
|---|---|
| Mermaid diagram | Relationships, flows, hierarchies — when connections are the point |
| Table | Comparisons, specs, 2-3 column data |
| Code block | Configs, commands, API examples |
| Prose paragraph | Narrative explanation, context, reasoning |
| Definition list | Term → meaning pairs |
| Callout box | Warnings, tips, important notes |
These govern Mermaid, which is a rendering technique rather than the diagram layer itself, so they
apply when you're writing the local design-system file (--local, or a non-capable fallback). On the
Artifact channel there is no Mermaid at all, and the built-in artifact-design skill owns density,
palette, and theming — the diagram type you chose in "Section-to-diagram mapping" carries over
unchanged, only the drawing technique differs (ADR 0009).
Read these reference files for implementation details — don't memorize them, read them each time:
${CLAUDE_PLUGIN_ROOT}/references/design-system/mermaid-patterns.md — Complete Mermaid syntax reference, theming, dark mode, zoom controls. This is the implementation bible — 13 type examples, classDef rules, CDN setup${CLAUDE_PLUGIN_ROOT}/references/design-system/semantic-tokens.md — Color/font roles and Mermaid themeVariables mapping${CLAUDE_PLUGIN_ROOT}/references/design-system/diagram-density-rules.md — Complexity budgets per typeKey rules for this channel (no need to look up):
#RRGGBBAAcolor: in classDef — breaks parser. Style text via themeVariables onlytheme: 'base' with themeVariables from semantic-tokens#8b5cf6/#7c3aed/#a78bfa/#d946ef) — the gate fails on theseEither channel's gate fails on dead links, alt-less images, and leftover scaffolding: give every <a> a real href, every <img> an alt (alt="" if decorative), and leave no {{ }}/lorem/[STUB] placeholders — those are content checks, so --content-only runs them too. This channel's full gate additionally fails on background-clip: text (gradient-clipped text — decorative slop) and on any font-family without a generic fallback, so end every stack with a system family (…, sans-serif).
You write your own CSS inline. These constraints matter:
font-family with a system fallback chain (e.g. Geist, system-ui, -apple-system, sans-serif) — the web fonts aren't bundled, so a bare family name silently drops to a browser default offline. See semantic-tokens.md for the per-role chains. Include a CJK font when the document might be Koreanprefers-color-scheme: dark via CSS custom properties. Map semantic roles (paper, ink, muted, accent) to both schemesviewBox × level (mermaid-patterns.md applyZoom()) — same vector sharpness as transform: scale(), but the diagram occupies the space it draws in, so the scroll container can reach all of it. Never the zoom propertymin-width: 0 on flex/grid childrenwhite-space: pre; overflow-x: autoprefers-reduced-motion: reduceThe source document's substance must survive intact in the report. This means:
If you're writing "this section covers X" or "the document describes Y" — stop. That's a summary of the content, not the content. Include the actual content.
This cardinal rule (call it summary-leak) is one of seven authoring reflexes that pass every mechanical gate and still flatten the output. Read ${CLAUDE_PLUGIN_ROOT}/references/design-system/anti-slop-tells.md for the full catalogue — linear dump, forced diagram, generic label, uniform density, empty decoration, accent overuse. They're named defaults to break, not design rules: layout and taste stay yours, the catalogue just flags the habits worth resisting.
Short documents (<500 chars) get 1 section + 1 hero diagram. Long documents get proper sectioning but still preserve all substance.
Which gate you run follows the channel (see "HTML channel routing" above):
--local / non-capable fallback) → the full gate immediately
below.For the local channel, after writing the HTML file run artifact-gate:
node ${CLAUDE_PLUGIN_ROOT}/scripts/artifact-gate.js <output-html-path>
It checks, in this order:
<img src="..."> pointing to nonexistent local files##, **, ``` leaked into HTML bodyrgb()/rgba() (parser break) or color: (dark-mode break) in a classDef<a> with no/empty/# href (pure id/name jump targets are exempt)<img> missing an alt attribute (alt="" for decorative images is allowed){{ … }}, lorem ipsum, or bracketed stubs left in the bodyIf violations found: fix them inline (re-edit the HTML). Max 2 retry cycles. If still failing after 2 fixes, remove the offending element and log a warning.
On the Artifact channel (the default), run the gate in content-only mode instead:
node ${CLAUDE_PLUGIN_ROOT}/scripts/artifact-gate.js <output-html-path> --content-only
This runs only checks 1, 2, 6, 7, 8 above (missing images, raw markdown, anchor hrefs, image alt, placeholders) — the facts that must survive regardless of who designed the page. Checks 3–5 (density, classDef, palette) don't apply: the built-in artifact-design skill owns the design layer on this channel (ADR 0007), and there's no Mermaid to check density on in the first place.
Runs only for the local design-system channel (--local / non-capable fallback) — it's the local
Chrome render loop. On the Artifact channel (the default) skip it entirely: the rendered picture is
the built-in artifact-design skill's responsibility there, and there's no local file to render before
publishing.
The gate reads the HTML as text — it never sees the rendered picture. A diagram can pass the density check and still render as an unreadable tangle; a label can clip at the container edge; hierarchy that reads fine in source can collapse into a flat wall once styled. After the gate passes, render the report and look at it before delivering:
node ${CLAUDE_PLUGIN_ROOT}/scripts/render-report.js <output-html-path>
On success it prints a PNG path. Read that PNG (you read images multimodally) and scan it for what the text gate can't judge:
<pre> text or as crossing/overlapping edges?Fix what you see and re-render. Cap at 2 audit passes — if something still looks off after the second, ship with a one-line note to the user rather than looping. This catches gross breakage, not pixel-perfection.
If Chrome is absent, render-report.js exits 1 (non-zero). Skip the audit and tell the user it was skipped (e.g. "rendered-image check skipped: Chrome not found — set CHROME_BIN or install Chrome"). The report already passed the gate; the visual pass is an enhancement and never blocks delivery.
Full procedure, limits (fixed-height clipping, downscaling, render cost), and the rationale for not mechanizing this with a measurement script live in ${CLAUDE_PLUGIN_ROOT}/references/design-system/visual-self-audit.md.
--local / non-capable fallback): save to
${CLAUDE_PLUGIN_DATA}/reports/{doc-basename}-doc-visual.html and run open <output-path>.${CLAUDE_PLUGIN_DATA}/reports/{doc-basename}-doc-visual.md. Footer links to the source path.For --format html, do this after the content-only gate passes. For --format md, there's no gate
to wait on — go straight to publishing once the branch in "Markdown format — Artifact channel" above
resolved to "publish."
Artifact tool: file_path = the file you saved (the html fragment or the md
file), favicon = one or two emoji fitting the document's topic (reused unchanged if a sidecar
from this session already set one — see above), description = one sentence on what the page is.node ${CLAUDE_PLUGIN_ROOT}/scripts/write-artifact-sidecar.js --report <output-path> --url <artifact-url> --title <title> --favicon <favicon>
Published to claude.ai — design is delegated to Claude's built-in Artifact renderer, so it differs from the local report's look; run --local for the local design-system + Mermaid version. This one line does double duty: it discloses the publish (the deliverable is now a URL,
not a local file) and the design delegation. Phrase it in whatever language you're already
replying in — the structure (published · delegated-design · --local escape hatch) is what's
canonical, not the exact English words.Fallback — non-capable session (regenerate, don't just open). If the Artifact tool is
unavailable or the publish call fails, the session is non-capable. Don't guess at the specific cause
and don't ask before falling back:
open it (that serves a broken, diagram-free page and breaks ADR 0009 §3's
promise of design-system + Mermaid on a non-capable session). Instead regenerate the full local
design-system + Mermaid report ("HTML format — local design-system channel" above), run its full
gate + visual self-audit, save to the …-doc-visual.html path, open it, and state the fallback in
one line (e.g. "Artifact publish unavailable — generated the local design-system report instead.").
Cost = one regeneration, only on a non-capable session.--format md path above) — and state the fallback in one generic line (e.g. "Artifact
publish unavailable — delivered as chat markdown instead.").| Failure | Action |
|---|---|
| File missing/no permission | Abort with message |
| Empty file | Abort — nothing to visualize |
| No headings (H1/H2/H3) | Treat as single section |
| html (default Artifact): Artifact tool unavailable or publish fails | Non-capable → regenerate the full local design-system + Mermaid report + open it + one-line reason, don't ask (never just open the fragment) |
| md + artifact intent: Artifact tool unavailable or publish fails | Fall back to chat-inserted markdown + one-line reason, don't ask |
| Mermaid syntax error after 2 fixes | Remove that diagram, keep section prose |
Read these during report generation (not upfront — read the relevant one when you need it):
| File | When to read |
|---|---|
${CLAUDE_PLUGIN_ROOT}/references/design-system/mermaid-patterns.md | Before writing any Mermaid diagram |
${CLAUDE_PLUGIN_ROOT}/references/design-system/semantic-tokens.md | When setting up CSS custom properties and Mermaid theme |
${CLAUDE_PLUGIN_ROOT}/references/design-system/diagram-type-selection.md | When deciding diagram type for a section |
${CLAUDE_PLUGIN_ROOT}/references/design-system/diagram-density-rules.md | When a diagram feels complex |
${CLAUDE_PLUGIN_ROOT}/references/design-system/anti-slop-tells.md | While shaping content — to check you're not falling into a behavioral-slop reflex |
${CLAUDE_PLUGIN_ROOT}/references/design-system/visual-self-audit.md | After the gate passes — the render-and-look loop (full procedure) |
npx claudepluginhub leejuoh/claude-code-zero --plugin vision-powersGenerates self-contained HTML pages for technical diagrams, architecture reviews, diff reviews, plans, and comparisons. Renders complex tables as styled HTML instead of ASCII.
Create HTML visualizations from repository documentation, markdown files, plan folders, and user context. Generates maps, flows, diagrams, and recommendation views using Mermaid and custom CSS.
Creates scientific documents, reports, and visualizations using markdown with embedded Mermaid diagrams. Includes style guides, 24 diagram types, and 9 templates for version-controlled text-based diagrams.