# TUI キーバインド `crates/tui` の対話画面で効くキー一覧。`crates/tui/src/main.rs:handle_key` を単一情報源とし、このドキュメントは人間向けの目次。 ## 入力編集 | キー | 動作 | |---|---| | 文字キー | カーソル位置に挿入(未割り当ての `Ctrl`+文字キーは無視) | | `Ctrl-A` | 入力欄全体の先頭へ | | `Backspace` | カーソル直前を削除(ペーストプレースホルダは 1 回で全削除) | | `Delete` | カーソル直後を削除(同上) | | `Left` / `Right` | カーソル移動 | | `Up` / `Down` | 通常は論理行単位の上下移動。入力欄の先頭/末尾では送信済み composer history を browse | | `Home` / `End` | 現在行の行頭 / 行末へ | | `Alt-Enter` | 改行を挿入(Input を複数行化) | | `Esc` | completion popup があれば閉じる | ### ペーストプレースホルダ ブラケットペーストで入力されたテキストは入力バッファ上では不可分な プレースホルダ `[Clipboard #N | X chars, Y lines]` として表示される。 実テキストは裏で保持され、送信時に `#N` ラベル無しで展開されて Pod に渡る。 カーソルはプレースホルダ内部には入れず、`Backspace` / `Delete` 1 回で プレースホルダ全体が消える。`#N` の通し番号は TUI プロセス起動中で連番。 ### Completion `@` file ref / `#` knowledge ref / `/` workflow invocation などは completion popup を開く。 | キー | 動作 | |---|---| | `Up` / `Down` | completion 候補を移動 | | `Tab` | 選択候補をテキストとして適用 | | `Enter` | committable な候補は chip 化して空白を追加。directory などはテキスト適用して drill-in | | `Esc` | popup を閉じる | | 空白文字 | exact match なら chip 化してから空白を挿入 | ## 送信(Enter) | 状態 | 入力あり | 入力空 | |---|---|---| | Idle | `Method::Run` で新ターン開始 | no-op | | Paused | `Method::Run`(前ターンは割り込み終了として扱い、新ターンとして開始) | `Method::Resume`(前ターンの続きを再開) | | Running | 入力は TUI 側 queue に積まれ、現在 turn の終了後に自動送信 | no-op | ### Running 中の queue Running 中に入力ありで Enter すると、現在の provider stream には割り込まず、typed input segments を TUI-local queue に積む。`RunResult::Finished` / `LimitReached` 後に先頭の queued input が次の `Method::Run` として自動送信される。`Paused` / `RolledBack` では自動送信しない。 | キー | 動作 | |---|---| | `Alt-Q` | queue 先頭を composer に戻す(composer が空の時のみ) | | `Alt-C` | queued input を全消去 | ### Paused からの挙動 Paused 中に Enter すると、入力の有無で 2 通り: - **空**: 前ターンを中断した地点から **Resume**。LLM はそのまま続きを書く(partial text は破棄済み)、未実行の tool があれば実行して続行 - **入力あり**: 前ターンは「割り込み終了」扱いとなり、新ターンとして **Run**。Pod 側では 1. 未応答 `tool_use` があれば synthetic `tool_result("[Interrupted by user]")` で閉じる 2. `[The previous turn was interrupted by the user]` system note を履歴に挿入 3. 入力を新しい user メッセージとして append 4. ターン開始 ## Command mode composer が空の通常入力で `:` を押すと command mode に入る。command mode 中は composer が command line として扱われる。 | キー | 動作 | |---|---| | `Enter` | command を実行 | | `Esc` | command mode を終了 | | `Backspace` | 文字を削除。空なら command mode を終了 | | `Ctrl-U` | command input をクリア | | `Tab` | command completion を適用 | | `Up` / `Down` | command completion 候補があれば移動、なければカーソル上下 | 主な command は `:help`, `:noop`, `:compact`, `:rewind` / `:rollback`。`:compact` は idle 時だけ即時 compaction を要求し、`:rewind` / `:rollback` は rewind target picker を開く。 ## 履歴ビューのナビゲーション 履歴ビューは全画面 TUI の上段にあり、TUI 内部で全ブロックを state として 保持してスクロール可能。スクロールバック(端末側の履歴)ではなく TUI の 自前バッファを動かす点に注意。 | キー / 操作 | 動作 | |---|---| | `Shift-Up` / `Shift-Down` | 1 論理行スクロール | | mouse wheel | 数行単位でスクロール | | `PageUp` / `PageDown` | 1 ページスクロール(task pane が開いている時は task pane をスクロール) | | `Ctrl-[` / `Ctrl-]` | 前 / 次のターン先頭へジャンプ | | `Ctrl-Home` | 履歴の先頭へ | | `Ctrl-End` | 履歴の末尾へ(末尾追従モードを再開) | ### 末尾追従 デフォルトは「末尾追従」モード:新しいイベント到着で自動的に最新行が 画面下に固定される。ユーザーが上方向にスクロールした瞬間に追従は解除され、 その位置で固定される(新着イベントが来ても画面は動かない)。再び追従に 戻すには `Ctrl-End`。追従解除中はステータスバー右に `↑ scrolled` が点く。 ### ターン単位ジャンプ `Ctrl-[` / `Ctrl-]` は TurnHeader ブロックの位置にスクロールオフセットを 合わせる。多数のツール呼び出しが挟まった長いターンでも前後ターンの先頭に 1 発で戻れる。末尾ターンから `Ctrl-]` を押すと末尾追従に復帰する。 ## 表示モード / 補助 pane 履歴各ブロックの密度を 3 段階で切り替える。現在のモードはステータスバー 右端に `[mode]` として表示される。 | キー | 動作 | |---|---| | `Ctrl-O` | `detail` → `normal` → `overview` → `detail` の順に循環 | | `Ctrl-T` | task pane を開閉 | - **detail**: 全ブロック完全表示。ツールブロックは結果本体も全量 - **normal**: 完了ブロックは概ね 5–6 行に圧縮、実行中のツールブロックは detail と同じ扱い - **overview**: 各ブロック 1 行に畳む(ツールブロックは `ToolResult.summary` 1 行、長文 AssistantText は先頭 1 行 + 省略記) モード切替は全体に一括適用。個別ブロックの開閉は持たない。 ## Pod 制御 | キー | Running 中 | Idle / Paused | |---|---|---| | `Ctrl-X` | queued input を消去して `Method::Cancel`(進行中ターンを破棄 → Idle) | `Method::Shutdown`(Pod を終了) | | `Ctrl-C` | `Method::Pause`(進行中ターンを中断 → Paused) | 1 回目 warn、3 秒以内の 2 回目で TUI 終了(Pod は残る) | | `Ctrl-D` | TUI 終了(Pod は残る、Pause しない) | TUI 終了(Pod は残る) | | `Ctrl-R` | rewind picker 要求は拒否される | rewind target picker を開く | ### Cancel と Pause の違い - **Cancel** は「ターンを捨てる」: 進行中の LLM リクエスト・未完了 tool を打ち切り、状態は Idle。続きは Resume できない - **Pause** は「止めるけど続けられるように」: 同じく打ち切るが状態は Paused、空 Enter で Resume 可能 Running 中に割り込みたい場合、ほとんどのケースで `Ctrl-C`(Pause)が自然。Ctrl-X(Cancel)は明示的に破棄したい時(LLM が暴走した時など)用。Pod を終了したい場合は、先に Running ではない状態(Idle / Paused)にしてから `Ctrl-X` で Shutdown する。 ### Rewind picker `Ctrl-R` または `:rewind` / `:rollback` で Pod に `Method::ListRewindTargets` を送り、main area に rewind target picker を開く。picker 中の操作は以下。 | キー | 動作 | |---|---| | `Up` / `Down` | target を移動 | | `Enter` | 選択 target へ `Method::RewindTo`。復元された user input は composer に戻る | | `Esc` | picker を閉じる | Running 中の rewind request は拒否される。Paused 中は picker を開けるが、実際の apply は idle で composer が空の時だけ行う。 ### Ctrl-C と Ctrl-D の終了 UX - Ctrl-X Running 中: queued input を消去して `Method::Cancel`。終了したい場合は、明示的にターンを止めて Idle に戻してからもう一度 `Ctrl-X` - Ctrl-X Idle / Paused: `Method::Shutdown` を送って Pod を終了 - Ctrl-C Running 中: 1 回目で即 Pause(破壊的ではない) - Ctrl-C Idle / Paused: 1 回目で warn メッセージ、3 秒以内の 2 回目で TUI 終了(Pod は残る) - Ctrl-D: 状態に関わらず即 TUI 終了(Pod は残る)。Running 中でも Pause / Cancel / Shutdown は送らない `Ctrl-X` は Running 中だけ Cancel、Idle / Paused では Shutdown。`Ctrl-C` は Running 中だけ Pod に `Method::Pause` を送り、それ以外では Pod は落とさず TUI プロセスだけ抜ける。`Ctrl-D` は常に Pod へ制御メソッドを送らず TUI プロセスだけ抜ける。 TUI のダイアログから Pod を起動する経路では、起動した Pod は TUI の子プロセスとして管理・終了されず、独立したプロセスとして残る。TUI 終了後は `yoi ` で再接続できる。 ## 履歴メモ - `Ctrl-R` はかつて Resume 専用だったが、空 Enter での Resume に統合された。現在の `Ctrl-R` は rewind picker の導線 - かつて存在した `Esc`(TUI 終了)は、`Ctrl-C` の 2 連打 UX に統合されたため廃止。現在の `Esc` は popup / picker / command mode のキャンセル用途 - かつて `Ctrl-D` は Pod に `Method::Shutdown` を送っていたが、TUI だけを抜けるデタッチ操作に変更された - 旧 inline viewport 時代は履歴スクロールを端末側スクロールバックに任せていたため TUI 内のスクロールキーは存在しなかった。全画面 alt screen への移行で `Shift-Up/Down` ほかのナビゲーションキーが追加された