Today the developer used Claude to build ACKS Studio, a desktop client for the Hermes local AI Agent framework. In one day the project advanced from zero to v0.3, completing work that would normally take two weeks.
The Electron + React application features a three-panel layout, real-time SSE streaming from the Hermes API, local file protocol for image rendering, localStorage persistence, auto-generated task titles, syntax highlighting, Markdown and CSV table rendering, preset skill prompts, and file attachments. Two Electron black-screen bugs and unwanted UI auto-expansion were debugged and fixed.
The GitHub repository is at https://github.com/shynloc/acks-agent-studio. Future steps include search, history recall, export, and SQLite storage.
系列:ACKS Studio 开发日记
日期:2026 年 5 月 12 日
标签:开发日记、Electron、React、AI Agent、Claude
今天做了一件有点递归感的事:用 AI(Claude)帮我开发一个连接 AI Agent 的桌面客户端。
从早上读文档到晚上推上 GitHub,一天内完成了我自己大概要花两周才能做完的工作量。这篇文章是这个系列的第一篇,我想把这个过程记录下来——不只是技术细节,也包括这种「人机协同开发」的体验和思考。
项目背景:为什么要做 ACKS Studio
我在用一个叫 Hermes 的本地 AI Agent 框架(基于 OpenClaw),它可以调用工具、写文件、执行代码。但它原来只有命令行界面,用起来很不直观:工具调用的过程看不到,产出的文件找不到,对话历史重启就丢失。
我想要一个真正「好用」的桌面客户端:能看到 Agent 实时思考的过程,能预览图片和代码产物,能管理多个任务,能重启后恢复状态。市面上没有现成的——毕竟 Hermes 是我自己搭的框架——所以只能自己做。
这就是 ACKS Studio 的由来。ACKS 是 Agent Client for Knowledge and Skill 的缩写,也是我对这类工具的定位:不只是聊天界面,而是一个让 AI Agent 真正「可操作」的工作台。
技术选型:为什么是 Electron + React
选型其实很快就定了:
- Electron:需要访问本地文件系统(读取 Agent 产出的图片、文档),需要原生协议注册(
localfile://),需要原生文件对话框。纯 Web 做不到这些。 - React:流式状态更新(SSE 事件流 → 实时消息渲染)用 React 的
useReducer处理起来很自然。 - Vite:开发体验好,HMR 让我能在 Electron 运行中实时看到 React 组件的变化,不用每次重启。
- 无 UI 库:从零用 CSS 变量写设计系统,暗色主题、橙色主调,完全可控。这是刻意选择——避免引入大型 UI 库后难以定制的问题。
技术栈很轻:Electron 32 + React 18 + Vite 5 + highlight.js,其他全靠手写。
今天做了什么
一天内从零完成了 v0.3,大概涵盖以下内容:
基础框架(v0.1)
三栏布局:左侧任务列表(TasksPanel)、中间对话区(ChatPanel)、右侧产物面板(ArtifactsPanel)。最左一列是图标导航栏(Rail)。
Hermes SSE 对话流:用户发消息 → 主进程 IPC → Hermes API POST 启动 run → 订阅 SSE 事件流 → 分发 message.delta / tool.started / tool.completed / run.completed 事件 → 渲染层实时更新。
一个细节让我花了不少时间:本地图片的渲染。Hermes 用 MEDIA:/path/to/file.png 这种格式告诉客户端「这里有个文件」。最初我用 IPC 把图片读成 base64 再传给渲染层,结果大图片会卡住整个界面。后来改用 Electron 的 protocol.registerFileProtocol 注册了一个 localfile:// 自定义协议,渲染层直接 <img src="localfile://..."> 就能加载本地图片,完全绕过 IPC,丝滑很多。
持久化(v0.2)
重启后数据丢失是最影响日常使用的问题。用 localStorage 做持久化,key 是 acks_state_v1,存储任务列表、对话记录、产物路径、当前选中任务。
一个坑:产物文件(尤其是图片)如果把 base64 内容也存进 localStorage,很快就会超过 5MB 限制而静默失败。解决方案是只存路径元数据,文件内容按需从磁盘重读——反正路径不变,再读一次没有任何问题。
另一个有意思的功能是任务标题自动生成:新建任务默认标题是「新任务」,等第一条对话完成后,客户端会静默调用 Hermes,用一个简单的 prompt "请用不超过10个字概括这个任务的核心主题" 生成一个短标题,然后更新任务列表。用户完全感知不到这个后台调用,但任务列表突然就有了有意义的名字。
能力扩展(v0.3)
这部分主要是让 Agent 的输出更「可读」,以及让输入更方便:
语法高亮:用 highlight.js 的按需加载模式(只引入 10 种语言的解析器),避免全量 bundle 过大。每次代码块渲染时用 useEffect 调 hljs.highlight(),样式和设计系统的暗色主题对齐。
Markdown 表格:手写了一个表格解析器,识别 | col | col | 格式,支持分隔行检测,渲染为带斑马纹、可点击表头排序的 HTML 表格。
产物面板 CSV 视图:写了一个支持引号转义的 CSV 解析器,渲染为可排序表格。点击表头切换升降序,数字列用数值排序,文字列用中文字符串排序。
技能面板:Composer 底部的「技能」按钮弹出 8 个预设 prompt(总结、分析数据、写邮件、调研等),点击自动填充输入框。一个小细节:说明文字可能超过弹窗宽度,用 overflow-x: auto + 隐藏滚动条(scrollbar-width: none)实现左右滑动查看,不截断文字。
文件附件:点击 📎 按钮调用 Electron 的 dialog.showOpenDialog,或者直接拖拽文件到输入框。图片附件转成 MEDIA: 路径追加到消息,文本文件读取内容内联插入,让 Agent 能看到文件内容。
遇到的问题和解决过程
黑屏问题(两次)
第一次:把 Hermes URL 从常量改成变量后,webRequest.onBeforeSendHeaders 回调还在引用旧变量名,Electron 主进程报错 HERMES_URL is not defined,渲染层直接黑屏。
第二次:为了剥离发往 Hermes 的 Origin header(绕过 CORS),我把拦截范围设成了 ['http://*/*', 'https://*/*']——结果把 Vite 的 WebSocket HMR 连接也拦截了,页面加载直接失败。修复方案是在回调里加一个 if (url.startsWith(hermesUrl)) 的判断,非 Hermes 请求直接放行。
两次黑屏都是 Electron 主进程的问题,诊断起来比渲染层的错误要麻烦——没有 DevTools,只能看终端日志。
Agent Trace 自动展开
TracePanel 每次新对话都会自动展开,用户得不停手动收起,很烦。根本原因是父组件传了 collapsed={!msg.streaming} 作为 prop,每次 streaming 开始时强制展开。修复是把这个 prop 完全移除,让 TracePanel 内部的 useState(true) 作为唯一折叠状态控制,用户折叠后就保持折叠。
关于「用 AI 写 AI 客户端」这件事
整个过程里,我基本上扮演的是产品经理和 QA 的角色:定需求、测功能、发现问题。Claude 扮演的是开发者:读代码、找问题根源、写修复代码。
有几个感受:
效率高得惊人,但方向控制在人这边。一天内完成 v0.3 的工作量,凭我自己写大概需要两周。但每个功能要做成什么样、交互细节怎么定,还是我来决策。AI 负责执行,我负责判断。
错误诊断是最有价值的能力。Claude 不只是写代码,更重要的是能快速定位问题。两次黑屏,我自己看终端日志可能要找半小时,Claude 看了一眼代码就定位到了根本原因。这个能力在 debug 阶段比写新功能更值钱。
上下文是瓶颈。一次对话的上下文有限,超过后需要用交接文档接力。我们今天就遇到了这个问题,专门写了一份 HANDOFF_PROMPT.md,让下一个 session 能快速继承状态继续工作。这是 AI 协同开发目前最大的摩擦点。
代码已开源
今天的代码已推送到 GitHub:
https://github.com/shynloc/acks-agent-studio
如果你也在用类似的本地 Agent 框架,或者对 Electron + React 桌面应用开发感兴趣,欢迎参考。
下一步
v0.4 的主要方向是体验打磨:
- 任务列表搜索(按标题/标签过滤)
- Composer 历史指令召回(↑/↓ 键)
- 对话导出(Markdown)
- 产物「在 Finder 中显示」
再往后(v0.5)需要解决 localStorage 5MB 的容量限制,迁移到 SQLite。
这个系列会持续更新,记录每一个开发阶段的决策、踩坑和思考。下篇见。
本文由 Taojin 和 Claude Sonnet 4.6 协同完成。代码仓库:github.com/shynloc/acks-agent-studio
了解 ~/jintaoblog/朝夕见闻志⚡️ 的更多信息
订阅后即可通过电子邮件收到最新文章。
