# 会话控制面 session-command（Agentic / 无头 Slash）

大量用户态能力原本只以 TUI slash 暴露（`/buddy`、`/yolo`、`/mcp` 等）。Issue #190 提供统一的 **session/slash control plane**，让 Agent / 脚本可安全调用同一语义，而不必手写 `~/.snow/*.json`。

## 入口

| 表面             | 用法                                            |
| ---------------- | ----------------------------------------------- |
| CLI（P0）        | `snow cmd <command> [args...] [--json] [--yes]` |
| Agent 工具（P1） | `session-command-list` / `session-command-run`  |
| SSE（P2）        | `POST /session/command`                         |

三者共用 `runSessionCommand()`。

## CLI 示例

```bash
snow cmd session-command list --json
snow cmd help --json
snow cmd buddy status --json
snow cmd buddy hatch 小雪 --species=fox --json
snow cmd buddy set --hat=crown --eye=✦ --color=cyan --rarity=legendary --shiny=true --json
snow cmd buddy say 你好 --json
snow cmd theme status --json
snow cmd theme set dark --json
snow cmd statusline status --json
snow cmd tool-display compact --json
snow cmd simple on --json
snow cmd think-display compact --json
snow cmd image-compress status --json
snow cmd hybrid-compress status --json
snow cmd speedometer on --json
snow cmd auto-format status --json
snow cmd subagent-depth 2 --json
snow cmd file-list-display tree --json
snow cmd language zh --json
snow cmd show-thinking on --json
snow cmd privacy status --yes --json
snow cmd mcp status --json
snow cmd mcp reconnect myservice --yes --json
snow cmd profiles list --json
snow cmd codebase status --json
snow cmd codebase agent-review on --yes --json
snow cmd yolo status --json
snow cmd yolo on --yes --json
snow cmd permissions status --json
snow cmd session list --json
snow cmd goal status --json
snow cmd loop list --json
snow cmd skills list --json
snow cmd config snapshot --json
snow cmd export md --json
snow cmd usage --json
snow cmd usage --period=day --json
snow cmd compact --yes --json
snow cmd reindex --yes --json
snow cmd buddy reset --yes --json
```

- `--json`：输出稳定 JSON `{ ok, command, data, code?, message?, risk? }`
- `--yes` / `--confirm`：确认中/高风险写操作

成功退出码 `0`，失败 `1`。

## Agent 工具

内置服务：**session-command**

1. `session-command-list` — 列出 allowlist（可按 `risk` 过滤）
2. `session-command-run` — 执行命令

```json
{
	"command": "buddy.hatch",
	"args": "小雪 --species=fox --personality=calm",
	"confirm": false
}
```

中高风险写操作必须 `confirm: true`。

## SSE

```http
POST /session/command
Content-Type: application/json

{
  "command": "tool-display",
  "args": "compact",
  "confirm": false
}
```

## 风险分级

| 风险           | 默认策略                    | 示例                                                             |
| -------------- | --------------------------- | ---------------------------------------------------------------- |
| `read`         | 允许                        | buddy status、mcp status、session list、goal status              |
| `low_write`    | 允许                        | buddy hatch/say、simple、tool-display、export、goal create       |
| `medium_write` | 需 `--yes` / `confirm:true` | yolo on、profile switch、codebase on、mcp enable、session resume |
| `high_risk`    | 需确认                      | buddy reset、permissions clear                                   |

`status` / `list` / `current` / 空参数查询按 **只读** 处理，无需确认。

裸命令默认解析：

| 裸命令            | 解析为                 |
| ----------------- | ---------------------- |
| `buddy`           | `buddy.status`         |
| `theme`           | `theme.status`         |
| `statusline`      | `statusline.status`    |
| `mcp`             | `mcp.status`           |
| `ide`             | `ide.status`           |
| `profiles`        | `profiles.list`        |
| `permissions`     | `permissions.status`   |
| `session`         | `session.list`         |
| `goal`            | `goal.status`          |
| `loop`            | `loop.list`            |
| `skills`          | `skills.list`          |
| `config`          | `config.snapshot`      |
| `session-command` | `session-command.list` |

## 命令矩阵

列：**命令 ID** | **CLI 形式** | **风险** | **确认** | **说明**

### Buddy

| 命令 ID         | CLI 形式                                         | 风险      | 确认 | 说明                                   |
| --------------- | ------------------------------------------------ | --------- | ---- | -------------------------------------- |
| `buddy.status`  | `snow cmd buddy status`                          | read      | 否   | 裸 `buddy` 默认                        |
| `buddy.hatch`   | `snow cmd buddy hatch <name> [--species=…]`      | low_write | 否   | 孵化伙伴                               |
| `buddy.pet`     | `snow cmd buddy pet`                             | low_write | 否   |                                        |
| `buddy.rename`  | `snow cmd buddy rename <name>`                   | low_write | 否   |                                        |
| `buddy.set`     | `snow cmd buddy set --hat=… --eye=… --color=… …` | low_write | 否   | 自定义外观/颜色/性格；`customize` 同义 |
| `buddy.mute`    | `snow cmd buddy mute`                            | low_write | 否   |                                        |
| `buddy.unmute`  | `snow cmd buddy unmute`                          | low_write | 否   |                                        |
| `buddy.profile` | `snow cmd buddy profile …`                       | low_write | 否   | list/current/set                       |
| `buddy.reset`   | `snow cmd buddy reset --yes`                     | high_risk | 是   | 移除伙伴                               |
| `buddy.species` | `snow cmd buddy species`                         | read      | 否   |                                        |
| `buddy.say`     | `snow cmd buddy say <message>`                   | low_write | 否   | 可能调用模型                           |

### 显示 / 主题

| 命令 ID             | CLI 形式                                                  | 风险      | 确认 | 说明                                                          |
| ------------------- | --------------------------------------------------------- | --------- | ---- | ------------------------------------------------------------- |
| `theme.status`      | `snow cmd theme status`                                   | read      | 否   | 裸 `theme`；含 toolIcons / toolStatusIcons / toolDisplayNames |
| `theme.set`         | `snow cmd theme set <name\|key=value…>`                   | low_write | 否   | 含 `toolIcons=`（类型/status 前缀）、`toolDisplayNames=`      |
| `statusline.status` | `snow cmd statusline status`                              | read      | 否   | 插件 + 内置 id                                                |
| `simple`            | `snow cmd simple [on\|off\|status]`                       | low_write | 否   | status 按只读                                                 |
| `tool-display`      | `snow cmd tool-display [mode\|status]`                    | low_write | 否   |                                                               |
| `think-display`     | `snow cmd think-display [mode\|status]`                   | low_write | 否   |                                                               |
| `image-compress`    | `snow cmd image-compress [on\|off\|status]`               | low_write | 否   |                                                               |
| `hybrid-compress`   | `snow cmd hybrid-compress [on\|off\|status]`              | low_write | 否   | status 只读                                                   |
| `speedometer`       | `snow cmd speedometer [on\|off\|status]`                  | low_write | 否   | 实时 tracker + 持久化                                         |
| `subagent-depth`    | `snow cmd subagent-depth [N\|status]`                     | low_write | 否   | 非负整数                                                      |
| `file-list-display` | `snow cmd file-list-display [list\|tree\|toggle\|status]` | low_write | 否   |                                                               |
| `language`          | `snow cmd language [en\|zh\|zh-TW\|status]`               | low_write | 否   |                                                               |
| `show-thinking`     | `snow cmd show-thinking [on\|off\|status]`                | low_write | 否   | emit showThinking                                             |

### 模式开关

| 命令 ID                 | CLI 形式                                 | 风险         | 确认 | 说明          |
| ----------------------- | ---------------------------------------- | ------------ | ---- | ------------- |
| `yolo`                  | `snow cmd yolo [on\|off\|status]`        | medium_write | 是\* | \*status 只读 |
| `plan`                  | `snow cmd plan [on\|off\|status]`        | medium_write | 是\* |               |
| `tool-search`           | `snow cmd tool-search [on\|off\|status]` | medium_write | 是\* |               |
| `vulnerability-hunting` | `snow cmd vulnerability-hunting …`       | medium_write | 是\* |               |
| `team`                  | `snow cmd team [on\|off\|status]`        | medium_write | 是\* |               |
| `ultra-todo`            | `snow cmd ultra-todo …`                  | medium_write | 是\* |               |

### MCP / IDE / 配置连接

| 命令 ID             | CLI 形式                                                       | 风险         | 确认 | 说明                                                                                  |
| ------------------- | -------------------------------------------------------------- | ------------ | ---- | ------------------------------------------------------------------------------------- |
| `mcp.status`        | `snow cmd mcp status`                                          | read         | 否   | 裸 `mcp`                                                                              |
| `mcp.reconnect`     | `snow cmd mcp reconnect <service> --yes`                       | medium_write | 是   |                                                                                       |
| `mcp.enable`        | `snow cmd mcp enable <service\|tool> --yes`                    | medium_write | 是   |                                                                                       |
| `mcp.disable`       | `snow cmd mcp disable <service\|tool> --yes`                   | medium_write | 是   |                                                                                       |
| `ide.status`        | `snow cmd ide status`                                          | read         | 否   | 裸 `ide`                                                                              |
| `ide.connect`       | `snow cmd ide connect [port] --yes`                            | medium_write | 是   |                                                                                       |
| `ide.disconnect`    | `snow cmd ide disconnect --yes`                                | medium_write | 是   |                                                                                       |
| `connection-status` | `snow cmd connection-status`                                   | read         | 否   | `ide.status` 别名                                                                     |
| `profiles.list`     | `snow cmd profiles list`                                       | read         | 否   | 裸 `profiles`                                                                         |
| `profiles.current`  | `snow cmd profiles current`                                    | read         | 否   |                                                                                       |
| `profiles.switch`   | `snow cmd profiles switch <name> --yes`                        | medium_write | 是   |                                                                                       |
| `codebase`          | `snow cmd codebase [on\|off\|status\|agent-review\|reranking]` | medium_write | 是\* | status 只读；agent-review/reranking 互斥                                              |
| `reindex`           | `snow cmd reindex [--force] --yes`                             | medium_write | 是   | 需已配置 codebase                                                                     |
| `auto-format`       | `snow cmd auto-format [on\|off\|status]`                       | low_write    | 否   |                                                                                       |
| `telemetry`         | `snow cmd telemetry [on\|off\|status]`                         | medium_write | 是\* |                                                                                       |
| `usage`             | `snow cmd usage [--period=...]`                                | read         | 否   | 会话快照 + 历史；`--period` 支持 hour/day/week/month 与 24h/7d/30d/12m，默认 last_30d |

### 会话自动化

| 命令 ID              | CLI 形式                                                   | 风险         | 确认 | 说明                   |
| -------------------- | ---------------------------------------------------------- | ------------ | ---- | ---------------------- |
| `compact`            | `snow cmd compact [sessionId] --yes`                       | medium_write | 是   | 需要活跃/目标会话      |
| `export`             | `snow cmd export <txt\|md\|html\|json> [sessionId] [path]` | low_write    | 否   | 格式：txt/md/html/json |
| `permissions.status` | `snow cmd permissions status`                              | read         | 否   | 裸 `permissions`       |
| `permissions.allow`  | `snow cmd permissions allow <tool> --yes`                  | medium_write | 是   | 永久放行工具           |
| `permissions.revoke` | `snow cmd permissions revoke <tool> --yes`                 | medium_write | 是   |                        |
| `permissions.clear`  | `snow cmd permissions clear --yes`                         | high_risk    | 是   | 清空全部永久放行       |

### 会话生命周期

| 命令 ID           | CLI 形式                               | 风险         | 确认 | 说明         |
| ----------------- | -------------------------------------- | ------------ | ---- | ------------ |
| `session.list`    | `snow cmd session list`                | read         | 否   | 裸 `session` |
| `session.current` | `snow cmd session current`             | read         | 否   |              |
| `session.resume`  | `snow cmd session resume <id> --yes`   | medium_write | 是   |              |
| `session.load`    | `snow cmd session load <id> --yes`     | medium_write | 是   | resume 别名  |
| `session.branch`  | `snow cmd session branch [name] --yes` | medium_write | 是   | 分叉当前会话 |

### Goal / Loop / Skills

| 命令 ID          | CLI 形式                               | 风险         | 确认 | 说明                            |
| ---------------- | -------------------------------------- | ------------ | ---- | ------------------------------- |
| `goal.status`    | `snow cmd goal status`                 | read         | 否   | 裸 `goal`                       |
| `goal.create`    | `snow cmd goal create <objective>`     | low_write    | 否   | **不会**自动启动完整 Ralph 循环 |
| `goal.pause`     | `snow cmd goal pause --yes`            | medium_write | 是   |                                 |
| `goal.resume`    | `snow cmd goal resume --yes`           | medium_write | 是   |                                 |
| `goal.clear`     | `snow cmd goal clear --yes`            | medium_write | 是   |                                 |
| `loop.list`      | `snow cmd loop list`                   | read         | 否   | 裸 `loop`                       |
| `loop.create`    | `snow cmd loop create <spec> --yes`    | medium_write | 是   |                                 |
| `loop.cancel`    | `snow cmd loop cancel <id> --yes`      | medium_write | 是   |                                 |
| `loop.tasks`     | `snow cmd loop tasks`                  | read         | 否   |                                 |
| `skills.list`    | `snow cmd skills list`                 | read         | 否   | 裸 `skills`                     |
| `skills.status`  | `snow cmd skills status [name]`        | read         | 否   |                                 |
| `skills.enable`  | `snow cmd skills enable <name> --yes`  | medium_write | 是   |                                 |
| `skills.disable` | `snow cmd skills disable <name> --yes` | medium_write | 是   |                                 |

### 帮助 / 配置 / 元命令

| 命令 ID                | CLI 形式                          | 风险      | 确认 | 说明                               |
| ---------------------- | --------------------------------- | --------- | ---- | ---------------------------------- |
| `help`                 | `snow cmd help`                   | read      | 否   | 常用命令与示例                     |
| `config.snapshot`      | `snow cmd config snapshot`        | read      | 否   | 裸 `config`；无密钥；含 `api` 摘要 |
| `config.status`        | `snow cmd config status`          | read      | 否   | maxContextTokens/maxTokens/models  |
| `config.set`           | `snow cmd config set key=value …` | low_write | 否   | 热写限制/模型；**无需重启**        |
| `home`                 | `snow cmd home`                   | read      | —    | 固定返回 `HEADLESS_UNSUPPORTED`    |
| `session-command.list` | `snow cmd session-command list`   | read      | 否   | 完整 allowlist                     |

## 错误码

| 错误码                  | 含义                                      |
| ----------------------- | ----------------------------------------- |
| `UNKNOWN_COMMAND`       | 不在 allowlist                            |
| `COMMAND_NOT_ALLOWED`   | 策略拦截                                  |
| `CONFIRMATION_REQUIRED` | 需要 `--yes` / `confirm:true`             |
| `INVALID_ARGS`          | 参数非法                                  |
| `HEADLESS_UNSUPPORTED`  | 无头/非 TUI 不可用（如 `home`）           |
| `EXECUTION_FAILED`      | 运行时失败                                |
| `NOT_FOUND`             | 资源不存在（buddy/profile/session/skill） |
| `ALREADY_EXISTS`        | 例如 buddy 已孵化                         |
| `NOT_CONFIGURED`        | 例如 codebase 嵌入未配置                  |
| `SESSION_REQUIRED`      | 需要活跃/目标会话（如 compact）           |

## 成功响应形状

```json
{
	"ok": true,
	"command": "buddy.hatch",
	"data": {
		"companion": {
			"name": "Pip",
			"species": "fox",
			"rarity": "rare"
		}
	},
	"message": "Pip hatched as a rare fox.",
	"risk": "low_write"
}
```

## 从私有 JSON 迁移

优先使用 `snow cmd …`（或 Agent `session-command-run` / SSE `POST /session/command`），不要把手改 `~/.snow/*.json` 当官方自动化路径。

| 旧做法 / 私有文件                                                            | 推荐命令                                                            |
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------- |
| 手改 `~/.snow/buddy.json` 孵化/状态/重置/外观                                | `buddy hatch` / `buddy status` / `buddy set` / `buddy reset --yes`  |
| 私有 AI 路径触发伙伴回复                                                     | `buddy say <message>`                                               |
| 手改 theme / simple / tool-display / toolIcons / 状态前缀 / toolDisplayNames | `theme status` / `theme set`（含 `toolIcons=on                      | off`、`toolIcons=status:on | off`、`toolIcons=status:success:✓`、`toolDisplayNames=<tool>:<名>`）、`simple`、`tool-display`、`think-display` |
| 在 settings 里翻 yolo/plan/tool-search                                       | `yolo` / `plan` / `tool-search`（写操作加 `--yes`）                 |
| 手改 always-approved 工具列表                                                | `permissions status                                                 | allow                      | revoke                                                                                                          | clear`     |
| 手改 MCP 启用状态                                                            | `mcp status                                                         | enable                     | disable                                                                                                         | reconnect` |
| 手改 skills 禁用列表                                                         | `skills list                                                        | status                     | enable                                                                                                          | disable`   |
| Agent 读取原始 settings                                                      | `config snapshot` / `config status`（仅非密钥字段）                 |
| 手改 `config.json` / profile 的上下文或模型                                  | `config set maxContextTokens=… maxTokens=… advancedModel=…`（热更） |
| 手建/删/改名 profile 文件                                                    | `profiles create` / `delete` / `rename`（写操作加 `--yes`）         |

`config set` 支持：`maxContextTokens`、`maxTokens`、`advancedModel`、`basicModel`、`requestMethod`（chat|responses|gemini|anthropic）。**不**支持通过控制面设置 `apiKey`。

本控制面**不**提供、也**不**文档化静默修改 API Key 的路径。

## 说明与边界

- `home` 仅为 TUI 导航 → `HEADLESS_UNSUPPORTED`。
- `goal create` 只记录目标，**不会**自动启动完整 Ralph 循环（推进仍走现有 goal 工具）。
- `export` 格式：`txt` | `md` | `html` | `json`。
- `usage` 返回会话 `contextUsage`（兼容旧字段）+ `history` 滚动窗统计；`--period`/`-p`/裸参数可选，默认 `week`（last_30d）。数据源 `~/.snow/usage`。
- `reindex` 需要已配置 codebase，否则 `NOT_CONFIGURED` / `EXECUTION_FAILED`。
- `reindex` 无头路径会**等待完整重建完成**（不是异步 job 队列）。
- 中/高风险写操作需要 `--yes` / `confirm:true`（status 类查询除外）。
- `config snapshot` 包含非密钥字段：modes、theme、`api:{advancedModel,basicModel,requestMethod,maxContextTokens,maxTokens}`、`speedometerEnabled`、`hybridCompressEnabled`、`autoFormatEnabled`、`subAgentMaxSpawnDepth`、`fileListDisplayMode`、`language`、`showThinking`、`privacy:{enabled,mode}`、`codebaseFlags` 等。
- `config set` 会写 `~/.snow/config.json` + 当前 active profile，并 emit `apiConfig`；同进程 TUI（含 StatusLine）热刷新。外部强写 `config.json` 也会被 `fs.watch` 拾取。
- 破坏性 git / 任意 shell / 静默改密钥仍**不在** allowlist。

## 双路径策略

很多 slash 能力目前有两套入口：

| 入口                                   | 职责                                       |
| -------------------------------------- | ------------------------------------------ |
| TUI slash（`source/utils/commands/*`） | 面向 UI：文案、remount action、i18n        |
| 控制面（`runSessionCommand`）          | 面向领域：CLI / Agent / SSE 稳定 JSON 契约 |

**策略**

- 业务真相以共享 **domain API**（theme/config/session/goal/loop/skills/permissions 等）为准。
- plane handler 不应在已有 domain helper 时重复实现私有文件格式。
- 把 TUI 全量合并进 plane 是**渐进**目标，不为 dedupe 强行改交互语义。
- `sessionCommandParity.ts` 记录 plane ↔ TUI 关键名重叠，便于防漂移测试。
- plane 配置写入会 emit `configEvents`，同进程 TUI 订阅者立即热刷新。
- 已覆盖热同步（同进程）：`simple`、`tool-display`、`think-display`、`show-thinking`、`image-compress`、`hybrid-compress`、`speedometer`、`auto-format`、`yolo`、`plan`、`tool-search`、`vulnerability-hunting`、`team`、`ultra-todo`、`theme`/`diffOpacity`/`customColors`/`toolIcons`（含状态前缀 `toolStatusIcons`）/`toolDisplayNames`、`language`、`file-list-display`、`privacy`、`telemetry`、`codebase`（含 flags）、`subagent-depth`、**`config set`（apiConfig）**。
- 跨进程外部 `snow cmd` **不会**热刷新已打开的 TUI；新 allowlist 也需要重启进程后才生效。
- plane 裸参数对开关类命令默认是 **status**（不是 TUI 裸 toggle）。

## 硬化 / 测试说明

- 中/高风险命令需要 `confirm:true` / `--yes`；status/list/current 查询仍免确认。
- `source/test/session-command-plane.test.ts` 覆盖：
  - 写命令确认门闩矩阵
  - 稳定失败码（`INVALID_ARGS` / `NOT_FOUND` / `SESSION_REQUIRED` 等）
  - 可逆写路径（theme toolDisplay、permissions、skills、goal）+ finally 还原
  - allowlist 完整性（除 `home` 外不应出现意外 `HEADLESS_UNSUPPORTED`）
  - risk 元数据 sanity + plane/TUI 重叠清单
  - 同进程 plan/yolo/theme 以及 matrix 开关（hybrid-compress/speedometer/language 等）的 `configEvents` 发射
- integrity 探测使用 `confirm:false`，避免测试中真实执行 reindex/compact。

## 不要做的事

- 不要把读写私有 `buddy.json` / `theme.json` 当作官方自动化路径
- 不要解析打包后的 `bundle/cli.mjs`
- 破坏性 git / 权限放大 / 密钥修改不在本 allowlist 默认范围内

## 相关文档

- [25.宠物伙伴指南](./25.宠物伙伴指南.md)
- [12.无头模式](./12.无头模式.md)
- [20.SSE 服务模式](./20.SSE服务模式.md)
- [28.官方文档工具 snow-docs](./28.官方文档工具snow-docs.md)
