Claude CodeをWezTermで使うときの通知設定
WezTermはClaude Codeのデスクトップ通知が既定の対象に入っていません。ベルとOSC 9のNotification hookで受け取る方法をまとめます。
このTipsでできること
WezTermはClaude Codeのデスクトップ通知が既定の通知対象に入っていないターミナルです。ベル文字での気づき方と、OSC 9を使ったNotification hookでの文言付き通知、WezTerm側の表示条件の絞り込みまでを扱います。
WezTermは通知の対応リストに入っていない
Claude Codeはタスク完了時や、権限確認の応答待ちのまま離席したと判断したときにNotificationイベントを発火します。これを画面の外まで届けるデスクトップ通知は、既定ではGhostty・Kitty・iTerm2の3つでしか動きません。WezTermはこの3つに含まれておらず、preferredNotifChannelが既定値の"auto"のままだと何も起こりません。Terminal.appのようにベルへ自動フォールバックする例外もないため、WezTermだけが完全な無音状態で放置されます。
まず疑うべきは設定漏れではなく、対応リストそのものにWezTermが入っていないという仕様です。バグでも見落としでもなく、公式ドキュメントが明記している既定挙動です。
WezTermはRust製のクロスプラットフォーム端末で、Linux・macOS・Windows・FreeBSD・NetBSDで動きます。長時間かかるリファクタリングや大量のテスト実行を任せて離席する運用ほど、この差が実際に困る場面です。
ベル文字でまず気づけるようにする
最も手早い対処はpreferredNotifChannelを"terminal_bell"に切り替えることです。
{
"preferredNotifChannel": "terminal_bell"
}この設定にすると、Claude CodeはターミナルにASCIIのBEL文字を送るようになります。WezTermはBELを受け取るとaudible_bellの設定に従ってベルを鳴らします。既定値は"SystemBeep"で、追加設定なしにシステムの通知音が鳴ります。音を止めたいときは"Disabled"を指定します。音の代わりに画面をわずかに光らせたい場合は、visual_bellで背景色やカーソル色を一瞬変える設定も選べます。
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.audible_bell = 'Disabled'
config.visual_bell = {
fade_in_duration_ms = 75,
fade_out_duration_ms = 75,
target = 'CursorColor',
}
return configここまでは音や色で気づく手段で、通知センターに文言付きのカードは出ません。離席中に本文まで確認したいなら、次のNotification hookが要ります。
OSC 9でデスクトップ通知を出す
Claude CodeのNotification hookは、JSON出力にterminalSequenceというフィールドを含められます。制御端末を持たないhookプロセスの代わりに、Claude Code自身がエスケープシーケンスを書き出す仕組みです。このフィールドはv2.1.141で追加されました。許可されるOSCシーケンスは限定されていて、OSC 9はiTerm2・ConEmu・Windows Terminal・WezTermの通知として扱われると公式ドキュメントに明記されています。OSC 777はurxvt・Ghostty・Warp向けの扱いで、WezTermはこの一覧には含まれていません。WezTerm自体はOSC 777の通知シーケンスも受け付けますが、Claude Code側のterminalSequenceが対応ターミナルとして案内しているのはOSC 9のほうなので、hookから書き出す形式はOSC 9に揃えておくと迷いません。
次のhookは、Notificationイベントが発火するたびにOSC 9で通知の本文(message)を渡します。OSC 9が運べるのは本文の1系列だけで、タイトルは含まれません。タイトルも表示したい場合はOSC 777(\e]777;notify;<title>;<body>\e\\)を使う方法があり、WezTermはこのシーケンスを受け付けます。ただしClaude Code docsのOSC 777対応ターミナル一覧にWezTermは載っていないため、terminalSequenceから書き出す形式としてはOSC 9を基本にするのが無難です。
{
"hooks": {
"Notification": [
{
"hooks": [{ "type": "command", "command": "~/.claude/hooks/wezterm-notify.sh" }]
}
]
}
}#!/bin/bash
input=$(cat)
body=$(jq -r '.message // "Needs your attention"' <<<"$input")
seq=$(printf '\033]9;%s\007' "$body")
jq -nc --arg seq "$seq" '{terminalSequence: $seq}'terminalSequenceはClaude Code自身がインタラクティブセッションの画面表示中にしか書き出しません。-pのヘッドレスモードやAgent SDK経由のセッションでは無視される点は覚えておいてください。
Notification hookへの入力にはmessage本文のほかにtitleとnotification_typeも渡されます。notification_typeの値はpermission_prompt(権限確認待ち)やidle_prompt(応答後の放置)など複数あり、matcherで絞り込めば種類ごとに別の通知を出し分けられます。権限確認のときだけWezTermへ通知したい場合は次のようにします。
{
"hooks": {
"Notification": [
{
"matcher": "permission_prompt",
"hooks": [{ "type": "command", "command": "~/.claude/hooks/wezterm-notify.sh" }]
}
]
}
}matcherを省略した場合の挙動が、これまでの例で使ってきた「全種類で発火」です。
動作確認だけなら、hookを介さずターミナルへ直接エスケープシーケンスを流し込んでも同じ通知が出ます。
printf '\033]9;%s\007' "Claude Code test notification"このコマンドを実行してWezTermの画面にトースト通知が出れば、hookの経路も同じ形式で届きます。出ない場合は、macOSやLinuxのOS側でWezTermに通知権限が付与されているかを先に確認してください。
WezTerm側で表示条件を絞り込む
WezTermには受け取った通知をどう表示するかを制御するnotification_handlingという設定キーがあります。バージョン20240127-113634-bbcac864以降が対象で、手元の環境が対応しているかはwezterm --versionで確認できます。既定値は"AlwaysShow"で、フォーカス状態に関係なく常に表示します。
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
config.notification_handling = 'SuppressFromFocusedWindow'
return config応用: bellイベントだけでトースト通知を出す
Notification hookを書かなくても、WezTermのbellイベントを使えば似た体験に近づけられます。preferredNotifChannelを"terminal_bell"にした状態で、~/.wezterm.luaに次のハンドラを足すと、ベルが鳴るたびにWezTerm自身がトースト通知を出します。
local wezterm = require 'wezterm'
local config = wezterm.config_builder()
wezterm.on('bell', function(window, pane)
window:toast_notification('Claude Code', 'Needs your attention', nil, 4000)
end)
return configこの方法には見落としやすい制約があります。bellイベントが受け取るのはBEL文字が鳴った事実だけで、タスク完了なのか権限確認待ちなのかを区別する本文は含まれていません。表示できるのは固定文言だけで、Notification hookのOSC 9のように実際のメッセージを差し込むことはできません。「何かが起きた」に気づければ十分な用途なら、hookスクリプトを書かずに済む分だけ手早い選択肢です。
3つの手段の使い分け
| 手段 | 出せる情報 | 追加で必要な設定 | 向いている場面 |
|---|---|---|---|
terminal_bellのみ | 出せる情報音か画面の色変化 | 追加で必要な設定Claude Code側の設定1行 | 向いている場面まず気づければ十分な場合 |
| Notification hook + OSC 9 | 出せる情報通知の本文 | 追加で必要な設定hookスクリプト1本 | 向いている場面内容まで確認してから戻りたい場合 |
bellイベント + toast_notification | 出せる情報固定の文言 | 追加で必要な設定~/.wezterm.luaへの追記のみ | 向いている場面hookスクリプトを増やしたくない場合 |
音だけで足りるなら1行の設定で終わり、本文まで見たいならNotification hookを足す、hookを増やしたくないならWezTerm側のLua設定で完結させる、という順で選べます。3つは互いに排他ではなく、terminal_bellとNotification hookは並行して動く独立した仕組みなので、両方同時に有効にしても構いません。
普段はWezTermの画面を前面に出したまま作業し、席を外したときだけ気づきたいという要望であれば、ベルとhookを両方仕込んでおいても実害はありません。片方が環境の都合で届かなくても、もう片方が保険になります。設定を足すごとに元の挙動が消えるわけではないので、まずは手早いベル通知から試し、物足りなければhookを足していく順番で困りません。
よくあるつまずき
tmuxの中でWezTermを使っている場合は、~/.tmux.confにallow-passthroughを設定していないと、BELもOSC 9もtmuxに飲み込まれて外側のWezTermまで届きません。tmux固有の設定手順はtmux配下でのClaude Code設定にまとめています。
SSH越しに作業している場合、WezTermのSSHドメインを経由したときにOSCシーケンスがどこまで転送されるかは接続方式に依存します。まずは同一端末内、同一マシン上で通知が出ることを確認してから、リモート接続の設定を切り分けるほうが原因の特定は早くなります。
通知が出ないときは次の順で切り分けます。まずwezterm --versionでnotification_handlingの対応バージョン(20240127-113634-bbcac864以降)を満たしているか確認します。次に/configのLocal notificationsが意図した値(terminal_bellなど)になっているかを見ます。最後に、printfでの直接テストが通るのにNotification hook経由だけ届かない場合を切り分けます。hookスクリプト自体に実行権限(chmod +x)が付いているか、jqがインストールされているかを確認してください。terminalSequenceはJSON出力の一部として渡す必要があるため、スクリプトの標準出力に余計な文字列が混ざるとフィールドごと無視されます。
macOSでは、テスト用のコマンドを実行してもウィンドウの外に通知が出ないことがあります。この場合の原因は設定ファイルではなく、システム設定の通知許可でWezTermそのものが許可されていないケースがほとんどです。一度でも通知を拒否した覚えがあると、以降は静かに握りつぶされ続けるため、システム設定側の許可状態を先に見直したほうが早く原因にたどり着けます。
Notification hook自体の書き方や、他のイベントと組み合わせた実装パターンはClaude Code Hooks実例カタログにまとまっています。preferredNotifChannelの全体像や、対応ターミナルごとの違いはClaude Code通知の設定を参照してください。
まとめ
WezTermでは、Claude Codeのデスクトップ通知はそのままでは届きません。まずpreferredNotifChannelを"terminal_bell"にしてベルで気づける状態を作り、文言付きの通知が欲しければNotification hookでOSC 9を書き出します。WezTerm側のnotification_handlingで表示条件を絞れば、フォーカス中の画面に毎回重なる煩わしさも減らせます。
まずはベル通知から試し、離席が多いなら文言付きの通知へ段階的に足していく進め方が、設定ファイルをいじる回数を最小限に抑えられます。