Automation & Headless Mode
BMO’s unified automation engine covers unattended execution for CI, scripts,
and scheduled tasks. Use bmo run for one-shot non-interactive prompts,
bmo recipe run for reusable YAML recipes, and bmo autopilot when you need a
long-lived background process or HTTP API server. Hooks stay separate as shell
callbacks; they are not part of this engine.
The canonical config surface for structured automation is options.automation:
use jobs for cron-backed work and rules for event-driven follow-ons.
options.reactions, options.activations, and feature-specific managed
schedule blocks are not accepted as public config surfaces; express that work
as canonical automation jobs or rules.
For unattended background stewardship, compaction is one built-in automation
target. Canonical automation jobs can run builtin://compaction, canonical
rules can enqueue compaction jobs with compaction_idle_gate = true, and the
nap controller can originate idle wakeups while bmo up or the scheduler
daemon is running. See Compaction.
This repo can also reconcile a daily docs-refresh job through the canonical
automation engine. Configure it as an options.automation.jobs entry that
points at the docs-refresh recipe.
Canonical automation config
Section titled “Canonical automation config”[options.automation] [[options.automation.jobs]] id = "daily-review" enabled = true cron = "0 0 9 * * *" recipe_path = "recipes/daily-review.yaml"
[[options.automation.rules]] id = "arena-log" on = ["arena.accepted"]
[[options.automation.rules.actions]] type = "notify" channel = "log"Use options.automation for new scheduled or event-driven work.
Inspect activation and reaction posture
Section titled “Inspect activation and reaction posture”Use the shared inspect family when you need to see whether canonical
options.automation.rules are wired, degraded, or actively producing recent
follow-on activity.
bmo config show-activation-reactionsbmo config show-activation-reactions --format=jsonWhen bmo serve is running, the live app-backed HTTP view is:
curl -s "$BMO_HTTP/v1/posture/activation-reactions"curl -s "$BMO_HTTP/v1/posture/activation-reactions?session_id=$SID"The TUI exposes /activation-reactions. Native agent and MCP parity use
get_activation_reactions_status and bmo_get_activation_reactions_status.
The CLI command is truthful about process boundaries: it is a config-only
out-of-process view and does not claim access to the live in-process recent
ring.
Running one prompt non-interactively
Section titled “Running one prompt non-interactively”Safety note: The --auto-approve-tools flag lets BMO execute all tool calls (file writes, shell commands) without asking for confirmation. Only use it in trusted, isolated environments such as CI containers or disposable VMs. In local development, omit it so BMO asks before each write.
bmo run --auto-approve-tools "Review the PR diff and print a short summary"bmo run skips the TUI and exits when the prompt completes. Add
--auto-approve-tools for unattended runs that should not stop on permission
prompts.
What you should see: BMO prints its output to stdout and exits. Check echo $? for the exit code (see table below).
Recovery: If bmo run modifies files unexpectedly, use git diff to inspect changes and git checkout -- . to revert. In CI, run BMO in a clean checkout to limit blast radius.
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 | Agent completed successfully |
1 | Agent error (model error, tool failure) |
2 | Autopilot configuration error before the agent workflow starts |
Lifecycle-hook vetoes currently surface as agent workflow failures (1) unless
a more specific runtime exit code is introduced.
Piping output
Section titled “Piping output”bmo run "Summarize the last 20 commits" | tee summary.txtCI integration
Section titled “CI integration”Safety note: In CI, always pin to a known BMO version and run in a fresh checkout. The --auto-approve-tools flag grants full tool access — ensure the prompt cannot be influenced by untrusted input (e.g., PR titles or commit messages from external contributors).
- name: AI code review run: | bmo run --auto-approve-tools "Review the diff in this PR. Output findings to findings.md" env: ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}Verify it worked: Check the CI step exit code and the findings.md artifact. Exit code 0 means success; 1 means an agent error occurred (see exit codes above).
Recipes
Section titled “Recipes”A recipe is a runnable YAML workflow (on-demand or scheduled); a skill is an in-session instruction set (SKILL.md) that shapes how the agent behaves. Both are first-class agent entrypoints.
Recipes are reusable YAML workflows with instructions, optional parameters, and runtime settings:
title: Daily Reviewdescription: Summarize today's git activityprompt: Review my git log from today and summarize key changes.Run with:
bmo recipe run daily-review --auto-approve-toolsYou can also use bmo run --recipe daily-review. Pass parameters with
--param key=value (or -p key=value), repeatable:
bmo run --recipe deploy-check -p env=staging -p region=us-east-1 --auto-approve-toolsWhat you should see: BMO loads the recipe, substitutes parameters, runs the prompt, and exits. Output appears on stdout.
Verify it worked: Check exit code 0 and review any files the recipe was expected to create or modify.
Recipes and skills as agent entrypoints. A recipe run is a first-class agent run: one prompt, one execution, optional parameters. Schedule a recipe with bmo schedule add ... to run that agent on a cron; use bmo recipe run or bmo run --recipe for on-demand runs. Skills (see Agent Skills) extend the agent’s instructions in-session; combine them with recipes or scheduled jobs when you want repeatable, scriptable agent behavior.
Headless autopilot runs
Section titled “Headless autopilot runs”Safety note: bmo autopilot --auto-approve gives the run full tool access
for that headless execution. Only use it in environments where you are
comfortable with unsupervised file and shell operations for the duration of that
run.
bmo autopilot --auto-approve "Watch this repository and keep the docs in sync"Plain bmo autopilot "<prompt>" runs the prompt once and exits. Use
bmo autopilot --server when you want the HTTP API server alongside that run,
or bmo autopilot --server-only / bmo up when you need a long-lived service
without a one-shot prompt.
What you should see: BMO executes the prompt, streams progress to stdout,
and exits when the run completes. Long-lived behavior applies only to
--server-only or bmo up.
Recovery: For a one-shot run, inspect git log and git diff after it
finishes. For --server-only or bmo up, send SIGINT (ctrl+c) or
SIGTERM to stop the long-lived process.