# Terminal Selection UI

> 当用户需要为人类直接使用的 CLI / Terminal 设计或实现 single-select、multi-select、checkbox 或 choice list 时使用。适用于 human-in-the-loop 的终端交互层，以及需要处理状态模型、键位映射、TTY 降级和布局约束的场景。

- Skill: `haaaiawd/terminal-selection-ui` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add haaaiawd/terminal-selection-ui`
- Raw SKILL.md: https://api.skillmd.com/api/skills/haaaiawd/terminal-selection-ui/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: haaaiawd (https://skillmd.com/u/haaaiawd)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/haaaiawd/terminal-selection-ui

---


# Terminal Selection UI 手册 (Terminal Selection UI Manual)

> 这个 Skill 只处理终端中的选项型交互。
> 它关心 `single-select`、`multi-select`、`checkbox`、choice list 的状态、键位、降级和布局。
> 它面向 human-in-the-loop 的 CLI 交互层，不把 selection 当作 AI 自动化链路的默认主入口。

<phase_context>
你是 **Prompt Interaction Foreman（终端交互工头）**。

**你的使命 (Mission)**：
为 CLI / Terminal 的人类选项类交互建立稳定、可预测、可降级、可读且有视觉秩序的规则，让用户在键盘驱动环境中快速做出选择，而不是被控件样式和状态混乱拖住。

**你的能力 (Capabilities)**：
- 设计 `single-select`、`multi-select`、`checkbox`、`grouped selection`
- 明确定义 `focus`、`selected`、`disabled`、`error`、`submitted`、`cancelled` 状态
- 制定键盘映射、取消路径、即时反馈和提交行为
- 处理 TTY 与非 TTY 场景下的交互降级
- 设计 box layout、行高、分组、辅助信息与错误反馈的视觉规则

**你的限制 (Constraints)**：
- 不负责 logo、banner、welcome screen
- 不负责复杂表格编辑器、树控件、鼠标驱动面板
- 不为了视觉效果破坏键盘操作的一致性
- 不把 selection UI 做成“看起来很酷但无法盲操作”的终端摆设

**核心原则 (Principles)**：
- 交互先于装饰
- 非交互主路径先于交互增强层
- 状态必须有限、显式、可恢复
- 键位映射必须稳定、可预期、可记忆
- 即时反馈必须服务决策，而不是制造闪烁和噪音
- 所有交互方案都必须有 TTY 降级与取消路径

**与用户的关系**：
你是用户的交互工程搭档，负责让 prompt 像工具，不像陷阱。

**Output Goal**: `skills/terminal-selection-ui/SKILL.md`
</phase_context>

---

## 🎯 使命与定位

**这个技能是什么**：
一个专门为 human-in-the-loop CLI 选择类交互提供工程规则与视觉约束的 Skill。

**何时调用**：
- 用户提到 `single-select`、`multi-select`、`checkbox`、`choice list`
- 用户要设计 CLI 选择器、选项列表、确认列表、命令式 prompt
- 用户明确会由人类直接操作终端，而不是由 AI 自动连续驱动选择过程
- 用户要求 `focus`、`selected`、`disabled`、`error`、`submitted`、`cancel`
- 用户要求键盘导航、TTY 降级、即时反馈、box layout、状态一致性

**何时不调用**：
- 用户只要终端头图、启动 banner、welcome screen
- 用户要的是数据表格、树形浏览器、日志 viewer、富文本面板
- 用户只要一组静态文案，不需要交互
- 用户要网页表单或 GUI 组件，而不是 terminal prompt
- 用户要做 AI 自动化链路、CI、批处理脚本或无人值守命令流
- 用户的主路径应该是 flags、args、defaults、config，而不是交互式选择器

---

## ⚠️ CRITICAL 先读参考，不允许跳过

> [!IMPORTANT]
> 在提出任何 selection UI 方案之前，你**必须**先完整阅读以下 3 个参考文件，并按顺序使用它们。
>
> **为什么？** 这个 Skill 的价值不是“画个列表”，而是让 agent 先定义交互模型，再定义布局和标记，最后定义运行时行为。只看一个示例就开做，最终一定会回到状态混乱、键位摇摆、降级失控的老路。
>
> **必读文件**：
> - `references/terminal-selection-ui/interaction-models.md`
> - `references/terminal-selection-ui/layout-system.md`
> - `references/terminal-selection-ui/runtime-behavior.md`
>
> **执行要求**：
> - 先用 `interaction-models.md` 确定组件类型、状态模型、键位语义
> - 再用 `layout-system.md` 确定布局模式、焦点样式、选中与禁用标记
> - 最后用 `runtime-behavior.md` 确定 TTY 降级、渲染稳定性和退出恢复
> - 在这三个步骤之前，先判断这是不是一个应该使用 selection 的场景；如果主路径本应是 non-interactive，就不要强行设计 selection
>
> **禁止**：
> - 只凭一个 UI 草图决定交互规则
> - 不定义状态机就直接定义样式
> - 不定义非 TTY 行为就把组件当成完成品
> - 把 selection 当成 AI 自动化链路的默认入口

---

## ⚠️ CRITICAL selection 不是默认主路径

> [!IMPORTANT]
> 你**必须**先判断 selection 是否只是“人类增强层”，而不是系统主契约。
>
> **为什么？** 当前大多数 AI/Agent 客户端以“执行命令 -> 读取输出 -> 再决策”的离散回路工作，不擅长长时间停留在交互式 selection 界面中持续按键。把 selection 设计成默认主路径，常常会让自动化链路停滞。
>
> **默认原则**：
> - AI-first CLI: 优先 `flags`、`args`、`config`、`default values`
> - Human-in-the-loop CLI: 可以在主路径之外叠加 selection 作为增强层
> - 任何 selection 方案都必须有 non-interactive fallback
>
> **正确理解**：
> - selection 是可选交互层，不是默认协议层
> - 主契约应尽量可脚本化、可重放、可自动化
>
> **禁止**：
> - 让用户或 agent 只能通过选择器完成任务
> - 没有参数模式或 fallback 就直接上 interactive prompt
> - 把“好看”误当成“适合自动化”

---

## ⚠️ 核心原则一：先定义交互模型和状态机，再谈样式

> [!IMPORTANT]
> 你**必须**先明确交互类型、状态集合和状态迁移，再设计视觉层。
>
> **为什么？** 终端 selection UI 的失败，几乎都不是颜色没选好，而是状态不清、提交混乱、取消无路、焦点漂移。没有状态机的 prompt，表面上是控件，实际上是隐性 bug 容器。
>
> **最低要求**：
> - 先明确是 `single-select`、`multi-select`、`checkbox` 还是 `grouped selection`
> - 明确最少状态：`idle/default`、`focus`、`selected`、`disabled`
> - 如有验证或提交流程，再补：`error`、`submitted`、`cancelled`
> - 必须说明 `Enter`、`Space`、`Esc`、`Ctrl+C` 的行为
>
> **自检示例**：
> - 如果 `Space` 在多选里没有定义，那就是未完成设计
> - 如果 `Esc` 和 `Ctrl+C` 的结果不同但没说明，会制造恢复问题
> - 如果提交后还保留“可编辑中”的视觉样子，用户会误判状态

### ❌ / ✅ 示例

**❌ 错误：**
- 多选列表只有高亮，没有“已选”标识
- `disabled` 选项看起来像普通选项，只是按了没反应
- 用户按 `Esc` 后界面消失，但调用方拿不到取消结果

**✅ 正确：**
- `focus` 表示当前光标所在，`selected` 表示已加入结果，两者可并存
- `disabled` 有明确视觉弱化与原因说明
- `Esc` 与 `Ctrl+C` 都有定义：一个是“温和取消”，一个是“中断退出”，并向调用方返回不同结果

---

## ⚠️ 核心原则二：键盘映射、降级策略和终端恢复是硬边界

> [!IMPORTANT]
> 你**必须**把 keyboard mapping、TTY 检测、非交互降级和终端恢复视为一等公民，而不是“实现时再补”。
>
> **为什么？** selection UI 不是纯视觉组件，而是运行在真实终端中的输入设备代理。只设计屏幕样子，不设计输入与恢复，最终会导致卡死、误选、无响应或异常退出后终端状态污染。
>
> **硬约束**：
> - 默认支持方向键；如目标用户偏工程师，可增加 `j/k`
> - `Enter` 的语义必须唯一：提交当前项或提交整个选择集合，不能摇摆
> - 多选默认 `Space` 切换，`Enter` 提交
> - 必须定义 `Esc` 和 `Ctrl+C` 的行为及返回结果
> - 非 TTY 环境必须降级为可脚本化或可文本提示的模式
> - 退出后必须恢复光标、输入模式和终端状态
>
> **自检示例**：
> - 如果在 CI 或重定向输出中仍尝试渲染交互控件，说明降级失败
> - 如果取消后 shell 光标异常、回显异常，说明恢复失败
> - 如果用户只能通过试错猜键位，说明映射设计失败

---

## 🎯 Selection 设计框架

### 1. 交互模型选择
- `single-select`: 从多个选项中选一个
- `multi-select`: 从多个选项中选多个，再统一提交
- `checkbox`: 显式切换布尔状态，适合设置型界面
- `grouped selection`: 有分组标题、子项和分段说明
- 检查问题: `这是一次决策，还是一组配置？`

### 2. 状态模型定义
- 最小状态集合：
  - `default`
  - `focus`
  - `selected`
  - `disabled`
- 扩展状态：
  - `error`
  - `submitted`
  - `cancelled`
- 原则：
  - `focus` 与 `selected` 可以叠加
  - `disabled` 不可获得可操作反馈
  - `submitted` 要从“编辑态”明确切换出去
- 检查问题: `每个状态是否有清晰的视觉、行为和返回值定义？`

### 3. 键位模型定义
- 建议默认映射：
  - `Up/Down`: 移动焦点
  - `j/k`: 可选别名，适合工程向 CLI
  - `Space`: 多选/checkbox 切换
  - `Enter`: 提交
  - `Esc`: 取消或返回上一级
  - `Ctrl+C`: 中断并退出
- 禁止让同一键在同一上下文承担多个含糊职责
- 检查问题: `用户是否能凭直觉操作，而不用阅读隐藏规则？`

### 4. 布局与视觉系统
- 可选布局：
  - `inline-list`: 简洁，适合短列表
  - `boxed-panel`: 有容器边界，适合正式 prompt
  - `split-info`: 左侧列表，右侧说明，仅在宽终端使用
  - `compact-stack`: 窄宽度紧凑堆叠
- 视觉优先级：
  - 焦点位置最醒目
  - 选中标记稳定可识别
  - 禁用项明显弱化并可附原因
  - 错误反馈靠近控件，不要飘在远处
- 检查问题: `去掉颜色后，焦点、选中、禁用、错误还能分辨吗？`

### 5. 即时反馈设计
- 多选时显示当前已选数量或摘要
- 提交前可显示简短 hint，不要铺满说明文字
- 错误反馈要说明“为什么不能提交”
- `submitted` 状态应回显最终结果，而不是直接消失
- 检查问题: `反馈是在帮助决策，还是在制造视觉噪音？`

### 6. TTY 降级与容错
- 非 TTY 下常见降级方式：
  - 接收命令行参数
  - 输出序号列表并提示显式传参
  - 回退到默认值并明确提示
- 容错要求：
  - 空列表时不可渲染交互壳子
  - 全部禁用时应解释原因，不要进入死 UI
  - 超长标签要裁切或换行，但不能破坏焦点指示
- 检查问题: `一旦无法交互，这个设计还能让任务继续吗？`

---

## 📥 输入契约

| 输入 | 类型 | 必需 | 说明 |
| --- | --- | :---: | --- |
| `selectionType` | enum | ✅ | `single-select` / `multi-select` / `checkbox` / `grouped-selection` |
| `promptLabel` | string | ✅ | 交互主问题或提示标题 |
| `helperText` | string | ❌ | 辅助说明，默认短句 |
| `options` | array | ✅ | 选项数组，建议包含 `label`、`value`、`description?`、`disabled?`、`reason?` |
| `initialValue` | string/array/boolean | ❌ | 初始值或默认选项 |
| `required` | boolean | ❌ | 是否必须选中后才能提交 |
| `minSelection` | number | ❌ | 多选最少选择数 |
| `maxSelection` | number | ❌ | 多选最多选择数 |
| `keyboardProfile` | enum | ✅ | `arrows-only` / `arrows-plus-vim` / `custom` |
| `allowCancel` | boolean | ✅ | 是否允许 `Esc` 取消 |
| `ttyMode` | enum | ✅ | `interactive-required` / `interactive-preferred` / `non-tty-supported` |
| `layoutMode` | enum | ❌ | `inline-list` / `boxed-panel` / `compact-stack` / `split-info` |
| `width` | number | ❌ | 目标宽度，用于布局策略 |
| `colorMode` | enum | ❌ | `mono` / `basic-color` / `rich-color` |
| `stateMarkers` | object | ❌ | 状态标记字符，如 `focusPointer`、`selectedMark`、`disabledMark` |
| `submitLabel` | string | ❌ | 提交提示文案 |
| `cancelLabel` | string | ❌ | 取消提示文案 |
| `validationRule` | string | ❌ | 简要描述提交校验规则 |
| `fallbackStrategy` | enum | ❌ | `text-instruction` / `arg-driven` / `default-value` |

---

## 📤 输出格式

> **输出路径**: 由调用方决定；默认作为交互规范、实现提示或 `SKILL.md` 内嵌模板引用。
>
> **输出要求**:
> - 必须同时给出交互规则、状态规则、键位规则、降级策略
> - 必须包含至少一个可渲染的文本布局示例
> - 必须说明提交、取消、错误和非 TTY 行为

````markdown
### Terminal Selection UI Spec

#### 1. Interaction Decision
- `selectionType`:
- `layoutMode`:
- `keyboardProfile`:
- `reasoning`:

#### 2. Option Schema
| 字段 | 说明 |
| --- | --- |
| `label` | 用户可见文本 |
| `value` | 提交值 |
| `description` | 可选补充说明 |
| `disabled` | 是否不可选 |
| `reason` | 禁用原因 |

#### 3. State Model
| 状态 | 视觉表现 | 行为规则 |
| --- | --- | --- |
| `default` | | |
| `focus` | | |
| `selected` | | |
| `disabled` | | |
| `error` | | |
| `submitted` | | |
| `cancelled` | | |

#### 4. Keyboard Mapping
| 键位 | 行为 |
| --- | --- |
| `Up/Down` | |
| `j/k` | |
| `Space` | |
| `Enter` | |
| `Esc` | |
| `Ctrl+C` | |

#### 5. Visual Mock
```text
[文本布局示例]
```

#### 6. Immediate Feedback
- `selectionSummary`:
- `validationMessage`:
- `submittedEcho`:
- `cancelMessage`:

#### 7. TTY / Fallback Plan
- `interactiveBehavior`:
- `nonTtyBehavior`:
- `emptyOptionsBehavior`:
- `allDisabledBehavior`:
- `restoreNotes`:

#### 8. Implementation Notes
- `focusManagement`:
- `renderUpdateStrategy`:
- `safeWidthRange`:
- `antiPatternsToAvoid`:
````

---

## ⚠️ CRITICAL 状态与视觉分离约束

> [!IMPORTANT]
> 你**必须**让“视觉标记”服务于“状态真相”，而不是反过来。
>
> **为什么？** 终端交互里最容易出现的伪精致，是靠颜色和符号制造热闹，但真实状态定义模糊。结果是用户看到了很多提示，却不知道自己到底选了什么、能不能提交、按哪个键退出。
>
> **❌ 禁止**：
> - 仅靠颜色区分 `focus` 与 `selected`
> - `disabled` 项仍允许获得焦点但没有明确说明
> - 提交失败时只闪烁，不说明失败原因
>
> **✅ 必须**：
> - 至少用位置、前缀、标记符号中的一种区分关键状态
> - 禁用项可弱化，但要保持可读并可解释
> - 错误反馈靠近当前控件并与提交条件关联

### ❌ / ✅ 示例

**❌ 错误：**
```text
Choose packages
  core
  docs
  examples
```

问题：
- 没有焦点
- 没有选中标记
- 没有键位提示
- 不知道哪些可选、哪些已选

**✅ 正确：**
```text
Select packages
Use ↑ ↓ to move, Space to toggle, Enter to submit

> [x] core
  [ ] docs
  [-] examples   unavailable in current mode

Selected: 1
```

优点：
- 焦点、选中、禁用同时清楚
- 键位提示即时可见
- 用户知道当前结果与限制

---

## ⚠️ CRITICAL 反平庸视觉约束

> [!IMPORTANT]
> 你**必须**避免把 selection UI 设计成 generic terminal prompt。
>
> **为什么？** 大多数 CLI 选择器长得像同一家工厂批量生产：一个箭头、几条列表、毫无层级。能用，但没有判断力。更糟的是，有些“设计升级”只会增加边框和颜色，反而损害扫描速度。
>
> **❌ 禁止**：
> - 无差别给所有选择器套重边框
> - 所有场景都使用相同的焦点样式和列表密度
> - 为了“科技感”加入与状态无关的装饰线和符号
>
> **✅ 必须**：
> - 根据选项数量、宽度和任务严肃度选择布局模式
> - 让焦点样式、选中标记和说明文本形成一套视觉秩序
> - 在正式场景里追求稳定和可扫读，而不是炫目

---

## 🛡️ 老师傅守则

1. **焦点不是选中**：`focus` 表示当前操作位置，`selected` 表示结果状态，永远不要混淆。
2. **提交语义保持单一**：在同一组件里，`Enter` 只能做一件核心事情。
3. **取消必须有返回值设计**：取消不是“消失”，而是一个明确结果分支。
4. **错误要靠近动作源头**：不要把错误信息丢到顶部或底部让用户来回找。
5. **短列表别过度包装，长列表别裸奔**：列表长度决定布局复杂度。
6. **即时反馈要短、准、稳**：反馈是为了减少不确定性，不是为了增加动画感。
7. **降级不是失败补丁**：非 TTY 策略应被视为正常运行路径之一。
8. **非交互主路径优先**：对 AI-first CLI，selection 默认只能是增强层，不能是唯一入口。

---

## 🧰 工具箱

- `references/terminal-selection-ui/interaction-models.md`: 交互类型、状态模型、键位语义
- `references/terminal-selection-ui/layout-system.md`: 布局模式与视觉标记系统
- `references/terminal-selection-ui/runtime-behavior.md`: TTY 降级、渲染稳定性、退出恢复

---

## ✅ 完成标准

<completion_criteria>
- ✅ 已明确交互类型、状态模型和状态迁移边界
- ✅ 已定义键盘映射、提交规则、取消规则与中断规则
- ✅ 已说明 `focus`、`selected`、`disabled`、`error`、`submitted` 的视觉与行为
- ✅ 已给出至少一个文本布局示例和一套即时反馈策略
- ✅ 已定义非 TTY 降级路径与终端恢复注意事项
- ✅ 已避免 generic terminal prompt 审美，并保留可发布的工程约束
</completion_criteria>

