Skip to content

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.

[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.

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.

Terminal window
bmo config show-activation-reactions
bmo config show-activation-reactions --format=json

When bmo serve is running, the live app-backed HTTP view is:

Terminal window
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.

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.

Terminal window
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.

CodeMeaning
0Agent completed successfully
1Agent error (model error, tool failure)
2Autopilot 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.

Terminal window
bmo run "Summarize the last 20 commits" | tee summary.txt

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).

.github/workflows/review.yml
- 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).

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:

~/.config/bmo/recipes/daily-review.yaml
title: Daily Review
description: Summarize today's git activity
prompt: Review my git log from today and summarize key changes.

Run with:

Terminal window
bmo recipe run daily-review --auto-approve-tools

You can also use bmo run --recipe daily-review. Pass parameters with --param key=value (or -p key=value), repeatable:

Terminal window
bmo run --recipe deploy-check -p env=staging -p region=us-east-1 --auto-approve-tools

What 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.

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.

Terminal window
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.

Automation swimlanes
CLI
run
recipe
params
stdout
Scheduler
cron
job
recipe
history
Rules
event
action
notify
artifact
Hooks
shell
veto
log
exit
Automation paths share the run substrate, but they enter through different control planes.