Configuration
Status: 2026-09-19. Living document.
Configure command options, provider credentials, console settings and run storage separately. Each section below gives its precedence rules.
Whole-harness execution profile
Section titled “Whole-harness execution profile”executionProfile selects the local execution boundary, not the LLM backend.
The operator-global setting is local by default for existing installations.
Choose smolvm after provisioning the online Kali workbench:
0 workbench setup --image /absolute/path/0-workbench-linux-arm64.tar \ --provider openai --provider chatgpt-codex0 workbench status --json0 consoleThe native runtime is currently qualified for Apple Silicon macOS. Setup
downloads and verifies the pinned signed SmolVM bundle, preserving its runtime
layout, and approves a digest-pinned local image archive. An initial image is an
explicit operator choice (--image); an archive discovered in a checkout or a
mutable registry tag is never silently trusted. Re-running setup and normal
launches resolve the saved approved image automatically.
Approved archives are limited to 8 GiB for both the main guest and broker
siblings. This compressed-archive ceiling is separate from guest storage.
| Setup option | Default | Effect |
|---|---|---|
--image <archive> | saved approved image | Explicit local OCI/Docker archive approval |
--state <directory> | ~/.0/workbench | Private runtime, image approval, guest state and admission |
--workspace <directory> | invocation’s current directory | Selected host workspace mounted at guest /workspace |
--provider <id> | no host provider grants | Repeat to grant selected provider accounts; list IDs with workbench providers |
--github / --no-github | not granted | Explicit token grant from GH_TOKEN, GITHUB_TOKEN, or existing gh authentication |
--cpus <count> | 2 | Virtual CPUs |
--memory <MiB> | 4096 | Guest RAM |
--storage <GiB> | 20 | VM-owned writable storage |
--sandbox-image <reference=archive> | no additional images | Repeat to approve a full repository@sha256:<64hex> identity for isolated container actions |
Operator choices live in the private, owner-only ~/.0/workbench.json; credential
values are not persisted there or displayed by status. Granted provider values
are resolved only when launching. Ungranted accounts, host HOME, SSH authority,
Docker sockets and unrelated environment variables are not forwarded. You may
authenticate a provider directly inside the guest instead.
Guest preferences preserve the more restrictive of saved sharing consent and
explicit environment policy. DO_NOT_TRACK and ZERO_NO_TELEMETRY keep analytics
and problem reports off without disabling ordinary workbench networking.
Reporting endpoints, account/API authority and unrelated environment values are
not copied into guest configuration.
Guest 0 receives the original argument array and stdin/stdout/stderr, with its
working directory at /workspace and private HOME at /home/zero. Use paths
relative to the selected workspace. The whole console, child agents and tools
execute in that guest. Networking is online by default. An explicitly enabled
ZERO_OFFLINE starts it without networking and keeps analytics/problem reports
off; workbench status shows the effective mode. This does not widen the
separate offline evolution/sandbox policy or substitute an offline sandbox for
the online workbench profile.
Broker siblings copy their bounded source snapshot into fresh, guest-owned
/tmp/0-workspace scratch and return verified artifacts from there. They never
receive the main guest’s writable /workspace mount or provider credentials.
Container/reproduction actions that request another image use an explicit operator-owned catalog, not a guest-selected archive or registry pull:
0 workbench configure --sandbox-image \ 'registry.example/security/runner@sha256:<64hex>=/absolute/path/runner.tar'0 workbench configure --clear-sandbox-imagesThe operator asserts that this immutable OCI identity corresponds to that local archive. Setup also digest-pins the archive bytes, a distinct digest from the OCI identity. Only the approved reference and archive digest enter guest admission; host archive paths and environment authority stay host-side. Unknown explicit references are refused. Adding an image grant does not enable mutable tags, nested Docker/KVM, host sockets or unrestricted code execution in the credential-bearing console guest.
Setup and status also show the isolated-action broker’s concrete hard ceilings: 4 MiB workspace/source, 256 files, 1 MiB stdin, 1 MiB output, 2 simultaneous jobs, 256 requests per workbench lifetime, 600 seconds, 2 CPUs and 2048 MiB RAM. These are separate from the outer workbench’s resource options. A workflow’s larger source/output limit does not raise this transport boundary; oversized inputs are refused rather than silently falling back to another execution backend.
0 workbench configure --provider openai,anthropic --no-github replaces grants;
--provider none revokes host provider grants. --current-workspace removes a
fixed workspace choice. 0 workbench status is read-only and never provisions or
downloads. Runtime, image, admission or cleanup failures refuse execution rather
than falling back to host or Docker. Retained admission remains visible in
status. A subsequent launch recovers it only under the native admission lock
with successful cleanup proof; missing or failed proof still refuses launch.
0 workbench disable is an explicit return to the local profile; it retains
the approved image and guest state.
A configured workbench requires an explicit valid operator execution profile.
Missing or malformed profile settings refuse launch instead of resetting the
choice to host-local. Use 0 workbench setup or 0 workbench disable to repair
that selection explicitly; ordinary display settings retain their normal
defaulting behavior.
The host workbench and config management commands stay available to repair
configuration. Project settings cannot select, disable or override this
operator-owned execution boundary. Changing the settings-screen profile takes
effect at the next process launch and does not retroactively isolate a running
host session.
Runtime modes
Section titled “Runtime modes”--runtime selects the LLM backend.
| Runtime | Flag | Description |
|---|---|---|
api | --runtime api | Direct HTTP calls to a configured provider. |
claude | --runtime claude | Spawns the authenticated Claude Code CLI; capabilities depend on the workflow and installed CLI. |
codex | --runtime codex | Uses the Codex CLI for source review. For live target scans, routes to the direct ChatGPT Codex provider when ZERO_CHATGPT_OAUTH_REFRESH_TOKEN is configured. |
gemini | --runtime gemini | Spawns the authenticated Gemini CLI for source-oriented work. |
auto | --runtime auto | Resolve an available runtime for the selected workflow. Default for scan, review, and audit. |
ollama | --runtime ollama | Local Ollama /api/chat runtime, exposed by review; requires an available tool-calling model. |
API runtime
Section titled “API runtime”The api runtime makes direct HTTP calls to a provider. Set one of:
# API-key providers can be exported normally.export OPENROUTER_API_KEY="sk-or-..."export ANTHROPIC_API_KEY="sk-ant-..."export AZURE_OPENAI_API_KEY="..."export OPENAI_API_KEY="sk-..."export DEEPSEEK_API_KEY="..."export Z_AI_API_KEY="..."export KIMI_API_KEY="..."export QWEN_API_KEY="..."export XAI_API_KEY="..."export OPENCODE_API_KEY="..."export CLINE_API_KEY="..."
# `ZERO_*` names begin with a digit; pass a Codex token with env.env ZERO_CHATGPT_OAUTH_REFRESH_TOKEN="..." 0 doctorSee API Keys for the full provider list, default models, and credential priority.
For Azure, configure an explicit endpoint and deployment. Ambient API routing
can also read an Azure-backed ~/.codex/config.toml; explicit provider pinning
and fallback routes require an environment endpoint. For the Responses API,
include /openai/v1. See Azure setup
for precedence and a complete pinned example.
For ChatGPT Codex, run codex login, then either rely on
~/.codex/auth.json or supply an explicit access/refresh token with env.
Codex auth leads the ambient API credential order, but an explicit provider pin
or recognized model with its own configured provider can override it.
Use --runtime api when you specifically want these HTTP provider rules rather
than workflow-dependent auto selection. Model selection is not runtime
selection: --model alone does not require auto to choose the API runtime.
CLI runtimes (claude, codex, gemini)
Section titled “CLI runtimes (claude, codex, gemini)”These spawn the respective CLI as a subprocess — install and authenticate it first:
# Claude Code CLInpm i -g @anthropic-ai/claude-code
# Codex CLInpm i -g @openai/codex
# Gemini CLInpm i -g @google/gemini-cliThen use them:
0 scan --target https://api.example.com/chat --scope ./scope.json --runtime claude0 review ./my-repo --runtime codex --depth deepThe Codex CLI isn’t used as a live-target wrapper. For live scans on a Codex subscription, configure the direct provider instead:
env ZERO_CHATGPT_OAUTH_REFRESH_TOKEN="..." \ 0 scan --target https://example.com --scope ./scope.json --runtime codexCodex runtime parity matrix
Section titled “Codex runtime parity matrix”Codex routing depends on the entry point and credentials. Source review can use the authenticated CLI; live-target subscription calls use the direct provider.
| Surface | Command | Supported via direct provider |
|---|---|---|
| Web / URL scan | 0 scan --target https://example.com --scope ./scope.json --runtime codex | yes |
| npm package audit | 0 audit lodash --ecosystem npm --runtime codex | yes |
| PyPI package audit | 0 audit requests --ecosystem pypi --runtime codex | yes |
| crates.io package audit | 0 audit tokio --ecosystem cargo --runtime codex | yes |
| OCI image audit | 0 audit nginx:1.25 --ecosystem oci --runtime codex | yes |
| Default source-code review | 0 review ./repo --runtime codex | yes |
| Linux kernel review | 0 review ./linux --profile linux-kernel --runtime codex | yes |
| C/C++ library review | 0 review ./lib --profile c-library --runtime codex | yes |
Managed runtime availability follows the separate 0cloud deployment policy.
Local Ollama source review
Section titled “Local Ollama source review”Start your Ollama server and provision a tool-calling model before running:
OLLAMA_HOST=http://localhost:11434 \ 0 review ./authorized-repo --runtime ollama --model gemma4:27bThe runtime uses --model, then ZERO_OLLAMA_MODEL, then gemma4:27b.
OLLAMA_HOST defaults to http://localhost:11434. A remote host sends source
context to that server; a local model is not a guarantee that every tool or
optional integration stays offline.
Scan modes
Section titled “Scan modes”--mode controls what kind of target is scanned.
| Mode | Description |
|---|---|
deep | Agentic LLM/AI-target probing; select explicitly for an HTTP endpoint that should not use web mode. |
probe | Lightweight surface scan — recon and fingerprinting without deep exploitation. |
web | Shell-first web application assessment. The automatic mode for HTTP/HTTPS targets passed to scan. |
mcp | Scan MCP (Model Context Protocol) servers for tool poisoning and schema abuse. Default when the target starts with mcp://. |
http_audit | Worker-driven authenticated HTTP assessment using operator-provided ZERO_TARGET_* configuration. |
# LLM API assessment: select deep mode explicitly.0 scan --target https://api.example.com/chat --scope ./scope.json --mode deep
# Web application assessment.0 scan --target https://example.com --scope ./scope.json --mode webDepth settings
Section titled “Depth settings”--depth controls how thorough the scan is.
| Depth | Use |
|---|---|
quick | Shorter investigation budget |
default | Normal workflow budget |
deep | Larger investigation budget |
These are not fixed test-case counts or guaranteed completion times. See Budget Management for the budget mechanisms.
0 scan --target https://api.example.com/chat --scope ./scope.json --mode deep --depth quick0 audit express --depth deep0 review ./my-repo --depth deep --runtime claudeOutput formats
Section titled “Output formats”Set with --format:
| Format | Description |
|---|---|
terminal | Human-readable terminal summary |
html | Rich browser report saved to a temporary file |
pdf | Printable report saved to a temporary file |
json | Machine-readable JSON output for pipelines |
sarif | SARIF format for the GitHub Security tab |
md / markdown | Human-readable Markdown report (md is the CLI alias) |
For GitHub Code Scanning, run the CLI with --format sarif and upload the
result with github/codeql-action/upload-sarif. A dedicated 0 composite
action has not shipped; use the complete GitHub CI workflow.
Diff-aware review
Section titled “Diff-aware review”Review only changed files against a base branch — handy in CI to skip scanning the whole codebase on every PR:
0 review ./my-repo --diff-base origin/main --changed-onlyVerbose output
Section titled “Verbose output”--verbose shows detailed agent output:
0 scan --target https://api.example.com/chat --scope ./scope.json --verboseOperational logs
Section titled “Operational logs”Enable metadata-only operational records on stderr:
env ZERO_LOG_FORMAT=json 0 review ./my-repoEach NDJSON record contains timestamp, level, service, event, and
allowlisted lifecycle or cost metadata. Prompts, responses, reasoning, tool
arguments/results, finding evidence, summaries and raw error text are excluded
from these records. Credential-like values in retained identifiers are redacted.
This adds records alongside existing stderr diagnostics; it does not make all
stderr output JSON or replace --format. Stdout and the ZERO_EVENT_* cloud
relay protocol are unchanged. Unset ZERO_LOG_FORMAT to disable the sink;
only the json format enables it. These operational log records are not uploaded
automatically; collect stderr through your runner or container logging pipeline.
Analytics and training data
Section titled “Analytics and training data”Analytics sharing is opt-in and starts at off. Optional /onboard setup
and /settings → Data sharing offer only off and usage. Skipping setup
does not grant consent or change a saved choice. Saved legacy commands and
full console choices migrate to usage; an existing opt-out remains off.
| Choice | Collected records |
|---|---|
off | No analytics uploads |
usage | Feature/finding counters, finite error categories, turns, duration and available cost totals; no tool arguments/results, code, scope or finding content |
The preference is operator-global; project settings cannot broaden it.
An explicit ZERO_ANALYTICS_LEVEL can restrict it. ZERO_OFFLINE,
ZERO_NO_TELEMETRY, or DO_NOT_TRACK forces analytics off when set to a
non-empty value other than 0, false, or no.
env ZERO_ANALYTICS_LEVEL=off 0 consoleenv ZERO_ANALYTICS_LEVEL=usage 0 scan https://authorized.exampleUsage goes through the configured first-party Cloud host’s
/api/cli-analytics receiver, using an explicitly supplied ZERO_CLOUD_TOKEN
with analytics:submit. ZERO_CLOUD_HOST can select an operator-provided
deployment. The CLI does not contact PostHog directly or need a PostHog key.
The Cloud receiver can export usage-only aggregates to PostHog when its
deployment provides POSTHOG_PROJECT_TOKEN and POSTHOG_CAPTURE_HOST;
vendor configuration is separate from CLI consent and credentials.
The first-party envelope includes the running CLI version and finite OS, architecture and runtime labels. Authenticated delivery and random install/session identifiers are not anonymity. The inspected Cloud vendor adapter exports allowlisted counter buckets, not tool/code content, and does not currently forward CLI release, source revision or development/production labels to PostHog. Those vendor properties require a corresponding Cloud deployment change; CLI configuration alone cannot supply them.
Consent is checked again before every POST. Lowering it discards disallowed
pending records; re-enabling does not replay those discarded records.
Post-redaction payloads attempted over HTTP are recorded in
~/.0/analytics-sent.log; that log is not proof of server acceptance.
Analytics consent does not grant automatic problem-report consent or broaden
diagnostic content. Run contributions have their own enrollment below.
Feedback delivery
Section titled “Feedback delivery”/feedback <message> is local-only and appends to ~/.0/feedback.md.
With ZERO_CLOUD_TOKEN explicitly configured, staged feedback defaults to the
configured Cloud host’s authenticated /api/cli-feedback receiver. It
attributes the message to the token’s organization and delivers through the
existing team-feedback channel. Ask the operator for a token with
feedback:submit if an older grant lacks that scope. ZERO_CLOUD_HOST can
select an agreed service host.
Use /feedback submit <message> to save locally and inspect the exact endpoint,
JSON body, headers, and secret-shaped-content warnings. Only a second
/feedback send transmits that exact staged payload; /feedback cancel drops
the pending network action while retaining the local file.
ZERO_FEEDBACK_URL overrides the cloud receiver for a self-hosted HTTPS relay:
env ZERO_FEEDBACK_URL="https://feedback.example.org/v1/feedback" 0 consoleDo not place an incoming Slack webhook URL directly in the CLI environment:
it is a bearer secret and does not accept 0’s feedback wire schema.
ZERO_OFFLINE, ZERO_NO_TELEMETRY, and DO_NOT_TRACK block every submission
before any connection is made.
Automatic problem reports
Section titled “Automatic problem reports”The console’s Problem reports setting defaults to ask. After a tool or
runtime problem, it can stage a limited diagnostic summary for review; nothing
is submitted without confirmation. Saved automatic or off choices remain
effective. This is separate from operational stderr logs and manually staged
/feedback messages.
Use /feedback → Problem-report preferences to select off, ask, or
automatic. The preference is global to this computer; project settings cannot
override it. An explicit saved opt-out remains off after upgrading.
ZERO_OFFLINE, ZERO_NO_TELEMETRY, and DO_NOT_TRACK still block submission.
With an explicitly configured ZERO_SENTRY_DSN, diagnostic reports use that
operator-provisioned CLI Sentry project’s HTTPS envelope endpoint. There is no
built-in DSN and no fallback to dashboard/server/browser Sentry configuration.
Invalid, credential-secret-bearing or non-HTTPS DSNs are refused rather than
silently rerouted. Provision a CLI project and distribute its approved DSN to
enable this destination; merely enabling Problem reports does not provision
Sentry.
When ZERO_SENTRY_DSN is absent, the existing ZERO_FEEDBACK_URL or
authenticated Cloud /api/cli-feedback route remains available. That Cloud
route delivers through first-party Slack/email feedback, not Sentry.
Ordinary manually staged /feedback messages continue to use this feedback
route even when a Sentry DSN is present.
Manual crash feedback keeps its explicit HTTPS feedback action, with recognized
credentials, authorization tokens, URL credentials, emails and home usernames
scrubbed from the note and captured crash text. This is best-effort redaction;
the always-on raw crash log remains local and is not uploaded.
Reports contain finite failure categories and bounded runtime metadata. Configured Sentry additionally receives at most 32 allowlisted built-in package-relative stack locations with line/column numbers; absolute paths, function names, arbitrary stack text, error messages and captured tool output are excluded. The full local review detail is never passed to the transport. This content policy is independent of every analytics level. Reports do not upload the feedback file, source code, credentials or enable update checks.
Sentry’s release identifies the actual running VERSION as
0-cli@<version>, with the existing embedded __ZERO_BUILD_COMMIT__ SHA appended
when available; cli_version and build_commit tags carry the same identity.
environment is development for source execution and production for
bundled releases, with an explicit NODE_ENV=development or
NODE_ENV=production taking precedence. Unknown build revisions are omitted,
not guessed from the working directory.
Without an available transport, automatic reports are saved locally and the
console reports submission as unavailable. ask and off cannot transmit a
diagnostic without individual confirmation; an explicitly saved automatic
preference permits automatic diagnostic submission after the first-report
consent flow. Hard environment opt-outs still win before any request. The
review shows the exact destination/body and redacted authentication headers;
changes to the reviewed destination or body require a new review.
Permissioned run contributions
Section titled “Permissioned run contributions”Run contributions use a separate, explicit enrollment. Analytics preferences, problem reports and service tokens don’t enroll a run.
ZERO_RUN_CONTRIBUTION_CONFIG points to an absolute, operator-owned JSON file
with private permissions (0600). It contains orgId, the authoritative
receipt, the matching policy, and an optional absolute spoolDir. Use the
configuration issued for your enrollment. A locally written receipt doesn’t
grant permission at the collector.
The client validates this configuration before capture and rechecks the receipt
before upload. The existing ZERO_OFFLINE, ZERO_NO_TELEMETRY and DO_NOT_TRACK
switches take precedence. Without valid enrollment, it creates no contribution
spool or contribution upload. Collection doesn’t change target scope or tool
authorization.
The spool defaults to run-contributions under the configured state directory.
Receipt content flags control model, tool and scope capture; redaction isn’t
anonymization. Versioned manifests and ordered transitions retain missing usage
as unknown, and interrupted attempts aren’t treated as successful runs.
Upload uses the existing Cloud credential loader and resumes from the collector’s
acknowledged chunk index. The policy and receipt bound local retention.
This is a candidate integration contract, not production enrollment or a grant of model-training, licensing or public-distribution rights.
Update checks
Section titled “Update checks”Startup behavior depends on the saved global updatePolicy:
off: no startup update request.notify: check asynchronously and report a newer release.automatic: check and, if needed, run the canonical installer before proceeding. This can delay startup; the current process keeps its running version, so restart to use the installed binary.
In an interactive terminal, updates show one status line with the current stage
and elapsed time. Reduced motion keeps the indicator still. Redirected output
stays plain text, and installer errors remain visible. Direct install.sh
downloads show a terminal progress bar.
If no global policy is saved, the built-in setting default alone does not grant
automatic installation. The compatibility path checks asynchronously only when
ZERO_UPDATE_CHECK=1. All startup paths require a TTY and honor CI,
ZERO_NO_UPDATE_CHECK and ZERO_OFFLINE (nonempty values other than 0 or
false suppress the check). Project settings cannot enable updates.
env ZERO_UPDATE_CHECK=1 0 --versionenv ZERO_NO_UPDATE_CHECK=1 0 consoleRelease checks use GitHub’s API and cache results for 24 hours. Automatic
installation downloads through the repository installer; repeated attempts for
the same tag are bounded. Windows automatic installation is unavailable.
Use /settings or the global config to set policy intentionally.
State directory
Section titled “State directory”Most per-user state is under ~/.0. Scan execution state is run-local,
while console settings and credentials are user-level. Project overrides,
Codex authentication and temporary reports have separate paths; moving one
directory does not relocate every subsystem.
Fresh scans default to ~/.0/runs/<scan-id>/state.db. --db-path overrides
ZERO_DB_PATH; ZERO_RUN_DIR controls the run directory. The legacy 0.db is
a resume fallback, not the default database for every new scan.
| Path | Purpose |
|---|---|
tui-settings.json | Console display settings (global layer). |
credentials.json | Stored API-key credentials (console credential store). |
console-sessions/ | Transcript JSON files, one per session. Owner-only (0600 file, 0700 dir). |
feedback.md | Locally staged feedback entries. |
0 config — console settings CLI
Section titled “0 config — console settings CLI”The 0 config command lets you inspect, export, and import the console
display settings without launching the TUI.
0 config show # effective config, each key labelled default/global/project0 config export # write effective config as shareable JSON to stdout0 config export ./my-settings.json0 config import ./my-settings.json # merge into global layer (default)0 config import ./my-settings.json --global # explicit global (same as default)0 config import ./my-settings.json --project # merge into project overrideConfiguration layers (precedence)
Section titled “Configuration layers (precedence)”Settings are resolved per-key, highest-priority first:
- Project —
<cwd>/.0/tui-settings.jsonoverrides individual keys. - Global —
~/.0/tui-settings.jsonis the per-user base. - Default — built-in defaults shown below.
Operator-global settings are exceptions: a project cannot override analytics, problem-report consent, update policy, onboarding state, or authorization for development-engine updates, or the whole-harness execution profile.
On load, settings are normalized against the schema: unknown keys are dropped
and invalid values reset to defaults. Saving writes the normalized object.
Persisted messenger framing migrates to bubble; new sessions default to
minimal. Other saved styles and explicit off settings remain effective.
Security-gated import
Section titled “Security-gated import”0 config import refuses to change security-sensitive settings, including
executionProfile, allowModelSelfExtension, allowDevSourceUpdates,
allowSubagentPeerMessaging and allowSubagentOperatorMessaging, unless --yes
is passed. The specific
changes are printed so you know what was rejected.
Settings reference
Section titled “Settings reference”| Key | Type | Default | Description |
|---|---|---|---|
executionProfile | local, smolvm | local | Operator-global whole-harness execution boundary; requires workbench setup before SmolVM launch |
showStatusBar | boolean | true | Bottom bar with model, working directory, git state and counters |
showComposerHints | boolean | true | Keyboard-hint line under the input |
showLogo | boolean | true | Product mark on an empty transcript |
showObjective | boolean | true | Header objective derived from the first message |
showScope | boolean | true | Header include/exclude scope; absent and explicitly empty scope remain distinct |
density | comfortable, compact | comfortable | Transcript spacing |
composerStyle | border, rail, plain | border | Input frame |
transcriptStyle | minimal, bubble, rail, plain, compact, document | minimal | Minimal transcript by default; alternative framed and document layouts |
roleLabelStyle | full, short, glyph, off | off | Speaker label treatment |
toolCardStyle | compact, rail, inline, hidden | compact | Successful tool/subagent-card treatment; failures always show |
richToolCards | boolean | true | Render shell and edit results as rich cards |
transcriptDetail | expanded, collapsed | expanded | Whether successful reasoning and tool steps are folded |
showRuntimeNotices | boolean | true | Surface runtime stdout/stderr as transcript notices |
showTurnSummary | boolean | false | Per-turn tool-call and token summary |
showSubagents | boolean | true | List active subagents while workers run |
showTimestamps | boolean | false | Relative timestamps on transcript entries |
allowSubagentPeerMessaging | boolean | true | Allow direct sibling-subagent messages |
allowSubagentOperatorMessaging | boolean | true | Allow sanitized child-to-operator transcript messages |
allowModelSelfExtension | boolean | true | Enable sandboxed model self-extension for new sessions, subject to role and capability gates |
allowDevSourceUpdates | boolean | false | Globally authorize trusted development-engine replacement between turns; requires ZERO_DEV_SOURCE_ROOT |
theme | built-in or installed theme ID | slate | Colour palette; installed themes live in ~/.0/themes |
showTokenUsage | boolean | false | Per-turn input/output token line |
showCost | boolean | false | Estimated dollar cost, per turn and in the status bar |
showContextMeter | boolean | true | Context-usage bar; missing context-window data displays unavailable |
modelDisplay | statusbar, message, off | statusbar | Where the model name appears |
logoAnimation | animation name or off | glitch | Intro or idle logo effect |
reduceMotion | boolean | false | Disable decorative animations |
Additional practical settings include composerSuggestions: true,
mouseSupport: true, busyInputMode: "steer", autoCompaction: true,
compactionThreshold: "80%", and elapsedTimer: "left". Finder-lens
autoEvolveFinderLenses and autoPromoteFinderLenses both default to false.
Operator-global analyticsLevel defaults to "off", diagnosticReporting
to "ask", and updatePolicy to "automatic". Use 0 config show
for the full effective inventory and each value’s source; see the privacy
sections above before sharing a configuration.
Self-extension and workspace trust
Section titled “Self-extension and workspace trust”Self-extension defaults on for new sessions, including the desktop checkbox.
Explicit or saved false stays off. Workspace-trusted ESM requires a separate,
acknowledged grant scoped to the canonical workspace.
Autonomy, self-extension and host trust are separate controls. Desktop retains unscoped-standard and scoped-YOLO authorization. See self-evolution for details.
Development engine updates
Section titled “Development engine updates”This is separate from sandboxed self-extension. Enable Development engine updates in global settings only for a trusted source checkout. Project settings cannot grant it. Loading that code runs with the console process’s host permissions, including credential access.
Start a development console from the current checkout:
./scripts/0dev.sh console0dev rebuilds the CLI dependency chain on launch and runs it with Bun. Build
failure stops launch; it never falls back to stale output. Provider connections
and explicit shell overrides work as they do in the normal CLI.
For frontend iteration:
./scripts/0dev.sh --watch consolePut --watch before the CLI command. It builds immutable TUI generations and
remounts the frontend on the same renderer only when every audit is safe.
Conversation, drafts, models, routes and audit state remain in memory; tools
are not replayed. Active turns, workers, approvals and authentication flows
defer activation. A rejected build or render keeps the known-good UI.
When enabled, changed Core source is built into an immutable generation and activated at an idle boundary. Conversation, scope decisions, task progress and usage survive the handoff. A build or checkpoint rejection leaves the current engine active. Disabling the setting stops later replacements; it does not revert an already-active generation.
Frontend watching is not component FastRefresh or Core engine replacement.
Startup, non-TUI CLI code, Core/shared dependencies, native integration and the
reload ABI require a full 0dev restart. Shared settings-store, output-guard and
crash services stay pinned. See development engine replacement.
Console credential store
Section titled “Console credential store”In the terminal UI, /connect offers Use my own API key and a separate
Provider subscription section. ChatGPT Codex uses device sign-in and its
own auth file. The local console does not use a Cloud account for inference.
Keys are stored in plaintext at ~/.0/credentials.json by default, with
0600 file and 0700 directory permissions. Nonblank environment credentials win.
See credential storage.
In the BYOK /model picker, Tab opens the full catalog and a nonblank query
searches it from either view. Check credentials and account access.
Treat missing price data as unknown. See Model picker.
Model and role-model selections apply to an existing audit while idle or after
its active turn finishes. A normal /connect choice prepares the next chat;
after connecting a new provider, reselect its model to apply it live. See
Model picker.
Service-directed telemetry credentials
Section titled “Service-directed telemetry credentials”If your organization opts to submit analytics
or feedback to the Cloud service, provide an
operator-issued ZERO_CLOUD_TOKEN explicitly. ZERO_CLOUD_HOST optionally
selects the operator’s deployment; the default is
https://cloud.0.security. These credentials do not configure local model
inference or authorize a managed scan. There is no standalone CLI login
command; use a provider key or subscription for the local console.
Provider selection and model routing
Section titled “Provider selection and model routing”Explicit provider pinning
Section titled “Explicit provider pinning”ZERO_SELECTED_PROVIDER selects the primary direct provider for a run or chat.
The public console offers openrouter, anthropic, openai, azure,
deepseek, chatgpt-codex, z-ai, kimi, qwen, xai, opencode,
cline, copilot, and google. Set an explicit ZERO_MODEL alongside an environment
selection. The provider must have its own credentials; a separately configured
model can use a different route for cross-model verification.
ZERO_FORCE_PROVIDER is an unconditional benchmark override. Setting it and
ZERO_SELECTED_PROVIDER to different values is an error.
env ZERO_SELECTED_PROVIDER=deepseek ZERO_MODEL=deepseek-flash \ 0 scan --target https://example.com --scope ./scope.json --mode web --runtime apiPer-model routing
Section titled “Per-model routing”When no explicit pin is set, --model <id> (or ZERO_MODEL) routes the call to
the provider whose credentials are available. The runtime maps model prefixes:
| Model prefix / identifier | Provider |
|---|---|
openrouter/* | OpenRouter |
glm-*, z-ai/*, IDs containing glm | Z.ai (GLM) |
qwen*, exact deepseek-v4-flash-0731 | Alibaba Qwen / Token Plan |
k3*, kimi* | Moonshot Kimi |
grok*, xai/*, x-ai/* | xAI Grok |
opencode/*, muse-spark*, mimo*, ling*, big-pickle, nemotron*, minimax* | OpenCode Zen |
cline/*, cline-pass/* | Cline API (Pass slugs preserved; subscription required) |
copilot/* | GitHub Copilot |
gemini*, google/* | Google Gemini Code Assist |
claude*, anthropic/*, IDs containing sonnet, opus or haiku | Anthropic, then OpenRouter when Anthropic auth is absent |
gpt-*, o1–o4 | ChatGPT Codex when configured, otherwise OpenAI |
Exact deepseek-flash, deepseek-v4-flash | Direct DeepSeek |
| Recognized Azure Foundry deployment IDs | Azure; takes precedence over family routing |
Natural-provider routing requires that provider’s credentials. If no matching credential is available, selection falls through to ambient priority; an unrecognized model is not proof of a supported route. Pin a provider to fail early rather than accidentally send a model ID to another account. Arbitrary Azure deployment names need an explicit Azure pin; pricing aliases do not configure provider routing. See API Keys for the Azure/DeepSeek identifier collision and wire protocols.
Multi-model role routing
Section titled “Multi-model role routing”The interactive console can use different models for different child-agent roles. This is not the same as provider failover, and it does not automatically enable an independent verification stage.
For a concrete multi-family setup, connect one gateway account that serves both models, then launch the console:
export OPENROUTER_API_KEY="sk-or-..."env ZERO_SELECTED_PROVIDER=openrouter \ ZERO_MODEL=anthropic/claude-sonnet-4.6 0 consoleIn /model:
- Select the parent model with Enter.
- Use Ctrl+Left/Right to target
verify(or another role), search for an account-supported model such asopenai/gpt-4o, and press Enter. - Use Ctrl+S to turn single-model policy off if it is on. When on, all role assignments are inactive and children use the parent model.
- Ctrl+Backspace clears the targeted role’s assignment so it inherits the parent again.
Role choices apply to the current audit while idle or after the active turn finishes. They affect subsequently created child runtimes, not an already running child’s in-flight request. Forked children retain the parent’s resolved provider, endpoint and credentials and do not inherit its cross-provider fallback chain. Choose models served by that same account/route; connecting another provider does not turn a role assignment into a cross-account router.
Embedded API callers can supply RuntimeConfig.agentModels, singleModel,
and autoRoute. The "auto" role sentinel or autoRoute widens the model
selection guard to credential-reachable choices, but does not change the
inherited transport boundary. The stock console has no --agent-model or
--auto-route flag. Independently constructed runtimes (for example, a workflow’s
cross-model refuter) use the per-model provider routing above instead.
Ambient credential priority
Section titled “Ambient credential priority”When no model is specified enough to route to one provider, the runtime checks env vars in this priority order:
ZERO_CHATGPT_ACCESS_TOKEN/ZERO_CHATGPT_OAUTH_REFRESH_TOKEN→ ChatGPT CodexDEEPSEEK_API_KEY→ DeepSeekOPENROUTER_API_KEY→ OpenRouterAZURE_OPENAI_API_KEY→ Azure OpenAIOPENAI_API_KEY→ OpenAIZ_AI_API_KEY→ Z.ai GLMKIMI_API_KEY→ Moonshot KimiQWEN_API_KEY→ Alibaba QwenXAI_API_KEY→ xAI GrokOPENCODE_API_KEY→ OpenCode ZenCLINE_API_KEY→ ClineZERO_COPILOT_GITHUB_TOKEN→ GitHub CopilotZERO_GEMINI_ACCESS_TOKEN/ZERO_GEMINI_OAUTH_REFRESH_TOKEN→ Google Gemini Code AssistANTHROPIC_API_KEY→ Anthropic- No usable credential → Anthropic (reports missing credentials at runtime)
Provider failover
Section titled “Provider failover”ZERO_LLM_FALLBACK configures an ordered chain of backup providers when the
primary exhausts its retry budget or hits a plan quota limit:
env ZERO_LLM_FALLBACK=deepseek:deepseek-flash,azure:gpt-5-deployment \ 0 review ./authorized-repo --runtime apiEach entry is <providerId>:<model>, comma-separated. Eligible retry-budget
exhaustion or recognized plan quota exhaustion advances to the next usable
route. Missing credentials (and missing endpoint configuration for Azure) skip
that entry. Failover changes the recipient of model context and the account
that pays; it is not a free retry or an automatic switch to a Cloud account.
Session persistence
Section titled “Session persistence”The console stores transcripts as one JSON file per session in
console-sessions/ under the state directory, so you can
close it and resume later. Files are owner-only (0600 file, 0700 dir),
filtered per working directory, capped at the 20 most recent.
A transcript is the full engagement record — every operator prompt, model reply, and tool call with its result. That means target hostnames, approved scope, untriaged findings, and raw request/response bodies, which can include cookies, bearer tokens, and anything a tool echoed.
Secrets are not scrubbed. A partial scrub over free-form output would corrupt resume evidence. Transcripts are not encrypted. Protection is filesystem permissions. Stored on local disk only.
Static analyzer selection
Section titled “Static analyzer selection”Source reviews and package source scans use Foxguard by default for pre-agent
static leads. Set ZERO_STATIC=semgrep to route them through Semgrep instead;
--changed-only narrowing works with either. Dependency advisory checks (npm audit, OSV, OCI inventory) run separately for package targets regardless.
The static runner uses foxguard from PATH when provisioned. Otherwise it
launches npx --yes [email protected], which requires Node/npm and access to the
package and release download on first use. Native v1 JSON reports and legacy
finding arrays are accepted. Launch failures, invalid reports, and scanner
error exits are surfaced as failures; the default path does not silently invoke
Semgrep or report a failed scan as clean. Exit 1 with a valid report means
findings were detected.
Scans run from the requested source root, so an explicitly selected installed
package is not skipped just because an ancestor directory is node_modules.
Finding paths are resolved back to that source root.
This pre-agent scan is separate from ZERO_FEATURE_MULTIMODAL=1, the opt-in
white-box cross-validation layer. Cross-validation and kernel variant-hunt
require an installed Foxguard binary (--foxguard can override it for
variant hunting). Static hits and scanner agreement remain leads, not proof
of exploitability.
env ZERO_STATIC=semgrep 0 review ./repo --depth quickSemgrep is required only when explicitly selected. Legacy report fields named
semgrepFindings and the SemgrepFinding type describe the existing wire shape,
not a runtime dependency. FoxGuard cross-validation remains opt-in; it does not
turn scanner agreement into independent exploit verification. The historical
ablation baseline is still unmeasured, so equal coverage or a speed advantage
over Semgrep is not established by the integration alone.
Stateful authorization and fix verification
Section titled “Stateful authorization and fix verification”Foxguard findings are static leads. Three complementary paths test authorization state changes, find incomplete application fixes, and replay a PoC with a negative control.
Stateful authorization
Section titled “Stateful authorization”The agent tool access_control_workflow observes a JSON resource as its owner,
executes up to ten ordered requests as a distinct actor, then observes it again.
It uses the existing per-identity sessions, cookie jars, scope checks, attribution,
and rate limiter without switching the active identity.
{ "allow_mutation": true, "owner_identity": "owner", "actor_identity": "other-tenant", "observation_url": "https://app.example/api/items/42", "observation_json_pointer": "/marker", "expected_state": "fresh-disposable-test-marker", "steps": [ { "method": "PATCH", "url": "https://app.example/api/items/42", "body": "{\"marker\":\"fresh-disposable-test-marker\"}" } ]}Use only disposable resources covered by the engagement. There is no automatic
cleanup or rollback. Every step is validated before requests start; actor requests
cannot override authentication headers. Both owner observations must succeed and
contain complete JSON. confirmed requires an exact string-marker transition,
not merely HTTP 2xx. An unchanged state is no_change; incomplete observations,
transport failures, or an unexpected state change are inconclusive. Choose a
unique marker to reduce ambiguity from concurrent legitimate activity.
Application incomplete-fix hunting
Section titled “Application incomplete-fix hunting”0 review ./repo --fix-commit <sha> --variants-only0 review ./repo --fix-commit <sha>--variants-only emits deterministic JSON without model calls. The second command
feeds candidates into the normal review pipeline as low-confidence SeedFinding
leads. The hunter compares the fix commit to its first parent, extracts added
authorization/validation checks, and searches current tracked working-tree files
in the affected directories for similar unguarded functions.
Extraction is heuristic for JavaScript, TypeScript, and Python—not a complete AST,
control-flow, or exploitability analysis. Other languages are explicitly skipped.
The default bound is 200 related files and 50 candidates; source files over 1 MiB
are skipped with an error entry. Guarded siblings are excluded. This is separate
from Foxguard’s kernel variant-hunt.
Reproduction bundles
Section titled “Reproduction bundles”Create a plan with exactly one of finding_path or an inline finding, explicit
source roots, and file allowlists. Finding JSON uses the same schema as verify --finding, including timestamp. Plan-relative paths resolve beside the plan.
{ "version": 1, "finding_path": "./finding.json", "vulnerable_root": "./before", "patched_root": "./after", "files": { "vulnerable": ["app.cjs"], "patched": ["app.cjs"] }, "runner": "local"}0 verify --create-bundle ./plan.json --out ./bundle0 verify --bundle ./bundle --runner local --out ./replay-resultsCreation never executes PoC steps. Replay requires an explicit runner, validates SHA-256 content, sizes, paths, and compatibility before execution, and uses fresh vulnerable/patched workspaces. Output directories must be empty. Symlinks, traversal paths, source/output overlap, and dirty output are rejected. Snapshot content is bounded to 256 MiB; plans and manifests to 4 MiB.
confirmed (exit 0) requires reproduction on the vulnerable side and a genuine
assertion failure on a successfully executed patched side. Reproduction on both
sides is inconclusive (exit 1); failure to reproduce the vulnerable side is
not_reproduced (exit 1). A crash, failed setup, timeout, or missing command is
error (exit 3), never proof of a fix. PoC processes must exit zero on both sides
and express the exploit condition through assertions. Results include both sides;
vulnerable.json, patched.json, and result.json are retained with artifacts.
Local replay executes trusted PoC code on the host. It checks the Node/engine version and platform/architecture; external tools and services remain outside the snapshot. Digests establish file integrity, while authorship requires separate review. Check bundles for secrets before execution or sharing, including source, finding metadata, and process output.
For Docker, set "runner": "docker" in the plan and provide
docker_shell_image / docker_http_image for the action types used, each as a full
repository@sha256:<64-hex-digest> reference. Docker action images must also be
digest-pinned. Replay binds the images to those references and uses the existing
Docker isolation controls; provision images locally first. HTTP replay additionally
requires --scope <scope.json> and an explicit --docker-network <name>.
Local replay supports shell actions; Docker supports shell, container, and scoped
HTTP actions. Notes are not executable bundle steps.
Shell cwd is relative to the mounted workspace; absolute paths and traversal
outside it are rejected before a container is launched.
The Docker replay CI workflow runs real containers. It covers isolation, writable workspaces, relative cwd and escape rejection, pinned-image execution, timeout cleanup, scoped HTTP, and vulnerable/patched negative controls. To run the same checks against the default local Docker daemon:
pnpm --filter @0/core... -r buildnode scripts/smoke-docker-replay.mjsThe smoke script pulls its fixture images, resolves their digests, and removes its test containers, network, and temporary workspaces afterward.
Feature flags
Section titled “Feature flags”Features is the canonical flag inventory. Do not copy a flag
from an archival experiment and assume the current engine reads it.
ZERO_FEATURE_TRIAGE_MEMORIES and ZERO_FEATURE_DEBATE are not current
standalone toggles.
Use env for names beginning with ZERO_; POSIX shells cannot export names
beginning with a digit. Enabling a capability does not supply its credentials,
scope, toolchain, or other prerequisites.
Opt-in Jev assistance
Section titled “Opt-in Jev assistance”Jev is a bounded advisory evaluator, not a chat-provider replacement. No feature
is enabled merely by having a key. ZERO_JEV_FEATURES explicitly opts selected
workflows into sending evaluation state to the selected provider:
browser, memory, dedupe, rank, specialist, redteam, kernel, crash,
radar, and foxguard (comma-separated).
Probabilities do not authorize actions, establish an exploit, or replace
deterministic verification. Unknown feature/provider names are configuration
errors.
ZERO_JEV_PROVIDER | Required credential / endpoint | Route |
|---|---|---|
vercel (default when enabled) | AI_GATEWAY_API_KEY | Vercel AI Gateway evaluation model typesafe-ai/jev, billed to your own gateway key |
cloud | ZERO_JEV_CLOUD_TOKEN and ZERO_JEV_CLOUD_URL | Your evaluation endpoint, which reaches the same upstream model and bills workspace credits; HTTPS except loopback HTTP |
Consumers are workflow-specific. Agentic scans use memory ranking, deduplication,
and final finding prioritization (rank); specialist selects methodologies only
inside native EGATS branches (scan --egats). Browser and red-team helpers have
their own entry points, as do explicit kernel, crash-triage, and radar commands.
Putting agentic-scan selectors on a source review does not add those consumers
to the source pipeline.
For example, opt only the browser helper in, through the gateway:
export AI_GATEWAY_API_KEY="..."env ZERO_JEV_FEATURES=browser ZERO_JEV_PROVIDER=vercel \ ZERO_JEV_BROWSER_READ_ONLY_URLS=https://authorized.example/docs \ 0 console --scope ./scope.jsonTo pilot finding prioritization and EGATS specialist selection after configuring
AI_GATEWAY_API_KEY:
env ZERO_JEV_FEATURES=rank,specialist ZERO_JEV_PROVIDER=vercel \ 0 scan --mode web --egats --target https://authorized.example \ --scope ./scope.jsonrank orders final canonical findings before reporting; it does not skip
investigation or verification. Scores and model provenance are recorded as
finding_priority events, separately from vulnerability confidence. Uncertain
or unavailable ranking evaluations return the complete set to the existing
generative ranker. specialist selects from existing methodologies only when
the chosen probability is at least 0.8; generic or uncertain answers remain
generic, while request failures retain the prior flag-gated regex path. This
threshold is a conservative pilot policy, not demonstrated security-domain
calibration. Each workflow shares one evaluator budget across its batches/nodes.
ZERO_JEV_BROWSER_READ_ONLY_URLS is a comma-separated list of exact normalized
URLs required for assisted navigation, in addition to explicit scope. Jev never
replaces target authorization; absent scope or approved URLs makes assistance
hand off without navigation. A normal ZERO_CLOUD_TOKEN is not automatically used
as the Jev token. See Jev budgets
for per-instance request, timeout, classification and estimated-cost limits.
Runtime resilience and retries
Section titled “Runtime resilience and retries”The runtime layers that keep a provider failure from silently corrupting a scan:
| Variable | Default | Purpose |
|---|---|---|
ZERO_LLM_STREAM_IDLE_TIMEOUT_MS | 120000 | SSE byte-idle watchdog; aborts a stream that stops emitting bytes. |
ZERO_LLM_STREAM_EVENT_IDLE_TIMEOUT_MS | 240000 | SSE event-idle watchdog; keep-alive comments and whitespace alone do not reset it. |
ZERO_LLM_MAX_RETRIES | 6 | Max retries for retryable statuses (429 + transient 5xx), with exponential backoff. |
ZERO_LLM_MAX_RETRY_WAIT_MS | 60000 | Cumulative backoff cap (ms) for the generic retry loop. |
ZERO_LLM_429_MAX_RETRIES | 12 | Max retries for 429 rate-limits specifically. Falls back to ZERO_LLM_MAX_RETRIES when unset. |
ZERO_LLM_429_MAX_RETRY_WAIT_MS | 300000 | Cumulative 429 backoff cap (ms). Falls back to ZERO_LLM_MAX_RETRY_WAIT_MS when unset. Bound server-guided Retry-After waits. |
ZERO_SUPPRESS_PROVIDER_STARTUP_LOG | unset | Set to 1 to suppress the “Provider: …” startup banner line. |
These watchdogs are separate from the request’s overall timeout, which remains
armed while streaming. scan --timeout defaults to 30000 ms;
review and audit --timeout default to 600000 ms. Retry counts mean retries
after the initial request. Generic retryable HTTP statuses are 429, 500, 502,
503 and 504; eligible transport failures also use bounded retries.
Retry-After / retry-after-ms waits are capped at 120 seconds per wait, with
the cumulative caps above and the request’s cancellation/timeout still applying.
An explicit operator cancellation is terminal, not a reason to fail over.
Auth errors (401/403) are never retried: the agent loop exits immediately,
warnings[] carries the provider error, and the run is marked failed, never
clean “0 findings”. Package audits add a per-file circuit breaker (3
identical-signature failures abort the rest).
Provider failover chain
Section titled “Provider failover chain”The provider failover configuration is opt-in. It advances only on eligible failure paths, never because a model answer was unhelpful. Keep backup credentials and account limits intentional.
Execution backends
Section titled “Execution backends”Backend selection is command-specific and separate from the whole-harness execution profile above:
- Source evolution defaults to Docker. Set
backend: "smolvm"and a localimageArchivein its config to use qualified Linux microVM workers. See Improvement Plane for prerequisites, image provisioning, restrictions, and real qualification commands. - Deterministic replay selects
--runner local|docker|qemu; Docker replay networking follows the explicit scope and--docker-networkrules above. - Agentic exploit execution requires
--containeror--exec-script; it does not default to running exploit commands on the host.
Selecting smolvm for evolution does not move general console/PTY tools, replay, or exploit executors into that VM. Provision toolbox dependencies before offline evaluation; candidate execution does not bootstrap packages over the network.
Cost ceiling
Section titled “Cost ceiling”Set a soft estimated-model-cost stop per scan, audit, or review. On a ceiling
breach, 0 preserves partial findings, exits with code 4, and emits
exit_reason: "cost_ceiling_exceeded" in the optional machine-readable result
line. --cost-ceiling overrides ZERO_COST_CEILING_USD; neither supplied means
no dollar ceiling. In-flight/concurrent calls can overshoot. This is not an
invoice cap, infrastructure budget, or guarantee that every external service
is metered. See Budget Management.
env ZERO_COST_CEILING_USD=5 \ 0 scan --target https://example.com --scope ./scope.json --mode web
0 audit lodash --cost-ceiling 20 review ./my-repo --cost-ceiling 10Machine-readable result line
Section titled “Machine-readable result line”Set ZERO_EMIT_RESULT_LINE=1 to print one final ZERO_RESULT=... JSON line with
success/failure, exit code and reason, target type, finding counts, and estimated
cost/token usage. Useful for wrappers and CI parsers.
Example: opt-in verification gates
Section titled “Example: opt-in verification gates”After enabling gates, inspect their execution records and evidence before accepting a finding.
env \ ZERO_FEATURE_CONSENSUS_VERIFY=1 \ ZERO_FEATURE_REACHABILITY_GATE=1 \ ZERO_FEATURE_POV_GATE=1 \ ZERO_FEATURE_MULTIMODAL=1 \ 0 scan --target https://example.com --scope ./scope.json --mode web --depth deepExample: web search
Section titled “Example: web search”env ZERO_FEATURE_WEB_SEARCH=1 \ 0 scan --target https://example.com --scope ./scope.json --mode web