- AI 应用
- 人工智能
- AI Agent
- 本地部署
- 前端
- 后端
- 工作流自动化
【免费下载链接】ekko-studio
Ekko Studio is a local-first AI workspace for multi-agent chat, coding, and visual workflows, available on desktop and the web.
导读
本文讲解 Ekko Studio 内置于 Ekko Agent 运行时中的tmux技能(位于 packages/ekko-agent/skills/tmux/SKILL.md),它让 Agent 能够发现会话、捕获输出、发送按键与粘贴文本、轮询等待提示符,从而操控那些已经运行在 tmux 中、或需要持久终端的交互式 CLI 程序。读完本文,你将掌握 tmux 的session:window.pane寻址模型、安全的文本/按键注入方式、会话生命周期管理原则,以及随技能分发的两个辅助脚本的完整参数与用法,并能将这一套能力复用到自己的 Agent 技能设计中。
技能定位:何时该用 tmux,何时不该用
tmux 技能的元数据将其能力概括为:
Control tmux sessions and panes for interactive CLIs: discover sessions, capture output, send keys, paste text, and monitor prompts.
即面向交互式 CLI的会话/窗格控制。技能正文给出了一条明确的适用分界线:
- 使用 tmux 技能:处理那些已经运行在 tmux 中、或需要一个持久终端的交互式命令(例如长驻的 REPL、SSH 会话、需要等待用户输入或持续输出的程序);
- 使用普通终端执行:一次性命令(one-shot commands)。
这个分界在源码层面同样成立:Ekko Agent 提供了独立的terminal_exec工具(见 packages/ekko-agent/src/tools/terminal.ts),它通过spawn直接启动进程、等待退出并返回受限的输出预览,默认超时 30 秒(DEFAULT_TERMINAL_EXEC_MAX_OUTPUT_BYTES为 100 KB)。terminal_exec适合“跑完拿结果”的场景;而需要跨多次调用保持进程存活、与交互式程序对话时,才需要 tmux 作为“持久化终端层”。
前置条件与检查方式
技能要求在使用前先确认 tmux 已安装,且不得静默安装:
command -v tmux如果命令不存在,应当明确告知用户必须先安装 tmux,而不是自作主张去安装。这一“先检查、不越权”的原则贯穿整个技能设计:tmux 会话往往承载着真实的工作状态,Agent 的任何误操作都可能破坏用户正在运行的程序。
基础:会话、窗口、窗格与寻址模型
tmux 的层级结构是会话(session)→ 窗口(window)→ 窗格(pane)。技能中给出的基础命令:
tmux ls # 列出所有会话 tmux list-windows -t shared # 列出 shared 会话中的窗口 tmux list-panes -t shared:0 # 列出 shared 会话第 0 号窗口中的窗格 tmux capture-pane -t shared:0.0 -p # 捕获窗格当前可见内容到 stdout tmux capture-pane -t shared:0.0 -p -S - # 捕获包含完整回滚缓冲(scrollback)的内容目标(target)统一使用session:window.pane形式,例如shared:0.0表示shared会话的第 0 号窗口第 0 号窗格。-p让capture-pane把内容写到标准输出(而不是默认的粘贴缓冲区),便于 Agent 直接读取;-S -表示从回滚缓冲起点开始捕获(-S -即“全部历史”),这是查看长输出、判断程序是否已输出关键信息的基础手段。
发送输入:文本与按键分离
向目标窗格发送输入是操控交互式程序的核心操作。技能明确要求字面文本与 Enter 分开发送:
tmux send-keys -t shared:0.0 -l -- "Please continue" tmux send-keys -t shared:0.0 Enter-l(literal):把后面的参数当作字面文本逐字键入,不经过按键名解析;--:结束选项解析,防止以-开头的文本被误认为选项;Enter:单独作为按键名发送,触发回车。
特殊按键同样使用按键名发送:
tmux send-keys -t shared:0.0 C-c # 发送 Ctrl-C(中断当前程序) tmux send-keys -t shared:0.0 C-d # 发送 Ctrl-D(EOF) tmux send-keys -t shared:0.0 Escape # 发送 Esc技能同时给出了一条安全红线:
Use
-l --for arbitrary text. Never approve a confirmation prompt until its target and consequences are understood.
即:任意文本一律走-l --;在确认提示符(confirmation prompt)的目标和后果之前,绝不批准。这与 Ekko Agent 的审批体系是呼应的——破坏性、提权、远程 shell、发布类命令在执行前需要运行时授权(见 terminal.ts 中terminalExecDefinition的说明)。
会话管理:创建、重命名与销毁
tmux new-session -d -s worker # 后台新建名为 worker 的会话 tmux rename-session -t old new # 将 old 会话重命名为 new tmux kill-session -t worker # 销毁 worker 会话-d(detached)让新会话在后台创建而不附着,这对 Agent 特别重要——Agent 没有真正的终端可供附着。技能特别强调:
Killing a session is destructive. Do it only when the user requested that outcome or the session was created solely for the current task and is no longer needed.
销毁会话是破坏性操作,只有两种情况允许:用户明确要求,或该会话是本任务临时创建且已不再需要。这体现了“最小破坏、状态可恢复”的 Agent 操作伦理。
辅助脚本:发现会话与等待文本
技能的Helpers一节指出,skill_view会返回该技能的baseDirectory(即技能目录的绝对路径),基于它可以运行随技能分发的两个脚本。以下两个脚本正是仓库中 packages/ekko-agent/skills/tmux/scripts 目录下的真实文件。
find-sessions.sh:跨 socket 发现会话
<baseDirectory>/scripts/find-sessions.sh它的完整用法如下(脚本内置帮助文本,-h可查看):
Usage: find-sessions.sh [-L socket-name|-S socket-path|-A] [-q pattern] Options: -L, --socket 指定 tmux socket 名称(传给 tmux -L) -S, --socket-path 指定 tmux socket 路径(传给 tmux -S) -A, --all 扫描 TMUX_SOCKET_DIR 下的所有 socket -q, --query 大小写不敏感的子串过滤会话名 -h, --help 显示帮助关键实现点(find-sessions.sh):
- 默认使用 tmux 默认 socket;
-A会遍历${TMUX_SOCKET_DIR:-${TMPDIR:-/tmp}/tmux-sockets}目录下所有 socket 文件(跳过非 socket 文件)逐一列出会话; -L与-S互斥,-A不能与二者组合,参数冲突会报错退出;- 通过
tmux list-sessions -F '#{session_name}\t#{session_attached}\t#{session_created_string}'输出结构化信息,再格式化为- 名称 (attached/detached, started 创建时间)的可读列表; -q支持按会话名做大小写不敏感子串过滤;- 找不到服务器时输出
No tmux server found on ...并返回非零退出码,便于 Agent 判断该 socket 上确实没有运行中的 tmux 服务。
这解决了技能正文提到的“discover sessions, including custom socket paths”需求:多用户环境或 CI 中常通过-L/-S使用独立 socket 隔离会话,-A则适合整体盘点。
wait-for-text.sh:轮询窗格直到出现指定文本
<baseDirectory>/scripts/wait-for-text.sh -t shared:0.0 -p "pattern"完整参数(同样可通过-h查看):
Usage: wait-for-text.sh -t target -p pattern [options] Options: -t, --target tmux 目标(session:window.pane),必填 -p, --pattern 要查找的正则表达式,必填 -F, --fixed 将 pattern 视为固定字符串(关闭正则) -T, --timeout 等待秒数(整数,默认 15) -i, --interval 轮询间隔秒数(默认 0.5) -l, --lines 检查的历史行数(整数,默认 1000) -h, --help 显示帮助核心实现(wait-for-text.sh):
- 循环中执行
tmux capture-pane -p -J -t "$target" -S "-${lines}",-J保留行尾换行,-S -1000表示取最近 1000 行历史(含回滚缓冲); - 对捕获文本用
grep -E(正则,默认)或grep -F(-F固定字符串)匹配 pattern; - 匹配成功立即以退出码 0 结束;超过
-T指定的 deadline 则输出Timed out after ${timeout}s waiting for pattern: ...并把最后 N 行内容打印到 stderr 后以退出码 1 结束; -T、-l均校验必须为整数,-t/-p缺失时报错退出。
这个脚本把“等待交互式程序输出某个提示符/关键字”这一常见 Agent 动作封装成了可复用、可超时的原语,配合capture-pane -p的 stdout 输出能力,Agent 可以像“读文件”一样轮询终端状态。
源码视角:skill_view 与 baseDirectory 从何而来
skill_view是 Ekko Agent 的技能加载工具,其实现位于 packages/ekko-agent/src/tools/skills.ts 的SkillViewTool:
- 输入
name(精确技能名)与可选的filePath(支持文件路径,限定在references/、templates/、scripts/、assets/四个支持目录内,默认读取SKILL.md); - 返回结果中会注入
baseDirectory=${skill.directory},这正是技能正文所说的skill_view返回baseDirectory的实现来源;返回内容还包含技能名、字符数、sha256、来源(builtin/external/local)、启用状态与验证状态等元数据; - 技能正文要求“先
skill_view再操作”,与SkillManageTool的“同一次运行内必须先用skill_view读过目标文件才能修改”的约束(currentViewedContent的 read-mark 校验)互相印证。
此外,tmux是 Ekko Agent 的内置(bundled)技能:仓库测试 tests/ekko-agent/builtin-skills.test.ts 会校验packages/ekko-agent/skills目录下的全部内置技能(含tmux)都具备合法的 frontmatter(metadata.keywords为 1~8 个 ASCII 关键字),并会在每个 Profile 的技能目录(如default、work)中初始化生成对应的SKILL.md。技能发现、关键字匹配与注入逻辑也集中在 skills.ts 的discoverSkills/resolveSkillRouting中:技能名与 frontmatter 关键字是自动路由的唯一输入。
实操示例:一次完整的“持久终端交互”流程
将以上能力串起来,一个典型的 Agent 交互流程如下:
# 1. 检查 tmux 是否可用 command -v tmux # 2. 发现已有会话(含自定义 socket) <baseDirectory>/scripts/find-sessions.sh <baseDirectory>/scripts/find-sessions.sh -A # 3. 确认目标窗格(shared 会话第 0 窗口第 0 窗格) tmux list-panes -t shared:0 tmux capture-pane -t shared:0.0 -p -S - # 4. 向交互式程序发送文本并回车 tmux send-keys -t shared:0.0 -l -- "Please continue" tmux send-keys -t shared:0.0 Enter # 5. 等待程序输出包含 "done" 的提示(最多 30 秒) <baseDirectory>/scripts/wait-for-text.sh -t shared:0.0 -p "done" -T 30 # 6. 必要时发送中断键 tmux send-keys -t shared:0.0 C-c # 7. 任务结束且会话为本任务临时创建时,才销毁 tmux kill-session -t worker关键特性与注意事项
- 回滚缓冲读取:
capture-pane -p -S -可读取完整 scrollback,是检查长输出历史的主要手段;wait-for-text.sh默认检查最近 1000 行。 - 跨 SSH 断连持久:tmux 会话在 SSH 断开后依然存活,这正是 Agent 通过它托管交互式长任务的核心价值——即使发起方连接中断,远端程序也不会随之终止。
- 文本注入安全:任意文本必须用
-l --发送,避免按键名解析歧义;Enter、C-c、C-d、Escape等按键单独发送。 - 破坏性操作边界:
kill-session只在用户要求或会话确为本任务临时创建时才执行;确认提示符未经理解不得批准。 - 先检查后行动:tmux 缺失时只提示用户安装,不静默安装;socket 参数冲突、目标缺失等异常均会明确报错,便于 Agent 感知并纠正。
通过本技能与两个辅助脚本,Ekko Agent 可以在不依赖人机交互的前提下,可靠地发现、读取、注入并监控 tmux 中的交互式 CLI 程序;这一“技能 + 脚本 + 工具权限约束”的组合模式,也为在 Ekko Studio 中编写其他面向持久化运行环境的技能提供了可参考的范本。
- AI 应用
- 人工智能
- AI Agent
- 本地部署
- 前端
- 后端
- 工作流自动化
【免费下载链接】ekko-studio
Ekko Studio is a local-first AI workspace for multi-agent chat, coding, and visual workflows, available on desktop and the web.
相关推荐
Genkit Python Agent 会话与会话持久化(Session Store)实战指南
Genkit Python Agent 会话与会话持久化(Session Store)实战指南 导读 本文围绕 Genkit Python(Beta)Agent
AI 技能人工智能大模型ECC dmux Workflows 实战指南:基于 tmux 窗格的 AI Agent 多会话并行编排
ECC dmux Workflows 实战指南:基于 tmux 窗格的 AI Agent 多会话并行编排 在 ECC(agent harness perform
人工智能AI 技能AI 插件AI 评测Agent 评测MCP Clients开发工具在 nanobot 中用 tmux Skill 远程操控交互式终端:会话管理、安全输入与多 Agent 并行编排实战
在 nanobot 中用 tmux Skill 远程操控交互式终端:会话管理、安全输入与多 Agent 并行编排实战 导读 本篇文章基于 nanobot 内置的
人工智能AI AgentAgent 框架多智能体工具调用MCP Clients交互助手后端任务调度
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考