Coordinate multiple Claude Code instances working on the same codebase using native Claude Code tasks.
From crates.io:
cargo install midtownOr from source:
cargo install --path .From your project directory:
midtown startThis starts the daemon and creates a tmux session with the Lead window.
midtown attachYou're now in the Lead's Claude Code instance.
The Lead can spawn coworkers to parallelize work:
midtown coworker spawn
# => Spawned coworker: lexingtonCoworkers are named after Manhattan avenues: lexington, park, madison, broadway, amsterdam, columbus, riverside, york, pleasant, vernon.
midtown statusShows: active coworkers, open tasks, open PRs, recent channel activity.
midtown stopMidtown is inspired by Gastown, but a bit simpler, less exciting, and, well, more mid.
At its core, Midtown is built around an IRC-like messaging model: a shared channel where team members (both the human-facing Lead and autonomous Coworkers) post updates, coordinate handoffs, and stay in sync. This append-only message stream is the backbone of multi-agent collaboration—each Claude Code instance reads the channel at natural pause points, just like checking a team chat.
When you're working with Claude Code on a complex project, you might want to parallelize work:
- The Lead collaborates with the human to create a plan & split up the work into tasks & depedendencies.
- Multiple Coworkers implement independent components simultaneously
- The Coworker review & merge PRs while the Lead & human collaborate on what's next
Midtown provides the infrastructure for this coordination:
- Channel messaging - IRC-like append-only message stream for team communication
- Coworker spawning - Launch Claude Code instances in isolated git worktrees
- Task coordination - Coworkers claim tasks via Claude Code's native task system
Access Midtown remotely via the built-in web interface:
midtown start # Web server starts on port 47022The web app provides:
- Real-time chat with WebSocket updates and markdown rendering
- Kanban board showing tasks and PRs at a glance
- Tmux tab for streaming any tmux window
- Mobile-friendly Svelte interface for on-the-go monitoring
A visual task board appears in both the terminal (chat pane) and web UI:
- In Progress column shows active tasks with duration
- Review column shows open PRs with CI status dots (✓ green, ✗ red, ○ pending)
- Done column shows recently merged PRs
- Clickable GitHub hyperlinks to PRs
The daemon handles routine coordination automatically:
- Auto-spawn - Spawns coworkers when pending tasks are available
- Auto-shutdown - Shuts down idle coworkers after 5 minutes
- Auto-review - Spawns reviewers for open PRs
- CI failure handling - Notifies PR owners of CI failures and merge conflicts
- Plugin sync - Automatically installs required plugins for coworkers
- Duplicate detection - Kills duplicate workers claiming the same task
The terminal chat pane includes:
- Selection mode (
skey) - Toggle for copying text - Coworker colors - Each coworker has a distinct color
- Grouped messages - Messages from the same author are grouped
- Live updates - Async tail-based updates for instant message delivery
- Scrollable history - Mouse wheel scrolling through message history
Stay informed about important events:
- @mention routing - Messages mentioning
@coworkerare delivered to that coworker - PR activity nudges - Coworkers are nudged when their PRs receive comments or reviews
- Feedback detection - Lead is nudged when coworkers request input
- Mobile nudges - Lead receives nudges for messages sent from the mobile web app
- Interrupted coworker detection - Detects and restarts stuck coworkers
Automatic webhook integration with GitHub events (requires gh auth login):
- PR opened, merged, closed events appear in channel
- CI status updates (checks passing/failing)
- Review comments and approvals
- Merge conflict detection
┌─────────────────────────────────────────────────────────────┐
│ Human Developer │
└─────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Lead (Claude Code) │
│ main git worktree │
└─────────────────────────┬───────────────────────────────────┘
│ midtown CLI
▼
┌─────────────────────────────────────────────────────────────┐
│ Midtown Daemon │
├─────────────────────────┬───────────────────────────────────┤
│ Channel │ Coworker Manager │
│ (append-only log) │ (spawn/track/shutdown) │
└─────────────────────────┴───────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────────┐
│ tmux session: midtown-<project> │
├─────────────┬─────────────┬─────────────┬───────────────────┤
│ Lead │ lexington │ park │ madison │
│ (window) │ (window) │ (window) │ (window) │
│ │ worktree │ worktree │ worktree │
└─────────────┴─────────────┴─────────────┴───────────────────┘
All agents run as windows within a single tmux session. Use Ctrl-b w to see everyone, Ctrl-b n/p to switch between them.
midtown <COMMAND>
Commands:
start Start the daemon and tmux session
stop Stop daemon and all coworkers
attach Attach to the tmux session
status Show system status
channel Channel messaging
post <MSG> Post a message
read Read recent messages
coworker Coworker management
spawn Spawn a new coworker
list List active coworkers
shutdown <N> Shutdown coworker by name
Midtown uses two config files:
- Global config at
~/.midtown/config.toml— applies to all projects - Project config at
~/.midtown/projects/<project>/config.toml— overrides per project
Project settings take precedence over global defaults. All fields are optional.
# Global config: ~/.midtown/config.toml
[default]
bin_command = "midtown" # CLI command to invoke midtown
chat_layout = "auto" # "auto", "split", or "window"
chat_min_width = 160 # Min terminal width for split layout (auto mode)
max_coworkers = 16 # Maximum concurrent coworkers
[plugins]
required = [
"superpowers@claude-plugins-official",
]
[daemon]
webhook_port = 47022 # Web UI & webhook port (0 to disable)
webhook_secret = "your-secret" # GitHub webhook signature secret
webhook_restart_interval_secs = 300 # Webhook forwarder restart interval
pr_poll_interval_secs = 30 # PR polling interval
chat_monitor_enabled = true # Enable @mention routingProject config files use only the [default] fields (no section header needed):
# Project config: ~/.midtown/projects/myproject/config.toml
bin_command = "cargo run --release --"
max_coworkers = 4Daemon settings can be overridden with environment variables:
| Variable | Overrides |
|---|---|
MIDTOWN_WEBHOOK_PORT |
webhook_port |
MIDTOWN_WEBHOOK_SECRET |
webhook_secret |
MIDTOWN_WEBHOOK_RESTART_INTERVAL |
webhook_restart_interval_secs |
MIDTOWN_PR_POLL_INTERVAL |
pr_poll_interval_secs |
MIDTOWN_CHAT_MONITOR |
chat_monitor_enabled (set to 0 to disable) |
MIDTOWN_MAX_COWORKERS |
max_coworkers |
Each coworker runs in:
- An isolated git worktree (no merge conflicts during development)
- A tmux window within the project session
- With a Stop hook that syncs the channel at natural pause points
Coworkers stay synchronized via a Claude Code Stop hook. When Claude pauses, the hook reads new channel messages and checks for unclaimed tasks. This means coworkers automatically receive updates at natural pause points.
MIT