Skip to content

Instantly share code, notes, and snippets.

@RanolP
Created April 23, 2026 15:25
Show Gist options
  • Select an option

  • Save RanolP/4f7fa18bc4e5625ab98846b385ece570 to your computer and use it in GitHub Desktop.

Select an option

Save RanolP/4f7fa18bc4e5625ab98846b385ece570 to your computer and use it in GitHub Desktop.
agent-watch: Claude Code stop hook → background Haiku agent → Mermaid DAG progress tracker

agent-watch

Claude Code stop hook that spawns a background Haiku agent every N turns to summarize what the agent is doing as a Mermaid DAG.

What it does

Every 7 turns (configurable), a one-shot Haiku agent reads the session transcript and appends new nodes to a Mermaid flowchart at:

.claude/agent-watch/yyyy-MM-dd-{session}.md

Open the file in any Mermaid-compatible viewer (VS Code, GitHub, Obsidian) to see a live DAG of the agent's progress — what was attempted, what succeeded, what failed.

Install

curl -sL https://gist.github.com/ranolp/GIST_ID/raw/install.sh | bash

Config

export AGENT_WATCH_INTERVAL=7  # default

Requirements

  • claude CLI in PATH
  • ANTHROPIC_API_KEY set
#!/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()
#!/usr/bin/env bash
# agent-watch installer
# Usage: curl -sL https://gist.github.com/ranolp/GIST_ID/raw/install.sh | bash
set -e
GIST_RAW="https://gist.github.com/ranolp/GIST_ID/raw"
HOOK_PATH="$HOME/.claude/agent-watch-hook.py"
SETTINGS="$(pwd)/.claude/settings.json"
echo "Installing agent-watch-hook.py → $HOOK_PATH"
curl -sL "$GIST_RAW/agent-watch-hook.py" -o "$HOOK_PATH"
chmod +x "$HOOK_PATH"
if [ ! -f "$SETTINGS" ]; then
mkdir -p "$(dirname "$SETTINGS")"
echo '{"hooks":{"Stop":[]}}' > "$SETTINGS"
fi
HOOK_CMD="python3 $HOOK_PATH"
if python3 -c "
import json, sys
s = json.load(open('$SETTINGS'))
hooks = s.setdefault('hooks', {}).setdefault('Stop', [])
cmd = '$HOOK_CMD'
for h in hooks:
for entry in h.get('hooks', []):
if entry.get('command') == cmd:
print('already registered'); sys.exit(0)
hooks.append({'matcher': '', 'hooks': [{'type': 'command', 'command': cmd}]})
json.dump(s, open('$SETTINGS', 'w'), indent=2)
print('registered')
"; then
echo "Done. Stop hook registered in $SETTINGS"
echo "Optional: set AGENT_WATCH_INTERVAL=7 to customize turn interval."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment