Skip to content

The bnerd team CLI

The bnerd team command group is the headless entry point for agent teams. It runs in pure line-based I/O — no Bubbletea, no terminal control codes — so it works in pipes, CI, SSH without a PTY, and as the target of another AI's MCP call.

Commands

bnerd team list

List all team recipes known to the CLI (from your mission repo and fallback locations).

bnerd team list
# pr-review            Run a multi-role review of a pull request
# cloud-app            Build/change the cloud product across its surfaces
# incident-response    Triage and respond to an active incident

Flag:

Flag Default Description
--mission-repo <path> auto-discovered Override the mission repo path

bnerd team describe <slug>

Show the full definition of a team recipe: its lead role, safety mode, members (always-on vs on-demand), and workspace.

bnerd team describe pr-review
# pr-review — Run a multi-role review of a pull request
# lead:   product-orchestrator
# safety: read-only
# members:
#   - code-reviewer              (always-on)
#   - security-reviewer          (always-on)

bnerd team run <slug> [prompt]

Spawn the named team and drive it headlessly. The initial prompt positions the team-lead; it can also be provided via --prompt.

bnerd team run pr-review "review PR #142 in cloud/app/hq"

Confirmations and clarifying questions surface inline on stderr:

[lead] spawning code-reviewer, security-reviewer
[code-reviewer] task #1: review PR #142 — code correctness

  ─── CONFIRM ────────────────────────────────────────────────
  code-reviewer wants to run:  gh pr view 142
  context: reading PR body before reviewing
  Approve? [y/N/explain]: ▮

  ─── ASK ────────────────────────────────────────────────────
  code-reviewer: Should I check the migration for reversibility?
  Answer (or "skip"): ▮

After the initial task the CLI accepts further operator input on stdin — type a message and press Enter to inject it into the team-lead's mailbox. This keeps the session interactive while teammates run in the background.

Flags:

Flag Default Description
--prompt <text> (empty) Initial prompt for the team lead (alternative to positional arg)
--safety <mode> read-only Safety floor: read-only, non-destructive, or full. Can only tighten the recipe's declared floor, never loosen it.
--auto-approve <policy> never Confirmation policy: never (ask every time), safe (auto-approve read-only tools only), all (auto-approve everything — only meaningful with --safety=read-only).
--auto-skip-questions off Answer every ask_question prompt with "skip" instead of blocking on stdin. Required for unattended / CI runs.
--json-events off Emit a JSONL event stream on stdout (see Event stream below). Enables CI / pipe / another-AI consumption. Turns off interactive stdin input.
--mission-repo <path> auto-discovered Override the mission repo path

Security note for unattended runs

--auto-approve=all with --safety=read-only does not restrict outbound web-tool URLs. A prompt-injection in fetched content could exfiltrate model-context data via web_fetch GET URLs. For unattended (cron/CI) runs, also pass --auto-skip-questions — otherwise ask_question blocks on stdin and hangs the job.

Storyboard A — interactive headless (default)

bnerd team run cloud-app "add POST /networks endpoint" \
    --workspace ~/cloud/app

Teammates stream their activity to stdout, confirmations and questions pause on stderr, and you answer inline. Same level of control as bnerd pa today — just multi-threaded.

Storyboard B — pre-authorised autonomy

bnerd team run inbox-triage "review yesterday's tickets" \
    --safety=read-only --auto-approve=safe --json-events
{"event":"spawned","teammate":"ops-investigator"}
{"event":"task_created","id":1,"subject":"summarise #7703 progress"}
{"event":"tool_call","by":"ops-investigator","tool":"openproject_read"}
{"event":"task_complete","id":1,"by":"ops-investigator"}
{"event":"team_done","report":"…"}

The safety floor is read-only, so auto-approving everything risks nothing. The final report is the last event; pipe it to jq or another process.

bnerd team status <team-id>

Print a non-blocking snapshot of a persisted team's state: coordinator status, teammate statuses, open tasks, and pending confirmations.

bnerd team status run-cloud-app
# coordinator: running
# teammates:
#   - product-orchestrator  routing task #3
#   - go-cli-dev            idle (waiting for task)
#   - rails-api-dev         claimed task #2: add POST /networks to hq
# tasks:
#   #1  completed   add POST /networks — rails-api-dev
#   #2  claimed     add networks CLI subcommand — go-cli-dev
#   #3  pending     document POST /networks — docs-engineer  [blocked by #1, #2]

bnerd team resume <team-id>

Restore a team from disk after a crash or kill. The coordinator rebuilds the task graph, rehydrates each teammate's chat history, and re-starts the idle/self-claim loop from where it left off. Teammates with dangling tool calls (interrupted mid-execution) receive a synthetic "interrupted — retrying" result and pick up from the next step.

bnerd team resume run-pr-review-01HX

bnerd team cleanup <team-id>

Shut down a running team, drain any pending approvals (auto-declined), and archive the team state directory.

bnerd team cleanup run-cloud-app

Event stream

When --json-events is set, every team event is emitted as a JSON object on its own line (JSONL). Events are separated from the human-readable log; the log goes to stderr while events go to stdout so they can be piped cleanly.

Key event types:

Event Fields Description
spawned teammate, role A teammate came online
task_created id, subject, by A task was added to the shared list
task_claimed id, by A teammate claimed a task
task_complete id, by, summary A task was marked done
gate_satisfied task_id, gate, by, at_ref, decision A review gate was satisfied
confirm_requested id, from, tool, args, context A tool confirmation is needed
question_requested id, from, question A teammate has a question
approval_requested task_id, from, summary A human-gate task needs approval
tip_mismatch task_id, gates Gates were satisfied at different commits; task held
team_paused reason, by Team entered pause state
team_done report Team finished; report is the final synthesis