Skip to content

Latest commit

 

History

History
209 lines (166 loc) · 9.32 KB

File metadata and controls

209 lines (166 loc) · 9.32 KB
title Configuration
type reference
summary Where Woopcode stores its settings, what each key means, and what happens when the file breaks.
prerequisites
related
/docs/guides/configuring-providers
/docs/guides/sessions-and-history
since 0.6.0

Configuration

Location

Platform Directory
macOS, Linux $XDG_CONFIG_HOME/woopcode/, or ~/.config/woopcode/

The directory is created on first run.

File Contents
providers.json Provider keys, the default provider, the selected model, the approval mode, session retention
sessions/ Saved conversations, one directory per project
models.json The model list

Configuration is global, not per-repository. Conversation history is the one thing scoped to where you are working: it lives under sessions/<project>/<session-id>.json, keyed by the repository root. See Sessions & history.

providers.json

{
  "defaultProvider": "google",
  "selectedModel": "gemini-3.6-flash",
  "approvalMode": "auto-read-only",
  "retentionDays": 30,
  "providers": {
    "google": { "type": "api", "apiKey": "..." }
  }
}
Key Type Default Description
defaultProvider string "google" Which provider a session starts with
selectedModel string first model of the provider Model id, as listed by woopcode models
approvalMode string "auto-read-only" One of the four approval modes
retentionDays number 30 Days a session survives after its last turn; 0 keeps them forever
sandbox boolean false Whether sessions start with sandboxed execution on
providers object three entries Keyed by provider id
providers.<id>.type string "api" How the provider authenticates
providers.<id>.apiKey string "" The stored key

Unrecognised keys are preserved when Woopcode rewrites the file, so anything you add by hand survives.

:::warning apiKey is stored in plain text, with no encryption and no keychain integration. The file is only as protected as your home directory. :::

Editing it by hand

You can, and Woopcode will read it. The safer path for the values that have a command is to use the command, because it validates: woopcode providers login verifies a key before saving it, and /approval cannot write a mode that does not exist.

An approval mode the parser does not recognise falls back to the default rather than being treated as permissive. An unreadable setting must not be able to widen what runs without asking.

When the file is corrupt

A providers.json or a session file that is not valid JSON — a truncated write, a bad hand edit — is moved aside rather than crashing every command that touches it:

Could not read provider config (invalid JSON). Moved it to
~/.config/woopcode/providers.json.corrupt-1785508675645 and started from
defaults.

Your broken copy is kept under that .corrupt-<timestamp> name; the next launch starts clean.

Retired providers

A provider that an earlier version offered and Woopcode has since dropped is removed from your config on startup — but only if it has no key stored. An entry with a key is left alone: deleting a credential silently would hide something you may want to remove yourself.

Environment

Location

Variable Effect
XDG_CONFIG_HOME Moves the config directory on macOS and Linux

Credentials

Woopcode reads an API key from the environment when one is present, and prefers it over the stored config. This is what lets it run somewhere with no writable home directory and no terminal to run setup in — a CI job, a benchmark container built fresh for every trial.

They are checked in this order, and the first one set wins:

Variable Provider
WOOPCODE_API_KEY Whatever WOOPCODE_PROVIDER names, or google
GEMINI_API_KEY google
GOOGLE_API_KEY google
GOOGLE_GENERATIVE_AI_API_KEY google
OPENAI_API_KEY openai
ANTHROPIC_API_KEY anthropic

An unusable provider is treated differently depending on which variable named it. WOOPCODE_API_KEY with WOOPCODE_PROVIDER is an instruction addressed to Woopcode, so naming a provider it has no client for is an error at startup rather than a failure on the first turn. A vendor variable is not an instruction — ANTHROPIC_API_KEY is usually exported for some other tool sharing the shell — so an unusable one is skipped and the search continues to the next, or to the stored config.

:::note A key in the environment is used as-is and never written to providers.json. Nothing is stored, which is the point for a container that is discarded after the run. :::

Behaviour

Variable Default Effect
WOOPCODE_PROVIDER google Pairs with WOOPCODE_API_KEY
WOOPCODE_MAX_ITERATIONS 40 Steps a turn may take before it stops to ask whether to keep going. Interactively the ceiling is a checkpoint, so it is set to catch a stuck loop rather than to ration requests — the provider rations those itself, and answering the checkpoint grants another 40. A headless run has nobody to ask, so this is the whole budget and exhausting it exits 2
WOOPCODE_MAX_WALL_SEC unset (off) Wall-clock seconds a turn may take, counted from process start. Pass the whole budget the harness enforces; a reserve is held back internally so the last step, the final answer and the session write still land. The loop stops on whichever budget binds first, and a spent clock exits 2 like a spent ceiling. Unset interactively, where a person decides when a turn has gone on too long
WOOPCODE_MAX_ATTEMPTS 3 Tries per provider request before the error surfaces
WOOPCODE_TOOL_HISTORY_BUDGET unset (off) Characters of tool history to keep before older results are compacted. Off by default — see the measurements in runtime/compaction.ts
WOOPCODE_THINKING_BUDGET -1 Reasoning depth; see below
WOOPCODE_NON_INTERACTIVE unset 1 stops Woopcode opening the setup wizard, so a missing key fails loudly instead of blocking on a prompt nothing can answer. CI=true does the same

A value that is not a positive integer is ignored with a warning on stderr, and the default is used. An unreadable setting never silently changes behaviour.

WOOPCODE_THINKING_BUDGET

Takes off, -1 (automatic, the default), or a token count. The three providers accept different things, so the same value does not mean the same thing everywhere — and a number is never faked into a budget the provider did not apply.

Value Google OpenAI Anthropic
off No thinking config sent reasoning.effort: none thinking: disabled
-1 Model decides Model default Model decides
a count Used as the token budget Model default Model decides

Only Gemini takes a token count. Current Claude models reject an explicit budget, and OpenAI takes an effort level rather than a number, so on both a count falls back to letting the model decide — which is what -1 already meant. On Gemini, budgets below roughly a thousand are ignored by the model rather than honoured.

Sandboxing

Read only when sandboxed execution is on. E2B_API_KEY is the one that decides whether it can be turned on at all — without it, --sandbox and /sandbox on refuse rather than falling back to running on this machine.

Variable Default Effect
E2B_API_KEY unset Required. No key, no sandbox
WOOPCODE_SANDBOX_TEMPLATE E2B's base image Template id to build sandboxes from
WOOPCODE_SANDBOX_TIMEOUT_MS 600000 How long a sandbox lives untouched. Refreshed before every command, so this is the window a single command has to finish in — ten minutes rather than E2B's five, because five is run_terminal's own timeout and a command using its whole budget would race the reaper
WOOPCODE_SANDBOX_MAX_FILE_BYTES 1048576 Files larger than this are not sent
WOOPCODE_SANDBOX_NETWORK full none blocks all egress from the sandbox. --sandbox-network overrides it
WOOPCODE_SANDBOX_ENV unset Comma-separated names to forward into the sandbox
WOOPCODE_SANDBOX_SETUP unset A command run once after the workspace is first pushed

As with the behaviour variables above, a value that is not a positive integer is ignored and the default is used, and an unreadable network mode falls back to full rather than to whatever a typo happened to spell.

:::warning WOOPCODE_SANDBOX_ENV is an allowlist, and it cannot be used to forward the agent's own credentials. WOOPCODE_API_KEY, E2B_API_KEY and any provider key are refused even when named explicitly, and the refusal is printed rather than silent — a token that was quietly not forwarded looks like a broken build much later. :::

See also