原始内容
plan-html
Turn AI agent plans into commentable, beautifully designed HTML pages. Works with pi and Claude Code.
What it does
Instead of having your AI agent dump a markdown TODO list, it produces a structured plan-json block that gets rendered as a polished, commentable HTML page with:
- A sticky table of contents and progress widget
- Realistic UI mockups (real HTML in window/browser/phone chrome — not ASCII art)
- Mermaid diagrams for data flow and sequence
- Syntax-highlighted code snippets
- Callouts (note / warn / risk / ok)
- File-touch lists per step
- Risks + open questions panels
- Inline comment threads anchored per step
Three slash commands drive the workflow:
| Command | What it does |
|---|---|
/plan <prompt> |
Read-only research → emits plan-json → renders HTML → opens browser |
/plan-iterate (Claude) / /iterate (pi) |
Reads your inline comments, produces v2 |
/plan-approve (Claude) / /approve (pi) |
Restores full tools, executes the plan, ticks off [DONE] markers |
Install — pi
Add to ~/.pi/agent/settings.json:
{
"packages": ["npm:pi-plan-html"]
}
Restart pi. The slash commands /plan, /iterate, /approve, /plan-off, /plan-open become available in every repo.
Verify:
$ pi
> /plan add a hello endpoint to the server
A browser tab should open showing the rendered plan. Plan files land in <cwd>/.pi/plans/.
Uninstall: remove "npm:pi-plan-html" from packages and restart pi.
Install — Claude Code
Two steps (the skill files and the renderer CLI):
# One-liner: installs SKILL.md, the slash commands, AND plan-html-cli globally
curl -fsSL https://raw.githubusercontent.com/saadzniber/pi-plan-html/main/claude-skill/install.sh | bash
Or manually:
# 1. Install the renderer
npm install -g plan-html-cli
# 2. Install the skill + commands
git clone https://github.com/saadzniber/pi-plan-html.git
mkdir -p ~/.claude/skills/plan-html ~/.claude/commands
cp pi-plan-html/claude-skill/SKILL.md ~/.claude/skills/plan-html/SKILL.md
cp pi-plan-html/claude-skill/commands/*.md ~/.claude/commands/
Restart Claude Code. The slash commands /plan, /plan-iterate, /plan-approve become available.
Verify:
$ claude
> /plan add a hello endpoint to the server
Same browser tab, same HTML, same .pi/plans/ directory — pi users and Claude Code users can hand plans back and forth.
Uninstall:
rm -rf ~/.claude/skills/plan-html
rm -f ~/.claude/commands/{plan,plan-iterate,plan-approve}.md
npm uninstall -g plan-html-cli
Workflow
- Type
/plan <prompt>— the agent stays read-only, explores the repo, emitsplan-json. - HTML opens in your browser — scroll the TOC, expand mockups, read mermaid diagrams.
- Comment inline — hover a section, click 💬 comment, type feedback. Save → exports
feedback.mdto.pi/plans/. /iterate(pi) or/plan-iterate(Claude) — agent reads feedback, produces v2. Comments anchored bystep.keypersist across revisions./approve(pi) or/plan-approve(Claude) — full tools restored, agent executes,[DONE:<key>]markers tick a progress bar in the page footer.
plan-json schema
Click to expand the full schema
Agents emit one fenced block — and nothing else after it — in this exact form:
```plan-json
{
"title": "Short, specific name for the plan",
"context": "1–3 sentences. Why this work, what it changes, what success looks like.",
"header_chips": [
{ "label": "complexity: medium", "tone": "info" },
{ "label": "blast radius: contained", "tone": "ok" }
],
"steps": [
{
"key": "bootstrap",
"title": "Bootstrap the extension",
"body": "Markdown description of the step. Lists, tables, inline `code`, **emphasis**.",
"files": ["src/extension.ts", "package.json"],
"callouts": [
{ "tone": "warn", "title": "Heads up", "body": "Don't forget to check existing patterns." }
],
"code": [
{ "lang": "ts", "label": "src/extension.ts", "source": "export default function () { /* ... */ }" }
],
"mockup": {
"frame": "window",
"title": "Recording — Product Sync",
"html": "<header><strong>● Recording</strong><span class=\"spacer\"></span><button data-variant=\"primary\">Stop & Save</button></header><main><section><label>What do you want to remember?</label><input placeholder=\"Ask about pricing roadmap…\"></section></main>"
},
"diagram": "flowchart LR\n A[User] --> B[Extension] --> C[Browser]",
"verification": "How to confirm this step works."
}
],
"risks": [ "Concrete risk 1", "Concrete risk 2" ],
"open_questions": [ "Question we still need a human to answer" ]
}
```
Rules:
- One fenced block. Nothing after the closing fence.
- Strict JSON. No comments, no trailing commas.
- Every field outside
title,context, andsteps[].titleis optional. steps[].keyis a short, stable kebab-case slug. Reusing keys between v1 and v2 preserves the comment thread on the right section.
Components
| Field | Purpose |
|---|---|
header_chips[] |
Top-of-page status pills. tone: info | ok | warn | bad | accent. Max 4. |
steps[].body |
Markdown prose. |
steps[].files[] |
Files that will be created/edited/deleted (not just read). |
steps[].callouts[] |
Annotated cards. tone: note | warn | risk | ok. |
steps[].code[] |
Syntax-highlighted snippets, 5–20 lines. lang must be Prism-supported. |
steps[].mockup |
Realistic HTML UI mockup in a sandboxed iframe with chrome. See below. |
steps[].diagram |
Mermaid syntax (flowchart, sequenceDiagram, classDiagram, stateDiagram, erDiagram, gantt). |
steps[].verification |
1–2 sentences on how to confirm the step works. |
risks[] |
Concrete > generic. |
open_questions[] |
Things only a human can answer. |
Mockup frames
| Frame | Use for |
|---|---|
window (default) |
Desktop app UIs — macOS-style window with traffic lights + title |
browser |
Web pages — traffic lights + URL bar (uses title as URL) |
phone |
Mobile UIs — phone bezel with notch + home indicator |
none |
Fragments / partial UIs / chrome-less surfaces |
The iframe ships with a preset stylesheet — plain semantic markup already looks like a real product. Utility classes: .row .col .spacer .muted .pill .card .primary .danger .success. Button variants: data-variant="primary|ghost". No <script> tags (stripped at render time).
CLI usage (any agent)
The renderer is a standalone CLI — you don't need pi or Claude Code to use it. Any agent (Cursor, Cline, Aider, raw API) that can produce plan-json works:
plan-html render plan.json --open # render + open
plan-html extract transcript.md --out plan.json # pull a plan-json fence out of an LLM transcript
plan-html --help
How it works
agent → plan-json block → renderer (CLI or pi extension) → HTML in .pi/plans/
↑ ↓
└──── feedback.md ←── browser comments ←── (pi: local server; Claude: download)
Both the pi extension and the CLI render through the same design system (packages/pi-plan-html/design-system/ and packages/plan-html-cli/design-system/ — kept in sync). Output is byte-identical for the same input.
Theming
Override design tokens in :root:
:root {
--pds-accent: #2e7d32;
--pds-font-serif: "Lora", serif;
}
Dark mode is automatic via prefers-color-scheme; force with data-pds-theme="dark" on <html>.
Development
git clone https://github.com/saadzniber/pi-plan-html.git
cd pi-plan-html
npm install # installs workspaces
npm run pack-all # produces tarballs in each package dir
Test the pi extension locally — pack and install into pi's npm store:
npm pack --workspace pi-plan-html
mv pi-plan-html-0.1.0.tgz ~/.pi/agent/npm/
cd ~/.pi/agent/npm && npm install ./pi-plan-html-0.1.0.tgz
# add "npm:pi-plan-html" to ~/.pi/agent/settings.json packages
Test the Claude skill locally:
./claude-skill/install.sh # detects local checkout, copies from disk
Test the CLI directly:
node packages/plan-html-cli/bin/plan-html.js render examples/plan.json --open
FAQ
Does this work with Cursor / Cline / Aider?
Yes, via plan-html-cli. Tell your agent to write plan-json to a file and run plan-html render <file> --open.
Does this require a specific model?
No. Any model that follows the plan-json schema (Claude, GPT, Gemini, local Llamas) works.
Why does the package include 3 MB of vendored Mermaid? So plan viewing works offline. The alternative (CDN at render time) breaks on planes and in sandboxes.
Plans saved by Claude Code can be iterated in pi and vice-versa?
Yes. Both write .pi/plans/<base>-vN.{json,html} with the same schema.
The Claude Code skill can't "lock tools" like pi does — what stops Claude from editing files during /plan?
The slash command's prompt explicitly tells Claude not to. The model follows it, but it's prompt-level, not enforced by the harness. If you need strict read-only enforcement, use pi.
Packages
| Package | What it is | Where it goes |
|---|---|---|
pi-plan-html |
The pi extension | npm:pi-plan-html in ~/.pi/agent/settings.json |
plan-html-cli |
The standalone renderer CLI | npm install -g plan-html-cli |
claude-skill |
Claude Code skill + slash commands | ~/.claude/skills/plan-html/ + ~/.claude/commands/ |
License
MIT. Built on top of pi. Package shape inspired by pi-show-diffs.