# 示例：TUI / 交互式终端应用

交互式终端应用（文本编辑器、REPL、基于 curses 的 UI）不能由代理的 bash 工具直接驱动——它们接管终端。技能必须展示如何将它们包装在 `tmux` 中，以便代理可以发送输入、捕获输出并截图。

## tmux 模式

这是标准方法：

1. 在分离的 tmux 会话中启动 TUI
2. 使用 `tmux send-keys` 发送按键
3. 使用 `tmux capture-pane` 读取屏幕内容
4. 使用 `tmux kill-session` 清理

技能的 `SKILL.md` 应将此呈现为驱动应用的主要方式。一个将启动+附加序列包装起来的小 `driver.sh` 可以放在技能目录中，但对于大多数 TUI，技能正文中的原始 tmux 命令就足够了。

## 示例片段

> ## 运行（交互式，供代理使用）
>
> 在 tmux 内启动 TUI：
>
> ```bash
> tmux new-session -d -s app -x 120 -y 40 './myapp'
> ```
>
> 轮询直到就绪标记出现（比固定的 sleep 更快、更可靠——应用一旦启动就立即返回，如果没有启动则大声失败）：
>
> ```bash
> timeout 10 bash -c 'until tmux capture-pane -t app -p | grep -q "Ready"; do sleep 0.2; done'
> tmux capture-pane -t app -p
> ```
>
> 发送输入（此例导航到设置屏幕并切换一个选项）：
>
> ```bash
> tmux send-keys -t app 's'
> timeout 5 bash -c 'until tmux capture-pane -t app -p | grep -q "Settings"; do sleep 0.2; done'
> tmux send-keys -t app 'Down' 'Down' 'Space'  # 导航 + 切换
> timeout 5 bash -c 'until tmux capture-pane -t app -p | grep -qF "[x]"; do sleep 0.2; done'
> tmux capture-pane -t app -p
> ```
>
> 如果你发现自己写了超过几条这样的轮询行，把它们放进技能旁边 `driver.sh` 中的 `wait_for()` 辅助函数。
>
> 退出：
>
> ```bash
> tmux send-keys -t app 'q'
> tmux kill-session -t app 2>/dev/null || true
> ```
>
> ### 按键参考
>
> | 键 | 操作 |
> |---|---|
> | `j` / `k` 或 `Down` / `Up` | 导航列表 |
> | `Enter` | 选择 |
> | `s` | 设置 |
> | `q` | 退出 |

## 值得记录的细节

- **终端尺寸。** 某些 TUI 在较小宽度下会崩溃或隐藏内容。在 `tmux new-session -x -y` 参数中指定一个已知良好的尺寸。
- **启动时间。** 轮询就绪标记（`until tmux capture-pane | grep -q X`）而不是固定的 `sleep N`——应用一旦启动就立即返回，而当它从未启动时则会有用的失败。说清楚什么字符串表示就绪。
- **按键绑定参考。** 主要按键的表格。这是 TUI 的"API"——代理需要它来驱动应用。
- **干净退出。** 展示退出按键 *以及* 作为回退的 `tmux kill-session`。
- **颜色/Unicode 怪异行为。** 如果 `capture-pane` 输出难以阅读，记下有帮助的标志（`-e` 用于转义序列，`-J` 用于连接折行）。

## 同时记录直接调用

对于交互式运行应用的人类，tmux 是过度设计。也包含单行命令：

> ## 运行（直接，供人类使用）
>
> ```bash
> ./myapp
> ```
>
> 按 `q` 退出。
