
MacOS TerminalアプリのClaude Codeに Shift + Enter で改行できるように設定してみた(おまけ:Enterキーの歴史問題)
はじめに
自分は普段MacOSのTerminalアプリでClaude Codeを使っていますが、ずっと気になっていたことがありました。VSCodeやCursorなどのエディタではShift + Enterで改行できるのに、TerminalアプリだとShift + Enterは普通のEnterと同じ扱いになってしまい、メッセージがそのまま送信されてしまいます。
改行するにはOption + Enterを使わないといけないのですが、エディタの癖で毎回Shift + Enterを押してしまい、意図せずメッセージが送られてしまうことがよくありました。
ターミナルの仕様上、EnterとShift + Enterは同じ信号(0x0d)として扱われるため、Terminalアプリの設定だけではShift + Enterを改行に変えることができません(詳しくは記事末尾の「Enterキーの歴史問題」で解説)。そこで、OS側でキー入力を変換できるKarabiner-Elementsを使って、Terminalアプリ上でのみShift + Enterをリマップすることで解決できました。
最初は単純にShift + EnterをOption + Enterにマッピングすればいいかと思ったのですが、調べていくうちにCtrl + J(LF:Line Feed)の方がターミナル環境全般で改行として広く通用するキーバインドだとわかったので、最終的にCtrl + Jへのマッピングを採用しました。この記事ではその手順を紹介します。
記事の最後に、なぜTerminalアプリでShift + Enterが効かないのか、Enterキーの歴史的な背景も解説します。
検証環境
- MacOS (Sequoia) Terminalアプリ
- Claude Code (v2.1.89)
- Homebrew (v5.1.6)
手順
1. Karabiner-Elementsのインストール
brew install --cask karabiner-elements
インストールできたら、アプリを開いて初期設定をします(キーボードタイプの選択、権限設定など)。
2. 権限の付与
初回起動時に、以下の権限許可を求められるので許可してください。
- System Settings → Privacy & Security → Input Monitoring →
Karabiner-Core-Serviceを有効にする

- System Settings → General → Login Items & Extensions → Driver Extensions →
.Karabiner-VirtualHIDDevice-Managerを有効にする



3. karabiner.jsonの編集
~/.config/karabiner/karabiner.jsonを編集します。
profilesの部分はアプリの初期設定で自動生成されるので、complex_modificationsのrules部分を追加してください。なお、自分のキーボードはUS配列なので、keyboard_type_v2は"ansi"となってます。日本語キーボードの方は初期設定か、もしくはKarabiner-ElementsアプリのVirtual Keyboard → Keyboard Type設定に、JISを選んでいただければ、"jis"になるはずです。

以下はShift + EnterをCtrl + Jにマッピングする設定です。
{
"profiles": [
{
"complex_modifications": {
"rules": [
{
"description": "Shift+Enter to Ctrl+J in Terminal.app",
"manipulators": [
{
"type": "basic",
"from": {
"key_code": "return_or_enter",
"modifiers": {
"mandatory": ["shift"]
}
},
"to": [
{
"key_code": "j",
"modifiers": ["control"]
}
],
"conditions": [
{
"type": "frontmost_application_if",
"bundle_identifiers": [
"^com\\.apple\\.Terminal$"
]
}
]
}
]
}
]
},
"name": "Default profile",
"selected": true,
"virtual_hid_keyboard": { "keyboard_type_v2": "ansi" }
}
]
}
Option + Enterにマッピングしたい場合は、"to"の中身を以下のように書き換えてください。
{
"key_code": "return_or_enter",
"modifiers": ["option"]
}
設定を保存すれば、Terminalアプリ上でShift + Enterが改行として動作するようになります。
おまけ:Enterキーの歴史問題
なぜTerminalアプリではShift + Enterが効かないのか? その背景には、ターミナルエミュレータの歴史的な仕様があります。
ターミナルのキー入力の仕組み
MacOSはUNIXベースで作られていて、Terminalアプリのキー入力は、古いターミナル規格の仕様に基づいています。

Enterキーは、元々テンキー(もしくはそれ以上のキーがあった古いキーボード)時代のSS3(1978年、VT100)規格に由来します。一方、現在のフルサイズキーボードの多くのキーは、その後のCSI(1979年以降、VT220〜)規格に準拠しています。
参考:VT100 User Guide — Chapter 3(Table 3-8 ANSI Mode Auxiliary Keypad Codes)
SS3規格の制約

SS3規格では、キーコードは以下のフォーマットで表現されます。
ESC O <1バイト>
ESC Oの後ろに1バイトのみが入る構造なので、修飾キー(Shiftなど)との組み合わせ情報を含める余地がありません。
キーパッドEnter = ESC O M = 0x1b 0x4f 0x4d
Other keys such as CTRL and SHIFT do not transmit codes when typed, but modify the codes transmitted by other keys.
VT100キーボードではShiftキーも存在していましたが、独立した信号として送信されるのではなく、キーボード内部で完結するモード切り替えとして使われていました。例えば、Aを押すとaが送られ、Shift + AでAが送られる。1を押すと1、Shift + 1で!が送られる、といった具合です。
現在のTerminalアプリでの動作
つまり、SS3由来のEnterキーは修飾キーとの組み合わせが定義されておらず、TerminalアプリではEnterもShift + Enterも同じ0x0d(CR:キャリッジリターン)として処理されます。
以下のPythonスクリプトをTerminalアプリで実行すると、キー入力のバイトコードを確認できます(Ctrl + Cで終了)。
python3 -c "
import sys, tty, termios
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
tty.setraw(fd)
try:
while True:
b = sys.stdin.buffer.read(1)
if b == b'\x03': break
sys.stdout.buffer.write(('0x{:02x}\r\n'.format(b[0])).encode())
sys.stdout.buffer.flush()
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
"
Karabiner-Elementsでマッピングする前に試すと、EnterもShift + Enterも同じ結果になります。
0x0d
Shift + EnterをCtrl + Jにマッピングした後は、以下のように変わります。
0x0a
0x0dはCR(Carriage Return)、0x0aはLF(Line Feed=改行)です。これにより、Terminalアプリ上のClaude CodeでもShift + Enterで改行できるようになります。
おわりに
TerminalアプリでShift + Enterが効かない原因は、VT100時代のSS3規格に由来する歴史的な制約でした。Karabiner-Elementsを使えば、Terminalアプリ上でのみキーをリマップできるので、他のアプリの挙動に影響を与えずに対応できます。
同じ悩みを持っている方の参考になれば幸いです。









