nodeterm
聪明在于学习,天才在于积累。所谓天才,实际上是依靠学习。—— 华罗庚
nodeterm:把终端与 AI 编码代理铺进一张无限画布
项目地址:https://github.com/eneskirca/nodeterm
终端本来是开发者最熟悉的工作空间之一。
可当终端标签不断增加,项目不断切换,多个命令同时运行,AI 编码代理也开始并行工作时,熟悉的窗口布局很容易变成一叠叠被遮住的上下文。某个任务正在构建,另一个任务在等待确认,一段代理会话跑到了哪里,某个分支又对应哪一个终端,往往需要在层层标签之间来回寻找。
nodeterm 尝试用一种更具空间感的方式回应这件事。
它是一个基于节点的终端管理器,将终端与 AI 编码代理放到可无限平移和缩放的画布上。每一个真实运行的终端都可以成为一个可拖动的节点,每一个项目既是一张画布,也是一块类似看板的实时会话面板。终端不再只是藏在标签栏后面的一行标题,而是可以被放置、分组、命名、缩放和持续保留的工作单元。
对于工作流容易分散、任务经常并行、需要长期维护上下文的人来说,nodeterm 不再把终端视作一摞窗口,而是将它们组织成一张可见的地图。
当终端不再是一叠隐藏的标签
传统终端标签的核心问题,不在于不能打开更多,而在于打开更多之后,上下文开始变得难以追踪。
哪个终端正在执行命令。
哪个终端属于某个项目。
哪个 AI 代理正在等待权限确认。
哪个任务已经完成。
哪个会话对应某个分支或工作树。
nodeterm 将这些问题放到了画布上处理。
每一个 shell 都以节点形式存在。用户可以将它放在画布中的任意位置,给它命名,将它与其他节点分组,也可以拉近或拉远视野。终端、代理、便签、编辑器、差异视图、网页与视频不再被限制在单一线性排列中,而是可以按项目、任务、分支或个人习惯摆放。
这种空间布局让工作区拥有了更直观的形状。
一个项目可以在画布左侧放置正在运行的开发服务,中间放置负责实现功能的代理,右侧放置与需求相关的便签和网页节点。另一个分支可以被放到独立分组中,与自己的终端、代理和编辑器一起存在。画布不要求所有任务排成队列,而是允许它们自然地分布。
一切都是节点
nodeterm 的核心表达很直接:一切都是节点。
在画布空白区域点击右键,可以创建终端,也可以创建 AI 代理。每个节点都运行在独立且持久化的 tmux 会话中。终端节点旁边可以放置便签、Monaco 编辑器、差异视图、网页节点和视频节点,让工作中的内容不只停留在命令输出里。
节点类型包括:
- 终端节点
- AI 代理节点
- 便签节点
- 分组节点
- 编辑器节点
- 差异视图节点
- 网页与视频节点
终端节点使用 xterm 与 tmux,并支持 AI 命名。
代理节点支持 Claude Code、Codex、Gemini、GitHub Copilot、opencode、Grok 以及自定义代理。
便签节点可以与代理关联,为代理提供上下文。
分组节点能够与 git worktree 绑定,用于组织一个分支对应一个代理的工作方式。
编辑器节点基于 Monaco,并支持保存操作。
差异节点用于查看变更。
网页与视频节点则可以作为画布中的信息入口。
这些节点被放在同一个空间中,意味着任务不再只能以文件夹、窗口或标签的形式区分。它们也可以通过位置关系建立联系。
tmux 让会话持续存在
nodeterm 的终端连续性依托 tmux。
终端会话能够跨节点重新挂载持续运行,也能够跨应用重启保持存在。正在执行的进程不会因为节点临时离开画布而消失。即使应用退出,再次打开之后,会话依然能够回到原处。
机器重启后,nodeterm 会恢复滚动历史,并恢复代理会话。README 中还说明,代理会话可以通过 claude --resume 继续。
在 macOS 应用中,nodeterm 自带 tmux,因此不需要额外安装也能使用这一机制。如果系统中已经存在 tmux,则会优先使用系统中的 tmux。升级之前打开的终端会维持原有状态,直到节点被刷新。
这种持续性让终端不再只是短暂的命令容器。
它可以成为一个真正持续存在的工作节点。一个正在执行的任务可以留在画布里,等待下一次查看。一个代理会话可以在退出应用后继续保持。一个项目的终端布局也不会因为关闭窗口而失去踪迹。
AI 代理不只是输出文本,而是有状态的工作单元
当 AI 编码代理开始执行任务时,最重要的信息往往不是输出内容本身,而是它当前处于什么状态。
它是在运行。
它需要用户确认。
它已经结束。
它是否派生了子代理。
它还拥有多少上下文空间。
nodeterm 使用基于 hook 的状态机制,而不是依靠输出内容抓取来判断代理状态。代理节点可以显示脉冲式的 RUNNING 与 NEEDS YOU 状态标识,也可以呈现带实时记录的子代理卡片,以及每个节点的上下文计量器。
当代理需要用户介入时,系统可以发送操作系统通知。用户点击通知后,可以直接在节点中回答权限提示。一个回合结束时,应用也会告知用户任务已经完成。
在 MacBook 上,代理状态还会出现在刘海区域中。
这让代理不再像一个需要不断切回查看的黑盒窗口。它拥有清晰的可视化状态,也能够在真正需要人参与的时候发出信号。
让代理之间共享必要的上下文
复杂任务往往并不只有一个代理。
一个代理可能负责实现功能,另一个代理负责检查变更,第三个代理则处理另一个分支上的任务。当这些代理彼此独立运行时,如何让它们在需要时理解相关背景,便成为工作流的一部分。
nodeterm 提供上下文链接能力,使代理节点能够按需读取彼此的会话记录。
对于 Claude,nodeterm 还提供会话分支能力,并支持多个已登录 Claude 身份并行管理。代理也能够借助内置画布控制命令行工具操作画布,例如打开节点、生成团队以及验证彼此的工作。
在这种组织方式下,画布不是单纯摆放终端的位置。它也可以成为代理协作时的工作场地。节点之间的位置、分组与上下文链接,构成了一种能够被人理解,也能够被代理参与的工作结构。
一个项目,两种视图
在 nodeterm 中,每个项目都是一张画布,同时也是一块看板。
看板上的卡片不是静态任务记录,而是实时会话本身。用户可以在不同列之间拖动卡片,而对应的代理仍然继续运行。点击卡片后,可以打开实时卡片弹窗,查看真实会话、成员、截止日期、优先级与评论。
项目画布与看板之间可以通过快捷键切换:
1 | ⌘⇧B |
画布更适合观察空间关系。
看板更适合观察任务流动。
同一个项目因此拥有两种可切换的表达方式。用户可以在画布里将终端、代理、文件与便签按照任务关系排布,也可以切换到看板,在列与卡片之间查看任务当前所处的位置。
会话仍然是同一批会话,只是被放进了不同的视角里。
看板中的 GitHub Issues
nodeterm 提供可选的 GitHub Issues 看板能力。
启用之后,Issue 可以以卡片形式进入看板,并支持标签与列之间的精确映射。看板中可以按全部内容、GitHub 内容和会话内容进行筛选。
卡片在列之间移动时,可以进行双向同步。Issue 的关闭与重新打开状态也能够同步。
这使看板不仅能够承载实时代理会话,也能够承载与项目任务相关的 Issue。实时执行中的工作与项目管理中的工作项,可以在同一个看板视图里并存。
从本机走向远程项目
nodeterm 支持远程项目与 SSH 项目。
用户可以通过 SSH 打开远程主机上的项目。终端、文件、git 操作,甚至看板都在远程主机上运行,而画布仍然保留在本地。
这种模式将画布与执行环境分开。
画布可以继续作为用户的本地交互界面,而实际终端、文件、仓库与代理可以位于远程主机。用户看到的是同样的节点结构,同样的项目组织方式,同样的终端与看板视图,只是工作实际发生在远程环境中。
在架构层面,nodeterm 为终端通信定义了 TerminalTransport 抽象。渲染层只依赖这一接口,不直接依赖 IPC 或 node-pty。
LocalTransport 用于连接本地主机。
RemoteTransport 用于通过 SSH 连接远程代理。
这种设计使远程项目能够接入画布,而不需要改动画布界面本身。
手机上的同一段实时会话
nodeterm 提供 iOS 配套应用。
用户可以通过二维码将手机与 nodeterm 配对。配对之后,手机可以连接到同一批正在运行的实时会话。会话不会变成另一个副本,而是继续指向原本的 tmux 会话。
在手机上,可以查看代理工作状态,可以响应 NEEDS YOU 状态,也可以向任意终端输入内容。移动端还提供推送通知与移动版看板视图。
会话通过中继进行端到端加密,而不是只依赖局域网连接。
这种连接方式让终端与代理不再被锁在桌面前。任务仍然可以在主机上运行,而用户可以在移动设备上跟进状态、查看进度或做出必要回应。
浏览器中的 Server Edition
nodeterm 不只是一款桌面应用。
它还提供 Server Edition,使同一张画布能够以无界面的形式运行在 Linux 或 macOS 主机上,并从任意浏览器访问。
在 Server Edition 中,终端、编辑器、源代码控制、看板与代理都运行在服务器上。用户通过浏览器连接这台主机,查看和操作同一套画布。
开发模式可以通过下面的命令启动:
1 | npm run server:dev |
启动后,可以打开本地地址:
1 | http://127.0.0.1:8443 |
并设置密码。
Server Edition 使用单用户认证,包含密码与安全 Cookie,也提供 WebSocket 桥接。它采用与桌面应用相同的渲染器,因此桌面端与浏览器端并不是两个完全分离的界面系统。
终端、文件、编辑器、差异视图、完整 git 面板、看板和代理状态标识,都可以在浏览器中使用。
在 SSH 主机上接收代理通知
除了通过浏览器访问完整画布,nodeterm 的服务端还可以作为无界面的后台通知主机运行。
将它安装在可以通过 SSH 访问的 Linux 主机上后,手机可以接收该主机上代理的 RUNNING 与 NEEDS YOU 推送通知,并获得 Live Activity 覆盖。
这个模式不需要开放端口。hook 服务保持只绑定本地回环地址,推送则通过 HTTPS 发出,授权信息由手机通过 SSH 提供。
安装命令如下:
1 | curl -fsSL https://raw.githubusercontent.com/eneskirca/nodeterm/main/scripts/install-server.sh | bash |
该命令会完成安装、构建,并将服务作为 systemd 服务运行,启用 NODETERM_HEADLESS=1。再次运行同一命令可以进行更新。
这让远程主机上的代理不仅可以持续运行,也可以在需要用户参与时主动将状态送到手机上。
语音输入终端,但内容不会自动提交
终端操作通常依赖键盘,但 nodeterm 也提供了语音输入方式。
按住 ⌘⌥ 后说话,设备上的 Whisper 会在本地进行转写。转写结果会先显示给用户审阅,只有在用户明确点击发送后,内容才会进入终端。
语音不会离开本机。
这一流程不是将语音直接转化为自动执行的命令,而是保留审阅与发送两个步骤。用户可以先看到文本,再决定是否将其送往当前聚焦的终端。
默认快捷键为:
1 | 按住 ⌘⌥ |
在其他平台上,对应为:
1 | Ctrl+Alt |
从终端到源代码控制
nodeterm 还集成了源代码控制能力。
它提供类似 VS Code 的暂存与取消暂存操作,也支持丢弃变更、切换或创建分支、提交、推送、同步、发布、worktree 以及 gh 登录。这些能力由系统中的 git 提供支持。
源代码控制不再必须发生在画布之外。
项目中的终端、代理、编辑器、差异视图与 git 操作可以放在同一套工作空间中。一个分组可以绑定到 git worktree,一个代理可以对应一个分支,差异节点可以展示变更,git 面板则承接暂存、提交与同步。
此外,nodeterm 还支持通过用户自带的本地代理命令行工具,根据已暂存差异或捕获的终端输出生成 AI 提交信息与终端名称。相关代理会以只读方式运行。
机器电源也会感知代理状态
当代理长时间工作时,机器进入空闲休眠可能会中断任务。
nodeterm 在代理工作期间阻止机器因空闲而休眠,并在代理完成后释放这一状态。这个行为默认开启,也可以在初始设置流程或设置中的行为选项里切换。
README 同时说明,没有应用能够在笔记本电脑合盖时持续阻止机器睡眠。若需要长时间运行代理,机器应保持打开并接通电源,或者将代理运行在不会休眠的主机上,再通过 Server Edition 访问。
这项能力让应用不只关注终端窗口是否可见,也关注任务执行过程中的机器状态。代理仍在工作时,系统不应因为用户暂时离开而过早沉睡。
常用快捷键
nodeterm 提供命令面板、文件浏览器、Markdown 视图、撤销与重做等操作,并允许在设置中重新映射快捷键。
默认快捷键包括:
| 快捷键 | 操作 |
|---|---|
⌘K |
命令面板 |
⌘T |
新建终端 |
⌘⇧C |
新建 Claude Code 会话 |
⌘⇧B |
切换看板 |
⌘W |
关闭选中的节点 |
⌘Z |
撤销 |
⌘⇧Z |
重做 |
⌘M |
切换终端或编辑器中的 Markdown 视图 |
⌘⇧E |
文件浏览器 |
⌘, |
设置 |
⌘/ |
快捷键设置 |
| 右键 | 打开空白区域或节点的操作菜单 |
这些快捷键让画布中的工作不必完全依赖鼠标。终端、代理、看板、文件浏览器与命令面板都可以在键盘操作中快速切换。
同一套核心,三种工作表面
nodeterm 的架构围绕多种运行表面展开。
桌面应用、浏览器 Server Edition 和移动配套应用,使用相同的核心与传输边界。
在 Electron 桌面应用中,代码分为三个上下文:
src/main负责 Electron 壳src/preload是唯一桥梁,并提供window.nodeTerminalsrc/renderer负责 React 界面
src/shared 保存三者共同使用的类型与 IPC 通道名称。
应用中的服务,包括 PTY、工作区与设置、git、代理和 hooks,都位于 src/core,并通过较小的平台接口进行组织。核心服务不导入 Electron。
Electron 是这一平台边界的一种实现。
浏览器 Server Edition 是另一种实现。
浏览器侧通过 WebSocket RPC 桥接运行,并由 src/renderer/bridge 在浏览器中填充 window.nodeTerminal。
React Flow 是实时节点的唯一事实来源。项目会将序列化后的节点持久化到磁盘,而 tmux 则负责让会话在重启后继续存在。
这套结构让 nodeterm 能够保持一个代码库、一个渲染器,同时拥有桌面端、浏览器端和移动端三种工作表面。
从源码构建
nodeterm 支持 macOS 与 Linux,需要 Node.js 20 或更高版本。README 建议使用 tmux,因为它是会话跨重启持续存在的关键。
源码检出不包含打包的 tmux。在 macOS 上,可以执行一次 node scripts/build-tmux.mjs,将 tmux 构建到 resources/bin/tmux。也可以自行安装 tmux。
常用开发与构建命令如下:
1 | npm install |
其中:
npm install会安装依赖,并在安装后根据 Electron ABI 重建 node-ptynpm run dev会启动带渲染层热更新的开发模式npm run build会将生产构建输出到outnpm start用于预览生产构建npm run typecheck是快速正确性检查npm test会运行 vitest 单元测试与集成测试npm run dist会在本地生成未签名的 macOS 安装包npm run dist:linux会在 Linux 主机上生成 AppImage 与.debnpm run server:dev会构建并启动浏览器 Server Edition,需要 Node.js 22 与 tmux
终端终于拥有了位置感
nodeterm 的价值,不只是让终端窗口变得可以拖动。
它试图为并行任务提供一种更适合观察的形态。
终端可以放在画布上。
代理可以显示运行状态与等待状态。
便签可以成为代理上下文。
编辑器与差异视图可以成为任务的一部分。
项目可以在画布与看板之间切换。
远程主机可以通过 SSH 接入。
手机可以连接到同一段实时会话。
浏览器可以访问服务器上的完整工作空间。
在这样的结构里,终端不再只是隐藏在标签栏深处的黑色窗口。它们有位置,有关系,有状态,也有持续存在的上下文。
当任务越来越多,代理越来越并行,真正需要整理的也许不只是命令,而是人对整个工作流的感知。
nodeterm 把这些原本分散在标签、窗口、远程主机和移动设备中的内容,重新铺进了一张可以平移、缩放、拖拽和持续保存的画布。
