{"id":49740525,"url":"https://github.com/gordonbrander/busytown","last_synced_at":"2026-05-09T18:15:25.035Z","repository":{"id":337169831,"uuid":"1151994248","full_name":"gordonbrander/busytown","owner":"gordonbrander","description":"Multi-agent factories coordinated over a SQLite queue","archived":false,"fork":false,"pushed_at":"2026-02-22T14:19:06.000Z","size":1328,"stargazers_count":23,"open_issues_count":16,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-22T19:24:12.132Z","etag":null,"topics":["agent","multi-agent-system","sqlite"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gordonbrander.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-07T07:32:09.000Z","updated_at":"2026-02-22T14:19:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gordonbrander/busytown","commit_stats":null,"previous_names":["gordonbrander/busytown"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/gordonbrander/busytown","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gordonbrander%2Fbusytown","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gordonbrander%2Fbusytown/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gordonbrander%2Fbusytown/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gordonbrander%2Fbusytown/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gordonbrander","download_url":"https://codeload.github.com/gordonbrander/busytown/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gordonbrander%2Fbusytown/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32829821,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"online","status_checked_at":"2026-05-09T02:00:06.633Z","response_time":123,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","multi-agent-system","sqlite"],"created_at":"2026-05-09T18:15:24.329Z","updated_at":"2026-05-09T18:15:25.029Z","avatar_url":"https://github.com/gordonbrander.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# busytown\n\n_A town full of busy little guys who do things._\n\n**busytown** is a multi-agent coordination framework built around a shared\nSQLite event queue. Each agent is a separate Claude Code instance. Agents listen\nfor events, react to them, and push new events, forming an asynchronous pipeline\nwhere no agent needs to know about any other agent, only about the events.\n\n\u003cp\u003e\u003cimg src=\"./busytown.png\" src=\"A town full of busy little guys who do things\" /\u003e\u003c/p\u003e\n\n## How it works\n\nEverything is stored in a single SQLite database (`events.db`). Events are\nsimple JSON objects:\n\n```json\n{\n  \"id\": 1,\n  \"type\": \"plan.request\",\n  \"timestamp\": \"...\",\n  \"worker_id\": \"user\",\n  \"payload\": { \"prd_path\": \"prds/my-feature.md\" }\n}\n```\n\nThe agent runner polls the queue and dispatches events to matching agents.\nAgents run in parallel, but each agent processes events serially, one at a time,\nin order. The agent:\n\n- **Listens** for specific event types (exact match, prefix glob like `file.*`,\n  or wildcard `*`)\n- **Reacts** by reading files, writing code, producing artifacts\n- **Pushes** new events to notify other agents of what it did\n- **Claims** events when needed, so only one agent acts on a given event\n\nAgents can also use the filesystem as a shared workspace for saving memories,\nplans, WIP, etc.\n\n## Architecture\n\n```\n┌──────────┐    push     ┌─────────────────┐    dispatch    ┌───────────┐\n│  User /  │───────────▸ │  SQLite Event   │ ─────────────▸ │  Agent    │\n│  Script  │             │  Queue          │                │  (Claude) │\n└──────────┘             │                 │ ◂───────────── └───────────┘\n                         │  events table   │    push new\n                         │  worker_cursors │    events\n                         │  claims         │\n                         └─────────────────┘\n                               ▲     │\n                               │     ▼\n                         ┌───────────┐\n                         │  Agent    │\n                         │  (Claude) │\n                         └───────────┘\n```\n\n## Getting started\n\n**Prerequisites:** [Deno](https://deno.land/) and\n[Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed.\n\n### Install\n\n```bash\n# Install the `busytown` command globally\ndeno task install\n```\n\nThis creates a `busytown` command you can run from any directory.\n\n### 1. Start the agent runner\n\n```bash\n# Run in foreground\nbusytown run\n\n# Or start as a background daemon\nbusytown start\n```\n\n### 2. Push an event\n\n```bash\nbusytown plan prds/my-feature.md\n```\n\n### 3. Watch it go\n\nThe runner picks up the event, dispatches it to matching agents, and each agent\npushes new events that trigger the next stage. Every event is streamed to the\nterminal as ndjson.\n\n## Included agents\n\nThe `agents/` directory ships with a **plan-code-review loop**:\n\n| Agent      | Listens for                      | Does                                                                          | Pushes                                        |\n| ---------- | -------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------- |\n| **plan**   | `plan.request`, `review.created` | Reads a PRD, explores the codebase, writes an implementation plan to `plans/` | `plan.created`                                |\n| **code**   | `plan.created`                   | Follows the plan to implement code changes                                    | `code.review`                                 |\n| **review** | `code.review`                    | Reviews the diff for correctness, writes a review to `reviews/`               | `review.created` (verdict: approve or revise) |\n\nIf the reviewer says \"revise\", the plan agent picks it up and the loop continues\nuntil approval.\n\n## Writing your own agent\n\nAn agent is a markdown file in `agents/` with YAML frontmatter:\n\n```markdown\n---\ndescription: Summarizes new documents\nlisten:\n  - \"file.create\"\nallowed_tools:\n  - \"Read\"\n  - \"Write\"\n---\n\nYou are a summarizer agent. When a new file is created, read it and write a\nsummary to `summaries/\u003cfilename\u003e.md`.\n\nAfter writing the summary, push an event:\n\n    busytown events push --type summary.created --worker summarizer \\\n      --payload '{\"path\": \"summaries/\u003cfilename\u003e.md\"}'\n```\n\nEach agent runs as a headless Claude Code subprocess (`claude --print`),\nsandboxed to only the tools you allow.\n\nThe agent's markdown body becomes its system prompt. The runner automatically\ninjects context about the event queue CLI so agents know how to push events.\n\n**Fields:**\n\n- `type` — Agent type (default `claude`)\n- `description` — What the agent does (included in its system prompt context)\n- `listen` — Event types to react to. Supports exact match (`plan.created`),\n  prefix glob (`file.*`), or wildcard (`*`)\n- `allowed_tools` — Claude Code tools the agent can use (e.g. `Read`, `Write`,\n  `Edit`, `Grep`, `Glob`, `Bash(git:*)`). Only applies to `claude` agents.\n- `model` — Claude model to use (e.g. `haiku`, `sonnet`, `opus`, or a full model\n  ID). Optional; defaults to whatever model the user has configured globally.\n- `effort` — Thinking effort level: `low`, `medium`, or `high`. Optional;\n  defaults to the CLI default.\n\n### Shell agents\n\nFor lightweight tasks that don't need an LLM — formatting, linting, running\nscripts — use `type: shell` instead. The text body becomes a shell script (run\nvia `sh -c`) with Mustache-style template placeholders. The body can be a single\ncommand or a full multi-line script — variables, conditionals, loops, pipes, and\nheredocs all work:\n\n```markdown\n---\ntype: shell\nlisten:\n  - \"file.create\"\n---\n\npath={{event.payload.path}} echo \"Processing $path\"\ndeno fmt \"$path\" busytown events push --type file.formatted --worker formatter\n```\n\n**Template syntax:**\n\n- `{{key}}` — Resolves the value and **shell-escapes** it (single-quote\n  wrapping). Safe by default.\n- `{{{key}}}` — Resolves the value and inserts it **raw** (no escaping). Use\n  when you need unquoted paths or command fragments.\n- Dot paths like `{{event.payload.path}}` walk nested objects.\n- Missing keys resolve to an empty string.\n\nThe template context contains the full event object as `event`, so any field\nfrom the event (id, type, timestamp, worker_id, payload) is available.\n\nShell agent stdout and stderr are logged to `logs/\u003cagent-id\u003e.log`, the same as\nClaude agents.\n\n## CLI\n\nAfter installing (`deno task install`), use `busytown` from any directory:\n\n```bash\nbusytown \u003ccommand\u003e [options]\n```\n\n### Event queue commands\n\n```bash\n# Push an event\nbusytown events push --type my.event --worker my-script --payload '{\"key\":\"value\"}'\n\n# Query events\nbusytown events list --type plan.* --limit 10 --tail\n\n# Watch for new events (streams ndjson)\nbusytown events watch --worker my-watcher\n\n# Check a worker's cursor position\nbusytown events cursor --worker my-agent\n\n# Claim an event\nbusytown events claim --event 42 --worker my-agent\n\n# Check who claimed an event\nbusytown events check-claim --event 42\n```\n\n### Agent runner commands\n\n```bash\nbusytown \u003ccommand\u003e [options]\n\n# Commands\nrun                    # Run poll loop in foreground\nstart                  # Start as background daemon\nstop                   # Stop the daemon\nrestart                # Restart the daemon\nstatus                 # Check if daemon is running\nplan \u003cprd-file\u003e        # Push a plan.request event\n\n# Options\n--agents-dir \u003cpath\u003e    # Agent definitions directory (default: agents/)\n--db \u003cpath\u003e            # Database path (default: events.db)\n--poll \u003cms\u003e            # Poll interval in ms (default: 1000)\n--agent-cwd \u003cpath\u003e     # Working directory for agents (default: .)\n--watch \u003cpaths\u003e        # Paths to watch for FS changes (default: .)\n--exclude \u003cpatterns\u003e   # Glob patterns to exclude from watching\n```\n\n## Dashboard\n\nbusytown includes a terminal dashboard for monitoring agent activity:\n\n```bash\nbusytown dashboard\n```\n\nThe dashboard tracks agent status, file events, active claims, and events. It\nalso surfaces tool permission requests from agents.\n\n**Keyboard shortcuts:**\n\n| Key     | Action                            |\n| ------- | --------------------------------- |\n| `j`/`k` | Scroll the event stream up/down   |\n| `y`/`n` | Allow / deny a permission request |\n| `s`     | Toggle system events on/off       |\n| `Tab`   | Switch focus between panels       |\n| `q`     | Quit                              |\n\n**Options:**\n\n```bash\nbusytown dashboard --db events.db --poll 500\n```\n\n- `--db \u003cpath\u003e` — Database path (default: `events.db`)\n- `--poll \u003cms\u003e` — Poll interval in ms (default: `500`)\n\n## File system watcher\n\nThe runner watches directories for file system changes and pushes `file.create`,\n`file.modify`, `file.delete`, and `file.rename` events. By default it watches\nthe current directory (`.`).\n\n```bash\n# Watch specific directories\nbusytown run --watch src --watch docs\n\n# Exclude patterns (glob syntax)\nbusytown run --exclude '**/dist/**' --exclude '**/build/**'\n```\n\nCommon paths (`.git`, `node_modules`, `.DS_Store`, `*.pid`, `*.log`,\n`events.db*`) are excluded automatically.\n\nThis lets you build agents that react to file changes — useful for\nauto-indexing, summarization, or triggering builds.\n\n## Key concepts\n\n- **Cursor-based delivery** — Each worker maintains its own cursor in the queue.\n  The cursor advances immediately when an event is read, before it is processed,\n  giving at-most-once delivery. Workers only see events newer than their cursor.\n- **First-claim-wins** — When multiple agents listen for the same event type,\n  `claimEvent()` ensures only one agent processes a given event.\n- **Namespace wildcards** — Event types use dot-separated namespaces. Agents can\n  listen for `file.*` to catch `file.create`, `file.modify`, etc.\n- **Agents are just markdown** — Agent definitions are markdown files. The body\n  is the system prompt, the frontmatter is config. Easy to version, review, and\n  iterate on.\n- **No agent coupling** — Agents don't know about each other. They only know\n  about events. You can add, remove, or swap agents without changing anything\n  else.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgordonbrander%2Fbusytown","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgordonbrander%2Fbusytown","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgordonbrander%2Fbusytown/lists"}