# Design Decisions

This document explains the reasoning behind Legionnaire's key design choices.

## Why Stateless?

### The Problem

State management introduces complexity:
- State files can become stale
- Syncing state across tools is error-prone
- Recovery from partial failures is difficult

### Our Approach

Legionnaire uses existing systems as the source of truth:
- Git tracks worktrees and branches
- tmux tracks sessions and windows
- PID files track agent processes

### Benefits

- **Robustness**: Partial failures leave discoverable state
- **Simplicity**: No manifest to corrupt
- **Idempotency**: Re-running `init` repairs inconsistencies

## Why Two Layers?

### The Problem

Parallel LLM work needs:
- Isolation (separate working directories)
- Coordination (shared base point)
- Organization (grouped terminal windows)

### Our Approach

The parent/child model maps naturally to:

| Concept | Git | tmux |
|---------|-----|------|
| Group | Branch prefix | Session |
| Integration point | Parent worktree | Parent window |
| Work item | Child worktree | Child window |

### Trade-offs

**Chosen**: Simple two-level hierarchy

**Rejected alternatives**:
- Flat structure: Loses grouping benefits
- Deep nesting: Adds complexity without clear benefit
- DAG: Overkill for the use case

## Why Deterministic Colors?

### The Problem

Multiple sessions with many windows become hard to navigate visually.

### Our Approach

Colors are assigned based on lexicographic position:
- Consistent across sessions with same children
- Parent always red (attention-grabbing)
- Children cycle through a gradient

### Benefits

- **Recognition**: Same child name = same color
- **Orientation**: Visual cues for navigation
- **Aesthetics**: Pleasing gradient effect

## Why libtmux?

### The Problem

Shelling out to `tmux` commands is fragile:
- Output parsing is brittle
- Error handling is inconsistent
- Session/window references are awkward

### Our Approach

libtmux provides:
- Pythonic objects for sessions, windows, panes
- Consistent error handling
- Server-level commands when needed

### Trade-offs

**Chosen**: libtmux dependency

**Benefits**:
- Cleaner code
- Better error messages
- Easier testing

**Costs**:
- Additional dependency
- API changes between versions

## Why Git Worktrees?

### The Problem

Parallel work needs isolated directories, but:
- Cloning is slow and wastes space
- Manual branch switching loses context
- Stashing is error-prone

### Our Approach

Git worktrees provide:
- Shared `.git` directory (fast, space-efficient)
- Separate working directories (isolation)
- Native git integration (familiar tooling)

### Benefits

- **Speed**: Creating a worktree is instant
- **Space**: Single object store
- **Familiarity**: Standard git commands work

## Why Only Claude and Cursor?

### The Problem

Supporting many agents increases complexity:
- Different launch commands
- Different behaviors
- Different configuration needs

### Our Approach

Start with the two most common LLM CLIs:
- Claude: Anthropic's official CLI
- Cursor: Popular AI editor

### Future Considerations

The agent system is designed for extension:
- `AgentType` enum for new agents
- `launch_command()` generates agent-specific commands
- Simple pattern to add more

## Why exec in Agent Launch?

### The Problem

When tracking PIDs, the process tree matters:

```
bash -c 'echo $$; claude'
```

Records bash's PID, not claude's.

### Our Approach

Using `exec` replaces the shell:

```
bash -lc 'echo $$ > file; exec claude'
```

The recorded PID is claude's actual PID.

### Why It Matters

- Correct process for status checks
- Correct process for signal delivery
- Clean process tree

## Why Slugify IDs?

### The Problem

Users type natural names:
- "perf logging" (with space)
- "schema v2" (with space)

But git refs and paths need:
- No spaces
- Valid characters only

### Our Approach

Minimal transformation:
- Replace whitespace with dashes
- Preserve slashes for hierarchy
- Strict validation for safety

### Why Not More Aggressive?

We preserve case and most characters because:
- User intent is clearer
- IDs are more readable
- Less surprising behavior
