news 2026/9/7 16:52:46

Superpowers 可视化头脑风暴伴侣:从实施计划到零依赖本地服务器的完整实现解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Superpowers 可视化头脑风暴伴侣:从实施计划到零依赖本地服务器的完整实现解析

Superpowers 可视化头脑风暴伴侣:从实施计划到零依赖本地服务器的完整实现解析

【免费下载链接】superpowersAn agentic skills framework & software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers

本文以 Superpowers 仓库中的实施计划 2026-01-17-visual-brainstorming.md 为主线,解析"可视化头脑风暴伴侣"(Visual Brainstorming Companion)的设计目标、架构与任务拆解:一个本地 Node.js 服务器监视 HTML 文件变更并向浏览器推送界面,用户的点击、表单与输入通过 WebSocket 回流到服务器标准输出,供 Claude(或其他编码 Agent)在下一轮对话中读取。读完本文,你将掌握该功能的完整数据流、服务端与客户端关键代码、测试验证方式,以及当前仓库中该方案演进的零依赖实现细节。

目标与总体架构

计划文档开篇明确了三个核心要素:

  • Goal:为 Claude 的头脑风暴会话提供一个基于浏览器的视觉伴侣——在终端对话旁边展示 mockup、原型和交互式选项;
  • Architecture:Claude 把 HTML 写入临时文件,一个本地 Node.js 服务器监视该文件并附带自动注入的 helper 库提供服务;用户的交互通过 WebSocket 流向服务器 stdout,Claude 在后台任务输出中看到这些事件;
  • Tech Stack:Node.js、Express、ws(WebSocket)、chokidar(文件监视)。

用数据流描述就是:

Agent 写 HTML 文件 ──> chokidar 检测到变更 ──> 向所有浏览器推送 reload 浏览器展示最新 HTML(helper.js 已注入) 用户点击/提交/输入 ──> helper.js 自动捕获 ──> WebSocket ──> 服务器 stdout 输出 JSON 事件 Agent 读取后台任务输出 ──> 获得结构化的用户反馈

终端始终是主对话界面,浏览器只是视觉辅助("The terminal remains the primary conversation interface. The browser is a visual aid.")。

Task 1:服务器基础(Server Foundation)

计划中的第一个任务创建lib/brainstorm-server/(含package.jsonindex.js)。package.json声明了三个依赖:

{ "name": "brainstorm-server", "version": "1.0.0", "description": "Visual brainstorming companion server for Claude Code", "main": "index.js", "dependencies": { "chokidar": "^3.5.3", "express": "^4.18.2", "ws": "^8.14.2" } }

最小可运行的index.js实现了五件关键事情,每一处都值得展开:

1. 环境变量驱动的端口与屏幕文件

const PORT = process.env.BRAINSTORM_PORT || 3333; const SCREEN_FILE = process.env.BRAINSTORM_SCREEN || '/tmp/brainstorm/screen.html'; const SCREEN_DIR = path.dirname(SCREEN_FILE);

端口默认 3333,被监视的屏幕文件默认/tmp/brainstorm/screen.html。服务器启动时会自动创建目录并写入一个"等待中"默认页面("Waiting for Claude to push a screen...")。

2. WebSocket 客户端集合与事件转发

const clients = new Set(); wss.on('connection', (ws) => { clients.add(ws); ws.on('close', () => clients.delete(ws)); ws.on('message', (data) => { // User interaction event - write to stdout for Claude const event = JSON.parse(data.toString()); console.log(JSON.stringify({ type: 'user-event', ...event })); }); });

注意事件被包裹为{ type: 'user-event', ...event }后写到 stdout——这是 Agent 消费用户反馈的唯一通道。

3. 页面路由与 helper 注入

app.get('/', (req, res) => { let html = fs.readFileSync(SCREEN_FILE, 'utf-8'); const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8'); const injection = `<script>\n${helperScript}\n</script>`; if (html.includes('</body>')) { html = html.replace('</body>', `${injection}\n</body>`); } else { html += injection; } res.type('html').send(html); });

每次请求都重新读取屏幕文件并在</body>前注入 helper 脚本——Agent 无需在 HTML 中写任何交互代码。

4. 文件变更监视与浏览器刷新

chokidar.watch(SCREEN_FILE).on('change', () => { console.log(JSON.stringify({ type: 'screen-updated', file: SCREEN_FILE })); clients.forEach(ws => { if (ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'reload' })); } }); });

5. 绑定回环地址并输出结构化启动信息

server.listen(PORT, '127.0.0.1', () => { console.log(JSON.stringify({ type: 'server-started', port: PORT, url: `http://localhost:${PORT}` })); });

服务器只绑定127.0.0.1,所有 stdout 输出都是单行 JSON(server-started/screen-updated/user-event),让 Agent 可以可靠地解析。计划要求运行cd lib/brainstorm-server && npm install安装依赖,再用timeout 3 node index.js验证能收到server-startedJSON。

Task 2:浏览器 Helper 库(自动事件捕获)

helper.js是一个自执行 IIFE,服务器注入后它完成了三件事:建立 WebSocket 连接、自动捕获用户交互、暴露显式 API。

连接与断线重连

(function() { const WS_URL = 'ws://' + window.location.host; let ws = null; let eventQueue = []; function connect() { ws = new WebSocket(WS_URL); ws.onopen = () => { // Send any queued events eventQueue.forEach(e => ws.send(JSON.stringify(e))); eventQueue = []; }; ws.onmessage = (msg) => { const data = JSON.parse(msg.data); if (data.type === 'reload') { window.location.reload(); } }; ws.onclose = () => { // Reconnect after 1 second setTimeout(connect, 1000); }; } // ...

要点:收到reload消息即整页刷新;断线 1 秒后自动重连;连接未就绪时事件进入eventQueue,重连后补发——保证用户交互不因瞬时断连丢失。

三类自动捕获

// Auto-capture clicks on interactive elements document.addEventListener('click', (e) => { const target = e.target.closest('button, a, [data-choice], [role="button"], input[type="submit"]'); if (!target) return; // Don't capture regular link navigation if (target.tagName === 'A' && !target.dataset.choice) return; e.preventDefault(); send({ type: 'click', text: target.textContent.trim(), choice: target.dataset.choice || null, id: target.id || null, className: target.className || null }); });

点击捕获用事件委托 +closest()匹配button, a, [data-choice], [role="button"], input[type="submit"];普通链接导航被排除,命中目标则preventDefault()后发送click事件,其中data-choice是"选项标识符"约定。

表单提交捕获:

document.addEventListener('submit', (e) => { e.preventDefault(); const form = e.target; const formData = new FormData(form); const data = {}; formData.forEach((value, key) => { data[key] = value; }); send({ type: 'submit', formId: form.id || null, formName: form.name || null, data: data }); });

输入变更捕获带 500ms 防抖:

let inputTimeout = null; document.addEventListener('input', (e) => { const target = e.target; if (!target.matches('input, textarea, select')) return; clearTimeout(inputTimeout); inputTimeout = setTimeout(() => { send({ type: 'input', name: target.name || null, id: target.id || null, value: target.value, inputType: target.type || target.tagName.toLowerCase() }); }, 500); // 500ms debounce });

显式 API

window.brainstorm = { send: send, choice: (value, metadata = {}) => send({ type: 'choice', value, ...metadata }) };

除了全自动捕获,页面作者也可以显式调用brainstorm.send(...)brainstorm.choice('custom', {extra: 'data'})发送任意结构化事件。计划要求用node -c lib/brainstorm-server/helper.js校验语法后提交。

Task 3:集成测试

计划为服务器编写位于tests/brainstorm-server/server.test.js的集成测试,思路是:用child_process.spawn拉起真实服务器(BRAINSTORM_PORT=3334BRAINSTORM_SCREEN=/tmp/brainstorm-test/screen.html),采集其 stdout,然后依次断言:

  1. 启动消息:stdout 包含server-started与端口号;
  2. HTML 服务与注入GET /返回 200,body 含brainstorm内容且注入了 helper(body 中出现WebSocket字样);
  3. 事件中继:通过真实 WebSocket 客户端发送{ type: 'click', text: 'Test Button' },断言 stdout 出现user-eventTest Button
  4. 文件变更通知:修改屏幕文件后,断言第二个 WebSocket 客户端收到{ type: 'reload' }消息。

测试用自写的fetch封装(基于http.get)、sleepcleanup()(删除测试目录)辅助,finally块中server.kill()并清理,失败时process.exit(1)。运行方式:cd tests/brainstorm-server && npm install ws && node server.test.js

当前仓库中该目录已扩展为更完整的测试套件,除server.test.js外还有 auth.test.js、lifecycle.test.js、ws-protocol.test.js、branding.test.js、helper.test.js 以及 start/stop 脚本的 shell 测试——可见测试面从"服务器基本行为"扩展到了认证、生命周期与 WebSocket 协议层。

Task 4:接入 Brainstorming Skill

计划将可视化伴侣作为 brainstorming skill 的可选能力:

  • 新建skills/brainstorming/visual-companion.md参考文档,覆盖启动服务器、推送屏幕、读取用户响应三类操作;
  • 在 SKILL.md 的 "Key Principles" 之后追加 "Visual Companion (Optional)" 小节,给出适用场景(UI/UX 选项对比、线框图、结构化反馈、点击原型)与四步用法。

计划文档中给出的参考文档草案包含以下关键内容,都值得完整保留:

启动服务器(作为后台任务):

node ${PLUGIN_ROOT}/lib/brainstorm-server/index.js

然后告知用户:"I've started a visual companion at http://localhost:3333 - open it in a browser."

推送屏幕:把 HTML 写入/tmp/brainstorm/screen.html,服务器监视该文件并自动刷新浏览器。

读取用户响应:在后台任务输出中检查 JSON 事件,例如:

{"type":"user-event","type":"click","text":"Option A","choice":"optionA","timestamp":1234567890} {"type":"user-event","type":"submit","data":{"notes":"My feedback"},"timestamp":1234567891}

事件类型共三种:click(点击按钮或data-choice元素)、submit(表单提交,含全部表单数据)、input(字段输入,500ms 防抖)。

HTML 模式(Patterns)

选项卡(Choice Cards):

<div class="options"> <button><div class="mockup"> <header><form> <label>Priority: <input type="range" name="priority" min="1" max="5"></label> <textarea name="notes" placeholder="Additional thoughts..."></textarea> <button type="submit">Submit</button> </form>

显式 JavaScript:

<button onclick="brainstorm.choice('custom', {extra: 'data'})">Custom</button>

验证步骤是grep -A5 "Visual Companion" skills/brainstorming/SKILL.md,确认新小节存在后提交。

Task 5 与 Summary:收尾

最后一个可选任务是确保.gitignore排除lib/brainstorm-server/node_modules/。计划文档的 Summary 部分归纳了完成后的四个产物:lib/brainstorm-server/下的服务器、自动注入的 helper 库、tests/brainstorm-server/下的测试,以及更新了 visual companion 小节与参考文档的 brainstorming skill。使用方法四步走:

  1. 后台启动服务器:node lib/brainstorm-server/index.js &
  2. 让用户打开http://localhost:3333
  3. 把 HTML 写入/tmp/brainstorm/screen.html
  4. 检查任务输出中的用户事件

从源码看:当前仓库的演进实现

上面的计划描述的是 v1 形态(Express + ws + chokidar,固定端口 3333,单文件监视)。当前仓库中的实际实现已演进为零依赖版本,位置在 skills/brainstorming/scripts/server.cjs,配套 start-server.sh、stop-server.sh、frame-template.html 与 helper.js,用法详见 visual-companion.md。对照计划文档,演进点如下:

1. 手写 RFC 6455 协议替代 ws 库

server.cjs顶部直接实现了 WebSocket 帧编解码:computeAcceptKey(SHA1 + 魔数258EAFA5-...)、encodeFrame/decodeFrame(支持 7/16/64 位长度、客户端掩码校验、10MB 帧上限),handleUpgrade中手动返回101 Switching ProtocolsdecodeFrame强制要求客户端帧带掩码("Client frames must be masked"),并处理 TEXT / CLOSE / PING / PONG 帧与未知 opcode 的 1003 关闭。这使服务器在无任何 npm 依赖的情况下即可运行。

2. 单文件监视升级为目录 + 最新文件语义

计划中的chokidar.watch(SCREEN_FILE)单文件监视,演进为对CONTENT_DIR$SESSION_DIR/content)的原生fs.watch目录监视,并维护knownFiles集合区分"新屏幕"与"更新":

if (!knownFiles.has(filename)) { knownFiles.add(filename); console.log(JSON.stringify({ type: 'screen-added', file: filePath })); maybeOpenBrowser(); } else { console.log(JSON.stringify({ type: 'screen-updated', file: filePath })); } broadcast({ type: 'reload' });

服务器始终提供按修改时间最新的 HTML 文件getNewestScreen()),每个屏幕一个语义化文件名、永不复用——这与计划中"一个屏幕文件"的模型相比,让 Agent 可以积累一组屏幕而互不覆盖。代码注释还解释了为何不依赖事件类型:macOS 的fs.watch对新文件和覆盖都报rename,所以靠已知文件集合判断。

3. 会话密钥与内容片段/完整文档双模

计划版 URL 是裸的http://localhost:3333;现行实现要求 URL 携带?key=…会话密钥(32 字节随机十六进制),HTTP 与 WebSocket 升级都经过isAuthorized()的常量时间比较(crypto.timingSafeEqual),首次访问后密钥写入 HttpOnly + SameSite=Strict 的 cookie,cookie 名带实际绑定端口(brainstorm-key-<port>)以避免本地多服务器共享 cookie 串扰。未授权的请求收到 403 页(提示"需要完整 URL")。

内容侧也升级了:屏幕文件以<!DOCTYPE/<html开头则原样服务,否则自动包进 frame 模板——即 visual-companion.md 中"默认写内容片段(content fragments)"的规则。frame 模板(frame-template.html)提供明暗主题、头部连接状态灯,以及.options/.option/.cards/.card/.mockup/.split/.pros-cons/.mock-nav/.mock-input/.placeholder等 CSS 类,替代了计划版"自己写全部 HTML/CSS"的要求。

4. 客户端 helper 的健壮性增强

现行 helper.js 保留了计划版的核心语义(data-choice点击捕获、window.brainstorm显式 API、事件队列补发),但增强了:指数退避重连(500ms 起、翻倍、30s 封顶,nextReconnectDelay为纯函数并导出供单测)、15 秒未恢复则显示 "Companion paused" 墓碑层(tombstone)并在服务器同端口重启后自动恢复刷新、WebSocket 升级请求上带会话密钥(/?key=...)。同时toggleSelect实现了单选/多选(data-multiselect)的选中态管理。

5. 生命周期:守护、闲置超时与优雅停机

计划版的服务器需要 Agent 自己管理进程存活;现行实现内置了完整生命周期:

  • start-server.sh为每个会话生成独立目录(/tmp/brainstorm-$$-<ts>--project-dir下的.superpowers/brainstorm/...),用nohup+disown后台启动并写 PID 文件,轮询日志等待server-startedJSON,且验证进程在短暂窗口后仍存活(捕获进程回收器);
  • 服务器接收BRAINSTORM_OWNER_PID(harness 的祖先进程 PID),周期性检查宿主是否死亡——死了就自杀;start-server.sh还处理了 WSL/Tailscale/Windows MSYS2 下 PID 不可见的情形(owner-pid-invalid日志后降级为纯闲置超时);
  • 默认 4 小时无活动自动关闭(--idle-timeout-minutes可调),关闭时先销毁所有已升级的 WebSocket socketserver.close()——否则进程会挂在打开的连接上,这正是 lifecycle.test.js 明确验证的行为;
  • 启动的server-startedJSON 写入$STATE_DIR/server-info(0600 权限,含 URL 与密钥),shutdown时写server-stopped标记;stop-server.sh用每次启动生成的--brainstorm-server-id参数核对 PID 属于本服务器才肯发信号(防止 PID 复用误杀),且只清理/tmp下的临时会话,--project-dir的 mockup 文件保留供后续查看。

6. 端口策略

计划版固定 3333 端口;现行实现按BRAINSTORM_PORT→ 上次绑定端口(BRAINSTORM_PORT_FILE,让重启复用同端口、已打开的标签页自动重连)→ 随机高端口(49152 起)的顺序选取,EADDRINUSE时一次性回退随机端口(但若设了BRAINSTORM_TOKEN环境变量则拒绝回退,直接失败退出,避免密钥与端口错配)。

事件模型对照:计划版与现行版

维度计划版(本文主体文档)现行仓库实现
传输依赖Express + ws + chokidar零依赖,手写 RFC 6455 +fs.watch
屏幕来源单文件/tmp/brainstorm/screen.htmlcontent/目录中最新的 HTML 文件
内容要求完整 HTML,注入 helper内容片段自动包 frame,或完整文档
访问控制无(仅绑定 127.0.0.1)?key=会话密钥 + HttpOnly cookie + 常量时间比较
事件输出stdout{type:'user-event', ...}stdout{source:'user-event', ...},且含choice的事件追加到$STATE_DIR/events(JSON Lines,新屏幕推入时清空)
刷新机制chokidar 变更 → 广播 reload目录监视 + 100ms 防抖 → 广播 reload,区分 screen-added/updated
进程管理Agent 自行后台运行start/stop 脚本、owner PID 守护、闲置超时、端口/密钥持久化

值得注意的一个细节:现行版把含choice字段的事件额外落盘到state_dir/events文件(见 server.cjs 的handleMessage),Agent 在下一轮直接读文件即可拿到浏览器交互的 JSON Lines 记录,与终端文本反馈合并——这比"盯着 stdout 滚动"更可靠,也是 visual-companion.md 中"主循环"(The Loop)的标准操作:每轮先确认server-info存在且server-stopped不存在 → 写新的语义化命名屏幕文件 → 提示用户查看并结束本轮 → 下一轮读取events与终端回复。

实践要点小结

  • 计划文档的价值:2026-01-17-visual-brainstorming.md 展示了 Superpowers 自身的工程方法——每个任务带 Files / Steps / 验证命令 / commit 信息,可直接交给 Agent 逐任务执行(文档开头即声明需用executing-plansskill);
  • 可复制的架构:HTML 文件作为"屏幕"单一事实源、文件变更作为推送触发器、stdout JSON 作为 Agent 可读的事件总线——三者解耦,使 Agent 侧不需要理解 WebSocket;
  • 当前仓库的演进:从"固定 3333 端口的单文件服务器"到"带会话密钥、零依赖、可自愈的多屏幕会话服务",演进路径本身由 tests/brainstorm-server/ 下的测试与 docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md、docs/superpowers/plans/2026-06-10-visual-companion-auth-hardening.md 等后续计划文档记录,可继续沿仓库内的计划/规格文档追溯。

【免费下载链接】superpowersAn agentic skills framework & software development methodology that works.项目地址: https://gitcode.com/GitHub_Trending/su/superpowers

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 16:52:34

第41篇|推送通知库适配 HarmonyOS:Token 管理、通知权限和消息去重

第41篇&#xff5c;推送通知库适配 HarmonyOS&#xff1a;Token 管理、通知权限和消息去重 图 1&#xff1a;推送通知库适配封面图&#xff0c;用来概括本文主题、适配对象和工程边界。 实际项目里&#xff0c;推送通知库适配经常不是“引入依赖就能用”的问题。真正麻烦的是输…

作者头像 李华
网站建设 2026/9/7 16:52:28

python的图论工业场景模拟第九十五篇:完美派单可行性校验与缺口分析,任务:验证是否存在完美匹配,不存在则输出缺口工单,图建模说明:二分无向图,核心点:最大匹配数与节点集规模对比。

完美派单可行性校验与缺口分析&#xff1a;验证是否存在完美匹配&#xff0c;不存在则输出缺口工单 "某设备运维中心&#xff0c;每晚要给 12 台待修设备派 8 个值班工程师。系统需要判断&#xff1a;能不能让每台设备都分到合适的人&#xff1f;——也就是完美匹配是否存…

作者头像 李华
网站建设 2026/9/7 16:52:23

3万棵树渲染性能优化实战:从Draw Call到LOD的完整诊断流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 16:52:03

SVN历史信息查看全攻略:从svn log到svn blame实战

1. 先搞清楚SVN历史信息的底层逻辑1.1 全局版本号&#xff1a;SVN历史的核心很多人刚接触SVN时&#xff0c;最容易迷糊的一个点就是版本号。和Git里每个提交有独立的、乱码一样的哈希值完全不同&#xff0c;SVN的版本号是纯数字&#xff0c;而且是整个仓库统一的全局计数器。什…

作者头像 李华
网站建设 2026/9/7 16:51:30

TMS32F28P550调试实战:C2000 CCS仿真器与Flash烧写问题排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 16:50:20

【单片机毕设案例分享】基于 STM32 的环境传感器数据采集与远程 APP 控制系统设计 基于 STM32 的室内环境监测排风联动声光告警系统设计(010107)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于单片机&#xff0c;STM32单片机&#xff0c;51单片机&#xff0c;J…

作者头像 李华