tmuxes
v0.1.14
Published
Web UI to run and supervise many CLI coding agents in tmux — local, SSH, and WSL.
Maintainers
Readme
🖥️ tmuxes
简体中文 | English
一个浏览器标签页,掌控一整群 CLI coding agent。
Claude Code · Codex · OpenCode · Hermes —— 每个 agent 独占一个 tmux 会话, 横跨 本地 · SSH · WSL,还自带每个 agent 工作目录的文件浏览器和 Git 面板。
🔔 Claude Code 结束运行、异常停止或需要决策时,浏览器会自动提醒你 —— 侧边栏红/绿状态点 +「结束 / 错误 / 决策」提示 + 提示音 + 后台标签页标题闪烁。Codex 的审批 / 决策请求不再触发提醒,避免 Codex 自动审批时误报。
🔒 仅本机 · ⚡ 一键启动 · 🔔 agent hook 提醒 · 🪟 Windows 上直通 WSL · 🧩 零配置
为什么做这个? 现代编码 agent 都是常驻的终端进程。同时跑好几个,你就开始在一堆窗格、SSH 窗口之间手忙脚乱: 「等等,刚那个是在哪台机器上来着?」tmuxes 把它们全塞进一个清爽的网页 UI: 开一个会话、丢进文件夹、看它干活、顺手瞄一眼它正在改的文件 —— 本地还是远程,都是同一个视图。
✨ 特性亮点
| | |
|---|---|
| 🧠 为 agent 而生 | 每个 agent 独占一个 tmux 会话。新建时可带初始命令(比如 claude 或 codex),选中后右侧就是一个完全可交互的实时终端。 |
| 🔔 结束 / 错误提醒 | 新建会话时初始命令是 claude 或 codex 会自动接入官方 lifecycle hooks。也可以先进入空 session cd 到目标目录,再点终端右上角的 claude / codex 按钮启动带 hook 的 agent。已展开目标每 5 秒同步一次:红点表示 agent 正在运行,绿点表示已结束或异常停止;结束运行和异常停止会显示不同提示。 |
| 🌐 本地 · SSH · WSL · 原生 Windows | 一个侧边栏同时列出你的本机、~/.ssh/config 里的主机、(Windows 上)你的 WSL 发行版,以及(Windows)原生 PowerShell / cmd 会话 —— 全部并排排开。 |
| 🗂️ 文件夹树 | 像资源管理器一样,把会话拖进可拖拽的文件夹里整理。按目标分别持久化到本地。 |
| 📂 实时文件浏览 + 编辑 | 侧边栏底部跟随每个会话的工作目录 —— 点一个代码文件就能把终端一分为二,在下面直接读和改(可保存、撤销/重做)。 |
| 🔀 Git 面板 | 侧边栏底部可切到 Git 视图,基于当前会话工作目录查看仓库状态、未提交更改、提交历史和远端未合入提交;点击待提交文件会在右侧大区域底部打开类似 VS Code 的左右红绿 diff,点击 commit 会在同一区域显示完整 patch;支持切换分支、fetch、pull、push、sync 和一键提交全部工作区更改。Git 认证沿用目标机器已有配置,tmuxes 不保存凭据。 |
| 🔁 真·多端同步 | 基于原生 tmux attach:同一个会话开两个标签页,逐键同步、互为镜像。 |
| ⚙️ 可调 | 侧边栏、终端、文件查看器的字号都能调,实时生效、刷新后仍保留。 |
| 🚀 一键启动 | 双击 start.cmd / start.command / start.sh → 自动构建、启动、打开浏览器。 |
🖼️ 长这样
🏗️ 架构
REST (create · list · rename · kill · cwd · files · git)
┌────────────┐ ┌──────────────────────┐ ┌──────────────────────────────────┐
│ Browser │──▶│ Node · Express · ws │──pty──▶│ tmux (Linux/macOS)│
│ xterm.js │◀──│ node-pty │──pty──▶│ ssh -tt user@host → tmux (remote)│
└────────────┘ └──────────────────────┘──pty──▶│ wsl.exe -d <distro> → tmux (Windows)│
▲ binary bytes ⇄ WebSocket ⇄ JSON control └──────────────────────────────────┘client/—— React + Vite + TypeScript,终端基于@xterm/xterm。server/—— Node + Express +ws+node-pty。一个小型 REST API 跑短命的 tmux 管理命令;单个 WebSocket 端点负责交互式 attach 的流式传输。
Windows 上没有原生 tmux? 没问题。服务端原生运行(node-pty 用 ConPTY),通过
wsl.exe直通你 WSL 发行版里的 tmux。Linux/macOS 上则直接和本地 tmux 通信。远程主机用系统ssh二进制,复用你已有的~/.ssh密钥 /ssh-agent—— 绝不存储任何密码。
📦 用 npm 安装
建议直接用 @latest,这样能拿到最新的修复包。tmuxes 是单用户本机工具,启动后只监听 127.0.0.1。
# 先验证 npm 包入口:
npx --yes tmuxes@latest --help
# 一键运行(无需克隆,默认自动开浏览器):
npx --yes tmuxes@latest
# 或全局安装后用 tmuxes 命令:
npm install -g tmuxes
tmuxes # → http://127.0.0.1:7420
# 常用参数:
tmuxes --port 8080 --no-open如果 Windows 上 npx 失败,先确认:
node -v是 22.12+ 且 <23,npm -v是 10+。- 使用的是官方 npm registry,且没有旧缓存污染;必要时先跑
npm cache verify再重试。 - 你要连接的机器/主机上已经装好 tmux。Linux 上
node-pty需要现场编译,先装build-essential+python3;Windows / macOS 使用预编译二进制。
🚀 从源码一键启动(开发用)
🔧 手动运行
npm install # node-pty:Win/macOS 有预编译,Linux 从源码编译
# 开发 —— Vite 开发服务器 + API,带热更新:
npm run dev # → http://localhost:5173
# 生产 —— 构建客户端,由单进程统一服务:
npm run build
npm start # → http://localhost:7420 (设 TMUXES_OPEN=1 可自动打开浏览器)🔔 启动带 hook 的 Claude Code / Codex
tmuxes 目前会给 Claude Code (claude) 和 Codex (codex) 自动接入官方 lifecycle hooks,用来判断 agent 是正在运行、已经结束或异常停止。
两种用法:
- 新建 session 时,在初始命令里直接填
claude或codex。 - 先新建空 session,进入后在终端里
cd /你的目标目录,再点终端右上角的claude/codex按钮。
状态含义:
- 红点:agent 正在运行。
- 绿点:agent 已结束、异常停止,或这个 session 没接入 agent hook。
结束badge:本轮运行结束。错误badge:agent 异常停止,例如 Codex 断流但没有触发 stop hook。tmuxes 会在已展开目标的 5 秒同步里扫描 running agent 的 pane 尾部并把这类错误纠正为提醒状态。
审批 / 决策请求的处理分两种:Claude Code 的 PermissionRequest、permission_prompt 和 elicitation_dialog 会触发「决策」提醒;Codex 的审批 / 决策请求不再触发提醒,也就是说 Codex 开启自动审批 / Approve for me 时不会因为 PermissionRequest 把 tmuxes 切成“需要决策”提醒,人工审批模式也同样不再响铃。
注意:右上角按钮本质上是向当前 tmux pane 发送一条带 hook 的 claude / codex 命令。不要在当前 pane 里已有程序正在接收输入时点击它。裸 cc 常常是系统 C 编译器,tmuxes 不会默认把它当作 Claude Code。原生 Windows shell 没有 tmux session option,因此不支持这套 hook 状态。
🔀 Git 面板
侧边栏底部可以从 文件 切到 Git。Git 面板绑定当前选中 tmux session 的工作目录,不做后台 Git 轮询;进入面板、切换会话、点击刷新或执行 Git 操作后才读取状态。
- 工作区更改:单独列出未提交文件。点击待提交文件会在右侧大区域底部打开类似 VS Code 的左右红绿 diff;未跟踪文件也会按新增文件显示。
- 提交:输入 commit message 后点
Commit,tmuxes 会执行git add -A再创建 commit;有冲突时不会提交。 - 提交历史 / 远端提交:显示当前分支最近提交,以及 upstream 上尚未合入本地的远端提交。点击任一 commit 会在同一个底部查看区显示完整 patch。
- 同步操作:支持 fetch、
pull --ff-only、push、sync(fetch --prune→pull --ff-only→ 必要时 push)和分支切换。不会执行 force push、reset、discard、clean 或删除分支。 - 凭据:Git 认证沿用目标机器已有 Git / SSH 配置,tmuxes 不保存凭据。若目标环境配置了缺失的
credential-managerhelper,fetch / pull / push 会临时禁用 credential helper 自动重试一次,避免 public / SSH 仓库被坏 helper 阻断。
🧩 目标(Targets)
本地 (Linux/macOS) —— 你机器上的 tmux。Windows 上不显示。
Windows 本机终端 (Windows) —— 服务端用 ConPTY 直接开 PowerShell / cmd 等本机 shell(自动探测
pwsh→powershell→cmd→ Git Bash),新建时可在下拉里选 shell。会话随服务端进程存活(刷新 / 重连 / 多标签都不丢,重启服务端会丢);这类会话没有 tmux 工作目录,故隐藏底部文件浏览器。WSL 发行版 (Windows) —— 通过
wsl.exe -l -q自动发现;每个发行版一个目标。发行版里必须装了 tmux。SSH 主机 —— 从你的
~/.ssh/config的Host条目里发现(跳过通配符)。也可显式添加:TMUXES_HOSTS="alice@web1,bob@db2:2222" npm run dev # Linux / macOS set TMUXES_HOSTS=alice@web1,bob@db2:2222 && npm run dev # Windows cmd密钥 / agent 认证必须在普通 shell 里已经能用。全新主机请先在普通终端里接受一次它的 host key。为避免短命管理命令反复新建 SSH 连接,类 Unix 平台会通过 OpenSSH
ControlMaster/ControlPersist长期复用同一条 SSH 连接;原生 Windows 则由 tmuxes 维护一条应用层 SSH 管理长连接,不使用 Windows OpenSSH mux socket,避免getsockname failed: Not a socket。tmuxes 不再强制设置ServerAliveInterval,如需保活请按所在平台规则写进你自己的~/.ssh/config。如果复用 / 管理连接中断,tmuxes 会自动重建并重试一次;仍失败时会在前端页面提示并暂停该 SSH 目标的自动轮询,点击Reconnect可手动再试一次。
💻 环境要求
所有平台都需要 Node 22.12+(项目版本文件固定为 22.22.2)和 npm 10+。其余:
- WSL2 且至少一个发行版,并在其中装好 tmux(
sudo apt install tmux)。 - 内置的 OpenSSH 客户端覆盖 SSH 目标。
- node-pty 提供预编译 Windows 二进制 —— 不需要编译器。
tmux在PATH上(brew install tmux)。- node-pty 提供预编译 darwin 二进制。
- 从访达启动却找不到 tmux?确保 Homebrew 的 bin 目录在 GUI 的
PATH里。
tmux,外加给 node-pty 的 C/C++ 工具链 + Python 3(没有 Linux 预编译 —— 安装时现场编译):sudo apt-get install -y build-essential python3 tmux- WSL 小坑:
node-gyp会用PATH上的任意python3。如果坏掉的 conda Python 把构建搞挂了:npm config set python /usr/bin/python3
在 Windows 上,你也可以把整个服务端跑在 WSL 内部(像 Linux 一样),然后在 Windows 上开浏览器 —— WSL2 会转发 localhost。一键启动脚本用的是「原生 Windows + wsl.exe」方案,这样能在一个地方同时覆盖 SSH 目标和多个发行版。
🔒 安全
⚠️ tmuxes 会把完整的 shell 访问权交给任何能连上它的人。 它是一个单用户、仅本机的开发工具。
设计上它:
- 只绑定
127.0.0.1—— 绑定地址在运行时不可配置, - 没有任何认证,
- 从不起 shell(argv 数组 +
shell:false),并对每个输入做白名单校验, - 拒绝
Origin非 localhost 的 WebSocket 升级(防 DNS-rebind), - 把文件浏览器 / 编辑器限制在所选 tmux 会话的当前工作目录之内。
请勿对它做反向代理、隧道、端口转发,或暴露到 0.0.0.0。机器上任何本地用户都能用它。
🧪 测试
npm test # vitest:输入校验、列表解析、ssh/tmux/wsl 的 argv 形状🐧 tmux 速查表
tmux 的「前缀键」默认是
Ctrl+b(下面记作C-b)—— 先按它,松开,再按后面的键。 在网页终端里最常用的是滚动 / 复制模式(往上看历史输出、复制文字)。
滚动 & 复制(最常用)
| 操作 | 按键 |
|---|---|
| 进入复制 / 滚动模式 | C-b 然后 [ |
| 在模式里上下翻 | ↑ ↓、PageUp / PageDown |
| 开始选择 → 复制 | Space 定起点 → 移动光标选中 → Enter 复制 |
| 把复制的内容粘回来 | C-b 然后 ] |
| 在模式里搜索 | C-s 向前 / C-r 向后(默认 emacs 风格) |
| 退出复制 / 滚动模式 | q |
| 开鼠标滚轮(直接滚轮翻 + 鼠标选) | 执行 tmux set -g mouse on,或写进 ~/.tmux.conf |
| 按住 Shift 用鼠标(绕过 tmux 鼠标模式) | 按住 Shift 拖动选中文字 → 浏览器右键「复制」;右键「粘贴」 |
提示:开了
mouse on后鼠标归 tmux 管;想用浏览器原生的框选 + 右键复制粘贴,按住Shift再拖动 / 右键即可。提示:在 tmuxes 里新建 / 选择 / 重命名 / 杀会话直接点 UI 就行,不用记命令;但往上滚看历史、复制文字、拆面板这些是 tmux 自己的功能,得用上面的快捷键。
❓ 常见问题
那台机器的登录 locale 不是 UTF-8(HPC 登录节点很常见,LANG=C / POSIX),于是 tmux 进入非 UTF-8 模式,把每个多字节字符用 _ 占位。在那台机器上修:
- 设一个 UTF-8 locale —— 先看哪些可用,再写进
~/.bashrc/~/.zshrc:locale -a | grep -i utf # 看有哪些(C.UTF-8 / en_US.UTF-8 / zh_CN.UTF-8 …) echo 'export LANG=C.UTF-8' >> ~/.bashrc # 换成上面真实存在的那个 - 重启该机器上的 tmux 服务,让会话以 UTF-8 重新创建:
tmux kill-server - 回到 tmuxes 重新连接 / 新建会话即可。
⚠️ pane 的 UTF-8 模式在创建时就定死了 —— 只改 locale 不重启 server 的话,已经变成下划线的旧会话不会自动恢复,必须重建。
📋 更新日志
0.1.14
- 恢复 Claude Code 决策提醒:0.1.13 误把 Claude Code 的审批、权限确认和用户决策请求一起移除。本版只针对 Codex 移除决策提醒,Claude Code 的
PermissionRequest、permission_prompt、elicitation_dialog重新触发「决策」badge、提示音和后台标签页闪烁。 - Codex 决策提醒保持移除:Codex 的审批 / 决策请求仍不触发浏览器提醒,避免
approvals_reviewer = "auto_review"/ Approve for me 自动审批流程误报。
0.1.13
- 移除决策提醒:Codex 的审批、权限确认和用户决策请求不再触发浏览器提醒;tmuxes 只提醒 agent 结束和异常停止,避免 Codex 自动审批流程误报。(注:0.1.13 同时误移除了 Claude Code 的决策提醒,已在 0.1.14 恢复。)
- Git 面板:侧边栏底部新增 Git 视图,支持当前会话工作目录的状态查看、未提交更改列表、文件 diff、分支切换、fetch、pull、push、sync,以及 stage 全部更改后创建 commit。
- 提交历史 / 远端提交:Git 面板会显示当前分支最近提交和 upstream 上尚未合入的远端提交,点击提交会在右侧大区域底部打开完整 patch;点击待提交文件会打开左右红绿 diff。
- credential-manager fallback:fetch / pull / push 遇到目标环境配置了缺失的
credential-managerhelper 时,会自动用临时禁用 credential helper 的方式重试一次,避免 public/SSH 仓库被错误 helper 阻断。
0.1.12
- Codex auto-review 提醒修复:Codex 开启
approvals_reviewer = "auto_review"/ Approve for me 时,审批请求会保持 running 状态,不再误触发决策badge、提示音或后台标签页闪烁;人工审批配置仍会正常提醒。
0.1.11
- 文档 / 发布规范:补齐 npm 发布检查流程,明确只发布
serverworkspace,发布前后都要验证npx/npm exec入口和本机启动 smoke test。 - 安全约束:发布流程不得提交或粘贴
.npmrctoken、NPM_TOKEN、SSH 私钥、一次性验证码或任何个人凭据。 - README 重整:安装说明加入
npx --help验证、Windows 排错提示,并压缩早期版本更新。
0.1.10
- 发布修正:重新发布 npm
latest包,确认线上tmuxesbin、前端public资源和npx tmuxes@latest入口可用。
0.1.9
- 修复: Windows SSH 原生管理命令改用应用层长连接。避免 Windows OpenSSH
ControlMastermux socket 的getsockname failed: Not a socket,同时避免短命管理命令反复新建 SSH 连接。 - 改进: 文件浏览器合并远端目录刷新。一次远端调用同时读取 pane 工作目录、校验路径并列目录,减少 SSH 管理流量。
0.1.0 - 0.1.8
- 早期功能成型:完成本地 / SSH / WSL / Windows shell 目标、tmux attach 多端同步、拖拽文件夹树、工作目录文件浏览与编辑。
- agent 提醒演进:从活动转静止提醒升级到 Claude Code / Codex 官方 lifecycle hooks,支持结束和异常停止状态。
- Windows / SSH 稳定性:修复 ConPTY 下
Ctrl+C退出、恢复浏览器原生右键,并将 SSH 管理命令改为长期复用连接且中断后只自动重试一次。
🧑🔬 关于作者
嗨,我是这个项目的作者 👋
中国科学技术大学(USTC)理论物理在读博士,白天的日常是和多体场论可解释的费米超流理论(这玩意是用来研究和解释高温超导的),还有一大坨高性能数值计算代码贴身肉搏 ⚛️。
这个小工具其实是被一堆 agent 终端搞到头大之后的「自救产物」—— 既然每天都要盯一群 CLI agent 干活,那干脆给它们造个顺手的指挥台 😎。
如果你也对这些感兴趣(物理也好、代码也好),或者想一起折腾这个开源项目,随时来找我玩 📮
