mcpField
S
skill-system-tmux

skill-system-tmux

github.com/arthur0824haoAgent 工作流44 次安装
代码仓库

关于 skill-system-tmux

为使用 shell 的 Agent 提供命令路由与 tmux 会话管理规范,判断命令应直接运行还是放入 tmux。适用于需要持久运行、交互终端或超时风险的任务,并强调会话命名和清理。

主要功能

  1. 01根据耗时和交互性选择执行方式
  2. 02按约定命名 tmux 会话
  3. 03启动、复用和关闭持久会话
  4. 04捕获输出并检查任务就绪状态
  5. 05清理 Agent 会话与残留进程

适用场景

  1. 01在后台运行长时间构建或安装命令
  2. 02保持开发服务器在工具调用间持续运行
  3. 03通过 SSH 执行可承受连接中断的任务
  4. 04并行运行隔离的 Agent 或测试套件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/arthur0824hao/skills --skill skill-system-tmux

安装后在 Claude Code 中输入/skill-system-tmux确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

SKILL.behavior.yaml
SKILL.spec.yaml
scripts/
test_tmux_tool.py
tmux_tool.py

详细介绍

Skill System Tmux

当 shell 命令可能超时、需要持久运行或需要交互式终端访问时,通过 tmux 执行。本技能提供决策启发式和会话管理约定,而非 tmux 教程。

决策矩阵

使用此矩阵决定使用直接 bash还是 tmux。

条件执行方式示例
预计耗时 > 60stmuxgit clone <large>、npm install、docker build、训练脚本
命令不会自行终止tmuxnpm run dev、python app.py、jupyter notebook
需要 TUI 或交互式输入tmuxvim、htop、pudb、claude
需要并行隔离执行tmux多个 Agent、并发测试套件
通过 SSH 远程执行tmux必须在连接断开后继续运行的命令
原子、非交互且快速(<30s)直接 bashls、grep、git status、cat、mkdir
单次执行且预期会有输出直接 bashpython script.py(快速)、git diff、npm test(短时)

默认:直接 bash。 只有满足上述条件时才使用 tmux。

耗时估算启发式

可能超过超时时间的命令:

  • Git 操作:clone(大型仓库)、push(大型载荷)、checkout(工作树 >1GB)
  • 安装软件包:npm install、pip install(依赖项很多)、cargo build
  • 构建工具:docker build、make(大型项目)、webpack(生产构建)
  • 数据处理:训练脚本、预处理流水线、大型文件传输
  • CI/测试套件:大型项目的完整测试运行

会话命名约定

使用包含项目上下文的名称,便于阅读:

Format: {project}-{purpose}

Agent-created sessions (MANDATORY prefix):
  oc-{purpose}        # e.g., oc-audit, oc-verify, oc-render
  oc-{project}-{task}  # e.g., oc-skills-build, oc-subproject-test

User/infra sessions (no prefix required):
  postgres-dev
  frontend-watch
  ml-training

规则:

  • 由 Agent 创建的会话必须使用 oc- 前缀——便于批量识别和清理
  • 使用小写字母,以连字符分隔(不要使用下划线)
  • 在多项目环境中包含项目上下文
  • 如果已有常用的 oc- 会话名称,则重复使用(例如 oc-exp-runner)
  • 如果继承了一个没有此前缀的旧 Agent 会话,在重新使用前将其重命名为 oc-*
  • 切勿创建仅由数字组成的会话名称(例如 531)

核心模式

模式 1:启动后不管(后台任务)

适用于不需要实时输出的长时间运行命令:

# Kill any existing session with same name, then start fresh
tmux kill-session -t {session} 2>/dev/null || true
tmux new-session -d -s {session} bash -c '{command}'

使用 interactive_bash 工具:

tmux_command: new-session -d -s {session}
tmux_command: send-keys -t {session} "{command}" Enter
模式 2:持久服务

适用于开发服务或必须持续运行的进程:

tmux_command: new-session -d -s {session}
tmux_command: send-keys -t {session} "{command}" Enter

稍后检查是否仍在运行:

tmux_command: has-session -t {session}
模式 3:捕获输出

读取 tmux 会话产生的内容:

tmux_command: capture-pane -p -t {session}

查看更长的历史记录(最近 1000 行):

tmux_command: capture-pane -p -t {session} -S -1000
模式 4:就绪状态检测

发送命令后,轮询以检测命令是否完成:

  1. 捕获窗格输出
  2. 查找输出末尾的 shell 提示符(正则表达式:/(\\$|>|#)\s*$/m)
  3. 如果出现提示符,则命令已完成
  4. 如果预期时长过后仍未出现提示符,则认为命令仍在运行或已挂起
模式 5:干净关闭

完成后务必清理会话:

tmux_command: kill-session -t {session}

先终止再新建模式可防止产生僵尸会话:

tmux_command: kill-session -t {session}
# (ignore error if doesn't exist)
tmux_command: new-session -d -s {session}
模式 6:批量回收资源

回收所有由 Agent 创建的会话,并检测过期资源。在以下情况下执行此操作:

  • 机器运行迟缓或内存占用较高时
  • Agent 长时间工作会话开始前或结束后
  • 用户要求清理时

步骤 1:识别 Agent 会话

tmux list-sessions -F '#{session_name} #{session_activity}' | grep '^oc-'

步骤 2:终止所有 Agent 会话

tmux list-sessions -F '#{session_name}' | grep '^oc-' | xargs -I{} tmux kill-session -t {}

步骤 3:检测过期的非 Agent 会话

以下情况表明会话可能已过期:

  • 上次活动时间超过 6 小时,且没有正在运行的前台进程
  • 会话只有一个空闲的 shell 提示符(capture-pane 只显示 $ 或 ╰─)
# List sessions with last activity timestamp
tmux list-sessions -F '#{session_name} #{session_activity}'
# Compare #{session_activity} (epoch) against current time
# Capture pane of suspects to verify idle state

步骤 4:回收孤立进程

# Find opencode processes whose parent tmux pane was killed
ps aux | grep opencode | grep -v grep
# Check if port is held by a zombie
lsof -i :{port} 2>/dev/null
# Force kill if needed (SIGTERM first, SIGKILL if unresponsive after 5s)
kill {pid} && sleep 5 && kill -0 {pid} 2>/dev/null && kill -9 {pid}

重要:未经用户明确确认,切勿终止已知的非 Agent 基础设施会话。来自同级项目的旧会话名称应先规范为 oc-*,然后再将其视为由 Agent 管理的会话。

与 Agent 工具集成

interactive_bash 工具

主要接口。直接传递 tmux 子命令(不带 tmux 前缀):

# Create session
tmux_command: new-session -d -s oc-my-session

# Send command
tmux_command: send-keys -t oc-my-session "npm run dev" Enter

# Read output
tmux_command: capture-pane -p -t oc-my-session

# Kill session
tmux_command: kill-session -t oc-my-session
带超时的 bash 工具

对于接近超时边界的命令,优先增加 timeout 参数,而不是使用 tmux:

bash(command="npm install", timeout=300000)  # 5 min timeout

仅在以下情况使用 tmux:

  • 无法可靠估算超时时间
  • 进程必须在当前工具调用结束后继续运行
  • 需要交互式/TUI 访问

已知错误与解决方法

interactive_bash 中的 capture-pane 被阻止

错误:'capture-pane' is blocked in interactive_bash

这是最常见的 tmux 错误。interactive_bash 工具会阻止某些 tmux 子命令(包括 capture-pane、pipe-pane、save-buffer)。执行这些操作时,始终改用 Bash 工具。

# WRONG — will be blocked:
# interactive_bash: tmux_command: capture-pane -p -t oc-dev-server

# CORRECT — use Bash tool:
tmux capture-pane -p -t oc-dev-server

# Capture with history (last 1000 lines):
tmux capture-pane -p -t oc-dev-server -S -1000

# Capture and grep for specific output:
tmux capture-pane -p -t oc-dev-server | grep -i "error\|ready\|listening"

规则:对于任何 tmux 只读操作(capture-pane、list-sessions、display-message、show-options),优先使用 Bash 工具。将 interactive_bash 留给修改操作(send-keys、new-session、kill-session)。

杀掉并重新创建后出现 session not found

错误:can't find session: oc-xxx

在先杀掉再新建的操作发生竞争时常会出现此问题。添加一个简短的保护措施:

tmux kill-session -t oc-build 2>/dev/null || true
tmux new-session -d -s oc-build bash -c 'make all'
使用 new-session 时出现 duplicate session

错误:duplicate session: oc-xxx

该会话已存在。可以复用该会话,或先杀掉再新建:

# Reuse (send new command to existing session):
tmux send-keys -t oc-build "make clean && make all" Enter

# Or kill and recreate:
tmux kill-session -t oc-build 2>/dev/null || true
tmux new-session -d -s oc-build bash -c 'make all'
出现 no server running / tmux 未启动

错误:no server running on /tmp/tmux-*/default

tmux 服务未运行。任何 new-session 命令都会自动启动它:

tmux new-session -d -s oc-init echo "tmux ready"
工具选择速查
tmux 子命令使用 interactive_bash?使用 Bash 工具?
new-session是是
send-keys是(优先)是
kill-session是是
capture-pane否 — 已阻止是(必须)
list-sessions避免使用是(优先)
has-session是是
pipe-pane否 — 已阻止是(必须)
display-message避免使用是(优先)

反模式

不要这样做应改为
通过 tmux 路由所有命令对快速、原子操作直接使用 bash
忘记在使用后杀掉会话始终使用 kill-session 清理
使用 s1 这类通用会话名称使用描述性名称:oc-project-purpose
创建没有 oc- 前缀的 Agent 会话始终添加前缀:oc-audit、oc-verify、oc-build
以紧密循环轮询 capture-pane每次轮询间隔 1-2 秒
不杀掉旧会话就启动新会话相同会话名称始终先杀掉再新建
未先清除当前行就发送命令如果当前行可能残留输入,发送命令前先发送 C-u
任务完成后仍让会话继续运行在会话结束时运行批量回收(模式 6)
使用 interactive_bash 执行 capture-pane执行 capture-pane 时始终使用 Bash 工具
在 interactive_bash 中重试被阻止的命令立即切换到 Bash 工具

现有项目约定

此技能系统的同级项目可能包含较旧的 tmux 命名模式,但此仓库中由 Agent 管理的会话必须统一为 oc-*。

  • 会话名称 oc-exp-runner:实验执行时优先使用的 Agent 自有名称
  • 监视器会话:通过 tmux send-keys 唤醒 Agent 的后台监视器
  • machines.json 配置:tmux_session 字段定义每台机器的会话名称
  • 先杀掉再新建:所有实验脚本中使用的标准清理模式

在具有现有 tmux 约定的项目中工作时,保留真正由用户/基础设施管理的会话,但在继续操作前,将继承的 Agent 会话重命名为 oc-* 格式。

{
  "schema_version": "2.0",
  "id": "skill-system-tmux",
  "version": "1.0.0",
  "capabilities": ["tmux-session-start", "tmux-capture", "tmux-wait", "tmux-session-list", "tmux-session-kill"],
  "effects": ["proc.exec"],
  "operations": {
    "start-session": {
      "description": "Start a long-running command in a managed tmux session.",
      "input": {
        "name": { "type": "string", "required": true, "description": "Logical session name" },
        "command": { "type": "string", "required": true, "description": "Command to execute inside tmux" }
      },
      "output": {
        "description": "Started session metadata",
        "fields": { "status": "string", "session_name": "string" }
      },
      "entrypoints": {
        "unix": ["python3", "{skill_dir}/scripts/tmux_tool.py", "start-session", "{name}", "{command}"]
      }
    },
    "capture-pane": {
      "description": "Capture output from a managed tmux session.",
      "input": {
        "session_name": { "type": "string", "required": true, "description": "Target session name" },
        "lines": { "type": "integer", "required": false, "description": "Number of lines to capture" }
      },
      "output": {
        "description": "Captured output",
        "fields": { "status": "string", "output": "string" }
      },
      "entrypoints": {
        "unix": ["python3", "{skill_dir}/scripts/tmux_tool.py", "capture-pane", "{session_name}"]
      }
    },
    "wait-completion": {
      "description": "Poll a managed tmux session until completion.",
      "input": {
        "session_name": { "type": "string", "required": true, "description": "Target session name" },
        "timeout_seconds": { "type": "integer", "required": false, "description": "Maximum wait time" }
      },
      "output": {
        "description": "Completion result and final output",
        "fields": { "status": "string", "completed": "boolean", "output": "string" }
      },
      "entrypoints": {
        "unix": ["python3", "{skill_dir}/scripts/tmux_tool.py", "wait-completion", "{session_name}"]
      }
    },
    "list-sessions": {
      "description": "List managed tmux sessions.",
      "input": {},
      "output": {
        "description": "Managed session rows",
        "fields": { "status": "string", "sessions": "array" }
      },
      "entrypoints": {
        "unix": ["python3", "{skill_dir}/scripts/tmux_tool.py", "list-sessions"]
      }
    },
    "kill-session": {
      "description": "Kill a managed tmux session.",
      "input": {
        "session_name": { "type": "string", "required": true, "description": "Target session name" }
      },
      "output": {
        "description": "Kill result",
        "fields": { "status": "string", "session_name": "string" }
      },
      "entrypoints": {
        "unix": ["python3", "{skill_dir}/scripts/tmux_tool.py", "kill-session", "{session_name}"]
      }
    }
  },
  "stdout_contract": {
    "last_line_json": false,
    "note": "Agent-executed; uses interactive_bash tool for tmux operations."
  }
}

评论

支持 Markdown