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.

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.

  • Ask before every decision
  • Show all options with explanations
  • Wait for explicit confirmation before acting
  • This is identical to pre-automation behavior
  • 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
  • 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

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`
Category L1 L2 L3
Safe + inferrable Ask Auto, show Auto, show
Reversible action Ask Auto, show Auto, show
Subjective content Ask Ask Ask
Destructive operation Ask Ask Ask
Push to remote Ask Confirm Auto (except main/master)
Conflict resolution Ask Ask Ask
Requirement/AC tracking Ask Auto-update, show Auto-update, show
Documentation housekeeping Ask Auto-update, show Auto-update silently
Warp-drive continue to next task Ask Ask Auto-continue, log
Warp-drive plan review Ask Ask Auto-proceed, log

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

Section titled “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:

Layer Blocks Why
Destructive-git floor git push --force, git push origin --force, git reset --hard, git branch -D, rm -rf Irrecoverable 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 shapes curl -T / --upload-file, curl -d @file, pipe-into-curl/wget, wget --post-file The 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.

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.

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 → L1 L2 L3
pr PR PR PR (capped — never auto-merges to main)
external (default) PR PR direct merge to main
test PR PR direct merge to main
prod PR PR direct merge to main

Deploy action — f(level, ceiling):

Ceiling ↓ \ Level → L1 L2 L3
pr none none none
external (default) none none none (git only — deployment is out-of-band)
test none none deploy to test
prod none none deploy 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.