---
title: Multi-project
description: Run AO against several repos from one dashboard, with per-project plugins and configs.
---

import { Callout } from "fumadocs-ui/components/callout";

One `agent-orchestrator.yaml` can drive many projects. Each project gets its own repo, tracker, plugin overrides, and — most importantly — its own dashboard lane.

## Config shape

```yaml title="agent-orchestrator.yaml"
runtime: tmux # global default
agent: claude-code

projects:
  web:
    repo: ComposioHQ/agent-orchestrator
    agent: claude-code

  api:
    repo: myorg/api
    agent: codex # per-project override
    tracker: linear
    trackerConfig:
      teamId: TEAM-123

  marketing:
    repo: myorg/site
    agent: cursor
    workspace: clone # full clone instead of worktree
```

Project IDs (`web`, `api`, `marketing`) are what you pass to `--project` / `-p`.

## Adding a project

Two ways:

- **By path**: `ao start ~/code/new-repo` — AO infers a project ID from the directory name and appends it.
- **By URL**: `ao start https://github.com/owner/repo` — AO clones it under `~/.agent-orchestrator/` and registers it.

Both update `agent-orchestrator.yaml` in place. Diff it if you're curious.

## Spawning in the right project

`ao spawn` auto-detects the project when you're in a worktree belonging to it. Otherwise name it:

```bash
ao spawn 42 -p api
ao batch-spawn 10 11 12 -p web
```

Or pass no project and AO will prompt.

## Per-project plugin overrides

Anything defined at the top level is a default. Override per project:

```yaml
tracker: github # default
notifier:
  - type: slack
    webhookUrl: ${SLACK_GLOBAL}

projects:
  internal:
    repo: myorg/internal
    tracker: linear
    notifier:
      - type: discord
        webhookUrl: ${DISCORD_INTERNAL}
```

The `internal` project uses Linear + Discord. Every other project uses GitHub + Slack.

## Status across projects

```bash
ao status                   # all projects
ao status -p api            # one project
ao status --json | jq       # scripted
ao status --watch           # live-updating table
```

The dashboard shows all projects as swim lanes.

## Stopping selectively

```bash
ao stop api          # stop one project's orchestrator + dashboard
ao stop --all        # stop everything
```

<Callout type="info">
	Each project can have a different agent, tracker, notifier, and workspace — that's the whole point of the plugin
	system. Don't force uniformity; let teams use what fits.
</Callout>
