mcpField
P
pilotty

pilotty

github.com/msmpsAgent 工作流161111 次安装16 周前更新
代码仓库

关于 pilotty

pilotty 是用于 Agent 自动化终端 TUI 的命令行工具。它通过独立会话、屏幕快照和等待界面变化来检查并操作终端应用。

主要功能

  1. 01在 PTY 会话中启动应用
  2. 02管理多个隔离会话
  3. 03获取文本及结构化屏幕快照
  4. 04发送按键、文本和点击
  5. 05等待屏幕变化或稳定
  6. 06读取保留的终端输出

适用场景

  1. 01自动操作终端编辑器
  2. 02填写终端表单或对话框
  3. 03检查 htop 等终端界面
  4. 04与流式 AI TUI 交互

安装

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

$npx skills add https://github.com/msmps/pilotty --skill pilotty

安装后在 Claude Code 中输入/pilotty确认已加载。

包含的文件

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

references/
key-input.md
session-management.md
templates/
dialog-interaction.sh
multi-session.sh
vim-workflow.sh

详细介绍

使用 pilotty 实现终端自动化

重要:参数位置

所有标志(--name、-s、--format 等)都必须放在位置参数之前:

# CORRECT - flags before command/arguments
pilotty spawn --name myapp vim file.txt
pilotty key -s myapp Enter
pilotty snapshot -s myapp --format text

# WRONG - flags after command (they get passed to the app, not pilotty!)
pilotty spawn vim file.txt --name myapp   # FAILS: --name goes to vim
pilotty key Enter -s myapp                # FAILS: -s goes nowhere useful

这是导致 Agent 失败的头号原因。如有疑问,请记住:先写标志,再写命令/参数。


快速开始

pilotty spawn vim file.txt        # Start TUI app in managed session
pilotty wait-for "file.txt"       # Wait for app to be ready
pilotty snapshot                  # Get screen text, cursor, and dimensions
pilotty key i                     # Enter insert mode
pilotty type "Hello, World!"      # Type text
pilotty key Escape                # Exit insert mode
pilotty kill                      # End session

核心工作流

  1. 启动:pilotty spawn <command> 在后台 PTY 中启动应用
  2. 等待:pilotty wait-for <text> 确保应用已就绪
  3. 快照:pilotty snapshot 返回当前屏幕状态
  4. 理解:读取屏幕文本和光标位置
  5. 交互:使用键盘命令(key、type)或按坐标点击
  6. 重新获取快照:检查 content_hash,观察屏幕变化

命令

会话管理
pilotty spawn <command>           # Start TUI app (e.g., pilotty spawn htop)
pilotty spawn --name myapp <cmd>  # Start with custom session name (--name before command)
pilotty kill                      # Kill default session
pilotty kill -s myapp             # Kill specific session
pilotty list-sessions             # List all active sessions
pilotty daemon                    # Manually start daemon (usually auto-starts)
pilotty stop                      # Stop daemon and all sessions
pilotty examples                  # Show end-to-end workflow example
屏幕捕获
pilotty snapshot                  # Full JSON with text content and hash
pilotty snapshot --format compact # JSON without text field
pilotty snapshot --format text    # Plain text with cursor indicator
pilotty snapshot -s myapp         # Snapshot specific session

# Wait for screen to change (eliminates need for sleep!)
HASH=$(pilotty snapshot | jq '.content_hash')
pilotty key Enter
pilotty snapshot --await-change $HASH           # Block until screen changes
pilotty snapshot --await-change $HASH --settle 50  # Wait for 50ms stability
pilotty snapshot --settle 50 --strict           # Exit nonzero on deadline/exit
保留的输出
pilotty output                     # Readable rendered output history
pilotty output -s myapp            # Readable history for a named session
pilotty output -s myapp --ansi     # Exact retained ANSI/VT bytes

使用可读输出检查已离开可见视口的内容。只有在重放或诊断需要精确终端字节时,才使用 --ansi。

输入
pilotty type "hello"              # Type text at cursor
pilotty type -s myapp "text"      # Type in specific session

pilotty key Enter                 # Press Enter
pilotty key Ctrl+C                # Send interrupt
pilotty key Escape                # Send Escape
pilotty key Tab                   # Send Tab
pilotty key F1                    # Function key
pilotty key Alt+F                 # Alt combination
pilotty key Up                    # Arrow key
pilotty key -s myapp Ctrl+S       # Key in specific session

# Key sequences (space-separated, sent in order)
pilotty key "Ctrl+X m"            # Emacs chord: Ctrl+X then m
pilotty key "Escape : w q Enter"  # vim :wq sequence
pilotty key "a b c" --delay 50    # Send a, b, c with 50ms delay
pilotty key -s myapp "Tab Tab Enter"  # Sequence in specific session
交互
pilotty click 5 10                # Click at row 5, col 10
pilotty click -s myapp 10 20      # Click in specific session
pilotty scroll up                 # Scroll up 1 line
pilotty scroll down 5             # Scroll down 5 lines
pilotty scroll up 10 -s myapp     # Scroll in specific session
终端控制
pilotty resize 120 40             # Resize terminal to 120 cols x 40 rows
pilotty resize 80 24 -s myapp     # Resize specific session

pilotty wait-for "Ready"          # Wait for text to appear (30s default)
pilotty wait-for "Error" -r       # Wait for regex pattern
pilotty wait-for "Done" -t 5000   # Wait with 5s timeout
pilotty wait-for "~" -s editor    # Wait in specific session

全局选项

选项描述
-s, --session <name>指定目标会话(默认值:"default")
--format <fmt>快照格式:full、compact、text
-t, --timeout <ms>wait-for 和 await-change 的超时时间(默认值:30000)
-r, --regex将 wait-for 模式视为正则表达式
--name <name>spawn 命令的会话名称
--delay <ms>序列中按键之间的延迟(默认值:0,最大值:10000)
--await-change <hash>阻塞快照,直到 content_hash 发生变化
--settle <ms>等待屏幕稳定指定的毫秒数(默认值:0)
--strict捕获期限到达时退出码为 3,会话退出时退出码为 4
--ansi从 output 写入精确保留的 ANSI/VT 字节
环境变量
PILOTTY_SESSION="mysession"       # Default session name
PILOTTY_SOCKET_DIR="/tmp/pilotty" # Override socket directory
RUST_LOG="debug"                  # Enable debug logging

快照输出

snapshot 命令返回描述当前屏幕的结构化 JSON:

{
  "outcome": "immediate",
  "size": { "cols": 80, "rows": 24 },
  "cursor": { "row": 5, "col": 10, "visible": true },
  "text": "Settings:\n  [x] Notifications  [ ] Dark mode\n  [Save]  [Cancel]",
  "content_hash": 12345678901234567890
}

使用 --format text 获取带光标指示符的纯文本视图:

--- Terminal 80x24 | Cursor: (5, 10) ---
bash-3.2$ [_]

[_] 表示光标位置。使用文本内容理解屏幕状态,并通过键盘命令进行导航。

等待屏幕变化(推荐)

别再猜要休眠多久了! 使用 --await-change 等待屏幕实际更新:

# Capture baseline hash
HASH=$(pilotty snapshot | jq '.content_hash')

# Perform action
pilotty key Enter

# Wait for screen to change (blocks until hash differs)
pilotty snapshot --await-change $HASH

# Or wait for screen to stabilize (for apps that render progressively)
pilotty snapshot --await-change $HASH --settle 100

标志:

标志描述
--await-change <HASH>阻塞,直到 content_hash 与此值不同
--settle <MS>检测到变化后,等待屏幕稳定 MS 毫秒
-t, --timeout <MS>最大等待时间(默认值:30000)
--strict保留证据,但遇到 deadline 或 exited 时以非零状态退出

每个快照都会报告返回原因:

结果含义Agent 操作
immediate未请求等待读取当前屏幕
changed已满足 --await-change 条件继续查看新屏幕
settled已满足请求的稳定时间窗口将屏幕视为稳定
deadline时间已到;已包含最新证据检查证据;如有需要,可增加等待时间后重试
exited会话已结束;已包含最终证据不要再发送输入;检查退出元数据或输出

默认情况下,deadline 和 exited 结果仍以退出码 0 结束。只有当 shell 控制流需要因这些结果而失败时,才添加 --strict。

为什么这比 sleep 更好:

  • sleep 1 只是猜测:时间太短会导致竞态,太长则会拖慢自动化
  • --await-change 会按需精确等待,不多也不少
  • --settle 适用于渐进式渲染的应用(先显示部分内容,再显示完整内容)
等待流式 AI 响应

与会流式输出响应的 AI 驱动型 TUI(如 opencode 等)交互时,需要设置更长的 --settle 时间,因为屏幕会随着 token 到达而持续更新:

# 1. Capture hash before sending prompt
HASH=$(pilotty snapshot -s myapp | jq -r '.content_hash')

# 2. Type prompt and submit
pilotty type -s myapp "write me a poem about ai agents"
pilotty key -s myapp Enter

# 3. Wait for streaming response to complete
#    - Use longer settle (2-3s) since AI apps pause between chunks
#    - Extend timeout for long responses (60s+)
pilotty snapshot -s myapp --await-change "$HASH" --settle 3000 -t 60000

# 4. Response may be scrolled - scroll up if needed to see full output
pilotty scroll -s myapp up 10
pilotty snapshot -s myapp --format text

流式输出的关键参数:

  • --settle 2000-3000:AI 响应的各个片段之间会有停顿;等待 2-3 秒可确保流式输出确实已完成
  • -t 60000:将超时时间延长到默认的 30s 以上,以适应更长的生成过程
  • 每次屏幕变化都会重置等待计时器,因此它会自然地等待流式输出停止
手动检测变化

如需手动轮询(不推荐),请直接使用 content_hash:

# Get initial state
SNAP1=$(pilotty snapshot)
HASH1=$(echo "$SNAP1" | jq -r '.content_hash')

# Perform action
pilotty key Tab

# Check if screen changed
SNAP2=$(pilotty snapshot)
HASH2=$(echo "$SNAP2" | jq -r '.content_hash')

if [ "$HASH1" != "$HASH2" ]; then
  echo "Screen changed - inspect the new text"
fi

导航方式

pilotty 采用键盘优先的导航方式,就像人类一样:

# 1. Take snapshot to see the screen
pilotty snapshot --format text

# 2. Navigate using keyboard
pilotty key Tab           # Move to the next control
pilotty key Enter         # Activate/select
pilotty key Escape        # Cancel/back
pilotty key Up            # Move up in list/menu
pilotty key Space         # Toggle checkbox

# 3. Type text when needed
pilotty type "search term"
pilotty key Enter

# 4. Click at coordinates for mouse-enabled TUIs
pilotty click 5 10        # Click at row 5, col 10

关键要点:读取快照文本以了解屏幕内容,然后使用键盘命令进行导航。


示例:使用 vim 编辑文件

# 1. Spawn vim
pilotty spawn --name editor vim /tmp/hello.txt

# 2. Wait for vim to load and capture baseline hash
pilotty wait-for -s editor "hello.txt"
HASH=$(pilotty snapshot -s editor | jq '.content_hash')

# 3. Enter insert mode
pilotty key -s editor i

# 4. Type content
pilotty type -s editor "Hello from pilotty!"

# 5. Wait for screen to update, then exit (no sleep needed!)
pilotty snapshot -s editor --await-change $HASH --settle 50
pilotty key -s editor "Escape : w q Enter"

# 6. Verify session ended
pilotty list-sessions

也可以使用单独的按键:

pilotty key -s editor Escape
pilotty type -s editor ":wq"
pilotty key -s editor Enter

示例:与对话框清单交互

# 1. Spawn dialog checklist (--name before command)
pilotty spawn --name opts dialog --checklist "Select features:" 12 50 4 \
    "notifications" "Push notifications" on \
    "darkmode" "Dark mode theme" off \
    "autosave" "Auto-save documents" on \
    "telemetry" "Usage analytics" off

# 2. Wait for dialog to render (use await-change, not sleep!)
pilotty snapshot -s opts --settle 200  # Wait for initial render to stabilize

# 3. Inspect the screen and capture its hash
SNAP=$(pilotty snapshot -s opts)
echo "$SNAP" | jq -r '.text'
HASH=$(echo "$SNAP" | jq '.content_hash')

# 4. Navigate to "darkmode" and toggle it
pilotty key -s opts Down      # Move to second option
pilotty key -s opts Space     # Toggle it on

# 5. Wait for change and inspect the updated screen
pilotty snapshot -s opts --await-change $HASH | jq -r '.text'

# 6. Confirm selection
pilotty key -s opts Enter

# 7. Clean up
pilotty kill -s opts

示例:填写表单

# 1. Spawn a form application
pilotty spawn --name form my-form-app

# 2. Get snapshot to understand the visible form
pilotty snapshot -s form --format text

# 3. Tab to first input (likely already focused)
pilotty type -s form "myusername"

# 4. Tab to password field
pilotty key -s form Tab
pilotty type -s form "mypassword"

# 5. Tab to remember me and toggle
pilotty key -s form Tab
pilotty key -s form Space

# 6. Tab to Login and activate
pilotty key -s form Tab
pilotty key -s form Enter

# 7. Check result
pilotty snapshot -s form --format text

示例:使用 htop 监控

# 1. Spawn htop
pilotty spawn --name monitor htop

# 2. Wait for display
pilotty wait-for -s monitor "CPU"

# 3. Take snapshot to see current state
pilotty snapshot -s monitor --format text

# 4. Send commands
pilotty key -s monitor F9    # Kill menu
pilotty key -s monitor q     # Quit

# 5. Kill session
pilotty kill -s monitor

示例:与 AI TUI 交互(opencode 等)

AI 驱动型 TUI 会流式输出响应,因此需要特殊处理:

# 1. Spawn the AI app
pilotty spawn --name ai opencode

# 2. Wait for the prompt to be ready
pilotty wait-for -s ai "Ask anything" -t 15000

# 3. Capture baseline hash
HASH=$(pilotty snapshot -s ai | jq -r '.content_hash')

# 4. Type prompt and submit
pilotty type -s ai "explain the architecture of this codebase"
pilotty key -s ai Enter

# 5. Wait for streaming response to complete
#    - settle=3000: Wait 3s of no changes to ensure streaming is done
#    - timeout=60000: Allow up to 60s for long responses
pilotty snapshot -s ai --await-change "$HASH" --settle 3000 -t 60000 --format text

# 6. If response is long and scrolled, scroll up to see full output
pilotty scroll -s ai up 20
pilotty snapshot -s ai --format text

# 7. Clean up
pilotty kill -s ai

AI 应用的注意事项:

  • 使用 --settle 2000-3000,因为 AI 响应的各个片段之间会有停顿
  • 对于复杂提示词,使用 -t 60000 延长超时时间
  • 较长的响应可能会滚动终端内容;使用 scroll up 查看开头
  • 每次屏幕更新都会重置等待计时器,因此它会等待响应真正完成

会话

每个会话都彼此隔离,并拥有自己的:

  • PTY(伪终端)
  • 屏幕缓冲区
  • 子进程
# Run multiple apps (--name must come before the command)
pilotty spawn --name monitoring htop
pilotty spawn --name editor vim file.txt

# Target specific session
pilotty snapshot -s monitoring
pilotty key -s editor Ctrl+S

# List all
pilotty list-sessions

# Kill specific
pilotty kill -s editor

如果创建首个会话时没有指定 --name,该会话会自动命名为 default。

重要: --name 标志必须放在命令之前。命令之后的所有内容都会作为参数传递给该命令。

守护进程架构

pilotty 使用后台守护进程管理会话:

  • 自动启动:首次执行命令时启动守护进程
  • 自动停止:没有会话时,5 分钟后关闭
  • 最终证据:已退出的会话会保留其状态、最终屏幕和有界输出,最长 10 分钟
  • 共享状态:多个 CLI 调用共享会话

你很少需要手动管理守护进程。

错误处理

错误信息会包含可执行的建议:

退出码类别Agent 操作
0命令已完成检查快照中的 outcome;如果未使用 --strict,它可能是 deadline 或 exited
1通用/API 错误查看错误代码、消息和建议
2用法错误修正命令语法
3严格捕获超时检查打印出的证据;如有必要,增加等待时间后重试
4会话生命周期已结束不要向该会话重试输入;请使用 status、snapshot 或 output
{
  "code": "SESSION_NOT_FOUND",
  "message": "Session 'abc123' not found",
  "suggestion": "Run 'pilotty list-sessions' to see available sessions"
}
{
  "code": "SPAWN_FAILED",
  "message": "Failed to spawn process: command not found",
  "suggestion": "Check that the command exists and is in PATH"
}

常见模式

可靠的操作与等待(推荐)
# The pattern: capture hash, act, await change
HASH=$(pilotty snapshot | jq '.content_hash')
pilotty key Enter
pilotty snapshot --await-change $HASH --settle 50

# This replaces fragile patterns like:
# pilotty key Enter && sleep 1 && pilotty snapshot  # BAD: guessing
等待后再操作
pilotty spawn my-app
pilotty wait-for "Ready"    # Ensure app is ready
pilotty snapshot            # Then snapshot
操作前检查状态
pilotty snapshot --format text | grep "Error"  # Check for errors
pilotty key Enter                               # Then proceed
超时后重试
pilotty wait-for "Ready" -t 5000 || {
  pilotty snapshot --format text   # Check what's on screen
  # Adjust approach based on actual state
}

深入文档

有关详细模式和边缘情况,请参阅:

参考文档说明
references/session-management.md多会话模式、隔离和清理
references/key-input.md完整的按键组合参考

即用型模板

可执行的工作流脚本:

模板说明
templates/vim-workflow.sh使用 vim 编辑文件、保存并退出
templates/dialog-interaction.sh处理 dialog/whiptail 提示
templates/multi-session.sh并行编排 TUI

用法:

./templates/vim-workflow.sh /tmp/myfile.txt "File content here"
./templates/dialog-interaction.sh
./templates/multi-session.sh

评论

支持 Markdown