brainstorm-companion 2.0.0 → 2.0.3

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,7 +4,7 @@ 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 never time out. Sessions stay alive until you explicitly stop them with `stop` or `brainstorm_stop_session`.
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
8
 
9
9
  ## Install
10
10
 
@@ -39,34 +39,43 @@ Once configured, the agent has access to 5 tools: `brainstorm_start_session`, `b
39
39
 
40
40
  ## Complete Usage Guide
41
41
 
42
- ### Quick Start (CLI)
42
+ ### Quick Start (CLI) — 3 commands, zero config
43
43
 
44
44
  ```bash
45
- # 1. Start server (opens browser automatically)
46
- brainstorm-companion start --project-dir .
45
+ brainstorm-companion start # opens browser
46
+ brainstorm-companion push --html '<h2>Hello World</h2>' # shows content
47
+ brainstorm-companion stop # cleans up
48
+ ```
49
+
50
+ That's it. No arguments required. Now a fuller example:
51
+
52
+ ```bash
53
+ # Start (opens browser, prints URL)
54
+ brainstorm-companion start
47
55
  # → Server started: http://127.0.0.1:54321
48
- # → Session ID: 1234-1700000000000
49
56
 
50
- # 2. Push content — browser updates instantly
51
- 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>'
52
59
 
53
- # 3. Update content — same browser, no restart needed
54
- 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>'
55
62
 
56
- # 4. Read user's selection
63
+ # Read what user clicked
57
64
  brainstorm-companion events
58
- # → [{"type":"click","choice":"grid","text":"A Grid Layout Cards in a responsive grid","timestamp":1700000001234}]
59
65
 
60
- # 5. Stop when done
66
+ # Done
61
67
  brainstorm-companion stop
62
68
  ```
63
69
 
64
- **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 — auto-isolates by working directory
72
+ - `start` reuses an existing session — never opens duplicate browsers
73
+ - `push` auto-reloads the browser every time — no restart or refresh needed
65
74
 
66
- ### Quick Start (MCP / Agent)
75
+ ### Quick Start (MCP / Agent) — 3 calls, zero config
67
76
 
68
77
  ```
69
- 1. brainstorm_start_session({ project_dir: "/path/to/project" })
78
+ 1. brainstorm_start_session()
70
79
  → { url: "http://127.0.0.1:54321", session_dir: "..." }
71
80
 
72
81
  2. brainstorm_push_screen({ html: "<h2>Option A</h2>...", slot: "a", label: "Minimal" })
@@ -80,7 +89,7 @@ brainstorm-companion stop
80
89
  5. brainstorm_stop_session({})
81
90
  ```
82
91
 
83
- **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. Sessions never time out.
92
+ **No arguments required.** Sessions auto-isolate by working directory different projects never collide. Sessions persist until `brainstorm_stop_session()` — use `idle_timeout_minutes` for auto-cleanup.
84
93
 
85
94
  ---
86
95
 
@@ -221,7 +230,7 @@ graph TD
221
230
 
222
231
  | Tool | Description |
223
232
  |------|-------------|
224
- | `brainstorm_start_session` | Start server (or reuse existing). Returns URL. Always pass `project_dir`. |
233
+ | `brainstorm_start_session` | Start server (or reuse existing). No args needed. Returns URL. |
225
234
  | `brainstorm_push_screen` | Push HTML content. Browser auto-reloads. Use `slot` + `label` for comparison. |
226
235
  | `brainstorm_read_events` | Read user interaction events. Option to clear after reading. |
227
236
  | `brainstorm_clear_screen` | Clear a specific slot or all content. |
@@ -234,7 +243,7 @@ graph TD
234
243
  ### Single Decision
235
244
 
236
245
  ```
237
- 1. brainstorm_start_session({ project_dir: "..." })
246
+ 1. brainstorm_start_session()
238
247
  2. brainstorm_push_screen({ html: "...options with data-choice..." })
239
248
  3. → Tell user to make their selection in the browser
240
249
  4. brainstorm_read_events({})
@@ -245,7 +254,7 @@ graph TD
245
254
  ### A/B/C Comparison
246
255
 
247
256
  ```
248
- 1. brainstorm_start_session({ project_dir: "..." })
257
+ 1. brainstorm_start_session()
249
258
  2. brainstorm_push_screen({ html: "...", slot: "a", label: "Option A" })
250
259
  3. brainstorm_push_screen({ html: "...", slot: "b", label: "Option B" })
251
260
  4. → Tell user to compare and pick a preference
@@ -257,7 +266,7 @@ graph TD
257
266
  ### Multi-Round Brainstorming
258
267
 
259
268
  ```
260
- 1. brainstorm_start_session({ project_dir: "..." })
269
+ 1. brainstorm_start_session()
261
270
 
262
271
  // Round 1: Layout
263
272
  2. brainstorm_push_screen({ html: "...", slot: "a", label: "Grid" })
@@ -280,7 +289,7 @@ graph TD
280
289
  ### Progressive Refinement
281
290
 
282
291
  ```
283
- 1. brainstorm_start_session({ project_dir: "..." })
292
+ 1. brainstorm_start_session()
284
293
 
285
294
  // Show initial mockup
286
295
  2. brainstorm_push_screen({ html: "...v1 mockup..." })
@@ -318,10 +327,10 @@ Global Options:
318
327
  ### `start`
319
328
 
320
329
  ```
321
- brainstorm-companion start [--project-dir <path>] [--port <N>] [--host <H>] [--foreground] [--no-open] [--new]
330
+ brainstorm-companion start [--project-dir <path>] [--port <N>] [--host <H>] [--timeout <min>] [--foreground] [--no-open] [--new]
322
331
  ```
323
332
 
324
- If a session is already running, prints its URL and reuses it. Use `--new` to force a separate parallel session.
333
+ 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).
325
334
 
326
335
  ### `push`
327
336
 
@@ -373,26 +382,25 @@ Shows Session ID, URL, uptime, event count, and active slots.
373
382
 
374
383
  ## Best Practices
375
384
 
376
- 1. **Always pass `project_dir`** to `brainstorm_start_session` avoids cross-agent conflicts
377
- 2. **Never restart to update content** — just call `brainstorm_push_screen` again; the browser auto-reloads
378
- 3. **One `brainstorm_start_session` per workflow** — it reuses the existing session automatically
379
- 4. **Push fragments, not full documents** — the frame template handles `<html>`, theming, and scroll
380
- 5. **Start with a heading** — `<h2>` describes what the user is looking at
381
- 6. **Add a `.subtitle`** — describes the decision being made
382
- 7. **One decision per screen** — don't combine unrelated choices
383
- 8. **Use slot labels** — `label` makes comparison tabs readable
384
- 9. **Use `data-choice` for interaction** — the built-in `toggleSelect` emits events automatically
385
- 10. **Tell the user to interact** — after pushing content, let them know the browser is ready
386
- 11. **Read events after user has time** — don't immediately read; wait for user to respond
387
- 12. **Clean up with `brainstorm_stop_session`**frees the port and removes temp files
385
+ 1. **Zero config** `brainstorm_start_session()` and `brainstorm-companion start` work with no arguments; sessions auto-isolate by working directory
386
+ 3. **Never restart to update content** — just call `push_screen` / `push` again; the browser auto-reloads
387
+ 4. **One start per workflow** — `start` reuses the existing session automatically
388
+ 5. **Push fragments, not full documents** — the frame template handles `<html>`, theming, and scroll
389
+ 6. **Start with a heading** — `<h2>` describes what the user is looking at
390
+ 7. **Add a `.subtitle`** — describes the decision being made
391
+ 8. **One decision per screen** — don't combine unrelated choices
392
+ 9. **Use slot labels** — `label` makes comparison tabs readable
393
+ 10. **Use `data-choice` for interaction** — the built-in `toggleSelect` emits events automatically
394
+ 11. **Tell the user to interact** — after pushing content, let them know the browser is ready
395
+ 12. **Read events after user has time** — don't immediately read; wait for user to respond
396
+ 13. **Use `--timeout <min>` for auto-cleanup** or call `stop` / `brainstorm_stop_session` when done
388
397
 
389
398
  ## Common Mistakes
390
399
 
391
400
  - **Starting a new session for each update** — DON'T. Call `push_screen` to update the existing browser.
392
- - **Omitting `project_dir`** — leads to `/tmp` collisions between agents.
393
401
  - **Pushing full HTML documents** — push fragments; the frame template adds theming and structure.
394
402
  - **Reading events immediately after push** — give the user time to interact first.
395
- - **Forgetting to stop** — always call `brainstorm_stop_session` when done.
403
+ - **Forgetting to stop** — always call `brainstorm_stop_session` / `stop` when done, or use `--timeout`.
396
404
 
397
405
  ## Author
398
406
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "brainstorm-companion",
3
- "version": "2.0.0",
3
+ "version": "2.0.3",
4
4
  "description": "AI-assisted visual brainstorming companion",
5
5
  "type": "commonjs",
6
6
  "license": "MIT",
package/skill/SKILL.md CHANGED
@@ -5,24 +5,32 @@ description: Visual brainstorming companion — opens a browser window for compa
5
5
 
6
6
  # Brainstorm Companion — Complete Agent Reference
7
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.
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
16
24
 
17
- **Don't use** for plain text output, simple data, or anything that works fine in the terminal.
25
+ **Don't use** for plain text, simple data, or anything fine in the terminal.
18
26
 
19
27
  ## Session Lifecycle
20
28
 
21
- Sessions are **persistent**they never time out. A session stays alive until explicitly stopped via `brainstorm_stop_session`. This means:
22
- - No 30-minute idle timeout
23
- - Sessions survive long user breaks
24
- - You only need to start once per workflow
25
- - Always clean up with `brainstorm_stop_session` when done
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
26
34
 
27
35
  ---
28
36
 
@@ -30,20 +38,24 @@ Sessions are **persistent** — they never time out. A session stays alive until
30
38
 
31
39
  ### brainstorm_start_session
32
40
 
33
- 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.
34
42
 
35
43
  ```
44
+ // Simplest — no args needed:
45
+ brainstorm_start_session()
46
+ → { url: "http://127.0.0.1:54321", session_dir: "..." }
47
+
48
+ // With options:
36
49
  brainstorm_start_session({
37
- 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
38
51
  open_browser: true, // default: true
39
- port: 0 // default: random
52
+ idle_timeout_minutes: 0 // default: 0 = no timeout. Set 30 for auto-cleanup.
40
53
  })
41
- → { url: "http://127.0.0.1:54321", session_dir: "..." }
42
54
  ```
43
55
 
44
- **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
+ **No arguments required.** Sessions are auto-isolated by working directory different projects never collide, even without `project_dir`. Pass `project_dir` only if you want session files stored inside the project folder.
45
57
 
46
- **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.
58
+ **Calling it multiple times is safe** — returns the existing session. Just call `brainstorm_push_screen` to update content.
47
59
 
48
60
  ### brainstorm_push_screen
49
61
 
@@ -332,7 +344,7 @@ All events include a `timestamp` field (Unix ms).
332
344
  ### Single Decision
333
345
 
334
346
  ```
335
- 1. brainstorm_start_session({ project_dir: "..." })
347
+ 1. brainstorm_start_session()
336
348
  2. brainstorm_push_screen({ html: "...options with data-choice..." })
337
349
  3. → Tell user to make their selection in the browser
338
350
  4. brainstorm_read_events({})
@@ -343,7 +355,7 @@ All events include a `timestamp` field (Unix ms).
343
355
  ### A/B/C Comparison
344
356
 
345
357
  ```
346
- 1. brainstorm_start_session({ project_dir: "..." })
358
+ 1. brainstorm_start_session()
347
359
  2. brainstorm_push_screen({ html: "...", slot: "a", label: "Option A" })
348
360
  3. brainstorm_push_screen({ html: "...", slot: "b", label: "Option B" })
349
361
  4. → Tell user to compare and pick a preference
@@ -355,7 +367,7 @@ All events include a `timestamp` field (Unix ms).
355
367
  ### Multi-Round Brainstorming
356
368
 
357
369
  ```
358
- 1. brainstorm_start_session({ project_dir: "..." })
370
+ 1. brainstorm_start_session()
359
371
 
360
372
  // Round 1: Layout
361
373
  2. brainstorm_push_screen({ html: "...", slot: "a", label: "Grid" })
@@ -378,7 +390,7 @@ All events include a `timestamp` field (Unix ms).
378
390
  ### Progressive Refinement
379
391
 
380
392
  ```
381
- 1. brainstorm_start_session({ project_dir: "..." })
393
+ 1. brainstorm_start_session()
382
394
 
383
395
  // Show initial mockup
384
396
  2. brainstorm_push_screen({ html: "...v1 mockup..." })
@@ -395,23 +407,22 @@ All events include a `timestamp` field (Unix ms).
395
407
 
396
408
  ## Best Practices
397
409
 
398
- 1. **Always pass `project_dir`** to `brainstorm_start_session` avoids cross-agent conflicts
399
- 2. **Never restart to update content** — just call `brainstorm_push_screen` again; the browser auto-reloads
400
- 3. **One `brainstorm_start_session` per workflow** — it reuses the existing session automatically
401
- 4. **Push fragments, not full documents** — the frame template handles `<html>`, theming, and scroll
402
- 5. **Start with a heading** — `<h2>` describes what the user is looking at
403
- 6. **Add a `.subtitle`** — describes the decision being made
404
- 7. **One decision per screen** — don't combine unrelated choices
405
- 8. **Use slot labels** — `label` makes comparison tabs readable
406
- 9. **Use `data-choice` for interaction** — the built-in `toggleSelect` emits events automatically
407
- 10. **Tell the user to interact** — after pushing content, let them know the browser is ready
408
- 11. **Read events after user has time** — don't immediately read; wait for user to respond
409
- 12. **Clean up with `brainstorm_stop_session`** — frees the port and removes temp files
410
+ 1. **Zero config** `brainstorm_start_session()` works with no arguments; isolation is automatic
411
+ 3. **Never restart to update content** — just call `brainstorm_push_screen` again; the browser auto-reloads
412
+ 4. **One `brainstorm_start_session` per workflow** — it reuses the existing session automatically
413
+ 5. **Push fragments, not full documents** — the frame template handles `<html>`, theming, and scroll
414
+ 6. **Start with a heading** — `<h2>` describes what the user is looking at
415
+ 7. **Add a `.subtitle`** — describes the decision being made
416
+ 8. **One decision per screen** — don't combine unrelated choices
417
+ 9. **Use slot labels** — `label` makes comparison tabs readable
418
+ 10. **Use `data-choice` for interaction** — the built-in `toggleSelect` emits events automatically
419
+ 11. **Tell the user to interact** — after pushing content, let them know the browser is ready
420
+ 12. **Read events after user has time** — don't immediately read; wait for user to respond
421
+ 13. **Clean up with `brainstorm_stop_session`** — or use `idle_timeout_minutes` for auto-cleanup
410
422
 
411
423
  ## Common Mistakes
412
424
 
413
425
  - **Starting a new session for each update** — DON'T. Call `push_screen` to update the existing browser.
414
- - **Omitting `project_dir`** — leads to `/tmp` collisions between agents.
415
426
  - **Pushing full HTML documents** — push fragments; the frame template adds theming and structure.
416
427
  - **Reading events immediately after push** — give the user time to interact first.
417
- - **Forgetting to stop** — always call `brainstorm_stop_session` when done.
428
+ - **Forgetting to stop** — always call `brainstorm_stop_session` when done, or use `idle_timeout_minutes`.
@@ -152,9 +152,9 @@ brainstorm_read_events()
152
152
  When running multi-round comparisons, clear events between rounds to avoid stale data:
153
153
 
154
154
  ```
155
- brainstorm_read_events() // read current events
156
- brainstorm_clear_screen({ target: "events" }) // clear event queue
157
- brainstorm_push_screen({ html: "Round 2..." }) // push next round
155
+ brainstorm_read_events({ clear_after_read: true }) // read and clear in one call
156
+ brainstorm_clear_screen({}) // clear content for next round
157
+ brainstorm_push_screen({ html: "Round 2..." }) // push next round
158
158
  ```
159
159
 
160
160
  ### Interpreting Events
@@ -250,10 +250,10 @@ stateDiagram-v2
250
250
 
251
251
  This example shows a full workflow for choosing a navigation pattern for a new app.
252
252
 
253
- ### Step 1: Present the question
253
+ ### Step 1: Start session and present the question
254
254
 
255
255
  ```
256
- brainstorm_start_session()
256
+ brainstorm_start_session() // no args needed — opens browser automatically
257
257
 
258
258
  brainstorm_push_screen({
259
259
  html: `
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,12 +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
 
49
- Sessions are persistent they never time out. Stop explicitly with "stop".
63
+ Sessions persist until explicitly stopped no timeout by default.
50
64
 
51
65
  Options:
52
66
  --project-dir <path> Session storage location (default: /tmp/brainstorm-companion/)
53
67
  --port <number> Bind to specific port (default: random ephemeral)
54
68
  --host <address> Bind address (default: 127.0.0.1)
69
+ --timeout <minutes> Auto-stop after N minutes of inactivity (default: none)
55
70
  --foreground Run server in foreground (don't background)
56
71
  --no-open Don't auto-open browser
57
72
  --new Force a new session even if one is already running
@@ -62,8 +77,9 @@ Output:
62
77
 
63
78
  Examples:
64
79
  brainstorm-companion start
65
- brainstorm-companion start --project-dir ./my-project --no-open
66
- 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`,
67
83
 
68
84
  push: `Usage: brainstorm-companion push [<file|->] [options]
69
85
 
@@ -169,6 +185,18 @@ function printHelp(command) {
169
185
  // Helpers
170
186
  // ---------------------------------------------------------------------------
171
187
 
188
+ function printNextSteps() {
189
+ console.log(`
190
+ Next steps:
191
+ brainstorm-companion push --html '<h2>Your content</h2>' Push content to browser
192
+ brainstorm-companion push file.html --slot a --label "A" Comparison mode
193
+ brainstorm-companion events Read user interactions
194
+ brainstorm-companion stop Stop when done
195
+
196
+ Full docs: https://www.npmjs.com/package/brainstorm-companion
197
+ Run: brainstorm-companion push --help for all CSS classes and options`);
198
+ }
199
+
172
200
  function sleep(ms) {
173
201
  return new Promise(resolve => setTimeout(resolve, ms));
174
202
  }
@@ -231,6 +259,7 @@ async function start(argv) {
231
259
  'project-dir': { type: 'string' },
232
260
  'port': { type: 'string', default: '0' },
233
261
  'host': { type: 'string', default: '127.0.0.1' },
262
+ 'timeout': { type: 'string' },
234
263
  'foreground': { type: 'boolean', default: false },
235
264
  'no-open': { type: 'boolean', default: false },
236
265
  'new': { type: 'boolean', default: false },
@@ -241,6 +270,8 @@ async function start(argv) {
241
270
  const projectDir = values['project-dir'] || null;
242
271
  const host = values['host'];
243
272
  const port = parseInt(values['port'], 10) || 0;
273
+ const timeoutMin = values['timeout'] ? parseInt(values['timeout'], 10) : 0;
274
+ const idleTimeoutMs = timeoutMin > 0 ? timeoutMin * 60 * 1000 : 0;
244
275
  const foreground = values['foreground'];
245
276
  const noOpen = values['no-open'];
246
277
  const forceNew = values['new'];
@@ -253,6 +284,7 @@ async function start(argv) {
253
284
  const url = existing.serverInfo.url;
254
285
  console.log(`Server already running: ${url}`);
255
286
  console.log(`Session ID: ${existing.sessionId}`);
287
+ printNextSteps();
256
288
  if (!noOpen) {
257
289
  openBrowser(url);
258
290
  }
@@ -269,11 +301,13 @@ async function start(argv) {
269
301
  host,
270
302
  port,
271
303
  ownerPid: process.pid,
304
+ idleTimeoutMs,
272
305
  });
273
306
 
274
307
  instance.server.once('listening', () => {
275
308
  console.log(`Server started: ${instance.url}`);
276
309
  console.log(`Session ID: ${path.basename(sessionDir)}`);
310
+ printNextSteps();
277
311
  if (!noOpen) {
278
312
  openBrowser(instance.url);
279
313
  }
@@ -304,9 +338,7 @@ async function start(argv) {
304
338
  BRAINSTORM_DIR: sessionDir,
305
339
  BRAINSTORM_HOST: host,
306
340
  BRAINSTORM_PORT: String(port),
307
- // No BRAINSTORM_OWNER_PID in background mode — the CLI process
308
- // exits immediately, so the server must live independently.
309
- // No idle timeout — session persists until explicitly stopped.
341
+ BRAINSTORM_IDLE_TIMEOUT: String(idleTimeoutMs),
310
342
  },
311
343
  });
312
344
  child.unref();
@@ -320,6 +352,7 @@ async function start(argv) {
320
352
 
321
353
  console.log(`Server started: ${serverInfo.url}`);
322
354
  console.log(`Session ID: ${path.basename(sessionDir)}`);
355
+ printNextSteps();
323
356
 
324
357
  if (!noOpen) {
325
358
  openBrowser(serverInfo.url);
package/src/mcp.js CHANGED
@@ -1,10 +1,15 @@
1
1
  'use strict';
2
2
 
3
+ const crypto = require('node:crypto');
3
4
  const fs = require('node:fs');
4
5
  const path = require('node:path');
5
6
  const { exec } = require('node:child_process');
6
7
  const { startServer } = require('./server');
7
8
 
9
+ function cwdHash() {
10
+ return crypto.createHash('md5').update(process.cwd()).digest('hex').slice(0, 8);
11
+ }
12
+
8
13
  class McpServer {
9
14
  constructor() {
10
15
  this.sessionDir = null; // absolute path once session is started
@@ -50,7 +55,7 @@ class McpServer {
50
55
  this.respond(id, {
51
56
  protocolVersion: '2024-11-05',
52
57
  capabilities: { tools: {} },
53
- serverInfo: { name: 'brainstorm-companion', version: '2.0.0' }
58
+ serverInfo: { name: 'brainstorm-companion', version: '2.0.1' }
54
59
  });
55
60
  break;
56
61
 
@@ -126,67 +131,54 @@ class McpServer {
126
131
  return [
127
132
  {
128
133
  name: 'brainstorm_start_session',
129
- description: `Start a visual brainstorming session opens a browser window where you push HTML content and the user interacts visually. Returns the session URL. Sessions have NO timeout and persist until explicitly stopped.
134
+ description: `Start a visual brainstorming session. Opens a browser window where you push HTML and users interact visually.
135
+
136
+ QUICKSTART — just these 3 calls:
137
+ brainstorm_start_session() → opens browser
138
+ brainstorm_push_screen({ html: "<h2>Hello</h2><p>Content</p>" }) → shows content
139
+ brainstorm_stop_session() → cleans up
130
140
 
131
- COMPLETE USAGE GUIDE:
132
- 1. Call brainstorm_start_session ONCE with project_dir set to the current working directory. It returns { url, session_dir }.
133
- 2. Call brainstorm_push_screen to send HTML content the browser auto-reloads instantly. Call it as many times as needed to update content without restarting.
134
- 3. Call brainstorm_read_events to get user clicks/preferences. Use clear_after_read:true between rounds.
135
- 4. Call brainstorm_stop_session when done to free the port and clean up.
141
+ FULL WORKFLOW:
142
+ 1. Call brainstorm_start_session ONCE (no args required works immediately). Returns { url, session_dir }.
143
+ 2. Call brainstorm_push_screen with HTML — browser auto-reloads. Call as many times as needed.
144
+ 3. Call brainstorm_read_events to get user clicks/preferences.
145
+ 4. Call brainstorm_stop_session when done.
136
146
 
137
- SINGLE SCREEN MODE: Push HTML fragments (not full documents). The frame template wraps content with themed CSS (auto light/dark mode).
147
+ If a session is already running, this returns the existing URL (safe to call repeatedly).
148
+ Sessions persist until explicitly stopped — no timeout by default.
138
149
 
139
- COMPARISON MODE: Push to slots a/b/c with labels for side-by-side comparison with tabs and preference buttons.
150
+ COMPARISON MODE: Push to slots a/b/c with labels for side-by-side view:
151
+ brainstorm_push_screen({ html: "...", slot: "a", label: "Option A" })
152
+ brainstorm_push_screen({ html: "...", slot: "b", label: "Option B" })
140
153
 
141
- BUILT-IN CSS CLASSES (themed light/dark):
142
- .options + .option — Selectable vertical option cards with .letter (A/B/C badge) and .content
154
+ CSS CLASSES (themed light/dark, push fragments not full docs):
155
+ .options + .option — Selectable cards with .letter (A/B/C) and .content
143
156
  .cards + .card — Grid cards with .card-image and .card-body
144
- .mockup — Browser-window container with .mockup-header and .mockup-body
145
- .split — Two-column 50/50 side-by-side layout
146
- .pros-cons Pros/cons grid with .pros (green) and .cons (red)
147
- .placeholder — Dashed placeholder area
148
- .mock-nav, .mock-sidebar, .mock-content, .mock-button, .mock-input — UI mockup blocks
149
- .subtitle Muted text below headings
150
- .section — Block with top margin spacing
151
- .label — Small uppercase badge
152
-
153
- MAKING ELEMENTS INTERACTIVE:
154
- Add data-choice="value" and onclick="toggleSelect(this)" to any element to capture clicks as events.
155
- For multi-select, add data-multiselect to the container.
157
+ .mockup — Browser-window container (.mockup-header + .mockup-body)
158
+ .split — Two-column layout | .pros-cons — Tradeoff grid (.pros/.cons)
159
+ .mock-nav, .mock-sidebar, .mock-content, .mock-button, .mock-input
160
+
161
+ INTERACTIVE ELEMENTS:
162
+ Add data-choice="value" onclick="toggleSelect(this)" to capture clicks.
156
163
  Example: <div class="option" data-choice="grid" onclick="toggleSelect(this)"><div class="letter">A</div><div class="content"><h3>Grid</h3></div></div>
157
164
 
158
- AUTO-DETECTED LIBRARIES (CDN injected automatically):
159
- class="mermaid" → Mermaid diagrams (flowchart, sequence, class, state, ER, Gantt, pie)
160
- class="language-*" Prism.js syntax highlighting
161
- $$...$$ or class="math" → KaTeX math rendering
162
-
163
- EVENT TYPES returned by brainstorm_read_events:
164
- click — User clicked a [data-choice] element. Fields: choice, text, id, timestamp
165
- preference User picked a preferred slot in comparison mode. Fields: choice (slot id), timestamp
166
- tab-switch — User switched tabs. Fields: slot, timestamp
167
- view-change — User toggled view mode. Fields: mode, timestamp
168
-
169
- WORKFLOW PATTERNS:
170
- Single Decision: start → push (options with data-choice) → tell user to select → read_events → use choice → stop
171
- A/B/C Comparison: start → push slot a → push slot b → tell user to compare → read_events → look for preference → stop
172
- Multi-Round: start → push round 1 → read_events(clear_after_read:true) → clear_screen → push round 2 → read_events → stop
173
- Progressive Refinement: start → push v1 → get feedback → push v2 (same browser updates) → iterate → stop
174
-
175
- BEST PRACTICES:
176
- - ALWAYS pass project_dir (use cwd) to avoid cross-agent conflicts
177
- - NEVER restart to update content — just call push_screen again
178
- - Push HTML fragments, not full documents
179
- - Start with <h2> heading + .subtitle describing the decision
180
- - One decision per screen
181
- - Tell the user the browser is ready after pushing
165
+ AUTO-DETECTED (CDN injected): class="mermaid" (diagrams), class="language-*" (syntax), $$...$$ (math)
166
+
167
+ EVENTS: click (choice,text), preference (choice), tab-switch (slot), view-change (mode)
168
+
169
+ RULES:
170
+ - NEVER restart to update — just push_screen again
171
+ - Push HTML fragments, not full <html> documents
172
+ - Tell user the browser is ready after pushing
182
173
  - Give user time before reading events
183
- - Always call stop_session when done`,
174
+ - Always stop_session when done`,
184
175
  inputSchema: {
185
176
  type: 'object',
186
177
  properties: {
187
- project_dir: { type: 'string', description: 'Project directory for session storage (ALWAYS pass this use cwd)' },
178
+ project_dir: { type: 'string', description: 'Optional. Stores session files under <dir>/.superpowers/brainstorm/. If omitted, auto-isolates by working directory.' },
188
179
  port: { type: 'number', description: 'Port to bind to (default: random ephemeral)' },
189
- open_browser: { type: 'boolean', description: 'Whether to open the browser automatically (default: true)' }
180
+ open_browser: { type: 'boolean', description: 'Open browser automatically (default: true)' },
181
+ idle_timeout_minutes: { type: 'number', description: 'Auto-stop after N minutes idle (default: 0 = no timeout)' }
190
182
  }
191
183
  }
192
184
  },
@@ -255,12 +247,12 @@ Give the user time to interact before reading — don't read immediately after p
255
247
  return { url: this.serverInstance.url, session_dir: this.sessionDir };
256
248
  }
257
249
 
258
- const { project_dir, port = 0, open_browser = true } = args;
250
+ const { project_dir, port = 0, open_browser = true, idle_timeout_minutes = 0 } = args;
259
251
 
260
252
  // Determine base directory and create session dir
261
253
  const baseDir = project_dir
262
254
  ? path.join(project_dir, '.superpowers', 'brainstorm')
263
- : '/tmp/brainstorm-companion';
255
+ : path.join('/tmp', 'brainstorm-companion', cwdHash());
264
256
  const sessionId = `${process.pid}-${Date.now()}`;
265
257
  const sessionDir = path.join(baseDir, sessionId);
266
258
  fs.mkdirSync(sessionDir, { recursive: true });
@@ -271,6 +263,7 @@ Give the user time to interact before reading — don't read immediately after p
271
263
  host: '127.0.0.1',
272
264
  port: port || 0,
273
265
  ownerPid: process.pid,
266
+ idleTimeoutMs: idle_timeout_minutes > 0 ? idle_timeout_minutes * 60 * 1000 : 0,
274
267
  logFn: (...a) => console.error(...a),
275
268
  });
276
269
 
package/src/session.js CHANGED
@@ -1,13 +1,18 @@
1
1
  'use strict';
2
2
 
3
+ const crypto = require('node:crypto');
3
4
  const fs = require('node:fs');
4
5
  const path = require('node:path');
5
6
 
7
+ function cwdHash() {
8
+ return crypto.createHash('md5').update(process.cwd()).digest('hex').slice(0, 8);
9
+ }
10
+
6
11
  class SessionManager {
7
12
  constructor(projectDir, targetSessionId) {
8
13
  this.baseDir = projectDir
9
- ? `${projectDir}/.superpowers/brainstorm/`
10
- : `/tmp/brainstorm-companion/`;
14
+ ? path.join(projectDir, '.superpowers', 'brainstorm')
15
+ : path.join('/tmp', 'brainstorm-companion', cwdHash());
11
16
  this.targetSessionId = targetSessionId || null;
12
17
  }
13
18