Files
ironclaw/.env.example
firat.sertgoz a3424a9d97 feat(agent-loop): add opt-in parallel tool batches (#7416)
* feat(agent-loop): add opt-in parallel tool batches

* fix(agent-loop): address parallel batch review

* fix(agent-loop): close parallel batch review gaps (#7416)

* fix(agent-loop): preserve sibling exit state (#7416)

* fix(agent-loop): preserve terminal batch sibling state

* fix(agent-loop): drain bounded parallel terminal outcomes

* fix(turn-runner): seal parallel batch configuration

* style(turn-runner): format merged imports

* test(agent-loop): pause parallel ordering clock

* test(agent-loop): bound paused launch wait

* fix(deps): update lru past unsound advisory

* fix(agent-loop): preserve hooked batch semantics

* fix(loop): address CodeRabbit review — fail closed batch ordering (#7416)

* fix(ci): rebaseline loop contracts size ratchet (#7416)
2026-08-12 10:54:11 +00:00

553 lines
28 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Database Configuration
DATABASE_URL=postgres://localhost/ironclaw
DATABASE_POOL_SIZE=30 # multi-tenant default; reduce to 5-10 for single-user or low-resource deployments
# LLM Provider
# LLM_BACKEND=nearai # default
# Possible values: nearai, ollama, openai_compatible, openai, anthropic, github_copilot, tinfoil, openai_codex, gemini_oauth
# LLM_REQUEST_TIMEOUT_SECS=120 # Increase for local LLMs (Ollama, vLLM, LM Studio)
# === Anthropic Direct ===
# Two auth modes:
# 1. API key: Set ANTHROPIC_API_KEY (from console.anthropic.com/settings/keys)
# 2. OAuth token: Set ANTHROPIC_OAUTH_TOKEN (from `claude login`)
# OAuth tokens use Authorization: Bearer instead of x-api-key header.
# ANTHROPIC_API_KEY=sk-ant-...
# ANTHROPIC_OAUTH_TOKEN=sk-ant-oat01-... # from `claude login` credentials
# ANTHROPIC_MODEL=claude-sonnet-4-20250514
# === OpenAI Direct ===
# OPENAI_API_KEY=sk-...
# Reuse Codex CLI auth.json instead of setting OPENAI_API_KEY manually.
# Works with both OpenAI API-key mode and Codex ChatGPT OAuth mode.
# In ChatGPT mode this uses the private `chatgpt.com/backend-api/codex` endpoint.
# LLM_USE_CODEX_AUTH=true
# CODEX_AUTH_PATH=~/.codex/auth.json
# === GitHub Copilot ===
# Uses the OAuth token from your Copilot IDE sign-in (for example
# ~/.config/github-copilot/apps.json on Linux/macOS), or run `ironclaw onboard`
# and choose the GitHub device login flow.
# LLM_BACKEND=github_copilot
# GITHUB_COPILOT_TOKEN=gho_...
# GITHUB_COPILOT_MODEL=gpt-4o
# IronClaw injects standard VS Code Copilot headers automatically.
# Optional advanced headers for custom overrides:
# GITHUB_COPILOT_EXTRA_HEADERS=Copilot-Integration-Id:vscode-chat
# === NEAR AI (Chat Completions API) ===
# Two auth modes:
# 1. Session token (default): Uses browser OAuth (GitHub/Google) on first run.
# Session token stored in ~/.ironclaw/session.json automatically.
# Base URL defaults to https://private.near.ai
# 2. API key: Set NEARAI_API_KEY to use API key auth from cloud.near.ai.
# Base URL defaults to https://cloud-api.near.ai
# When NEARAI_API_KEY is set at startup, IronClaw bootstraps the
# `nearai` MCP integration automatically, using the default endpoint
# unless NEARAI_BASE_URL is also set:
# legacy startup persists a `nearai` MCP server, and Reborn local-dev
# seeds product-auth and activates the bundled NEAR AI MCP extension.
# Leave NEARAI_MODEL / NEARAI_BASE_URL unset to use the built-in defaults
# (model `deepseek-ai/DeepSeek-V4-Flash`; base URL chosen by auth mode:
# cloud-api.near.ai with an API key, private.near.ai for session tokens) and
# to let the WebUI onboarding selection take effect. Set them only for a pure
# env-configured deployment — they apply process-wide. Precedence: an explicit
# WebUI/config.toml selection wins over these env vars, which in turn win over
# the built-in defaults.
# NEARAI_MODEL=deepseek-ai/DeepSeek-V4-Flash
# NEARAI_BASE_URL=https://private.near.ai
# NEARAI_AUTH_URL=https://private.near.ai
# NEARAI_SESSION_TOKEN=sess_... # hosting providers: set this
# NEARAI_SESSION_PATH=~/.ironclaw/session.json # optional, default shown
# NEARAI_API_KEY=... # API key from cloud.near.ai
# Local LLM Providers (Ollama, LM Studio, vLLM, LiteLLM)
# === Ollama ===
# OLLAMA_MODEL=llama3.2
# LLM_BACKEND=ollama
# OLLAMA_BASE_URL=http://localhost:11434 # default
# === OpenAI-compatible (LM Studio, vLLM, Anything-LLM) ===
# LLM_MODEL=llama-3.2-3b-instruct-q4_K_M
# LLM_BACKEND=openai_compatible
# LLM_BASE_URL=http://localhost:1234/v1
# LLM_API_KEY=sk-... # optional for local servers
# Custom HTTP headers for OpenAI-compatible providers
# Format: comma-separated key:value pairs
# LLM_EXTRA_HEADERS=HTTP-Referer:https://github.com/nearai/ironclaw,X-Title:ironclaw
# === OpenRouter (300+ models via OpenAI-compatible) ===
# LLM_MODEL=anthropic/claude-sonnet-4 # see openrouter.ai/models for IDs
# LLM_BACKEND=openai_compatible
# LLM_BASE_URL=https://openrouter.ai/api/v1
# LLM_API_KEY=sk-or-...
# LLM_EXTRA_HEADERS=HTTP-Referer:https://myapp.com,X-Title:MyApp
# === Together AI (via OpenAI-compatible) ===
# LLM_MODEL=meta-llama/Llama-3.3-70B-Instruct-Turbo
# LLM_BACKEND=openai_compatible
# LLM_BASE_URL=https://api.together.xyz/v1
# LLM_API_KEY=...
# === Fireworks AI (via OpenAI-compatible) ===
# LLM_MODEL=accounts/fireworks/models/llama4-maverick-instruct-basic
# LLM_BACKEND=openai_compatible
# LLM_BASE_URL=https://api.fireworks.ai/inference/v1
# LLM_API_KEY=fw_...
# === MiniMax ===
# LLM_BACKEND=minimax
# MINIMAX_API_KEY=...
# MINIMAX_MODEL=MiniMax-M2.7
# MINIMAX_BASE_URL=https://api.minimax.io/v1 # default (global); use https://api.minimaxi.com/v1 for China
# === Anthropic Direct ===
# LLM_BACKEND=anthropic
# ANTHROPIC_MODEL=claude-sonnet-4-6
# ANTHROPIC_API_KEY=sk-ant-...
# ANTHROPIC_BASE_URL=https://api.anthropic.com # default
# Prompt cache retention — controls Anthropic server-side prompt caching:
# none = disabled (no cache_control injected)
# short = 5-minute TTL, 1.25× (125%) write surcharge (default)
# long = 1-hour TTL, 2.0× (200%) write surcharge
# ANTHROPIC_CACHE_RETENTION=short
# === OpenAI Codex (ChatGPT subscription, OAuth) ===
# LLM_BACKEND=openai_codex
# OPENAI_CODEX_MODEL=gpt-5.5 # default (must be entitled to your ChatGPT plan)
# OPENAI_CODEX_CLIENT_ID=app_EMoamEEZ73f0CkXaXp7hrann # override (rare)
# OPENAI_CODEX_AUTH_URL=https://auth.openai.com # override (rare)
# OPENAI_CODEX_API_URL=https://chatgpt.com/backend-api/codex # override (rare)
# === Google Gemini (OAuth, Gemini CLI compatible) ===
# LLM_BACKEND=gemini_oauth
# GEMINI_MODEL=gemini-2.5-flash # default
# GEMINI_CREDENTIALS_PATH=~/.gemini/oauth_creds.json # default
# GEMINI_API_KEY=... # optional: use API key instead of OAuth
# GEMINI_API_KEY_AUTH_MECHANISM=query # "query" (default) or "header"
# GEMINI_SAFETY_BLOCK_NONE=true # disable safety filters (default: false)
# GEMINI_CLI_CUSTOM_HEADERS=Key:Value,Key2:Value2
# GEMINI_TOP_P=0.95
# GEMINI_TOP_K=40
# GEMINI_SEED=42
# GEMINI_PRESENCE_PENALTY=0.0
# GEMINI_FREQUENCY_PENALTY=0.0
# GEMINI_RESPONSE_MIME_TYPE=application/json
# GEMINI_RESPONSE_JSON_SCHEMA={"type":"object"}
# GEMINI_CACHED_CONTENT=cachedContents/abc123
# For full provider setup guide see docs/LLM_PROVIDERS.md
# Progressive tool disclosure. The default is `namespaces`; set `off` for the
# rollback path. `bridged` additionally enables reviewed per-profile pins.
# REBORN_TOOL_DISCLOSURE=namespaces
# JSON map from validated capability-surface profile ids to capability ids.
# Invalid JSON/ids reject startup; unset means no pins. Pins affect visibility
# only and never bypass authorization.
# REBORN_TOOL_DISCLOSURE_PROFILE_PINS={"interactive_tools":["github.search_code"]}
# Channel Configuration
# CLI is always enabled
# Slack Bot (optional)
SLACK_BOT_TOKEN=xoxb-...
SLACK_APP_TOKEN=xapp-...
SLACK_SIGNING_SECRET=...
# Telegram Bot (optional)
TELEGRAM_BOT_TOKEN=...
# Reborn Telegram WASM v2 ProductAdapter (issue #3285) — DEFAULT OFF.
# When true, the v2 ProductAdapter path takes mutually-exclusive ownership
# of the telegram webhook installation. Legacy v1 Telegram MUST NOT be
# configured for the same installation while this flag is true; the host
# fails closed on startup if both are active.
# REBORN_TELEGRAM_V2_ENABLED=false
# HTTP Webhook Server (optional)
HTTP_HOST=0.0.0.0
HTTP_PORT=8080
HTTP_WEBHOOK_SECRET=your-webhook-secret
# Webhook authentication uses HMAC-SHA256 signature verification.
# Callers must send an X-IronClaw-Signature header with format: sha256=<hex_digest>
# where the digest is HMAC-SHA256(HTTP_WEBHOOK_SECRET, raw_request_body) in lowercase hex.
#
# Example (bash):
# BODY='{"content":"hello"}'
# SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$HTTP_WEBHOOK_SECRET" | cut -d' ' -f2)
# curl -X POST http://localhost:8080/webhook \
# -H "Content-Type: application/json" \
# -H "X-IronClaw-Signature: sha256=$SIG" \
# -d "$BODY"
#
# DEPRECATED: Passing "secret" in the JSON body still works but will be removed in a future release.
# Signal Channel (optional, requires signal-cli daemon --http)
# SIGNAL_HTTP_URL=http://127.0.0.1:8080
# SIGNAL_ACCOUNT=+1234567890
# SIGNAL_ALLOW_FROM=+1234567890,uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx # comma-separated, * for all, empty = deny/require pairing
# SIGNAL_ALLOW_FROM_GROUPS= # comma-separated group IDs, * for all, empty = deny all groups
# SIGNAL_DM_POLICY=pairing # open | allowlist | pairing
# SIGNAL_GROUP_POLICY=allowlist # allowlist | open | disabled
# SIGNAL_GROUP_ALLOW_FROM= # comma-separated, empty = inherit from ALLOW_FROM
# SIGNAL_IGNORE_ATTACHMENTS=false
# SIGNAL_IGNORE_STORIES=true
# Agent Settings
AGENT_NAME=ironclaw
AGENT_MAX_PARALLEL_JOBS=5
AGENT_JOB_TIMEOUT_SECS=3600
AGENT_STUCK_THRESHOLD_SECS=300
# Maximum tokens per job (0 = unlimited, also settable via settings.json agent.max_tokens_per_job)
# AGENT_MAX_TOKENS_PER_JOB=0
# Enable planning phase before tool execution (default: true)
AGENT_USE_PLANNING=true
# Self-repair settings
SELF_REPAIR_CHECK_INTERVAL_SECS=60
SELF_REPAIR_MAX_ATTEMPTS=3
# Heartbeat settings (proactive periodic execution)
# When enabled, reads HEARTBEAT.md checklist and reports findings
HEARTBEAT_ENABLED=false
HEARTBEAT_INTERVAL_SECS=1800
HEARTBEAT_NOTIFY_CHANNEL=cli
HEARTBEAT_NOTIFY_USER=default
# Memory hygiene settings (automatic cleanup of stale workspace documents)
# Runs on each heartbeat tick; discovers cleanup targets from .config metadata
# MEMORY_HYGIENE_ENABLED=true
# MEMORY_HYGIENE_VERSION_KEEP_COUNT=50 # max versions to keep per document
# MEMORY_HYGIENE_CADENCE_HOURS=12 # minimum hours between cleanup passes
# Trigger poller (scheduled / cron trigger firing)
# OFF by default. Enable to allow the host background poller to scan due trigger
# records and auto-fire scheduled (cron) triggers. Without this, triggers can be
# created and listed but will never fire automatically.
# IRONCLAW_TRIGGER_POLLER_ENABLED=true # accepts 1/true to enable, 0/false to disable (default: false; any other value is a fatal startup error)
# IRONCLAW_TRIGGER_POLLER_INTERVAL_SECS=60 # how often the poller checks for due triggers (integer seconds, 1..=3600)
# IRONCLAW_CREDENTIAL_REFRESH_ENABLED=true # accepts 1/true to enable, 0/false to disable (default: false; any other value is a fatal startup error)
# Turn-runner concurrency (overrides the config-file [runner] section)
# Highest-precedence layer; a set-but-blank value is a fatal startup error.
# For every knob below, 0 means "unlimited". Use 0 to stress-test the DB
# backend (e.g. libSQL) with no concurrency throttle.
# IRONCLAW_REBORN_RUNNER_WORKER_COUNT=16 # global scheduler slots; 0 = unlimited; positive = that many, verbatim; default 16
# IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_RUNS_PER_USER=3 # per (tenant, owner) cap; 0 = unlimited; default 3
# IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_TRIGGER_RUNS=8 # scheduled-trigger cap; 0 = unlimited; default 8
# IRONCLAW_REBORN_RUNNER_MAX_CONCURRENT_CONVERSATION_RUNS=0 # inbound/web cap; 0 = unlimited (default)
# Execute capability batches already classified safe for parallelism with a
# fixed fan-out of four. Default/off keeps the legacy sequential batch path.
# Accepted opt-in values: on, 1, true. Unknown values fail closed to off.
# REBORN_PARALLEL_TOOL_BATCH=off
# Railway Sandboxes preview. Preferred IronClaw-scoped identifiers fall back
# to RAILWAY_PROJECT_ID / RAILWAY_ENVIRONMENT_ID used by the Railway CLI.
# Set exactly one of RAILWAY_TOKEN or RAILWAY_API_TOKEN in the deployment.
# IRONCLAW_REBORN_RAILWAY_PROJECT_ID=
# IRONCLAW_REBORN_RAILWAY_ENVIRONMENT_ID=
# IRONCLAW_REBORN_RAILWAY_CLI_PATH=railway
# IRONCLAW_REBORN_RAILWAY_IDLE_TIMEOUT_MINUTES=30
# IRONCLAW_REBORN_RAILWAY_WORKER_IMAGE=python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de
# RAILWAY_TOKEN=
# RAILWAY_API_TOKEN=
# Reborn skill prompt injection: "listing" (default) advertises non-activated
# skills as a one-line "- name: description" listing and loads a skill's full
# instructions only on explicit $name mention or builtin.skill_activate;
# "full" restores the legacy inject-bodies-by-keyword-score behavior.
# IRONCLAW_REBORN_SKILL_INJECTION=listing
# Docker Sandbox
# SANDBOX_ENABLED=true
# SANDBOX_POLICY=readonly # readonly, workspace_write, or full_access
# SANDBOX_ALLOW_FULL_ACCESS=false # REQUIRED second opt-in for full_access policy.
# # FullAccess bypasses Docker entirely and runs
# # commands directly on the host. Without this
# # set to "true", full_access is downgraded to
# # workspace_write.
# SANDBOX_IMAGE=ironclaw-worker:latest
# SANDBOX_TIMEOUT_SECS=120
# SANDBOX_MEMORY_LIMIT_MB=2048
# Reborn sandbox container transport
# Overrides Docker daemon discovery for the Reborn sandbox transport. Accepts a
# unix socket path (optionally "unix://"-prefixed) or an http://host:port /
# tcp://host:port address. Unset means "probe local defaults, then the
# well-known unix sockets".
#
# SECURITY: the http(s)/tcp form is plaintext and unauthenticated; the Docker
# Engine API it reaches can create containers and mount host paths, so it is
# restricted to a unix socket or a loopback address ("localhost"/127.0.0.1/::1)
# by default. A non-loopback value (e.g. a remote daemon, or a DinD/CI sidecar
# reachable at a container-network IP) additionally requires
# IRONCLAW_REBORN_DOCKER_HOST_ALLOW_REMOTE=1 as an explicit second opt-in.
# IRONCLAW_REBORN_DOCKER_HOST=unix:///var/run/docker.sock
# IRONCLAW_REBORN_DOCKER_HOST_ALLOW_REMOTE=false # required to use a non-loopback IRONCLAW_REBORN_DOCKER_HOST
#
# Extra domains appended to the sandboxed shell's default egress allowlist
# (crates.io, npm, PyPI, the Go proxy, GitHub). Comma-separated hostnames;
# a leading "*." wildcard is allowed. A bare "*" is rejected (would allow
# every host). These add to the defaults, never replace them.
# IRONCLAW_SANDBOX_EXTRA_ALLOWED_DOMAINS=example.com,*.internal.example.com
#
# Per-request egress volume cap (bytes) for the sandboxed shell's network
# policy. Default 2147483648 (2 GiB) — generous enough for ordinary
# cargo/npm/pip/git workflows while still bounding a single request well
# short of a bulk-exfiltration attempt. Must be a positive integer; 0 or
# non-numeric values fail to start.
# IRONCLAW_SANDBOX_MAX_EGRESS_BYTES=2147483648
# ACP (Agent Client Protocol) agents
# ACP_ENABLED=false # Enable ACP agent sandbox mode
# ACP_MEMORY_LIMIT_MB=4096 # Memory limit for ACP containers
# ACP_TIMEOUT_SECS=1800 # Maximum session timeout
# Configure agents via CLI: ironclaw acp add goose --command goose --arg "--stdio"
# Safety settings
SAFETY_MAX_OUTPUT_LENGTH=100000
SAFETY_INJECTION_CHECK_ENABLED=true
# Restart Feature (Docker containers only)
# Set IRONCLAW_IN_DOCKER=true in the container entrypoint to enable the restart feature.
# Without this, the restart tool and /restart command will be disabled.
# IRONCLAW_IN_DOCKER=false
# IRONCLAW_RESTART_DELAY=5 # default wait before exit (seconds, range: 1-30)
# IRONCLAW_MAX_FAILURES=10 # max consecutive failures before container exits
# ─── OAuth / Social Login ────────────────────────────────────────────────
# Enable direct OAuth login (Google, GitHub). Disabled by default.
# OAUTH_ENABLED=true
# Base URL for OAuth callback URLs. Defaults to http://localhost:{GATEWAY_PORT}.
# Set this to your public URL in production (e.g., https://myapp.example.com).
# OAUTH_BASE_URL=https://myapp.example.com
# Restrict OAuth login to specific email domains (comma-separated).
# When set, only users with verified emails from these domains can log in.
# Applies to all OAuth providers and OIDC. Leave unset to allow all domains.
# OAUTH_ALLOWED_DOMAINS=company.com,partner.org
# Google OAuth — Create credentials at https://console.cloud.google.com/apis/credentials
# 1. Create an OAuth 2.0 Client ID (Web application type)
# 2. Add authorized redirect URI: {OAUTH_BASE_URL}/auth/callback/google
# 3. Copy Client ID and Client Secret below
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=
# GOOGLE_OAUTH_REDIRECT_URI=https://myapp.example.com/auth/callback/google
# Reborn Product Auth Google OAuth setup recovery.
# Prefer these Reborn-specific vars when configuring the WebChat v2 setup flow.
# IRONCLAW_REBORN_GOOGLE_CLIENT_ID=
# IRONCLAW_REBORN_GOOGLE_CLIENT_SECRET=
# IRONCLAW_REBORN_GOOGLE_OAUTH_REDIRECT_URI=https://myapp.example.com/api/reborn/product-auth/oauth/google/callback
# Optional Reborn setup hint. CURRENTLY INERT (measured 2026-08-05): the value
# is resolved and stored but nothing reads it, because the auth engine builds
# its authorization parameters from the vendor recipe's manifest
# `extra_authorize_params` and the Google recipes declare no `hd`. Setting it
# adds nothing. For real Google-Workspace restriction of WebChat *login*, use
# IRONCLAW_REBORN_WEBUI_GOOGLE_ALLOWED_HD below instead.
# IRONCLAW_REBORN_GOOGLE_HOSTED_DOMAIN_HINT=company.com
# Restrict Google login to a specific Workspace (G Suite) domain.
# Adds the `hd` parameter to the authorization URL and validates server-side.
# GOOGLE_ALLOWED_HD=company.com
# Apple Sign In — Configure in https://developer.apple.com/account/resources/identifiers
# 1. Register a Services ID (e.g. com.example.myapp) under Identifiers
# 2. Enable "Sign In with Apple" and configure the return URL: {OAUTH_BASE_URL}/auth/callback/apple
# 3. Create a key (Keys section), enable "Sign In with Apple", download the .p8 file
# 4. Note your Team ID (top right of developer portal) and Key ID
# APPLE_CLIENT_ID=com.example.myapp
# APPLE_TEAM_ID=XXXXXXXXXX
# APPLE_KEY_ID=YYYYYYYYYY
# APPLE_PRIVATE_KEY_PATH=/path/to/AuthKey_YYYYYYYYYY.p8
# Or inline: APPLE_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
# GitHub OAuth — Create an OAuth App at https://github.com/settings/developers
# 1. Create a new OAuth App
# 2. Set Authorization callback URL to: {OAUTH_BASE_URL}/auth/callback/github
# 3. Copy Client ID and generate a Client Secret below
# GITHUB_CLIENT_ID=
# GITHUB_CLIENT_SECRET=
# NEAR Wallet — No external setup needed. Users sign in with any NEAR wallet
# (HOT, Meteor, MyNearWallet, etc.) via the near-connect SDK.
# NEAR_AUTH_ENABLED=true
# NEAR_AUTH_NETWORK=mainnet # or testnet
# NEAR_AUTH_RPC_URL=https://rpc.mainnet.near.org # auto-detected from network
# ─── OIDC / SSO (Okta, Cognito, etc.) ──────────────────────────────────
# For reverse-proxy SSO (e.g., AWS ALB + Okta). The gateway validates JWTs
# from the configured header. See also OAUTH_ALLOWED_DOMAINS above, which
# applies to OIDC logins too.
# GATEWAY_OIDC_ENABLED=true
# GATEWAY_OIDC_JWKS_URL=https://your-idp.example.com/.well-known/jwks.json
# GATEWAY_OIDC_HEADER=x-amzn-oidc-data
# GATEWAY_OIDC_ISSUER=https://your-idp.example.com
# GATEWAY_OIDC_AUDIENCE=your-client-id
# ─── Reborn WebUI v2 (`ironclaw serve`) ─────────────────────────
# The Reborn binary is separate from v1 and does not share auth/middleware
# with the v1 channels/web stack. These variables configure the v2 native
# HTTP surface owned by `crates/product/ironclaw_webui`. They have
# no effect on the v1 binary.
#
# Bearer token consulted by `EnvBearerAuthenticator`. Keep this in the
# environment ONLY — operators must NOT put the token value into
# `config.toml`. The token is compared with `subtle::ConstantTimeEq` so
# leading/trailing whitespace counts.
# IRONCLAW_REBORN_WEBUI_TOKEN=replace-with-strong-random-token
#
# UserId stamped onto the `WebUiAuthenticatedCaller` when the bearer
# token matches. Pair this with the tenant_id resolved from
# `[identity].installation_tenant` in `config.toml`.
# IRONCLAW_REBORN_WEBUI_USER_ID=reborn-cli-operator
#
# Optional path under /opt/ironclaw to the default TOML copied into
# `$IRONCLAW_REBORN_HOME/config.toml` by the Reborn Docker entrypoint on first
# start. Existing home configs are preserved.
# IRONCLAW_REBORN_DEFAULT_CONFIG=/opt/ironclaw/reborn/config.toml
#
# Show the WebChat v2 Projects surface (the conversations-panel "Projects"
# entry + the /projects route). Hidden by default while the surface is still
# being finished. The flag is read at serve composition and delivered to the
# browser via `GET /api/webchat/v2/session` (`features.reborn_projects`).
# IRONCLAW_REBORN_PROJECTS=true
#
# Enable QA-only scrubbed run and full-thread regression artifact downloads.
# Disabled by default: production users receive no download affordance and the
# artifact HTTP routes are not mounted. Enable only on trusted QA deployments.
# IRONCLAW_REBORN_REGRESSION_ARTIFACT_EXPORT=true
#
# Enable the admin thread-scraping panel (cross-user transcript artifact
# collection for debugging/optimization). Disabled by default and gated
# independently of the QA-only regression export flag: enabling QA self-export
# must never silently mount tenant-wide admin transcript access.
# IRONCLAW_REBORN_ADMIN_THREAD_SCRAPE=true
#
# Tenant-shared tool credentials (#5459). Any variable matching
# `IRONCLAW_REBORN_DEV_SECRET__<handle>=<value>` is read once at `serve`
# startup and stored under `<handle>` at the tenant-shared, admin-managed
# secret scope, so a keyed WASM tool (network + `use_secret`) resolves its
# credential for EVERY user of the tenant from one operator-set key. The
# credential resolver checks the caller's own scope first and falls back to
# the tenant-shared scope; if neither has the key the tool gates with
# AuthRequired. The `<handle>` suffix must match the `handle` declared in the
# tool manifest's `runtime_credentials` (e.g. `market_data_api_key`).
# Ops/dev provisioning path; inert unless set.
# IRONCLAW_REBORN_DEV_SECRET__market_data_api_key=replace-with-shared-api-key
#
# Reborn Docker deployment/runtime knobs. Keep the local serve host loopback
# unless a platform such as Railway is fronting the container and requires
# 0.0.0.0. `IRONCLAW_REBORN_CONFIRM_HOST_ACCESS` is only for
# local-dev-yolo-style trusted host access and should stay unset for public
# container deployments.
#
# The Reborn Docker image defaults to local-dev so local `docker run` does not
# require Postgres. Set IRONCLAW_REBORN_PROFILE=production on Railway to seed
# the production/Postgres config and keep user extension install/activation
# state durable across image redeploys. If you keep local-dev/local-dev-yolo on
# Railway, attach a persistent volume at /data or set IRONCLAW_REBORN_HOME under
# RAILWAY_VOLUME_MOUNT_PATH; otherwise local-dev extension state under
# `$IRONCLAW_REBORN_HOME/local-dev/system/extensions` is container-local. The
# entrypoint fails closed for Railway local-dev profiles without a volume unless
# IRONCLAW_REBORN_ALLOW_EPHEMERAL_RAILWAY=true is set for disposable tests.
# IRONCLAW_REBORN_HOME=/data/ironclaw-reborn
# IRONCLAW_REBORN_PROFILE=local-dev
# IRONCLAW_REBORN_LOG=info
# IRONCLAW_REBORN_POSTGRES_URL=postgres://user:password@db.example.com/ironclaw?sslmode=require
# IRONCLAW_REBORN_SECRET_MASTER_KEY=replace-with-independent-secret-key-material
# IRONCLAW_REBORN_SERVE_HOST=127.0.0.1
# IRONCLAW_REBORN_SERVE_PORT=3000
# IRONCLAW_REBORN_CONFIRM_HOST_ACCESS=false
#
# There is no Slack or Telegram enablement variable. Channel webhook routes are
# always mounted; a channel goes live when its extension is installed and set up
# in the WebUI at /extensions.
#
# WebChat v2 SSO login (Google / GitHub). Setting either CLIENT_ID
# surfaces that provider's login button on the `serve` listener; the
# matching CLIENT_SECRET is required for the real code exchange. Each
# distinct OAuth identity maps to its own persisted user (looked up by
# provider + subject, linked across providers by a verified email), so
# different people who log in become different users with isolated
# threads. Every session is a stateless signed token (keyed off
# IRONCLAW_REBORN_WEBUI_TOKEN + the host tenant), accepted alongside the
# env bearer above.
#
# Admission is fail-closed: when a provider is configured you MUST set
# IRONCLAW_REBORN_WEBUI_ALLOWED_EMAIL_DOMAINS (below) — otherwise `serve`
# refuses to start. GitHub has no org allowlist and Google's `hd` check is
# optional, so without an email-domain allowlist any Google/GitHub account
# could log in (open registration).
#
# These deliberately live in the IRONCLAW_REBORN_WEBUI_* namespace,
# SEPARATE from the bare GOOGLE_CLIENT_ID / IRONCLAW_REBORN_GOOGLE_* vars
# in the OAuth section above:
# - bare GOOGLE_CLIENT_ID / GITHUB_CLIENT_ID → v1 gateway SSO login.
# - IRONCLAW_REBORN_GOOGLE_* → Reborn product-auth
# (connect a Google *credential* for the agent; requires a redirect
# URI). Setting these without the redirect URI makes every
# ironclaw command fail at startup — keep them unset unless
# you are configuring product-auth.
# - IRONCLAW_REBORN_WEBUI_GOOGLE_* (here) → Reborn WebChat *login*.
# Register {base}/auth/callback/{provider} as the authorized redirect URI,
# where {base} is IRONCLAW_REBORN_WEBUI_BASE_URL below (or the bound
# listener address in local dev).
# IRONCLAW_REBORN_WEBUI_GOOGLE_CLIENT_ID=
# IRONCLAW_REBORN_WEBUI_GOOGLE_CLIENT_SECRET=
# Optional: additionally restrict Google login to one Workspace domain
# (server-side `hd` claim) — narrower than the email-domain allowlist below.
# IRONCLAW_REBORN_WEBUI_GOOGLE_ALLOWED_HD=example.com
# IRONCLAW_REBORN_WEBUI_GITHUB_CLIENT_ID=
# IRONCLAW_REBORN_WEBUI_GITHUB_CLIENT_SECRET=
#
# REQUIRED when any provider above is configured: comma-separated list of
# verified-email domains allowed to log in. A login is admitted only when
# the provider asserts a VERIFIED email whose domain is in this list;
# everyone else is rejected and no session is minted. Set it to your own
# domain(s).
# IRONCLAW_REBORN_WEBUI_ALLOWED_EMAIL_DOMAINS=example.com,team.example.com
#
# Public base URL used to build the OAuth callback URLs for Reborn WebUI
# login and product-auth flows, including Notion MCP. Reborn-scoped only —
# it does NOT fall back to the v1 gateway's OAUTH_BASE_URL, so a legacy v1
# setting cannot rewrite Reborn callback URLs. Absent this var, Reborn uses
# the bound listener address. Set it to your public URL in production. Google
# product-auth still uses IRONCLAW_REBORN_GOOGLE_OAUTH_REDIRECT_URI explicitly.
# IRONCLAW_REBORN_WEBUI_BASE_URL=https://myapp.example.com
#
# Optional per-call HTTP timeout (whole seconds) for the OAuth provider
# token/userinfo requests, applied to every configured provider. Defaults
# to 20s. Raise it on a slow or cross-border path to the provider (e.g.
# `github.com`) where the exchange times out. If the provider host is
# actually blocked/throttled, route through a proxy instead — the OAuth
# client honors the standard HTTPS_PROXY / ALL_PROXY env vars.
# IRONCLAW_REBORN_WEBUI_OAUTH_HTTP_TIMEOUT_SECS=30
# ─── Skills ────────────────────────────────────────────────────────────
# Regex-pattern skill auto-activation is a config-file setting, not an env
# var: set `regex_activation_enabled = false` under `[skills]` in the
# ironclaw config file to make only keyword/tag activation and explicit
# `/skill` mentions select a skill (see
# crates/app/ironclaw_config/src/config_file.rs, SkillsSection). The former
# SKILLS_REGEX_ACTIVATION_ENABLED env var is not read by anything.
# ─── Test / CI: OS keychain ────────────────────────────────────────────
# Set to "1" to stop the secrets master-key lookup from touching the real OS
# keychain (macOS Keychain / Linux Secret Service). Without it, a test or
# tool run that resolves the master key while SECRETS_MASTER_KEY is unset
# pops a macOS Keychain authorization dialog (or blocks on a locked Secret
# Service). Crate unit tests are already covered by cfg!(test); set this for
# integration/e2e runs (the CI workflows set it automatically). Leave UNSET in
# production so the real keychain fallback works.
# IRONCLAW_DISABLE_OS_KEYCHAIN=1
# Logging
RUST_LOG=ironclaw=debug,tower_http=debug