SkillAgentSearch skills...

Busytown

Multi-agent factories coordinated over a SQLite queue

Install / Use

/learn @gordonbrander/Busytown
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

busytown

A town full of busy little guys who do things.

busytown is a multi-agent coordination framework built around a shared SQLite event queue. Each agent is a separate Claude Code instance. Agents listen for events, react to them, and push new events, forming an asynchronous pipeline where no agent needs to know about any other agent, only about the events.

<p><img src="./busytown.png" src="A town full of busy little guys who do things" /></p>

How it works

Everything is stored in a single SQLite database (events.db). Events are simple JSON objects:

{
  "id": 1,
  "type": "plan.request",
  "timestamp": "...",
  "worker_id": "user",
  "payload": { "prd_path": "prds/my-feature.md" }
}

The agent runner polls the queue and dispatches events to matching agents. Agents run in parallel, but each agent processes events serially, one at a time, in order. The agent:

  • Listens for specific event types (exact match, prefix glob like file.*, or wildcard *)
  • Reacts by reading files, writing code, producing artifacts
  • Pushes new events to notify other agents of what it did
  • Claims events when needed, so only one agent acts on a given event

Agents can also use the filesystem as a shared workspace for saving memories, plans, WIP, etc.

Architecture

┌──────────┐    push     ┌─────────────────┐    dispatch    ┌───────────┐
│  User /  │───────────▸ │  SQLite Event   │ ─────────────▸ │  Agent    │
│  Script  │             │  Queue          │                │  (Claude) │
└──────────┘             │                 │ ◂───────────── └───────────┘
                         │  events table   │    push new
                         │  worker_cursors │    events
                         │  claims         │
                         └─────────────────┘
                               ▲     │
                               │     ▼
                         ┌───────────┐
                         │  Agent    │
                         │  (Claude) │
                         └───────────┘

Getting started

Prerequisites: Deno and Claude Code installed.

Install

# Install the `busytown` command globally
deno task install

This creates a busytown command you can run from any directory.

1. Start the agent runner

# Run in foreground
busytown run

# Or start as a background daemon
busytown start

2. Push an event

busytown plan prds/my-feature.md

3. Watch it go

The runner picks up the event, dispatches it to matching agents, and each agent pushes new events that trigger the next stage. Every event is streamed to the terminal as ndjson.

Included agents

The agents/ directory ships with a plan-code-review loop:

| Agent | Listens for | Does | Pushes | | ---------- | -------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------- | | plan | plan.request, review.created | Reads a PRD, explores the codebase, writes an implementation plan to plans/ | plan.created | | code | plan.created | Follows the plan to implement code changes | code.review | | review | code.review | Reviews the diff for correctness, writes a review to reviews/ | review.created (verdict: approve or revise) |

If the reviewer says "revise", the plan agent picks it up and the loop continues until approval.

Writing your own agent

An agent is a markdown file in agents/ with YAML frontmatter:

---
description: Summarizes new documents
listen:
  - "file.create"
allowed_tools:
  - "Read"
  - "Write"
---

You are a summarizer agent. When a new file is created, read it and write a
summary to `summaries/<filename>.md`.

After writing the summary, push an event:

    busytown events push --type summary.created --worker summarizer \
      --payload '{"path": "summaries/<filename>.md"}'

Each agent runs as a headless Claude Code subprocess (claude --print), sandboxed to only the tools you allow.

The agent's markdown body becomes its system prompt. The runner automatically injects context about the event queue CLI so agents know how to push events.

Fields:

  • type — Agent type (default claude)
  • description — What the agent does (included in its system prompt context)
  • listen — Event types to react to. Supports exact match (plan.created), prefix glob (file.*), or wildcard (*)
  • allowed_tools — Claude Code tools the agent can use (e.g. Read, Write, Edit, Grep, Glob, Bash(git:*)). Only applies to claude agents.
  • model — Claude model to use (e.g. haiku, sonnet, opus, or a full model ID). Optional; defaults to whatever model the user has configured globally.
  • effort — Thinking effort level: low, medium, or high. Optional; defaults to the CLI default.

Shell agents

For lightweight tasks that don't need an LLM — formatting, linting, running scripts — use type: shell instead. The text body becomes a shell script (run via sh -c) with Mustache-style template placeholders. The body can be a single command or a full multi-line script — variables, conditionals, loops, pipes, and heredocs all work:

---
type: shell
listen:
  - "file.create"
---

path={{event.payload.path}} echo "Processing $path"
deno fmt "$path" busytown events push --type file.formatted --worker formatter

Template syntax:

  • {{key}} — Resolves the value and shell-escapes it (single-quote wrapping). Safe by default.
  • {{{key}}} — Resolves the value and inserts it raw (no escaping). Use when you need unquoted paths or command fragments.
  • Dot paths like {{event.payload.path}} walk nested objects.
  • Missing keys resolve to an empty string.

The template context contains the full event object as event, so any field from the event (id, type, timestamp, worker_id, payload) is available.

Shell agent stdout and stderr are logged to logs/<agent-id>.log, the same as Claude agents.

CLI

After installing (deno task install), use busytown from any directory:

busytown <command> [options]

Event queue commands

# Push an event
busytown events push --type my.event --worker my-script --payload '{"key":"value"}'

# Query events
busytown events list --type plan.* --limit 10 --tail

# Watch for new events (streams ndjson)
busytown events watch --worker my-watcher

# Check a worker's cursor position
busytown events cursor --worker my-agent

# Claim an event
busytown events claim --event 42 --worker my-agent

# Check who claimed an event
busytown events check-claim --event 42

Agent runner commands

busytown <command> [options]

# Commands
run                    # Run poll loop in foreground
start                  # Start as background daemon
stop                   # Stop the daemon
restart                # Restart the daemon
status                 # Check if daemon is running
plan <prd-file>        # Push a plan.request event

# Options
--agents-dir <path>    # Agent definitions directory (default: agents/)
--db <path>            # Database path (default: events.db)
--poll <ms>            # Poll interval in ms (default: 1000)
--agent-cwd <path>     # Working directory for agents (default: .)
--watch <paths>        # Paths to watch for FS changes (default: .)
--exclude <patterns>   # Glob patterns to exclude from watching

Dashboard

busytown includes a terminal dashboard for monitoring agent activity:

busytown dashboard

The dashboard tracks agent status, file events, active claims, and events. It also surfaces tool permission requests from agents.

Keyboard shortcuts:

| Key | Action | | ------- | --------------------------------- | | j/k | Scroll the event stream up/down | | y/n | Allow / deny a permission request | | s | Toggle system events on/off | | Tab | Switch focus between panels | | q | Quit |

Options:

busytown dashboard --db events.db --poll 500
  • --db <path> — Database path (default: events.db)
  • --poll <ms> — Poll interval in ms (default: 500)

File system watcher

The runner watches directories for file system changes and pushes file.create, file.modify, file.delete, and file.rename events. By default it watches the current directory (.).

# Watch specific directories
busytown run --watch src --watch docs

# Exclude patterns (glob syntax)
busytown run --exclude '**/dist/**' --exclude '**/build/**'

Common paths (.git, node_modules, .DS_Store, *.pid, *.log, events.db*) are excluded automatically.

This lets you build agents that react to file changes — useful for auto-indexing, summarization, or triggering builds.

Key concepts

  • Cursor-based delivery — Each worker maintains its own cursor in the queue. The cursor advances immediately when an event is read, before it is processed, giving at-most-once delivery. Workers only see events newer than their cursor.
  • First-claim-wins — When multiple agents listen for the same event type, claimEvent() ensures only one agent processes a given event.
  • Namespace wildcards — Event types use dot-separated namespaces. Agents can listen for file.* to catch file.create, file.modify, etc.
  • Agents are just markdown — Agent definitions are markdown files. The body is the system prompt, the frontmatter is config. Easy to version, review, and iterate on.
  • No agent coupling — Agents

Related Skills

View on GitHub
GitHub Stars39
CategoryData
Updated8d ago
Forks4

Languages

TypeScript

Security Score

95/100

Audited on Mar 29, 2026

No findings