Skip to content

Automation Level Behavior Guide

Reference for how commands and skills should adjust interaction ceremony based on the active automation level. The big-picture description of each level (and how to switch) is in project-orchestration-handbook.md §7.1; this doc is the per-decision behavior table. Warp-drive's level-specific behavior is in the handbook §7.2 and warp-drive.md.

Detection

Read .claude/settings.local.json in the project directory. Look for _automation.active_level (1, 2, or 3). If not found or the file doesn't exist, default to Level 1.

Level Principles

Level 1 — Supervised (default)

  • Ask before every decision
  • Show all options with explanations
  • Wait for explicit confirmation before acting
  • This is identical to pre-automation behavior

Level 2 — Trusted Dev

  • Auto-proceed on safe, inferrable, or reversible decisions
  • Still confirm destructive operations (force push, delete, overwrite)
  • Still ask for subjective content (summaries, descriptions, priorities)
  • Show each auto-decision inline as it happens

Level 3 — Autonomous

  • Minimize prompts — only stop for destructive ops or subjective content
  • Auto-infer from git context, branch names, file paths, commit history
  • Batch auto-decisions into a summary rather than inline notifications
  • Ask for: rebase conflicts, subjective writing, destructive operations

Transparency Format

Commands must show what was auto-decided so the user stays informed.

Level 2 — inline per decision:

> Auto (L2): Branch type set to `tooling/` (inferred from .claude/ changes)
> Auto (L2): Stashed 2 uncommitted files

Level 3 — batched summary:

> Auto (L3) decisions:
>   - Branch type: `tooling/` (inferred from .claude/ changes)
>   - Stashed 2 uncommitted files
>   - Branch name: `tooling/automation-behavior`

Decision Classification

CategoryL1L2L3
Safe + inferrableAskAuto, showAuto, show
Reversible actionAskAuto, showAuto, show
Subjective contentAskAskAsk
Destructive operationAskAskAsk
Push to remoteAskConfirmAuto (except main/master)
Conflict resolutionAskAskAsk
Requirement/AC trackingAskAuto-update, showAuto-update, show
Documentation housekeepingAskAuto-update, showAuto-update silently
Warp-drive continue to next taskAskAskAuto-continue, log
Warp-drive plan reviewAskAskAuto-proceed, log

Autonomous profile — auto-approved vs always-blocked (#420)

Level 3 (the autonomous profile, profiles/autonomous.json) is the only level designed to run unattended — including overnight. Because nothing prompts, "what exactly is this allowed to do while I'm asleep?" needs a documented answer. This is it.

When to use it vs. interactive defaults. Use L3 only for a scoped, version-controlled repo where every change is recoverable from git and you have reviewed the work queue — e.g. an area:-scoped warp-drive batch of approved requirements. Stay at L1/L2 (interactive) for exploratory work, anything touching production credentials or external services by hand, or a repo whose state you are not ready to have advanced without review. L3 trades the per-action prompt for an after-the-fact audit trail (below) — that trade only pays off when the queue is trusted and the blast radius is git.

Auto-approved at L3 (no prompt): reads, search, edits/writes, Bash, the dev/test/commit/push/merge skills, Playwright, WebFetch/WebSearch, and push/merge to main/master (subject to the promotion ceiling — a pr ceiling still caps L3 at a pull request).

Always-blocked at L3 (denied even though everything else is auto-approved) — three layers, each entry carries a rationale in profiles/autonomous.json_meta.deny_rationale:

LayerBlocksWhy
Destructive-git floorgit push --force, git push origin --force, git reset --hard, git branch -D, rm -rfIrrecoverable history/working-tree loss. This floor is a deliberate guardrail and is never loosened — see the autonomous-deny-destructive-git guardrail.
Secrets / credential reads.env / .env.*, *credential*, ~/.ssh, ~/.aws, ~/.config/gcloud, ~/.kube, ~/.npmrc, ~/.netrc (via both Read and shell cat)An unattended run has no legitimate reason to read raw secret stores; blocking them shrinks the exfil surface.
Network-exfil shapescurl -T / --upload-file, curl -d @file, pipe-into-curl/wget, wget --post-fileThe obvious "send a local file to a remote host" shapes.

Honest limitation. The secrets/exfil blocks are defense-in-depth, not a sandbox. Bash is broadly allowed, so a sufficiently creative shell command can still read a file or reach the network — the deny patterns only catch the obvious shapes. The real backstop for an unattended run is the audit log, not the deny-list.

Audit log

When _automation.active_level == 3, the autonomous-audit-log.sh PreToolUse hook records every auto-approved tool call — tool, target, timestamp, session, cwd — as one JSONL line per call:

  • Location: ~/.claude/logs/autonomous-audit/<session-id>.jsonl (override with $BOB_AUTONOMOUS_AUDIT_DIR).
  • Per session: one file per Claude Code session, so an overnight run is one reviewable trail.
  • Recorder, never a gate: it always exits 0 and never blocks — it only observes.
  • Strict no-op below L3: at L1/L2 (and outside BoB projects) it reads one settings field and exits, so it cannot affect interactive or Trusted-Dev runs.

To review an unattended run afterwards: jq -r '"\(.ts) \(.tool) \(.target)"' ~/.claude/logs/autonomous-audit/<session>.jsonl.

So — is it safe to leave running overnight? For a scoped, git-backed repo with a reviewed queue: yes — irrecoverable git ops, secret reads, and obvious exfil are blocked, and everything auto-approved is captured in the audit log for morning review. It is not a substitute for a sandbox on an untrusted workload, and the promotion ceiling still governs how far work is actually promoted.

Promotion ceiling (#448)

The automation level governs how much autonomy the agent has. It used to also decide how far work is promoted — the two were fused: Level 2 ≡ "open a PR", Level 3 ≡ "merge to master". That made "run fully autonomously, but never push past a PR" impossible to express.

A project's promotion ceiling (dev.jsonpromotion.ceiling, default external) decouples those axes. The merge/deploy decision becomes f(automation_level, ceiling), computed by the shared library scripts/promotion/promotion.js and enforced everywhere — warp-drive's merging phase, /finish-work, and the promotion-ceiling-guard PreToolUse hook. View or set it with /promotion.

Git action (merge) — f(level, ceiling):

Ceiling ↓ \ Level →L1L2L3
prPRPRPR (capped — never auto-merges to main)
external (default)PRPRdirect merge to main
testPRPRdirect merge to main
prodPRPRdirect merge to main

Deploy action — f(level, ceiling):

Ceiling ↓ \ Level →L1L2L3
prnonenonenone
external (default)nonenonenone (git only — deployment is out-of-band)
testnonenonedeploy to test
prodnonenonedeploy to prod

The default external reproduces the legacy fused behavior exactly (L3 → direct merge + no deploy, L2 → PR), so a project with no promotion block is unchanged. Setting a ceiling only ever narrows (pr) or extends (test/prod) from that baseline. Deploy adapters that execute the test/prod deploy land in #450; until then a non-external deploy action is a recorded intent, not yet an executed deploy.