Ekko Agent tmux 技能实战:让 AI Agent 安全操控持久化终端会话与窗格
2026/9/23 21:38:41 网站建设 项目流程
  • 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.

项目地址:https://gitcode.com/gh_mirrors/he/ekko-studio
点击查看免费下载

导读

本文讲解 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 号窗格。-pcapture-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 的技能目录(如defaultwork)中初始化生成对应的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 --发送,避免按键名解析歧义;EnterC-cC-dEscape等按键单独发送。
  • 破坏性操作边界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.

项目地址:https://gitcode.com/gh_mirrors/he/ekko-studio
点击查看免费下载

相关推荐

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询