Skip to content

CTlanston/claude-dispatch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Claude Dispatch

A local multi-agent dispatcher wrapping Claude Code: Orchestrator → Workers → Heterologous Validator. Push notifications, behavioral contracts, a WebUI, and a stuck-session watchdog.

What it is

  • Orchestrator (CC Opus) plans a task, writes a behavioral contract.md, and dispatches Workers.
  • Code Workers (CC Opus) and RW Workers (CC Sonnet) produce artifacts in workspace/<sid>/outputs/. Code workers serialize via a write lock; RW workers can parallelize.
  • Validator (Gemini 2.5 Pro, via google-genai SDK) sees ONLY the contract + worker self-reports + outputs file listing + test result files. It never sees source code. Writes verdict.md (PASS or FAIL).
  • WebUI (FastAPI + HTMX) on http://127.0.0.1:7777 shows live status, events, and artifacts.
  • Notify hooks push to Mac (terminal-notifier) and phone (ntfy.sh) on Stop, Notification, SubagentStop, watchdog stuck, and dispatch-start.
  • Watchdog flags any session whose workspace has been idle longer than WATCHDOG_TIMEOUT_SEC.

Install

Dependencies (one-time):

brew install terminal-notifier tmux jq python@3.13
~/.claude-dispatch/.venv/bin/pip install fastapi uvicorn jinja2 \
                                          google-genai python-dotenv

claude CLI must already be installed and authenticated.

Configure

Copy and edit .env:

cp ~/.claude-dispatch/.env.example ~/.claude-dispatch/.env
$EDITOR ~/.claude-dispatch/.env

Fill in:

  • GEMINI_API_KEY — get one at https://aistudio.google.com/apikey (starts with AIza...)
  • NTFY_TOPIC — a long random string (e.g. openssl rand -hex 16); subscribe to it in the ntfy mobile app

DISPATCH_HOME, WEBUI_PORT, WATCHDOG_TIMEOUT_SEC, and NTFY_SERVER come with sane defaults.

Wire hooks into Claude Code's user settings (idempotent):

jq -s '.[0] * .[1]' ~/.claude/settings.json ~/.claude-dispatch/settings.json \
  > /tmp/merged.json && mv /tmp/merged.json ~/.claude/settings.json

Wire the global behavioral contract:

ln -s ~/.claude-dispatch/CLAUDE.md ~/.claude/CLAUDE.md

First run

~/.claude-dispatch/bin/dispatch "create a python script that prints fibonacci, plus a README"

You'll get a "🚀 Dispatch started" push. The Orchestrator session lives in a tmux session named dispatch-<sid>.

Observe

  • WebUI: http://127.0.0.1:7777 — sessions list and per-session detail (2s HTMX polling). Auto-starts on first dispatch call.
  • Attach to a session: tmux attach -t dispatch-<sid> — see the Orchestrator's chat thread live.
  • Files: ~/.claude-dispatch/workspace/<sid>/ contains task.md, plan.md, contract.md, verdict.md, events.jsonl, and the outputs/ deliverables.

Stop a session

~/.claude-dispatch/bin/dispatch-stop <sid>

Writes a session_end event and kills the tmux session.

Watchdog

Optional background daemon — alerts when a session's workspace has been idle longer than WATCHDOG_TIMEOUT_SEC:

nohup ~/.claude-dispatch/.venv/bin/python3 \
      ~/.claude-dispatch/watchdog/watchdog.py \
      > /tmp/dispatch-watchdog.log 2>&1 &

Logs to /tmp/dispatch-watchdog.log.

Smoke test

End-to-end check (runs ~5–10 min, costs ~$0.50 in API tokens):

bash ~/.claude-dispatch/bin/smoke-test.sh

Dispatches a mathx + pytest task, polls for verdict.md, asserts PASS, sends a "🎉 Smoke test passed" notification.

Troubleshooting

No Mac banner notifications. macOS notification permission is required: open System Settings → Notifications → terminal-notifier, enable "Allow Notifications", set style to Banners or Alerts.

No phone push. Make sure you've installed the ntfy app (iOS / Android / F-Droid), added a subscription, and used the exact NTFY_TOPIC from .env. Anyone with this topic can read your notifications, so keep it long and random.

Sessions never finish (sit at "running" forever). Attach with tmux attach -t dispatch-<sid> and look at the Orchestrator's last message. If the watchdog is running you'll get a 🔴 Stuck push after WATCHDOG_TIMEOUT_SEC. Kill with dispatch-stop <sid>.

Write-lock seems stuck. Code workers serialize via a directory lock at workspace/<sid>/.write-lock/. If a code worker is killed mid-run the lock dir may persist:

rmdir ~/.claude-dispatch/workspace/<sid>/.write-lock

WebUI won't start. Check the log: tail /tmp/dispatch-webui.log. Common cause: port 7777 already in use by another process (lsof -i :7777). Set a different WEBUI_PORT in .env.

Orchestrator stalls on a "trust this folder?" dialog. bin/dispatch pre-registers each workspace in ~/.claude.json. If you see this prompt it means jq failed during launch — check that jq is installed.

Files

~/.claude-dispatch/
├── BUILD_SPEC.md           — the build specification (for reference)
├── CLAUDE.md               — Karpathy 4 behavioral rules (symlinked to ~/.claude/)
├── settings.json           — hooks template (merged into ~/.claude/settings.json)
├── .env                    — your secrets (gitignored)
├── agents/
│   ├── orchestrator.md     — Orchestrator system prompt
│   ├── worker-code.md      — Code Worker system prompt
│   └── worker-rw.md        — RW Worker system prompt
├── bin/
│   ├── dispatch            — launch an Orchestrator
│   ├── dispatch-stop       — kill a session
│   ├── spawn-worker.sh     — called by Orchestrator
│   └── smoke-test.sh       — end-to-end test
├── hooks/                  — notify.sh + on-stop/on-notification/on-subagent-stop
├── validator/              — validate.py + prompt.md (Gemini, heterologous)
├── watchdog/               — watchdog.py
├── webui/                  — FastAPI + HTMX observatory
├── .venv/                  — Python 3.13 venv (gitignored)
└── workspace/<sid>/        — per-dispatch state (gitignored)

About

Multi-agent dispatcher for Claude Code: Orchestrator → Workers → Heterologous (Gemini) Validator. Push notifications, behavioral contracts, watchdog, FastAPI WebUI.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors