brainstorm-companion 1.2.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,6 +4,8 @@ Visual brainstorming tool for AI coding sessions. Opens a browser window where a
4
4
 
5
5
  Zero dependencies. Node.js >= 18 only.
6
6
 
7
+ **Sessions are persistent** — they stay alive until you explicitly stop them with `stop` or `brainstorm_stop_session`. Use `--timeout <minutes>` if you want auto-cleanup.
8
+
7
9
  ## Install
8
10
 
9
11
  ```bash
@@ -16,33 +18,83 @@ Or run directly:
16
18
  npx brainstorm-companion start
17
19
  ```
18
20
 
19
- ## Quick Start
21
+ ### Claude Code MCP Setup
22
+
23
+ Add to `~/.claude/settings.json`:
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "brainstorm": {
29
+ "command": "npx",
30
+ "args": ["brainstorm-companion", "--mcp"]
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ Once configured, the agent has access to 5 tools: `brainstorm_start_session`, `brainstorm_push_screen`, `brainstorm_read_events`, `brainstorm_clear_screen`, and `brainstorm_stop_session`. Full documentation is embedded in the tool descriptions — the agent becomes an expert immediately upon connecting.
37
+
38
+ ---
39
+
40
+ ## Complete Usage Guide
41
+
42
+ ### Quick Start (CLI) — 3 commands, zero config
43
+
44
+ ```bash
45
+ brainstorm-companion start # opens browser
46
+ brainstorm-companion push --html '<h2>Hello World</h2>' # shows content
47
+ brainstorm-companion stop # cleans up
48
+ ```
20
49
 
21
- ### CLI
50
+ That's it. No arguments required. Now a fuller example:
22
51
 
23
52
  ```bash
24
- # 1. Start server (opens browser automatically)
25
- brainstorm-companion start --project-dir .
53
+ # Start (opens browser, prints URL)
54
+ brainstorm-companion start
26
55
  # → Server started: http://127.0.0.1:54321
27
- # → Session ID: 1234-1700000000000
28
56
 
29
- # 2. Push content — browser updates instantly
30
- brainstorm-companion push --html '<h2>Dashboard Layout</h2><div class="options"><div class="option" data-choice="grid" onclick="toggleSelect(this)"><div class="letter">A</div><div class="content"><h3>Grid Layout</h3><p>Cards in a responsive grid</p></div></div><div class="option" data-choice="list" onclick="toggleSelect(this)"><div class="letter">B</div><div class="content"><h3>List Layout</h3><p>Vertical scrolling list</p></div></div></div>'
57
+ # Push content — browser updates instantly
58
+ brainstorm-companion push --html '<h2>Dashboard</h2><p>First draft</p>'
31
59
 
32
- # 3. Update content — same browser, no restart needed
33
- brainstorm-companion push --html '<h2>Updated Layout</h2><p>Refined version based on feedback</p>'
60
+ # Update — same browser, auto-reloads
61
+ brainstorm-companion push --html '<h2>Dashboard v2</h2><p>Refined</p>'
34
62
 
35
- # 4. Read user's selection
63
+ # Read what user clicked
36
64
  brainstorm-companion events
37
- # → [{"type":"click","choice":"grid","text":"A Grid Layout Cards in a responsive grid","timestamp":1700000001234}]
38
65
 
39
- # 5. Stop when done
66
+ # Done
40
67
  brainstorm-companion stop
41
68
  ```
42
69
 
43
- **Key behavior:** Calling `start` when a session is already running reuses it — no duplicate browsers. Just keep calling `push` to update the same window. The browser auto-reloads on every push.
70
+ **Key behaviors:**
71
+ - `start` with no args works immediately (stores in `/tmp/brainstorm-companion/`)
72
+ - `start` reuses an existing session — never opens duplicate browsers
73
+ - `push` auto-reloads the browser every time — no restart or refresh needed
74
+ - Add `--project-dir .` for project-local storage
44
75
 
45
- ### Side-by-Side Comparison
76
+ ### Quick Start (MCP / Agent) — 3 calls, zero config
77
+
78
+ ```
79
+ 1. brainstorm_start_session()
80
+ → { url: "http://127.0.0.1:54321", session_dir: "..." }
81
+
82
+ 2. brainstorm_push_screen({ html: "<h2>Option A</h2>...", slot: "a", label: "Minimal" })
83
+ brainstorm_push_screen({ html: "<h2>Option B</h2>...", slot: "b", label: "Sidebar" })
84
+
85
+ 3. brainstorm_read_events({})
86
+ → { events: [{ type: "preference", choice: "a" }], count: 1 }
87
+
88
+ 4. brainstorm_push_screen({ html: "<h2>Revised A</h2>...", slot: "a", label: "Minimal v2" })
89
+
90
+ 5. brainstorm_stop_session({})
91
+ ```
92
+
93
+ **No arguments required.** `brainstorm_start_session()` works with zero config. Pass `project_dir` for project-local storage or when multiple agents run simultaneously. Sessions persist until `brainstorm_stop_session()` — use `idle_timeout_minutes` for auto-cleanup.
94
+
95
+ ---
96
+
97
+ ## Side-by-Side Comparison
46
98
 
47
99
  Push to named slots for comparison mode with tabs and preference selection:
48
100
 
@@ -54,7 +106,7 @@ brainstorm-companion push --html '<h2>Hybrid</h2><p>Collapsible sidebar + top ba
54
106
 
55
107
  Browser shows all three side-by-side with tabs, keyboard shortcuts (1/2/3), and a preference bar.
56
108
 
57
- ### Updating Content In-Place
109
+ ## Updating Content In-Place
58
110
 
59
111
  The browser auto-reloads whenever content is pushed. No need to restart the session or manually refresh:
60
112
 
@@ -72,7 +124,7 @@ brainstorm-companion push --html '<h2>Updated Option A</h2>' --slot a --label "R
72
124
  # → Only slot A updates, others stay
73
125
  ```
74
126
 
75
- ### From Files or Stdin
127
+ ## From Files or Stdin
76
128
 
77
129
  ```bash
78
130
  brainstorm-companion push mockup.html
@@ -80,7 +132,7 @@ brainstorm-companion push mockup.html --slot a --label "v1"
80
132
  cat design.html | brainstorm-companion push -
81
133
  ```
82
134
 
83
- ### Parallel Instances
135
+ ## Parallel Instances
84
136
 
85
137
  Multiple agents can run simultaneously on the same project. Use `--new` to force a separate session:
86
138
 
@@ -102,26 +154,80 @@ brainstorm-companion stop --session 1111-000
102
154
 
103
155
  Without `--new`, `start` reuses the existing session (the default for single-agent use).
104
156
 
105
- ## MCP Server
157
+ ---
106
158
 
107
- Brainstorm Companion runs as an [MCP](https://modelcontextprotocol.io) server for direct integration with AI coding tools.
159
+ ## HTML Content Guide
108
160
 
109
- ### Claude Code
161
+ ### Built-in CSS Classes
110
162
 
111
- Add to `~/.claude/settings.json`:
163
+ The frame template provides themed styles (auto light/dark mode). Push HTML **fragments**, not full documents — the frame wraps your content with theming, a header, and a selection indicator bar.
112
164
 
113
- ```json
114
- {
115
- "mcpServers": {
116
- "brainstorm": {
117
- "command": "npx",
118
- "args": ["brainstorm-companion", "--mcp"]
119
- }
120
- }
121
- }
165
+ | Class | Purpose |
166
+ |-------|---------|
167
+ | `.options` + `.option` | Selectable vertical option cards with letter badges |
168
+ | `.option .letter` | A/B/C badge inside an option |
169
+ | `.option .content` | Text content inside an option |
170
+ | `.cards` + `.card` | Grid cards with `.card-image` and `.card-body` |
171
+ | `.mockup` | Browser-window container with `.mockup-header` and `.mockup-body` |
172
+ | `.split` | Side-by-side two-column layout |
173
+ | `.pros-cons` | Pros/cons comparison with `.pros` (green) and `.cons` (red) |
174
+ | `.placeholder` | Dashed placeholder area |
175
+ | `.subtitle` | Muted text below headings |
176
+ | `.section` | Block with top margin spacing |
177
+ | `.label` | Small uppercase badge |
178
+ | `.mock-nav`, `.mock-sidebar`, `.mock-content` | UI mockup building blocks |
179
+ | `.mock-button`, `.mock-input` | Styled form elements |
180
+
181
+ ### Making Elements Interactive
182
+
183
+ Add `data-choice` and `onclick="toggleSelect(this)"` to capture user selections:
184
+
185
+ ```html
186
+ <div class="option" data-choice="grid" onclick="toggleSelect(this)">
187
+ <div class="letter">A</div>
188
+ <div class="content"><h3>Grid Layout</h3></div>
189
+ </div>
190
+ ```
191
+
192
+ For multi-select, add `data-multiselect` to the container:
193
+
194
+ ```html
195
+ <div class="options" data-multiselect>...</div>
196
+ ```
197
+
198
+ ### Auto-detected Libraries
199
+
200
+ Content is automatically enhanced when these patterns are detected (CDN injected automatically):
201
+
202
+ | Pattern | Library | What it does |
203
+ |---------|---------|-------------|
204
+ | `class="mermaid"` | Mermaid | Renders diagrams (flowchart, sequence, class, state, ER, Gantt, pie) |
205
+ | `class="language-*"` | Prism.js | Syntax highlighting |
206
+ | `$$...$$` or `class="math"` | KaTeX | Math rendering |
207
+
208
+ ```html
209
+ <div class="mermaid">
210
+ graph TD
211
+ A[Start] --> B{Decision}
212
+ B -->|Yes| C[Action]
213
+ B -->|No| D[Other]
214
+ </div>
122
215
  ```
123
216
 
124
- ### MCP Tools
217
+ ---
218
+
219
+ ## Event Types
220
+
221
+ | Event | When | Key Fields |
222
+ |-------|------|-----------|
223
+ | `click` | User clicks a `[data-choice]` element | `choice`, `text`, `id`, `timestamp` |
224
+ | `preference` | User picks a preferred slot in comparison mode | `choice` (slot id), `timestamp` |
225
+ | `tab-switch` | User switches tabs in comparison mode | `slot`, `timestamp` |
226
+ | `view-change` | User toggles side-by-side vs single view | `mode`, `timestamp` |
227
+
228
+ ---
229
+
230
+ ## MCP Tools Reference
125
231
 
126
232
  | Tool | Description |
127
233
  |------|-------------|
@@ -131,25 +237,73 @@ Add to `~/.claude/settings.json`:
131
237
  | `brainstorm_clear_screen` | Clear a specific slot or all content. |
132
238
  | `brainstorm_stop_session` | Stop server and clean up session files. |
133
239
 
134
- ### MCP Workflow Example
240
+ ---
241
+
242
+ ## Workflow Patterns
243
+
244
+ ### Single Decision
135
245
 
136
246
  ```
137
- 1. brainstorm_start_session({ project_dir: "/path/to/project" })
138
- { url: "http://127.0.0.1:54321", session_dir: "..." }
247
+ 1. brainstorm_start_session({ project_dir: "..." })
248
+ 2. brainstorm_push_screen({ html: "...options with data-choice..." })
249
+ 3. → Tell user to make their selection in the browser
250
+ 4. brainstorm_read_events({})
251
+ 5. → Use the choice to proceed
252
+ 6. brainstorm_stop_session({})
253
+ ```
139
254
 
140
- 2. brainstorm_push_screen({ html: "<h2>Option A</h2>...", slot: "a", label: "Minimal" })
141
- brainstorm_push_screen({ html: "<h2>Option B</h2>...", slot: "b", label: "Sidebar" })
255
+ ### A/B/C Comparison
142
256
 
143
- 3. brainstorm_read_events({})
144
- { events: [{ type: "preference", choice: "a" }], count: 1 }
257
+ ```
258
+ 1. brainstorm_start_session({ project_dir: "..." })
259
+ 2. brainstorm_push_screen({ html: "...", slot: "a", label: "Option A" })
260
+ 3. brainstorm_push_screen({ html: "...", slot: "b", label: "Option B" })
261
+ 4. → Tell user to compare and pick a preference
262
+ 5. brainstorm_read_events({})
263
+ 6. → Look for { type: "preference", choice: "a"|"b" }
264
+ 7. brainstorm_stop_session({})
265
+ ```
145
266
 
146
- // Update content — same browser, no restart
147
- 4. brainstorm_push_screen({ html: "<h2>Revised A</h2>...", slot: "a", label: "Minimal v2" })
267
+ ### Multi-Round Brainstorming
148
268
 
149
- 5. brainstorm_stop_session({})
269
+ ```
270
+ 1. brainstorm_start_session({ project_dir: "..." })
271
+
272
+ // Round 1: Layout
273
+ 2. brainstorm_push_screen({ html: "...", slot: "a", label: "Grid" })
274
+ 3. brainstorm_push_screen({ html: "...", slot: "b", label: "List" })
275
+ 4. brainstorm_read_events({ clear_after_read: true })
276
+ 5. → User chose "Grid"
277
+
278
+ // Round 2: Color scheme (clear old slots first)
279
+ 6. brainstorm_clear_screen({})
280
+ 7. brainstorm_push_screen({ html: "...", slot: "a", label: "Light" })
281
+ 8. brainstorm_push_screen({ html: "...", slot: "b", label: "Dark" })
282
+ 9. brainstorm_read_events({ clear_after_read: true })
283
+ 10. → User chose "Dark"
284
+
285
+ // Show final summary
286
+ 11. brainstorm_push_screen({ html: "<h2>Decisions: Grid + Dark</h2>..." })
287
+ 12. brainstorm_stop_session({})
288
+ ```
289
+
290
+ ### Progressive Refinement
291
+
292
+ ```
293
+ 1. brainstorm_start_session({ project_dir: "..." })
294
+
295
+ // Show initial mockup
296
+ 2. brainstorm_push_screen({ html: "...v1 mockup..." })
297
+ 3. → Get feedback from user (text in chat, not events)
298
+
299
+ // Push refined version — browser auto-reloads
300
+ 4. brainstorm_push_screen({ html: "...v2 mockup with changes..." })
301
+ 5. → Iterate until user is satisfied
302
+
303
+ 6. brainstorm_stop_session({})
150
304
  ```
151
305
 
152
- **Important:** Call `brainstorm_start_session` once. It returns the existing session if already running. Update content by calling `brainstorm_push_screen` repeatedly — the browser auto-reloads each time.
306
+ ---
153
307
 
154
308
  ## CLI Reference
155
309
 
@@ -174,10 +328,10 @@ Global Options:
174
328
  ### `start`
175
329
 
176
330
  ```
177
- brainstorm-companion start [--project-dir <path>] [--port <N>] [--host <H>] [--foreground] [--no-open] [--new]
331
+ brainstorm-companion start [--project-dir <path>] [--port <N>] [--host <H>] [--timeout <min>] [--foreground] [--no-open] [--new]
178
332
  ```
179
333
 
180
- If a session is already running, prints its URL and reuses it. Use `--new` to force a separate parallel session.
334
+ If a session is already running, prints its URL and reuses it. Use `--new` to force a separate parallel session. Use `--timeout 30` for auto-cleanup after 30 minutes idle (default: no timeout).
181
335
 
182
336
  ### `push`
183
337
 
@@ -215,58 +369,7 @@ brainstorm-companion status
215
369
 
216
370
  Shows Session ID, URL, uptime, event count, and active slots.
217
371
 
218
- ## HTML Content Guide
219
-
220
- ### Built-in CSS Classes
221
-
222
- The frame template provides themed styles (auto light/dark mode):
223
-
224
- | Class | Purpose |
225
- |-------|---------|
226
- | `.options` + `.option` | Selectable vertical option cards with letter badges |
227
- | `.cards` + `.card` | Grid cards with `.card-image` and `.card-body` |
228
- | `.mockup` | Container with `.mockup-header` and `.mockup-body` |
229
- | `.split` | Side-by-side two-column layout |
230
- | `.pros-cons` | Pros/cons comparison with `.pros` and `.cons` |
231
- | `.placeholder` | Dashed placeholder area |
232
- | `.mock-nav`, `.mock-sidebar`, `.mock-content` | UI mockup building blocks |
233
- | `.mock-button`, `.mock-input` | Styled form elements |
234
-
235
- ### Making Elements Interactive
236
-
237
- Add `data-choice` and `onclick="toggleSelect(this)"` to capture user selections:
238
-
239
- ```html
240
- <div class="option" data-choice="grid" onclick="toggleSelect(this)">
241
- <div class="letter">A</div>
242
- <div class="content"><h3>Grid Layout</h3></div>
243
- </div>
244
- ```
245
-
246
- For multi-select, add `data-multiselect` to the container:
247
-
248
- ```html
249
- <div class="options" data-multiselect>...</div>
250
- ```
251
-
252
- ### Auto-detected Libraries
253
-
254
- Content is automatically enhanced when these patterns are detected:
255
-
256
- | Pattern | Library | What it does |
257
- |---------|---------|-------------|
258
- | `class="mermaid"` | Mermaid | Renders diagrams from text |
259
- | `class="language-*"` | Prism.js | Syntax highlighting |
260
- | `$$...$$` or `class="math"` | KaTeX | Math rendering |
261
-
262
- ```html
263
- <div class="mermaid">
264
- graph TD
265
- A[Start] --> B{Decision}
266
- B -->|Yes| C[Action]
267
- B -->|No| D[Other]
268
- </div>
269
- ```
372
+ ---
270
373
 
271
374
  ## How It Works
272
375
 
@@ -276,7 +379,30 @@ graph TD
276
379
  4. Click events are sent over WebSocket to the server and appended to a `.events` JSONL file
277
380
  5. `events` reads the JSONL file and returns structured JSON
278
381
  6. Each session is fully isolated: own port, own directory, own event log
279
- 7. Server runs independently with a 30-minute idle timeout; `stop` cleans up immediately
382
+ 7. Sessions are persistent they stay alive until explicitly stopped with `stop` or `brainstorm_stop_session`
383
+
384
+ ## Best Practices
385
+
386
+ 1. **Always pass `project_dir`** to `brainstorm_start_session` — avoids cross-agent conflicts
387
+ 2. **Never restart to update content** — just call `brainstorm_push_screen` again; the browser auto-reloads
388
+ 3. **One `brainstorm_start_session` per workflow** — it reuses the existing session automatically
389
+ 4. **Push fragments, not full documents** — the frame template handles `<html>`, theming, and scroll
390
+ 5. **Start with a heading** — `<h2>` describes what the user is looking at
391
+ 6. **Add a `.subtitle`** — describes the decision being made
392
+ 7. **One decision per screen** — don't combine unrelated choices
393
+ 8. **Use slot labels** — `label` makes comparison tabs readable
394
+ 9. **Use `data-choice` for interaction** — the built-in `toggleSelect` emits events automatically
395
+ 10. **Tell the user to interact** — after pushing content, let them know the browser is ready
396
+ 11. **Read events after user has time** — don't immediately read; wait for user to respond
397
+ 12. **Clean up with `brainstorm_stop_session`** — frees the port and removes temp files
398
+
399
+ ## Common Mistakes
400
+
401
+ - **Starting a new session for each update** — DON'T. Call `push_screen` to update the existing browser.
402
+ - **Omitting `project_dir`** — leads to `/tmp` collisions between agents.
403
+ - **Pushing full HTML documents** — push fragments; the frame template adds theming and structure.
404
+ - **Reading events immediately after push** — give the user time to interact first.
405
+ - **Forgetting to stop** — always call `brainstorm_stop_session` when done.
280
406
 
281
407
  ## Author
282
408
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainstorm-companion",
3
- "version": "1.2.1",
3
+ "version": "2.0.1",
4
4
  "description": "AI-assisted visual brainstorming companion",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
package/skill/SKILL.md CHANGED
@@ -1,41 +1,61 @@
1
1
  ---
2
2
  name: brainstorm-companion
3
- description: Visual brainstorming companion — opens a browser window for comparing design mockups, architecture options, and UI prototypes. Agents push HTML content and users interact visually.
3
+ description: Visual brainstorming companion — opens a browser window for comparing design mockups, architecture options, and UI prototypes. Agents push HTML content and users interact visually. Sessions are persistent and never time out.
4
4
  ---
5
5
 
6
- # Brainstorm Companion
6
+ # Brainstorm Companion — Complete Agent Reference
7
+
8
+ ## Quickstart (3 calls, no setup)
9
+
10
+ ```
11
+ brainstorm_start_session()
12
+ brainstorm_push_screen({ html: "<h2>Hello World</h2><p>Your content here</p>" })
13
+ brainstorm_stop_session()
14
+ ```
15
+
16
+ That's it. No arguments required. A browser opens, your HTML appears, and cleanup happens automatically.
7
17
 
8
18
  ## When to Use
9
19
 
10
- Use this tool when you need to:
11
- - Show visual mockups, UI designs, or layout options to the user
12
- - Compare multiple design alternatives side-by-side (A/B/C comparison)
20
+ - Show visual mockups, UI designs, or layout options
21
+ - Compare design alternatives side-by-side (A/B/C)
13
22
  - Present architecture diagrams (Mermaid), code samples (Prism), or math (KaTeX)
14
- - Get visual feedback — user clicks and preferences are captured as events
15
- - Show interactive prototypes or wireframes
23
+ - Get visual feedback — user clicks and preferences captured as events
24
+
25
+ **Don't use** for plain text, simple data, or anything fine in the terminal.
16
26
 
17
- **Don't use** for plain text output, simple data, or anything that works fine in the terminal.
27
+ ## Session Lifecycle
28
+
29
+ - **No setup needed** — `brainstorm_start_session()` works with zero arguments
30
+ - **Sessions are persistent** — they stay alive until you call `brainstorm_stop_session`
31
+ - **Safe to call start multiple times** — reuses existing session, never duplicates
32
+ - **Optional timeout** — pass `idle_timeout_minutes` for auto-cleanup
33
+ - **Always stop when done** — `brainstorm_stop_session()` frees port and cleans up
34
+
35
+ ---
18
36
 
19
37
  ## MCP Tools Reference
20
38
 
21
39
  ### brainstorm_start_session
22
40
 
23
- Start the server and open a browser window. If a session is already running, it reuses it no duplicate browsers.
41
+ Start the server and open a browser. Works with no arguments. Reuses existing session if one is running.
24
42
 
25
43
  ```
44
+ // Simplest — no args needed:
45
+ brainstorm_start_session()
46
+ → { url: "http://127.0.0.1:54321", session_dir: "..." }
47
+
48
+ // With options:
26
49
  brainstorm_start_session({
27
- project_dir: "/path/to/project", // ALWAYS pass this — use the current working directory
50
+ project_dir: "/path/to/project", // optional — use cwd for project-local storage
28
51
  open_browser: true, // default: true
29
- port: 0 // default: random
52
+ idle_timeout_minutes: 0 // default: 0 = no timeout. Set 30 for auto-cleanup.
30
53
  })
31
- → { url: "http://127.0.0.1:54321", session_dir: "..." }
32
54
  ```
33
55
 
34
- **Always pass `project_dir`** this keeps session files with the project and avoids conflicts between agents. Without it, all sessions go to `/tmp/brainstorm-companion/` and may collide.
56
+ **`project_dir` is optional.** Without it, sessions go to `/tmp/brainstorm-companion/`. Pass the current working directory for project-local storage or when multiple agents may run simultaneously.
35
57
 
36
- **Calling `brainstorm_start_session` multiple times is safe** — it returns the existing session URL if one is already running. You do NOT need to stop and restart to update content. Just call `brainstorm_push_screen` to update the same browser window.
37
-
38
- The server runs independently in the background with a 30-minute idle timeout.
58
+ **Calling it multiple times is safe** — returns the existing session. Just call `brainstorm_push_screen` to update content.
39
59
 
40
60
  ### brainstorm_push_screen
41
61
 
@@ -94,6 +114,8 @@ brainstorm_stop_session({})
94
114
 
95
115
  Always call this when done brainstorming to free the port and clean up files.
96
116
 
117
+ ---
118
+
97
119
  ## HTML Content — What to Push
98
120
 
99
121
  You push HTML **fragments**, not full documents. The frame template wraps your content with theming (auto light/dark mode), a header, and a selection indicator bar.
@@ -271,6 +293,8 @@ Use `$$...$$` for display math. KaTeX CDN is injected automatically.
271
293
  <p>$$L = -\sum_{i} y_i \log(\hat{y}_i)$$</p>
272
294
  ```
273
295
 
296
+ ---
297
+
274
298
  ## CSS Classes Quick Reference
275
299
 
276
300
  | Class | Purpose |
@@ -300,6 +324,8 @@ Use `$$...$$` for display math. KaTeX CDN is injected automatically.
300
324
  | `.mock-button` | Styled button element |
301
325
  | `.mock-input` | Styled input field |
302
326
 
327
+ ---
328
+
303
329
  ## Event Types
304
330
 
305
331
  | Event | When | Key Fields |
@@ -311,6 +337,8 @@ Use `$$...$$` for display math. KaTeX CDN is injected automatically.
311
337
 
312
338
  All events include a `timestamp` field (Unix ms).
313
339
 
340
+ ---
341
+
314
342
  ## Workflow Patterns
315
343
 
316
344
  ### Single Decision
@@ -375,6 +403,8 @@ All events include a `timestamp` field (Unix ms).
375
403
  6. brainstorm_stop_session({})
376
404
  ```
377
405
 
406
+ ---
407
+
378
408
  ## Best Practices
379
409
 
380
410
  1. **Always pass `project_dir`** to `brainstorm_start_session` — avoids cross-agent conflicts
package/src/cli.js CHANGED
@@ -14,30 +14,44 @@ const { SessionManager } = require('./session');
14
14
  const HELP = {
15
15
  main: `Usage: brainstorm-companion <command> [options]
16
16
 
17
- Opens a browser window for visual brainstorming alongside AI coding sessions.
18
- Agents push HTML content and users interact visually.
17
+ Visual brainstorming tool. Opens a browser, you push HTML, users interact.
18
+
19
+ Quickstart (3 commands):
20
+ brainstorm-companion start
21
+ brainstorm-companion push --html '<h2>Hello World</h2>'
22
+ brainstorm-companion stop
23
+
24
+ How it works:
25
+ 1. "start" opens a browser (reuses existing session if one is running)
26
+ 2. "push" sends HTML to the browser — auto-reloads instantly, every time
27
+ 3. "events" reads what the user clicked (choices, preferences)
28
+ 4. "stop" ends the session
19
29
 
20
30
  Commands:
21
- start Start the brainstorm server and open browser
22
- push Push HTML content to the browser
23
- events Read user interaction events
31
+ start Start server and open browser (or reuse existing session)
32
+ push Push HTML content browser auto-reloads each time
33
+ events Read user interaction events (clicks, preferences)
24
34
  clear Clear content or events
25
- stop Stop the server
26
- status Show server status
35
+ stop Stop the server and clean up
36
+ status Show session info (URL, uptime, slots, events)
27
37
 
28
38
  Global Options:
29
- --project-dir <path> Session storage location (default: /tmp/brainstorm-companion/)
30
- --session <id> Target a specific session (required for parallel instances)
39
+ --project-dir <path> Session storage (default: /tmp/brainstorm-companion/)
40
+ --session <id> Target a specific session (for parallel use)
31
41
  --mcp Run as MCP server (stdio JSON-RPC)
32
- --help, -h Show help (use "<command> --help" for command details)
42
+ --help, -h Show help (use "<command> --help" for details)
33
43
 
34
- Examples:
35
- brainstorm-companion start
36
- brainstorm-companion push --html '<h2>Hello</h2>'
37
- brainstorm-companion push mockup.html --slot a --label "Option A"
38
- echo '<h2>World</h2>' | brainstorm-companion push -
39
- brainstorm-companion events --format json
40
- brainstorm-companion stop`,
44
+ Comparison mode (side-by-side with tabs):
45
+ brainstorm-companion push --html '<h2>A</h2>' --slot a --label "Grid"
46
+ brainstorm-companion push --html '<h2>B</h2>' --slot b --label "List"
47
+
48
+ Key concepts:
49
+ - No setup needed — "start" works with zero arguments
50
+ - Push HTML fragments (not full documents) — theming is automatic
51
+ - Use --slot a/b/c + --label for side-by-side comparison
52
+ - Add data-choice="val" onclick="toggleSelect(this)" for clickable elements
53
+ - class="mermaid", class="language-*", $$math$$ auto-detected
54
+ - Sessions persist until stopped — use --timeout <min> for auto-cleanup`,
41
55
 
42
56
  start: `Usage: brainstorm-companion start [options]
43
57
 
@@ -46,10 +60,13 @@ Start the brainstorm server and open a browser window.
46
60
  If a session is already running for this project, it reuses it (prints the
47
61
  existing URL). Use --new to force a separate session.
48
62
 
63
+ Sessions persist until explicitly stopped — no timeout by default.
64
+
49
65
  Options:
50
66
  --project-dir <path> Session storage location (default: /tmp/brainstorm-companion/)
51
67
  --port <number> Bind to specific port (default: random ephemeral)
52
68
  --host <address> Bind address (default: 127.0.0.1)
69
+ --timeout <minutes> Auto-stop after N minutes of inactivity (default: none)
53
70
  --foreground Run server in foreground (don't background)
54
71
  --no-open Don't auto-open browser
55
72
  --new Force a new session even if one is already running
@@ -60,8 +77,9 @@ Output:
60
77
 
61
78
  Examples:
62
79
  brainstorm-companion start
63
- brainstorm-companion start --project-dir ./my-project --no-open
64
- brainstorm-companion start --new # force separate parallel session`,
80
+ brainstorm-companion start --project-dir .
81
+ brainstorm-companion start --timeout 30 # auto-stop after 30min idle
82
+ brainstorm-companion start --new --no-open # parallel session, no browser`,
65
83
 
66
84
  push: `Usage: brainstorm-companion push [<file|->] [options]
67
85
 
@@ -229,6 +247,7 @@ async function start(argv) {
229
247
  'project-dir': { type: 'string' },
230
248
  'port': { type: 'string', default: '0' },
231
249
  'host': { type: 'string', default: '127.0.0.1' },
250
+ 'timeout': { type: 'string' },
232
251
  'foreground': { type: 'boolean', default: false },
233
252
  'no-open': { type: 'boolean', default: false },
234
253
  'new': { type: 'boolean', default: false },
@@ -239,6 +258,8 @@ async function start(argv) {
239
258
  const projectDir = values['project-dir'] || null;
240
259
  const host = values['host'];
241
260
  const port = parseInt(values['port'], 10) || 0;
261
+ const timeoutMin = values['timeout'] ? parseInt(values['timeout'], 10) : 0;
262
+ const idleTimeoutMs = timeoutMin > 0 ? timeoutMin * 60 * 1000 : 0;
242
263
  const foreground = values['foreground'];
243
264
  const noOpen = values['no-open'];
244
265
  const forceNew = values['new'];
@@ -267,6 +288,7 @@ async function start(argv) {
267
288
  host,
268
289
  port,
269
290
  ownerPid: process.pid,
291
+ idleTimeoutMs,
270
292
  });
271
293
 
272
294
  instance.server.once('listening', () => {
@@ -302,9 +324,7 @@ async function start(argv) {
302
324
  BRAINSTORM_DIR: sessionDir,
303
325
  BRAINSTORM_HOST: host,
304
326
  BRAINSTORM_PORT: String(port),
305
- // No BRAINSTORM_OWNER_PID in background mode — the CLI process
306
- // exits immediately, so the server must live independently.
307
- // Server still has 30-minute idle timeout for cleanup.
327
+ BRAINSTORM_IDLE_TIMEOUT: String(idleTimeoutMs),
308
328
  },
309
329
  });
310
330
  child.unref();
package/src/mcp.js CHANGED
@@ -50,7 +50,7 @@ class McpServer {
50
50
  this.respond(id, {
51
51
  protocolVersion: '2024-11-05',
52
52
  capabilities: { tools: {} },
53
- serverInfo: { name: 'brainstorm-companion', version: '1.1.0' }
53
+ serverInfo: { name: 'brainstorm-companion', version: '2.0.1' }
54
54
  });
55
55
  break;
56
56
 
@@ -126,52 +126,107 @@ class McpServer {
126
126
  return [
127
127
  {
128
128
  name: 'brainstorm_start_session',
129
- description: 'Start a brainstorm companion server and open a browser window for visual brainstorming. Returns the URL.',
129
+ description: `Start a visual brainstorming session. Opens a browser window where you push HTML and users interact visually.
130
+
131
+ QUICKSTART — just these 3 calls:
132
+ brainstorm_start_session() → opens browser
133
+ brainstorm_push_screen({ html: "<h2>Hello</h2><p>Content</p>" }) → shows content
134
+ brainstorm_stop_session() → cleans up
135
+
136
+ FULL WORKFLOW:
137
+ 1. Call brainstorm_start_session ONCE (no args required — works immediately). Returns { url, session_dir }.
138
+ 2. Call brainstorm_push_screen with HTML — browser auto-reloads. Call as many times as needed.
139
+ 3. Call brainstorm_read_events to get user clicks/preferences.
140
+ 4. Call brainstorm_stop_session when done.
141
+
142
+ If a session is already running, this returns the existing URL (safe to call repeatedly).
143
+ Sessions persist until explicitly stopped — no timeout by default.
144
+
145
+ COMPARISON MODE: Push to slots a/b/c with labels for side-by-side view:
146
+ brainstorm_push_screen({ html: "...", slot: "a", label: "Option A" })
147
+ brainstorm_push_screen({ html: "...", slot: "b", label: "Option B" })
148
+
149
+ CSS CLASSES (themed light/dark, push fragments not full docs):
150
+ .options + .option — Selectable cards with .letter (A/B/C) and .content
151
+ .cards + .card — Grid cards with .card-image and .card-body
152
+ .mockup — Browser-window container (.mockup-header + .mockup-body)
153
+ .split — Two-column layout | .pros-cons — Tradeoff grid (.pros/.cons)
154
+ .mock-nav, .mock-sidebar, .mock-content, .mock-button, .mock-input
155
+
156
+ INTERACTIVE ELEMENTS:
157
+ Add data-choice="value" onclick="toggleSelect(this)" to capture clicks.
158
+ Example: <div class="option" data-choice="grid" onclick="toggleSelect(this)"><div class="letter">A</div><div class="content"><h3>Grid</h3></div></div>
159
+
160
+ AUTO-DETECTED (CDN injected): class="mermaid" (diagrams), class="language-*" (syntax), $$...$$ (math)
161
+
162
+ EVENTS: click (choice,text), preference (choice), tab-switch (slot), view-change (mode)
163
+
164
+ RULES:
165
+ - NEVER restart to update — just push_screen again
166
+ - Push HTML fragments, not full <html> documents
167
+ - Tell user the browser is ready after pushing
168
+ - Give user time before reading events
169
+ - Always stop_session when done`,
130
170
  inputSchema: {
131
171
  type: 'object',
132
172
  properties: {
133
- project_dir: { type: 'string', description: 'Project directory for session storage' },
134
- port: { type: 'number', description: 'Port to bind to (default: random)' },
135
- open_browser: { type: 'boolean', description: 'Whether to open the browser (default: true)' }
173
+ project_dir: { type: 'string', description: 'Project directory for session storage. Optional — defaults to /tmp/brainstorm-companion/. Pass cwd for project-local storage.' },
174
+ port: { type: 'number', description: 'Port to bind to (default: random ephemeral)' },
175
+ open_browser: { type: 'boolean', description: 'Open browser automatically (default: true)' },
176
+ idle_timeout_minutes: { type: 'number', description: 'Auto-stop after N minutes idle (default: 0 = no timeout)' }
136
177
  }
137
178
  }
138
179
  },
139
180
  {
140
181
  name: 'brainstorm_push_screen',
141
- description: 'Push HTML content to the brainstorm browser window. Supports comparison mode via slots.',
182
+ description: `Push HTML content to the brainstorm browser window. The browser auto-reloads instantly — call repeatedly to update content without restarting the session.
183
+
184
+ SINGLE SCREEN: Pass html only. Previous content is replaced.
185
+ COMPARISON MODE: Pass html + slot (a/b/c) + label. Browser shows tabs, side-by-side view, and preference buttons.
186
+
187
+ Push HTML fragments (not full <html> documents). The frame template adds theming, fonts, and scroll handling.
188
+
189
+ Built-in CSS classes: .options/.option (selectable cards), .cards/.card (grid), .mockup (browser frame), .split (two-column), .pros-cons (tradeoffs).
190
+ Interactive: Add data-choice="value" onclick="toggleSelect(this)" to capture clicks as events.
191
+ Auto-detected: class="mermaid" (diagrams), class="language-*" (syntax highlighting), $$...$$ (math).`,
142
192
  inputSchema: {
143
193
  type: 'object',
144
194
  properties: {
145
- html: { type: 'string', description: 'HTML content to display' },
146
- slot: { type: 'string', description: 'Slot for comparison mode: a, b, or c' },
147
- label: { type: 'string', description: 'Label for the slot' }
195
+ html: { type: 'string', description: 'HTML fragment to display (not a full document — the frame template wraps it)' },
196
+ slot: { type: 'string', description: 'Slot for comparison mode: a, b, or c. When used, browser shows tabbed comparison view.' },
197
+ label: { type: 'string', description: 'Display label for the slot tab (e.g., "Option A", "Minimal", "Dark Theme")' }
148
198
  },
149
199
  required: ['html']
150
200
  }
151
201
  },
152
202
  {
153
203
  name: 'brainstorm_read_events',
154
- description: 'Read user interaction events (clicks, preferences) from the brainstorm browser.',
204
+ description: `Read user interaction events from the brainstorm browser. Returns { events: [...], count: N }.
205
+
206
+ Event types: click (data-choice element clicked — fields: choice, text, id), preference (slot comparison pick — fields: choice), tab-switch (tab changed — fields: slot), view-change (view toggled — fields: mode). All events include timestamp.
207
+
208
+ Use clear_after_read: true between brainstorming rounds to avoid reading stale events from the previous round.
209
+ Give the user time to interact before reading — don't read immediately after pushing content.`,
155
210
  inputSchema: {
156
211
  type: 'object',
157
212
  properties: {
158
- clear_after_read: { type: 'boolean', description: 'Clear events after reading (default: false)' }
213
+ clear_after_read: { type: 'boolean', description: 'Clear events after reading to avoid stale data in next round (default: false)' }
159
214
  }
160
215
  }
161
216
  },
162
217
  {
163
218
  name: 'brainstorm_clear_screen',
164
- description: 'Clear content from the brainstorm browser window.',
219
+ description: 'Clear content from the brainstorm browser. Pass slot to clear a specific comparison slot, or omit to clear all content (all slots and screens). Useful between multi-round brainstorming to reset the view before pushing new content.',
165
220
  inputSchema: {
166
221
  type: 'object',
167
222
  properties: {
168
- slot: { type: 'string', description: 'Clear specific slot (a, b, or c). Omit to clear all.' }
223
+ slot: { type: 'string', description: 'Clear specific slot (a, b, or c). Omit to clear all content.' }
169
224
  }
170
225
  }
171
226
  },
172
227
  {
173
228
  name: 'brainstorm_stop_session',
174
- description: 'Stop the brainstorm companion server and clean up.',
229
+ description: 'Stop the brainstorm companion server and clean up all session files. Always call this when done brainstorming to free the port and remove temp files. Safe to call multiple times.',
175
230
  inputSchema: { type: 'object', properties: {} }
176
231
  }
177
232
  ];
@@ -187,7 +242,7 @@ class McpServer {
187
242
  return { url: this.serverInstance.url, session_dir: this.sessionDir };
188
243
  }
189
244
 
190
- const { project_dir, port = 0, open_browser = true } = args;
245
+ const { project_dir, port = 0, open_browser = true, idle_timeout_minutes = 0 } = args;
191
246
 
192
247
  // Determine base directory and create session dir
193
248
  const baseDir = project_dir
@@ -203,6 +258,7 @@ class McpServer {
203
258
  host: '127.0.0.1',
204
259
  port: port || 0,
205
260
  ownerPid: process.pid,
261
+ idleTimeoutMs: idle_timeout_minutes > 0 ? idle_timeout_minutes * 60 * 1000 : 0,
206
262
  logFn: (...a) => console.error(...a),
207
263
  });
208
264
 
package/src/server.js CHANGED
@@ -11,7 +11,10 @@ const { detectLibraries, buildInjections } = require('./content-detect');
11
11
  // Constants
12
12
  // ---------------------------------------------------------------------------
13
13
 
14
- const IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
14
+ // Idle timeout is DISABLED by default (0 = no timeout). Sessions stay alive
15
+ // until explicitly stopped via `stop` / `brainstorm_stop_session`, or the
16
+ // owner process exits. Pass a positive `idleTimeoutMs` to override.
17
+ const DEFAULT_IDLE_TIMEOUT_MS = 0;
15
18
  const OWNER_CHECK_INTERVAL_MS = 60 * 1000; // 60 seconds
16
19
 
17
20
  const MIME_TYPES = {
@@ -110,6 +113,7 @@ function startServer(config = {}) {
110
113
  host = '127.0.0.1',
111
114
  port: requestedPort = 0,
112
115
  ownerPid = null,
116
+ idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_MS,
113
117
  logFn = console.log,
114
118
  } = config;
115
119
 
@@ -141,9 +145,11 @@ function startServer(config = {}) {
141
145
 
142
146
  function resetIdleTimer() {
143
147
  if (idleTimer) clearTimeout(idleTimer);
148
+ // 0 or falsy = no idle timeout — session stays alive until explicitly stopped
149
+ if (!idleTimeoutMs) return;
144
150
  idleTimer = setTimeout(() => {
145
151
  shutdown('idle-timeout');
146
- }, IDLE_TIMEOUT_MS);
152
+ }, idleTimeoutMs);
147
153
  // Don't block the event loop
148
154
  if (idleTimer.unref) idleTimer.unref();
149
155
  }
@@ -614,6 +620,7 @@ if (require.main === module) {
614
620
  screenDir,
615
621
  host: process.env.BRAINSTORM_HOST || '127.0.0.1',
616
622
  port: process.env.BRAINSTORM_PORT ? parseInt(process.env.BRAINSTORM_PORT, 10) : 0,
623
+ idleTimeoutMs: process.env.BRAINSTORM_IDLE_TIMEOUT ? parseInt(process.env.BRAINSTORM_IDLE_TIMEOUT, 10) : 0,
617
624
  });
618
625
  instance.server.on('listening', () => {
619
626
  console.log(JSON.stringify({ type: 'server-ready', url: instance.url }));