åŒã°ããŠããªããšãŒãžã§ã³ããçãåºã â Stop hookã§äœ¿çšçãã°ãåã£ãŠãŸã³ããåã
ã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 ãžð
çããã® â€ïž ãã·ã§ã¢ãå±ã¿ã«ãªããŸãïŒ