Skip to main content

bouquet logo

bouquet

CI

Warning — Alpha Software Bouquet is under active development. APIs, config format, and CLI behavior may change without notice. Use at your own risk.

An orchestration layer for multi-agent coding — multiplexing coding agents across git worktrees with isolated services, all in one tmux session.

cd my-project
bouquet start              # TUI launches, create worktrees, agents spin up

Key Features

Feature Details
🌿 Git worktree isolation Each feature branch gets its own worktree, venv, and node_modules — no cross-contamination
🖥️ Multi-pane services Run API servers, workers, frontends alongside the agent with automatic port offsetting per worktree
🤖 Agent orchestration TUI in tmux window 0 to create, switch, and manage worktree-backed agent windows
📋 Task queue Define a backlog of tasks that get automatically delegated to worktrees — agents pick up work without manual intervention
🔧 Rich configuration Expressive .bouquet.toml with template expressions ({{ 8000 + BOUQUET_WORKTREE_INDEX }}), per-worktree variables, agent profiles, and multi-service layouts
⚡ Fast bootstrap CoW-clones .venv/node_modules (APFS), copies .env files, runs uv sync/pnpm install
🔌 Agent-agnostic Named profiles let you mix Claude, Aider, Codex, or any CLI agent — even different agents per worktree

Requirements

  • Python 3.14+
  • tmux (brew install tmux)
  • GitHub CLI (optional, brew install gh — enables PR links in TUI and GitHub Issues task backend)
  • direnv (optional, brew install direnv)
  • Language package managers as needed (uv, pnpm)

Installation

# Run without installing
uvx pybouquet --help

# Or install via pip
pip install pybouquet

# Or from source (development)
git clone https://github.com/promptromp/bouquet.git
cd bouquet
uv sync

Quick Start

1. Initialize

cd /path/to/your/repo
bouquet init

Creates a .bouquet.toml template. Edit it to configure your project.

2. Start a session

bouquet start

This will:

  1. Create a tmux session (bouquet-<project-name>)
  2. Launch the orchestrator TUI in window 0
  3. Adopt any existing git worktrees
  4. Attach you to the session

You can also pass arguments explicitly:

bouquet start my-project --repo /path/to/repo --config /path/to/.bouquet.toml

3. Use the TUI

Key Action
N Create a new worktree (opens branch dialog with optional agent profile selector)
S / Enter Switch to the selected worktree's window
D Delete the selected worktree and its window
a Toggle auto-accept for selected worktree (auto-sends "y" at permission prompts)
A Toggle autopilot mode (auto-schedules tasks by dependency order)
P Send a prompt to selected or all agent terminal(s) via tmux send-keys
T Request a status summary from all agents (captures responses)
C Create a new task in the task queue
X Pick up the highlighted task (creates worktree and sends task to agent)
M Complete the highlighted task (optionally remove the associated worktree)
Backspace Delete the highlighted task from the queue
R Refresh the worktree list and task queue
Q Quit (with confirmation — kills the session)

When you create a worktree, bouquet will:

  • Create a git worktree with a new branch
  • Bootstrap the environment (copy .env files, CoW-clone .venv/node_modules)
  • Open a new tmux window with service panes (if configured)
  • Launch the agent (e.g. claude) in pane 0

Switch back to the orchestrator: Ctrl-b 0.

4. Stop

bouquet stop

Cleans up all managed worktrees, resets any in-progress tasks back to open, kills the tmux session, and removes state.


Services

Run dev servers alongside the agent in each worktree window. Define them in .bouquet.toml:

[[services]]
name = "api"
command = "uv run uvicorn app.main:app --reload --port {{ 8000 + BOUQUET_WORKTREE_INDEX }}"

[[services]]
name = "frontend"
command = "npm run dev -- --port {{ 3000 + BOUQUET_WORKTREE_INDEX }}"

[tmux]
layout = "main-vertical"

Each worktree gets a unique index (1, 2, 3, ...) so services bind to different ports automatically.

Template Variables

Variable Type Example
BOUQUET_WORKTREE_INDEX int 1, 2, 3
BOUQUET_WORKTREE_BRANCH str feature/auth
BOUQUET_WORKTREE_PATH str /path/to/.bouquet-worktrees/feature-auth
BOUQUET_PROJECT_NAME str my-project

Arithmetic supported: {{ 8000 + BOUQUET_WORKTREE_INDEX }} → 8001.

The same template variables are also available in [bootstrap] setup_commands, post_deps_commands, and teardown_commands — both as {{ … }} placeholders and as plain shell env vars ($BOUQUET_WORKTREE_INDEX, etc.) — so setup/teardown scripts can provision and reclaim per-worktree resources (databases, queues, …) without external coordination.

No services defined = single pane with just the agent (backward compatible).

Bootstrap hooks: setup_commands vs post_deps_commands vs teardown_commands

The three [bootstrap] hook lists run at different points in the worktree lifecycle:

Hook When On failure Typical use
setup_commands Before python_deps_command / node_deps_command Loud — raises SetupCommandsError, worktree → ERROR private-registry auth (CodeArtifact tokens), provisioning per-worktree DBs / queues
post_deps_commands After deps install, before direnv_allow (so .venv / node_modules exist) Loud — same as setup_commands uv run migrate upgrade head, asset compilation, anything that needs the project's tooling
teardown_commands Before tmux window kill + git worktree removal (so the on-disk checkout is still reachable) Best-effort — failures logged, cleanup proceeds reclaiming external per-worktree resources at remove time (drop DBs, delete queues)

setup_commands and post_deps_commands also have env-capture: any export FOO=bar lines in the user's commands are captured and propagated into both subsequent install commands and the tmux session, so service panes inherit them.

See docs/configuration.md for the full reference.


Agent Profiles

Named agent configurations so you can switch between Claude, Aider, Codex, etc. per worktree:

[agent]
command = "claude"
default_profile = "claude"

[[agent.profiles]]
name = "claude"
command = "claude"

[[agent.profiles]]
name = "aider"
command = "aider"
args = ["--model", "claude-sonnet-4-20250514"]

When profiles are defined, the TUI's new-worktree dialog shows a profile selector. If no profiles are defined, the top-level command/args are used (backward compatible).


Activity Detection

Bouquet polls each agent's tmux pane every 2 seconds to infer real-time status:

Status Meaning
● running (green) Agent output is actively changing
◆ waiting (yellow) Agent output stopped and a permission prompt was detected
○ idle (dim) Agent output hasn't changed for several polls

This replaces the static "active" status with live feedback. The TUI table updates automatically.


Task Queue

Define a backlog of tasks that agents pick up automatically. Two backends are supported:

Local (SQLite) — default

Tasks are stored in ~/.local/state/bouquet/<project>.tasks.db. No external dependencies.

[task_queue]
backend = "local"
auto_branch_prefix = "task/"

GitHub Issues

Uses your repo's GitHub Issues as the task source. Requires gh CLI authenticated.

[task_queue]
backend = "github"
label_filter = "bouquet"     # only issues with this label appear as tasks
auto_branch_prefix = "task/"

Status mapping: OPEN = open issue, IN_PROGRESS = open issue + in-progress label, DONE = closed issue.

Task workflow

  1. Create (c) — opens a dialog to create a task with an optional parent dependency
  2. Pick up (x) — creates a worktree from the task, marks it in-progress, and sends the task description to the agent
  3. Complete (m) — marks the task as done, optionally removes the associated worktree
  4. Reconciliation — on startup, tasks stuck as in-progress (from a crash or quit) are automatically reset to open if their worktree no longer exists

Task Dependencies

Tasks can declare a parent dependency, forming a DAG. A task with an unsatisfied dependency shows as blocked in the queue and cannot be picked up until its parent is done. Cycles are rejected at creation time.

Autopilot

Press A to toggle autopilot mode. When active, bouquet automatically:

  • Picks up tasks whose dependencies are satisfied (or have none)
  • Runs up to max_autopilot_concurrency tasks in parallel (default 3)
  • Enables auto-accept on all autopilot-created worktrees
  • Auto-completes tasks when their agent goes idle (~10 seconds)
  • Cascades: completing a parent unblocks its children for the next scheduling cycle
[task_queue]
max_autopilot_concurrency = 3    # max parallel worktrees
autopilot_auto_complete = true   # auto-complete IDLE tasks

Pane Layout

With layout = "main-vertical" and two services:

┌──────────────────┬────────────┐
│                  │   api      │
│   agent (claude) ├────────────┤
│                  │  frontend  │
└──────────────────┴────────────┘

Logs & Troubleshooting

Bouquet writes a rotating log file to ~/.local/state/bouquet/<project>.log (5 MB × 3 backups). bouquet start prints the path to stderr on launch.

When a worktree creation fails — most often because a setup_commands or post_deps_commands step exited non-zero — the TUI shows a terse toast (Error creating worktree: …) but the captured stdout and stderr from your bash commands land in the log file, along with the phase name (setup_commands vs post_deps_commands), cwd, and exit code. Tail it to debug:

tail -f ~/.local/state/bouquet/<project>.log

The SetupCommandsError raised on failure includes the log file path in its message, so the toast will point you there directly.

teardown_commands failures are best-effort and don't block worktree removal — they log a WARNING-level line in the same log file, so check there if a worktree was removed but external resources weren't reclaimed.

Pass --log-level=DEBUG to bouquet start for more verbose output (e.g. each rendered setup_commands / post_deps_commands / teardown_commands line):

bouquet start --log-level=DEBUG

Architecture

The Conceptual Stack
┌─────────────────────────────────────────┐
│         Orchestration Layer             │  ← TUI, agent coordination, task queue
├─────────────────────────────────────────┤
│         Session / Mux Layer             │  ← tmux sessions, windows, panes
├─────────────────────────────────────────┤
│         Isolation Layer                 │  ← git worktrees + env isolation
├─────────────────────────────────────────┤
│         Environment Layer               │  ← venv/node_modules/env vars
└─────────────────────────────────────────┘

Bouquet draws inspiration from and complements several tools in the multi-agent coding space:

  • claude-squad — A Go-based TUI for managing multiple Claude Code instances in parallel. Claude-squad focuses on running agents side-by-side with a clean terminal UI. Bouquet goes further with declarative multi-service layouts (API servers, frontends, workers per worktree), a rich template-based configuration language with per-worktree variable expansion, and a task queue for automatic work delegation across agents.

  • ruflo — A Rust-based agentic workflow orchestrator with a focus on DAG-based task execution and CI/CD integration. Ruflo takes a pipeline-oriented approach to agent coordination, while bouquet is designed around the developer's local workflow — git worktrees, tmux sessions, and interactive TUI management with live activity detection.

  • Claude Code Agent Teams — Anthropic's experimental built-in feature for coordinating multiple Claude Code agents. Agent Teams operates within the Claude Code runtime itself. Bouquet is agent-agnostic (works with Claude, Aider, Codex, or any CLI tool), provides full control over environment isolation, service orchestration, and configuration through .bouquet.toml.

Metadata

Release files for pybouquet 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pybouquet 0.6.1
File Size Uploaded Provenance
pybouquet-0.6.1.tar.gz 579.7 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pybouquet 0.6.1
File Interpreter ABI Platform
pybouquet-0.6.1-py3-none-any.whl Python 3 none any Details

Total release size: 638.6 kB

Release files / pybouquet-0.6.1.tar.gz

Download URL pybouquet-0.6.1.tar.gz
Size 579.7 kB
Tags Source
SHA-256 checksum
How to use checksums
f16c77fda742e1993af0732acc3f594677ab6c523847558497f3e8379d09b660
BLAKE2b-256 checksum
How to use checksums
4b5e5153538fa5c6068f19ee1b6e54b80849203dca61407604ceb2fa28b069b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 1, 2026.

Transparency log

Release files / pybouquet-0.6.1-py3-none-any.whl

Download URL pybouquet-0.6.1-py3-none-any.whl
Size 58.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
be296cc701ccd7fb6f802305f4c3a7ee817e8a5668cf113a1272658005b6ea40
BLAKE2b-256 checksum
How to use checksums
0e97bdede4e386f33e4dd678b23c7824331b41aafdbeba73d97d69958293dc82
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 1, 2026.

Transparency log

Security for pybouquet 0.6.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pybouquet-0.6.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 1, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page