Skip to content

moonexpr/dispatch

Repository files navigation

dispatch

dispatch logo — a control tower broadcasting signal

dispatch is your engineering control tower. It watches a GitHub Issues queue, picks up one ready job at a time, runs it through a workflow engine across a spec → work → build cycle, opens a pull request, and either arms it for merge or escalates back to you — all unattended, a few times a day. You write the issues and approve the results; dispatch coordinates the work in between.

It does three things and nothing more:

  1. Intake — fetch and classify queued issues, claim one.
  2. Issue the job — the Architect phase composes a structured work order; the work phase implements it in an isolated worktree.
  3. Approve or escalate — on success, arm auto-merge (awaiting your approval); on failure, advance the fix ladder; on ambiguity, comment and escalate.

📖 Full guide: the dispatch wiki. Start with Getting started and Strengths and limitations.

What dispatch is

Underneath the GitHub control tower, dispatch is a small, focused orchestration tool over a workflow engine. It gives you a declarative, programmable surface for the hard parts of putting LLM agents to work on real engineering: organizing user requests, marshalling resources, coordinating agents, handling communication, and recovering from failure. It sits one abstraction level above raw model/agent libraries (Transformers, OpenRouter): you express what the workflow is, and the engine runs it — deterministically validated, observable, and recoverable.

Its competencies are deliberately narrow:

  • Task decomposition — break a request into independently shippable units.
  • Slice-based work processing — fan work out across per-unit slices.
  • Admin validation — verify process and outcome (CI, review, acceptance).
  • Arbitrary inputs and outputs — GitHub issues are one input adapter, not the core. The engine consumes generic work items and emits generic deliverables; the GitHub queue above is the first such adapter.

The aim is to let everyday consumer programs benefit from AI through both classical and AI-engineering principles — engineering loops, process verification, agent communication, lifecycle management — so a complicated request can be solved by a swarm of small agents working in parallel without the end user ever needing to know they ran.

The three layers

dispatch keeps a clear boundary between three layers; consumer code never reaches past its own:

  1. Foundation tooling (foundation/) — primitives: agents, backends, models, shelves, process/filesystem facades. The vocabulary.
  2. Workflow-engine subsystems (foundation/workflow/, baseworkflow/ subsystems) — the HFSM/statechart engine: controllers, actions, manifests, validation, the declarative composition surface. The grammar.
  3. Consumer app code (app/) — concrete workflows (app/workflows/*.yml), config, the ./dispatch entry point, and the /dispatch skills. The programs.

For now, YAML + Python is expressive enough to convey function composition and implementation complexity; the abstraction boundary is what keeps the engine flexible enough to take on new workflow problems.

Watch it run — the debug viewer

./debug-viewer draws every workflow as a live statechart and lights up each state as a tick executes it (mock engine, no network). It makes the three-layer model — and superseedable states — concrete.

The dispatch debug viewer: the seed phase, where the seed controller supersedes its own processing with a variation of itself

Above is the shared seed phase (shown on websitewf, which inherits it from baseworkflow). The workflow references the seed.intake controller (cyan); the three dashed supersede targetsseed.handle.github / .interactive / .job — are variations of the seed controller entered dynamically. On a run, seed:route classifies the request and supersedes its own processing with the matching variant. The live-session log captures the preemption as it happens:

0.61s → 2.seed:route
0.91s · supersede.accepted
0.91s → 4.seed.handle.job
1.22s → 0.seed:accept_job
1.52s → 1.seed:emit_work_item
1.82s · supersede.completed

The variant takes over (policy abandon), the generic seed:fallback is skipped, and every intake source converges on one source-agnostic work_item before the lifecycle continues into spec → work → build. Because a supersede target's states carry the same ids the engine mints at run time, the dashed subgraph highlights live the moment a run routes into it — no special-casing. See docs/adr/003-controller-needs-supersede.md.

Roadmap

The guiding principle: 1.x is refinement and discipline; 2.0 is expansion. 1.x hardens the existing single-host pipeline — clean layering, decoupling, and serialization/tool/shelf hygiene — before 2.0 builds outward with new backends, multi-host scaling, and new surfaces.

  • 1.x — refinement & discipline. Superseedable HFSM states (a more pressing state can preempt the active one) and per-workflow event responders (handlers for unexpected lifecycle conditions — e.g. no ready issues → exit; missing information → open a clarifying ticket), so dispatch behaves less like a straight-line program and more like an agent with reflexes. Plus the discipline work that keeps the layers clean: decoupling GitHub-issue intake from core, agent-runtime / tool-layer hardening, shelf observability and typing, a typed wire contract, TOON serialization for agent-bound data, proxy tools for context management, the live-parallelism fix, and containerized worker isolation on a single host.
  • 2.0 — expansion. OpenRouter (tool-using) backends, declarative backend-bound agent profiles, and a CPU-pressure-aware fleet dispatcher that scales containerized workers across multiple hosts. Built outward on the refined 1.x layers.
  • Exploratory (not committed) — a readable, debuggable scriptable workflow language expressing asynchronous communication, function composition, and parameterizable invocation. Direction, not scope.

Interact with dispatch via Claude skills (recommended)

dispatch is L3-class automation: it shines on small, clear, checkable units of work and struggles with vague or sprawling ones. The standard, encouraged way to drive it is the composable /dispatch Claude Code skill family, which interviews you (AskUserQuestion) and shapes work toward what the pipeline does well — before anything reaches the queue.

Skill What it does
/dispatch Front door: takes any high-level ask, interviews until it is specified, then routes it.
/dispatch:scope One rough idea → one well-formed issue (goal, acceptance criteria, scope, verification).
/dispatch:decompose A large ask → small, shippable leaf issues filed as a Draft epic.
/dispatch:tick Preview a tick in dry-run, then a deliberate go-live.
/dispatch:review Vet a pipeline pull request against its acceptance criteria before you approve.
/dispatch:oneshot Interview a task, then feed it straight into the engine — bypassing GitHub issue intake.

The skills ship under .claude/skills/ and work automatically when this repo is your Claude Code workspace. To use them in any project, run the cross-platform installer (Windows · macOS · Linux):

python install_claude_skills.py            # copy the skills into ~/.claude/skills/
python install_claude_skills.py --list     # preview what would be installed
python install_claude_skills.py --force     # overwrite an existing copy

Then just say what you want — "have dispatch build a Vercel landing page" — and /dispatch takes it from there. Full guide: Interacting with dispatch.

Installation

git clone git@github.com:ReclaimByDesign/dispatch.git
cd dispatch

# 1. Secrets and config (gitignored). Set CLAUDE_CODE_OAUTH_TOKEN, PIPELINE_REPO, tokens.
cp .env.example .env

# 2. Verify the workflow engine.
python3 app/scripts/smoke.py

# 3. Dry-run a tick — prints what it would do, mutates nothing.
./dispatch -r owner/repo

# 4. When ready, provision labels and go live.
bash scripts/bootstrap-labels.sh        # requires gh authed + a live run
./dispatch -r owner/repo --live

Dry-run is the default; --live is the only switch that lets dispatch mutate GitHub. Configure branch protection on main (CI + one human review) before going live — auto-merge waits on it, and no token may merge directly. See Configuration and Unattended Linux server installation (systemd) for the full setup.

Use cases

dispatch earns its keep on work that is bounded and checkable:

  • Backlog burndown — a queue of small, well-specified bugs and features, worked a few at a time on a schedule.
  • Repetitive, well-patterned changes — a new route, a config key, a localized fix, scaffolding that resembles many prior examples.
  • Decomposed projects — a larger build (a website, a service) broken via /dispatch:decompose into leaf issues the pipeline takes one at a time.
  • Test-backed work — anything whose success a test or command can confirm, so mistakes are caught before they reach you.

Guidelines

dispatch is a capable but fallible L3 collaborator — treat it like one:

  • Write small, clear, verifiable issues. Use the issue templates (or /dispatch:scope); every task needs a goal, acceptance criteria, scope, and a way to verify "done".
  • Decompose big asks. Hand the pipeline leaves, not epics — do the sprawling or novel thinking interactively with Claude first.
  • Stay in the loop. Escalations arrive as GitHub comments and merges wait on your approval. It is scheduled, not fire-and-forget.
  • Review before you merge. Every pull request is a draft to read — use /dispatch:review. Merging is never delegated.
  • Label by priority. Carry one status rung — UnscheduledDraftCandidateRelease — plus the Blocker overlay to jump the queue; dispatch works the highest-priority ready issue first.

Learn more

The wiki is the complete reference:

In-repo references: CLAUDE.md (worker contract) · docs/adr/ (architecture decisions) · schemas/ (Job Request / Invoice).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors