> 記事

ターミナルで Shift+Enter が改行にならないのはなぜ?kitty キーボードプロトコル入門

Claude Code などのツールで、Shift+Enter が改行になるターミナルと、そのまま送信されるターミナルがあります。その理由と kitty キーボードプロトコルを解説します。

公開

目次
  1. ターミナルはキー入力をどう伝えているか
  2. kitty キーボードプロトコル:キーの新しい伝え方
  3. ターミナルによって使えたり使えなかったりする理由
  4. SSH 経由で使うとき
  5. Shift+Enter が使えないとき
  6. キーボードの様子が急におかしくなったら
  7. ShellRS では

Claude Code のような AI コマンドラインツールで長めのプロンプトを書き、改行しようと Shift+Enter を押すと、Ghostty や iTerm2 では改行になります。ところが別のターミナルや、SSH でサーバーに入ってから使うと、同じキーで書きかけの文章が送信されてしまいます。ツールの不具合ではなく、ターミナルがキー入力をプログラムに伝える方法が違うためです。この記事では、その理由と、背景にある kitty キーボードプロトコルを説明します。

ターミナルはキー入力をどう伝えているか

ターミナルの中で動くプログラムには、キーボードは見えていません。キーを押すたびに、ターミナルがそれを 1 つまたは数個の文字に変換してプログラムに送り、プログラムはその文字を受け取って、何が押されたかを知ります。逆に、プログラムも特別な文字を送ってターミナルを操作します。ウィンドウのタイトルを変えたり、デスクトップ通知を出したりするしくみは「OSC とは」で紹介しています。

この変換のルールは何十年も前に決まったものです。当時のターミナルは大型コンピューターにつながったテレタイプで、キーの数も今よりずっと少ないものでした。このルールでは Enter は決まった 1 つの文字で、「Shift を押しながら」を表す方法がありません。そのため Shift+Enter を押しても、ターミナルが送るのは Enter だけを押したときとまったく同じです。プログラムは同じ文字を受け取るので Enter として扱うしかなく、メッセージが送信されてしまいます。

こうした「衝突」は Shift+Enter だけではありません。Tab と Ctrl+I は同じ文字を送りますし、Esc と Ctrl+[ も同じです。Vim を使う人なら、Tab と Ctrl+I に別々の機能を割り当てられないことに気づいたことがあるかもしれません。

kitty キーボードプロトコル:キーの新しい伝え方

kitty はターミナルアプリの名前です。作者の Kovid Goyal がキー入力の新しい表し方を設計しました。これが kitty キーボードプロトコルで、「CSI u」とも呼ばれます。この方式では、押したキーごとに、どのキーか、どの修飾キー(Shift、Ctrl、Alt など)を押していたかを明記します。Shift+Enter と Enter は別のものになり、プログラムは Shift が押されていたことがすぐにわかります。

すぐに広まったのは、慎重な設計のおかげです。このプロトコルは最初はオフになっています。プログラムは起動時にターミナルへ「このプロトコルに対応していますか」と尋ね、対応しているという返事があればオンにしてもらい、終了するときにオフに戻します。このプロトコルを知らない古いプログラムは尋ねないので、ターミナルは従来どおりのルールで送り、何も壊れません。

Shift+Enter のほかにも、Tab と Ctrl+I を区別したり、キーを離したタイミングを知ったり、Esc 単独の入力に少し待たずに反応したりできるようになります。名前に kitty とありますが、今では多くのターミナルとプログラムが採用しています。ターミナルでは Ghostty、WezTerm、foot、Alacritty、Windows Terminal など、プログラムでは Neovim、Helix、fish、Claude Code などです。

ターミナルによって使えたり使えなかったりする理由

Shift+Enter で改行するには、ターミナルとプログラムの両方が協力する必要があります。ターミナルは「Shift が押されている」ことを伝えられなければならず、プログラムは尋ねて、それを受け取らなければなりません。

ターミナル Claude Code での Shift+Enter
Ghostty、kitty、iTerm2、WezTerm、Warp、macOS 標準の「ターミナル」、Windows Terminal そのまま使える
foot、Alacritty 0.16 以降、そのほか kitty キーボードプロトコルに対応したターミナル そのまま使える(Claude Code 2.1.269 以降)
VS Code、Cursor、Zed、Alacritty 0.16 より前 Claude Code で /terminal-setup を一度実行する
GNOME Terminal、PyCharm など JetBrains IDE のターミナル 使えない。下の代わりの方法を使う

1 行目は Claude Code が知っているターミナルで、最初から使えます。2 行目のターミナルは知らないかもしれませんが、2.1.269 以降の Claude Code は kitty キーボードプロトコルに対応しているかをターミナルに直接尋ね、対応していれば使います。3 行目のターミナルはこのプロトコルに対応していないため、/terminal-setup がターミナルの設定ファイルにキー設定を 1 つ追加し、Shift+Enter で Enter とは違う文字列が送られるようにします。最後の行は、プロトコルにも対応しておらず、こうした設定もできません。

ここに kitty キーボードプロトコルの意味があります。プログラムは世の中のターミナルを 1 つずつ覚えなくても、一度尋ねるだけでキーを区別できるかどうかがわかります。

SSH 経由で使うとき

SSH でサーバーに入ってから Claude Code を実行する人も多いでしょう。このときプログラムはサーバー上で動いていて、手元でどのターミナルを使っているかは、たいていわかりません。ここで kitty キーボードプロトコルが役に立ちます。問い合わせも返事もただの文字なので、SSH がそのまま運び、サーバー側の設定は何もいりません。手元のターミナルがこのプロトコルに対応していて、Claude Code が 2.1.269 以降であれば、サーバー上でも Shift+Enter で改行できます。

間に tmux がある場合は事情が違います。tmux 自体もターミナルなので、プログラムが尋ねる相手は tmux です。そして tmux は(3.8 の時点で)まだ kitty キーボードプロトコルに対応していません。回避するには tmux 独自の「拡張キー」をオンにします。~/.tmux.conf に次の 2 行を加えてください。

set -s extended-keys on
set -as terminal-features 'xterm*:extkeys'

そのあと tmux source-file ~/.tmux.conf を実行するか、tmux を起動し直します。

Shift+Enter が使えないとき

Claude Code では、次の 2 つの改行方法がどのターミナルでも設定なしで使えます。

  • Ctrl+J を押す
  • \ を入力してから Enter を押す

Option+Enter(Windows と Linux では Alt+Enter)でも改行できますが、macOS ではたいていのターミナルで、先に設定で Option キーを Meta キーとして使うようにしておく必要があります。ほかのツールの改行キーはそれぞれ違うので、各ツールの説明を確認してください。

キーボードの様子が急におかしくなったら

このプロトコルを使っているプログラムがクラッシュしたり強制終了されたりすると、ターミナルを元に戻せないまま終わることがあります。コマンドラインに戻ると、Ctrl+C が効かない、画面に ;5u のような文字が出る、といったおかしなことが起こります。そのときは reset と入力して Enter を押せば、たいてい元に戻ります。このプロトコルは Enter や Backspace といった基本的なキーをあえて変えないので、このコマンドはいつでも入力できます。それでもだめなら、そのタブを閉じて開き直してください。

ShellRS では

ShellRS は無料でオープンソースの SSH クライアントで、kitty キーボードプロトコルに対応しています。

  • Claude Code などのツールから問い合わせがあると、ShellRS は対応していると答え、ツールの実行中はプロトコルに従ってキーを送ります。そのため Shift+Enter で改行できます(Claude Code 2.1.269 以降)。Option+Enter(Windows と Linux では Alt+Enter)もこれまでどおり使えます。
  • リモートサーバーで実行しても同じで、サーバー側の設定はいりません。
  • 普通のシェルではこのプロトコルを求めるプログラムがないので、Shift+Enter は Enter と同じです。複数行のコマンドを書いてから送りたいときは、Compose pane(⌘⇧E、Windows と Linux では Ctrl+Shift+E)を使えます。ここでは Shift+Enter で改行し、Enter で送信します。

詳しくは ShellRS のマニュアルを参照してください。ShellRS はダウンロードページから入手できます。

ShellRS を試す

無料でオープンソースの SSH クライアント。ターミナル、SFTP、ポートフォワーディングを 1 つのウィンドウで。macOS、Windows、Linux に対応。