|
#!/usr/bin/env python3 |
|
"""agent-watch-hook.py — Stop hook: spawns a background DAG updater agent every N turns. |
|
|
|
Usage: add to .claude/settings.json Stop hooks: |
|
{ "type": "command", "command": "python3 /path/to/agent-watch-hook.py" } |
|
|
|
Env: |
|
AGENT_WATCH_INTERVAL turns between updates (default: 7) |
|
""" |
|
import json |
|
import os |
|
import subprocess |
|
import sys |
|
from datetime import datetime |
|
from pathlib import Path |
|
|
|
N = int(os.environ.get("AGENT_WATCH_INTERVAL", "7")) |
|
|
|
|
|
def main(): |
|
raw = sys.stdin.read() |
|
try: |
|
payload = json.loads(raw) |
|
except json.JSONDecodeError: |
|
sys.exit(0) |
|
|
|
transcript_path = payload.get("transcript_path", "") |
|
cwd = payload.get("cwd", ".") |
|
|
|
if not transcript_path or not Path(transcript_path).exists(): |
|
sys.exit(0) |
|
|
|
session_short = Path(transcript_path).stem[:4] |
|
date_str = datetime.now().strftime("%Y-%m-%d") |
|
|
|
watch_dir = Path(cwd) / ".claude" / "agent-watch" |
|
watch_dir.mkdir(parents=True, exist_ok=True) |
|
|
|
output_file = watch_dir / f"{date_str}-{session_short}.md" |
|
counter_file = watch_dir / f".counter-{session_short}" |
|
|
|
count = int(counter_file.read_text().strip()) if counter_file.exists() else 0 |
|
count += 1 |
|
counter_file.write_text(str(count)) |
|
|
|
if count % N != 0: |
|
sys.exit(0) |
|
|
|
prompt = f"""Read the Claude Code transcript at: {transcript_path} |
|
Update the Mermaid flowchart at: {output_file} |
|
|
|
Rules: |
|
- Format: markdown file, single mermaid flowchart block |
|
- Append only NEW nodes since the last update — never rewrite existing ones |
|
- Node label: short action (Korean or English ok) |
|
- Edge labels: success / failed / retry / in-progress |
|
- Max 20 nodes total; merge similar steps into one |
|
- Status shapes: rectangle=action, diamond=decision, stadium=result |
|
- If file doesn't exist, create it: |
|
# Agent Watch — {date_str}-{session_short} |
|
(then the mermaid block) |
|
|
|
Write the file. No explanation, no commentary.""" |
|
|
|
subprocess.Popen( |
|
["claude", "-p", prompt, "--model", "claude-haiku-4-5-20251001"], |
|
cwd=cwd, |
|
stdout=subprocess.DEVNULL, |
|
stderr=subprocess.DEVNULL, |
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |