---
slug: "bacchus"
source_type: "readme"
source_url: "https://cdn.jsdelivr.net/gh/vu1n/bacchus@main/README.md"
repo: "https://github.com/vu1n/bacchus"
source_file: "README.md"
branch: "main"
---
# Bacchus

Workspace-based coordination CLI for multi-agent work on codebases using [jj (Jujutsu)](https://martinvonz.github.io/jj/).

Bacchus helps AI agents coordinate when working on the same codebase by:
- **Workspace isolation** - each agent works in its own jj workspace
- **Task management** - SQLite-based task tracking with dependencies and footprints
- **Session management** - stop hooks keep agents working until tasks complete
- **Orchestrator-driven release** - agents mark work ready, orchestrator handles merging
- **Non-blocking conflicts** - jj allows conflict detection without blocking work

## Installation

### 1. Install the binary

```bash
curl -fsSL https://raw.githubusercontent.com/vu1n/bacchus/main/scripts/install.sh | bash
```

This installs the `bacchus` binary to `~/.local/bin/` and cleans up any legacy global hooks/skills from previous versions.

### 2. Initialize per project

```bash
cd your-project
bacchus init
```

This sets up everything project-local:
- `.bacchus/` - task database, workspaces, archetypes
- `.claude/settings.json` - project-level stop hook
- `.claude/skills/bacchus/SKILL.md` - Claude Code skill (teaches Claude how to use bacchus)

### Prerequisites

- [jj (Jujutsu)](https://martinvonz.github.io/jj/latest/install/) v0.20+
- git (jj uses git backend)

### From Source

```bash
git clone https://github.com/vu1n/bacchus.git
cd bacchus
cargo build --release
cp target/release/bacchus ~/.local/bin/
```

### Uninstall

```bash
curl -fsSL https://raw.githubusercontent.com/vu1n/bacchus/main/scripts/uninstall.sh | bash
```

## How It Works

Bacchus coordinates multi-agent work through a **plan → orchestrate → execute** flow:

```
┌─────────────────────────────────────────────────────────────────────┐
│  1. PLAN                                                            │
│     User request → planner/architect workflow                       │
│     Breaks down work into tasks with dependencies                   │
│     Outputs: .bacchus/tasks.yaml                                    │
├─────────────────────────────────────────────────────────────────────┤
│  2. IMPORT                                                          │
│     bacchus task import --epic-id <EPIC>                           │
│     Loads tasks from YAML into SQLite                               │
│     Calculates ready tasks (no blockers, no footprint conflicts)   │
├─────────────────────────────────────────────────────────────────────┤
│  3. ORCHESTRATE                                                     │
│     session start orchestrator + session spawn-workers              │
│     Monitors progress, handles merges, manages conflicts            │
├─────────────────────────────────────────────────────────────────────┤
│  4. EXECUTE                                                         │
│     Each agent: claim → work in jj workspace → release             │
│     Orchestrator: rebase → merge to main → close task              │
└─────────────────────────────────────────────────────────────────────┘
```

## Swarm Methodology

Bacchus runs a deterministic swarm loop:

1. **Plan** - break goal into atomic tasks with dependencies and footprints
2. **Admit** - only tasks that are dependency-clear and non-overlapping become `ready`
3. **Execute** - workers claim one task each in isolated jj workspaces
4. **Reconcile** - orchestrator merges ready work, reopens failed/stale work, resolves conflicts via `needs_resolution`
5. **Measure** - `bacchus eval` reports throughput plus worker-reliability signals

Swarm safety comes from hard invariants:

- **Single-task ownership** via task claims (`claimed_by`, heartbeat)
- **Leader fencing** via orchestrator lease (one orchestrator run controls scheduling)
- **Workspace isolation** (one jj workspace per task)
- **Failure recovery** (stale worker detection, task reopen, optional stale PID kill)

### How to Run

Ralph mode is the default recommendation (permissioned, auditable runs):

```bash
claude
```

Yolo mode is optional for trusted local repos:

```bash
claude --dangerously-skip-permissions
```

In both modes, keep `bacchus` stop hooks enabled so sessions enforce task completion and orchestration safety.

### How to Prompt Claude

Tell Claude what you want and mention bacchus:

```
"I want to add user authentication with login, logout, and password reset.
Use bacchus to parallelize this work across multiple agents."
```

With the bacchus skill workflow, Claude can plan tasks, import them, and orchestrate agents with archetype prompts.
Autonomous worker spawning requires `BACCHUS_WORKER_CMD` (see Session Management).

| What you want | What to say |
|---------------|-------------|
| Full automation | "Use bacchus to implement X with N agents" |
| Plan only | "Break down X into tasks for bacchus" |
| Single task | "Work on task TASK-001 with bacchus" |
| Check status | "Show bacchus status" |

**Key roles:**
- **Planner**: Breaks down requests into atomic tasks with dependencies
- **Orchestrator**: Spawns agents, monitors progress, handles merges
- **Agent**: Works on a single task in an isolated workspace (with type-specific archetype)

## Agentic Quick Start (Paste Into Your LLM)

Copy/paste this and replace `<GOAL>`:

```text
Use bacchus to implement: <GOAL>

Operating mode:
- Use Ralph mode by default (no --dangerously-skip-permissions).
- Keep sessions active; do not exit while bacchus session check blocks.

Execution contract:
1) Ensure jj is initialized for this repo (colocated with git if needed).
2) Create/update an epic and task plan in .bacchus/tasks.yaml (atomic tasks, dependencies, footprints, archetypes).
3) Import tasks into SQLite and verify ready queue.
4) Start orchestrator session with max concurrency 3.
5) Use bacchus session spawn-workers --dry-run first, then launch workers.
6) Continuously process releases and recover stale/failed workers.
7) Finish when all tasks are closed or explicitly blocked, then summarize outcomes and risks.

Required commands to use:
- bacchus task import --epic-id <EPIC>
- bacchus task list --ready
- bacchus session start orchestrator --max-concurrent 3
- bacchus session spawn-workers --count 3
- bacchus process-releases
- bacchus eval --days 7
```

## Quickstart Guide

This guide walks through setting up Bacchus for a multi-agent workflow.

### Step 0: Fast Initialization Check

```bash
cd your-project

# One-shot bootstrap (recommended)
bacchus init --epic-id AUTH --epic-title "Authentication"

# Initialize jj once (if repo is git-only today)
if ! jj root >/dev/null 2>&1; then
  jj git init --colocate
  jj config set --repo user.name "Your Name"
  jj config set --repo user.email "you@example.com"
  jj bookmark create main -r @
  jj describe -m "Initialize jj for bacchus"
  jj new
fi
```

`bacchus init` is idempotent: it creates `.bacchus/tasks.yaml` if missing, bootstraps jj unless `--skip-jj`, and can create an initial epic.

### Step 1: Initialize Your Repository

Bacchus uses jj (Jujutsu) for version control. If your project uses git, initialize jj in colocated mode:

```bash
cd your-project
jj git init --colocate

# Set up user config for jj
jj config set --repo user.name "Your Name"
jj config set --repo user.email "you@example.com"

# Create main bookmark (like a branch)
jj bookmark create main -r @
jj describe -m "Initial commit"
jj new
```

### Step 2: Plan Your Tasks

You can create tasks manually or ask Claude to help plan:

**Option A: Ask Claude to plan (recommended for complex work)**
```
"Break down user authentication into tasks for bacchus"
```
Claude will analyze your request and create tasks with proper dependencies.

**Option B: Create tasks manually**

```bash
bacchus task init
```

**Option C: Generate recursively with Bun (experimental)**

```bash
bun scripts/recursive-planner.ts \
  --goal "Implement user authentication with login, logout, and password reset" \
  --epic-id AUTH \
  --llm-provider claude \
  --task-granularity small \
  --import \
  --validate
```

The recursive planner writes `.bacchus/tasks.yaml`, can split broad tasks into smaller subtasks, and can optionally run `task import` + `task validate`.
When your prompt is goal-only (no PRD/spec), it generates explicit spec + scaffolding + architecture tasks before implementation slices.
Use `--llm-provider codex` to decompose with Codex headless, `--llm-provider openai` for API mode, or `--llm-provider off` for heuristic-only planning.
Use `--task-granularity small` to force finer agent-sized tasks.

Edit `.bacchus/tasks.yaml`:

```yaml
version: 1

tasks:
  - id: AUTH-001
    title: "Add user login endpoint"
    description: |
      Create POST /api/login that:
      - Validates credentials
      - Returns JWT token
      - Handles errors appropriately
    priority: 1
    status: open
    depends_on: []
    footprint:
      creates:
        - "src/routes/login.rs"
      modifies:
        - "src/routes/mod.rs::*"

  - id: AUTH-002
    title: "Add authentication middleware"
    description: "Protect routes with JWT validation"
    priority: 2
    status: open
    depends_on: [AUTH-001]  # Must complete login first
    footprint:
      creates:
        - "src/middleware/auth.rs"

  - id: AUTH-003
    title: "Add logout endpoint"
    description: "POST /api/logout to invalidate tokens"
    priority: 2
    status: open
    depends_on: [AUTH-001]  # Can run parallel with AUTH-002
    footprint:
      creates:
        - "src/routes/logout.rs"
```

Import tasks to SQLite:

```bash
bacchus task import --epic-id AUTH

# Verify import
bacchus task list
bacchus task list --ready  # Shows AUTH-001 (others blocked)
```

### Step 3: Work on a Task (Agent Mode)

Claim your first task:

```bash
bacchus claim AUTH-001 agent-1
```

Output:
```json
{
  "success": true,
  "task_id": "AUTH-001",
  "title": "Add user login endpoint",
  "workspace_path": ".bacchus/workspaces/AUTH-001"
}
```

Work in the isolated workspace:

```bash
# Check workspace status
jj -R .bacchus/workspaces/AUTH-001 status

# Make your changes (files are auto-tracked by jj)
# Create src/routes/login.rs, etc.

# Describe your change (like a commit message)
jj -R .bacchus/workspaces/AUTH-001 describe -m "Implement login endpoint with JWT"

# View what you've done
jj -R .bacchus/workspaces/AUTH-001 log
jj -R .bacchus/workspaces/AUTH-001 diff
```

> **Warning**: Never `cd` into the workspace! Use `jj -R <path>` instead. Workspaces are deleted on release.

### Step 4: Release Your Work

When done, mark the task ready for release:

```bash
bacchus release AUTH-001 --status done
```

Output:
```json
{
  "success": true,
  "task_id": "AUTH-001",
  "status": "ready_for_release",
  "commit_id": "abc123...",
  "message": "Task AUTH-001 marked ready for release. Orchestrator will merge."
}
```

Check what's now available:

```bash
bacchus task list --ready
# Now shows AUTH-002 and AUTH-003 (AUTH-001 unblocked them)
```

### Step 5: Handle Conflicts (If Needed)

If the orchestrator detects conflicts during merge:

```bash
# Task will be marked needs_resolution
bacchus task show AUTH-001

# Resolve conflicts in your workspace
jj -R .bacchus/workspaces/AUTH-001 resolve

# Mark resolved and ready again
bacchus resolve AUTH-001
```

### Common Scenarios

**Abandoning work:**
```bash
# Discard changes and reset task to open
bacchus release AUTH-001 --status failed
```

**Blocked on something:**
```bash
# Keep workspace but mark task blocked
bacchus release AUTH-001 --status blocked
```

**Finding stale work:**
```bash
# List claims older than 30 minutes
bacchus stale --minutes 30

# Clean them up automatically
bacchus stale --minutes 30 --cleanup
```

**Full workflow with Claude:**
```
# Tell Claude what you want:
"Implement user authentication with bacchus using 3 agents"

# Claude will:
# 1. Plan: break down into tasks.yaml
# 2. Import: bacchus task import --epic-id AUTH
# 3. Orchestrate: spawn agents and monitor progress
```

**Manual orchestration:**
```bash
# After planning and importing, start orchestrator session
bacchus session start orchestrator --max-concurrent 3
# Optional: enable autonomous worker spawning from orchestrator checks
export BACCHUS_WORKER_CMD='claude'
# Spawn workers on demand
bacchus session spawn-workers --count 3
# Then run `bacchus session check` in your stop-hook loop
```

### Worker Runners (Claude or Codex)

The worker is just a shell command (`worker.cmd`) that bacchus runs per task with
env vars injected (`$BACCHUS_AGENT_ID`, `$BACCHUS_TASK_ID`, …) — it is not tied to
Claude. The `worker.runner` config field selects the default command:

| Runner | Default `worker.cmd` |
|--------|----------------------|
| `claude` (default) | `claude --dangerously-skip-permissions -p '/bacchus-worker $BACCHUS_AGENT_ID $BACCHUS_TASK_ID'` |
| `codex` | `codex exec --dangerously-bypass-approvals-and-sandbox "$(bacchus worker-prompt $BACCHUS_AGENT_ID $BACCHUS_TASK_ID)"` |

Pick one at init time:

```bash
bacchus init --runner codex     # writes a codex worker.cmd into .bacchus/config.yaml
```

Claude resolves the `/bacchus-worker` slash command from the installed skill. Codex
has no slash command, so `codex exec` is fed the protocol as plain text via
`bacchus worker-prompt <AGENT_ID> [TASK_ID]` (the same protocol, runner-agnostic).
Set `worker.runner: codex` (and leave `cmd` unset) to derive the codex command, or
set `cmd` explicitly to override. Liveness is bacchus-owned (the heartbeat loop),
not a Claude hook, so codex workers stay alive the same way.

The review loop calls the `/tighten` and `/ship-review` skills — install these for
your runner (both ship as Claude **and** Codex skills; bacchus bundles copies under
`skills/`). `codex exec` requires the [Codex CLI](https://grok-wiki.com/public/docs/openai-codex-c82680b15ec1)
on `PATH`.

## Commands

### Task Management

| Command | Description |
|---------|-------------|
| `task init` | Create tasks.yaml template |
| `task list [--status X] [--ready]` | List tasks |
| `task show <task_id>` | Show task details |
| `task import [--epic-id X]` | Import tasks from YAML to SQLite |
| `task validate` | Validate task definitions |

### Coordination

| Command | Description |
|---------|-------------|
| `init [--skip-jj] [--force-tasks] [--epic-id X --epic-title Y]` | Bootstrap bacchus in the current repo (jj + tasks template + optional epic) |
| `next <agent_id>` | Get next ready task, create workspace, claim it |
| `claim <task_id> <agent_id> [--force]` | Claim specific task (must be ready unless --force) |
| `heartbeat <task_id> <agent_id>` | Refresh task claim lease heartbeat |
| `release <task_id> --status done\|blocked\|failed` | Mark task ready for release |
| `process-releases [--limit N]` | Orchestrator: merge tasks in `ready_for_release` |
| `stale [--minutes N] [--cleanup]` | Find/cleanup abandoned claims |
| `list` | List all active claims |
| `resolve <task_id>` | Mark task ready after resolving conflicts |
| `abort <task_id>` | Reset from needs_resolution to in_progress |

### Review & Eval

| Command | Description |
|---------|-------------|
| `review <task_id> [--build-cmd X] [--test-cmd Y]` | Review task before release (includes symbol-aware footprint checks) |
| `eval [--epic X] [--days N]` | Show completion metrics plus worker reliability counters (timeouts, stale recovery, kill attempts/successes) |

### Session Management

| Command | Description |
|---------|-------------|
| `session start agent --task-id <id> [--agent-id <agent>]` | Start agent session (enables stop hook and background heartbeat when owner known) |
| `session start orchestrator [--max-concurrent N]` | Start orchestrator session |
| `session start architect --agent-id <id>` | Start architect session |
| `session stop` | Clear session, allow exit |
| `session status` | Show current session state |
| `session check` | Check if exit should be blocked (for hooks) |
| `session spawn-workers [--count N] [--dry-run]` | Launch ready workers once for active orchestrator session |
| `session prune [--minutes N]` | Remove stale scoped sessions and orphaned expired leases |

### Epic Management

| Command | Description |
|---------|-------------|
| `epic list [--status X]` | List epics (open, planning, active, closed) |
| `epic show <epic_id>` | Show epic details with task counts |
| `epic create --id X --title Y [--description Z]` | Create a new epic |
| `epic assign <epic_id> <agent_id>` | Assign epic to architect for breakdown |
| `epic set-status <epic_id> <status>` | Update epic status (open/planning/active/closed) |

### Archetype Management

| Command | Description |
|---------|-------------|
| `archetype list` | List available agent archetypes |
| `archetype show <name>` | Show archetype details and keywords |
| `archetype prompt <name>` | Get the specialized prompt for an archetype |
| `archetype select <task_id>` | Select best archetype for a task |

### Messaging

| Command | Description |
|---------|-------------|
| `message list [--agent X] [--status Y]` | List agent messages |
| `message send <agent> <type> <payload>` | Send message to agent |
| `message claim <agent> [--limit N]` | Claim pending messages for processing |
| `message ack <message_id> <agent>` | Mark claimed message as processed |
| `message fail <message_id> <agent> [--reason X]` | Mark claimed message as failed |
| `message reclaim-stale` | Requeue/fail stale processing messages |

### Symbols

| Command | Description |
|---------|-------------|
| `index <path>` | Index files for symbol search |
| `symbols [--pattern X] [--kind Y]` | Search for symbols |
| `symbols [--file X] [--lang Y]` | Filter by file path or language |
| `symbols [--search X] [--fuzzy]` | Full-text search with fuzzy matching |
| `symbols --handle` | Return handle instead of full results (token-saving) |

### Handles (Token-Saving)

Handles provide compact pointers to query results, reducing token overhead by 90%+.

| Command | Description |
|---------|-------------|
| `handle expand <handle> [-n N] [--offset M]` | Retrieve data from handle with pagination |
| `handle filter <handle> [--kind X] [--file Y]` | Filter handle creating new handle |
| `handle list` | List all active handles |
| `handle clear` | Clear all handles |
| `handle info <handle>` | Get metadata about a handle |

**Example workflow:**
```bash
# Search returns a handle instead of full data
$ bacchus symbols --search "auth" --handle
{
  "handle": "$sym1",
  "count": 47,
  "preview": ["auth::login", "auth::logout", "auth::verify"]
}

# Expand to get actual data (on demand)
$ bacchus handle expand $sym1 --limit 5

# Filter to narrow results
$ bacchus handle filter $sym1 --kind function
# Returns: $sym2 with 32 functions

# Clean up when done
$ bacchus handle clear
```

Handles are session-scoped and automatically cleared on `bacchus session stop`.

### Info

| Command | Description |
|---------|-------------|
| `status` | Show claims, orphaned workspaces, broken claims |
| `context [--task-id X]` | Generate markdown context for agent |
| `workflow` | Print protocol documentation |
| `events [--limit N]` | Show recent orchestration events |
| `self-update` | Update bacchus to latest version |
| `check-update` | Check if newer version is available |

## Claude Code Integration

Bacchus integrates with Claude Code through a skill and stop hooks:

### Skill

The bacchus skill (`~/.claude/skills/bacchus/SKILL.md`) provides:
- Workflow guidance for planning, importing, and orchestrating tasks
- Agent archetype prompts for specialized task execution
- Command reference for the bacchus CLI

The skill is automatically loaded when you mention "bacchus" or multi-agent coordination.

### Stop Hooks

Stop hooks in `~/.claude/settings.json` prevent premature exit:
- **Agent mode**: Blocks exit until assigned task is closed
- **Orchestrator mode**: Blocks exit while work remains

### Type vs Archetype

Tasks have two separate classifications:

**Task Type** (PM workflow - what kind of work):
`bug_fix` | `feature` | `refactor` | `test` | `docs` | `infra` | `generic`

**Archetype** (Agent specialization - what expertise):

Default archetypes for reference:
| Archetype | Focus |
|-----------|-------|
| `frontend` | UI/UX, components, styling |
| `backend` | APIs, auth, validation |
| `data` | Pipelines, SQL, schemas |
| `test` | Coverage, fixtures, e2e |
| `infra` | CI/CD, containers, cloud |
| `review` | Quality, patterns |
| `security` | Vulnerabilities, OWASP |
| `generic` | General development |

Archetypes are explicitly set by the planner. Bacchus uses `archetypes.yaml` as the source of truth - customize by copying to `.bacchus/archetypes.yaml` in your project.

## Workflow

```
claim/next → work in workspace → release (mark ready) → orchestrator merges
```

### 1. Get Work

```bash
# Option A: Next ready task
bacchus next agent-1

# Option B: Specific task
bacchus claim TASK-42 agent-1
```

Output:
```json
{
  "success": true,
  "task_id": "TASK-42",
  "title": "Implement auth",
  "workspace_path": ".bacchus/workspaces/TASK-42"
}
```

### 2. Do Work

Work in the jj workspace. Changes are auto-snapshotted - no explicit add/commit needed.

> **Warning**: Never `cd` into a workspace. Use `jj -R` instead - workspaces are ephemeral and get deleted on release.

```bash
# Check status
jj -R .bacchus/workspaces/TASK-42 status

# Describe your change (like a commit message)
jj -R .bacchus/workspaces/TASK-42 describe -m "Implement auth"

# View your changes
jj -R .bacchus/workspaces/TASK-42 diff
```

### 3. Release

```bash
# Success - mark ready for release (orchestrator will merge)
bacchus release TASK-42 --status done

# Blocked - keep workspace, mark task blocked
bacchus release TASK-42 --status blocked

# Failed - discard workspace, reset task to open
bacchus release TASK-42 --status failed
```

### 4. Orchestrator Merges (Automatic)

When you mark a task ready, the orchestrator:
1. Rebases your commit onto current main
2. If conflicts: marks task `needs_resolution` (you fix with `jj resolve`)
3. If clean: advances main bookmark and closes task

Manual trigger (outside orchestrator stop-hook loops):
```bash
bacchus process-releases
```

## Session Management

Sessions enable stop hooks that prevent premature exit:

```bash
# Start agent session (blocks until task closed; pass agent id for immediate heartbeat loop)
bacchus session start agent --task-id TASK-42 --agent-id agent-1

# Start orchestrator session (blocks while work remains)
bacchus session start orchestrator --max-concurrent 3

# Launch ready workers once (optional manual trigger)
bacchus session spawn-workers --count 3

# Check session state
bacchus session status

# Clear session to exit
bacchus session stop

# Cleanup stale scoped session files
bacchus session prune --minutes 240
```

Session state is scoped per CLI/session identity in `.bacchus/sessions/<scope>.json`.
Set `BACCHUS_SESSION_ID` explicitly when running multiple concurrent sessions from the same repo root.
Only one orchestrator can hold the leader lease at a time; secondary orchestrator starts are rejected.

Autonomous worker spawning controls:
- `BACCHUS_ORCHESTRATOR_AUTO_SPAWN=1` (default) enables auto-spawn attempts during `session check`.
- `BACCHUS_WORKER_CMD` sets the worker shell command (required for auto-spawn); overrides `worker.runner`/`worker.cmd`. See Worker Runners for the Claude vs Codex defaults.
- `BACCHUS_WORKER_MAX_RETRIES` limits retries per task (default: `3`).
- `BACCHUS_WORKER_RETRY_BACKOFF_MS` sets retry backoff (default: `60000`).
- `BACCHUS_WORKER_STALE_GRACE_MS` extends stale-worker recovery grace beyond claim timeout (default: `60000`).
- `BACCHUS_WORKER_MAX_RUNTIME_MS` optionally fails/reopens long-running workers after this runtime (default: disabled).
- `BACCHUS_WORKER_KILL_STALE=1` enables best-effort PID termination before failing/reopening stale workers (default: `0`).
Use `bacchus session spawn-workers --dry-run` to preview ready candidates and slot usage without launching workers.
When a worker is stale (task heartbeat expired), orchestrator recovers it by marking worker failed and reopening the task.

## Stale Detection

Find and cleanup abandoned claims:

```bash
# List stale claims (>30 min old)
bacchus stale --minutes 30

# Auto-cleanup
bacchus stale --minutes 30 --cleanup
```

## Task Definition

Tasks are defined in YAML and imported to SQLite:

```yaml
# .bacchus/tasks.yaml
version: 1

tasks:
  - id: AUTH-001
    title: "Implement user authentication"
    description: "Add JWT-based auth"
    type: feature              # PM workflow: bug_fix | feature | refactor | test | docs | infra | generic
    archetype: backend         # Agent expertise: frontend | backend | data | test | infra | review | security | generic
    priority: 1
    status: open
    depends_on: []
    footprint:
      modifies:
        - "src/auth/handler.rs::AuthHandler"
      creates:
        - "src/auth/middleware.rs"

  - id: API-002
    title: "Add rate limiting"
    type: feature
    archetype: backend
    priority: 2
    depends_on: [AUTH-001]
    footprint:
      modifies: ["src/middleware/mod.rs::*"]

  - id: AUTH-001-SEC
    title: "Security review of auth"
    type: feature              # The review is a feature task
    archetype: security        # But needs security expertise
    priority: 3
    depends_on: [AUTH-001]
```

Import with: `bacchus task import --epic-id MY-EPIC`

## Directory Structure

```
project/
├── .jj/                    # jj repository data
├── .bacchus/
│   ├── bacchus.db          # SQLite database (tasks, claims, metrics)
│   ├── tasks.yaml          # Task definitions (import source)
│   ├── sessions/           # Scoped session state files
│   │   ├── default.json
│   │   └── <scope>.json
│   └── workspaces/
│       ├── TASK-42/        # Agent 1's jj workspace
│       └── TASK-43/        # Agent 2's jj workspace
```

## Stop Hook Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                    ORCHESTRATOR MODE                         │
│  Spawns agents for ready tasks                              │
│  Blocks while: ready tasks exist OR agents active           │
│  Approves when: all work done or blocked                    │
├─────────────────────────────────────────────────────────────┤
│   ┌─────────┐   ┌─────────┐   ┌─────────┐                  │
│   │ Agent 1 │   │ Agent 2 │   │ Agent 3 │                  │
│   │ TASK-A  │   │ TASK-B  │   │ TASK-C  │                  │
│   └─────────┘   └─────────┘   └─────────┘                  │
│                                                              │
│  AGENT MODE                                                  │
│  Blocks while: assigned task not closed                     │
│  Approves when: task status == "closed"                     │
└─────────────────────────────────────────────────────────────┘
```

## Supported Languages (Symbol Indexing)

- TypeScript / JavaScript
- Python
- Go
- Rust

## License

MIT
