Midtown
Coordinate multiple Claude Code instances working on the same codebase using native Claude Code tasks.
Quick Start
1. Install
From crates.io:
Or from source:
2. Start midtown
From your project directory:
This starts the daemon and creates a tmux session with the Lead window.
For multi-repo projects, specify a project name and additional repos:
3. Attach to the session
You're now in the Lead's Claude Code instance.
To attach to a named project from any directory:
4. Call in coworkers
The Lead can call in coworkers to parallelize work:
# => Called in coworker: lexington
Coworkers are named after Manhattan avenues: lexington, park, madison, broadway, amsterdam, columbus, riverside, york, pleasant, vernon.
5. Monitor progress
Shows: active coworkers, open tasks, open PRs, recent channel activity.
6. Stop when done
Why Midtown?
Midtown 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 & dependencies.
- Multiple Coworkers implement independent components simultaneously
- The Coworkers 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 call-in - Launch Claude Code instances in isolated git worktrees
- Task coordination - Coworkers claim tasks via Claude Code's native task system
- Multi-project support - Run multiple projects simultaneously with isolated daemons
Features
Multi-Project Support
Midtown can manage multiple projects, each with its own daemon, tmux session, and set of coworkers. Projects are identified by name and can span multiple repositories.
Starting a project:
# Single-repo project (name inferred from directory)
# Named project with additional repos
Managing projects:
# List all known projects and their status
# Attach to a specific project
Each project gets:
- Its own daemon process and Unix socket
- A tmux session named
midtown-<project> - A dedicated channel log and task list
- An auto-assigned webhook port (47023+)
- Per-project configuration in
~/.midtown/projects/<project>/config.toml
Multi-Repo Worktrees
For projects spanning multiple repositories, coworkers automatically get isolated worktrees in every repo. When a coworker is called in, midtown creates a git worktree in each configured repo and passes them to Claude Code via --add-dir flags. This gives each coworker access to all repos in the project.
When coworkers shut down, worktrees with no commits and no uncommitted changes are automatically cleaned up, along with their branches.
Shared Webserver
A standalone webserver provides a unified view across all projects:
The shared webserver discovers running project daemons and proxies to their per-project webhook servers. Port 47022 is reserved for the shared webserver; per-project daemons use ports 47023+.
The midtown start command auto-launches the shared webserver if it's not already running.
Web App
Access Midtown remotely via the built-in web interface:
The 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
- Project tabs for switching between projects (shared webserver)
Kanban Board
A visual task board appears in both the terminal (chat pane) and web UI:
- Backlog column shows pending tasks
- In Progress column shows active tasks with owner and duration
- Review column shows open PRs with CI status dots (● green, ● red, ○ pending), author, and reviewer
- Done column shows recently merged PRs
- Clickable GitHub hyperlinks to PRs
- Collapsible column headings
- Repo badges in multi-repo projects (e.g.,
[frontend] PR#42)
The terminal also displays a repo status bar showing the latest commit, CI status, and tag for each repo. Multi-repo projects show one status line per repo.
Automation
The daemon handles routine coordination automatically:
- Auto-call-in - Calls in coworkers when pending tasks are available
- Auto-shutdown - Shuts down idle coworkers after 5 minutes
- Auto-review - Calls in 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
- Reviewer slot reservation - Reserves 2 coworker slots for PR reviewers
- Orphan recovery - Detects and nudges orphaned coworkers to resume their tasks
- Channel log rotation - Auto-rotates channel.jsonl every 24 hours
Chat TUI
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
- Expandable input - Input box grows vertically with line wrapping
- Scroll-to-bottom button - Quick return to latest messages
Notifications & Nudges
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
- Review completion nudges - Idle PR authors are nudged when reviews finish
- Feedback detection - Lead is nudged when coworkers request input
- Mobile nudges - Lead receives nudges for messages sent from the mobile web app
- Orphan detection - Detects and restarts stuck or orphaned coworkers
GitHub Integration
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
Custom System Prompts
Customize the system prompts for Lead and Coworkers with markdown files:
~/.midtown/LEAD.md/~/.midtown/COWORKER.md- Global custom prompts~/.midtown/projects/<project>/LEAD.md/COWORKER.md- Per-project custom prompts
Content from these files is appended to the built-in system prompts. Project-level files supplement global ones.
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Human Developer │
└─────────────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Lead (Claude Code) │
│ main git worktree │
└─────────────────────────┬───────────────────────────────────┘
│ midtown CLI
▼
┌─────────────────────────────────────────────────────────────┐
│ Midtown Daemon │
├─────────────────────────┬───────────────────────────────────┤
│ Channel │ Coworker Manager │
│ (append-only log) │ (call-in/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.
For multi-project setups, each project gets its own daemon and tmux session. A shared webserver on port 47022 provides a unified view:
┌─────────────────────────────────────────────────────────────┐
│ Shared Webserver (:47022) │
│ discovers and proxies to project daemons │
└────────┬────────────────────────┬───────────────────────────┘
│ │
▼ ▼
┌────────────────────┐ ┌────────────────────┐
│ Project: backend │ │ Project: frontend │
│ Daemon (:47023) │ │ Daemon (:47024) │
│ tmux: midtown- │ │ tmux: midtown- │
│ backend │ │ frontend │
└────────────────────┘ └────────────────────┘
CLI Reference
midtown [OPTIONS] <COMMAND>
Options:
-C, --repo <PATH> Path to git repository (defaults to cwd)
Commands:
start Start the daemon and tmux session
--project <NAME> Project name (overrides auto-detection)
--repo <PATH> Additional repository paths (repeatable)
--daemon-only Start daemon without tmux session
stop Stop daemon and all coworkers
--keep-session Keep the tmux session running
restart Restart midtown (stop + start)
attach [PROJECT] Attach to a project's tmux session
status Show system status
project Project management
list List all projects and their status
channel Channel messaging
post <MSG> Post a message
read Read recent messages
coworker Coworker management
call-in Call in a new coworker
list List active coworkers
shutdown <NAME> Shutdown coworker by name
webserver Standalone multi-project webserver
run Start the webserver (port 47022)
stop Stop the webserver
restart Restart the webserver
Configuration
Midtown uses two levels of 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.toml
# ~/.midtown/config.toml
[]
= "midtown" # CLI command to invoke midtown
= "auto" # "auto", "split", or "window"
= 160 # Min terminal width for split layout (auto mode)
= 16 # Maximum concurrent coworkers
[]
= [
"superpowers@claude-plugins-official",
]
[]
= 47022 # Web UI & webhook port (0 to disable)
= "your-secret" # GitHub webhook signature secret
= 300 # Webhook forwarder restart interval
= 30 # PR polling interval
= true # Enable @mention routing
Project config.toml
Project configs support all global settings plus project metadata:
# ~/.midtown/projects/myapp/config.toml
[]
= "myapp"
= ["/path/to/backend", "/path/to/frontend"]
= "/path/to/backend"
[]
= "cargo run --release --"
= 4
[]
= 47023 # Auto-assigned if not set
The [project] section defines:
name- Project name used for tmux sessions, paths, etc.repos- List of repository paths belonging to the projectprimary_repo- The main repo used for the daemon socket and channel
For single-repo projects, only name is needed; repos and primary_repo are inferred from the working directory. This config is auto-created on first midtown start.
Environment Variable Overrides
Daemon 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 |
How It Works
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
- With
--add-dirworktrees for additional repos in multi-repo projects
Channel Sync
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.
Worktree Lifecycle
When a coworker is called in, midtown creates a detached git worktree at the current HEAD. The coworker creates a feature branch and works independently. When the coworker shuts down, worktrees with no commits and no uncommitted changes are automatically cleaned up along with their branches. Worktrees with work in progress are preserved.
Webhook Ports
Each project daemon runs its own webhook server for GitHub integration. Port 47022 is reserved for the shared multi-project webserver. Per-project daemons auto-assign ports starting at 47023, persisting the assignment in the project's config.toml for stability across restarts.
License
MIT