# Start polecat on issue (creates fresh worktree)
gt handoff # Polecat requests shutdown (run when done)
gt session stop # Kill polecat session (Witness uses this)
```
**Note**: `gt wake` and `gt sleep` are deprecated - polecats are ephemeral, not pooled.
### Landing & Merge Queue
```bash
gt merge-queue add # Add to merge queue (normal flow)
gt merge-queue list # Show pending merges
gt refinery process # Trigger Refinery to process queue
gt land --direct / # Direct landing (bypass Refinery)
gt land --direct --force ... # Skip safety checks
gt land --direct --skip-tests ... # Skip test verification
gt land --direct --dry-run ... # Preview only
```
### Emergency Operations
```bash
gt stop --all # Kill ALL sessions (emergency halt)
gt stop --rig # Kill all sessions in one rig
gt doctor --fix # Auto-repair common issues
```
## Plugins
Gas Town supports **plugins** - but in the simplest possible way: plugins are just more agents.
### Philosophy
Gas Town is intentionally rough and lightweight. A "credible plugin system" with manifests, schemas, and invocation frameworks would be pretentious for a project named after a Mad Max wasteland. Instead, plugins follow the same patterns as all Gas Town agents:
- **Identity**: Plugins have persistent identities like polecats and witnesses
- **Communication**: Plugins use mail for input/output
- **Artifacts**: Plugins produce beads, files, or other handoff artifacts
- **Lifecycle**: Plugins can be invoked on-demand or at specific workflow points
### Plugin Structure
Plugins live in a rig's `plugins/` directory:
```
wyvern/ # Rig
βββ plugins/
β βββ merge-oracle/ # A plugin
β βββ rig/ # Plugin's git clone (if needed)
β βββ CLAUDE.md # Plugin's instructions/prompts
β βββ mail/inbox.jsonl # Plugin's mailbox
β βββ state.json # Plugin state (optional)
```
That's it. No plugin.yaml, no special registration. If the directory exists, the plugin exists.
### Invoking Plugins
Plugins are invoked like any other agent - via mail:
```bash
# Refinery asks merge-oracle to analyze pending changesets
gt send wyvern/plugins/merge-oracle -s "Analyze merge queue" -m "..."
# Mayor asks plan-oracle for a work breakdown
gt send beads/plugins/plan-oracle -s "Plan for bd-xyz" -m "..."
```
Plugins do their work (potentially spawning Claude sessions) and respond via mail, creating any necessary artifacts (beads, files, branches).
### Hook Points
Existing agents can be configured to notify plugins at specific points. This is just convention - agents check if a plugin exists and mail it:
| Workflow Point | Agent | Example Plugin |
|----------------|-------|----------------|
| Before merge processing | Refinery | merge-oracle |
| Before work dispatch | Mayor | plan-oracle |
| On worker stuck | Witness | debug-oracle |
| On PR ready | Refinery | review-oracle |
Configuration is minimal - perhaps a line in the agent's CLAUDE.md or state.json noting which plugins to consult.
### Example: Merge Oracle
The **merge-oracle** plugin analyzes changesets before the Refinery processes them:
**Input** (via mail from Refinery):
- List of pending changesets
- Current merge queue state
**Processing**:
1. Build overlap graph (which changesets touch same files/regions)
2. Classify disjointness (fully disjoint β parallel safe, overlapping β needs sequencing)
3. Use LLM to assess semantic complexity of overlapping components
4. Identify high-risk patterns (deletions vs modifications, conflicting business logic)
**Output**:
- Bead with merge plan (parallel groups, sequential chains)
- Mail to Refinery with recommendation (proceed / escalate to Mayor)
- If escalation needed: mail to Mayor with explanation
The merge-oracle's `CLAUDE.md` contains the prompts and classification criteria. Gas Town doesn't need to know the internals.
### Example: Plan Oracle
The **plan-oracle** plugin helps decompose work:
**Input**: An issue/epic that needs breakdown
**Processing**:
1. Analyze the scope and requirements
2. Identify dependencies and blockers
3. Estimate complexity (for parallelization decisions)
4. Suggest task breakdown
**Output**:
- Beads for the sub-tasks (created via `bd create`)
- Dependency links (via `bd dep add`)
- Mail back with summary and recommendations
### Why This Design
1. **Fits Gas Town's aesthetic**: Rough, text-based, agent-shaped
2. **Zero new infrastructure**: Uses existing mail, beads, identities
3. **Composable**: Plugins can invoke other plugins
4. **Debuggable**: Just look at mail logs and bead history
5. **Extensible**: Anyone can add a plugin by creating a directory
### Plugin Discovery
```bash
gt plugins # List plugins in a rig
gt plugin status # Check plugin state
```
Or just `ls /plugins/`.
## Failure Modes and Recovery
Gas Town is designed for resilience. Common failure modes and their recovery:
| Failure | Detection | Recovery |
|---------|-----------|----------|
| Agent crash | Session gone, state shows 'working' | `gt doctor` detects, reset state to idle |
| Git dirty state | Witness pre-kill check fails | Nudge worker, or manual commit/discard |
| Beads sync conflict | `bd sync` fails | Beads tombstones handle most cases |
| Tmux crash | All sessions inaccessible | `gt doctor --fix` cleans up |
| Stuck work | No progress for 30+ minutes | Witness escalates, Overseer intervenes |
| Disk full | Write operations fail | Clean logs, remove old clones |
### Recovery Principles
1. **Fail safe**: Prefer stopping over corrupting data
2. **State is recoverable**: Git and beads have built-in recovery
3. **Doctor heals**: `gt doctor --fix` handles common issues
4. **Emergency stop**: `gt stop --all` as last resort
5. **Human escalation**: Some failures need Overseer intervention
### Doctor Checks
`gt doctor` performs health checks at both workspace and rig levels:
**Workspace checks**: Config validity, Mayor mailbox, rig registry
**Rig checks**: Git state, clone health, Witness/Refinery presence
**Work checks**: Stuck detection, zombie sessions, heartbeat health
Run `gt doctor` regularly. Run `gt doctor --fix` to auto-repair issues.
## Federation: Outposts
Federation enables Gas Town to scale across machines via **Outposts** - remote compute environments that can run workers.
**Full design**: See `docs/federation-design.md`
### Outpost Types
| Type | Description | Cost Model | Best For |
|------|-------------|------------|----------|
| Local | Current tmux model | Free | Development, primary work |
| SSH/VM | Full Gas Town clone on VM | Always-on | Long-running, autonomous |
| CloudRun | Container workers on GCP | Pay-per-use | Burst, elastic, background |
### Core Abstraction
```go
type Outpost interface {
Name() string
Type() OutpostType // local, ssh, cloudrun
MaxWorkers() int
ActiveWorkers() int
Spawn(issue string, config WorkerConfig) (Worker, error)
Workers() []Worker
Ping() error
}
type Worker interface {
ID() string
Outpost() string
Status() WorkerStatus // idle, working, done, failed
Issue() string
Attach() error // for interactive outposts
Logs() (io.Reader, error)
Stop() error
}
```
### Configuration
```yaml
# ~/gt/config/outposts.yaml
outposts:
- name: local
type: local
max_workers: 4
- name: gce-burst
type: ssh
host: 10.0.0.5
user: steve
town_path: /home/steve/ai
max_workers: 8
- name: cloudrun-burst
type: cloudrun
project: my-gcp-project
region: us-central1
service: gastown-worker
max_workers: 20
cost_cap_hourly: 5.00
policy:
default_preference: [local, gce-burst, cloudrun-burst]
```
### Cloud Run Workers
Cloud Run enables elastic, pay-per-use workers:
- **Persistent HTTP/2 connections** solve cold start (zero-to-one) problem
- **Cost**: ~$0.017 per 5-minute worker session
- **Scaling**: 0βN automatically based on demand
- **When idle**: Scales to zero, costs nothing
Workers receive work via HTTP, clone code from git, run Claude, push results. No filesystem mail needed - HTTP is the control plane.
### SSH/VM Outposts
Full Gas Town clone on remote machines:
- **Model**: Complete town installation via SSH
- **Workers**: Remote tmux sessions
- **Sync**: Git for code and beads
- **Good for**: Long-running work, full autonomy if disconnected
### Design Principles
1. **Outpost abstraction** - Support multiple backends via unified interface
2. **Local-first** - Remote outposts are for overflow/burst, not primary
3. **Git as source of truth** - Code and beads sync everywhere
4. **HTTP for Cloud Run** - Don't force mail onto stateless containers
5. **Graceful degradation** - System works with any subset of outposts
### Architecture Diagram
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MAYOR β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Outpost Manager β β
β β - Tracks all registered outposts β β
β β - Routes work to appropriate outpost β β
β β - Monitors worker status across outposts β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β β β
β βΌ βΌ βΌ β
β ββββββββββββ ββββββββββββ ββββββββββββββββ β
β β Local β β SSH β β CloudRun β β
β β Outpost β β Outpost β β Outpost β β
β ββββββ¬ββββββ ββββββ¬ββββββ ββββββββ¬ββββββββ β
βββββββββΌβββββββββββββββΌβββββββββββββββββββΌββββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββ βββββββββββ βββββββββββββββ
β tmux β β SSH β β HTTP/2 β
β panes β βsessions β β connections β
βββββββββββ βββββββββββ βββββββββββββββ
β β β
ββββββββββββββββΌβββββββββββββββββββ
βΌ
βββββββββββββββββββ
β Git Repos β
β (code + beads) β
βββββββββββββββββββ
```
### CLI Commands
```bash
gt outpost list # List configured outposts
gt outpost status [name] # Detailed status
gt outpost add ... # Add new outpost
gt outpost ping # Test connectivity
```
### Implementation Status
Federation is tracked in **gt-9a2** (P3 epic). Key tasks:
- `gt-9a2.1`: Outpost/Worker interfaces
- `gt-9a2.2`: LocalOutpost (refactor current spawning)
- `gt-9a2.5`: SSHOutpost
- `gt-9a2.8`: CloudRunOutpost
## Implementation Status
Gas Town is being ported from Python (gastown-py) to Go (gastown). The Go port (GGT) is in development:
- **Epic**: gt-u1j (Port Gas Town to Go)
- **Scaffolding**: gt-u1j.1 (Go scaffolding - blocker for implementation)
- **Management**: gt-f9x (Town & Rig Management: install, doctor, federation)
See beads issues with `bd list --status=open` for current work items.