Claude Code 自定义快捷键
目的:让
Shift + Enter在 Windows Terminal 里真正发送出去,实现换行不发送。 最后更新:2026-10-06
一句话总结
Claude Code 内部已经支持 Shift + Enter 换行(chat:newline),但绝大多数终端默认不会把 Shift + Enter 作为独立按键序列发给程序,终端只会告诉程序"这是 Enter"。所以要让 Shift + Enter 生效,必须在终端这一层手动把一段转义序列注入给 Claude Code。
问题不在 Claude Code,在 Windows Terminal。
为什么需要这一步
| 层次 | 默认行为 | 问题 |
|---|---|---|
| Claude Code | shift+enter → chat:newline(换行) |
✅ 支持 |
| 终端 | 只上报"Enter 被按下"(\r) |
❌ 丢掉 shift 信息 |
| 结果 | Shift + Enter 触发的还是发送消息 |
换行失败 |
Windows Terminal 的键盘增强协议(Kitty keyboard protocol)里,Shift + Enter 对应的 CSI 序列是:
即 JSON 中的 "\u001b[13;2u"。让终端把这个序列发给 Claude Code,问题就解决了。
方案一:改 Windows Terminal(推荐)
打开 settings.json
不要用 VS Code 的 Preferences: Open Default Settings (JSON),那条命令打开的是只读的默认配置。要改的是用户实际配置。
打开设置面板(Ctrl + ,)→ 左下角点「打开 JSON 文件」按钮,即可跳到真实文件。
文件路径分两种安装方式:
| 安装方式 | 路径 |
|---|---|
| Microsoft Store / 预装(打包版) | %LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json |
| 独立安装版 / 预览版 | %LOCALAPPDATA%\Microsoft\Windows Terminal\settings.json |
打开后建议「用 VS Code 打开」,方便格式化、查错。
修改原则
用「插入」,不要全选替换。 这个文件里还有主题、配色、profiles 等等全部配置,覆盖掉等于全部归零。
第一步:加 Action(动作)
找到 "actions" 字段(通常是一个 [] 中括号)。如果整个文件都没有这个字段,可以在顶层 {} 里加上 "actions": []。
在 "actions": [ 里面插入:
第二步:加 Keybinding(键绑定)
找到 "keybindings" 字段(同样通常是 [])。在 "keybindings": [ 里面插入:
两段的 id 必须完全一致——keybindings 靠 id 找到 actions 里对应的动作,对不上就等于没配。
⚠️ JSON 格式注意
Windows Terminal 的 settings.json 通常长这样:
千万不要漏逗号。
- 如果
actions/keybindings里已经有其他项,每个{}之间用英文逗号,隔开 - 如果是空数组,直接放进去,不用加逗号
input的值必须写成"\u001b[13;2u"这种转义写法,不要真的打出 ESC 控制字符——JSON 里放裸 ESC 会导致整个文件解析失败,Terminal 会静默回退到默认配置
验证
改完保存,Terminal 会自动热重载(不用重启)。回到 Claude Code 里按 Shift + Enter,出现新行而不发送,即成功。
如果没生效,打开 PowerShell 执行:
解析报错 = JSON 语法有问题(多半是逗号)。
方案二:改 Claude Code 的 keybindings.json
什么是 keybindings.json
Claude Code 支持自定义快捷键。配置文件位于:
在 Claude Code 里运行 /keybindings 可以直接创建或打开它。
文件格式
顶层必须是 "bindings" 数组,里面每项按 context(生效场景)分组,一个 context 只需要写你真正要改的键。
常用场景 context
| context | 生效时机 |
|---|---|
Global |
任何时候,无视焦点 |
Chat |
输入框聚焦时 |
Confirmation |
权限确认弹窗 |
Transcript |
查看历史对话时 |
Scroll |
可滚动区域聚焦(全屏布局) |
键位写法
| 类别 | 写法 |
|---|---|
| 修饰键 | ctrl alt shift meta(alt 与 meta 在终端里等价,用 meta 代表 Win/Cmd) |
| 特殊键 | escape enter tab space backspace delete up down left right |
| 组合 | + 连接,如 ctrl+shift+p、alt+enter |
| 和弦 | 空格分隔,如 ctrl+x ctrl+s(两键间隔 1 秒内) |
常用动作
| 动作 | 默认键 | context |
|---|---|---|
chat:newline |
ctrl+j |
Chat |
chat:submit |
enter |
Chat |
chat:clearInput |
ctrl+l |
Chat |
chat:externalEditor |
ctrl+x ctrl+e |
Chat |
chat:cycleMode |
shift+tab |
Chat |
app:toggleTodos |
ctrl+t |
Global |
app:toggleTranscript |
ctrl+o |
Global |
history:search |
ctrl+r |
Global |
完整列表见 官方 keybindings 文档。
解绑默认键
值设为 null 即解除绑定:
改键 vs 加键
用户绑定是追加在默认绑定之后的。想换掉某个默认键,必须两个一起写:旧键设 null,新键写目标动作。
只写 ctrl+e 的话,ctrl+g 依然能用——两个都会触发。
关于 Shift + Enter
本机 ~/.claude/keybindings.json 的 Chat context 里已经有:
也就是说 Claude Code 侧不用改,缺的只是终端侧那层注入(方案一)。方案一做完后该绑定才会真正收到按键。
常见报错
| 报错 | 原因 | 修复 |
|---|---|---|
keybindings.json must have a "bindings" array |
少了外层包装 | 包成 { "bindings": [...] } |
"bindings" must be an array |
bindings 不是数组 |
改成 [{ context, bindings }] |
Unknown context "X" |
context 名拼错 | 用官方表里的原名,Chat 首字母大写 |
Duplicate key "X" in Y bindings |
同一 context 里键重复 | 删掉重复项 |
Invalid action for "X" |
动作值不是字符串 | 动作要是 "app:help" 这类字符串,或 null |
错误(error)会让绑定完全不生效,警告(warning)一般还能用。
不可改的键
| 键 | 原因 |
|---|---|
ctrl+c |
中断/退出,硬编码 |
ctrl+d |
退出,硬编码 |
ctrl+m |
在终端里等同于 Enter(都是 CR) |
ctrl+i |
在终端里等同于 Tab |
ctrl+[ |
在终端里等同于 Escape |
ctrl+h |
在终端里等同于 Backspace |
capslock |
Caps Lock 不会传给终端程序 |
两套系统的分工
| 想改的东西 | 改哪里 |
|---|---|
让 Shift + Enter 换行 |
Windows Terminal settings.json(方案一) |
换 Ctrl + L、Ctrl + R 之类 |
~/.claude/keybindings.json(方案二) |
| 终端的复制粘贴、分屏 | Windows Terminal keybindings(ctrl+c 复制等) |
一句话:终端负责"把什么送进来",Claude Code 负责"收到之后干什么"。
本机当前状态(已验证)
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json 中实际内容:
本机装的是 Store/打包版(只有 _8wekyb3d8bbwe 一个包目录,没有 Preview 版),所以配置在 LocalState 下。