# zwarm

Multi-agent CLI for orchestrating coding agents. Spawn, manage, and converse with multiple Codex sessions in parallel.

## Installation

```bash
# From the workspace
cd /path/to/labs
uv sync

# Or install directly
uv pip install -e ./zwarm
```

**Requirements:**
- Python 3.13+
- `codex` CLI installed and authenticated

**Environment:**
```bash
export OPENAI_API_KEY="sk-..."        # Required for Codex
export WEAVE_PROJECT="entity/zwarm"   # Optional: Weave tracing
```

## Two Modes

zwarm has two ways to orchestrate coding agents:

| Mode | Who's in charge | Use case |
|------|-----------------|----------|
| `zwarm interactive` | **You** | Manual control, experimentation |
| `zwarm orchestrate` | **LLM** | Autonomous task execution |

Both use the **same underlying session manager** - the orchestrator LLM has access to the exact same tools you do.

---

## Interactive Mode

**You are the orchestrator.** Spawn sessions, check on them, continue conversations.

```bash
zwarm interactive
```

### Commands

| Command | Description |
|---------|-------------|
| `spawn "task"` | Start a session (waits for completion) |
| `spawn --async "task"` | Start async (returns immediately) |
| `spawn -d /path "task"` | Start in specific directory |
| `ls` | List all sessions |
| `? <id>` | Quick peek: status + latest message |
| `show <id>` | Full details: all messages, tokens, etc. |
| `c <id> "msg"` | Continue conversation (waits) |
| `ca <id> "msg"` | Continue async (returns immediately) |
| `kill <id>` | Stop a running session |
| `rm <id>` | Delete session entirely |
| `killall` | Stop all running sessions |
| `clean` | Remove sessions older than 7 days |
| `q` | Quit |

### Example Session

```
$ zwarm interactive

> spawn "Add a login function to auth.py"
✓ Started session a1b2c3d4, waiting...
[a1b2c3d4] codex (completed) - 32s
Response: I've added a login function with JWT support...

> spawn --async "Fix the type errors in utils.py"
✓ Session: b2c3d4e5 (running in background)

> spawn --async "Add unit tests for auth.py"
✓ Session: c3d4e5f6 (running in background)

> ls
1 running | 2 done

ID         │   │ T │ Task                        │ Updated │ Last Message
a1b2c3d4   │ ✓ │ 1 │ Add a login function...     │ 2m      │ I've added a login function...
b2c3d4e5   │ ✓ │ 1 │ Fix the type errors...      │ 30s ★   │ Fixed 3 type errors in...
c3d4e5f6   │ ● │ 1 │ Add unit tests...           │ 5s      │ (working...)

> ? b2c3d4e5
✓ b2c3d4e5 Fixed 3 type errors: Optional[str] -> str | None, added missing...

> c a1b2c3d4 "Now add password hashing with bcrypt"
Continuing session a1b2c3d4...
[a1b2c3d4] codex (completed) - 28s
Response: Done! I've updated the login function to use bcrypt...

> rm b2c3d4e5
✓ Deleted session b2c3d4e5

> q
```

### Session Status Icons

| Icon | Status |
|------|--------|
| `●` | Running |
| `✓` | Completed |
| `✗` | Failed |
| `○` | Killed |
| `★` | Recently completed (< 60s) |

---

## Orchestrate Mode

**An LLM is the orchestrator.** Give it a task and it delegates to coding agents.

```bash
zwarm orchestrate --task "Build a REST API with authentication"
```

The orchestrator LLM uses the same tools available in interactive mode:

| Tool | Description |
|------|-------------|
| `delegate(task, ...)` | Start a new session |
| `converse(id, msg)` | Continue a conversation |
| `peek_session(id)` | Quick status check |
| `check_session(id)` | Full session details |
| `list_sessions()` | List all sessions with `needs_attention` flags |
| `end_session(id, delete=False)` | Kill/delete a session |

### Task Input

```bash
# Direct
zwarm orchestrate --task "Build a REST API"

# From file
zwarm orchestrate --task-file task.md

# From stdin
echo "Fix the bug in auth.py" | zwarm orchestrate
```

---

## Configuration

zwarm looks for config in this order:
1. `--config` flag
2. `.zwarm/config.toml`
3. `config.toml` in working directory

### Minimal Config

```toml
[weave]
enabled = true
project = "your-entity/zwarm"

[executor]
adapter = "codex_mcp"
model = "gpt-5.1-codex-mini"
```

### Full Config Reference

```toml
[orchestrator]
lm = "gpt-5-mini"
max_steps = 100

[orchestrator.compaction]
enabled = true
max_tokens = 100000
threshold_pct = 0.85
target_pct = 0.7

[executor]
adapter = "codex_mcp"
model = "gpt-5.1-codex-mini"
sandbox = "workspace-write"
timeout = 300

[weave]
enabled = true
project = "your-entity/zwarm"

[watchers]
enabled = true
watchers = [
    { name = "progress" },
    { name = "budget", config = { max_steps = 50, max_sessions = 10 } },
    { name = "delegation_reminder", config = { threshold = 10 } },
]
```

---

## Session Management

Sessions are the core abstraction. Each session is a conversation with a Codex agent.

### Lifecycle

```
spawn → running → completed/failed
                      ↓
              continue → running → completed
                              ↓
                        continue → ...
```

### Storage

```
.zwarm/sessions/<uuid>/
├── meta.json           # Status, task, model, messages, tokens
└── turns/
    ├── turn_1.jsonl    # Raw codex output for turn 1
    ├── turn_2.jsonl    # Output after first continue
    └── ...
```

### Sync vs Async

| Mode | Spawn | Continue | Use case |
|------|-------|----------|----------|
| **Sync** | `spawn "task"` | `c id "msg"` | Sequential work, immediate feedback |
| **Async** | `spawn --async "task"` | `ca id "msg"` | Parallel work, batch processing |

Async sessions return immediately. Poll with `ls` or `?` to check status.

---

## Watchers

Watchers monitor agent behavior and intervene when needed.

| Watcher | Purpose |
|---------|---------|
| `progress` | Detects stuck/spinning agents |
| `budget` | Enforces step/session limits |
| `scope` | Detects scope creep |
| `delegation_reminder` | Nudges orchestrator to delegate |

Configure in `config.toml`:

```toml
[watchers]
enabled = true
watchers = [
    { name = "progress" },
    { name = "budget", config = { max_steps = 50 } },
]
```

---

## CLI Reference

```bash
zwarm init              # Initialize .zwarm/ in current directory
zwarm interactive       # Start interactive REPL
zwarm orchestrate       # Start LLM orchestrator
zwarm exec              # Run single executor directly (testing)
zwarm status            # Show current state
zwarm history           # Show event history
zwarm clean             # Remove old sessions
```

---

## Project Structure

```
zwarm/
├── src/zwarm/
│   ├── sessions/           # Session management (core)
│   │   ├── manager.py      # CodexSessionManager
│   │   └── __init__.py
│   ├── tools/
│   │   └── delegation.py   # Orchestrator tools (delegate, converse, etc.)
│   ├── cli/
│   │   └── main.py         # CLI commands and interactive REPL
│   ├── core/
│   │   ├── config.py       # Configuration loading
│   │   ├── compact.py      # Context window management
│   │   └── state.py        # State persistence
│   ├── watchers/           # Trajectory alignment
│   └── orchestrator.py     # Orchestrator agent
├── docs/
│   └── INTERNALS.md        # Technical architecture
└── README.md
```
