Claude CodeをKittyで使うと出る通知アイコンと画像表示の症状
Kittyで通知がkittyのロゴになる、tmuxの中で画像が出ない。2つの未解決issueの中身と、いま手元でできる切り分けをまとめます。
このTipsでできること
KittyでClaude Codeを使うと、キー入力と通知は設定なしで動きます。ただ、通知のアイコンが常にkittyのロゴになる症状と、tmuxの中で画像が出ない症状は、未解決のissueとして報告されています。それぞれ何が起きているのか、手元で何を確かめられるのかをまとめます。
Kittyは既定で通知とキー入力に対応している
Claude Codeの端末設定ページでは、KittyのShift+Enterは設定なしで動くターミナルに数えられています。デスクトップ通知も、既定で送られるのはGhostty・Kitty・iTerm2の3つです。
preferredNotifChannelの値は次のとおりです。
| 値 | 動き |
|---|---|
"auto"(既定) | 動きiTerm2・Ghostty・Kittyでデスクトップ通知を送る |
"kitty" | 動きKittyのデスクトップ通知を送る |
"terminal_bell" | 動きどの端末でもベル文字を鳴らす |
"notifications_disabled" | 動き通知を送らない |
SSH越しの場合も、GhostttyとKittyは追加設定なしで手元のOS通知に転送されると説明されています。通知が来ないときは、まずOS側でターミナルアプリに通知の権限があるかを見ます。tmuxの中ならパススルーも要ります。
ここまでは正常系です。以下の2つが、既知の症状です。
通知がいつもkittyのロゴで表示される
何が起きているか
Linuxで通知が出る点は問題なく、アイコンだけがおかしい、という報告です。Claude Code 2.1.278のKittyで、通知のタイトルが「Claude Code」でも、アイコンはkitty標準のロゴになります。報告者の環境は、CachyOSのniri(Wayland)で通知デーモンはNoctalia 5.1.0、kittyは0.48.2です。2.1.270でもまったく同じ出力だったとされています。
報告者がキャプチャしたClaude Codeの出力は、OSC 99(kittyのデスクトップ通知用エスケープシーケンス)3本だけでした。
ESC ] 99 ; i=3766:d=0:p=title ; Claude Code
ESC ] 99 ; i=3766:p=body ; Claude is waiting for your input
ESC ] 99 ; i=3766:d=1:a=focus ;アプリケーション名を表す f= も、アイコン名を表す n= も、アイコン画像を送る p=icon もありません。
なぜロゴになるのか
kittyの通知仕様には、次の趣旨の記述があります。
- 行儀のよいアプリは、アプリ名の
fと通知種別のtで自分を名乗る - アイコンは
nで名前を指定するのが最も簡単な方法で、名前なら端末が現在のアイコンテーマから探せる - アイコンの指定がなくても
fがあれば、端末はfの値からアイコンを推定する
Claude Codeは f も n も送らないので、kittyは解決の手がかりをすべて失い、同梱のロゴを使います。issueのDBusのキャプチャでは、通知デーモンへ渡る app_icon が /usr/lib/kitty/logo/kitty.png という絶対パスでした。名前ではなくパスなので、どこでもアイコンテーマの検索が働きません。同じ環境で名前の kitty をテーマに問い合わせるとPapirus-LightのSVGに解決するので、テーマにアイコンがないのではなく、テーマを通らない経路になっているのが要点です。
設定で直せるか
issueの報告者は、ユーザー側の設定はないと書いています。Claude Codeの通知関連の設定はpreferredNotifChannel・inputNeededNotifEnabled・agentPushNotifEnabledだけです。kitty側で用意されているのは filter_notification と notify_on_cmd_finish で、どちらもアイコンを差し替える設定ではありません。報告者が挙げた回避策は、kittyの設定ディレクトリに notifications.py というハンドラースクリプトを置く方法だけです。
Claude Codeは、Linuxで claude-code-url-handler.desktop を書き、macOSでは com.anthropic.claude-code-url-handler というバンドルIDを使っています。報告者は、この名前をOSC 99の f= に載せれば仕様どおりの経路になると提案しています。ただし、そのdesktopファイルには Icon= キーがなく、f= だけでは現状アイコンは解決しない、とも指摘しています。
なお、macOSやWindowsのKittyで同じ症状が出るかどうかは、このissueには書かれていません。
自分の環境でも確かめる
issueと同じ手順で、通知デーモンに渡る内容を見られます。
dbus-monitor --session \
"type='method_call',interface='org.freedesktop.Notifications',member='Notify'"別のウィンドウでClaude Codeの1ターンを終わらせ、「Claude is waiting for your input」の通知を出します。表示された Notify 呼び出しの app_icon が、アイコン名か絶対パスかを読みます。
OSC 99にアイコン名を載せると表示が変わるかは、仕様書の例に沿った送信で試せます。n の値はBase64で、kitty は a2l0dHk= です。
# 仕様書にある最小の例
printf '\x1b]99;;Hello world\x1b\\'
# アイコン名を n= で指定する例(値はBase64)
printf '\x1b]99;n=a2l0dHk=;Hello world\x1b\\'2本目で表示されるアイコンがテーマのkittyアイコンに変わるなら、アイコン名を送れば解決する、というissueの見立てと整合します。送る側がClaude Codeでないので、あくまで切り分けの材料です。
tmuxの中で画像が表示されない
何が起きているか
こちらはmacOSのGhosttyでの報告ですが、タイトルにあるとおりkitty graphicsの話で、Kittyでも同じ前提が当てはまります。tmuxの中でClaude Codeを動かすと、allow-passthrough on にしていても、Image 要素の画像が出ません。プラグインのmod(Claude Codeのインターフェースを拡張する仕組み。作り方はmod入門にまとめています)が描く画像は、代替テキストに置き換わります。
issueは、判定が失敗する理由を2つ挙げています。
- 画像対応の問い合わせ(APCシーケンス)をラップせずに送っていて、tmuxは外側の端末に渡さず、ペインのタイトルとして扱ってしまう
- 端末名の問い合わせ(
XTVERSION)にtmux自身がtmux 3.7cと答えるため、kittyとGhosttyだけを許可する名前の判定を通らない
環境変数を立てても出ない
端末の詳細な判定を飛ばすための環境変数として、CLAUDE_CODE_FORCE_TERMINAL_IMAGES=1 があります。ドキュメントでは、Unicodeプレースホルダー方式のkitty graphicsを描ける端末が自動検出されないときの設定、と説明されています。
tmuxやscreenの中では、これを立てても効かないと明記されています。代替テキストは消えるものの、画像の送信自体がtmux向けのパススルー包みなしで書かれるからです。issueのコメントでも、環境変数で判定を通した状態で、画像本体の転送(a=T,U=1,…)と削除(a=d)のシーケンスが包まれていないことが確認されています。裸のAPCは allow-passthrough がoffでもonでも外側に届かず、ESC P tmux; … で包んで内側のESCを二重にすると届く、という検証です。
issueの要望は3つです。
$TMUXがありallow-passthroughがonなら、画像のシーケンスをすべて包んで送る- 端末名ではなく、問い合わせへの肯定的な応答を信じる
- プローブが読めない環境向けに、明示的な上書き用の環境変数を用意する
Claude Codeは画像をUnicodeプレースホルダーで描くため、プレースホルダーのセルは普通の文字としてtmuxを通ります。パススルーが要るのは転送のAPCだけです。
いまの回避策
issueの時点で、tmuxの中で画像を出す手段は報告されていません。選べるのは次のどちらかです。
- 画像を見たいセッションはtmuxの外、Kitty本体のウィンドウやタブで動かす
- tmuxの中では代替テキストを頼りに使う(modを書く側は、画像を見られなくても意味が通る
altを書く)
フルスクリーン表示のtmux側の注意点はClaude Code tmux設定とTUI(フルスクリーン)の解説にあります。
アイコンを自分で決めたいときの代替策
Claude Code側が n= を送るようになるまで、Linuxでアイコンを自分で決めたい場合は、Notification hookで通知を出す方法があります。フックは組み込みの通知と並んで動くので、重複を避けるなら組み込み側を止めます。
{
"preferredNotifChannel": "notifications_disabled",
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "notify-send -i kitty 'Claude Code' 'Claude Code needs your attention'"
}
]
}
]
}
}notify-send は端末ではなく通知デーモンへ直接送る仕組みです。-i はアイコン名を渡すnotify-sendのオプションで、kitty の部分は手元のテーマにある名前に置き換えます。Claude Codeのガイドに載っている例は、アイコンなしの notify-send 'Claude Code' '…' です。通知デーモンのないSSH先やコンテナでは動かないので、リモートで使うならOSC 99経由の組み込み通知のままにします。
組み込みの通知を止めると、その分の通知はフックだけが頼りになります。フックの書き方はClaude Code通知の設定も参考になります。
tmuxの設定はどこまでが必要か
通知については、tmuxの中でもパススルーを有効にすれば外側の端末に届きます。
# ~/.tmux.conf
set -g allow-passthrough on
set -s extended-keys on
set -as terminal-features 'xterm*:extkeys'1行目が通知とプログレスバーを外側の端末に通す設定です。2、3行目がShift+Enterを区別するための設定です。反映は tmux source-file ~/.tmux.conf で行います。
画像に関しては、この設定を入れても上の症状は変わりません。通知が届くことと、画像が届くことは別の経路だからです。
どの症状かを見分ける早見表
| 症状 | 原因の層 | まず試すこと |
|---|---|---|
| 通知が出ない | 原因の層通知の権限・tmuxのパススルー | まず試すことOS側の権限、allow-passthrough on |
| 通知は出るがロゴがkitty | 原因の層OSC 99に f=/n= がない | まず試すことdbus-monitor で app_icon を見る |
| tmuxで画像が代替テキストのまま | 原因の層画像の判定と転送がパススルーされない | まず試すことtmuxの外で動かす |
| 画像がtmuxの外でも出ない | 原因の層端末の対応外・バックグラウンドセッション | まず試すことCLAUDE_CODE_FORCE_TERMINAL_IMAGES=1 |
バックグラウンドセッションは、どの端末から接続しても画像の判定が失敗する扱いです。
他のターミナルとの違い
通知の扱いは端末ごとに変わります。ベルで気づく設定はClaude Code通知の設定、Ghosttyで使う場合はGhosttyでのClaude Codeの設定と既知の症状、通知の対応リストに入っていないWezTermはWezTermの通知設定が詳しいです。
まとめ
Kittyでは、通知は動くのにアイコンが固定される症状と、tmuxの中で画像が出ない症状の2つが未解決です。前者は表示の問題にとどまり、通知の中身は届きます。後者はtmuxの外に出れば避けられます。どちらも、報告されているissueが閉じるのを待つか、各自の環境での切り分けに止まります。Kittyの通知設定で困っているなら、まず preferredNotifChannel と dbus-monitor の出力を見るのが近道です。