Browser-based visual brainstorming companion for showing mockups, diagrams, and options.
Decide per-question, not per-session. The test: would the user understand this better by seeing it than reading it?
Use the browser when the content itself is visual:
Use the terminal when the content is text or tabular:
A question about a UI topic is not automatically a visual question. "What kind of wizard do you want?" is conceptual — use the terminal. "Which of these wizard layouts feels right?" is visual — use the browser.
The server watches a directory for HTML files and serves the newest one to the browser. You write HTML content, the user sees it in their browser and can click to select options. Selections are recorded to a .events file that you read on your next turn.
Content fragments vs full documents: If your HTML file starts with <!DOCTYPE or <html, the server serves it as-is (just injects the helper script). Otherwise, the server automatically wraps your content in the frame template — adding the header, CSS theme, selection indicator, and all interactive infrastructure. Write content fragments by default. Only write full documents when you need complete control over the page.
The brainstorm server is a Node.js app in lib/brainstorm-server/ inside the superpowers plugin directory.
Finding the server: Use $CLAUDE_PLUGIN_ROOT if it's set. If not, locate the superpowers plugin — check ~/.claude/plugins/cache/ (Claude Code), ~/.agents/skills/superpowers/ (Codex), or similar. The server entry point is lib/brainstorm-server/start-server.sh.
Starting with bash (Mac/Linux, or Windows with Git Bash):
/path/to/superpowers/lib/brainstorm-server/start-server.sh --project-dir /path/to/project
# Returns: {"type":"server-started","port":52341,"url":"http://localhost:52341",
# "screen_dir":"/path/to/project/.superpowers/brainstorm/12345-1706000000"}
Without bash (Windows/PowerShell): Run node directly from lib/brainstorm-server/:
node index.js
Set these environment variables before running: BRAINSTORM_DIR (session directory you create — e.g., <project>/.superpowers/brainstorm/<session-id>), BRAINSTORM_HOST (default 127.0.0.1), BRAINSTORM_URL_HOST (default localhost).
Save screen_dir from the response. Tell user to open the URL.
Note: Pass the project root as --project-dir (or set BRAINSTORM_DIR under it) so mockups persist in .superpowers/brainstorm/ and survive server restarts. Without it, files go to /tmp and get cleaned up. Remind the user to add .superpowers/ to .gitignore if it's not already there.
Codex behavior: In Codex (CODEX_CI=1), start-server.sh auto-switches to foreground mode by default because background jobs may be reaped. Use --background only if your environment reliably preserves detached processes.
If background processes are reaped in your environment: run in foreground from a persistent terminal session. With bash, pass --foreground. With node directly, it runs in foreground by default.
If the URL is unreachable from your browser (common in remote/containerized setups), bind a non-loopback host by passing --host 0.0.0.0 --url-host localhost (bash) or setting BRAINSTORM_HOST=0.0.0.0 and BRAINSTORM_URL_HOST=localhost (node).
Write HTML to a new file in screen_dir:
platform.html, visual-style.html, layout.htmlTell user what to expect and end your turn:
On your next turn — after the user responds in the terminal:
$SCREEN_DIR/.events if it exists — this contains the user's browser interactions (clicks, selections) as JSON lines.events provides structured interaction dataIterate or advance — if feedback changes current screen, write a new file (e.g., layout-v2.html). Only move to the next question when the current step is validated.
Unload when returning to terminal — when the next step doesn't need the browser (e.g., a clarifying question, a tradeoff discussion), push a waiting screen to clear the stale content:
<!-- filename: waiting.html (or waiting-2.html, etc.) -->
<div style="display:flex;align-items:center;justify-content:center;min-height:60vh">
<p class="subtitle">Continuing in terminal...</p>
</div>
This prevents the user from staring at a resolved choice while the conversation has moved on. When the next visual question comes up, push a new content file as usual.
Write just the content that goes inside the page. The server wraps it in the frame template automatically (header, theme CSS, selection indicator, and all interactive infrastructure).
Minimal example:
<h2>Which layout works better?</h2>
<p class="subtitle">Consider readability and visual hierarchy</p>
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Single Column</h3>
<p>Clean, focused reading experience</p>
</div>
</div>
<div class="option" data-choice="b" onclick="toggleSelect(this)">
<div class="letter">B</div>
<div class="content">
<h3>Two Column</h3>
<p>Sidebar navigation with main content</p>
</div>
</div>
</div>
That's it. No <html>, no CSS, no <script> tags needed. The server provides all of that.
The frame template provides these CSS classes for your content:
<div class="options">
<div class="option" data-choice="a" onclick="toggleSelect(this)">
<div class="letter">A</div>
<div class="content">
<h3>Title</h3>
<p>Description</p>
</div>
</div>
</div>
Multi-select: Add data-multiselect to the container to let users select multiple options. Each click toggles the item. The indicator bar shows the count.
<div class="options" data-multiselect>
<!-- same option markup — users can select/deselect multiple -->
</div>
<div class="cards">
<div class="card" data-choice="design1" onclick="toggleSelect(this)">
<div class="card-image"><!-- mockup content --></div>
<div class="card-body">
<h3>Name</h3>
<p>Description</p>
</div>
</div>
</div>
<div class="mockup">
<div class="mockup-header">Preview: Dashboard Layout</div>
<div class="mockup-body"><!-- your mockup HTML --></div>
</div>
<div class="split">
<div class="mockup"><!-- left --></div>
<div class="mockup"><!-- right --></div>
</div>
<div class="pros-cons">
<div class="pros"><h4>Pros</h4><ul><li>Benefit</li></ul></div>
<div class="cons"><h4>Cons</h4><ul><li>Drawback</li></ul></div>
</div>
<div class="mock-nav">Logo | Home | About | Contact</div>
<div style="display: flex;">
<div class="mock-sidebar">Navigation</div>
<div class="mock-content">Main content area</div>
</div>
<button class="mock-button">Action Button</button>
<input class="mock-input" placeholder="Input field">
<div class="placeholder">Placeholder area</div>
h2 — page titleh3 — section heading.subtitle — secondary text below title.section — content block with bottom margin.label — small uppercase label textWhen the user clicks options in the browser, their interactions are recorded to $SCREEN_DIR/.events (one JSON object per line). The file is cleared automatically when you push a new screen.
{"type":"click","choice":"a","text":"Option A - Simple Layout","timestamp":1706000101}
{"type":"click","choice":"c","text":"Option C - Complex Grid","timestamp":1706000108}
{"type":"click","choice":"b","text":"Option B - Hybrid","timestamp":1706000115}
The full event stream shows the user's exploration path — they may click multiple options before settling. The last choice event is typically the final selection, but the pattern of clicks can reveal hesitation or preferences worth asking about.
If .events doesn't exist, the user didn't interact with the browser — use only their terminal text.
platform.html, visual-style.html, layout.htmllayout-v2.html, layout-v3.htmlStop the server using stop-server.sh in lib/brainstorm-server/ (same directory as start-server.sh), passing the $SCREEN_DIR. Or kill the process by pid from $SCREEN_DIR/.server.pid.
If the session used --project-dir, mockup files persist in .superpowers/brainstorm/ for later reference. Only /tmp sessions get deleted on stop.
lib/brainstorm-server/frame-template.html in the superpowers plugin directorylib/brainstorm-server/helper.js in the superpowers plugin directory