はじめに
Gemini CLI、便利に使っていますか?
コーディングをガッツリ任せられるので最高なのですが、処理が長いときに別のtmuxウィンドウで作業していると、「ツールの実行許可待ち(y/n)」で止まっているのに気づかず放置し、Geminiをフルに活かせないことがあります。
2026/1/28にGemini CLIもhooksがリリースされていたので、これを使ってtmuxのウィンドウ名にGeminiの状態を表示するようにGemini CLIで実装をし、動作確認をしました。
Tailor Gemini CLI to your workflow with hooks - Google Developers Blog
Gemini CLI hooks | Gemini CLI
Claude Codeで同じことをしている方がおり、pythonスクリプトはそちらのコードを大部分参考にさせていただきましたm(_ _)m
Claude Code Hooksでtmuxのウィンドウ名を変更して通知の代わりにする #ClaudeCode - Qiita
何ができるの?
Gemini CLIのHooks機能を利用して、イベント発生時にtmuxのウィンドウ名の先頭にアイコンを付与・更新します。

上記の図のように、Geminiの状態が表示されるようになります。
-
処理中:
💎🤖 window_name -
確認待ち:
💎✋ window_name(←これ重要!) -
完了:
💎✅ window_name -
セッション終了:
window_name(アイコンを削除)
これで、ステータスラインを見るだけで「お、呼ばれてるな」と気づけるようになります。
ダイヤアイコンなのは、GeminiのGem機能からイメージ合っているなと思いました。
実行環境
| 項目 | バージョン | 備考 |
|---|---|---|
| macOS | 26.2 | Build 25C56 |
| zsh | 5.9 | arm-apple-darwin24.2.0 |
| tmux | 3.6a | |
| gemini-cli | 0.27.4 | |
| Python | 3.14.3 |
設定手順
1. スクリプトの準備
まずは、tmuxを操作するためのPythonスクリプトを作成します。
まずディレクトリを作成します。
mkdir -p ~/.gemini/hooks
以下のpythonスクリプトを ~/.gemini/hooks/gemini-hook.py として保存します。
#!/usr/bin/env python3
import json
import os
import re
import subprocess
import sys
from enum import Enum
class HookStatus(Enum):
COMPLETED = "✅"
NOTIFICATION = "✋"
ONGOING = "🤖"
@classmethod
def get_emoji_pattern(cls) -> str:
# 置換用に絵文字のパターンを生成
return "".join(status.value for status in cls) + "💎"
IDENTIFIER = "💎"
def main():
# 引数からイベント名を取得
if len(sys.argv) < 2:
return
event_name = sys.argv[1]
# 標準入力からJSON(通知内容など)を読み込む
data = {}
try:
if not sys.stdin.isatty():
data = json.load(sys.stdin)
except Exception:
pass
# イベントに応じてステータスを変更
if event_name == "notification":
if data.get("notification_type") == "ToolPermission":
update_tmux_window_name(HookStatus.NOTIFICATION)
elif event_name in ["after_agent"]:
update_tmux_window_name(HookStatus.COMPLETED)
elif event_name in ["before_agent", "before_tool"]:
update_tmux_window_name(HookStatus.ONGOING)
elif event_name in ["after_tool"]:
update_tmux_window_name(HookStatus.ONGOING)
elif event_name in ["session_end"]:
remove_tmux_window_icon()
def get_current_tty() -> str:
"""現在のプロセスの制御端末(TTY)のパスを取得"""
try:
# os.ttyname(0)などは /dev/tty を返すことがあり、tmuxの #{pane_tty} (/dev/ttysXXX) と一致しないため
# psコマンドを使用して具体的なTTYデバイス名を取得する
result = subprocess.run(
["ps", "-p", str(os.getpid()), "-o", "tty="],
capture_output=True,
text=True,
check=True,
)
tty_name = result.stdout.strip()
if not tty_name or tty_name in ["?", "??"]:
return ""
if not tty_name.startswith("/"):
return f"/dev/{tty_name}"
return tty_name
except Exception:
return ""
def is_valid_tmux_context(pane_id: str) -> bool:
"""
現在のプロセスが指定されたtmuxペイン内で実行されているか確認
環境変数が継承されただけの別ターミナル(VSCode等)での誤動作を防ぐ
"""
try:
current_tty = get_current_tty()
if not current_tty:
return False
# tmuxペインのTTYを取得
result = subprocess.run(
["tmux", "display-message", "-p", "-t", pane_id, "#{pane_tty}"],
capture_output=True,
text=True,
check=True,
)
pane_tty = result.stdout.strip()
return current_tty == pane_tty
except Exception:
return False
def update_tmux_window_name(status: HookStatus):
"""指定されたステータスでtmuxウィンドウ名を更新"""
try:
# $TMUX_PANE環境変数から実行元のペインIDを取得
pane_id = os.environ.get("TMUX_PANE")
if not pane_id:
return
# 環境変数が継承されただけの別ターミナル(VSCode等)での誤動作を防ぐ
if not is_valid_tmux_context(pane_id):
return
# ペインが属するウィンドウIDを取得
result = subprocess.run(
["tmux", "display-message", "-p", "-t", pane_id, "#I"],
capture_output=True,
text=True,
check=True,
)
window_id = result.stdout.strip()
# 現在のウィンドウ名を取得
result = subprocess.run(
["tmux", "display-message", "-p", "-t", window_id, "#W"],
capture_output=True,
text=True,
check=True,
)
current_name = result.stdout.strip()
emoji = f"{IDENTIFIER}{status.value}"
# 既存の絵文字があれば置換、なければ追加
emoji_pattern = HookStatus.get_emoji_pattern()
new_name = re.sub(rf"^[{emoji_pattern}]*", f"{emoji}", current_name)
if not new_name.startswith(emoji):
new_name = f"{emoji}{current_name}"
# ウィンドウ名を更新
subprocess.run(["tmux", "rename-window", "-t", window_id, new_name], check=True)
except Exception:
pass
def remove_tmux_window_icon():
"""tmuxウィンドウ名から状態アイコンを削除"""
try:
pane_id = os.environ.get("TMUX_PANE")
if not pane_id:
return
# 環境変数が継承されただけの別ターミナル(VSCode等)での誤動作を防ぐ
if not is_valid_tmux_context(pane_id):
return
result = subprocess.run(
["tmux", "display-message", "-p", "-t", pane_id, "#I"],
capture_output=True,
text=True,
check=True,
)
window_id = result.stdout.strip()
result = subprocess.run(
["tmux", "display-message", "-p", "-t", window_id, "#W"],
capture_output=True,
text=True,
check=True,
)
current_name = result.stdout.strip()
# 先頭の絵文字パターンを削除
emoji_pattern = HookStatus.get_emoji_pattern()
new_name = re.sub(rf"^[{emoji_pattern}]+", "", current_name)
if new_name != current_name:
subprocess.run(
["tmux", "rename-window", "-t", window_id, new_name],
check=True
)
except Exception:
pass
if __name__ == "__main__":
main()
2. Gemini CLIの設定
次に~/.gemini/settings.json を開き、hooks セクションに以下の設定を追加します。
イベント発生時に上記のスクリプトを呼び出すようにします。
{
... 他の設定 ...
"hooks": {
"Notification": [
{
"matcher": ".*",
"hooks": [
{
"type": "command",
"command": "python3 ~/.gemini/hooks/gemini-hook.py notification"
}
]
}
],
"AfterAgent": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 ~/.gemini/hooks/gemini-hook.py after_agent"
}
]
}
],
"BeforeAgent": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 ~/.gemini/hooks/gemini-hook.py before_agent"
}
]
}
],
"BeforeTool": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 ~/.gemini/hooks/gemini-hook.py before_tool"
}
]
}
],
"SessionEnd": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "python3 ~/.gemini/hooks/gemini-hook.py session_end"
}
]
}
]
},
... 他の設定 ...
}
注意点
-
automatic-rename設定: tmuxの
automatic-renameがONの場合、ウィンドウ名が自動リセットされることがあります。- 必要に応じて
set-option -g automatic-rename offで無効化してください。
- 必要に応じて
-
tmux環境外での実行: スクリプト内で
TMUX_PANEの有無をチェックしているので、tmuxの外でGeminiを使ってもエラーにはなりませんが、当然ウィンドウ名は変わりません。 -
Pythonパス: 環境に合わせて
python3のパスや実行権限を調整してください。
まとめ
これで、Geminiが「ツール実行していい?」と聞いてきたときに、ウィンドウ名が 💎✋ に変わるようになりました。
チラッと見るだけで状態がわかるので、開発体験がグッと向上しました!
良きGeminiライフを!
Gemini CLIのHooksを使って通知を出してみたので、よかったらそちらもどうぞ!
Gemini CLIの承認待ちや応答完了の通知をHooksを使って実装してみた #Mac - Qiita