# 自定义快捷键

> 通过 keybindings 配置文件自定义 CodeBuddy Code 的键盘快捷键。

CodeBuddy Code 支持自定义键盘快捷键。运行 `/keybindings` 命令创建或打开位于 `~/.codebuddy/keybindings.json` 的配置文件。


## 上下文（Contexts）

每个绑定块指定一个 **context**，决定快捷键在何时生效：

| Context | 说明 |
| :--- | :--- |
| `Global` | 在应用的任何位置生效 |
| `Chat` | 聊天输入框获得焦点时 |
| `InputBox` | 文本输入框处于活跃状态时 |
| `Terminal` | 终端视图处于活跃状态时 |
| `Autocomplete` | 自动补全菜单显示时 |
| `Confirmation` | 确认/权限对话框显示时 |
| `HistorySearch` | 搜索命令历史时 (Ctrl+R) |
| `Task` | 任务/代理在前台运行时 |
| `Settings` | 设置面板打开时 |
| `CommandPalette` | 命令面板打开时 |
| `Select` | 选择/列表组件获得焦点时 |
| `PermissionDialog` | 工具权限对话框显示时 |
| `Help` | 帮助页面打开时 |
| `Plugin` | 插件对话框打开时 |
| `DiffDialog` | Diff 对话框打开时 |
| `MessageSelector` | 消息选择器 (rewind) 打开时 |

---

## 可用动作（Actions）

动作遵循 `namespace:action` 格式，如 `chat:submit` 发送消息、`app:toggleTodos` 切换待办事项列表。每个上下文有特定的可用动作。

### 应用动作

在 `Global` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `app:interrupt` | Ctrl+C | 中断当前操作 |
| `app:exit` | Ctrl+D | 退出 CodeBuddy Code |
| `app:redraw` | Ctrl+L | 刷新终端屏幕 |
| `app:toggleTodos` | Ctrl+T | 切换待办事项列表 |
| `app:toggleTranscript` | Ctrl+O | 切换详细转录 |
| `app:toggleSidebar` | Cmd+B | 切换侧边栏（Web UI） |
| `app:toggleTerminal` | Cmd+J | 切换终端（Web UI） |
| `app:commandPalette` | Cmd+Shift+P / Ctrl+Shift+P | 打开命令面板（Web UI） |
| `app:newChat` | Cmd+N | 新建对话（Web UI） |
| `app:settings` | Cmd+, | 打开设置（Web UI） |
| `app:focusInput` | Cmd+L | 聚焦输入框（Web UI） |

### 历史动作

用于导航命令历史：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `history:search` | Ctrl+R | 打开历史搜索 |
| `history:previous` | Up | 上一条历史 |
| `history:next` | Down | 下一条历史 |

### 聊天动作

在 `Chat` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `chat:cancel` | Escape | 取消当前输入，或中断当前前台请求 |
| `chat:submit` | Enter | 发送消息 |
| `chat:killAgents` | Ctrl+X Ctrl+K | 终止所有后台代理 |
| `chat:cycleMode` | Shift+Tab* | 切换权限模式 |
| `chat:modelPicker` | Meta+P | 打开模型选择器 |
| `chat:thinkingToggle` | Meta+T | 切换扩展思考 |
| `chat:undo` | Ctrl+_, Ctrl+Shift+- | 撤销 |
| `chat:externalEditor` | Ctrl+G, Ctrl+X Ctrl+E | 在外部编辑器中打开 |
| `chat:stash` | Ctrl+S | 暂存当前输入 |
| `chat:imagePaste` | Ctrl+V (Windows: Alt+V) | 粘贴图片 |

\*在没有 VT 模式的 Windows 上（Node <24.2.0/<22.17.0，Bun <1.2.23），默认为 Meta+M。

### 自动补全动作

在 `Autocomplete` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `autocomplete:accept` | Tab | 接受建议 |
| `autocomplete:dismiss` | Escape | 关闭菜单 |
| `autocomplete:previous` | Up | 上一项 |
| `autocomplete:next` | Down | 下一项 |

### 确认动作

在 `Confirmation` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `confirm:yes` | Y, Enter | 确认 |
| `confirm:no` | N, Escape | 取消 |
| `confirm:previous` | Up | 上一项 |
| `confirm:next` | Down | 下一项 |
| `confirm:toggle` | Space | 切换选中 |
| `confirm:toggleExplanation` | Ctrl+E | 切换权限说明 |
| `permission:toggleDebug` | Ctrl+D | 切换权限调试信息 |

### 转录动作

在 `Transcript` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `transcript:toggleShowAll` | Ctrl+E | 切换显示全部内容 |
| `transcript:exit` | Q, Ctrl+C, Escape | 退出转录视图 |

### 历史搜索动作

在 `HistorySearch` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `historySearch:next` | Ctrl+R | 下一条匹配 |
| `historySearch:accept` | Escape, Tab | 接受选择 |
| `historySearch:cancel` | Ctrl+C | 取消搜索 |
| `historySearch:execute` | Enter | 执行选中命令 |

### 任务动作

在 `Task` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `task:background` | Ctrl+B | 将当前任务转入后台 |

### 帮助动作

在 `Help` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `help:dismiss` | Escape | 关闭帮助菜单 |

### 设置动作

在 `Settings` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `settings:search` | / | 进入搜索模式 |
| `settings:close` | Enter | 保存并关闭配置面板 |

### 选择列表动作

在 `Select` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `select:next` | Down, J, Ctrl+N | 下一项 |
| `select:previous` | Up, K, Ctrl+P | 上一项 |
| `select:accept` | Enter | 确认选择 |
| `select:cancel` | Escape | 取消选择 |

### 命令面板动作

在 `CommandPalette` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `commandPalette:previous` | Up | 上一项 |
| `commandPalette:next` | Down | 下一项 |
| `commandPalette:execute` | Enter | 执行命令 |
| `commandPalette:close` | Escape | 关闭面板 |

### Diff 动作

在 `DiffDialog` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `diff:dismiss` | Escape | 关闭 Diff 查看器 |
| `diff:previousFile` | Up | 上一个文件 |
| `diff:nextFile` | Down | 下一个文件 |
| `diff:viewDetails` | Enter | 查看详情 |

### 消息选择器动作

在 `MessageSelector` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `messageSelector:up` | Up, K, Ctrl+P | 向上移动 |
| `messageSelector:down` | Down, J, Ctrl+N | 向下移动 |
| `messageSelector:top` | Shift+Up | 跳到顶部 |
| `messageSelector:bottom` | Shift+Down | 跳到底部 |
| `messageSelector:select` | Enter | 选择消息 |

### 插件动作

在 `Plugin` 上下文中可用：

| 动作 | 默认按键 | 说明 |
| :--- | :--- | :--- |
| `plugin:toggle` | Space | 切换插件选中 |
| `plugin:install` | I | 安装选中插件 |

---

## 按键语法

### 修饰键

使用 `+` 分隔符组合修饰键：

- `ctrl` 或 `control` — Control 键
- `alt`、`opt` 或 `option` — Alt/Option 键
- `shift` — Shift 键
- `meta`、`cmd` 或 `command` — Meta/Command 键

示例：

```
ctrl+k          单个修饰键 + 按键
shift+tab       Shift + Tab
meta+p          Command/Meta + P
ctrl+shift+c    多个修饰键
```

### 弦序列（Chords）

弦序列是用空格分隔的连续按键组合：

```
ctrl+x ctrl+k   先按 Ctrl+X，松开，再按 Ctrl+K
ctrl+x ctrl+e   先按 Ctrl+X，松开，再按 Ctrl+E
```

弦序列有 1000ms 超时。如果超时未完成第二步，弦序列将被取消。

### 特殊按键

- `escape` 或 `esc` — Escape 键
- `enter` 或 `return` — Enter 键
- `tab` — Tab 键
- `space` — 空格键
- `up`、`down`、`left`、`right` — 方向键
- `backspace`、`delete` — 删除键

---

## 解绑默认快捷键

将动作设为 `null` 以解绑默认快捷键：

```json
{
  "bindings": [
    {
      "context": "Chat",
      "bindings": {
        "ctrl+s": null
      }
    }
  ]
}
```

解绑弦序列的所有组合后，可以将前缀键用作单键绑定：

```json
{
  "bindings": [
    {
      "context": "Chat",
      "bindings": {
        "ctrl+x ctrl+k": null,
        "ctrl+x ctrl+e": null,
        "ctrl+x": "chat:newline"
      }
    }
  ]
}
```

如果只解绑了部分弦序列，按下前缀键仍会进入弦等待模式。

---

## 保留快捷键

以下快捷键不可重新绑定：

| 快捷键 | 原因 |
| :--- | :--- |
| Ctrl+C | 硬编码的中断/取消 |
| Ctrl+D | 硬编码的退出 |
| Ctrl+M | 在终端中等同于 Enter（两者都发送 CR） |

---

## 终端冲突

某些快捷键可能与终端复用器冲突：

| 快捷键 | 冲突 |
| :--- | :--- |
| Ctrl+B | tmux 前缀键（按两次发送） |
| Ctrl+A | GNU screen 前缀键 |
| Ctrl+Z | Unix 进程挂起 (SIGTSTP) |

---

## Web UI 可视化配置

除了编辑 JSON 文件，你还可以在 Web UI 中通过可视化界面管理快捷键：

1. 在侧边栏点击 **快捷键** 导航项，或使用 URL `#/keybindings`
2. 使用搜索框按名称、按键或上下文筛选快捷键
3. 点击编辑按钮（铅笔图标）录制新的快捷键组合
4. 录制对话框会实时显示冲突检测
5. 用户自定义的绑定以左侧高亮边框标记
6. 点击重置按钮可恢复单个绑定为默认值

### REST API

Web UI 通过 REST API 管理快捷键：

| 端点 | 方法 | 说明 |
| :--- | :--- | :--- |
| `/api/v1/keybindings` | GET | 获取所有快捷键（默认 + 用户 + 合并） |
| `/api/v1/keybindings` | PUT | 保存用户快捷键配置 |
| `/api/v1/keybindings/reset` | POST | 重置为默认值（删除用户配置） |
| `/api/v1/keybindings/validate` | POST | 验证配置（不保存） |

---

## 验证

CodeBuddy Code 会验证你的快捷键配置并对以下情况显示警告：

- 解析错误（无效的 JSON 或结构）
- 无效的上下文名称
- 保留快捷键冲突
- 终端复用器冲突
- 同一上下文中的重复绑定
