0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude codeが暇になってたら通知してくれたら便利じゃyね!?天才すぎる!!

とおもってつくってたんだけど、Hookができて投げ捨てたやつ。

供養カレンダー

> このプロジェクトが使っているClaudeCodeの暇状態を検出する方法は?色々あると思うので全部洗い出して。

Claude Code暇状態検出方法の全リスト

  1. 通常の入力プロンプト検出 (claude_monitor.py:119, claude_monitor_multi.py:186)

tmux出力から以下のパターンを検索:

  • │ > - 通常のスペースでの組み合わせ
  • │\xa0> - ノンブレーキングスペース(\xa0)での組み合わせ
  • \xa0 - プロンプトとノンブレーキングスペースの組み合わせ

  1. UI フレーム検出 (claude_monitor.py:121-122, claude_monitor_multi.py:188-189)

Claude CodeのTUIフレームを検出:

  • ╰─ - 下部フレーム
  • ╭─ - 上部フレーム
  1. Yes/No 確認プロンプト検出 (claude_monitor.py:126-139, claude_monitor_multi.py:193-206)

12種類のパターンで確認ダイアログを検出(大文字小文字区別なし):

  1. (y/n) - 汎用yes/noプロンプト
  2. [Y/n] - デフォルトYes
  3. [y/N] - デフォルトNo
  4. (yes/no) - 汎用yes/noプロンプト
  5. Continue? - 継続確認
  6. Proceed? - 実行確認
  7. confirm - 確認キーワード
  8. Are you sure - 確認フレーズ
  9. Do you want to - 意思確認フレーズ
  10. ❯ 1. Yes - Claude Code固有の選択肢UI
    1. Yes, and don't ask again - Claude Code固有の選択肢
    1. No, and tell Claude - Claude Code固有の選択肢

判定ロジック (claude_monitor.py:148, claude_monitor_multi.py:214)

return (has_prompt and has_frame) or has_yesno

待機状態と判定される条件:

  • (方法A) プロンプト検出 AND フレーム検出
  • (方法B) Yes/Noパターンのいずれかを検出

どちらか一方でも満たせば「暇状態」として通知が送られます。

> 画面の表示をテキストでとる方法は?

⏺ このプロジェクトでは tmux capture-pane コマンド を使って画面の表示をテキストで取得しています。

取得方法

  1. 基本コマンド (test_local.py:22)

tmux capture-pane -t : -p

  • -t : ターゲット(セッション:ウィンドウ番号)
  • -p : 標準出力に出力(print to stdout)
  1. SSH経由での取得 (claude_monitor.py:67-72)

ssh -p user@host "tmux capture-pane -t : -p | tail -10"

リモートサーバー上のtmuxセッションから取得する場合の方法です。

  1. 実装での具体例

単一サーバー版 (claude_monitor.py:67-72)

cmd = [
"ssh",
f"-p{self.config['ssh_port']}",
f"{self.config['ssh_user']}@{self.config['ssh_host']}",
f"tmux capture-pane -t {self.config['tmux_session']}:{self.config['tmux_window']} -p | tail -10"
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
output = result.stdout # ここにテキストが入る

複数サーバー版 (claude_monitor_multi.py:120-127)

cmd = [
"ssh",
f"-p{config['ssh_port']}",
f"{config['ssh_user']}@{config['ssh_host']}",
f"tmux capture-pane -t {config['tmux_session']}:{config['tmux_window']} -p | tail -20"
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
output = result.stdout # 最後の20行のテキスト

ポイント

  1. 取得範囲: tail -10 や tail -20 で最後のN行だけを取得(効率化)
  2. エンコーディング: text=True でUTF-8テキストとして取得
  3. タイムアウト: timeout=10 で10秒でタイムアウト
  4. 出力形式: tmuxのpane内容がそのままテキストとして返される(Box Drawing文字や絵文字も含む)

この方法で、Claude CodeのTUI(Terminal User Interface)の表示内容を文字列として取得し、パターンマッチングで待機状態を検出しています。

tmuxでClaudeCodeをたくさん動かすのが流行っていたときだ!

> なんか、pythonのライブラリでwrapする方法もためしてたような?

⏺ はい!pyteというPythonライブラリを使った方法も試していますね。

Pythonライブラリで画面表示をテキストで取る方法

pyte (Pure Python Terminal Emulator) を使った実装

  1. 基本的な仕組み (claude-wrapper-pyte.py:36-39)

import pyte

仮想ターミナル画面を作成

self.screen = pyte.Screen(80, 24) # 80列 x 24行
self.stream = pyte.Stream(self.screen)

  1. ターミナル出力を処理 (claude-wrapper-pyte.py:168-171)

Claude Codeの出力を受け取る

data = os.read(master_fd, 4096)

pyteで解析(エスケープシーケンスを解釈)

decoded = data.decode('utf-8', errors='replace')
self.stream.feed(decoded)

  1. 画面内容を取得 (claude-wrapper-pyte.py:78-87)

def get_screen_content(self, lines=None):
"""tmux capture-paneの代替"""
if lines is None:
# 全画面
return '\n'.join(self.screen.display)
else:
# 最後のN行
display = self.screen.display
return '\n'.join(display[-lines:])

  1. カーソル位置も取得可能 (claude-wrapper-pyte.py:89-100)

def get_visible_content_with_cursor(self):
"""カーソル位置も含めた画面情報"""
cursor_y, cursor_x = self.screen.cursor.y, self.screen.cursor.x
# カーソル位置をマーク
# ...

2つの方法の比較

方法 tmux capture-pane pyte ライブラリ
対象 既存のtmuxセッション Claude Codeをラップ
セットアップ tmux必須、SSH可 ラッパー経由で起動
精度 tmuxの表示そのまま エスケープシーケンスを完全解析
カーソル位置 ❌ 取得不可 ✅ 取得可能
画面サイズ変更 tmuxが処理 ✅ pyteが処理 (claude-wrapper-pyte.py:60-76)
オーバーヘッド 低い やや高い(2-10倍)
独立性 別プロセスから監視 同一プロセス内

パフォーマンス (benchmark_pyte.py より)

実使用では、pyteは1秒あたり1-5ms程度のオーバーヘッド。リアルタイム処理には十分高速です (benchmark_pyte.py:203-207)。

どちらを使うべきか?

  • 既存のtmuxセッションを監視: tmux capture-pane (現在のメイン実装)
  • tmuxなしで直接監視: pyte ラッパー (claude-wrapper-pyte.py)

pyteの利点は、tmux不要で、カーソル位置や正確な画面状態が取得できる点ですね。

> ほかにも面白いライブラリ使ってたり、面白いポイントがないか徹底的に探して

⏺ わお!すごい探索結果になりました!まとめます!


🎯 Claude Code暇状態検出プロジェクトの全貌

📚 使用ライブラリ一覧

  1. pyte - Pure Python Terminal Emulator ⭐
  • VT102互換のターミナルエミュレータ
  • エスケープシーケンスを完全に解析
  • 画面バッファ、カーソル位置を追跡
  • claude-wrapper-pyte.py, benchmark_pyte.py で使用
  1. rumps - macOSメニューバーアプリ 🍎
  • macOSのメニューバーアプリを簡単に作成
  • 通知センター連携
  • 全バージョンで使用(claude_monitor*.py)
  1. asciinema形式 - ターミナル録画 📹
  • JSONベースの軽量録画形式
  • analyze_asciinema_approach.py, terminal_recording_tools.py で分析
  • ハイブリッド版で録画機能として実装可能
  1. AppleScript / Accessibility API 🖥️
  • test_accessibility.py で実験
  • ウィンドウタイトル、UI要素の取得
  • 権限が必要で実用性は限定的
  1. PTY (Pseudo-Terminal) 🔌
  • explain_tty_pty.py で詳細解説
  • 全ラッパー実装の基盤技術
  • マスター/スレーブ構造で透過的な仲介

🔍 暇状態検出方法の全パターン

方法1: tmux capture-pane (メイン実装)

  • ファイル: claude_monitor.py, claude_monitor_multi.py
  • 仕組み: SSH経由でtmuxから画面をテキスト取得
  • 検出パターン:
    • │ > (プロンプト) + ╰─ (フレーム)
    • │\xa0> (ノンブレーキングスペース対応!)
    • yes/no: Do you want to, ❯ 1. Yes など12種類

方法2: pyteエミュレーション (ラッパー方式)

  • ファイル: claude-wrapper-pyte.py
  • 仕組み: Claude Codeをラップし、出力をpyteで解析
  • 利点:
    • カーソル位置取得可能 (claude-wrapper-pyte.py:89-100)
    • 画面サイズ変更対応 (SIGWINCH)
    • tmux不要

方法3: スクロールバック管理 (履歴ベース)

  • ファイル: claude-wrapper-scrollback.py
  • 仕組み: 最後10,000行をdequeで保持
  • 特徴:
    • tmux capture-paneの代替 (scrollback.py:78-81)
    • エスケープシーケンス除去版と生データの両方保存

方法4: CPU使用率推測 (補助的)

  • ファイル: test_cpu_monitor.py
  • 仕組み: プロセスのCPU使用率を監視
  • 判定: CPU < 5%で安定 → 待機中の可能性
  • 精度: 限定的(test_cpu_monitor.py:195-199)

方法5: 画面ハッシュ変更検出 ⚡

  • ファイル: screen_idle_monitor.py
  • 仕組み: MD5ハッシュで画面変更を検出
  • 特徴:
    • 段階的トリガー: "30,60,60" → 30秒後、90秒後、150秒後...
    • 無限繰り返し: "60,300*∞" (screen_idle_monitor.py:32-112)
    • アクション実行: 変数展開で通知コマンド

方法6: 定期画面キャプチャ 📸

  • ファイル: periodically_pyte_capture_demo.py
  • 仕組み: N秒ごとに画面をファイル保存(変更時のみ)
  • 用途: デバッグ、履歴記録
  • 実例: test_captures/ に100個以上のキャプチャ保存済み!

方法7: 統合監視 🎛️

  • ファイル: claude_monitor_unified.py
  • 仕組み: tmux + wrapper + プロセスを同時監視
  • 機能:
    • 3ソース並行監視 (unified.py:56-64)
    • リマインダー: 2分、5分、10分、15分、30分 (unified.py:27)
    • 自動クリーンアップ

🎨 実装バリエーション

A. ハイブリッド版 ⚡💾

ファイル: claude-wrapper-hybrid.py

  • リアルタイム監視(pyte)+ オプション録画(asciinema)
  • メモリ内イベントバッファ(1000件)
  • 非ブロッキング録画(hybrid.py:213-217)

B. アイドル監視版 ⏱️

ファイル: screen_idle_monitor.py

  • 画面変化がN秒ないときアクション実行
  • スケジュール機能が超高機能!
  • コマンド変数: {idle_time}, {screen_content}, {trigger_count}

C. 複数サーバー版 🌐

ファイル: claude_monitor_multi.py

  • 複数サーバーの同時監視
  • サーバーごとの有効/無効切り替え
  • 通知履歴記録(~/.claude_monitor_history.txt)

🧪 テスト・デモファイルの宝庫

  1. test_local.py - ローカルtmux検出テスト
  2. test_yesno.py - yes/no待ち検出テスト
  3. test_cpu_monitor.py - CPU使用率監視テスト
  4. test_accessibility.py - macOS Accessibility API実験
  5. test_non_tmux.py - tmux外での検出実験
  6. benchmark_pyte.py - pyteのパフォーマンス計測
  7. demo_tui_resize.py - TUIリサイズ動作デモ
  8. demo_safe_redraw.py - 安全な再描画デモ
  9. demo_resize_detection.py - リサイズ検出デモ
  10. explain_tty_pty.py - TTY/PTYの詳細解説

💎 超面白い技術ポイント

  1. ノンブレーキングスペース対応 🎯

Claude Codeは通常のスペースではなく \xa0 を使用!
if "│ >" in line or "│\xa0>" in line or ">\xa0" in line: # 3パターン対応

  1. SIGWINCH処理 📐

ウィンドウサイズ変更をリアルタイムで追跡:

  • ターミナルサイズ取得
  • pyteスクリーンをリサイズ
  • PTYに新サイズを伝達
    (claude-wrapper-pyte.py:60-76)
  1. dequeによる効率的スクロールバック 🔄

self.event_buffer = deque(maxlen=1000) # 自動で古いデータを削除

  1. 段階的リマインダー ⏰

self.reminder_intervals = [2, 5, 10, 15, 30] # 分

2分後、5分後、10分後...と段階的に通知

  1. PTYの透過性 🪟

1. 即座に転送(最優先)

sys.stdout.buffer.write(data)
sys.stdout.flush()

2. 同時に解析

self.stream.feed(decoded)

  1. 画面状態のJSONエクスポート 📤

{
"state": "waiting",
"screen_content": "最後の20行",
"cursor_position": {"y": 10, "x": 5},
"event_count": 523
}

  1. asciinema形式の再利用 🎬

[elapsed_time, "o", data] # タイムスタンプ + 出力データ

  1. 実際のキャプチャデータ保存 📂

test_captures/aaa/ に実際のClaude Code画面が100個以上保存されている!

  • 176x55の画面サイズ
  • プロンプト、ウェルカムメッセージ含む
  • タイムスタンプ付き(20250717_111619.txt など)

📖 ドキュメント構造

  • investigation.md - 技術調査結果(待機パターン分析)
  • REQ.md - 要件定義
  • todos.md - タスク管理(ほぼ完了!)
  • README.md - 使用方法
  • CLAUDE.md - プロジェクトガイド
  • simulate_yesno.md - yes/no待ちシミュレーション

🏗️ アーキテクチャの進化

基本版 (tmux)

複数サーバー版

ラッパー版 (pyte)

スクロールバック版

ハイブリッド版 (監視+録画)

統合版 (全ソース統合)


🎪 最も面白い発見

  1. 段階的アイドル検出 - screen_idle_monitor.py のスケジュール機能が異常に柔軟!

30秒後、その後300秒ごとに10回通知

--idle "30,300*10"
2. 3ソース統合監視 - tmux、wrapper、生プロセスを同時監視
3. 100個以上の実キャプチャ - test_captures/ ディレクトリに実データ
4. パフォーマンス検証済み - pyteは2-10倍遅いが、実用上は1-5ms/秒で問題なし
5. 完全な録画機能 - asciinema形式で入出力を完全記録可能
6. TTY/PTYの詳細解説 - explain_tty_pty.py が教科書レベル


すごいプロジェクトです!多様なアプローチを試行錯誤し、それぞれの長所短所を検証した痕跡が見られます。特に「段階的リマインダー」「統合監視」「ハイブリッド実装」
のアイデアが秀逸ですね!

供養...

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?