关于 pty-bridge
pty-bridge 是用于管理交互式终端会话的命令行工具,提供完整 PTY 支持,适合需要真实终端的命令和程序。它支持会话输入、输出读取、命令执行及所有权控制,并可在 macOS、Linux 和 Windows 上使用。
主要功能
- 01启动和管理 PTY 会话
- 02增量或按范围读取终端输出
- 03发送文本和特殊按键
- 04运行命令并等待完成
- 05跟踪会话所有权
适用场景
- 01交互使用 SSH 会话
- 02操作 REPL 和数据库命令行工具
- 03处理密码提示和 TUI 应用
- 04监控命令及服务输出
MCP 相关
输入将 pty-bridge 描述为管理终端会话的命令行工具和技能,未说明 MCP 接口。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ briqt/ pty-bridge --skill pty-bridge安装后在 Claude Code 中输入/pty-bridge确认已加载。
详细介绍
pty-bridge
pty-bridge 是一个 CLI,可管理具备完整 PTY 支持的交互式终端会话。当标准 Bash 工具无法处理交互式程序时,请使用它,例如 SSH、REPL、数据库 CLI、TUI 应用,或任何需要真实终端的命令。
本手册要求使用 pty-bridge 1.5.0+。技能文件与 CLI 分别安装:
pty-bridge --version
pty-bridge doctor --json # inspects an existing daemon; never starts one
npm i -g github:briqt/pty-bridge --install-links
npx skills add briqt/pty-bridge -g -y
doctor 会报告 CLI/Node 路径、原生 PTY 可用性、套接字以及正在运行的守护进程版本。安装新的 CLI 不会替换已有的守护进程或其会话。没有版本字段的旧版守护进程需要先停止运行,新的运行时功能才会生效。
设置
如果无法使用 pty-bridge,请从 GitHub 安装(而非 npm 注册表):
npm i -g github:briqt/pty-bridge --install-links
要求:Node.js 18+。支持 macOS、Linux 和 Windows。
适用场景
- 通过 SSH 登录远程服务
- 交互式 REPL(python、node、irb、psql、mysql 等)
- 会提示输入密码或进行确认的程序
- TUI 应用(htop、vim、less 等)
- 任何使用常规 Bash 工具时会挂起或行为异常的命令
隔离(必需)
同一 OS 用户下的所有 Agent 共用一个守护进程。除非用户要求接管,否则绝不从 list 中选择会话。
- 为此对话设置一个稳定的所有者,并在每次会修改状态的调用中传入该所有者(工具调用可能使用新的 shell):
export PTY_BRIDGE_OWNER="agent-$(uuidgen | cut -c1-8)" pty-bridge start ssh user@host --keepalive 30 --owner "$PTY_BRIDGE_OWNER" --json # Store sessionId and owner from the JSON response. pty-bridge exec <id> "pwd" --owner <stored-owner> --wait-exit - 仅使用
start返回的sessionId(--json)或Session: <id>。同时保存会话 ID 和所有者。 - 修改其他所有者的会话(
write/exec/sendkey/kill/resize)会被拒绝。仅当用户明确要求接管时才使用--force。 list会显示owner=,方便你查看哪些会话属于自己。
命令
pty-bridge [--timeout <ms>] <command> [options]
pty-bridge start <command> [args...] # Start a PTY session
pty-bridge read <id> [options] # Read output (see Read options)
pty-bridge write <id> <input> # Send input (or pipe via stdin)
pty-bridge exec <id> <command> [options] # Execute command and return new output
pty-bridge sendkey <id> <key> # Send special key
pty-bridge wait-for <id> <pattern> [--timeout <s>] # Block until pattern appears (default: 30s)
pty-bridge snapshot <id> # Capture current visible screen
pty-bridge list # Active sessions + lost-session tombstones
pty-bridge kill <id> # Terminate a session
pty-bridge resize <id> <cols> <rows> # Resize terminal (sends SIGWINCH to the child)
pty-bridge status # Daemon PID, memory, lost sessions
全局选项
pty-bridge --timeout 60000 exec <id> "slow-command" # Client RPC timeout in ms (must be BEFORE the subcommand)
使用 --rpc-timeout-ms 设置 RPC 时间预算(可放在子命令之前或之后);旧版 --timeout 仍可用,但 wait-for --timeout 表示秒。使用 exec --wait 设置命令等待时间预算。RPC 超时会自动延长至 max(30000, waitMs+5000)。
支持 read --help、exec --help 及其他子命令的帮助调用。
启动选项
pty-bridge start ssh user@host --keepalive 30 --owner "$PTY_BRIDGE_OWNER"
pty-bridge start cmd --wait 1000
pty-bridge start cmd --cols 200 --rows 50
读取选项
未知标志会报错(不会被忽略)。--full、--from、--from-exec 和 --last/--lines 不能同时使用。
pty-bridge read <id> # Incremental new output (advances cursor)
pty-bridge read <id> --full # Entire rendered buffer (does not advance cursor)
pty-bridge read <id> --from 12:40 # Rendered line 12, UTF-8 byte column 40
pty-bridge read <id> --from 12 # From line 12 (resume cursor from exec metadata)
pty-bridge read <id> --from-exec # From last exec start (after an RPC timeout)
pty-bridge read <id> --last 60 # Last 60 lines
pty-bridge read <id> --lines 60 # Alias of --last
pty-bridge read <id> --raw [--full] # Unwrapped PTY bytes (no xterm line wrapping)
pty-bridge read <id> --max-bytes 100000 # Truncate; 0 = unlimited (default 256000)
pty-bridge read <id> --buffer normal # normal | alternate | active (default)
snapshot 是当前的可见屏幕(cols×rows),而不是日志末尾。快照看起来为空通常表示屏幕已清除或处于替代屏幕模式——请使用 read --last 或 read --raw。
执行选项
pty-bridge exec <id> "ls -la" # wait 200ms, then return output so far --owner "$PTY_BRIDGE_OWNER"
pty-bridge exec <id> "make build" --wait-for-idle 500 # poll until output idle (max 5s unless --wait) --owner "$PTY_BRIDGE_OWNER"
pty-bridge exec <id> "make build" --wait-exit --wait 120000 # shell only: wait until command exits --owner "$PTY_BRIDGE_OWNER"
pty-bridge exec <id> "dmesg" --max-bytes 100000 --owner "$PTY_BRIDGE_OWNER"
--wait-exit 会追加一个哨兵(cmd; echo PTYBRIDGE_DONE_<token>:$?)。仅在 shell(bash/ssh)中使用。不要在 python/mysql/vim 中使用。
Wait-for 选项
pty-bridge wait-for <id> "Uvicorn running" --timeout 120
pty-bridge wait-for <id> "Started" --from-now --timeout 60 # ignore history
pty-bridge wait-for <id> "Started" --from 0 # full buffer (legacy)
默认搜索范围是最后 200 行加上新的输出,因此数小时前的旧 Started 不会匹配。
特殊按键
enter、tab、escape、space、backspace、delete、up、down、left、right、home、end、pageup、pagedown、ctrl-a 到 ctrl-z、ctrl-\、ctrl-]
工作流模式
SSH 会话(推荐)
export PTY_BRIDGE_OWNER="agent-<unique-conversation-id>"
# Retain this literal owner between tool calls, and pass it again each time.
pty-bridge start ssh user@host --keepalive 30 --owner "$PTY_BRIDGE_OWNER"
# If password / MFA prompt:
echo -n "password" | pty-bridge write <id> --stdin --owner "$PTY_BRIDGE_OWNER"
pty-bridge sendkey <id> enter --owner "$PTY_BRIDGE_OWNER"
pty-bridge read <id>
# Prefer --wait-exit for shell commands so you get done/failed + exitCode:
pty-bridge exec <id> "ls -la" --wait-exit --wait 15000 --owner "$PTY_BRIDGE_OWNER"
pty-bridge exec <id> "apt update" --wait-exit --wait 120000 --owner "$PTY_BRIDGE_OWNER"
pty-bridge exec <id> "exit" --wait-exit --wait 5000 --owner "$PTY_BRIDGE_OWNER"
等待服务启动
pty-bridge exec <id> "docker compose up -d" --wait-exit --wait 60000 --owner "$PTY_BRIDGE_OWNER"
pty-bridge exec <id> "docker logs -f myservice" --wait 1000 --owner "$PTY_BRIDGE_OWNER"
pty-bridge wait-for <id> "Uvicorn running" --from-now --timeout 120
交互式 REPL
pty-bridge start python3
pty-bridge exec <id> "print('hello')" # no --wait-exit (not a shell) --owner "$PTY_BRIDGE_OWNER"
pty-bridge sendkey <id> ctrl-d
输出格式约定
- stdout:PTY 内容
- stderr:一行元数据
[key=value ...],例如[status=still_running cursor=42 startCursor=10 alive=true truncated=false totalBytes=1200 returnedBytes=1200] status为done、still_running或failed。still_running不表示失败——命令已被接受。请勿重新发送。cursor是下一个--from值:渲染后的行或line:byte-column;使用--raw时,它是绝对 UTF-8 字节偏移量,缓冲区淘汰后仍保持稳定。- 原始输出中的
lostBytes>0表示较旧的输出已被淘汰;应报告缺失部分,而不是将输出视为完整。有限读取不会越过实际返回的字节。 - 如果
truncated=true,请使用read <id> --from <cursor>(或--from-exec)继续读取。 list/status可能会输出Warning: daemon restarted at <iso>, N session(s) lost。这些 PTY 已不存在;远程nohup任务可能仍在运行。请重新登录;不要根据list猜测其他 Agent 的会话。
错误恢复
| 症状 | 原因 | 操作 |
|---|---|---|
command not found: pty-bridge | 尚未安装 | npm i -g github:briqt/pty-bridge --install-links |
connect ENOENT 或守护进程启动错误 | 守护进程已退出 | pty-bridge status;下次执行 start 时会重新启动。检查 list 中是否有 lost 墓碑记录。 |
Session not found + lost 警告 | 守护进程重启并丢弃了内存中的会话 | 重新执行 start。不要复用旧 ID。 |
Session ... is owned by | 所有者不匹配 | 使用你自己的 ID;只有在被要求接管时才使用 --force |
RPC 超时 / status=still_running | 等待时限或 RPC 限制已触发;命令已经发送 | 不要再次执行。 使用 read <id> --from-exec 或 wait-for |
| SSH 密码提示 | 交互式身份验证 | 执行 write --stdin,然后执行 sendkey enter |
wait-for 超时 | 最近 200 行及新增输出中都没有匹配内容 | 使用 --from-now / --from 0;检查返回的输出 |
Cannot find module @lydell/node-pty-… | 没有预编译二进制文件 | linux/darwin/win32 × x64/arm64。使用 --install-links 重新安装 |
输出被换行(S\nYS) | xterm 按当前列数渲染 | 使用 read --raw(如果需要保持远程 TTY 不变,请勿执行 resize) |
| 未知选项 | 拼写错误 / 不支持的标志 | 不会忽略标志;请修正标志名称 |
重要说明
- 在 Shell 中,优先使用
--wait-exit,不要猜测--wait。对于 REPL/TUI,请使用不带--wait-exit的exec/write。 - 默认情况下,
read是增量读取。--full/--from/--last不会推进增量游标。 exec不会推进read游标。- 超时 ≠ 失败。由于
still_running或 RPC 超时,绝不要重新发送exec。 write会原样发送文本——之后使用sendkey enter(或exec/--wait-exit)。- 密钥:
echo -n "password" | pty-bridge write <id> --stdin --owner "$PTY_BRIDGE_OWNER" - 完成后,请终止自己的会话。没有存活会话时,守护进程会在 5 分钟后自动退出(正常退出会清除墓碑记录)。
- 通过 sendkey 发送
ctrl-c可中断卡住的命令。 - 终端默认尺寸为 120x40。
resize会更改子进程的 TTY 尺寸。 - 优先使用
--rpc-timeout-ms,以区分 RPC 超时(毫秒)与wait-for --timeout(秒)。 - 默认的 read/exec 负载上限为 256000 字节;元数据会告知是否还有更多内容。
机器可读会话与筛选
pty-bridge start bash --owner <conversation-owner> --json
pty-bridge list --owner <conversation-owner> --alive-only --json
pty-bridge exec <id> "pwd" --owner <conversation-owner> --wait-exit
pty-bridge kill <id> --owner <conversation-owner>
筛选后的列表并不授权你接管任何会话。请保留自己执行 start 时响应中的 ID 和所有者。
snapshot 会显示屏幕;要查看日志末尾,请使用 read --last 30。
对于脚本、大型导出或通过 SSH 传输文件,优先使用文件/SFTP 通道,而不是通过 PTY 传输 base64。RPC 超时意味着已提交的命令可能仍在运行:应通过读取继续查看,而不要再次提交命令。