CLI Reference

September 4, 2026 ยท View on GitHub

Bernstein ships a large surface of CLI commands registered in cli/main.py. This page is the single-source reference for every flag on every visible command. For driving Bernstein from a script, also read cli/task-lifecycle.md and cli/replay.md.

Find a command fast: Ctrl-F for the command name. Every entry below cites its source as cli/<file>:<line>. Get rich help in the terminal: bernstein --help (root rich-formatted help) and bernstein help-all (the same, exhaustive). Per-command help: bernstein <command> --help works on every visible command and group.


Root command flags

bernstein itself accepts these flags (defined at cli/main.py:482-572). Most of them only matter when invoked without a subcommand - i.e. when you run bernstein to start orchestration from bernstein.yaml or an inline --goal.

FlagDefaultMeaning
--version-Print version and exit.
-g, --goal TEXTnoneInline goal; bypasses the seed file.
--jsonoffEmit machine-readable JSON for any subcommand that supports it.
`--output {jsontext}`text
-e, --evolveoff(hidden) Continuous self-improvement mode.
--max-cycles N0(hidden) Stop after N evolve cycles. 0 = unlimited.
--budget USD0.0Cost cap. 0 = unlimited.
--interval N300(hidden) Seconds between evolve cycles.
--githuboff(hidden) Sync evolve proposals as GitHub Issues.
--headlessoff(hidden) Run without dashboard (overnight/CI).
--dry-runoffPreview the task plan without spawning agents.
-y, --yesoff(hidden) Skip cost confirmation prompt.
--freshoffIgnore saved session; start clean.
--plan-onlyoffShow the execution plan without running agents.
--from-plan FILEnoneExecute a saved plan file (skips interactive planning).
--auto-approveoffSkip confirmation prompt before execution.
--approval {auto|review|pr}autoApproval gate: merge immediately / pause for review / open GitHub PR.
--merge {pr|direct}prMerge strategy: open a PR, or push directly to main.
--cli NAMEnoneForce a specific agent: any adapter from bernstein adapters list, or auto (overrides auto-detection).
--model NAMEnoneForce a specific model (e.g. opus, sonnet, o3).
--workflow {governed}noneActivate governed workflow mode.
-v, --verboseoffShow debug-level output.
-q, --quietoffSuppress all non-error output.
-t, --task PATTERNnoneRun only backlog tasks matching PATTERN.
--auto-proffAuto-open a GitHub PR when all tasks complete.
--activity-log [PATH]offWrite activity to a log file. Default path .sdd/logs/activity.log.

The hidden flags (--evolve, --max-cycles, --interval, --github, --headless, --yes) are visible via --help-all and via bernstein --evolve --help once you know they exist.

Any global flag may also be set via bernstein.yaml (e.g. budget: 5.00); the CLI flag wins on conflict.


Commands by category

The commands are organised below by purpose, not alphabetically. Use the table inside each category for quick lookup; the longer per-command entries follow for the highest-traffic commands.

Conventions

  • Synopsis lines use [flags] where every visible flag is listed in the flag table below it.
  • All commands accept the root-level --json / -v / -q flags.
  • Hidden subcommands (task compose, task sync, etc.) are documented in the Hidden commands section at the end.
  • Flags marked auth require a logged-in session (bernstein login).

Run & control

The "do work" commands. This is where most operators live.

CommandPurposeSource
bernsteinRun from bernstein.yaml (or inline -g GOAL).cli/main.py:482
bernstein run [PLAN.yaml]Execute a plan file.cli/run_bootstrap.py (re-exported via cli/run_cmd.py)
bernstein startStart the server + orchestrator (no goal).cli/run_bootstrap.py:start
bernstein stopGraceful stop (agents save work first).cli/commands/stop_cmd.py:717
bernstein cancel TASK_IDCancel a running or queued task.cli/commands/task_cmd.py:160
bernstein cleanupClean worktrees and old logs.cli/maintenance_cmd.py:162
bernstein demo --flask-todoZero-config Flask TODO API demo (bernstein quickstart is a deprecated alias, removed in 4.0.0).cli/quickstart_cmd.py
bernstein quickstartDeprecated alias of bernstein demo --flask-todo; removed in v4.0.0. Keeps its own adapter auto-detection, so it can spend money without --real.cli/quickstart_cmd.py
bernstein demo60-second zero-to-running demo.cli/run_confirm.py:demo
bernstein cookRun a recipe (multi-stage demo).cli/run_confirm.py:cook
bernstein initInitialize project (.sdd/ + bernstein.yaml).cli/run_bootstrap.py:394
bernstein init --wizardInteractive project setup (bernstein init-wizard is a deprecated alias, removed in 4.0.0).cli/init_wizard_cmd.py
bernstein init-wizardDeprecated alias of bernstein init --wizard; removed in v4.0.0.cli/init_wizard_cmd.py
bernstein dry-runPreview the plan without spawning.cli/commands/dry_run_cmd.py:203
bernstein replay RUN_IDReplay a past run step-by-step.cli/commands/advanced_cmd.py:876
bernstein undoUndo the last operation. --dry-run TASK_ID prints the paths that task changed and exits without touching the tree (task revert).cli/commands/undo_cmd.py:22
bernstein checkpointSave progress for later resume.cli/commands/checkpoint_cmd.py:49
bernstein wrap-upEnd session with summary + learnings.cli/wrap_up_cmd.py
bernstein fork --run ID --from-step NRewind a run to journal step N and branch a new run from its content-addressed worktree snapshot.cli/commands/fork_cmd.py

bernstein run

Execute a plan file (or start orchestration with no plan).

Synopsis: bernstein run [PLAN_FILE] [flags]

The full flag list is large (see bernstein run --help and cli/run_bootstrap.py:533+). Most commonly used:

FlagDefaultMeaning
PLAN_FILEnoneA YAML plan to execute. Optional.
--budget USD0.0Cost cap. 0 = unlimited.
--max-cost-usd NunsetHard cap on cumulative routed model spend; aborts the run when crossed. Sets BERNSTEIN_MAX_COST_USD.
--cliautoForce agent: any registered adapter name (see bernstein adapters list) or auto.
--modelnoneForce a specific model.
--auto-approveoffSkip the interactive plan-approval gate.
--dry-runoffPreview without spawning.
--plan-onlyoffShow plan, do not run agents.
--auto-proffAuto-open a GitHub PR on completion.
--task PATTERNnoneRun only matching backlog tasks.
--wait [SECONDS]offBlock until the run reaches a terminal state and exit with its outcome. Optional ceiling in seconds, default 3600.
--port N8052Task server port.
-v / -qoffVerbosity.

The merge strategy is not a run flag: set merge_strategy: pr|direct in bernstein.yaml (default pr).

--max-cost-usd is a hard cap, separate from the soft --budget threshold model. It writes the value to BERNSTEIN_MAX_COST_USD before bootstrap; the orchestrator drains live agents and aborts when cumulative routed spend crosses the threshold. Precedence is BERNSTEIN_MAX_COST_USD > run_config.json > seed.budget_usd

default (0 = unlimited). Non-positive values normalise to 0.

Non-interactive output (pipes, CI). When stdout is not a terminal the CLI detaches after bootstrap instead of opening the dashboard. Before exiting it waits up to ~10 seconds for the first spawn outcome:

  • If the first spawn attempt was refused or errored before any work started, the failure reason is printed and the command exits 1. Details: bernstein status or .sdd/runtime/retrospective.md.
  • Otherwise the summary is followed by an explicit detach notice; the run continues in the background and the command exits 0. Check progress with bernstein status.

bernstein stop

Graceful or force stop.

FlagDefaultMeaning
--force / --hardoffHard stop: kill processes immediately.
--timeout SEC30Seconds to wait for agents on a soft stop.

bernstein stop (no flag) sends SIGTERM to the orchestrator and waits for agents to finish their current step and persist artefacts. bernstein stop --force terminates everything immediately and runs orphan-recovery on the next start.

bernstein cancel

See cli/task-lifecycle.md#bernstein-cancel.

bernstein cleanup

FlagDefaultMeaning
--workdir.Project root.
--yesoffSkip the confirmation prompt.
--forceoffAlso delete agent branches not merged into main (may discard in-flight work).

bernstein replay

See cli/replay.md for full reference.

bernstein checkpoint

FlagDefaultMeaning
--goal TEXTnoneGoal label embedded in the checkpoint.

Snapshots .sdd/ state so a later bernstein run can resume from it.

bernstein wrap-up

End a session with a summary, retrospective, and learning capture. Hides under no flags; useful at the end of a long-running orchestration.

bernstein init / bernstein init --wizard

FlagDefaultMeaning
--dir PATH.Directory to initialise.
--wizard / -woffRun the interactive setup wizard.
--non-interactiveoffWith --wizard: take the wizard's defaults without prompting. Plain init never prompts.
--remoteoffInitialise for a remote container quickstart (e.g. Codespaces); skips local-binary checks.
--add-badgeoffInsert a shields.io "powered by bernstein" badge into README.md.
--badge-variant NAMEsignedBadge wording when --add-badge is passed.

init-wizard adds an interactive prompt flow (project type, default agent, budget, etc.) and is preferred for first-time users.


Plan & tasks

CommandPurposeSource
bernstein planShow the task backlog.cli/commands/task_cmd.py:454
bernstein plan generate "<goal>"Generate a plan YAML.cli/plan_generate_cmd.py
bernstein plan compile SPECCompile a spec into a gated task graph with requirement-hash lineage.cli/plan_compile_cmd.py
bernstein plan lsList archived plans.cli/plan_archive_cmd.py:plan_ls
bernstein plan show NAMEShow a stored plan.cli/plan_archive_cmd.py:plan_show
bernstein add-task TITLECreate a task on the running server.cli/commands/task_cmd.py:37
bernstein approve TASK_IDApprove a pending review.cli/commands/task_cmd.py:249
bernstein reject TASK_IDReject a pending review.cli/commands/task_cmd.py:270
bernstein pendingList tasks awaiting approval.cli/commands/task_cmd.py:291
bernstein list-tasksList tasks with filters.cli/commands/task_cmd.py:637
bernstein tasksAlias of bernstein plan.cli/main.py:706
bernstein mergeMerge a completed task's worktree.cli/commands/merge_cmd.py:64
bernstein reviewTrigger queue review or run a review pipeline.cli/commands/task_cmd.py:175
bernstein verifyVerify WAL integrity, execution determinism, memory provenance, formal properties, or a wheelhouse.cli/commands/verify_cmd.py
bernstein from-ticket FILEGenerate tasks from a ticket file.cli/commands/ticket_cmd.py:231
bernstein ticketTicket integration group.cli/commands/ticket_cmd.py:246
bernstein plan validate PLAN.yamlValidate a plan file's schema (bernstein validate is a deprecated alias, removed in 4.0.0).cli/plan_validate_cmd.py:142
bernstein validate PLAN.yamlDeprecated alias of bernstein plan validate; removed in v4.0.0.cli/plan_validate_cmd.py
bernstein taskDurable task lifecycle: complete, park, and resume a task.cli/commands/task_cmd.py:837

bernstein plan

FlagDefaultMeaning
--export FILEnoneWrite full task list as JSON to FILE.
--status STATUSnoneFilter: open / claimed / in_progress / done / failed / blocked / cancelled.
--graphoffRender an ASCII dependency graph.

The graph view shows the critical path in bold yellow with a star (โ˜…) and lists bottlenecks at the bottom.

bernstein plan generate

FlagDefaultMeaning
DESCRIPTIONrequiredGoal description (positional).
--output FILE / -oplans/<slug>.yamlOutput path for the YAML plan.
--model NAMEanthropic/claude-haiku-4-5Model used to draft the plan.
--provider NAMEopenrouterLLM provider (openrouter, openai, ...).
--workdir PATH.Project root directory to analyse.
--dry-runoffPrint the generated plan without saving to disk.
--enforce-vertical / --no-enforce-verticalonEnforce vertical-slice shape checks on the generated plan.
--max-loc NconfigHard LOC cap per slice; overrides bernstein.yaml [plan].max_loc.
--max-files NconfigMax files per slice; overrides bernstein.yaml [plan].max_files.

bernstein plan compile

Compile a requirements document into a gated task graph. A three-stage pipeline with at most one model call: draft (structured requirement extraction), approve (the requirement-set hash is bound into the audit chain), and compile (a deterministic, model-free transformation to a task graph). Each task node carries the content hashes of the requirement lines it implements, so every artefact traces back to spec lines through lineage.

FlagDefaultMeaning
SPECrequiredSpec / requirements document (positional).
--name NAMEspec stemPlan name and output slug under .sdd/spec/.
--approveoffRecord an approval receipt for the requirement set into the audit chain.
--jsonoffEmit a JSON summary instead of a table.

Artefacts are written to .sdd/spec/<name>/ (requirements.json, graph.json, and, with --approve, receipt.json). The same approved requirement set always compiles to a byte-identical graph, so graph_hash is reproducible; editing one requirement re-plans only the affected node while every other node keeps its content-addressed identity.

bernstein add-task

See cli/task-lifecycle.md#bernstein-add-task.

bernstein review

See cli/task-lifecycle.md#bernstein-review-bernstein-verify.

bernstein task

A group, with four subcommands. A task that must wait on something outside the run - a mid-flight approval, an external review, a credential rotation, a dependency landing - can be parked rather than left holding its resources: the park writes an attested receipt, releases the seat, sandbox and budget headroom, and resume restores from that receipt.

SubcommandPurposeSource
complete TASK_IDMark a task complete on the running task server.cli/commands/task_cmd.py:861
suspend TASK_IDPark a running task and free its seat, sandbox and budget.cli/commands/task_cmd.py:918
resume TASK_IDResume a parked task from its attested suspend receipt.cli/commands/task_cmd.py:1035
list-suspendedList parked tasks with their parked-at hash and freed resources.cli/commands/task_cmd.py:1154

The group itself takes no flags beyond --help; each subcommand carries its own, below.

bernstein task complete

Resolves the task-server URL and the session token itself, from BERNSTEIN_SERVER_URL / .sdd/runtime/server.port and BERNSTEIN_AUTH_TOKEN / the persisted run-token file, so a completion does not have to be hand-assembled as a request with a bearer header.

FlagDefaultMeaning
--summary TEXT / -srequiredResult summary recorded on the task (max 2000 chars).
--jsonoffPrint the server's task payload as JSON.
bernstein task suspend
FlagDefaultMeaning
--workdir PATH.Project root (the parent of .sdd/).
--adapter TEXTlatest checkpointAdapter owning the session.
--session-id TEXTlatest checkpointNative session id.
--worktree TEXTcheckpoint worktree, else cwdWorktree to hash.
--envelope TEXTsubscriptionQuota envelope whose headroom is freed.
--reserved-usd FLOATnoneEnvelope headroom reserved for the task.
--spent-usd FLOATnoneSpend recorded against the reservation at park time.
--until approvaloffResume only once bernstein approve TASK_ID lands.
--role TEXTthe task's recorded roleRole the checkpoint's grant is bound to.
--parent-run-id TEXT$BERNSTEIN_RUN_IDRun that owns the task, bound into the grant.
--jsonoffPrint the park result as JSON.
bernstein task resume
FlagDefaultMeaning
--workdir PATH.Project root (the parent of .sdd/).
--worktree TEXTthe parked pathRe-materialized worktree to hash.
--mode [warm|fork|cold]warmRequested continuation mode; downgraded, never upgraded, on drift.
--jsonoffPrint the resume result as JSON.
bernstein task list-suspended
FlagDefaultMeaning
--workdir PATH.Project root (the parent of .sdd/).
--jsonoffPrint the parked tasks as JSON.

Status & monitoring

CommandPurposeSource
bernstein statusTask summary + agent health.cli/commands/status_cmd.py:147
bernstein liveInteractive Textual TUI dashboard.cli/commands/advanced_cmd.py:47
bernstein gui serveServe the maintained web GUI at /ui.gui/cli.py
bernstein psRunning agent processes.cli/commands/status_cmd.py:241
bernstein watchStream task events.cli/watch_cmd.py:252
bernstein logsTail agent logs (group).cli/logs_group_cmd.py:45
bernstein recapPost-run summary.cli/commands/advanced_cmd.py:558
bernstein retroDetailed retrospective.cli/commands/advanced_cmd.py:299
bernstein wrap-upEnd-of-session summary.cli/wrap_up_cmd.py
bernstein historyShow run history.cli/maintenance_cmd.py:history_cmd
bernstein runs reportFinished runs with a classified outcome.cli/commands/runs_cmd.py
bernstein report commitsPer-run git diff stats.cli/commands/status_cmd.py:1232
bernstein reportBuild a custom report (group).cli/report_cmd.py
bernstein sloSLO dashboard.cli/slo_cmd.py:191
bernstein trace TASK_IDStep-by-step trace.cli/commands/advanced_cmd.py:666
bernstein report incidentOpen an incident report.cli/commands/incident_cmd.py:53
bernstein report postmortemFailed-task postmortem.cli/commands/postmortem_cmd.py:12

bernstein status

Compact one-screen project view.

FlagDefaultMeaning
--jsonoffEmit JSON.
--mode {novice|standard|expert}persisted or standardDashboard detail level.
--no-coloroffDisable colour output.

bernstein live

FlagDefaultMeaning
--interval SEC2.0Polling interval.
--classicoffUse the simpler Rich Live display.
--no-splashoffSkip the startup splash.

The default is the 3-column Textual TUI: Agents | Tasks | Activity feed. --classic falls back to a single-pane Rich Live view.

Both views resolve the task server the same way as the rest of the CLI: BERNSTEIN_SERVER_URL, then the port the running orchestrator persisted in .sdd/runtime/server.port, then http://localhost:8052. When the poll cannot reach that server the header says No connection to <url> rather than drawing empty panels, which would be indistinguishable from an orchestrator with nothing to do. That state means every read failed: one route erroring while the others answer is a broken route, not a dead server, so the dashboard keeps rendering the panels that did load.

The run token the orchestrator persists under .sdd/runtime is only ever sent to a loopback address: it is a credential this machine minted for its own run, and BERNSTEIN_SERVER_URL can name any host. A token you set in BERNSTEIN_AUTH_TOKEN yourself goes wherever you point the dashboard.

bernstein logs

A subcommand group; defaults to bernstein logs tail.

SubcommandFlagsPurpose
tail--follow / -f, --agent / -a ID, --lines / -n N, --runtime-dir DIRTail the most recent agent log.
search QUERY--time-range, --agent-roleSearch logs across all agent sessions and the orchestrator.

bernstein logs (no subcommand) is equivalent to bernstein logs tail.

bernstein recap

FlagDefaultMeaning
--archive PATH.sdd/archive/tasks.jsonlPath to task archive.
--since DURATIONnoneBuild the report from workspace files instead of the task server (45m, 6h, 2d; a bare number is minutes).
--workdir PATH.Project root, used with --since.
--as-jsonoffEmit raw JSON.

With --since the summary is the "since you were away" report: completed and failed tasks, provider errors, and estimated cost read from .sdd/ alone, so it still answers what happened after the run and its server have exited.

bernstein retro

FlagDefaultMeaning
--since HOURSallHours back to include.
--output FILE / -o.sdd/runtime/retrospective.mdOutput path.
--printoffAlso print to stdout.
--archive PATH.sdd/archive/tasks.jsonlSource archive.

bernstein runs

Group over the runs recorded in the work ledger.

SubcommandFlagsPurpose
report--since DURATION, --workdir PATH, --jsonFinished runs with a classified outcome and one line of evidence.
bernstein runs report
FlagDefaultMeaning
--since DURATIONallOnly include runs started in the last DURATION (45m, 6h, 2d).
--workdir PATH.Project root.
--jsonoffEmit stable machine-readable rows instead of the table.

The report is projected from .sdd/ alone, so it still answers what came of a batch of runs after the orchestrator and its task server have exited. Each row carries the outcome class and the one line of evidence it was classified from: pr-opened (a branch was published), gate-failed (a quality gate blocked the run), no-changes (zero commits over base), infra-error (adapter or transport death, or no wrap-up was ever recorded), and wedged (the run ended with open tasks nothing could spawn).

bernstein watch

FlagDefaultMeaning
DIRECTORY.Directory to watch (positional).
--glob PATTERNnoneRestrict watching to files matching PATTERN (e.g. src/**/*.py).

bernstein trace

Group: inspect, serve, and verify local agent traces.

FlagDefaultMeaning
--traces-dir DIR.sdd/tracesDirectory containing trace files.
SubcommandPurpose
show TASK_IDStep-by-step execution trace for a task; --as-json emits raw JSON.
verify TRACE_IDConfirm the on-disk bytes match the indexed sha256.
reindexRebuild .sdd/traces/index.jsonl from the on-disk blob tree.
serveRead-only FastAPI viewer over the local content-addressed store (--port, --bind).
project RUN_IDProject the run's event journal into a signed OTel span set.
verify-projection RUN_IDRecompute span ids from the journal and verify the signature.

Subcommands project RUN_ID and verify-projection RUN_ID emit and verify a signed OTel GenAI span set projected from the run event journal. Span ids are derived from journal entry hashes (byte-identical across replays), each span carries bernstein.journal.entry_hash, and the set is signed with the install identity. --no-genai-stability omits the Development-stage GenAI convention attributes while keeping the ids journal-anchored; the local .sdd/runs/<run_id>/projection.otel.json store emits even with no OTLP endpoint set. (cli/commands/advanced_cmd.py, core/observability/otel_projection.py.)

bernstein slo

FlagDefaultMeaning
--workdir.Project root.
--jsonoffEmit raw JSON.
--watchoffRefresh every --interval seconds until interrupted.
--interval SEC30Refresh interval in --watch mode.
--compactoffCompact output without sparkline.

Quality & autofix

CommandPurposeSource
bernstein verifyVerify WAL integrity, execution determinism, memory provenance, formal properties, or a wheelhouse.cli/commands/verify_cmd.py
bernstein autofixAuto-repair CI failures (group).cli/commands/autofix_cmd.py:172
bernstein ciCI integration commands (group).cli/commands/ci_cmd.py:49
bernstein chaosChaos engineering (group).cli/commands/chaos_cmd.py:33
bernstein evalEvaluation pipelines (group).cli/commands/eval_benchmark_cmd.py:426
bernstein benchmarkBenchmark pipelines (group). Deprecated alias until v4.0.0: use bernstein eval.cli/commands/eval_benchmark_cmd.py:29
bernstein impactChange-impact analysis (group): API compatibility, caller sites, blast radius.cli/commands/impact_cmd.py:23
bernstein api-checkDetect breaking-API changes. Second spelling of bernstein impact api.cli/commands/api_check_cmd.py:22
bernstein dep-impactDeprecated alias of bernstein impact deps; removed in v4.0.0.cli/commands/impact_cmd.py:39
bernstein blast-radiusDeprecated alias of bernstein impact blast; removed in v4.0.0.cli/commands/impact_cmd.py:57
bernstein diffTask-state diff.cli/diff_cmd.py:504

bernstein verify

Group: verifies integrity and reproducibility artefacts. It does not run lint / test / type-check quality gates; use bernstein test and the project's configured quality gates for that.

SubcommandPurpose
run RUN_IDBuild the signed run receipt for a run (--workdir, --output, signing-key options).
receipt RECEIPT_PATHVerify a run receipt offline (--public-key, --require-provenance, --json).
ladder RECEIPT_HASHRe-derive and verify a verifier-ladder receipt (--workdir).
legacy [WHEELHOUSE_PATH]The pre-receipt checks: --wal-integrity RUN_ID, --determinism RUN_ID (gated by --expect / --baseline), --memory-audit, --formal TASK_ID, or a positional wheelhouse path for air-gap signature verification.

bernstein autofix

SubcommandPurpose
startStart the autofix daemon (watches PRs, repairs CI failures). --repo, --config, --foreground, --once.
stopStop the daemon. --timeout.
statusShow daemon status + recent activity. --watch, --json, --limit.
attachAttach to the running daemon's activity feed. --limit.
ladderSingle-shot escalation-ladder run against one failing PR. --pr, --repo, --dry-run.
reviewRespond to review findings on a PR. --pr, --repo, --poll-seconds, --once.
review-register / review-resolveRegister / resolve review-finding state.

See cli/commands/autofix_cmd.py:172+ for the full flag list.

bernstein ci

SubcommandPurpose
fixOne-shot fix of a specific failing GitHub Actions run.
watch REPOWatch a repo for CI failures and auto-create fix tasks.

Common flags: --token (env: GITHUB_TOKEN), --server, --interval. (cli/commands/ci_cmd.py:49+.)

bernstein chaos

SubcommandPurpose
agent-killKill a random or specific agent.
file-removeDelete files matching a glob.
statusShow recent chaos events.
sloSLO impact of recent chaos events.

agent-kill accepts --agent-id, file-remove accepts --pattern, and status accepts --limit. (cli/commands/chaos_cmd.py:33+.)

bernstein eval

Group: evaluation pipelines. The subcommands carry the flags; the group itself only accepts the reliability options listed below.

SubcommandPurpose
run SPECDrive the golden harness or a YAML eval spec (--tier, --compare, --save/--no-save, --output).
swe-benchSWE-bench runner (--subset, --sample, --instance, --dataset, --save/--no-save).
programbenchProgramBench runner (--adapter, --subset, --tasks, --task, --dataset, --out).
simulateReplay the standard benchmark task set (--tasks-dir, --seed, --task-id, --baseline).
compareCompare eval runs (--tasks-dir, --mode).
goldenRun the curated golden suite (--workdir).
gate / gate-verifyStatistical promotion gate and its receipt verification.
receiptEmit / verify eval receipts.

bernstein eval run is the typical command for SWE-bench-style evaluations; bernstein eval swe-bench and bernstein eval golden cover the harness and the curated golden suite. See cli/commands/eval_benchmark_cmd.py:127+ and :426+.

bernstein eval additionally accepts group-level reliability options โ€” a pass^k alias for bench run --reliability that cannot be combined with an eval subcommand:

FlagDefaultMeaning
--reliability KnoneRun each suite task K times under fixed coordination; emit a signed pass^k reliability receipt.
--suite NAMEgolden-v1Suite name or .json path (--reliability mode only).
--out PATHreliability.jsonOutput path for the reliability receipt.
--scheduler NAMEdefaultScheduler name embedded in the receipt.
--stub-signeroffStub signer instead of the install identity (testing).

Verification stays on bernstein bench reliability-verify / bernstein bench reliability-check. (cli/commands/eval_benchmark_cmd.py:800+.)

bernstein benchmark (deprecated)

bernstein benchmark is a deprecated alias for bernstein eval and prints a warning on stderr before running; it keeps every subcommand it carried and is removed in v4.0.0. The group itself takes no flags โ€” including the reliability options above, which are eval-only. Every subcommand name is reachable under eval before the removal:

DeprecatedCanonicalNotes
benchmark runeval runDifferent command. eval run drives the golden harness or a YAML eval spec (positional SPEC, --output, --compare, tiers smoke/standard/stretch/adversarial); benchmark run drives the evolution benchmark tree (--benchmarks-dir, tiers smoke/capability/stretch). --benchmarks-dir has no eval equivalent.
benchmark swe-bencheval swe-benchSame runner and same options; benchmark swe-bench --lite is itself a deprecated alias, so migrate it to eval swe-bench --subset lite.
benchmark programbencheval programbenchSame command object.
benchmark compareeval compareSame command object.
benchmark simulateeval simulateSame command object.
benchmark receipt emit/verifyeval receipt emit/verifySame command object.

One capability does not survive the rename: bernstein benchmark run --benchmarks-dir DIR runs the evolution benchmark tree and eval run cannot. Until that option is ported onto an eval command, bernstein benchmark run is the only spelling for it, and v4.0.0 should not unregister the alias without porting it first. tests/unit/test_fold_benchmark_subcommands.py declares the list of alias-only options and fails if it widens or if a declared replacement stops being accepted, so this note cannot silently go stale.

eval simulate is not the top-level bernstein simulate. The top-level command is a digital-twin simulation of a plan against historical traces (--plan, --from-traces, --traces-dir); eval simulate replays the standard benchmark task set for throughput, cost and quality (--tasks-dir, --task-id, --baseline). They share a verb and no options, and the top-level command is unaffected by this change. bernstein bench is a separate command and is not folded in.

bernstein impact

Change-impact analysis for a working tree. Three subcommands, each answering a different question about the same change.

bernstein impact api --base main     # do the changed files break their own signatures?
bernstein impact deps --base main    # which callers elsewhere in the repo break?
bernstein impact blast score --file src/db/migrate.py   # how irreversible is it?

bernstein impact api

Compares Python function signatures between the working tree and a base ref. Exits 1 when breaking changes are found.

FlagDefaultMeaning
--base REFHEAD~1Git ref to compare the working tree against.
--workdir PATHcurrent directoryRepository to inspect.

bernstein impact deps

Finds every call site in the repository that the changed signatures break.

FlagDefaultMeaning
--base REFHEAD~1Git ref to compare the working tree against.
--workdir PATHcurrent directoryRepository to inspect.
--strictoffExit 1 on any call-site impact, even without an API break.
--jsonoffEmit the report as JSON on stdout.

bernstein impact blast

Group. score scores a change described on the command line; show TASK_ID pretty-prints a saved report from .sdd/metrics/blast_radius/.

bernstein api-check

Second spelling of bernstein impact api. Same flags, same exit codes.

FlagDefaultMeaning
--base REFHEAD~1Git ref to compare the working tree against.
--workdir PATHcurrent directoryRepository to inspect.

bernstein dep-impact

Deprecated alias of bernstein impact deps, kept registered through the 3.x line and removed in v4.0.0. Prints a deprecation notice to stderr, then runs bernstein impact deps with the arguments it was given, so --json output on stdout stays parseable.

FlagDefaultMeaning
--base REFHEAD~1Git ref to compare the working tree against.
--workdir PATHcurrent directoryRepository to inspect.
--strictoffExit 1 on any call-site impact, even without an API break.
--jsonoffEmit the report as JSON on stdout.

bernstein blast-radius

Deprecated alias of bernstein impact blast, kept registered through the 3.x line and removed in v4.0.0. Exposes the same score and show subcommands and prints a deprecation notice to stderr before running them.

bernstein diff

Show the diff an agent produced for a task, resolved from its live worktree, its merged branch, or the merge commit.

FlagDefaultMeaning
TASK_IDrequired unless --compareTask whose agent diff to show.
--base REVmainBase branch to diff against.
--workdir PATH.Project root.
--statoffShow the --stat summary only.
--rawoffPrint the raw diff without syntax highlighting.
--foldoffCollapse each hunk to its header plus a few lines.
--fold-lines N3Lines kept per hunk when --fold is set.
--word-diffoffHighlight only the tokens that changed on replaced lines.
--compare A BnoneSide-by-side comparison of two agents' work.

Adapters & agents

CommandPurposeSource
bernstein agentsAgent catalog ops (group).cli/commands/agents_cmd.py:22
bernstein test-adapterSpawn one adapter to verify its plumbing.cli/adapter_cmd.py:84
bernstein workerJoin a cluster as a remote worker node.cli/commands/worker_cmd.py
bernstein evolveSelf-improvement loop.cli/evolve_cmd.py:48

bernstein agents

SubcommandPurpose
listAvailable agents and capabilities (--source, --identities).
syncPull the latest agent catalog.
validateValidate the local catalog.
showcasePrint example invocations for each agent.
match--role X --task TEXT - show which agent best matches.
sandbox-backendsList available sandbox backends.
discoverAuto-detect installed CLI agents. --net also searches GitHub/npm.
trustPer-agent trust tiers from task outcomes (--agent ID adds the tier's permission profile, --as-json for machine output).

bernstein test-adapter

FlagDefaultMeaning
--adapter NAMErequiredAdapter to test (e.g. gemini, codex).
--task TEXTrequiredTask for the adapter to execute.
--model NAMEadapter defaultModel to use for the smoke run.
--timeout SEC120Wait up to N seconds for exit.

bernstein worker

FlagDefaultMeaning
--server URLrequiredCentral Bernstein task server URL (e.g. http://central:8052).
--token TOKENnoneBearer token for cluster auth.
--name NAMEhostnameWorker node name.
--slots N6Max concurrent agents on this worker.
--roles LISTbackend,qa,security,frontendComma-separated roles this worker accepts.
--label K=VnoneNode labels (repeatable: --label gpu=true --label region=us-east).
--adapter NAMEauto-detectCLI agent adapter.
--model NAMEadapter defaultDefault model for tasks that carry no explicit model.
--poll-interval SEC10Seconds between task polling cycles.
--poll-interval-ms MSnoneMilliseconds between polling cycles (overrides --poll-interval).
--heartbeat-interval-ms MS15000Milliseconds between heartbeats to the central server.
--pool NAMEnoneNamed sandbox pool to enrol into (signs an Ed25519 enrolment receipt).
--pool-hash HASHnoneExplicit pool hash to enrol against (overrides --pool name resolution).

See operations/cluster-mode.md for the full setup walkthrough.

bernstein evolve

Preview: bernstein evolve run is not a zero-workspace first-run path. In a clean directory it exits before starting the evolution loop because .sdd/ is missing. Initialise a Bernstein workspace first, then run the command from that workspace.

Group: self-evolution proposals and their review lifecycle. See Evolve CLI for the run-ledger to draft to issue contour and the dry-run flow.

SubcommandPurpose
runRun evolution cycles (--window, --max-proposals, --cycle, --dir, --github, --github-repo); reads evolve config from bernstein.yaml for flags not set. --dry-run prints the failure-pattern drafts and makes no remote writes.
reviewShow upgrade proposals pending human review (--dir).
approve PROPOSAL_IDApprove an upgrade proposal (--reviewer, --dir).
export OUTPUTExport a static evolution report, HTML or Markdown (--format, --dir).
statusShow evolution history (--dir).

Plugins & skills

CommandPurposeSource
bernstein pluginsList installed plugins.cli/commands/advanced_cmd.py:488
bernstein skillsSkill packs (group).cli/commands/skills_cmd.py:13
bernstein promptsPrompt-template management (group).cli/commands/prompts_cmd.py:36
bernstein manifestManifest mgmt (group).cli/commands/manifest_cmd.py:18
bernstein templatesProject template mgmt (group).cli/commands/templates_cmd.py:41
bernstein skillSkill usage provenance (group): install receipts + provenance graph.cli/commands/skill_cmd.py:1
bernstein security-reviewPattern-scan a diff for security issues.cli/commands/security_review_cmd.py

bernstein plugins

FlagDefaultMeaning
--workdir.Project root.
--trust-detailsoffPrint the full trust-signal breakdown for each low-trust plugin.

Lists plugins in .bernstein/plugins/<name>/meta.json with a trust tier and score derived from the plugin's own signals - signature file, packaging metadata, README, tests - so an unreviewed plugin is visible before it loads.

bernstein skills

SubcommandPurpose
listList every discoverable skill with a one-line description. --layered shows the base/team/user view.
show NAMEPrint a skill's SKILL.md body. --reference FILE / --per-layer to inspect a specific reference or the per-layer diff.
install NAMEInstall a skill from a local path.
remove NAMERemove a previously installed skill.

The skills catalog ... subgroup browses, installs, searches, and upgrades skill packs from the registry. Other subcommands include bench, diff, lint, test, sync, and watch. (cli/commands/skills_cmd.py.)

bernstein skill

Usage-attestation surface for installed skills. Each catalog install anchors a lineage receipt in the run's Merkle+HMAC spine; provenance recomputes usage from verified journal heads rather than a stored counter.

SubcommandPurpose
provenance SKILLPrint the verified runs and artifacts a skill contributed to; the verified-run count is recomputed from journal heads on every call.
verify SKILLRecompute the install receipt and flag a manifest-hash drift between the receipt and the currently installed content.

SKILL is a catalog entry id (resolved via skills.lock) or a raw content digest. (cli/commands/skill_cmd.py.)

bernstein prompts

SubcommandPurpose
listList all versioned prompts and their active versions.
show NAMEShow all versions of a prompt with their metrics.
compare NAME V1 V2Compare metrics between two prompt versions.
promote NAME VERSIONPromote a specific version to active.
ab-start NAME A BStart an A/B test between two prompt versions.
ab-stop NAMEStop an active A/B test without promoting either version.
seedSeed .sdd/prompts/ from templates/prompts/ as v1.

bernstein manifest

SubcommandPurpose
listList all available run manifests.
show RUN_IDShow the manifest for a run.
diff RUN_A RUN_BCompare two run configurations and highlight differences.

bernstein templates

SubcommandPurpose
listList available templates.
show TEMPLATE [OUTPUT]Print template content (or write to OUTPUT).
use TEMPLATE [OUTPUT]Copy TEMPLATE to OUTPUT (default plans/<name>.yaml).
compress ROLE|--allOperator-gated LLM compression of role prompt templates (cli/commands/templates_cmd.py). Rewrite via the configured adapter (--model, --provider), then mechanical validators (fenced blocks, headings, URLs, inline code, placeholders, completion-contract block; at most two targeted fix retries), then apply. Originals are stored under ~/.local/share/bernstein/template-backups/ keyed by content hash with readback verification; the receipt {role, pre_sha256, post_sha256, pre_tokens, post_tokens, validators, adapter, model} is chained to the audit log and a templates.lock row lets bernstein team drift classify the change as intentional. Prints only the template token delta; per-spawn savings come from bernstein cost grouped by role. --workdir DIR, --yes skips the confirmation.
restore ROLEReverse the most recent receipted compression byte-identically (backup hash, on-disk hash, and directory digest all verified). --workdir DIR.
hooks list / hooks useBrowse and scaffold bundled command-hook templates.

Cloud & cluster

CommandPurposeSource
bernstein cloudCloudflare cloud agent ops (group).cli/commands/cloud_cmd.py:35
bernstein workerJoin a cluster as worker (see Adapters & agents).cli/commands/worker_cmd.py
bernstein gatewayGateway mgmt (group).cli/commands/gateway_cmd.py:28
bernstein tunnelTunnel mgmt (group).cli/commands/tunnel_cmd.py:62
bernstein remoteRemote-host execution (group).cli/commands/remote_cmd.py:52
bernstein connectConnect to a remote Bernstein server.cli/commands/creds_cmd.py:95
bernstein fleetMulti-project supervision (group).cli/commands/fleet_cmd.py:50

bernstein cloud

SubcommandPurpose
loginAuthenticate with Bernstein Cloud.
logoutRemove stored cloud credentials.
run GOALRun an agent on Cloudflare Workers. --max-agents N, --model, --budget USD, --wait/--no-wait.
status [RUN_ID]Status of a cloud run.
runsRecent cloud runs. --limit N, --json.
costCloud usage and spend.
initGenerate wrangler.toml and the worker entry point. --worker-name, -o FILE. Deploy afterwards with npx wrangler deploy.

(cli/commands/cloud_cmd.py:35+.)

bernstein gateway

SubcommandPurpose
startStart the MCP gateway proxy.
replayReplay recorded MCP tool calls from a previous gateway run.

bernstein tunnel

SubcommandPurpose
startStart a tunnel exposing localhost:<PORT> publicly. --name NAME, --provider {cloudflared|ngrok|bore|tailscale}.
listList active tunnels.
stopStop a named tunnel or (with --all) every active tunnel.

(cli/commands/tunnel_cmd.py:62-117.)

bernstein remote

SubcommandPurpose
run HOSTInvoke bernstein run PATH against HOST over SSH. --user, --port, --identity-file, --remote-path.
test HOSTCheck that HOST is reachable and time the round trip.
forget HOSTRemove any cached ControlMaster sockets for HOST.

(cli/commands/remote_cmd.py:52-200.)

bernstein connect

FlagDefaultMeaning
PROVIDERrequiredProvider ID (e.g. bernstein-cloud).
Various --*-Provider-specific (see cli/commands/creds_cmd.py:95-200).

bernstein fleet

Multi-project dashboard.

SubcommandPurpose
listList instances discovered under the fleet root.
lsList configured projects without launching the dashboard.
reloadRescan the fleet root and report what would be picked up.
bulk-cost-reportRun bernstein cost against every matching project.
bulk-pause / bulk-resume / bulk-stopPause, resume, or stop every matching project.

The group also accepts --web [host:]port to run the web view instead of the TUI. (cli/commands/fleet_cmd.py:50+.)


Auth & security

CommandPurposeSource
bernstein loginLog in (alias for auth login).cli/commands/auth_cmd.py:auth_login
bernstein authAuth ops (group).cli/commands/auth_cmd.py:139
bernstein credsCredential mgmt (group).cli/commands/creds_cmd.py:214
bernstein policyPolicy mgmt (group).cli/commands/policy_cmd.py:12
bernstein complianceCompliance reports (group).cli/commands/compliance_cmd.py:26
bernstein auditAudit-log ops (group).cli/commands/audit_cmd.py:25
bernstein identityInstall-identity ops (group): fingerprint helpers, keydir, export-verifier, plus agents (the agent-principal registry projected from the chain).cli/commands/identity_cmd.py:identity_group
bernstein delegationDelegation-receipt verification (group).cli/commands/delegation_cmd.py:delegation_group
bernstein lineageArtifact-provenance lineage-spine ops (group).cli/commands/lineage_cmd.py
bernstein credentialC2PA content credentials projected from the lineage spine (group).cli/commands/credential_cmd.py
bernstein mandateVerifiable spending mandates as journal-anchored consent receipts (group): emit / verify / revoke.cli/commands/mandate_cmd.py
bernstein compactionCompaction receipt-chain ops (group).cli/commands/compaction_cmd.py:32
bernstein quarantineQuarantined-task ops (group).cli/commands/advanced_cmd.py:1120
bernstein approve-toolApprove a tool-call request (alias; flag form approve --tool <id>).cli/commands/approval_cmd.py:approve_tool_cmd
bernstein reject-toolReject a tool-call request (alias; flag form reject --tool <id>).cli/commands/approval_cmd.py:reject_tool_cmd
bernstein review-receiptAttested PR review receipts binding issue / plan / tool calls / diff (group): emit / verify.cli/commands/review_receipt_cmd.py
bernstein review-annotationContent-addressed anchors for operator review annotations (group, read-only): derive binds a comment digest to the blob hash and the target lines' digest; resolve reports the range those bytes occupy now, or exits 1 with an orphaned reason code when they are gone rather than re-anchoring to the recorded line numbers.cli/commands/review_annotation_cmd.py
bernstein receiptResult receipt bundles binding a worker submission's patch / gate logs / task ref / sandbox selection into one DSSE-signed envelope, verifiable offline (group): create / verify.cli/commands/receipt_cmd.py
bernstein volunteerVolunteer-worker surfaces for opt-in projects (group): verify validates a project's .bernstein/volunteer.json through the same loader a donor's worker uses and prints the manifest digest a receipt binds to as manifest_sha256.cli/commands/volunteer_cmd.py
bernstein gate verify <run>Verify a maker-checker / judge-panel gate's signed adjudication record: recompute inputs_hash from --inputs and confirm the panel saw exactly those inputs, then confirm the spine anchor still verifies. Exit 1 when no record, 2 on mismatch.cli/commands/gate_cmd.py
bernstein govern verify <run>Recompute every RBAC access and per-subject budget decision recorded for a run from the signed spine and confirm the recorded verdicts: re-resolve roles from the signed --bindings, re-project spend from the --ledger, and match. Exit 1 when no records, 2 on mismatch.cli/commands/governance_cmd.py
bernstein govern planGenerate a signed, lineage-bearing govern plan representing the diff between declared posture (playbook) and enumerated environment (inventory).cli/commands/governance_cmd.py
bernstein govern ingestAnchor OTLP spans reported by a runtime Bernstein did not schedule.cli/commands/governance_cmd.py
bernstein govern discoverRun governance discovery and optionally draft a playbook.cli/commands/governance_cmd.py
bernstein govern postureScore the install's governance posture from chain-evidenced facts only: per-control coverage over the lineage log, no configuration read. Names every contributing chain event, the weights version, and its own denominator (the weight that was measurable). Signed with the audit-chain key; --json-output prints the canonical document.cli/commands/governance_cmd.py
bernstein govern inventory --renderEmit the inventory topology graph from a store as mermaid or dot. Same store, same bytes.cli/commands/govern_cmd.py
bernstein govern reconcileDiff the adapter / lane / schedule / capability surface against a desired-state document and record it.cli/commands/govern_cmd.py
bernstein governance ...Deprecated alias for bernstein govern, removed in v4.0.0 (#5010).cli/commands/governance_cmd.py
bernstein poolNamed sandbox pool ops (group): register, list, show, verify. Projected from audit chain. Distinct from bernstein limits pool.cli/commands/pool_cmd.py
bernstein limitsLease-backed admission and concurrency limits (group): pool, tag, rate, queue, status, verify. Projected from admission ledger. Distinct from bernstein pool.cli/commands/limits_cmd.py
bernstein admissionExecutor admission policy declared in bernstein.yaml (group, read-only): check evaluates the executor identity each configured role would spawn on and prints the decision plus the deciding rule id without spawning. Distinct from bernstein limits, which governs slot concurrency rather than which executors are permitted at all.cli/commands/admission_cmd.py

Task-level approve / reject are different commands - see Plan & tasks. Both also accept --tool <id> to resolve tool-call approvals (the flag form of approve-tool / reject-tool).

bernstein identity

SubcommandPurpose
showPrint the install-rev fingerprint token.
decode TOKENConfirm a token came from a real install (shape + sentinel check).
verify TOKEN [--nonce HEX]Full HMAC-strength verify when the operator holds the install nonce.
keydirPrint the install-identity key directory (JWKS) used to verify outbound HTTP Message Signatures. Mirrors /.well-known/http-message-signatures-directory.
export-verifier [--target local|server] [--dry-run]Write the install-identity JWKS to a per-platform verifier file (local: ~/.config/bernstein/verifier/local.json; server: ~/.config/bernstein/verifier/server.json). Writes the canonical JSON and a .json.sha256 sidecar; skips the write when the hash is unchanged.
disablePrint the env line that suppresses every fingerprint emit site.
agentsList the agent principals the grant and delegation chains establish: derived SPIFFE ID, the capability ceiling in force at --as-of, the grants issued to each, the delegations each made, and the chain events behind every entry. --root DIR, --json, --trust-domain + --install-key for id derivation. --verify FILE recomputes a stored projection from the chain and refuses any entry no chain event establishes (exit 0 verified, 2 mismatch). Read-only.

Outbound agent-facing requests (A2A card fetch, browser/research rendering) carry an RFC 9421 Ed25519 signature keyed to the install-identity thumbprint. BERNSTEIN_HTTP_SIGNING_REQUIRED=1 turns an unsigned outbound path into a hard error. BERNSTEIN_AGENT_CARD_KEY_DIR overrides the key directory location.

identity agents is a projection, not a directory: deleting the rendered output and rebuilding it from the same chain at the same --as-of instant reproduces identical bytes, and a run whose chain does not verify contributes no principals at all.

bernstein delegation

SubcommandPurpose
verify RUN [--root DIR] [--json]Reconstruct the principal -> orchestrator -> sub-agent chain for a run from HMAC-chained per-hop receipts and confirm it is intact; exits non-zero on tamper, deleted hop, or a missing chain.

bernstein login

FlagDefaultMeaning
--server URLenv BERNSTEIN_SERVER_URL or localhostServer URL.
--ssooffOpen browser automatically for SSO.

(cli/commands/auth_cmd.py:145-146.)

bernstein auth

SubcommandPurpose
loginSame as bernstein login.
logoutRevoke the current session and clear the cached token.
statusShow current authentication status.
dashboard-tokenScoped dashboard credentials (group): issue / list / revoke. See Dashboard authentication.

bernstein creds

SubcommandPurpose
listList stored credentials.
revoke PROVIDERRemove a credential locally and call the provider's revoke endpoint.
test PROVIDERRe-validate a stored credential against the provider's whoami.

(cli/commands/creds_cmd.py:214-282.)

bernstein policy

SubcommandPurpose
checkRun YAML / Rego policies against the current repository diff.

bernstein compliance

SubcommandPurpose
listList available compliance policies.
enable / disableActivate or deactivate a compliance framework policy set.
checkEvaluate compliance policies against the current runtime.
assessRun the EU AI Act compliance assessment.
eu-ai-actShow the current EU AI Act task-risk summary.
reportPrint the EU AI Act compliance report from an existing assessment.
packBuild a one-command EU AI Act Article 12 evidence bundle.
regoExport OPA / Rego rule files for a compliance framework.

(cli/commands/compliance_cmd.py:26+.)

bernstein audit

SubcommandPurpose
showShow recent audit log events. --limit N.
verifyVerify audit log integrity. --merkle-only, --hmac-only.
sealCompute a Merkle root across all audit log files and store the seal.
export PERIODExport evidence for a period. --output DIR, --dir WORKDIR. Tenant-scoped slice via --tenant.
sliceWrite a deterministic JSONL subset between two HMAC anchors. --from, --to, -o PATH.
queryQuery audit events. --event-type, --actor, --since, --limit.

(cli/commands/audit_cmd.py:25+. The slice verb is the deterministic-subset extractor described in HMAC-chained audit log.)

bernstein lineage

SubcommandPurpose
verify RUN_IDVerify the run's lineage spine: recompute the full Merkle hash chain and every HMAC tag, print the head hash. --workdir DIR. Exit 0 = OK, 1 = no entries / seal-only (chain intact but no produced-artifact provenance), 2 = tamper.
replay RUN_IDWalk the run's spine entries in append order (artifact, actor, step, model, content hash, entry hash). --workdir DIR, --limit N. Exit 1 on an empty run.

Every adapter artifact write is recorded, without per-adapter opt-in, as one Merkle-chained, HMAC-tagged entry in the run's lineage spine under .sdd/lineage/<run_id>/spine.jsonl (head hash in spine.head). The head hash is the run's artifact-provenance identity. Recording is gated by BERNSTEIN_LINEAGE_ENABLED (default on); when enabled it fails closed, so a write that cannot be recorded raises rather than dropping provenance. verify against an empty run reports a distinct NO ENTRIES status instead of passing trivially. (cli/commands/lineage_cmd.py, core/lineage/spine.py.)

bernstein credential

SubcommandPurpose
emit ARTIFACT --run-id RUN_IDProject the artifact's lineage-spine subtree into a signed C2PA 2.2 manifest and write <artifact>.c2pa.json. --workdir DIR, --json. Exit 0 = written, 1 = no lineage / bad input.
verify ARTIFACTConfirm the manifest's hard-binding hash matches the artifact bytes and the signature chains to the install identity. --workdir DIR, --manifest PATH. Exit 0 = OK, 1 = bad input, 2 = verification failed.

The manifest is a deterministic projection of the artifact's lineage entries: a hard-binding assertion (c2pa.hash.data) carries the spine entry's content hash and an actions assertion (c2pa.actions) records the producing model and actor. It is signed with the install-identity Ed25519 key, so one attestation root covers both who ran the artifact and what was produced. With no lineage entry for the artifact there is nothing to project, so emit fails rather than fabricating an unsigned label. Watermark and fingerprint soft-binding layers are pluggable via c2pa.soft-binding. Two replays of the same run produce byte-identical manifests. (cli/commands/credential_cmd.py, core/lineage/c2pa.py.)

bernstein compaction

SubcommandPurpose
logPrint a task's compaction receipt chain. --task ID (required), --audit-dir, --sdd-dir, --json, --verify.

Every context compaction (proactive threshold or reactive overflow recovery) is recorded as a compaction.receipt event in the HMAC-chained audit log and as a step in the worker's replay journal. log prints those receipts (trigger, token delta, validator verdicts, retry count, pre/post SHA-256). --verify re-runs the receipt verification: the HMAC chain must verify and every journaled compaction step must have a chain receipt with matching hashes; the command exits non-zero otherwise.

(cli/commands/compaction_cmd.py:32+.)

bernstein quarantine

Reads and writes .sdd/runtime/quarantine.json, the cross-run quarantine the orchestrator maintains, so neither subcommand needs a running task server.

SubcommandPurpose
listList active quarantine entries. --all includes expired ones, --workdir PATH selects the project root.
clearClear entries. --task TITLE clears one, --confirm skips the prompt.

(cli/commands/advanced_cmd.py.)

bernstein security-review

Pattern-scans a unified diff without calling a model. Exit 0 clean or advisory-only, 1 on any critical/high finding, 2 when there is no diff.

FlagDefaultMeaning
TASK_IDnoneScan the diff one agent produced for that task.
--workdir PATH.Project root.
--base REVmainBase revision when scanning the working tree.
--diff-file PATHnoneScan a saved diff; - reads stdin.
--as-jsonoffEmit findings as JSON.
--fail-on-anyoffExit non-zero on any finding, not just critical/high.

bernstein pool

Define and govern named sandbox pools projected from the HMAC audit chain.

SubcommandPurpose
register SPEC_FILERegister or update a sandbox pool from a JSON manifest spec file. --workdir DIR, --json.
listList active sandbox pools projected from the audit chain. --workdir DIR, --json.
show NAMEShow canonical manifest and hash for an active sandbox pool. --workdir DIR.
verifyVerify sandbox pool bodies in the content-addressed store and placement receipts offline. --workdir DIR.

Deliberate distinction (#3138): bernstein pool defines and verifies execution sandbox environments (backends, capability ceilings, egress classes, templates) projected from the HMAC audit chain (.sdd/audit/) and content-addressed store (.sdd/sandbox/). It is distinct from bernstein limits pool, which manages admission slot concurrency in the hash-chained admission work ledger (.sdd/admission/).

bernstein limits

Named resource pools with lease-backed admission (verify, status, CRUD) projected from the admission work ledger.

SubcommandPurpose
pool create NAMECreate or update a named admission slot pool (e.g. staging-env --slots 1). --slots N, --posture {enforce|advise|off}, --workdir DIR, --json.
tag set TAGSet concurrency ceiling over a task tag (--limit 0 quarantines). --limit N, --posture {enforce|advise|off}, --workdir DIR, --json.
rate set NAMEDefine a fleet-wide named rate limit with adaptive decay. --base-limit N, --floor N, --posture {enforce|advise|off}, --workdir DIR, --json.
queue create NAMECreate or update an operator-defined named queue. --priority N, --workdir DIR, --json.
queue pause NAMEPause or resume a named queue. --resume, --workdir DIR, --json.
statusShow projected admission state (pools, tags, rates, queues, active grants, waivers, quarantines). --workdir DIR, --json.
verifyRecompute admission state from genesis over the admission ledger and fail closed on drift. --workdir DIR, --json.

Deliberate distinction (#3138): bernstein limits pool manages lease-backed concurrency slot pools in the admission work ledger (.sdd/admission/). It is distinct from bernstein pool, which defines sandbox execution environments in the HMAC audit chain.

bernstein admission

Check the executor admission policy declared in bernstein.yaml without spawning anything. The gate itself runs inside the spawner, so without this command an operator only learns a role is refused when a run reaches it.

SubcommandPurpose
checkDerive one executor identity per configured role from the config alone, evaluate each against the declared policy, and print ROLE ADAPTER MODEL ENDPOINT SANDBOX DECISION RULE. Exits 1 when any row is refused, so it doubles as a CI check that a config change did not make a role unspawnable. --workdir DIR, --role NAME, --json, plus --adapter / --model / --endpoint / --sandbox / --task-type to evaluate a hypothetical subject.

A config with no admission: block reports that no policy is declared and exits 0. See Executor admission policy for the rule model and a worked example.

bernstein approve-tool / bernstein reject-tool

Tool-call approval gate. When an agent requests a sensitive tool call (network egress, file write outside its worktree, exec outside its sandbox), the orchestrator pauses and writes a request to .sdd/runtime/tool_approvals/. Resolve with these commands.

bernstein approve-tool --id <request_id>
bernstein reject-tool  --id <request_id>
# Flag form (the aliases above stay registered through the 3.10 line,
# unregistered in 4.0.0):
bernstein approve --tool <request_id>
bernstein reject --tool <request_id>

With no identifier, the oldest pending approval is resolved.


Cost & tokens

CommandPurposeSource
bernstein costSpend breakdown by model / task.cli/commands/cost.py:540
bernstein cost profile-reportContent-addressed per-profile cost report, appended to the audit chain.cli/commands/cost.py
bernstein cost policy preflightSurface pool exhaustion before a run starts; exits non-zero when a capped pool is (or would be) exhausted.cli/commands/cost.py
bernstein cost policy verify DECISION_HASHVerify a sealed dispatch receipt offline against the lineage spine.cli/commands/cost.py
bernstein cost estimateEstimate cost before running.cli/commands/cost.py
bernstein cost envelopes showPer-quota-envelope cost attribution.cli/commands/cost.py
bernstein estimateDeprecated alias of bernstein cost estimate; removed in v4.0.0.cli/commands/cost.py
bernstein cost-envelopesDeprecated alias of bernstein cost envelopes; removed in v4.0.0.cli/commands/cost.py

bernstein cost

FlagDefaultMeaning
--last {1h|24h|7d|30d}noneTime range window.
--since ANCHORnoneAnchor for --last (e.g. today, yesterday).
--by {agent|model|task|day|role|feature_label|envelope|profile}modelGroup-by dimension. profile groups by response-style profile; tasks whose profile changed mid-run appear as an explicit excluded bucket.
--ledger PATH.sdd/cost/ledger.jsonlRolling spend ledger (used when --by is role|feature_label|profile).
--metrics-dir DIR.sdd/metricsDirectory containing metrics JSONL files.
--jsonoffEmit JSON.
--shareoffPrint only the shareable summary snippet.

bernstein cost profile-report

FlagDefaultMeaning
--last {1h|24h|7d|30d}whole ledgerLedger window.
--ledger PATH.sdd/cost/ledger.jsonlSpend ledger to compute from.
--metrics-dir DIR.sdd/metricsMetrics JSONL files for the quality-outcome join.
--transitions PATH.sdd/cost/profile_transitions.jsonlProfile-transition event records.
--audit-dir DIR.sdd/auditAudit chain the report event is appended to.
--reports-dir DIR.sdd/reports/cost_profilesWhere the content-addressed report artifact is written.
--eval-ab-dir DIR.sdd/reports/eval_abEval A/B artifacts; cross-profile claims link the latest one per pair.
--jsonoffEmit JSON.

Emits per-profile tasks / output tokens / USD / mean tokens per task plus joined verification pass rates. The artifact is canonical JSON named by its own SHA-256, embeds the ledger line-hash range it was computed from, and is appended to the audit chain, so anyone holding the ledger can recompute it byte-identically. Cross-profile savings are only claimed when both profiles have at least 5 tasks with the same role and model; otherwise the report states "insufficient comparable runs".

bernstein cost estimate

FlagDefaultMeaning
GOALrequiredTask description to estimate (positional).
--role ROLEnoneAgent role for the task.
--scope {small|medium|large}noneTask scope.
--complexity {low|medium|high}noneTask complexity.
--metrics-dir DIR.sdd/metricsDirectory containing historical metrics.

bernstein cost policy preflight

Cost-aware scheduling (issue #2354). Projects the spend ledger into named pools, compares each against its configured cap plus the planned run spend, and exits non-zero when any capped pool is (or would be) exhausted -- so pool exhaustion stops a run at the gate, not halfway through. Also reports the shipped price-table staleness advisory.

FlagDefaultMeaning
--ledger PATH.sdd/cost/ledger.jsonlRolling spend ledger to project.
--config PATHbernstein.yamlConfig holding cost_policy.pools caps.
--plan SPECnonePlanned per-pool spend, e.g. api=2.50,subscription=0.
--jsonoffEmit JSON.

bernstein cost policy verify DECISION_HASH

Re-derives the decision hash from the stored dispatch receipt (catching a forged admit / zeroed overrun) and re-checks the lineage-spine anchor. A receipt that no longer recomputes fails exactly like a tampered chain entry.

FlagDefaultMeaning
--workdir DIR.Project root holding .sdd/cost/dispatch receipts and .sdd/lineage.
--jsonoffEmit JSON.

Maintenance & debug

CommandPurposeSource
bernstein cleanupClean worktrees / logs.cli/maintenance_cmd.py:162
bernstein gcReclaim storage held by durable stores (group).cli/commands/gc_cmd.py:gc_group
bernstein daemonsystemd / launchd unit (group).cli/commands/daemon_cmd.py:76
bernstein drDisaster recovery (group).cli/commands/disaster_recovery_cmd.py:12
bernstein debug bundleBug-report bundle.cli/debug_bundle.py:bundle_cmd
bernstein debug-bundleDeprecated, removed in v4.0.0. A separate, older builder -- not a rename of debug bundle.cli/commands/debug_cmd.py:debug_cmd
bernstein doctorSelf-diagnostics.cli/doctor_cmd.py:281
bernstein selfProvenance-verified update lifecycle (group).cli/commands/self_update_cmd.py:self_group
bernstein self-updateCompatibility alias for bernstein self.cli/commands/self_update_cmd.py:self_update_cmd
bernstein man-pagesMan-page generator.cli/man_page.py:man_pages_cmd
bernstein completionsShell completion script.cli/commands/completions_cmd.py:14
bernstein config-pathShow config path.cli/config_path_cmd.py:54
bernstein configConfig mgmt (group).cli/workspace_cmd.py:180
bernstein workspaceWorkspace mgmt (group).cli/workspace_cmd.py:30
bernstein sessionSession mgmt (group).cli/session_cmd.py:27
bernstein memoryMemory store (group).cli/commands/memory_cmd.py:19
bernstein cachePrompt-cache mgmt (group).cli/commands/cache_cmd.py:45
bernstein notifyOutbound notification drivers (group).cli/commands/notify_cmd.py:63
bernstein triggersTrigger sources (group).cli/commands/triggers_cmd.py:17
bernstein issue-to-pr trace --repo OWNER/NAME NPrint the read-only issue-to-PR pipeline state snapshot.cli/commands/issue_to_pr_cmd.py:trace_cmd

bernstein gc cas

Mark-and-sweep of the content-addressed store. Referenced digests are collected from the durable roots -- the write-ahead log, snapshots, audit seals, lineage records and the backlog -- so a blob reachable from any of them survives regardless of its age. Exits non-zero if the sweep fails.

FlagDefaultMeaning
--workdir PATHcurrent directoryRoot directory containing .sdd/.
--days Nconfigured retention windowDelete unreferenced blobs older than N days; 0 deletes immediately.
--dry-runoffReport what would be deleted without modifying the store.
--yesoffSkip the confirmation prompt.

bernstein doctor

FlagDefaultMeaning
--jsonoffEmit raw JSON.
--fixoffAttempt to auto-fix issues.
--suggest-docsoffPrint the top curated documentation gaps and exit.
--failover-drilloffExercise every declared provider fallback chain; exit non-zero on any broken chain.
--endpoint URLnoneCertify an OpenAI-compatible endpoint; see Endpoint certification.
--endpoint-model NAMEfirst /models entryModel id to certify.
--endpoint-engine NAMEnoneRuntime label recorded in the receipt (e.g. ollama, lmstudio, mlx).
--endpoint-api-key-env NAMEnoneName of the env var holding the endpoint's API key (never the key itself).
--endpoint-timeout SEC60Per-probe response budget; exceeding it fails the probe.
--role NAMElow-stakes local tierRole(s) to evaluate against --endpoint (repeatable).

(cli/commands/advanced_cmd.py:536-550 re-exposes cli/status_cmd.py:doctor.)

bernstein debug bundle

FlagDefaultMeaning
--task IDnoneFilter traces/metrics by task.
--run IDnoneFilter traces/metrics by run.
--last / --no-last--lastSelect the most recent run.
--out FILEtimestamped file in CWDOutput zip path.
--manifest-onlyoffPrint the manifest JSON instead of writing a ZIP.
--include-source-snippets N0Include the N most-recently-changed src/ files.

bernstein debug-bundle (deprecated)

The older, separate builder. Removed in v4.0.0; bernstein debug bundle does not accept these flags.

FlagDefaultMeaning
--yes / -yoffSkip the confirmation prompt.
--output PATH / -otimestamped fileOutput zip path.
--extendedoffInclude full (untruncated) logs. No equivalent in debug bundle.

bernstein self

SubcommandPurpose
check-updateVerify the signed release feed offline and seal a chain-anchored advisory.
updateInstall the verified candidate; refuses mid-run, verifies the wheel hash first. --override-pin crosses a signed pin.
pin VERSION / unpinSigned version pin the updater will not cross unless explicitly overridden.
rollbackReturn to the previous receipted version.

See Updates: check, verify, apply.

bernstein self-update

FlagDefaultMeaning
--checkoffSame as bernstein self check-update.
--rollbackoffSame as bernstein self rollback.
--yes, -yoffSkip the confirmation prompt.

bernstein completions

FlagDefaultMeaning
--shell {bash|zsh|fish}bashTarget shell.
eval "$(bernstein completions --shell bash)"
bernstein completions --shell zsh > ~/.zsh/completion/_bernstein

bernstein config

SubcommandPurpose
listList all config keys with their effective values and sources.
get KEYShow the effective value for KEY and its source.
set KEY VALUEUpdate a config value.
diffShow settings that differ from defaults.
conflictsShow settings where multiple sources define conflicting values.
view-modeSet the dashboard detail level (novice, standard, expert).
validateValidate project configuration.

bernstein workspace

SubcommandPurpose
cloneClone all missing repos defined in the workspace.
validateCheck workspace health: all repos exist and are valid git checkouts.

For worktree lifecycle (inspection / reaping) use the bernstein worktrees group below.

bernstein worktrees

SubcommandPurpose
listTabular dump of every worktree, with its classified state.
gcReap orphan worktrees. --dry to preview, --yes to skip the prompt.
unlockRelease a stale GC lock left by an interrupted run.
graphRender one fan-out's sealed run graph, branch by branch (below).
bernstein worktrees graph

Render one fan-out's sealed run graph, branch by branch, from the receipt under .sdd/run-graph/.

Argument / flagPurpose
FANOUT_IDThe receipt hash, or any unique prefix of it. An ambiguous prefix lists its candidates rather than choosing one.
--run-id SESSION=RUNPair a branch's session id with the run whose spine recorded it. Repeatable.
--verifyRe-derive the whole receipt and report the verdict. Needs --public-key.
--jsonEmit the signed receipt verbatim and nothing else.
--public-key FILEPEM public key the receipt was signed with.
--workdir DIRECTORYProject root holding .sdd (default: the current directory).

Exits non-zero when a branch's spine no longer verifies, or when --verify refuses the receipt. A branch with no --run-id is reported as unresolved, not as failing: it was not checked, so it did not fail.

bernstein session

SubcommandPurpose
listList all recorded sessions, newest first.
show NAMEShow full details of a recorded session.
forkFork a recorded session into a sibling git worktree.
replayReplay a recorded session for deterministic reproducibility.

bernstein memory

SubcommandPurpose
listList stored memories.
add CONTENTAdd a persistent memory entry.
remove IDRemove a memory entry by id.
share KEY VALUE --tag TAGPublish a cross-task fact.
query --tag TAGList published facts (redacted by default).
verify --scope SCOPE --namespace NSProve every fact in a scope/namespace chain was written by its actor and never edited; recomputes the hash chain, every HMAC tag, and each source_hash anchor against the lineage spine. Exit 0 = OK, 1 = no entries, 2 = tamper.
why FACT --scope SCOPE --namespace NSReturn the originating run id and step for a stored fact (only when its source_hash resolves to a real lineage-spine entry).
forget ENTRY_HASH --scope SCOPE --namespace NSAppend a signed tombstone for a memory-chain entry without deleting it; the original entry and chain stay verifiable.
show --scope SCOPE --namespace NSPrint what a scope/namespace currently says: every live claim in append order with the run, step, actor and entry_hash it came from. --json emits the canonical fold bytes, which are byte-identical across readers. Exit 0 = live claims, 1 = nothing live.

bernstein cache

SubcommandPurpose
listList cached task-result entries. --workdir, --limit, --json.
inspect TASK_IDInspect the cached result produced by a specific task. --workdir, --json.
actionInspect / replay the action-level LLM cache.
clearClear response-cache entries. --workdir, --unverified, --yes.

(cli/commands/cache_cmd.py:45-146.)

bernstein notify

SubcommandPurpose
listList configured sinks from bernstein.yaml.
testFire a synthetic event end-to-end through --sink.

(cli/commands/notify_cmd.py:63+.)

bernstein triggers

SubcommandPurpose
listShow all configured triggers and their status. -n LIMIT.
fire NAMEManually fire a trigger by name (for testing).
historyShow the recent trigger fire log.

bernstein dr

Disaster recovery; see operations/disaster-recovery.md.

SubcommandPurpose
backupBackup persistent .sdd/ state to a file.
restoreRestore .sdd/ state from a backup file.

bernstein daemon

systemd / launchd unit installer.

SubcommandPurpose
installInstall the unit. --user / --system, --command, --env, --force.
uninstallRemove the unit.
statusShow daemon status.
start / stop / restartControl daemon lifecycle.

(cli/commands/daemon_cmd.py:76+.)

bernstein man-pages

FlagDefaultMeaning
--output-dir DIRdocs/manDirectory to write man page files into.

bernstein config-path

Print the path Bernstein would read config from. Useful for shell completion and CI. No flags.


Integration & MCP

CommandPurposeSource
bernstein mcpMCP server (transport, port).cli/mcp_cmd.py:29
bernstein mcp catalogMCP catalog (group).cli/commands/mcp_catalog_cmd.py:130
bernstein chatChat-control bridges (group).cli/commands/chat_cmd.py:54
bernstein hooksHook mgmt (group).cli/commands/hooks_cmd.py:35
bernstein github setupGitHub integration setup.cli/commands/advanced_cmd.py:1056
bernstein github test-webhookTest webhook config.cli/commands/advanced_cmd.py:1065
bernstein prGitHub PR ops.cli/commands/pr_cmd.py:183
bernstein review-responderPR review responder daemon (group).cli/commands/review_responder_cmd.py:46
bernstein previewSandboxed dev-server with public tunnel (group).cli/commands/preview_cmd.py:46

bernstein mcp

The root MCP command - runs Bernstein as an MCP server itself.

FlagDefaultMeaning
--transport {stdio|http}stdioMCP transport.
--port N8053HTTP port (when --transport http).
--host HOST127.0.0.1Bind host.
--server-url URLhttp://localhost:8052Upstream Bernstein server.
--mcp-tier {core|standard|all}unsetTool tier to advertise (context-budget knob); overrides BERNSTEIN_MCP_TOOL_TIER, and the effective default is standard.

bernstein mcp catalog

See reference/mcp-catalog.md for the full reference.

bernstein chat

SubcommandPurpose
serveRun the chat bridge until Ctrl-C. --platform {telegram|discord|slack|teams}, --token, --allow.
statusPrint active chat<->session bindings.
logoutDrop cached bindings for PLATFORM.

bernstein hooks

SubcommandPurpose
listPrint registered hooks for each lifecycle event.
run EVENTFire EVENT with an empty context (useful for smoke-testing).
checkValidate hook-config syntax and script availability.
dry-run EVENTFire EVENT with a synthetic payload to see what fires.

bernstein pr

The title names the commit that changed the most under src/; merge, [WIP], style:/chore:, formatter and lint-repair commits and generated-context-file syncs are excluded, so a run that ends with upkeep is still titled after the change it made. The body is composed from the linked issue's problem statement, the files the diff touches and the gates that ran, and carries a Provenance block naming the diff hash and the run's journal head; bernstein review-receipt verify recomputes both and rejects a description whose diff has since changed.

FlagDefaultMeaning
--session-id IDmost recent completed sessionSession to publish.
--base BRANCHmainBase branch for the pull request.
--issue N|URLnoneLink the PR to a GitHub issue: the issue's problem statement opens the body, Closes #N links it, and its title names the PR when the run left only housekeeping commits. Reads the issue, so --dry-run makes that one request.
--title TEXTthe dominant commit's subjectOverride the PR title.
--body TEXTgenerated from the diffOverride the PR body. Closes #N is still prepended with --issue.
--draftoffOpen as a draft PR.
--dry-runoffPrint the would-be title and body without calling gh. Reads the issue when --issue is given.
--no-pushoffSkip git push; assume the branch is already on origin.

(cli/commands/pr_cmd.py:183-220.)

bernstein review-responder

SubcommandPurpose
startStart the review-responder daemon. --repo, --tunnel, --port, --quiet-window, --cost-cap, --foreground.
statusShow daemon status. --pr.
tickSingle-shot poll-and-respond cycle. --repo, --pr.

bernstein preview

SubcommandPurpose
startStart a preview server in the current task's worktree. --cwd, --command, --provider, --auth, --expire, --no-clipboard.
listList active previews. --json.
status IDShow a preview's URL and process. --json.
stop [ID]Stop one preview. --all stops every active preview.

(cli/commands/preview_cmd.py:46-220.)


Misc

CommandPurposeSource
bernstein explain CONCEPTConcept explainer.cli/explain_help_cmd.py:171
bernstein help-allComprehensive help screen.cli/commands/advanced_cmd.py:378
bernstein aliasesShow CLI aliases.cli/aliases.py
bernstein fingerprintReplay verification (group).cli/fingerprint_cmd.py:37
bernstein graphDependency graph (group).cli/graph_cmd.py:19
bernstein profileTask profiling.cli/profile_cmd.py:73
bernstein evolveSelf-improvement loop (see Adapters & agents).cli/evolve_cmd.py:48
bernstein changelogChangelog from runs (group: bare = agent-produced diffs, conventional subcommand = from conventional commits).cli/changelog_cmd.py:405
bernstein run-changelogDeprecated alias for bernstein changelog (removed in a later release).cli/changelog_cmd.py:533
bernstein checkpointSave progress (see Run & control).cli/commands/checkpoint_cmd.py:49
bernstein listenVoice control (experimental).cli/commands/voice_cmd.py
bernstein install-hooksInstall git hooks.cli/commands/advanced_cmd.py:448
bernstein ab-testA/B model comparison.cli/commands/ab_test_cmd.py:14
bernstein acp serveRun an ACP server.cli/commands/acp_cmd.py:33
bernstein scaffold "<prompt>"Bootstrap a project from a prompt.cli/commands/scaffold_cmd.py
bernstein testRun automated resilience tests.cli/commands/test_cmd.py:13
bernstein wiki buildRender WIKI.md from the AST symbol graph.cli/commands/wiki_cmd.py
bernstein workflowWorkflow mgmt (group).cli/workflow_cmd.py:15
bernstein replay RUN_ID --verify / --from-step NRecompute the run journal's Merkle head and report the first divergent step (writes divergence_report.json), or rebuild deterministic state to step N.cli/commands/advanced_cmd.py
bernstein thread verify --run <id>Prove the live event stream equals the run journal: recompute the journal's Merkle chain and confirm every streamed event carries the byte-identical entry hash. --json for machine output. Exit 1 on divergence, 2 when the run journal is missing.cli/commands/thread_cmd.py
bernstein webhook verify <event_id>Verify an audited webhook node's signed receipts: recompute the inbound event hash and the outbound result hash against the run journal, re-check both Ed25519 signatures offline, and re-anchor both receipts against the webhook-node lineage spine. Exit 1 when no receipt / no outbound yet, 2 on tamper.cli/commands/webhook_cmd.py
bernstein escalation show <id>Print the operator projection of a stall escalation receipt: stall reason, deterministic recommended action, resume fork point, and spine anchor. --json for machine output. Exit 1 when no receipt matches the id.cli/commands/escalation_cmd.py
bernstein escalation verify <id>Reconstruct the trailing failure window from the run journal, walk the journal's Merkle chain, and confirm every bound entry hash matches the receipt (plus the Ed25519 signature and spine anchor). Exit 0 verified, 1 no receipt, 2 mismatch (a tampered journal entry inside the window).cli/commands/escalation_cmd.py
bernstein schedule show <id> --at <time> / bernstein schedule verifyProject a recurring fire onto a canonical task graph. show --at <epoch-or-ISO8601> prints the deterministic graph hash the schedule would dispatch at that instant without firing (no journal, receipt, or last_fire_at mutation). verify replays every recorded fire and confirms its graph hash reproduces byte-identically from (schedule, fire_time, state); --json for machine output, exit 1 on any mismatch. RFC-5545 RRULE and cron are both accepted; a webhook / file-change trigger binds its event as an input hash.cli/commands/schedule_cmd.py
bernstein schedule routine export|provision|register|bindingsBridge a scenario to an external Routine session and back (bernstein routine is a deprecated alias, removed in 4.0.0). See routine scenarios.cli/commands/routine_cmd.py
bernstein activity verify <run>Re-verify every typed activity boundary crossing anchored in a run's canonical event journal. Confirms the journal's Merkle chain is intact, recomputes each activity's evidence_set_hash from its pinned observation hashes, and reattaches the evidence bytes from the run's content store (when present), re-checking each content hash. Works across modalities (research, browser/computer-use, data, ops, coding). --json for machine output. Exit 0 verified, 1 no run / no activity, 2 mismatch (a tampered journal entry or a divergent stored blob).cli/commands/activity_cmd.py
bernstein interop a2a verify-thread --from-thread <task-uuid>Prove a cross-agent A2A thread equals the executed actions: for the task uuid, recompute every signed message receipt binding {message_hash, peer_card_fingerprint, task_uuid, journal_entry_hash}, re-check each Ed25519 signature offline, verify the message-receipt lineage spine, re-anchor each receipt against it, and confirm every message hash is referenced by the seeded per-task journal. --json for machine output. Exit 0 verified, 1 on no thread / mismatch (a tampered receipt, spine, or journal).cli/commands/interop_cmd.py
bernstein a2a verify --receipt <file> --response <file>Verify an inbound A2A response against its lineage receipt, offline. Recomputes content_hash over the canonical response bytes and checks the Ed25519 head signature over the receipt binding {schema_version, task_id, artefact_path, content_hash, entry_hash, operator_hmac, kid}. --trusted-jwk <file> pins the signing key instead of trusting the embedded one; --json for machine output. Exit 0 verified, 1 on a tampered answer, a rewritten receipt field, or a missing signature (an unattested answer is treated as unverified, not trusted).cli/commands/a2a_cmd.py
bernstein a2a publish --endpoint <url>Emit agent-registry records advertising this node's signed capability card. Each record embeds the full signed card plus an ed25519/<fp> publisher fingerprint so a consumer verifies the claim against the node's own key. --surface a2a-card|mcp-registry|agntcy-ads (repeatable) selects surfaces; the default emits a2a-card and mcp-registry, while agntcy-ads is opt-in and emits an OASF capability descriptor (a deterministic projection of the card pinned to a stated OASF schema version) with Sigstore provenance signed by a distinct provenance key. --card <file> reuses a persisted card so republishing keeps one identity, --output-dir <dir> sets the destination. Output is deterministic: republishing an unchanged node rewrites identical bytes.cli/commands/a2a_cmd.py
bernstein evidence show <task>Render the sealed verification evidence bundle for a task: gate verdict, bundle hash, spine anchor, and a per-producer table (kind, required/advisory, pass/fail, exit code, stored size, content hash). -w/--workdir sets the project root. Exit 0 when a bundle exists, 1 when there is none.cli/commands/evidence_cmd.py
bernstein evidence verify <task>Recompute a task's evidence bundle offline: check the Ed25519 signature over the canonical binding, verify the evidence lineage spine and the bundle's spine anchor, and re-hash every stored evidence blob (plus each media item's C2PA content credential) against the sealed manifest. Exit 0 verified, 1 no bundle, 2 mismatch (a tampered evidence file, bundle, or spine). bernstein audit verify runs the same check across every bundle.cli/commands/evidence_cmd.py
bernstein ledger verify <run>Walk a run's durable work ledger (.sdd/runtime/ledger/<run-id>/) and recompute every entry hash against the canonical-JSON contract. A tampered entry is named at its exact position (entry <seq> (line <n>)). --expected-head HASH additionally pins the tail. --json for machine output. Exit 0 verified, 1 no ledger, 2 mismatch.cli/commands/ledger_cmd.py
bernstein ledger anchor <run>Verify the run's chain, then publish it -- chunked, with a deterministic tree identity -- to refs/bernstein/work-ledger/<run-id> and mirror the anchor into the HMAC audit chain as a work_ledger.anchor event. Re-anchoring an extended chain adds a child commit; an identical chain is idempotent. Exit 0 anchored, 1 no ledger, 2 broken chain or git refusal, 3 the anchored chain diverges from the local one.cli/commands/ledger_cmd.py
bernstein ledger fetch <run>Pull the anchored ledger ref from a remote (default origin) after a clone and materialize it into .sdd/runtime/ledger/<run-id>/. Verifies the anchored chain end to end before writing; an existing local chain is only ever fast-forwarded -- a diverged pair is refused with the exact fork entry named. Exit 0 materialized, 1 no anchored ledger on the remote, 2 broken anchored chain, 3 divergence.cli/commands/ledger_cmd.py
bernstein ledger resume <run>Resume a run from its work ledger on any clone: verify the chain end to end, rebuild scheduler state by deterministic replay (completed / in-flight / scheduled / failed tasks), record the resume as a new chain entry, and write one resume signal per frontier task for the resume watcher. --dry-run prints the plan without recording anything; --json for machine output. Exit 0 resumed, 1 no ledger, 2 verification failed (exact entry position reported), 3 two divergent resumes detected and refused.cli/commands/ledger_cmd.py
bernstein ledger runsList runs with an anchored work ledger in this repository. --json for machine output.cli/commands/ledger_cmd.py
bernstein ledger gc <run>Squash the run's anchor history to a single commit, preserving the current anchored tree byte for byte. Superseded chunk blobs become unreachable so a normal git gc reclaims them -- the repo-bloat bound for long runs. Exit 0 done, 1 no anchored ledger.cli/commands/ledger_cmd.py
bernstein seal publish <run>Anchor the run's sealed journal head to an RFC 3161 timestamping authority, so the head carries an external witness of when it existed. Refuses a run whose journal chain does not verify or whose recomputed head disagrees with the seal in its lineage spine. --tsa-url <url> requests a token (the only option that opens a socket); --token <file> stores a DER reply obtained on another host, for installs with no network. The reply is written to .sdd/runs/<run>/seal_anchor.json. Exit 0 anchored, 1 nothing to anchor / refused.cli/commands/seal_cmd.py
bernstein seal verify <run>Re-check a stored anchor offline: recompute the journal head, confirm the anchor witnesses exactly that head, then chain the timestamp token to TSA roots supplied with --rfc3161-trusted-tsa-bundle <file> and confirm its messageImprint covers the head. Never contacts the TSA. --json for machine output. Exit 0 verified; 1 for mismatched (the head moved since anchoring), invalid (the token failed to chain), unverifiable (no trust bundle), or no anchor at all.cli/commands/seal_cmd.py
bernstein run-service submit <goal> --task <id>...Open a detached run: seed the work ledger (run.open + one task.scheduled per --task), persist the run descriptor (goal digest, never the goal text), and sign a submitted lifecycle receipt into the HMAC audit chain. By default spawns a session-detached supervisor that survives the terminal; --foreground advances the run in-process; --per-task-delay makes off-terminal progress observable; --json for machine output. --backend ssh runs each task off-host on the ssh backend in its own isolated remote git worktree (one branch per task) and signs a run.ssh_task receipt binding that worktree; pass --ssh-host and --ssh-path (absolute remote dir), optionally --ssh-user/--ssh-port/--ssh-identity, --ssh-repo to git-worktree from with --ssh-base-branch, and --ssh-secret ENV=PROVIDER (repeatable) to inject a vault credential into the remote env resolved from the vault only, never the ledger or the receipts.cli/commands/run_service_cmd.py
bernstein run-service attach <run>Reattach from any shell: prove the current ledger head is a forward extension of the head last seen (the reattach artefact is that continuity proof), record a reattached receipt, and render the live projection (completed / in-flight / scheduled tasks). --json for machine output. Exit 0 continuous, 1 no such run, 3 continuity broken (the ledger diverged or failed to verify).cli/commands/run_service_cmd.py
bernstein run-service status [<run>]Show supervisor liveness plus the ledger projection for a run; with no run id, list every run in the project. --json for machine output. Exit 1 when the named run does not exist.cli/commands/run_service_cmd.py
bernstein run-service stop <run>Stop the run's supervisor process (SIGTERM then SIGKILL after a grace window) and record a detached boundary receipt so a later attach can prove continuity. --json for machine output. Exit 1 when the run does not exist.cli/commands/run_service_cmd.py
bernstein run-service verify <run>Re-verify offline that the HMAC audit chain is intact, the work ledger recomputes end to end, and every lifecycle receipt binds a ledger head that exists in the chain (every reattach / daemon-restart boundary is a genuine ancestor). --json for machine output. Exit 0 verified, 2 a check failed (each reason listed).cli/commands/run_service_cmd.py

bernstein ab-test

FlagDefaultMeaning
--model-a NAMErequiredFirst model.
--model-b NAMErequiredSecond model.
--task TEXTrequiredTask description handed to both models.
--role NAMEbackendAgent role.
--scope {small|medium|large}mediumTask scope.
--timeout SECONDS1800Per-model timeout.

bernstein acp serve

FlagDefaultMeaning
--stdio/--no-stdio--stdioServe over POSIX stdio (line-delimited JSON-RPC), the IDE embedding transport.
--http HOST:PORToffServe over HTTP on HOST:PORT (e.g. :8062 or 127.0.0.1:8062). Overrides --stdio when both are supplied.
--server-url URLhttp://localhost:8052URL of the running Bernstein task server.

bernstein fingerprint

SubcommandPurpose
buildBuild a local similarity index from a corpus directory.
check FILECheck generated code against the index.

(cli/commands/fingerprint_cmd.py:37+.)

bernstein graph

SubcommandPurpose
tasksRender the current task dependency graph as ASCII or Mermaid.
impact FILE_QUERYPrint downstream files impacted by changing FILE_QUERY.

bernstein govern

SubcommandPurpose
inventoryEmit the inventory topology from a store (--render mermaid or dot).

bernstein govern inventory

See govern inventory --render.

FlagDefaultMeaning
--render {mermaid|dot}requiredGraph format. Nodes and edges are sorted so the same store produces the same bytes.
--store PATHrequiredInventory graph JSON (nodes + edges).

bernstein listen

Experimental voice control (see operations/voice-control.md when published).

FlagDefaultMeaning
--model SIZEbaseWhisper model size; smaller is faster but less accurate.
--threshold RMS0.01RMS amplitude threshold distinguishing speech from silence.
--min-duration SEC0.5Minimum utterance duration before transcription.
--alias-file PATH~/.bernstein/voice.yamlVoice alias YAML file.
--dry-runoffShow the parsed command without executing.

bernstein explain

FlagDefaultMeaning
CONCEPTrequiredConcept name (e.g. cascade-router, wal, janitor).

bernstein test

Runs automated resilience tests. This is not a project test-suite runner; use bernstein.yaml: quality_gates.tests (and your configured test runner) for that.

FlagDefaultMeaning
--duration N300Test duration in seconds.
--workdir PATH.Project root.

bernstein wiki build

FlagDefaultMeaning
--repo PATHcurrent directoryRepo root to scan.
--writeoffWrite to WIKI.md at the repo root.
--output PATHunsetCustom output path; implies --write.

Renders a deterministic Markdown wiki from the AST symbol graph plus the agents.md IR. Streams to stdout by default. See Wiki build for the operator guide.

bernstein scaffold

FlagDefaultMeaning
PROMPTrequiredFree-form goal prompt.
--template NAMEautoPin a template; auto runs the keyword heuristic.
--output DIR./<slug>Destination directory.
--forceoffAllow writing into a non-empty directory.

First slice of the prompt-to-repo scaffolder. See Prompt-to-repo scaffold.


Hidden commands

Three task-related commands carry hidden=True, so they do not appear in --help. They are stable and supported, and each is registered at the top level -- not under bernstein task. The spellings below are the ones that resolve.

CommandSourceNotes
bernstein add-task TITLEcli/commands/task_cmd.py:155Declared as compose, registered top-level as add-task.
bernstein synccli/commands/task_cmd.py:337Reconciles on-disk task files with the running server. Use when you've hand-edited backlog files and want them registered without restarting.
bernstein list-taskscli/commands/task_cmd.py:776Declared as parts, registered top-level as list-tasks.

A command's declared name and its registered name differ here, so the declared spelling is not an invocation: bernstein task compose and bernstein task parts resolve to nothing. Type the names in the table.

bernstein task itself is a real group and is not hidden - it carries the durable lifecycle subcommands documented under Plan & tasks. It is only these three that are not under it, despite their declared names suggesting otherwise.

task_cmd.py also declares a notes command (_notes_legacy, cli/commands/task_cmd.py:753) that is registered nowhere and therefore cannot be invoked at all. To tail server / spawner logs, use bernstein logs.


See also


Endpoint certification: bernstein doctor --endpoint

Certify an OpenAI-compatible endpoint (a local runtime such as ollama, LM Studio, or an MLX server) for per-role use. The doctor runs a fixed conformance subset -- reachability, chat completion, tool calling, patch format fidelity, timeout behavior, context floor -- and prints a deterministic certify/reject verdict per role with machine reason codes. The result is sealed as a signed receipt under .sdd/endpoints/certifications/, anchored to the lineage spine, and mirrored into the audit chain; config validation gates merge-critical roles on it.

FlagDefaultMeaning
--endpoint URL-Base URL of the endpoint to certify (activates this mode).
--endpoint-model NAMEfirst /models entryModel id to certify.
--endpoint-engine NAMEemptyRuntime label recorded in the receipt.
--endpoint-api-key-env NAMEnoneNAME of the env var holding the endpoint key.
--endpoint-timeout SECONDS60Per-probe response budget; exceeding it fails the probe.
--role ROLElow-stakes local tierRole(s) to evaluate (repeatable).
--jsonoffMachine-readable transcript, verdicts, and receipt anchor.

Exit codes: 0 every evaluated role certified, 1 at least one role rejected, 2 no model could be resolved.

bernstein doctor --endpoint http://127.0.0.1:11434/v1 --endpoint-engine ollama
bernstein doctor --endpoint http://127.0.0.1:11434/v1 --role manager

See Local endpoints for profiles, role tiers, and the verified-configuration table.

Provider failover drill

bernstein doctor --failover-drill

FlagDefaultMeaning
--failover-drilloffExercise every fallback chain declared under provider_availability in bernstein.yaml.
--jsonoffMachine-readable drill report (for CI).

Probes every declared chain element and evaluates each chain position as the dispatch target under a simulated outage of its predecessors. Exits non-zero when any declared chain element is broken, and zero when all are healthy. Each drill row carries the deterministic routing-decision hash its simulated outage prefix would produce; drill outcomes are mirrored into the audit chain when a .sdd workspace is present. See Provider availability & failover.

Packaged agent skill: bernstein skills package

Bernstein ships a cross-vendor bernstein-run skill (open SKILL.md format) so agent sessions can drive orchestration without a separate shell. Installs are receipt-backed: each install anchors a content-addressed receipt in the skills lineage spine and mirrors a plugin.install_receipt event into the HMAC audit chain.

bernstein skills package show

Prints the bundled skill's content address, manifest hash, and the supported host list.

bernstein skills package install

FlagDefaultMeaning
--host NAME-Target host (claude, codex, copilot, cursor, gemini); selects the host's default skills directory.
--scope project|userprojectInstall under the project root or the home directory.
--dest DIR-Explicit destination directory (overrides --host/--scope).
--record-onlyoffAnchor a tree the host already installed (e.g. a plugin checkout) without copying.
--forceoffOverwrite a destination whose content differs from the bundled skill.
--workdir DIR.Project root where the receipt is anchored.

Exit codes: 0 installed and anchored, 1 error.

bernstein skills package verify

Re-hashes the installed tree and proves it against the anchored receipt: the recomputed content address selects the receipt, then the install spine and the manifest hash are checked. A tampered tree resolves to a content address with no receipt, so the verdict is structural.

Exit codes: 0 verified, 1 missing directory, 2 attestation failure.

bernstein skills package update

Supersedes a previously attested install with new content. Unlike install --force (which overwrites and anchors an independent install receipt), update binds the prior content address to the new one: the update receipt is content-addressed by the new tree, anchored in the same skills lineage spine, and mirrored into the HMAC chain as a plugin.update_receipt event. A verifier walks the update receipts newest to oldest and lands on the root install, so the supersession history of an installed tree is reconstructable offline. A tree that was never anchored is refused (run install first).

FlagDefaultMeaning
--host NAME-Target host; selects the host's default skills directory.
--scope project|userprojectUpdate under the project root or the home directory.
--dest DIR-Explicit installed directory (overrides --host/--scope).
--source DIRbundled skillTree to update to.
--workdir DIR.Project root where the receipt is anchored.

Exit codes: 0 updated or already current, 1 error (missing or unattested install).

bernstein skills package status

Scans the default skill directory for each supported host and scope, re-hashes any present tree, and proves it against its anchored install or update receipt. --json emits the per-install verdicts as JSON; --home overrides the home directory for user-scoped destinations.

Exit codes: 0 every present install verifies (or none present), 2 at least one present install failed verification.

bernstein skills package conformance

Installs the bundled skill into every selected host against one shared install, then replays the skill's documented self-check contract (skills package show, then skills package verify --dest) per host. Each host runs the contract as it would from inside its own session; the per-host pass/fail table, the shared content address, and the aggregate verdict are sealed into a content-addressed conformance receipt anchored in the lineage spine and a plugin.conformance_receipt audit-chain event.

Options: --host (repeatable; defaults to every supported host), --scope (project/user), --min-hosts (green hosts required for an overall pass; default 3), --json, --workdir.

Exit codes: 0 every host green and the --min-hosts bar met, 2 conformance failed, 1 error.

bernstein skills package image-verify

Proves, offline, that the MCP registry listing (server.json) and the Docker MCP catalog entry (packaging/docker-mcp/server.yaml) resolve to the same canonical signed ghcr.io/<owner>/bernstein image and that the registry listing pins the release version, so a host cannot pull a different (or unsigned) image than the catalog advertises. With --online it additionally runs gh attestation verify against the live Sigstore build-provenance attestation.

Options: --version (the release version the image must pin; defaults to the installed bernstein version), --online, --json, --repo-root.

Exit codes: 0 consistent (and, with --online, attestation verified or tooling unavailable), 2 a manifest mismatch or a failed online attestation.

bernstein skills package install --host claude --scope project
bernstein skills package install --dest ~/.claude/plugins/bernstein --record-only
bernstein skills package verify --host claude --scope project
bernstein skills package update --host claude --scope project
bernstein skills package status
bernstein skills package conformance --host claude --host codex --host cursor

See Agent sessions for the skill body, per-host notes, and the registry listings generated at release time.

Dashboard authentication: bernstein auth dashboard-token

The dashboard (bernstein gui serve, /dashboard on the task server) accepts two credential kinds: a password (BERNSTEIN_DASHBOARD_PASSWORD or the dashboard_auth block in bernstein.yaml) and scoped tokens issued here. Tokens carry a principal and a scope: viewer reads every surface and can change nothing; operator can also trigger state-changing actions.

Grants live in an append-only journal of HMAC-signed rows (.sdd/auth/dashboard_tokens.jsonl) that stores only the token's SHA-256 digest - the raw token is printed once at issue time. Editing a row (for example widening viewer to operator) breaks its signature and the token stops validating. Every issue and revoke is mirrored onto the audit chain (dashboard.token_grant), and every login and write authorization is a signed governance decision in the dashboard-auth lineage run - recompute them offline with bernstein governance verify dashboard-auth.

SubcommandPurpose
issue --principal NAME [--scope viewer|operator]Issue a token (printed once, digest journaled).
listShow journal rows: id, kind, principal, scope. Never prints tokens.
revoke TOKEN_IDAppend a signed revocation; the token stops validating immediately.

All subcommands accept --workdir (default .) pointing at the project root containing .sdd/.

bernstein auth dashboard-token issue --principal alice --scope viewer
bernstein auth dashboard-token list
bernstein auth dashboard-token revoke 3f1a9c2d5e7b0a41
bernstein governance verify dashboard-auth

Startup posture: bernstein gui serve on a loopback host without any credential configured issues an operator token and prints it once; on a non-loopback host it refuses to start until a token or password is configured. There is no silent open mode on a routable interface. Use the token as Authorization: Bearer <token> or in the dashboard login form (POST /dashboard/auth/login); the session cookie inherits exactly the token's principal and scope.

SPIFFE workload identity: bernstein spiffe

Infrastructure teams standardizing on SPIFFE workload identity can consume Bernstein workloads directly. The Ed25519 install identity and each agent card map onto a deterministic SPIFFE ID; when a SPIRE agent is present (optional bernstein[spiffe] extra) its X.509-SVID is bound to a card by a receipt anchored in the HMAC audit chain. The self-contained Ed25519 path stays the default with the extra absent.

SPIFFE ID scheme (deterministic):

spiffe://<trust-domain>/bernstein/<install>/<agent>
  • <trust-domain>: operator SPIFFE trust domain (validated, lowercase DNS-like).
  • <install>: 16-hex fingerprint of the install public key (SHA-256 prefix).
  • <agent>: the agent card id.

Two operators deriving the id for the same install and agent obtain the same string, and a verifier re-derives it later to check a card-to-SVID binding.

SubcommandPurpose
id --install-key PEM --agent ID --trust-domain TDDerive and print the SPIFFE ID offline (pure, no network).
verify-binding BINDING.json --install-key PEM --trust-domain TD [--audit-dir DIR]Re-derive the id from the install key and verify a card-to-SVID binding; with --audit-dir, also check it against its chained spiffe.svid_binding receipt.
bernstein spiffe id \
    --install-key .bernstein/keys/agent-card.ed25519.pub \
    --agent backend-1 --trust-domain example.org
# -> spiffe://example.org/bernstein/<install>/backend-1

bernstein spiffe verify-binding binding.json \
    --install-key .bernstein/keys/agent-card.ed25519.pub \
    --trust-domain example.org --audit-dir .sdd/audit
# -> valid (chain-anchored)

The card-to-SVID binding is the receipt: bind_svid_to_card records a spiffe.svid_binding event pinning the binding content hash, the derived SPIFFE ID, the install fingerprint, the card hash, and the leaf SVID content address -- never the SVID private key. A post-hoc tamper to the binding fails verify-binding because its recomputed content hash no longer matches the chained receipt. SVID material also projects onto the cluster mTLS config, so the task server enforces mutual TLS through its existing uvicorn --ssl path. See SPIFFE workload identity for an example SPIRE configuration and threat-model notes.

In-process verification gate: bernstein hook-gate

A gate-capable adapter (Claude Code) wires its worker's PreToolUse and Stop hooks to bernstein hook-gate check. The command reads the hook event JSON on stdin, loads the task's persisted policy (.sdd/runtime/hook_gate/<session>.json, written at spawn from the task's owned_files and required evidence_producers), and enforces it in-session:

EventBehaviour
PreToolUseA write whose target is outside the task's path allowlist is refused; the refusal is sealed as a gate receipt and the command exits 2 so the tool call never runs. Realpath containment refuses a .. traversal or an in-scope symlink that resolves outside the worktree.
StopThe task's required verification producers run in-session; the attempt is sealed as a proof-of-done receipt and the command exits 2 when a required check failed, so the worker cannot end its turn on red.
# Invoked by the worker's hook runner, not by hand:
bernstein hook-gate check --session <id> --event PreToolUse < event.json
bernstein hook-gate check --session <id> --event Stop < event.json

Trust model: the in-process gate is defence in depth and a cost optimisation. The scheduler-side evidence gate stays authoritative and runs regardless. A gate receipt IS an evidence bundle (bernstein evidence show / verify, bernstein audit verify), so a verifier cannot tell from the schema whether the gate fired in-process or scheduler-side. An adapter with no blocking hook surface injects no gate hooks and degrades to the scheduler-side gate with no policy weakening.

bernstein tournament

Tournament runs: parallel attempts selected by deterministic evaluators (#2353).

CommandDescriptionSource
bernstein tournament show <task>Render the tournament selection receipt for a task: the winner, the attempt count, the evaluators and tie-break, the spine anchor, and a per-attempt table (rank, attempt hash, score, chosen/sibling edge). -w/--workdir sets the project root. Exit 0 when a receipt exists, 1 when there is none.cli/commands/tournament_cmd.py
bernstein tournament verify <task>Recompute a task's tournament selection offline: replay the deterministic scorer over the recorded evaluator outputs, check exactly one chosen edge over the recorded attempts, verify the Ed25519 signature over the canonical binding, verify the tournament lineage spine, and re-anchor the receipt. A tampered score or a hand-picked winner diverges from the replay and fails. Exit 0 verified, 1 no receipt, 2 mismatch. bernstein audit verify runs the same check across every receipt.cli/commands/tournament_cmd.py

Selection is a pure function of the evaluator outputs (test pass rate, lint status, coverage delta, mutation score, arbitrary commands) with a stable attempt-hash tie-break, so replaying the run reproduces the identical decision. Fan-out is gated on the task's existing per-ticket budget ceiling and aborts with a clear error before spawning when projected spend would breach the cap.