Role-aware agent team launcher built on top of AMQ by Aviv Sinai.
AMQ owns messaging between agents. amq-squad owns the layer above: who is in
the team, what role each agent plays, and how to bring the whole squad back up
after a restart.
AMQ's coop exec is a generic launcher. It sets up a mailbox and execs into claude or codex, but it doesn't know:
- Which agent is the "CPO" vs "CTO" vs "Fullstack" vs "QA" vs "PM" vs "Designer"
- What command you originally used to launch each one (cwd, binary, flags, workstream)
- What slash commands or skills that role leans on
- Which peers a given agent actively talks to
amq-squad captures this at team-setup time (.amq-squad/team.json) and
per-agent at launch time (launch.json + role.md inside the AMQ mailbox).
AMQ itself stays unchanged.
go install github.com/omriariav/amq-squad/cmd/amq-squad@v0.6.1Use @latest if you intentionally want the newest published tag.
Requires Go 1.25+ and the amq binary in PATH (v0.34+). Installing to
$GOBIN (or $HOME/go/bin) is enough; the launch commands team show emits
use the absolute path to whichever amq-squad binary is running, so nothing
else needs to be on PATH.
cd ~/Code/my-project
amq-squad teamFirst run: pick personas from the squad market, then choose which CLI runs
each one. amq-squad writes .amq-squad/team.json, seeds
.amq-squad/team-rules.md, and prints launch commands. Later runs print the
same launch commands without asking again. If you are inside tmux, use
amq-squad team launch to open the squad automatically. Otherwise, paste one
command into each terminal pane or tab.
You do not need to run amq coop init for the normal single-project flow.
Generated launch commands put the team into one AMQ workstream session. By
default that workstream is the sanitized team-home directory name, and AMQ
creates the needed mailbox directories on first launch. Use amq coop init or
a hand-written .amqrc only when you want a custom root, explicit project name,
or cross-project peer routing.
Non-interactive setup:
amq-squad team init --personas cpo,cto,senior-dev,frontend-dev,mobile-dev,qa,pm,designerWith per-persona CLI overrides:
amq-squad team init \
--personas cto,junior-dev,qa \
--binary junior-dev=codex,qa=claudeMembers don't have to share a working directory. The dir where you run
team init becomes the team-home (where team.json and team-rules.md live);
individual members can live in other projects:
cd ~/Code/project-a
amq-squad team init \
--personas cpo,cto,fullstack,qa \
--cwd qa=~/Code/project-bteam show emits a cd <member-cwd> per command so every agent boots in the
right project. team sync walks each unique member cwd and syncs CLAUDE.md +
AGENTS.md in all of them.
Generated launch commands include these agent defaults:
- Claude:
--permission-mode auto - Codex: nothing by default (sandboxed). Pass
--trust trustedto prepend--dangerously-bypass-approvals-and-sandboxfor the local power-user path. The trust profile is persisted inteam.jsonfromteam initand re-emitted byteam show/team launch.
amq-squad launch --trust sandboxed|trusted controls the same boundary for
direct launches. Trust is Codex-specific; Claude defaults are unaffected.
Pass --no-default-args to skip all built-in defaults entirely.
--trust trusted and --no-default-args together are rejected, as is
sandboxed mode with --dangerously-bypass-approvals-and-sandbox smuggled
through --codex-args.
Pass a model name to either binary natively via --model:
amq-squad launch --model gpt-5 codex
amq-squad launch --model sonnet claudeteam init --model role=model,... persists per-member models in
team.json. team show --model role=model,... and team launch --model ...
override per run. Restore replays the persisted model.
Duplicate-launch guard: amq-squad launch refuses by default when a live
agent for the same handle/workstream is detected (live amq wake lock,
running agent PID with matching command, or fresh active presence). Stale
artifacts are cleaned up automatically. team launch preflights the entire
roster before any tmux command so a partial team never appears. Override
with --force-duplicate when you really want a second instance.
Add native Codex or Claude flags as binary args when the whole team should run with the same extra switches:
amq-squad team init \
--personas cto,fullstack \
--codex-args '--enable goals' \
--claude-args '--chrome'Those args are stored in .amq-squad/team.json, included in team show and
team launch, and treated as launch defaults so bootstrap and --conversation
continue to work. Use the same flags on team show or team launch for a
one-off run without changing team.json:
amq-squad team launch --codex-args '--enable goals' --claude-args '--chrome'If you are already working inside tmux, team launch opens the configured team
in the current tmux window:
amq-squad team launchDefaults:
--terminal tmux--target current-window--layout vertical--session <sanitized team-home directory name>--stagger 750ms
The current pane becomes the first agent pane. Additional team members are opened as vertical side-by-side panes, pane titles are set to role names, and agent launches are staggered to avoid flooding terminal control channels.
Preview the exact tmux script without creating panes:
amq-squad team launch --dry-runLaunch into an explicit AMQ workstream:
amq-squad team launch --session issue-96Use --fresh --session issue-96 when accidental reuse should fail if the
workstream already exists.
Explicit workstream names must be AMQ-safe: lowercase letters, digits, -, and
_. Release names such as v0.5.0 should be written as v0-5-0.
Alternative layouts:
amq-squad team launch --layout horizontal
amq-squad team launch --layout tiledTo create a separate detached tmux session instead:
amq-squad team launch --target new-session --terminal-session squad-issue-96
tmux attach -t squad-issue-96When iTerm2 tmux -CC control-mode clients are detected, amq-squad warns
about the known pause-after risk. If input stalls in iTerm2 cc-mode, recover
from a non-tmux shell:
tmux list-clients
tmux detach-client -t /dev/ttysXXXteam launch is wired as a small backend registry. The CLI handles shared
team loading, bootstrap flags, and common launch options, then dispatches to a
terminal backend by name. v0.5.0 ships the tmux backend.
Adding another terminal should be isolated to a new
internal/cli/team_launch_<name>.go file that implements teamLaunchBackend
and registers itself with registerTeamLaunchBackend from init.
Representative generated commands look like this (sandboxed Codex, the new default):
cd ~/Code/my-project && /path/to/amq-squad launch \
--role cto \
--session my-project \
--team-workstream \
--trust sandboxed \
--team-home /Users/you/Code/my-project \
--me cto \
codex
cd ~/Code/my-project && /path/to/amq-squad launch \
--role fullstack \
--session my-project \
--team-workstream \
--trust sandboxed \
--team-home /Users/you/Code/my-project \
--me fullstack \
claude -- --permission-mode autoRun amq-squad team init --trust trusted (or pick trusted in the
interactive prompt) for the local-power-user profile that includes
--dangerously-bypass-approvals-and-sandbox for Codex.
When a terminal closes, the machine reboots, or you upgrade Codex/Claude,
you do not need to remember whether to use team launch or restore. Run:
amq-squad team resumeThis inspects .amq-squad/team.json, local launch history, and live-agent
signals (wake locks, agent PIDs, presence) and prints a per-member plan
plus copy-pasteable commands. Per-member action labels:
live: a matching agent is still running; the command is suppressed by default. Pass--force-duplicateto launch a second instance anyway.restore: a launch record exists for the workstream; the emitted command replays it and preserves trust, model, conversation, role, handle, and binary args.launch fresh: no matching launch history; the emitted command is the same shapeteam launchwould use, with current team trust/model/binary args.blocked: ambiguous live state; choose--force-duplicateor narrow with--session.
Common flows:
# Default: resume the team's saved workstream, prefer restore.
amq-squad team resume
# Resume into an explicit session.
amq-squad team resume --session v0-6-0-review
# Refuse if no member has restorable history (catch a stale workstream pick).
amq-squad team resume --restore-existing
# Start a brand-new workstream from team.json (ignore restore records).
amq-squad team resume --fresh --session v0-6-1
# Force a second instance even when a live agent is detected.
amq-squad team resume --force-duplicateteam resume is plan-only. The existing power-user commands stay
available: team launch for tmux-pane launches from team intent, restore
for explicit launch-history replay, and list for inspection.
At launch time, each agent's bootstrap prompt includes a current team routing
block generated from .amq-squad/team.json. That block is the live routing
source of truth: role, handle, workstream, project, cwd, and the appropriate
amq send shape from the agent's current project. Sibling workstreams are
listed as metadata only; message bodies from old workstreams are not loaded
unless the user asks.
Think of personas as employees in a small internal market. The persona is the job you are hiring for; the CLI is the tool that employee runs on.
| ID | Label | Default binary | Profile |
|---|---|---|---|
cpo |
CPO | codex | Product direction, scope pressure, user value. |
cto |
CTO | codex | Architecture, tradeoffs, final technical review. |
senior-dev |
Senior Developer | codex | Takes harder code paths and reviews junior work. |
fullstack |
Fullstack Developer | claude | End-to-end feature builder across UI and backend. |
frontend-dev |
Frontend Developer | claude | Product UI, components, state, browser polish. |
backend-dev |
Backend Developer | codex | APIs, data flow, services, integrations. |
mobile-dev |
Mobile Developer | claude | Native and mobile app flows, device polish. |
junior-dev |
Junior Developer | codex | Fast on scoped tasks, needs review before merge. |
qa |
QA Manager | claude | Regression thinking, release risk, test coverage. |
pm |
Project Manager / Product Owner | claude | Keeps work ordered, unblocked, and shippable. |
designer |
Product Designer | claude | Product flows, visual shape, UI polish. |
Defaults are starting points. Override binaries per persona at team init time.
Choose a workstream for a run with --session on team show or team launch,
or store a shared default with team init --session <workstream>.
Launch-time overrides do not write back to .amq-squad/team.json.
team init --session is a single shared workstream name. The old
comma-separated role=name syntax is intentionally rejected; use one
workstream for the team run, then use threads for focused conversations.
Team-wide norms ("every change ships via a PR", "CTO approves before merge") live in a single file:
.amq-squad/team-rules.md
Claude reads CLAUDE.md, Codex reads AGENTS.md. Rather than maintaining
both by hand, you edit team-rules.md and amq-squad team sync pushes the
content into a managed block in both files. Everything outside the markers is
yours and stays untouched.
amq-squad team rules init Seed missing .amq-squad/team-rules.md with a stub
amq-squad team sync Preview what would change (exit 1 if drift)
amq-squad team sync --apply Write the managed block into CLAUDE.md and AGENTS.md
amq-squad team sync --apply --allow-outside
Also write member cwds outside team-home
On first --apply with an existing CLAUDE.md, your content is adopted as the
user region and the managed block is appended. Subsequent syncs only refresh
the managed block. Sync writes are guarded with same-directory temporary files,
atomic rename, and a stale-plan check. Member cwds outside the team-home
directory require --allow-outside so a hand-edited team.json cannot write
instructions into unrelated folders by surprise. Every configured cwd must
already exist before sync writes there.
Two agents in one repo: CTO on codex, Fullstack on claude.
cd ~/Code/my-project
amq-squad team init --personas cto,fullstackOpen .amq-squad/team-rules.md and refine the generated role scope, workflow,
approvals, and communication norms for your team. Then push the
managed block into the doc files each binary reads:
amq-squad team sync # preview (exit 1 if anything would change)
amq-squad team sync --apply # writes the managed block into CLAUDE.md and AGENTS.mdPrint the launch commands:
amq-squad teamYou'll get two commands, one per role. Open separate terminal panes or tabs and
paste one command per pane, or run amq-squad team launch from inside tmux to
create the panes automatically. Each agent boots through amq-squad launch,
which writes launch.json + a catalog-seeded role.md into the mailbox before
handing off to amq coop exec. From there both agents share one AMQ workstream
and use the canonical thread p2p/cto__fullstack for design escalations and
review handoffs.
One team, members in two repos: CTO and Fullstack in project-a, QA in
project-b. The team-home (team.json + team-rules.md) lives in
project-a.
Create AMQ project config in each project so cross-project peers have stable
project names. amq coop init is the easiest way to create the starter
.amqrc files:
(cd ~/Code/project-a && amq coop init)
(cd ~/Code/project-b && amq coop init)For cross-project messages to route, each project's .amqrc needs a peers
entry pointing at the other project's .agent-mail/. Edit
~/Code/project-a/.amqrc:
{
"root": ".agent-mail",
"project": "project-a",
"peers": {
"project-b": "/Users/you/Code/project-b/.agent-mail"
}
}Mirror it in ~/Code/project-b/.amqrc:
{
"root": ".agent-mail",
"project": "project-b",
"peers": {
"project-a": "/Users/you/Code/project-a/.agent-mail"
}
}This peers step is manual today; see the Known gaps section below.
Now pick the team from the team-home project:
cd ~/Code/project-a
amq-squad team init --personas cto,fullstack,qa --cwd qa=~/Code/project-bEdit ~/Code/project-a/.amq-squad/team-rules.md. Then sync. Because one member
lives elsewhere, sync walks both cwds and writes CLAUDE.md + AGENTS.md in each:
amq-squad team sync --apply --allow-outside
# Wrote 4 files: CLAUDE.md and AGENTS.md in project-a, same in project-bPrint the launch commands:
amq-squad teamYou'll get three commands, each with the correct cd <member-cwd> so every
agent boots in the right repo. Open three panes and paste one per pane. QA's
codex or claude will live in project-b's mailbox tree; CTO and Fullstack in
project-a's. AMQ uses the peers config you set above to route messages
across.
The generated bootstrap for each role prints send commands relative to that
role's project. For example, a project-a agent sending to QA in project-b
will see a route shaped like:
amq send --to qa --project project-b --session project-a --thread p2p/cto__qaamq-squad team Smart default: show commands, or init if none exists
amq-squad team init [--personas ...] [--session workstream]
[--trust sandboxed|trusted]
[--model role=model,...]
[--codex-args args] [--claude-args args]
Pick personas, choose CLIs, models, and
Codex trust profile; seed rules.
amq-squad team show [--session name] [--fresh] [--no-bootstrap]
[--trust sandboxed|trusted]
[--model role=model,...]
[--codex-args args] [--claude-args args]
[--force-duplicate]
Print launch commands for the configured team
amq-squad team launch [--terminal tmux] [--target current-window|new-session]
[--session workstream] [--fresh]
[--layout vertical|horizontal|tiled]
[--terminal-session name] [--stagger 750ms]
[--no-bootstrap]
[--trust sandboxed|trusted]
[--model role=model,...]
[--codex-args args] [--claude-args args]
[--force-duplicate] [--dry-run]
Open the configured team in tmux panes.
Whole-roster live-agent preflight runs
before any tmux command; --force-duplicate
overrides.
amq-squad team resume [--session name] [--fresh] [--restore-existing]
[--dry-run] [--force-duplicate]
[--no-bootstrap] [--trust sandboxed|trusted]
[--model role=model,...]
[--codex-args args] [--claude-args args]
Plan the safe path to bring the team back
after reboot/upgrade/terminal close.
Classifies each member as
live / restore / launch fresh / blocked
and prints copy-pasteable commands.
Plan-only; no disk mutation.
amq-squad team rules init [--force] Seed or refresh .amq-squad/team-rules.md
amq-squad team sync [--apply] [--allow-outside]
Sync CLAUDE.md and AGENTS.md from team-rules.md
amq-squad launch --role <r> --session <s> [--team-workstream] --me <handle>
[--conversation ref] [--no-bootstrap] [--no-default-args]
[--trust sandboxed|trusted] [--model <name>]
[--codex-args args] [--claude-args args]
[--force-duplicate]
<binary> [-- <flags>]
Launch one agent. Writes launch.json + role.md
in the AMQ mailbox, adds a bootstrap prompt,
then execs 'amq coop exec'.
Usually called by the output of 'team show'.
--trust sandboxed (default) keeps Codex
out of bypass mode; --trust trusted
prepends --dangerously-bypass-approvals-and-sandbox.
Claude defaults (--permission-mode auto)
are still prepended when missing.
--no-default-args opts out of all built-in
defaults.
--model passes a native --model <name>
flag to Codex or Claude.
--codex-args and --claude-args add native
binary flags, such as '--enable goals' or
'--chrome', while still allowing bootstrap.
--conversation stores a restore ref and
translates it to Codex or Claude resume args.
--force-duplicate overrides the duplicate
live-agent guard for the same handle and
workstream.
Do not combine --conversation with extra args
after "--"; use --codex-args or --claude-args
for native flags that should remain compatible
with conversation restore.
amq-squad restore [--project dir1,dir2,...] [--conversation ref]
Reconstruct launch commands from local
launch.json history and nearby role.md
persona files. Falls back to older AMQ
mailbox history when launch.json is absent
and the binary can be inferred.
For records that look active, the metadata
line surfaces wake-health:
wake: pid:N wake.lock present and
the wake process is alive
wake: missing agent looks active but
no wake.lock was found
wake: stale wake.lock present but
the PID is dead or
unrelated
amq-squad restore --exec --role cto Exec one selected local launch through
amq coop exec.
amq-squad list [--json] List restorable amq-squad records and
AMQ-only inferred history across known
projects.
amq-squad version Print the installed amq-squad version.
<project>/.amq-squad/team.json Team intent: which roles are on this squad.
<project>/.amq-squad/team-rules.md Shared norms and workflow (user-edited).
<project>/CLAUDE.md, AGENTS.md Managed block synced from team-rules.md;
user content outside markers untouched.
<AM_ROOT>/agents/<handle>/extensions/
io.github.omriariav.amq-squad/
launch.json Per-agent invocation record, written at launch.
Includes conversation ref when supplied.
role.md Per-agent role doc, seeded from the catalog
with default operating guidance. User
edits are preserved.
<AM_ROOT> is resolved via AMQ's JSON env contract (amq env --json) so
amq-squad and amq coop exec always agree on the mailbox, root source, handle,
and session. v0.6.1 writes extension namespaced metadata under
extensions/io.github.omriariav.amq-squad/ and still reads legacy
direct-agent launch.json and role.md files created by v0.5.x.
- True cross-workstream sends from a setup terminal still depend on upstream
AMQ semantics tracked in
avivsinai/agent-message-queue#96.
The normal team flow now avoids that path by launching one workstream and
routing peer conversations with
--thread. - Multi-cwd teams still need manual
peersconfig in each project's.amqrcfor cross-project AMQ routing.team syncdoesn't touch.amqrc; that's left to the user until we're sure of the shape.
- Go 1.25+
amqbinary in PATH (v0.34+)tmuxin PATH foramq-squad team launch