git-paw 0.1.0

Parallel AI Worktrees — orchestrate multiple AI coding CLI sessions across git worktrees
Documentation
# CLAUDE.md — git-paw

## Project Overview

**git-paw** (Parallel AI Worktrees) is a Rust CLI tool that orchestrates multiple AI coding CLI sessions across git worktrees from a single terminal using tmux.

Repository: `bearicorn/git-paw`
Crate: `git-paw`
Binary: `git-paw` (invokable as `git paw` via git subcommand convention)

## Command Set

```
git paw                        # Smart start (default)
git paw start                  # Same — reattach / recover / launch new
git paw start --cli claude     # Skip CLI picker
git paw start --cli claude --branches feat/a,feat/b  # Fully non-interactive
git paw start --dry-run        # Preview without executing
git paw start --preset backend # Use config preset
git paw stop                   # Kill tmux, keep worktrees + state for later
git paw purge                  # Nuclear: kill tmux, remove worktrees, delete state
git paw purge --force          # Skip confirmation
git paw status                 # Show session state for current repo
git paw list-clis              # Show detected + custom CLIs
git paw add-cli <name> <cmd>   # Register a custom CLI globally
git paw remove-cli <name>      # Unregister a custom CLI
```

One session per repo. `start` is smart — it reattaches if active, recovers if stopped/crashed, or launches new if nothing exists.

## Architecture

```
src/
├── main.rs           # Entry point, wires modules together
├── cli.rs            # Clap derive structs and subcommands
├── detect.rs         # AI CLI detection (scans PATH + custom CLIs)
├── git.rs            # Git operations (branches, worktrees)
├── tmux.rs           # Tmux session/pane orchestration
├── session.rs        # Session state persistence (~/.local/share/git-paw/)
├── config.rs         # .git-paw/config.toml and global config parsing
├── interactive.rs    # Dialoguer prompts (branch picker, CLI picker)
└── error.rs          # PawError enum (thiserror)
```

## Development Commands

Prefer using `just` recipes — they mirror what CI runs:

```bash
just check                     # fmt + clippy + test (run this before pushing)
just test                      # Run all tests
just test-all                  # Include tmux-dependent ignored tests
just coverage                  # Generate HTML coverage report
just lint                      # cargo fmt --check + cargo clippy
just deny                      # cargo deny check (licenses, advisories, duplicates)
just audit                     # cargo audit (vulnerability scan)
just docs                      # Build mdBook and open
just api-docs                  # Build and open Rustdoc
just changelog                 # Regenerate CHANGELOG.md with git-cliff
just build                     # cargo build --release
just install                   # cargo install from local source
just clean                     # cargo clean
```

Raw cargo commands:

```bash
cargo build                    # Build
cargo test                     # Run all tests
cargo test -- --ignored        # Run tmux-dependent tests
cargo clippy -- -D warnings    # Lint (must pass with zero warnings)
cargo fmt --check              # Format check (must pass)
cargo run -- --help            # Run locally
cargo llvm-cov --html          # Generate coverage report
cargo doc --no-deps --open     # Build and open API docs
git cliff -o CHANGELOG.md      # Regenerate changelog
```

## Conventions

### Code Style

- Use `cargo fmt` formatting (configured in `rustfmt.toml`)
- Clippy pedantic lints enabled (configured in `Cargo.toml` under `[lints.clippy]`)
- All public functions and types must have doc comments (`///`)
- All modules must have module-level doc comments (`//!`)
- No `unwrap()` or `expect()` in non-test code — propagate errors with `?`
- Use `PawError` variants from `error.rs` for all error cases
- Use `anyhow::Result` at the application boundary (`main.rs`, `cli.rs`)
- Use `thiserror` for library-level error types (`error.rs`)
- Prefer `std::process::Command` for calling external tools (git, tmux)

### Linting & Supply Chain

- **rustfmt** — code formatting, configured in `rustfmt.toml`. Run: `cargo fmt`
- **clippy** — linting with pedantic mode. Run: `cargo clippy -- -D warnings`
- **cargo deny** — license compliance, duplicate deps, advisory checks. Config: `deny.toml`. Run: `cargo deny check`
- **cargo audit** — vulnerability scanning. Run: `cargo audit`
- All four run in CI and must pass for PRs to merge

### Commit Conventions

This project follows **Conventional Commits** (Commitizen compatible).

Format: `<type>(<scope>): <description>`

Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `ci`, `chore`, `perf`
Scopes: `detect`, `git`, `tmux`, `session`, `config`, `interactive`, `error`, `cli`, `docs`, `ci`

Examples:
```
feat(detect): add CLI detection for aider and amp
fix(git): handle branch names with multiple slashes
test(session): add round-trip serialization test
docs(readme): add quick start section
ci: add coverage threshold check to CI pipeline
```

Breaking changes: add `!` after type/scope and `BREAKING CHANGE:` footer.
All commit messages must be lowercase descriptions (no period at end).

### CLI Help Text

Every subcommand needs `about` + `long_about` with examples.
Every flag/option needs a `help` string.
The root command has `after_help` with a quick-start guide.

### Testing

- Unit tests in `#[cfg(test)] mod tests {}` at bottom of each module
- Integration tests in `tests/` directory
- `tempfile` for filesystem-touching tests
- `assert_cmd` for CLI binary tests
- Tests requiring `tmux` marked `#[ignore]`
- All tests independent — no shared mutable state
- All tests should test behavior and not implementation

### Dependencies

Only add dependencies listed in the approved set:

| Crate | Purpose |
|-------|---------|
| `clap` v4 | CLI parsing with derive |
| `dialoguer` | Interactive terminal prompts |
| `console` | Terminal colors/styling |
| `which` | PATH binary detection |
| `thiserror` | Error derive macros |
| `anyhow` | Application error handling |
| `serde` + `serde_json` | Session state serialization |
| `toml` + `serde` | Config file parsing |
| `dirs` | Platform XDG directories |

Dev: `assert_cmd`, `predicates`, `tempfile`, `serial_test`

Do not add other dependencies without explicit approval.

## Spec-Driven Development

This project uses OpenSpec-style specifications. Each module has a spec in its GitHub issue.

Specs use RFC 2119 keywords: **SHALL/MUST** (mandatory), **SHOULD** (recommended), **MAY** (optional).
Requirements include GIVEN/WHEN/THEN scenarios. Each scenario maps to at least one test.

## Parallel Development Rules

**CRITICAL: Only modify files listed in your issue's "Files Owned" section.**

Do not modify files owned by another branch. If you need a type from another module, use the stub on `main` and add `// TODO: wire up after merge`.

### Branch → File Ownership

**Wave 1: Core Implementation**

| Branch | Owned Files |
|--------|-------------|
| `feat/detect` | `src/detect.rs` |
| `feat/git-ops` | `src/git.rs` |
| `feat/tmux` | `src/tmux.rs` |
| `feat/session-state` | `src/session.rs` |
| `feat/config` | `src/config.rs` |
| `feat/interactive` | `src/interactive.rs` |
| `feat/errors` | `src/error.rs` |

**Wave 2: Testing, CI, Docs, Polish**

| Branch | Owned Files |
|--------|-------------|
| `feat/wire-up` | `src/main.rs`, `src/cli.rs` |
| `feat/unit-tests` | `#[cfg(test)]` blocks in `src/*.rs`, `tests/helpers/` |
| `feat/integration-tests` | `tests/*.rs` |
| `feat/ci` | `.github/workflows/`, `.github/dependabot.yml`, `deny.toml` |
| `feat/openspec` | `openspec/` |
| `feat/docs-site` | `docs/` |
| `feat/readme` | `README.md`, `CONTRIBUTING.md`, `CHANGELOG.md`, etc. |

### Merge Order

**Wave 1:** `feat/errors` first → all others in any order
**Wave 2:** `feat/wire-up` first → tests → openspec/docs/readme → CI last

## External Tool Interaction

### Git
- Call via `std::process::Command::new("git")`
- Always capture stderr for error messages
- Parse stdout for branch lists, worktree info

### Tmux
- Call via `std::process::Command::new("tmux")`
- Builder pattern: accumulate ops, execute or return as strings (for testing/dry-run)
- Session names: `paw-<project-name>`
- **Critical: apply `tiled` layout before each new split**, not just at the end. Without this, tmux runs out of space after ~5 panes even on large terminals.
- Apply final `tiled` layout after all panes for clean alignment.
- Enable `mouse on` per-session (not globally) so users can click panes and drag borders.
- Set pane titles to `<branch> → <cli>` via `select-pane -T` so users can identify panes at a glance.
- Enable `pane-border-status top` and `pane-border-format " #{pane_title} "` per-session to display titles.

## Testing Conventions

### Unit Tests
- In `#[cfg(test)] mod tests {}` at bottom of each module
- Every OpenSpec scenario maps to at least one test
- `tempfile` for filesystem tests
- No system side effects

### Integration Tests
- In `tests/` directory
- `assert_cmd` for CLI binary tests
- `predicates` for output assertions
- Tmux-dependent tests marked `#[ignore]`
- Shared helpers in `tests/helpers/mod.rs`

### Coverage
- Tool: `cargo-llvm-cov`
- Local: `cargo llvm-cov --html``target/llvm-cov/html/`
- CI uploads LCOV to Codecov
- Target: >= 80% line coverage

## Documentation

### Four Layers
1. `--help` text — comprehensive with examples
2. README.md — landing page with badges, quick starts, CLI table
3. mdBook site — full user guide at `https://bearicorn.github.io/git-paw/`
4. `cargo doc` / Rustdoc — API docs for contributors

All layers must be consistent.

### mdBook
- Source: `docs/src/`, Config: `docs/book.toml`
- OpenSpec specs embedded via `{{#include}}` — single source of truth
- Two quick start tutorials: same-CLI mode and per-branch CLI mode

### OpenSpec
- Specs in `openspec/specs/<capability>/spec.md`
- RFC 2119 keywords, GIVEN/WHEN/THEN scenarios with `Test:` annotations
- Included in mdBook docs site

### Changelog
- [Keep a Changelog]https://keepachangelog.com/ format
- Generated from Conventional Commits using `git-cliff`
- Config: `cliff.toml`
- Generate: `git cliff -o CHANGELOG.md`
- CI auto-generates on tag push

## Platform Support

- **macOS** (ARM + x86) — fully supported
- **Linux** (x86_64 + ARM64) — fully supported
- **Windows** — WSL only. Native Windows is not supported (tmux is Unix-only).

## Release & Distribution

Handled by `cargo-dist`. Config: `[workspace.metadata.dist]` in Cargo.toml.

- **Trigger:** push tag `v*`
- **Automatic:** cross-platform binaries, checksums, shell installer, Homebrew formula
- **Workflow:** `.github/workflows/release.yml` (generated by cargo-dist)
- **Homebrew tap:** `bearicorn/homebrew-tap`

Install methods:
```bash
cargo install git-paw
brew install bearicorn/tap/git-paw
curl --proto '=https' --tlsv1.2 -LsSf \
  https://github.com/bearicorn/git-paw/releases/latest/download/git-paw-installer.sh | sh
```

## Project Metadata

- License: MIT
- MSRV: current stable
- Targets: macOS (ARM + x86), Linux (x86_64 + ARM64), Windows (WSL)

## Commits

Commits should not include any reference to claude. It should also be one clean linear commit. The commit should also resolve the issue that you are working on.