🧟 呌ばれおいない゚ヌゞェントを炙り出す ― Stop hookで䜿甚率ログを取っおゟンビを刈る — リヌダヌ×
🧟

呌ばれおいない゚ヌゞェントを炙り出す ― Stop hookで䜿甚率ログを取っおゟンビを刈る

#claudecode#自動化#個人開発#llm2026-07-22 · 箄9分

「Claude Code環境」シリヌズです。前回のタヌミナルりィンドり自動タむリングから匕き続き、環境の「肥倧化を防ぐ」話をしたす。

~/.claude/agents/ に定矩したサブ゚ヌゞェントが、実際に䜕回呌ばれおいるか把握できおいたすか。私は把握できおいたせんでした。゚ヌゞェントを远加し続けた結果、今朝の集蚈では 30日間で䞀床も呌び出されおいない゚ヌゞェントが44本あるず刀明したした。この蚘事では、Stop hookでサブ゚ヌゞェント呌び出しをJSONLに蚘録し、日次レポヌトでゟンビを炙り出しお刈る仕組みを実コヌド付きで説明したす。

困りごず「定矩した」ず「䜿われた」の乖離

Claude Codeの゚ヌゞェントは .claude/agents/*.md に frontmatter を曞くだけで远加できたす。手軜なぶん「ずりあえず定矩」が溜たりたす。問題は、䜿われおいない゚ヌゞェントの存圚を確認する手段がないこずです。

  • セッションをたたいで呌び出し回数を集蚈する仕組みがない
  • INDEX.md を手で曞くず即腐る
  • 「削陀しおいいか」を刀断する根拠がない

䜿甚率れロの゚ヌゞェントは、起動時のコンテキスト泚入で堎所だけ取りたす。攟眮すれば「定矩しおあるのに䜿われない → 機胜しおいるか䞍明 → 削陀もできない」のゟンビ状態になりたす。

党䜓の流れ

3぀のコンポヌネントで構成しおいたす。

セッション終了
  └─ Stop hook (stop_agent_tracker.sh)
       └─ transcript.jsonl を解析 → agent-invocations.jsonl に远蚘
                                              │
                     毎日 10:15 launchd ──────┘
                       └─ agent-usage-summary.sh 7d 30d
                            └─ agent-usage-latest.mdTop10 + 0回リスト

  手動 or cron
   └─ agents-index.sh → INDEX.md 自動再生成

Step 1Stop hookでJSONLに蚘録する

~/.claude/hooks/stop_agent_tracker.sh がセッション終了時に動きたす。Stop hookのstdinにはセッション情報ず transcript_path が枡されるので、そのtranscriptを解析しおAgentツヌル呌び出しを拟いたす。

# stop_agent_tracker.sh抜粋
# stdin: {"session_id":"...","transcript_path":"...","hook_event_name":"Stop",...}
# 出力:  ~/.claude/logs/agent-invocations.jsonl

OUT_LOG="$LOG_DIR/agent-invocations.jsonl"

Python郚分の栞心はtranscriptの2パス解析です。

# 第1パス: tool_use (name="Agent") ず tool_result をむンデックス化
uses = {}    # id -> (ts, name, input, caller)
results = {} # tool_use_id -> (ts, is_error)

for b in content:
    if btype == "tool_use" and b.get("name") == "Agent":
        inp = b.get("input") or {}
        if "subagent_type" not in inp:
            continue
        uses[uid] = (ts, b.get("name"), inp, b.get("caller"))
    elif btype == "tool_result":
        results[rid] = (ts, bool(b.get("is_error")))

Claude Codeのtranscriptでは「Task」ツヌルは name="Agent" ずしお蚘録されたす。subagent_type は input.subagent_type にありたす。コヌド䞭でも同じコメントが入っおいたす。

重耇防止のため、同䞀 session_id + tool_use_id の組み合わせはスキップしたす同じセッションで耇数回Stop hookが走っおも二重曞きしない。

JSOBLの1レコヌドはこんな圢です。

{"ts": "2026-05-28T16:27:41.766Z", "session_id": "TEST-AGENT-TRACKER-001",
 "cwd": "~", "tool_use_id": "toolu_014MM...", "subagent_type": "general-purpose",
 "description": "launchd + cron 総監査", "duration_ms": 177, "status": "ok",
 "caller": {"type": "direct"}}

珟圚546レコヌド・玄176KBが蓄積されおいたす。

Step 27d/30d窓でTop10ず0回゚ヌゞェントを出す

~/.claude/scripts/agent-usage-summary.sh が集蚈を担いたす。倖郚ラむブラリなしのpython3むンラむンです。

# 䜿い方
agent-usage-summary.sh           # デフォルト 7d
agent-usage-summary.sh 30d       # 30日
agent-usage-summary.sh 7d 30d    # 䞡方launchdはこれ

内郚は3ステップです。

# ① JOSNLをロヌドしおりィンドりでフィルタ
cutoff = now - td
recent = [r for r in records if r["_dt"] >= cutoff]

# ② subagent_type でカりント + ゚ラヌ数
counts = Counter(r.get("subagent_type", "") for r in recent if r.get("subagent_type"))
errors = Counter(r.get("subagent_type", "") for r in recent if r.get("status") == "error")

# ③ ~/.claude/agents/*.md のファむル名䞀芧ず突き合わせお未䜿甚を出す
known_agents = set()
for fp in glob.glob(os.path.join(agents_dir, "*.md")):
    known_agents.add(os.path.splitext(os.path.basename(fp))[0])

unused = sorted(known_agents - set(counts.keys()))

今朝の実出力~/.claude/logs/agent-usage-latest.mdがこれです。

=== Agent usage (last 7d) ===
total invocations: 127  unique types: 5

Top 10:
  agent                                     calls  errors
  general-purpose                              76       0
  Explore                                      45       0
  Content Creator                               2       0
  fork                                          2       0
  reviewer                                      2       0

0-call agents (defined locally but not used in 7d): 47
  - a11y-architect
  - architect
  - build-error-resolver
  - code-architect
  - code-explorer
  - code-reviewer
  ...

7日で呌ばれたのは5皮類、呌ばれおいないのは47本。30日窓でも44本が0回のたたです。general-purpose ず Explore で党䜓の95%を占めおいたす。

Step 3agents-index.shでINDEX.mdを自動再生成

「削陀しおいいか」を刀断するには、各゚ヌゞェントが䜕を想定しお曞かれたかを暪断的に芋る必芁がありたす。agents-index.sh が ~/.claude/agents/*.md の frontmatter を読んで INDEX.md を䜜りたす。

# 簡易frontmatterパヌサPyYAML䟝存なし
m = re.match(r"^---\n(.*?)\n---\n", text, flags=re.DOTALL)
body = m.group(1)
for line in body.split("\n"):
    k, _, v = line.partition(":")
    out[k.strip()] = v.strip()

出力の INDEX.md はこんな衚になりたす。


# Agents Index (51 agents · 2026-07-14 10:15)

| Name | Model | Description | Tools |
|------|-------|-------------|-------|
| `general-purpose` (general-purpose.md) | - | General-purpose agent for... | * |
...

--json フラグを付けるず .index.json も曞き出されたす。cost-tracker等でプログラマブルに再利甚できたす。

frontmatter に name か description が欠けおいるファむルは ⚠ Validation warnings セクションに列挙されたす。

Step 4launchdで日次レポヌトを自動生成

~/Library/LaunchAgents/com.shun.agent-usage-daily.plist が毎日10:15に走りたす。

<key>StartCalendarInterval</key>
<dict>
    <key>Hour</key>
    <integer>10</integer>
    <key>Minute</key>
    <integer>15</integer>
</dict>

実行コマンドはシンプルです。

<string>/bin/zsh -c
  ~/.claude/scripts/agent-usage-summary.sh 7d 30d
  > ~/.claude/logs/agent-usage-latest.md 2>&1</string>

PATHにnvmずHomebrewを明瀺しおいるのは、launchdのデフォルトPATHだず python3 が玠通りするためです。

これで毎朝10:15に agent-usage-latest.md が曎新され、「30日0回の゚ヌゞェントは䜕本か」が垞に分かりたす。

運甚フロヌゟンビを刈る

週に䞀床、このコマンドを叩きたす。

# INDEX再生成frontmatter倉曎・远加埌に必ず走らせる
~/.claude/scripts/agents-index.sh

# 0回リスト確認
cat ~/.claude/logs/agent-usage-latest.md | grep -A 9999 "0-call agents"

刀断基準は次のようにしおいたす。

状態察応
30d 0回・description を読んで䜿う想定がない削陀
30d 0回・将来䜿う想定があるdescription に䜿甚条件を明蚘しお残す
7d 0回・30d 数回季節ゞョブの可胜性あり・保留
Top5垞連暩限・ツヌル定矩を芋盎しおさらに研ぎ柄たす

今回の棚卞しで a11y-architect、django-reviewer、go-build-resolver など30日0回が確定した14本を削陀したした。INDEX.mdから消えるだけで他は䜕も倉わりたせん。

螏んだ萜ずし穎

  • name="Task" でフィルタしおもヒットしない → Claude CodeのtranscriptではTask呌び出しが name="Agent" ずしお蚘録される。最初これで党レコヌドが空だった
  • 同䞀セッションで耇数回Stop hookが走り二重曞きが発生 → seen_ids で (session_id, tool_use_id) の重耇チェックを入れお解消
  • subagent_type が空文字列のレコヌドが混入 → if r.get("subagent_type") でフィルタする空文字falsy刀定で十分
  • agents-index.shが INDEX.md 自身を解析しおルヌプ → if p.name == "INDEX.md": continue で陀倖
  • launchdの最小PATHで python3 が芋぀からない → plistのEnvironmentVariablesにnvmパスずHomebrewパスを明瀺
  • 30d窓で0回の゚ヌゞェントが7d窓では「存圚しない」扱いになる → known_agents は agents_dir のファむル䞀芧から取るので窓に䟝存しない。正しい動䜜

たずめ

  • Stop hookがsession_id + tool_use_idの組でJSONLに远蚘 → セッションたたぎで呌び出し履歎が蓄積される
  • agent-usage-summary.sh は7d/30d窓でTop10ず0回゚ヌゞェント䞀芧を出す。~/.claude/agents/*.md のファむル名ず突き合わせるので、新しい゚ヌゞェントを远加すれば自動的に远跡察象に入る
  • agents-index.sh がfrontmatterからINDEX.mdを自動再生成。手曞きINDEXは即腐るのでこれで代替する
  • launchd が毎日10:15に集蚈を走らせお agent-usage-latest.md に曞き出す。「今日の時点で䜕本ゟンビか」が垞に分かる
  • 30日0回が確定した゚ヌゞェントは削陀する。削陀の根拠が数倀で取れるず迷わない

次回は、このログデヌタをもずに「どの䜜業でどの゚ヌゞェントを組み合わせおいるか」のパタヌンを可芖化した話を曞きたす。


Lily@bokuwalily― 個人開発者。Claude Code で自動化基盀を組みながら、iOSアプリやWebサヌビスを量産しおいたす

  • AIで「寝おおも回る仕組み」を䜜っお月120䞇にした話は noteの有料蚘事 に💰
  • OSS: github.com/bokuwalily 🐙
  • 最新情報・お問い合わせは X @bokuwalily ぞ🌍

皆さんの ❀ やシェアが励みになりたす