mcpField
P
pilotty

pilotty

github.com/msmpsエージェントワークフロー161111 回インストール16 週間前に更新
リポジトリ

pilotty について

pilottyは、エージェントによるターミナルTUI操作のためのコマンドラインツールです。独立したセッション、画面スナップショット、変化検知を使ってアプリを確認・操作できます。

主な機能

  1. 01PTYセッションでアプリを起動
  2. 02独立したセッションの管理
  3. 03テキストと構造化スナップショットの取得
  4. 04キー、テキスト、クリックの送信
  5. 05画面の変化や安定を待機
  6. 06保持されたターミナル出力の読み取り

活用シーン

  1. 01ターミナルエディターの自動操作
  2. 02ターミナルのフォームやダイアログ入力
  3. 03htopなどの画面の確認
  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

エージェントの失敗の原因で最も多いのはこれです。迷った場合は、フラグを先に、その後にコマンド/引数を指定してください。


クイックスタート

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, --regexwait-for のパターンを正規表現として扱います
--name <name>spawn コマンドのセッション名
--delay <ms>シーケンス内のキー入力間の遅延(デフォルト:0、最大:10000)
--await-change <hash>content_hash が変わるまでスナップショットを待機します
--settle <ms>画面が安定するまで、このミリ秒数だけ待機します(デフォルト:0)
--strictキャプチャ期限に達した場合は 3、セッションが終了した場合は 4 で終了します
--ansioutput から保持された 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 の場合はゼロ以外の終了コードで終了します

各スナップショットには、返された理由が報告されます。

結果意味エージェントの動作
immediate待機は要求されていません現在の画面を確認します
changed--await-change の条件が満たされました新しい画面を確認します
settled要求された安定時間が経過しました画面が安定したものとして扱います
deadline時間切れです。最新の証拠が含まれています証拠を確認し、有用であれば待機時間を延ばして再試行します
exitedセッションが終了しました。最終的な証拠が含まれていますこれ以上入力を送らず、終了メタデータまたは出力を確認します

期限切れと終了の結果でも、デフォルトでは終了コード 0 で終了します。シェルの制御フローでこれらの結果を失敗として扱う場合にのみ、--strict を追加してください。

sleep より優れている理由:

  • sleep 1 は推測です。短すぎると競合状態が発生し、長すぎると自動化が遅くなります
  • --await-change は必要な時間だけ正確に待機します。長すぎることも短すぎることもありません
  • --settle は段階的に描画されるアプリ(一部を表示してから全体を表示するアプリ)に対応します
ストリーミング AI 応答を待つ

応答をストリーミングする AI 搭載 TUI(opencode など)とやり取りする場合、トークンが届くたびに画面が更新されるため、より長い --settle 時間が必要です。

# 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:生成に時間がかかる場合に備えて、デフォルトの 30 秒より長くタイムアウトを設定します
  • --settle タイマーは画面が更新されるたびにリセットされるため、ストリーミングが止まるまで自然に待機します
手動で変更を検出する

手動でポーリングする場合(推奨されません)は、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 アプリを使用する際の注意点:

  • AI の応答ではチャンク間に間が空くため、--settle 2000-3000 を使用します
  • 複雑なプロンプトには、-t 60000 でタイムアウトを延長します
  • 長い応答では端末がスクロールする場合があります。冒頭を確認するには scroll up を使用します
  • --settle タイマーは画面が更新されるたびにリセットされるため、実際に完了するまで待機します

セッション

各セッションは、以下を備えた独立した環境です。

  • 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 呼び出しでセッションを共有します

デーモンを手動で管理する必要はほとんどありません。

エラー処理

エラーには、実行可能な提案が含まれます。

終了コードカテゴリーエージェントの対応
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.shvim でファイルを編集し、保存して終了する
templates/dialog-interaction.shダイアログ/whiptail のプロンプトを処理する
templates/multi-session.shTUI を並行してオーケストレーションする

使用方法:

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

コメント