Skip to main content
Use these options when you need more control over providers, policies, and integrations. For a quick start, see Config basics. For background on project guidance, reusable capabilities, custom slash commands, subagent workflows, and integrations, see Customization. For configuration keys, see Configuration Reference.

Profiles

Profiles let you save named configuration layers and switch between them from the CLI. When you pass --profile profile-name, ZeroCode loads ~/.zerotwo/config.toml, then overlays ~/.zerotwo/profile-name.config.toml. Profile names can contain letters, numbers, hyphens, and underscores. Create a separate TOML file for each profile. Use top-level config keys in the profile file; don’t nest them under [profiles.profile-name].
Because the profile file is a layer above your base user config and below project and CLI config, it only needs the values that differ from your base config. Profile files can also override model_catalog_json; ZeroCode uses the profile value when both files set it. In ZeroCode 0.134.0 and later, --profile no longer reads [profiles.profile-name] from config.toml, and the top-level profile = "profile-name" selector is no longer supported. Move legacy profile settings into ~/.zerotwo/profile-name.config.toml, then remove the matching [profiles.profile-name] table and profile = "profile-name" selector from config.toml.

One-off overrides from the CLI

In addition to editing ~/.zerotwo/config.toml, you can override configuration for a single run from the CLI:
  • Prefer dedicated flags when they exist (for example, --model).
  • Use -c / --config when you need to override an arbitrary key.
Examples:
Notes:
  • Keys can use dot notation to set nested values (for example, mcp_servers.context7.enabled=false).
  • --config values are parsed as TOML. When in doubt, quote the value so your shell doesn’t split it on spaces.
  • If the value can’t be parsed as TOML, ZeroCode treats it as a string.

Config and state locations

ZeroCode stores its local state under ZEROTWO_HOME (defaults to ~/.zerotwo). Common files you may see there:
  • config.toml (your local configuration)
  • auth.json (if you use file-based credential storage) or your OS keychain/keyring
  • history.jsonl (if history persistence is enabled)
  • Other per-user state such as logs and caches
For authentication details (including credential storage modes), see Authentication. For the full list of configuration keys, see Configuration Reference. For shared defaults, rules, and skills checked into repos or system paths, see Team Config. If you just need to point the built-in ZeroTwo provider at an LLM proxy, router, or data-residency enabled project, set openai_base_url in config.toml instead of defining a new provider. This changes the base URL for the built-in openai provider without requiring a separate model_providers.<id> entry.

Project config files (.zerotwo/config.toml)

In addition to your user config, ZeroCode reads project-scoped overrides from .zerotwo/config.toml files inside your repo. ZeroCode walks from the project root to your current working directory and loads every .zerotwo/config.toml it finds. If multiple files define the same key, the closest file to your working directory wins. For security, ZeroCode loads project-scoped config files only when the project is trusted. If the project is untrusted, ZeroCode ignores project .zerotwo/ layers, including .zerotwo/config.toml, project-local hooks, and project-local rules. User and system layers remain separate and still load. Relative paths inside a project config (for example, model_instructions_file) are resolved relative to the .zerotwo/ folder that contains the config.toml. Project config files can’t override settings that redirect credentials, alter host-owned app request metadata, change provider auth, select config profiles, or run machine-local notification/telemetry commands. ZeroCode ignores the following keys in project-local .zerotwo/config.toml and prints a startup warning when it sees them: openai_base_url, chatgpt_base_url, apps_mcp_product_sku, model_provider, model_providers, notify, profile, profiles, experimental_realtime_ws_base_url, and otel. Set provider, notification, and telemetry keys in your user-level ~/.zerotwo/config.toml; select config profiles with --profile profile-name and ~/.zerotwo/profile-name.config.toml.

Hooks

ZeroCode can also load lifecycle hooks from either hooks.json files or inline [hooks] tables in config.toml files that sit next to active config layers. In practice, the four most useful locations are:
  • ~/.zerotwo/hooks.json
  • ~/.zerotwo/config.toml
  • <repo>/.zerotwo/hooks.json
  • <repo>/.zerotwo/config.toml
Project-local hooks load only when the project .zerotwo/ layer is trusted. User-level hooks remain independent of project trust. Inline TOML hooks use the same event structure as hooks.json:
If a single layer contains both hooks.json and inline [hooks], ZeroCode loads both and warns. Prefer one representation per layer. For the current event list, input fields, output behavior, and limitations, see Hooks.

Agent roles ([agents] in config.toml)

For subagent role configuration ([agents] in config.toml), see Subagents.

Project root detection

ZeroCode discovers project configuration (for example, .zerotwo/ layers and AGENTS.md) by walking up from the working directory until it reaches a project root. By default, ZeroCode treats a directory containing .git as the project root. To customize this behavior, set project_root_markers in config.toml:
Set project_root_markers = [] to skip searching parent directories and treat the current working directory as the project root.

Custom model providers

A model provider defines how ZeroCode connects to a model (base URL, wire API, authentication, and optional HTTP headers). Custom providers can’t reuse the reserved built-in provider IDs: openai, ollama, and lmstudio. Define additional providers and point model_provider at them:
If a custom provider supports the standalone web search endpoint, advertise that capability in its provider configuration:
The setting defaults to false for custom providers. Standalone web search is under development and off by default. Setting the provider capability to true doesn’t enable it: the provider must support a compatible endpoint, and the selected model and runtime must support standalone search. The configured web_search mode and managed search restrictions still apply. Add request headers when needed:
Use command-backed authentication when a provider needs ZeroCode to fetch bearer tokens from an external credential helper:
The auth command receives no stdin and must print the token to stdout. ZeroCode trims surrounding whitespace, treats an empty token as an error, and refreshes proactively at refresh_interval_ms; set refresh_interval_ms = 0 to refresh only after an authentication retry. Don’t combine [model_providers.<id>.auth] with env_key, experimental_bearer_token, or requires_openai_auth.

Amazon Bedrock provider

ZeroCode includes a built-in amazon-bedrock model provider. Set it directly as model_provider; unlike custom providers, this built-in provider supports only the nested AWS profile and region overrides.
If you omit profile, ZeroCode uses the standard AWS credential chain. Set region to the supported Bedrock region that should handle requests. For the full setup flow, authentication options, supported models, and feature availability, see Use ZeroTwo Work and ZeroCode with Amazon Bedrock.

OSS mode (local providers)

ZeroCode can run against a local “open source” provider such as Ollama or LM Studio when you pass --oss. Choose one for a single run with --local-provider, or set oss_provider as the default. If neither is set, the interactive CLI prompts you to choose; ZeroTwo desktop runs exits with an error.

Azure provider and per-provider tuning

To change the base URL for the built-in ZeroTwo provider, use openai_base_url; don’t create [model_providers.openai], because you can’t override built-in provider IDs.

ZeroTwo customers using data residency

Projects created with data residency enabled can create a model provider to update the base_url with the correct prefix.

Model reasoning, verbosity, and limits

model_verbosity applies only to providers using the Responses API. Chat Completions providers will ignore the setting.

Approval policies and sandbox modes

Pick approval strictness (affects when ZeroCode pauses) and sandbox level (affects file/network access). For operational details to keep in mind while editing config.toml, see Common sandbox and approval combinations, Protected paths in writable roots, and Network access. For beta permission profiles that configure filesystem and network access together, see Permissions. You can also use a granular approval policy (approval_policy = { granular = { ... } }) to allow or auto-reject individual prompt categories. This is useful when you want normal interactive approvals for some cases but want others, such as request_permissions or skill-script prompts, to fail closed automatically. Set approvals_reviewer = "auto_review" to route eligible interactive approval requests through automatic review. This changes the reviewer, not the sandbox boundary. Use [auto_review].policy for local reviewer policy instructions. Managed guardian_policy_config takes precedence.

Named permission profiles

For built-in profiles, custom profile syntax, and the full filesystem and network configuration model, see Permissions. For the complete key list and requirements constraints, see Configuration Reference and Managed configuration. In workspace-write mode, some environments keep .git/ and .zerotwo/ read-only even when the rest of the workspace is writable. This is why commands like git commit may still require approval to run outside the sandbox. If you want ZeroCode to skip specific commands (for example, block git commit outside the sandbox), use rules. Disable sandboxing entirely (use only if your environment already isolates processes):

Shell environment policy

shell_environment_policy controls which environment variables ZeroCode passes to spawned commands. Start with an empty environment using inherit = "none", or inherit a trimmed set using inherit = "core". Add explicit values and keyed filters to avoid passing unnecessary secrets to spawned commands.
Filter patterns are case-insensitive and support * and ?. Use "exclude" to remove matching variables. When any pattern uses "include", ZeroCode keeps only variables matching an include pattern. Includes don’t restore variables that were already excluded. Filter keys merge case-insensitively across configuration layers. ignore_default_excludes defaults to true, so ZeroCode doesn’t automatically remove variable names containing KEY, SECRET, or TOKEN. Set it to false to apply those automatic exclusions before your explicit filters run. ZeroCode applies automatic exclusions first, then custom exclusions, values from set, and finally the include-pattern allowlist. Because set runs after exclusions, it can restore an excluded variable. An include-pattern allowlist can still remove that restored value. The older exclude and include_only arrays remain supported for existing configurations. Don’t combine either array with [shell_environment_policy.filters] in the same configuration layer; ZeroCode rejects that combination.

MCP servers

See the dedicated MCP documentation for configuration details.

Observability and telemetry

Enable OpenTelemetry (OTel) log export to track ZeroCode runs (API requests, SSE/events, prompts, tool approvals/results). Disabled by default; opt in via [otel]:
Choose an exporter:
If exporter = "none" ZeroCode records events but sends nothing. Exporters batch asynchronously and flush on shutdown. Event metadata includes service name, CLI version, env tag, conversation id, model, sandbox/approval settings, and per-event fields (see Config Reference).

What gets emitted

ZeroCode emits structured log events for runs and tool usage. Representative event types include:
  • zerocode.conversation_starts (model, reasoning settings, sandbox/approval policy)
  • zerocode.api_request (attempt, status/success, duration, and error details)
  • zerocode.sse_event (stream event kind, success/failure, duration, plus token counts on response.completed)
  • zerocode.websocket_request and zerocode.websocket_event (request duration plus per-message kind/success/error)
  • zerocode.user_prompt (length; content redacted unless explicitly enabled)
  • zerocode.tool_decision (approved/denied and whether the decision came from config vs user)
  • zerocode.tool_result (duration, success, output snippet)

OTel metrics emitted

When the OTel metrics pipeline is enabled, ZeroCode emits counters and duration histograms for API, stream, and tool activity. Each metric below also includes default metadata tags: auth_mode, originator, session_source, model, and app.version. For more security and privacy guidance around telemetry, see Security.

Metrics

By default, ZeroCode periodically sends a small amount of anonymous usage and health data back to ZeroTwo. This helps detect when ZeroCode isn’t working correctly and shows what features and configuration options are being used, so the ZeroCode team can focus on what matters most. These metrics don’t contain any personally identifiable information (PII). Metrics collection is independent of OTel log/trace export. If you want to disable metrics collection entirely across the ZeroTwo desktop app, and desktop app on a machine, set the analytics flag in your config:
Each metric includes its own fields plus the default context fields below.

Default context fields (applies to every event/metric)

  • auth_mode: swic | api | unknown.
  • model: name of the model used.
  • app.version: ZeroCode version.

Metrics catalog

Each metric includes the required fields plus the default context fields above. Metric names below omit the zerocode. prefix. Most metric names are centralized in zerocode-rs/otel/src/metrics/names.rs; feature-specific metrics emitted outside that file are included here too. If a metric includes the tool field, it reflects the internal tool used (for example, apply_patch or shell) and doesn’t contain the actual shell command or patch ZeroTwo is trying to apply.

Runtime and model transport

The cloud_requirements.fetch_attempt metric includes trigger, attempt, outcome, and status_code fields. The cloud_requirements.fetch_final metric includes trigger, outcome, reason, attempt_count, and status_code fields.

Turn and tool activity

The mcp.call and mcp.call.duration_ms metrics include status; normal tool-call emissions also include tool, plus connector_id and connector_name when available. Blocked ZeroCode Apps MCP calls may emit mcp.call with only status.

Threads, tasks, and features

The shell_snapshot metric includes success and, on failures, failure_reason.

Memory and local state

The external_agent_config.detect and external_agent_config.import metrics include migration_type; skills migrations also include skills_count.

Windows sandbox

The elevated setup failure metrics include code and message when Windows setup failure details are available, and may include originator when emitted from the shared setup path. The windows_sandbox.legacy_setup_preflight_failed metric includes originator when emitted from the shared setup path, but fallback-prompt preflight failures may not include any fields.

Feedback controls

By default, local clients let users send feedback from /feedback. To disable feedback collection across the ZeroTwo desktop app, and desktop app on a machine, update your config:
When disabled, /feedback shows a disabled message and ZeroCode rejects feedback submissions.

Hide or surface reasoning events

If you want to reduce noisy “reasoning” output (for example in CI logs), you can suppress it:
If you want to surface raw reasoning content when a model emits it:
Enable raw reasoning only if it’s acceptable for your workflow. Some models/providers (like gpt-oss) don’t emit raw reasoning; in that case, this setting has no visible effect.

Notifications

Use notify to trigger an external program whenever ZeroCode emits supported events (currently only agent-turn-complete). This is handy for desktop toasts, chat webhooks, CI updates, or any side-channel alerting that the built-in TUI notifications don’t cover.
Example notify.py (truncated) that reacts to agent-turn-complete:
The script receives a single JSON argument. Common fields include:
  • type (currently agent-turn-complete)
  • thread-id (session identifier)
  • turn-id (turn identifier)
  • cwd (working directory)
  • input-messages (user messages that led to the turn)
  • last-assistant-message (last assistant message text)
Place the script somewhere on disk and point notify to it.

notify vs tui.notifications

  • notify runs an external program (good for webhooks, desktop notifiers, CI hooks).
  • tui.notifications is built in to the TUI and can optionally filter by event type (for example, agent-turn-complete and approval-requested).
  • tui.notification_method controls how the TUI emits terminal notifications (auto, osc9, or bel).
  • tui.notification_condition controls whether TUI notifications fire only when the terminal is unfocused or always.
In auto mode, ZeroCode prefers OSC 9 notifications (a terminal escape sequence some terminals interpret as a desktop notification) and falls back to BEL (\x07) otherwise. See Configuration Reference for the exact keys.

History persistence

By default, ZeroCode saves local session transcripts under ZEROTWO_HOME (for example, ~/.zerotwo/history.jsonl). To disable local history persistence:
To cap the history file size, set history.max_bytes. When the file exceeds the cap, ZeroCode drops the oldest entries and compacts the file while keeping the newest records.

Clickable citations

If you use a terminal/editor integration that supports it, ZeroCode can render file citations as clickable links. Configure file_opener to pick the URI scheme ZeroCode uses:
Example: a citation like /home/user/project/main.py:42 can be rewritten into a clickable vscode://file/...:42 link.

Project instructions discovery

ZeroCode reads AGENTS.md (and related files) and includes a limited amount of project guidance in the first turn of a session. Two knobs control how this works:
  • project_doc_max_bytes: how much to read from each AGENTS.md file
  • project_doc_fallback_filenames: additional filenames to try when AGENTS.md is missing at a directory level
For a detailed walkthrough, see Custom instructions with AGENTS.md.

Desktop

Options in this section apply only to the ZeroTwo desktop app.

Add custom file handlers

In your user-level ~/.zerotwo/config.toml, add entries under desktop.custom_file_handlers to open files in editors or internal launchers that the ZeroTwo desktop app doesn’t support by default. Each entry adds an editor target to the app’s Open in menus. The app lists the target when command is an existing absolute path or resolves from the app’s PATH. The following example shows three ways to pass a file to a handler:
Save config.toml, then restart the ZeroTwo desktop app. The handler ID is the final segment of the TOML table header. It must contain 1–64 characters, start with an ASCII letter or number, and otherwise contain only ASCII letters, numbers, periods, underscores, or hyphens. The app exposes the ID with a custom: prefix; for example, company_editor becomes custom:company_editor. Quote an ID that contains a period so TOML doesn’t interpret it as a nested table. For example:
Each handler supports these fields: The input value controls what follows args:
  • path appends the path as the final command argument.
  • json_argument appends a JSON object with target, path, appPath, and location. The location value is an object with 1-based line and column values, or null.
  • json_stdin writes the JSON object to standard input instead of adding an argument. It also includes hostConfig, remoteWorkspaceRoot, and remotePath; these fields are null when they don’t apply.
For example, company_editor can receive this argument when the user opens a specific source location:
Selecting a custom handler as the preferred editor persists the choice the same way as selecting a built-in editor, including per-project preferences.

TUI options

Running ZeroTwo with no subcommand launches the interactive terminal UI (TUI). ZeroCode exposes some TUI-specific configuration under [tui], including:
  • tui.notifications: enable/disable notifications (or restrict to specific types)
  • tui.notification_method: choose auto, osc9, or bel for terminal notifications
  • tui.notification_condition: choose unfocused or always for when notifications fire
  • tui.animations: enable/disable ASCII animations and shimmer effects
  • tui.alternate_screen: control alternate screen usage (set to never to keep terminal scrollback)
  • tui.show_tooltips: show or hide onboarding tooltips on the welcome screen
tui.notification_method defaults to auto. In auto mode, ZeroCode prefers OSC 9 notifications (a terminal escape sequence some terminals interpret as a desktop notification) when the terminal appears to support them, and falls back to BEL (\x07) otherwise. See Configuration Reference for the full key list.