ai-dispatch 10.44.0

Multi-AI CLI team orchestrator
# ai-dispatch (aid)

## Install

- NEVER cp binary to `/opt/homebrew/bin/` — macOS provenance xattr blocks execution
- `/opt/homebrew/bin/aid` is a symlink to `~/.cargo/bin/aid`
- Install command (MUST re-sign after copy — sandbox provenance blocks execution):
  ```bash
  cp "$CARGO_TARGET_DIR/release/aid" ~/.cargo/bin/aid && codesign --force --sign - ~/.cargo/bin/aid
  ```

## Release

Release must go through `scripts/release.sh`. Do not manually bump `Cargo.toml`, edit the top release entry in `CHANGELOG.md`, create the release commit, create the release tag, or push the release branch/tag by hand.

Tests and their compilation run on the build box through `rbox`, never on this Mac
(boss rule 2026-09-11). Set `AID_RELEASE_TEST_CMD='scripts/remote-test.sh'` for releases;
project verify is `scripts/remote-test.sh -- --bin aid`. AID starts verify outside the
agent sandbox, inheriting the operator's `AID_BUILD_BOX`, `RBOX_CONFIG`, and `PATH` with rbox.

```bash
export AID_BUILD_BOX='<configured rbox name>'   # never commit the name
export AID_RELEASE_TEST_CMD='scripts/remote-test.sh'
```

The wrapper uses one `rbox exec` and runs the full workspace suite as the configured
non-root user, with no test skips. Checkouts live at `~/.rbox/work/<repo-name>/<checkout-id>`:
the Git common directory supplies the repo name, and the branch (short HEAD SHA when
detached) is sanitized to letters, digits, `_`, and `-`. All worktrees share
`$HOME/.rbox/target/<repo-name>`. Rbox owns sync, transport, streaming, and the box lock.
Use `--jobs N` (default 4, or `AID_BUILD_JOBS`), `--timeout S` (5400),
`--lock-timeout S` (3600), `-- <extra cargo test args>`, or `--dry-run` to print the command.
Exit 124 means the wait timed out and the job continues; 75 means the box lock was not
acquired. Diagnostics name the job ID when assigned (sync lock failure has no job yet).
Completed test exits retain their status and are identified by rbox's completion marker.
If the agent sandbox cannot reach Tailscale, stop at dry-run/fake-rbox checks; the
operator runs the live release-test path. Never fall back to local compilation.

Release flow requirements:
- Start from a clean git worktree. Commit or stash local edits before running the release script.
- Prepare a Markdown notes file with one `- ` bullet per shipped change.
- Run `scripts/release.sh --dry-run <version> <notes-file>` first and review the planned commit/tag/push.
- Run `scripts/release.sh <version> <notes-file>` for the actual release.
- Treat any direct `git tag`, manual version bump, or manual changelog-only release edit as an invalid release flow.
- Clean up before releasing. The script's orphan hygiene check only *warns* on `--dry-run` but **fails the real release** if a branch already merged into `main` still exists. Delete merged branches, `aid accept` then `aid gc --task <id>` any task still holding worktree custody, and `git worktree prune`.

```bash
cat > /tmp/aid-release-notes.md <<'EOF'
- Short release summary
- Additional shipped change
EOF

scripts/release.sh --dry-run 8.75.0 /tmp/aid-release-notes.md
scripts/release.sh 8.75.0 /tmp/aid-release-notes.md
```

## Official Guide Maintenance

`default-skills/aid-guide/` is the release-managed, authoritative AID operating
guide. Any change to a public command, flag, lifecycle transition, safety
invariant, configuration key, or recommended workflow must update the relevant
guide reference in the same commit. Keep `references/command-index.md`
complete. Run:

```bash
python3 ~/.codex/skills/.system/skill-creator/scripts/quick_validate.py \
  default-skills/aid-guide
scripts/remote-test.sh -- --test aid_guide_e2e --test init_e2e
```

## Run

Dispatch a task to an AI agent. Core command — most other features build on this.

```bash
aid run codex "Add unit tests" --verify              # with auto-verify
aid run gemini "Research topic" -o notes.md           # research with output file
aid run codex "Refactor" -w feat/refactor --bg        # background + worktree
aid advise "implement feature" --difficulty moderate --budget standard --urgency normal --rigor standard
```

Built-in run agents: `gemini`, `agy`, `qwen`, `codex`, `copilot`, `opencode`, `commandcode`, `cursor`, `kilo`, `mimocode`, `droid`, `oz`, `claude`, and `grok`. Use `aid advise` to compare agents; there is no `auto` agent.

`agy` (Antigravity CLI) is a drop-in successor to `gemini` for Google One / Gemini Code Assist (individuals) users. After June 18, 2026, gemini stops serving those tiers — switch to `agy`. Paying API users keep using `gemini`.

### Key flags

| Flag | Purpose |
|------|---------|
| `-w, --worktree <branch>` | Run in isolated git worktree |
| `--verify [<cmd>]` | Auto-verify on completion (default: project verify cmd) |
| `--judge [<agent>]` | AI judge evaluates output quality |
| `--peer-review <agent>` | Dispatch peer review after completion |
| `--cascade <agents>` | Comma-separated fallback agents on failure |
| `--context <file>...` | Inject files as context into the prompt |
| `--context-from <task-id>...` | Inject output from previous tasks as context |
| `--scope <path>...` | Restrict agent file access to specific paths |
| `--skill <name>...` | Inject methodology skills into the prompt |
| `--template <name>` | Wrap prompt with a template |
| `--on-done <cmd>` | Shell command to run on task completion |
| `--hook <spec>...` | Hook specs for the dispatched task |
| `--bg` | Run in background (non-blocking) |
| `--sandbox` | Run agent in sandboxed mode |
| `--container <image>` | Run agent inside a container |
| `--best-of <N>` | Run N copies, pick best result |
| `--metric <cmd>` | Custom metric command for best-of selection |
| `--budget` | Use budget-optimized model |
| `--read-only` | Agent cannot modify files |
| `--idle-timeout <secs>` | Kill agent if idle for N seconds |
| `--retry <N>` | Auto-retry on failure (default: 0) |
| `-g, --group <wg-id>` | Assign to workgroup |

## Batch

Dispatch multiple tasks from a TOML file.

```bash
aid batch tasks.toml --parallel                     # parallel dispatch
aid batch tasks.toml --parallel --max-concurrent 3  # limit concurrency
aid batch tasks.toml --analyze                      # warn about file overlaps
aid batch tasks.toml --wait                         # block until all complete
aid batch tasks.toml --var key=value                # template variables
aid batch init                                      # generate template TOML
aid batch retry --group wg-abc1                     # re-dispatch failed tasks
```

### Batch TOML format

```toml
[defaults]
dir = "."
agent = "codex"
team = "dev"
verify = "cargo check"
fallback = "cursor"
model = "o3"
context = ["src/types.rs"]
skills = ["implementer"]
worktree_prefix = "feat/my-feature"    # auto-generates worktree per task
analyze = true                          # warn about overlapping file edits
max_duration_mins = 30                  # hard timeout in minutes for batch tasks

[[task]]
name = "parser"                         # REQUIRED if sharing worktree with other tasks
prompt = "Implement parser"
worktree = "feat/my-feature/parser"
depends_on = ["types"]                  # wait for named task to complete
fallback = "oz,opencode"
on_success = "tests"                    # trigger conditional task on success
on_fail = "cleanup"                     # trigger conditional task on failure
conditional = true                      # only runs when triggered by on_success/on_fail
idle_timeout = 120
```

- `context`, `skills`, `scope` accept both string and array: `context = "file.md"` or `context = ["a.md", "b.md"]`
- `fallback` supports comma-separated agents: `fallback = "oz,opencode,codex"`
- `worktree_prefix` auto-generates `{prefix}/{task-name}` (or `{prefix}/task-{index}` for unnamed tasks)
- Batch hard timeout uses `max_duration_mins`; the old `timeout` key is rejected with a rename hint

## Watch & Board

```bash
aid watch t-1234                         # live TUI for one task
aid watch --wait t-1234                  # block until done (for scripts)
aid watch --wait --group wg-abc1         # block until group finishes
aid watch --tui                          # full dashboard TUI
aid watch --exit-on-await t-1234         # exit when task awaits input
aid watch --timeout 600 t-1234           # timeout after 10 minutes
aid board                                # recent tasks (default: 50)
aid board --running                      # only active tasks
aid board --today                        # today's tasks
aid board --group wg-abc1                # tasks in workgroup
aid board -l 10                          # limit to 10 tasks
aid board --stream                       # live-updating stream
aid board --json                         # machine-readable JSON
```

## Task Lifecycle

```bash
aid retry t-1234 -f "Fix the compilation error in parser.rs"
aid retry t-1234 -f "Use HashMap instead" --agent opencode   # switch agent
aid retry t-1234 -f "try again" --model gpt-5.4              # same agent, different model
aid retry t-1234 -f "try again" --idle-timeout 900           # longer idle leash
aid retry t-1234 -F feedback.md                              # feedback from file
aid retry t-1234 -f "Start fresh" --reset                    # reset worktree
aid stop t-1234                          # graceful stop
aid stop t-1234 --force                  # force kill
aid steer t-1234 "Focus on the error handling, skip the logging changes"
aid respond t-1234 "Yes, use the async version"
aid respond t-1234 -F response.md        # respond with file contents
```

## Show

`aid show <task-id>` auto-detects task type and adjusts output:

- **Code tasks**: events + diff stat (default), `--diff` for full diff
- **Research tasks** (no worktree/changes): events + **Findings** section with agent conclusions

```bash
aid show <task-id>                   # smart default: diff stat OR findings
aid show <task-id> --events          # events only
aid show <task-id> --diff            # full diff (code tasks)
aid show <task-id> --output          # agent messages (truncated)
aid show <task-id> --output --full   # complete untruncated output
aid show <task-id> --log --full      # complete raw log
aid show <task-id> --summary         # one-line status + conclusion
aid show <task-id> --context         # original + resolved prompt
aid show <task-id> --explain         # AI-generated explanation of changes
aid show <task-id> --json            # machine-readable JSON
```

## Merge

```bash
aid merge <task-id>                      # merge into current branch
aid merge <task-id> --target release     # merge into specific branch
aid merge --group <wg-id>                # merge all tasks in group
aid merge --group <wg-id> --check        # dry-run conflict check
aid merge --group <wg-id> --lanes        # apply each branch as a GitButler lane
```

## GitButler Integration (optional)

`aid` can integrate with [GitButler](https://gitbutler.com) (CLI: `but`) to add
per-task auto-commit, oplog/undo, and a single-workspace "lane" view for whole
batches. Integration is strictly opt-in and gated by the
`[project] gitbutler` field in `.aid/project.toml`; `auto` mode also requires
the `but` binary on `PATH`.

Enable during `aid project init` — if `but` is detected, you'll be prompted
to set `gitbutler = "auto"`. Modes:

| Mode | Behavior |
|---|---|
| `off` (default) | No GitButler integration |
| `auto` | Active when `but` is on `PATH`; silent no-op otherwise |
| `always` | Skips the PATH probe and attempts GitButler commands; downstream commands warn or fail if `but` is missing |

What gets activated per dispatched task (when active):
- `but setup` runs inside the task's worktree (idempotent).
- Claude Code agents get `.claude/settings.local.json` with `PreToolUse`,
  `PostToolUse`, `Stop` hooks calling `but claude pre-tool|post-tool|stop`  this auto-attributes edits to the task's virtual branch and auto-commits
  on session end.
- Non-Claude agents get an `on-done` shell hook running `but -C <wt> commit -i`
  at task end — same outcome, different mechanism.
- Escape hatch: `AID_GITBUTLER=0` disables all GitButler integration for one invocation — both dispatch hooks and `aid merge --lanes`.

Post-batch lane assembly: `aid merge --group <wg> --lanes` uses `but apply`
to apply each task's branch as a lane in the main repo's GitButler workspace
instead of sequentially `git merge`-ing them. Review the whole batch with
`but status`, then push selectively. Worktrees remain in custody until the
principal runs `aid accept <task>` and `aid gc --task <task>`.

## Workgroups

```bash
aid group create --name "v9 release"           # create workgroup
aid group list                                  # list workgroups
aid group show wg-abc1                          # show group + member tasks
aid group update wg-abc1 --name "v9.1 release" # rename
aid group summary wg-abc1                       # milestones, findings, costs
aid group finding wg-abc1 "Key discovery"       # post a finding
aid group broadcast wg-abc1 "Update: ..."       # message all group members
aid group delete wg-abc1                        # delete group definition
```

## Worktree Management

```bash
aid worktree create feat/my-feature      # create worktree
aid worktree list                        # list aid-managed worktrees
aid accept t-1234                        # principal accepts delivered artifacts
aid gc --task t-1234                     # delete after recursive durability proof
```

Context files specified via `--context` are automatically synced into worktrees if they don't exist there (e.g., files created by earlier batch waves).

### Worktree Safety Rules

- **Shared worktree naming**: When 2+ batch tasks share the same worktree, ALL must have `name = "..."` so aid can auto-sequence access via `depends_on`. Unnamed tasks sharing a worktree will be rejected at validation time.
- **Lock mechanism**: Each worktree gets an `.aid-lock` file during task execution. If another task tries to use a locked worktree, it fails with a clear error. Stale locks (dead PID) are auto-cleared.
- **Failure preservation**: When a task fails in a shared worktree, the worktree is preserved if sibling tasks are still active.
- **`worktree_prefix`**: Auto-generates unique worktree paths per task (`{prefix}/{name}` or `{prefix}/task-{idx}`). Preferred over manually assigning the same worktree to multiple tasks.

## Utilities

```bash
aid ask "What is the latest Rust edition?"               # one-shot question
aid query "key insight" -g wg-abc1 --finding             # search task history
aid tree t-1234                          # show task tree (parent + children)
aid output t-1234                        # raw agent output (--full for complete)
aid export t-1234                        # export as markdown (default)
aid export t-1234 --format json -o out.json  # export as JSON
aid build check                          # compact cargo check/clippy diagnostics
aid test --bin aid                       # trusted tests (zero-match is an error)
aid test --bin aid my_test -- --exact    # filter; lists which tests ran
aid test -- my_filter                    # same as cargo; zero-match still fails
aid test --isolated --bin aid            # temp AID_HOME for the cargo test process
aid memory add discovery "fact"          # store agent memory
aid memory list | search "keyword"       # recall memories
aid tool list | show <name> | add <name> | test <name>   # manage tools
aid container build | list | stop        # manage containers
aid experiment run experiment.toml       # automated experiment loops
aid clean                                # remove tasks older than 7 days
aid clean --older-than 30 --worktrees    # custom retention + prune worktrees
aid upgrade                              # upgrade aid to latest version
aid stats                                # agent performance (--window today/30d)
aid config agents | pricing | skills | templates         # configuration
aid config clear-limit codex             # clear rate-limit marker
```

Audit and review prompts now default to an audit-report flow: `aid run codex "Cross-audit ..."` auto-writes `result.md`, asks the agent for a Markdown report, and makes `aid show --output` / TUI / web prefer the saved report over raw logs.

## Teams

Teams provide **knowledge context and soft agent preferences** — not hard restrictions. All agents remain available; `--team` boosts preferred agents in `aid advise` scoring and injects team knowledge into prompts.

```toml
[team]
id = "dev"
display_name = "Development Team"
preferred_agents = ["codex", "opencode", "cursor"]  # soft boost, not hard filter
default_agent = "codex"
rules = ["Do NOT run cargo fmt or any auto-formatter"]

[team.overrides.opencode]
simple_edit = 10
```

Knowledge: `~/.aid/teams/<id>/KNOWLEDGE.md` — auto-injected into prompts with `--team`.

```bash
aid team list | show <name> | create <name> | delete <name>
```

## Agent Config

Per-agent default model stored in `~/.aid/agent_config.toml`. CLI `--model` flag overrides.

```bash
aid agent config cursor --model composer-2   # set default model
aid agent config codex --model gpt-5.4       # set codex default
```

## Project Profiles

Per-repo configuration via `.aid/project.toml`. Profiles expand into defaults for verify, budget, and rules.

| Profile | Verify | Budget | Rules |
|---------|--------|--------|-------|
| `hobby` | - | $5/day, prefer_budget | - |
| `standard` | `auto` | $20/day | Tests for new functions |
| `production` | `cargo test`/`npm test` | $50/day | Tests, no unwrap(), cross-review |

CLI: `aid project init`, `aid project show`, `aid project sync`. Project defaults are fallbacks — CLI flags always win.

## MCP & Hooks

```bash
aid mcp                                  # start MCP server mode
aid hook session-start                   # print session-start hook text
```

<!-- aid:start -->
## aid orchestration

This project uses [aid](https://github.com/agent-tools-org/ai-dispatch) as the primary development method.
Use `aid run` to dispatch coding tasks to AI agents instead of writing code directly.

- **Project**: ai-dispatch
- **Profile**: production
- **Language**: rust
- **Budget**: $50
- **Verify**: scripts/remote-test.sh -- --bin aid
- **Team**: dev

### Rules
- File size limit: 300 lines per file
- Never use features = ["full"] for dependencies
- All public functions must have tests
- All changes must have tests
- No unwrap() in production code
- Changes require cross-review

### Usage
- Dispatch work: `aid run <agent> "<prompt>" --dir .`
- Review output: `aid show <id> --diff`
- Batch dispatch: `aid batch <file> --parallel`
- Project config: `.aid/project.toml`

<!-- aid:end -->

## Test Layout Rule

One convention (audit 2026-07, issue #164): tests are **inline** (`#[cfg(test)] mod tests`) while the file stays ≤300 lines; otherwise a **sibling `<name>_tests.rs`** included via `#[path]`. Cross-binary integration tests live in `tests/`. Do not introduce new `*_tests/` subdirectories.