Claude CodeでxtermのCtrl+Enterを改行に割り当てられない理由
xtermやVTE系の端末では、keybindingsに書いたctrl+enterが効かず送信されます。modifyOtherKeysが有効にならない条件と、Ctrl+Jなど今すぐ使える改行の手段を載せます。
xtermやVTE系の端末でkeybindings.jsonに"ctrl+enter": "chat:newline"を書いても、Ctrl+Enterは改行にならず、メッセージが送信されます。原因は設定の書き間違いではありません。Claude Codeがxtermのmodifyotherkeys(修飾キー付きキーを区別して送る拡張モード)を、限られた端末でしか有効にしないためです。
この仕様はGitHubのissue #96526で報告されており、openのままです。直るまでの間は、設定なしで動く改行キーに切り替えるのが近道です。
症状: ctrl+enterのバインドが一度も発火しない
再現条件は単純です。modifyOtherKeysには対応しているが、kitty keyboard protocol(kittyが提唱したキー入力の拡張規格)には答えない端末で、次の設定を入れます。
{
"context": "Chat",
"bindings": {
"ctrl+enter": "chat:newline"
}
}claudeを起動し、文字を打ってCtrl+Enterを押すと、期待する「改行」ではなく「送信」になります。報告者の環境は次のとおりです。
- Claude Code 2.1.281、Linux(Fedora)
- modifyOtherKeysに対応するようパッチを当てたVTE系の端末(
VTE_VERSION=8401) TERM=xterm-256colorで、TERM_PROGRAMは未設定(Claude Codeからはvte-basedとして見える)
端末が悪いわけでも、keybindingsの書式が悪いわけでもありません。Ctrl+Enterの押下が、Claude Codeに届く時点で素のEnter(CR)になっているのです。
なぜ有効にならないのか: modifyOtherKeysがkittyに相乗りしている
issueの本文とコメントによると、Claude Codeの拡張キーモードは1つのスイッチで管理されています。このスイッチがオンになる条件は次の2つだけです。
| 条件 | 内容 |
|---|---|
| 許可リストにある端末 | 内容iTerm.app、kitty、WezTerm、ghostty、tmux、windows-terminal、WarpTerminal |
| kittyプロトコルへの応答 | 内容起動時の問い合わせCSI ? uに端末が答える |
スイッチがオンのときだけ、kittyのキー入力モードを要求する列に続けて、modifyOtherKeysを有効にするCSI > 4 ; 2 mが送られます。つまりmodifyOtherKeysは、kittyプロトコルと必ずセットで有効になります。単独で有効にする経路はなく、xterm本体や、modifyOtherKeysだけに対応した端末は、どちらの条件にも当たりません。
端末の名前はTERM_PROGRAMが設定されていればその値、なければvte-basedやxtermのような値で判定されます。
逆側の処理は実装済みです。TERM_PROGRAM=WezTerm claudeで許可リストに乗せて起動すると、Claude CodeはCSI > 4 ; 2 mを送り、Ctrl+Enterは設定どおり改行になります。足りないのは、有効にするかどうかを決める入口のゲートだけだと報告されています。
公式ドキュメントの記述との対応
keybindingsのドキュメントは、拡張キーを報告しない端末ではCtrl+Enterが素のEnterとして届くと書いています。cmd系の修飾キーが使えるのも、kittyプロトコルかxtermのmodifyOtherKeysに対応した端末に限られます。Ctrl+Enterが効かない状況の説明として、issueの内容と同じ向きです。
自分の環境が当たるかを確かめる
次のコマンドで、Claude Codeに端末がどう見えているかの目安を取れます。
echo "TERM_PROGRAM=$TERM_PROGRAM"
echo "TERM=$TERM"
echo "VTE_VERSION=$VTE_VERSION"
echo "XTERM_VERSION=$XTERM_VERSION"TERM_PROGRAMが空で、TERMがxterm-256color、VTE_VERSIONかXTERM_VERSIONが入っていれば、この記事の条件に近い環境です。ただしfootやAlacritty 0.16以降のように、kittyプロトコルに応答する端末なら、同じ表示でも拡張キーは有効になります。
自分の端末で効く改行キーの早見表
terminal-configのShift+Enter対応表から、xterm系・VTE系の環境で当たりそうな行を抜き出すと次のとおりです。
| 端末 | Shift+Enter | 備考 |
|---|---|---|
| foot、Alacritty 0.16以降 | Shift+Enter設定なしで動く | 備考kittyプロトコル対応。Claude Code v2.1.269以降が必要 |
| Alacritty 0.16より前 | Shift+Enter/terminal-setupを1回実行 | 備考端末の設定ファイルにバインドが書き込まれる |
| gnome-terminal(VTE系) | Shift+Enter使えない | 備考Ctrl+Jか\+Enterを使う |
| xtermそのもの、Konsole | Shift+Enter表に載っていない | 備考まずCtrl+Jで確かめる |
表に載っていない端末の動作は、ここでは断定しません。Ctrl+Jと\+Enterは端末を選ばないので、迷ったらこの2つが確実です。/terminal-setupは、tmuxやscreenの中ではなく、外側の端末で直接実行します。
今すぐ使える改行の手段
直るまでの回避策は、ctrl+enterに頼らないことです。
設定なしで使える改行
Ctrl+J
どの端末でも設定なしで動きます。
chat:newlineの既定の割り当ても、Ctrl+Jです。バックスラッシュ + Enter
行末に
\を打ってからEnterを押します。こちらも端末を選びません。Shift+Enter
kittyプロトコルに対応した端末では設定なしで動きます。gnome-terminalのように「使えない」と書かれた端末もあります。
terminal-configは、Ctrl+Jと\+Enterを「どの端末でも設定なしで動く」手段として挙げています。Shift+Enterは端末ごとに差があり、gnome-terminalとJetBrains系IDEは「利用不可。Ctrl+Jか\+Enterを使う」と書かれています。Shift+Enterの対応表全体と/terminal-setupの使い分けは、terminal-setupでShift+Enterが改行にならないときの対処にまとめています。
Enterの役割を入れ替える
改行を「Ctrl+Enterで」にこだわる理由が、Enterを送信にしたくないだけなら、役割を入れ替える手もあります。terminal-configには、chat:newlineとchat:submitを割り当て直せば、Enterで改行、別のキーで送信にできると書かれています。端末が確実に送れるキーを選んでください。
入れ替えの前に、keybindingsの表で既定の割り当てと、拡張キーに頼るかどうかを見比べておきます。
| アクション | 既定のキー | 拡張キーへの依存 |
|---|---|---|
chat:newline | 既定のキーCtrl+J | 拡張キーへの依存不要(どの端末でも動く) |
chat:submit | 既定のキーEnter | 拡張キーへの依存記載なし |
chat:queueSubmit | 既定のキーCtrl+X Enter | 拡張キーへの依存記載なし |
chat:sendNow | 既定のキーCtrl+Enter、Ctrl+X Ctrl+S | 拡張キーへの依存Ctrl+Enterは必要。Ctrl+X Ctrl+Sはどの端末でも動く |
chat:sendNowのCtrl+Enterは、拡張キーを報告しない端末では素のEnterとして届きます。xterm系でCtrl+Enterが効かない原因は、改行でも送信でも同じです。
ChatコンテキストでEnterをchat:newlineやchat:queueSubmitに割り当て直しても、エージェントパネルの行のようなフッター項目を選択している間は、Enterがその項目を開く動作のままです。入れ替えたあとにEnterが想定どおり動かないときは、プロンプト側にフォーカスがあるかを先に見てください。
{
"context": "Chat",
"bindings": {
"enter": "chat:newline",
"ctrl+j": "chat:submit"
}
}上は書式の例です。ほかのバインドとぶつからないかは、実際に入力して確かめてから使ってください。
どうしてもCtrl+Enterを使いたいとき
issueのコメントには、許可リストの値をTERM_PROGRAMに与えて起動する回避策が載っています。
TERM_PROGRAM=WarpTerminal claudeコメントでは、WarpTerminalが副作用の最も少ない値だと書かれています。WezTermでも動きますが、TERM_PROGRAM_VERSIONも設定しない限りハイパーリンクが無効になり、OSC 133(シェルの統合用エスケープ)も切れるとされています。
この方法は、Claude Codeの端末判定をだましているだけです。Warp向けの挙動が他の機能に及ぶ可能性があり、公式の手順でもありません。シェルのaliasに入れるより、まず単発のコマンドで副作用を見てください。
落とし穴
tmuxの中では結果が変わる
tmuxは許可リストに入っています。一方、terminal-configには、tmux内でShift+Enterを使うにはextended-keysなどの追加設定が必要だと書かれています。外側の端末が対応していても、tmuxの設定が足りなければ素のEnterになります。tmuxを挟んでいる場合は、外側の端末の問題と切り分けて考えてください。
tmuxの設定は、~/.tmux.confに次の4行を足し、tmux source-file ~/.tmux.confで実行中のサーバーに反映します。
set -g allow-passthrough on
set -g focus-events on
set -s extended-keys on
set -as terminal-features 'xterm*:extkeys'extended-keysの2行が、tmuxにShift+Enterと素のEnterを区別させる部分です。allow-passthroughは通知や進捗表示を外側の端末へ通すための行で、改行とは関係ありません。この設定を足しても、Ctrl+Enterが届くかどうかは別に確かめる必要があります。terminal-configが保証しているのはShift+Enterのほうです。
修正の見込み: issueが提案している3つの方向
報告者の提案は3つです。
- modifyOtherKeysを、kittyプロトコルから独立した別の機能として扱う
- 起動時の問い合わせに、modifyOtherKeysの状態を尋ねるXTQMODKEYS(
CSI ? 4 m)を足す - 同期出力の
CLAUDE_CODE_FORCE_SYNC_OUTPUTのように、強制的にオンにする環境変数を用意する
xtermでXTERM_VERSIONが設定されていれば既定でオンにする案も添えられています。コメントでは、2.1.286のバンドルを読んだ投稿者が、これはenhancementではなくバグだと主張しています。同じ要望のissue #83491は、staleとして自動クローズされています。
issueはopenで、3件のコメントはいずれも報告の補足と進捗の問い合わせで、実装方針の回答は載っていません。修正が入るかどうか、入るならどの方式かは決まっていません。chat:newlineにctrl+enterを割り当てたままにしておいても害はありませんが、修正が入るまでは、xterm系ではこのバインドが発火しません。
症状別の切り分け
| 症状 | 考えられる原因 | 次に見るもの |
|---|---|---|
xtermやVTE系でctrl+enterのバインドが発火せず送信になる | 考えられる原因modifyOtherKeysが有効になっていない(この記事) | 次に見るものCtrl+Jか\+Enterに切り替える |
| iTerm2でCtrl+Enterがメニューを開く | 考えられる原因端末側のショートカット | 次に見るものiTerm2のコンテキストメニュー回避策 |
| Ctrl+Enterを「今すぐ送信」に使いたい | 考えられる原因chat:sendNowの割り当て | 次に見るものCtrl+Enterの送信挙動 |
| 組み合わせキーを自分で組みたい | 考えられる原因chordの書式 | 次に見るものkeybindingsのchord |
最後の逆向きの話も押さえておきます。Ctrl+Enterをchat:sendNow(キュー済みのメッセージを今すぐ送る)に使う場合も、拡張キーが届かない端末では同じ理由で素のEnterになります。keybindingsの表は、どの端末でも動く割り当てとしてCtrl+X Ctrl+Sを挙げています。
まとめ
xterm系でctrl+enterが改行にならないのは、Claude Codeがmodifyotherkeysをkittyプロトコルや許可リストの端末にしか有効にしないからで、設定側では直せません。issueがopenの間は、Ctrl+Jか\+Enterを改行の標準手段にし、どうしてもctrl+enterが必要なときだけTERM_PROGRAMの指定を、副作用を承知で試す流れになります。