Claude Media
Claude CodeをKittyで使うと出る通知アイコンと画像表示の症状

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つ挙げています。

  1. 画像対応の問い合わせ(APCシーケンス)をラップせずに送っていて、tmuxは外側の端末に渡さず、ペインのタイトルとして扱ってしまう
  2. 端末名の問い合わせ(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 の出力を見るのが近道です。

この記事を共有:XはてブLinkedIn