Gemini CLI 键盘快捷键全解:默认键位、自定义 keybindings.json 与 Vim 模式
本文基于 gemini-cli 仓库的官方快捷键参考文档 keyboard-shortcuts.md,完整梳理 Gemini CLI 终端界面中用于编辑输入、导航历史和控制 UI 的全套默认键盘快捷键,并深入源码讲解快捷键注册机制、~/.gemini/keybindings.json 自定义绑定的加载与合并逻辑、上下文相关的特殊快捷键以及 Vim 模式的完整键位,帮助你既能在日常使用中以最高效率操作 CLI,也能按团队或个人习惯重塑整套键位映射。
快捷键系统的源码实现:命令、绑定与匹配
Gemini CLI 的快捷键体系是数据驱动的,核心定义在 keyBindings.ts 中。理解以下三个结构,有助于正确配置自定义键位:
Command枚举:以字符串形式(如edit.clear、app.toggleYolo)标识每一个可绑定的命令,覆盖基本控制、光标移动、编辑、滚动、历史搜索、导航、补全、文本输入、应用控制、后台 Shell 控制和扩展控制等类别。你在keybindings.json中填写的command字段必须是该枚举中的合法值,配置会被 keyBindings.ts 中的 zod schema 校验,非法命令会报Invalid command错误。KeyBinding类:负责解析键位字符串。它循环剥离ctrl+、shift+、alt+、option+、opt+、cmd+、meta+等修饰前缀(顺序不限),剩余部分必须是单个 Unicode 字符或白名单中的特殊键名(f1–f35、pageup、numpad0等),否则抛出Invalid keybinding key错误。值得注意的是,单个大写字母会隐式推导 shift 修饰符(例如A等价于shift+a),这与源码中this.shift = shift || (isSingleChar && this.name !== key)的逻辑一致。- 精确匹配规则:KeyBinding.matches() 要求键名与
shift、alt、ctrl、cmd四个修饰位全部严格相等,这正是官方文档强调“键匹配是显式的”(ctrl+f不会命中ctrl+shift+f)的底层原因。 - 默认配置:
defaultKeyBindingConfig是一个Map<Command, readonly KeyBinding[]>,保存了本文后面列出的全部默认键位,与 UI 中实际生效的硬编码行为保持逐一对应。
此外,界面提示中的修饰符显示是平台感知的:keybindingUtils.ts 中定义了按操作系统的修饰符映射(macOS 显示 Option/Cmd、Windows 显示 Alt/Win、Linux 显示 Super),因此同一命令在不同系统上的 UI 提示会呈现不同的修饰符名称,但底层绑定语义不变。
默认快捷键参考
以下表格完整继承自官方参考文档(该区块由脚本自动生成,见文末“自动生成机制”一节),按功能类别组织。Keys 列中的多个按键表示该命令的所有默认触发方式。
基本控制(Basic Controls)
| 命令 | 作用 | 按键 |
|---|---|---|
basic.confirm |
确认当前选择。 | Enter |
basic.cancel |
关闭对话框或取消当前焦点。 | Esc、Ctrl+[ |
basic.quit |
取消当前请求;输入为空时退出 CLI。 | Ctrl+C |
basic.exit |
输入缓冲为空时退出 CLI。 | Ctrl+D |
光标移动(Cursor Movement)
| 命令 | 作用 | 按键 |
|---|---|---|
cursor.home |
光标移到行首。 | Ctrl+A、Home |
cursor.end |
光标移到行尾。 | Ctrl+E、End |
cursor.up |
光标上移一行。 | Up |
cursor.down |
光标下移一行。 | Down |
cursor.left |
光标左移一个字符。 | Left |
cursor.right |
光标右移一个字符。 | Right、Ctrl+F |
cursor.wordLeft |
光标左移一个单词。 | Ctrl+Left、Alt+Left、Alt+B |
cursor.wordRight |
光标右移一个单词。 | Ctrl+Right、Alt+Right、Alt+F |
编辑(Editing)
| 命令 | 作用 | 按键 |
|---|---|---|
edit.deleteRightAll |
删除光标到行尾的内容。 | Ctrl+K |
edit.deleteLeftAll |
删除光标到行首的内容。 | Ctrl+U |
edit.clear |
清空输入框全部文本。 | Ctrl+C |
edit.deleteWordLeft |
删除前一个单词。 | Ctrl+Backspace、Alt+Backspace、Ctrl+W |
edit.deleteWordRight |
删除后一个单词。 | Ctrl+Delete、Alt+Delete、Alt+D |
edit.deleteLeft |
删除光标左侧字符。 | Backspace、Ctrl+H |
edit.deleteRight |
删除光标右侧字符。 | Delete、Ctrl+D |
edit.undo |
撤销最近一次文本编辑。 | Ctrl+Z、Alt+Z、Cmd/Win+Z |
edit.redo |
重做最近一次撤销。 | Ctrl+Shift+Z、Shift+Cmd/Win+Z、Alt+Shift+Z |
其中撤销/重做的默认键位是按平台区分的,源码 getPlatformUndoBindings / getPlatformRedoBindings 显示:
- Windows:撤销为
Ctrl+Z、Alt+Z; - macOS:撤销为
Cmd+Z、Alt+Z; - Linux/WSL:撤销为
Alt+Z(升为首选,避免被 Windows 环境拦截)、Cmd+Z、Ctrl+Z(保留给“智能冒泡”行为); - 重做的顺序在所有平台统一为
Ctrl+Shift+Z、Cmd+Shift+Z、Alt+Shift+Z,以减少键位抖动。
这也是为什么文档表格中 edit.undo 合并展示了三个平台的全部变体——文档生成脚本会专门对 UNDO/REDO 做跨平台合并去重。
滚动(Scrolling)
| 命令 | 作用 | 按键 |
|---|---|---|
scroll.up |
向上滚动内容。 | Shift+Up |
scroll.down |
向下滚动内容。 | Shift+Down |
scroll.home |
滚动到顶部。 | Ctrl+Home、Shift+Home |
scroll.end |
滚动到底部。 | Ctrl+End、Shift+End |
scroll.pageUp |
向上翻一页。 | Page Up |
scroll.pageDown |
向下翻一页。 | Page Down |
历史记录与搜索(History & Search)
| 命令 | 作用 | 按键 |
|---|---|---|
history.previous |
显示历史中的上一条输入。 | Ctrl+P |
history.next |
显示历史中的下一条输入。 | Ctrl+N |
history.search.start |
启动历史反向搜索。 | Ctrl+R |
history.search.submit |
提交反向搜索中选中的匹配项。 | Enter |
history.search.accept |
反向搜索时接受建议项。 | Tab |
导航(Navigation)
| 命令 | 作用 | 按键 |
|---|---|---|
nav.up |
列表中向上移动选择。 | Up |
nav.down |
列表中向下移动选择。 | Down |
nav.dialog.up |
对话框选项内上移。 | Up、K |
nav.dialog.down |
对话框选项内下移。 | Down、J |
nav.dialog.next |
移动到对话框中的下一项/问题。 | Tab |
nav.dialog.previous |
移动到对话框中的上一项/问题。 | Shift+Tab |
J/K 这组按键专为不需要文本输入的对话框场景设计(源码中对应 DIALOG_NAVIGATION_UP/DOWN 的注释说明),与 Emacs 风格编辑键 Alt+B/Alt+F 等并存于不同上下文。
建议与补全(Suggestions & Completions)
| 命令 | 作用 | 按键 |
|---|---|---|
suggest.accept |
接受内联建议。 | Tab、Enter |
suggest.focusPrevious |
移动到上一个补全选项。 | Up、Ctrl+P |
suggest.focusNext |
移动到下一个补全选项。 | Down、Ctrl+N |
suggest.expand |
展开内联建议。 | Right |
suggest.collapse |
收起内联建议。 | Left |
文本输入(Text Input)
| 命令 | 作用 | 按键 |
|---|---|---|
input.submit |
提交当前提示词。 | Enter |
input.queueMessage |
将当前提示词排队,待当前任务结束后处理。 | Tab |
input.newline |
插入换行而不提交。 | Ctrl+Enter、Cmd/Win+Enter、Alt+Enter、Shift+Enter、Ctrl+J |
input.openExternalEditor |
在外部编辑器中打开当前提示词或计划。 | Ctrl+G、Ctrl+Shift+G |
input.deprecatedOpenExternalEditor |
已弃用的打开外部编辑器命令。 | Ctrl+X |
input.paste |
从剪贴板粘贴。 | Ctrl+V、Cmd/Win+V、Alt+V |
应用控制(App Controls)
| 命令 | 作用 | 按键 |
|---|---|---|
app.showErrorDetails |
切换显示调试控制台,查看详细错误信息。 | F12 |
app.showFullTodos |
切换显示完整 TODO 列表。 | Ctrl+T |
app.showIdeContextDetail |
显示 IDE 上下文详情。 | F4 |
app.toggleMarkdown |
切换 Markdown 渲染。 | Alt+M |
app.toggleCopyMode |
在备用缓冲区(alternate buffer)模式下切换复制模式。 | F9 |
app.toggleMouseMode |
切换鼠标模式(滚动与点击)。 | Ctrl+S |
app.toggleYolo |
切换 YOLO(工具调用自动批准)模式。 | Ctrl+Y |
app.cycleApprovalMode |
循环切换审批模式:default(询问)、auto_edit(自动批准编辑)、plan(只读);Agent 忙碌时跳过 plan 模式。 | Shift+Tab |
app.showMoreLines |
非备用缓冲区模式下展开/收起内容块。 | Ctrl+O |
app.expandPaste |
光标位于粘贴占位符上时展开/收起它。 | Ctrl+O |
app.focusShellInput |
焦点从 Gemini 移到活动 shell。 | Tab |
app.unfocusShellInput |
焦点从 shell 移回 Gemini。 | Shift+Tab |
app.clearScreen |
清屏并重绘 UI。 | Ctrl+L |
app.restart |
重启应用。 | R、Shift+R |
app.suspend |
挂起 CLI 并将其转入后台。 | Ctrl+Z |
app.showShellUnfocusWarning |
尝试移开 shell 输入焦点时显示警告。 | Tab |
app.voiceModePTT |
语音模式下按住说话。 | Space |
后台 Shell 控制(Background Shell Controls)
| 命令 | 作用 | 按键 |
|---|---|---|
background.escape |
关闭后台 shell 列表。 | Esc |
background.select |
确认后台 shell 列表中的选择。 | Enter |
background.toggle |
切换当前后台 shell 的可见性。 | Ctrl+B |
background.toggleList |
切换后台 shell 列表。 | Ctrl+L |
background.kill |
结束活动后台 shell。 | Ctrl+K |
background.unfocus |
焦点从后台 shell 移回 Gemini。 | Shift+Tab |
background.unfocusList |
焦点从后台 shell 列表移回 Gemini。 | Tab |
background.unfocusWarning |
尝试移开后台 shell 焦点时显示警告。 | Tab |
app.dumpFrame |
将当前帧导出为快照。 | F8 |
app.startRecording |
开始录制会话。 | F6 |
app.stopRecording |
停止录制会话。 | F7 |
扩展控制(Extension Controls)
| 命令 | 作用 | 按键 |
|---|---|---|
extension.update |
若可用则更新当前扩展。 | I |
extension.link |
将当前扩展链接到本地路径。 | L |
自定义快捷键:keybindings.json
你可以在 home 的 gemini 目录(通常为 ~/.gemini/keybindings.json)创建 keybindings.json 文件,为命令添加备用按键或移除默认按键。源码中该路径由 Storage.getUserKeybindingsPath() 拼接全局 gemini 目录与 keybindings.json 得到。
配置格式
配置是一个 JSON 对象数组,形式与 VS Code 的键位 schema 类似。每个对象必须指定上面参考表中的一个 command 和一个 key 组合:
[
{
"command": "edit.clear",
"key": "cmd+l"
},
{
// 在 command 前加 "-" 前缀表示解绑按键
"command": "-app.toggleYolo",
"key": "ctrl+y"
},
{
"command": "input.submit",
"key": "ctrl+y"
},
{
// 多个修饰符组合
"command": "cursor.right",
"key": "shift+alt+a"
},
{
// 某些 Mac 键盘会把 "shift+option+a" 发送为 "Å"
"command": "cursor.right",
"key": "Å"
},
{
// 部分基础键有特殊的多字符名称
"command": "cursor.right",
"key": "shift+pageup"
}
]
上面的 JSON 注释之所以合法,是因为 keyBindings.ts 的加载器使用 comment-json 的 parseIgnoringComments 解析,即支持带注释的 JSON。
绑定规则要点
- 解绑(Unbinding):移除已有或默认键位时,在
command名前加减号(-)。从源码看,解绑按“精确键位”粒度匹配:loadCustomKeybindings()会用KeyBinding.equals()过滤掉与所写键位完全相同的那一项;如果你试图解绑一个实际未绑定的按键,会得到cannot remove "<key>" since it is not bound错误提示。 - 不自动解绑(No Auto-unbinding):同一按键可以在不同上下文中同时绑定多个命令,因此新建绑定不会自动把该按键从其他命令上解绑。
- 修饰符显式匹配(Explicit Modifiers):键匹配是精确的,例如绑定
ctrl+f只会在恰好按下ctrl+f时触发,不会在ctrl+shift+f或alt+ctrl+f时触发(对应上文matches()的严格比较逻辑)。 - 字面字符绑定(Literal Characters):终端常把复杂组合键(尤其是 macOS 上的
Option键)翻译成特殊字符,修饰符与击键信息随之丢失。例如shift+5可能以%的形式到达,此时必须绑定字面字符%,绑定shift+5永远不会触发。要确认终端实际发送的内容,可开启Debug Keystroke Logging并按F12打开调试日志控制台。 - 支持的修饰符:
ctrl;shift;alt(同义词opt、option);cmd(同义词meta)。这与 KeyBinding 构造函数 中识别的前缀集合一致。 - 基础键(Base Key):可以是任意单个 Unicode 码点,或以下特殊键之一:
- 导航:
up、down、left、right、home、end、pageup、pagedown - 动作:
enter、escape、tab、space、backspace、delete、clear、insert、printscreen - 开关:
capslock、numlock、scrolllock、pausebreak - 功能键:
f1到f35 - 小键盘:
numpad0到numpad9、numpad_add、numpad_subtract、numpad_multiply、numpad_divide、numpad_decimal、numpad_separator
- 导航:
加载与合并逻辑(源码视角)
loadCustomKeybindings() 的行为值得注意:
- 若
keybindings.json不存在(ENOENT),静默回退到defaultKeyBindingConfig,不产生任何错误; - 文件存在时,先复制默认配置,再逐条应用用户配置:新增绑定会被前置(prepend)到绑定数组头部,使其成为 UI 中优先展示的主键位;
- 单条键位解析失败(例如键名非法)不会中断整体加载,而是收集进
errors列表上报,其余配置照常生效; command不是合法枚举值时由 zod schema 校验拦截并给出Invalid command信息。
这一“错误收集而非中断”的策略意味着一条坏配置不会让你失去整份自定义键位,但会在 UI 中提示,便于排查。
上下文相关的特殊快捷键
除注册命令外,还有一批依赖上下文的内置快捷键(这些行为直接内嵌在 UI 组件逻辑中,不通过 keybindings.json 重映射):
Option+B/F/M(仅 macOS):即使终端未配置为“Option 发送 Meta”,也会被解释为Cmd+B/F/M。- 空提示词下按
!:进入或退出 shell 模式。 - 空提示词下按
?:在输入框上方切换显示快捷键面板;按Esc、Backspace、任意可打印字符或已注册的应用热键可关闭。Agent 运行/流式输出期间或出现需操作对话框时面板自动隐藏。再按一次?会关闭面板并把?插入提示词。 - 连按两次
Tab(输入提示词时):在无补全/搜索交互激活时,在极简 UI 与完整 UI 之间切换,所选模式会被记住并在后续会话中生效;首次运行默认完整 UI,单次Tab保持原有补全/焦点行为。 Shift+Tab(输入提示词时):循环切换审批模式:default、auto-edit、plan(Agent 忙碌时跳过 plan)。- 行尾
\+Enter:在单行模式下插入换行而不出单行模式。 - 快速按两次
Esc:若输入非空则清空输入提示;否则进入历史回看(rewind)浏览。 Up/Down方向键:光标位于单行输入顶部/底部时,向后/向前浏览提示词历史。- 数字键(1-9,支持多位数):在带编号选项的选择对话框中直接跳转到对应编号的单选选项,数字输完整后自动确认。
Ctrl+O:光标位于粘贴占位符([Pasted Text: X lines])上时,原地展开或收起其内容。Ctrl+X(展示计划期间):在外部编辑器中打开计划,以协作编辑或批注实现策略。- 双击粘贴占位符(仅 alternate buffer 模式):展开查看完整内容;再次双击收起。
Vim 模式快捷键
通过 /vim 命令或设置 general.vimMode: true 启用 vim 模式后(对应 vim.ts 中的按键处理逻辑与 VimModeContext.tsx 的模式状态),Gemini CLI 支持 NORMAL 与 INSERT 两种模式。
模式切换
| 操作 | 按键 |
|---|---|
| 从 INSERT 进入 NORMAL 模式 | Esc |
| 在光标处进入 INSERT 模式 | i |
| 在光标后进入 INSERT 模式 | a |
| 在行首进入 INSERT 模式 | I |
| 在行尾进入 INSERT 模式 | A |
| 下方插入新行并进入 INSERT | o |
| 上方插入新行并进入 INSERT | O |
| NORMAL 模式下清空输入 | Esc Esc |
NORMAL 模式导航
| 操作 | 按键 |
|---|---|
| 左移 | h |
| 下移 | j |
| 上移 | k |
| 右移 | l |
| 移到行首 | 0 |
| 移到首个非空白字符 | ^ |
| 移到行尾 | $ |
| 前移一个单词 | w |
| 后移一个单词 | b |
| 移到单词尾 | e |
| 前移一个 WORD | W |
| 后移一个 WORD | B |
| 移到 WORD 尾 | E |
| 到第一行 | gg |
| 到最后一行 | G |
| 到第 N 行 | N G 或 N gg |
导航命令支持计数前缀,例如 5j 下移五行、3w 前移三个单词。
NORMAL 模式编辑
| 操作 | 按键 |
|---|---|
| 删除光标下字符 | x |
| 删除到行尾 | D |
| 删除整行 | dd |
| 变更到行尾 | C |
| 变更整行 | cc |
| 前删单词 | dw |
| 后删单词 | db |
| 删到单词尾 | de |
| 前删 WORD | dW |
| 后删 WORD | dB |
| 删到 WORD 尾 | dE |
| 前改单词 | cw |
| 后改单词 | cb |
| 改到单词尾 | ce |
| 前改 WORD | cW |
| 后改 WORD | cB |
| 改到 WORD 尾 | cE |
| 删到行首 | d0 |
| 删到首个非空白字符 | d^ |
| 改到行首 | c0 |
| 改到首个非空白字符 | c^ |
| 从第一行删到当前行 | dgg |
| 从当前行删到最后一行 | dG |
| 从第一行改到当前行 | cgg |
| 从当前行改到最后一行 | cG |
| 撤销上一次修改 | u |
| 重复上次命令 | . |
编辑命令同样支持计数,例如 3dd 删除三行、2cw 修改两个单词。
NORMAL 模式的查找、替换、复制与粘贴
| 操作 | 按键 |
|---|---|
| 查找下一个匹配字符 | f{char} |
| 查找上一个匹配字符 | F{char} |
| 移动到下一个匹配字符之前 | t{char} |
| 移动到上一个匹配字符之后 | T{char} |
| 重复最近一次字符查找 | ; |
| 反向重复最近一次字符查找 | , |
| 删除光标前字符 | X |
| 切换光标下字符大小写 | ~ |
| 替换光标下字符 | r{char} |
| 复制整行 | yy |
| 复制到行尾 | Y 或 y$ |
| 复制单词 / WORD | yw、yW |
| 复制到单词尾 / WORD 尾 | ye、yE |
| 粘贴在光标后 | p |
| 粘贴在光标前 | P |
删除与变更操作符还能与字符查找动作组合,因此 dfx、dtx、cFx、cTx 等命令均受支持。
平台差异与已知限制
快捷键的可用性受终端与运行环境影响,官方明确列出以下限制(适用于当前仓库版本所述行为):
- Windows Terminal:
shift+enter仅 1.25 及以上版本支持;shift+tab在 Node 20 及 Node 22 的早期版本上不受支持(该问题已有对应 issue 记录,见仓库 issue 编号 20314)。
- macOS 自带 Terminal:
- 不支持
shift+enter(多行输入请改用其他input.newline绑定,如Ctrl+Enter、Alt+Enter或Ctrl+J)。
- 不支持
结合前文的平台感知键位设计(撤销/重做的平台分支、修饰符显示映射),可以推断 Gemini CLI 的按键体系在实现层面始终将“同一语义命令、多平台多按键”作为一等公民处理,这也是自定义 keybindings.json 时应当遵循的思路:为新平台或新终端补充绑定,而不是依赖隐式推导。
快捷键文档的自动生成机制
keyboard-shortcuts.md 中从 <!-- KEYBINDINGS-AUTOGEN:START --> 到 <!-- KEYBINDINGS-AUTOGEN:END --> 的表格区块并非手写维护,而是由 scripts/generate-keybindings-doc.ts 从 keyBindings.ts 的 commandCategories、commandDescriptions 与 defaultKeyBindingConfig 中生成:
- 脚本按类别渲染 Markdown 表格,键位显示经由 formatKeyBinding() 以通用(
Cmd/Win)风格格式化并去重; - UNDO/REDO 会专门合并 win32/darwin/linux 三个平台的变体,保证文档覆盖全平台键位;
- 生成内容通过
injectBetweenMarkers注入到文档标记之间(见 scripts/utils/autogen.ts),再经 Prettier 格式化; - 可用
npm run docs:keybindings重新生成文档,或附加--check参数仅校验文档是否为最新(过时时报错并提示重新生成)。
这意味着当你阅读本仓库其他 PR 时,若默认键位发生变化,文档中的表格会随之自动更新——参考表与源码行为的一致性由该机制保证,而非人工同步。
小结
Gemini CLI 的快捷键体系由三部分组成:keyBindings.ts 中数据驱动的默认命令-键位映射(精确匹配、平台感知)、~/.gemini/keybindings.json 的增量覆盖机制(注释 JSON、zod 校验、错误收集、前置插入),以及一批上下文相关与 Vim 模式的内置快捷键。日常使用中,? 面板可即时查阅面板内快捷键;深度定制时,优先记住三条规则——修饰符显式匹配、组合键需按终端实际发送的字符绑定、新建绑定不会自动解绑旧绑定——再用 F12 调试控制台验证终端实际发出的键事件,即可完成从“能用”到“顺手”的键位改造。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00