For AI agents: a documentation index is available at https://www.plungeai.com/docs/llms.txt. Append .md to any page URL, or send Accept: text/markdown, to get markdown. Setup instructions for agents are at https://www.plungeai.com/docs/agents.md. One ozk_ key opens every plane, models included.

Documentation Index: fetch the complete documentation index at /llms.txt. Use this file to discover all available pages before exploring further.

oceancode reads a JSON config file and a set of environment variables. Nothing needs to be configured to start — every key falls back to a built-in default.

Config file locations and precedence

There are two config files, and both are optional.

ScopePathNotes
Global$OC_CONFIG, else <config-dir>/oceancode/oceancode.jsonOne file for every project you run.
Project<project>/.oceancode/oceancode.jsonc, then <project>/.oceancode/oceancode.jsonPer-repository, kept next to the code.

<config-dir> is $XDG_CONFIG_HOME when set, otherwise ~/.config — on every platform, macOS included (the binary uses the XDG layout everywhere, not ~/Library).

Precedence, lowest to highest: built-in default → project file → global file → the managed file (12) (crates/ocean-app/src/services.rs:3000). The global file is layered over the project file, so a key set in both takes the global value; the jev section is the one exception, read per file (13). Within the project directory, oceancode.json is merged over oceancode.jsonc when both exist. Merging is per section, last writer wins.

Comments and trailing commas are allowed in the .jsonc file.

Top-level keys

Every key is optional; an empty or absent value takes the built-in default. Unknown keys are ignored, so a file that still carries the native-TUI keys removed on 2026-10-05 (tui, keybindings, disabled_providers, notifications) loads unchanged.

KeyTypeDefaultMeaning
$schemastringnoneJSON-schema URL, for editor completion only.
modelstringprovider defaultDefault model, as provider/model.
effortstringnoneReasoning effort a new session's model runs at, as the model's own level name (xhigh, high, on, off, minimal, …; /effort lists the levels the current model has). Any level without whitespace loads; one the model does not list sends no effort field. Wins over ~/.claude/settings.json's effort when both name the same model. An empty value never overrides an earlier layer.
default_agentstringbuildAgent a new session starts in.
modestringmodelThe work mode: a diagram id (lowercase letters, digits and dashes, starting with a letter), such as delegate or race. model lets the model decide, as before work modes. An id no diagram has runs model, with a log line. A session's own pick (/mode, F4) and agents.<id>.mode come first. See 23 · Work modes.
test_commandstringnoneThe project's test command, run by a work mode's tests gate that names no command (Race needs it). It runs through the bash permission rules.
agentsobjectnonePer-agent overrides, keyed by agent name. Each agent may set model, prompt, temperature, disable, tool_profile (default / codex — apply_patch is the sole mutation tool / hashline — the content-anchored hashline tool replaces edit), and effort. model (provider/model) and effort (a level name) are the agent's defaults: when a session switches to the agent (Shift+Tab, or a new session started in it) it takes that model, when the catalog lists it and its provider is connected, and that effort, clamped to the levels the model offers (the highest offered level at or below it, else the lowest; none on a model without levels). An empty field keeps the session's own. An agent that sets both model and effort also makes a task call naming that model (model: "provider/id") run at that effort, over a modelSettings row in ~/.claude/settings.json for the same model. The pager edits the rows for build, plan, ask and debug under F2 › Agent defaults (22).
agents.<id>.modestringnoneThe work mode a session of that agent runs when the session picked none itself; the picker's d writes it. This is a diagram id, not the mode: line of an agent's markdown file (primary / subagent / all). See 23.
providersobjectnonePer-provider settings (endpoints, options).
formatterbool or objectbuilt-ins onCode formatters: false/true toggles the built-ins; an object overrides them per formatter.
instructionsarray of stringsnoneExtra system-prompt sources — each a file path (~- or working-dir-relative) or an http(s) URL.
mcpobjectnoneMCP servers, keyed by name.
oceanobjectnoneOcean Platform integration — see 15 · Platform mode.
permissionarray* * allowBase permission rules (allow / ask / deny); last matching rule wins. An empty config allows every call except the shell's dangerous floor, an external_directory ask and denied .env reads; add bash * ask to make every shell command off the read-only safe list ask (the posture Jev's permission point advises on, 13).
permission_modestringaskDefault permission mode applied at boot: acceptEdits, dontAsk, bypassPermissions, or empty to ask on every side effect. An empty value never overrides an earlier layer. See 12 · Permissions and sandbox.
shellobjectbuilt-in guardShell tool-guard overrides: safe_list_extra (extra read-only commands), allow / deny (Tool(pattern) rules layered on the classifier); plus kind (auto / bash / sh / powershell / cmd, default auto) — the shell the bash tool spawns, mainly for Windows (auto = sh on Unix, PowerShell on Windows). See 12 and 17 · Distribution and updates.
child_envobjectstrip secretsHow a spawned child's environment is composed: inherit (all / core / none), include_only, set (name→value), strip_secrets. See 12.
sandboxobjectoffOS isolation profile: profile (off / workspace / readonly / strict), deny (roots refused even inside the workspace), network (off / allowlist), allow_hosts. See 12.
refsobjectnoneProject-reference aliases: refs maps @name → a path; a @name/… path in any file tool expands to it and its root is auto-allowed through the external-directory prompt. See 12.
tool_outputobjectbuilt-in thresholdsOverrides for tool-output truncation limits (built in: 2,000 lines / 50 KiB). A result over them reaches the model as a head preview with the full output saved to a spill file it can read; this applies to every tool that does not page itself, bash included.
claudeobjectnoneClaude Code (Pro/Max subscription) transport settings.
ledgerobjecton, tideline = 40% of the model's context, block = 70% of the lineSession Ledger settings, under ledger.tideline (the aliases ledger.shelve and ledger.window still parse): tideline.percent (the tideline — the line — as a share of the model's context, 1..=100, default 40 — while the window's real-token gauge is at or over it, the oldest closed block leaves the window); tideline.block (how much a block holds before it closes: a token count used verbatim (70000), or a share of the line as a string ("35%", 1..=100) that is re-derived whenever /tideline or the route changes the line — the rule "cut 35 % per cut" stays 35 % on every model; unset = 70% of the line; 0, "0%", "101%" and a string without % are refused at load); tideline.tokens (the fixed-token line used only when the model's context is unknown, default 300k; 0 = the model's own ceiling). The keys of the old band geometry — low, reserve, profile under the tideline block and ledger.hard_tokens — are removed: an old config still loads, they are ignored, and the load logs one warning naming them. ledger.model — the merge/lint model, default the session's (empty): every merge and lint call is a separate full-price request that never touches the session's cache prefix, so an empty value bills it at the session model's price — set a cheaper one (provider/model). Examples {"ledger":{"tideline":{"percent":50}}}, {"ledger":{"tideline":{"percent":20,"block":"35%"}}} (a 200 K line on a 1 M model, 70 K per cut), {"ledger":{"tideline":{"tokens":500000,"block":20000}}} or {"ledger":{"model":"openai/gpt-5-mini"}}. See 06 · Session ledger and export.
retention.daysnumber7 (0..=3650)How many days an idle session is kept: past it the session (with its whole sub-agent tree) is deleted from oceancode.db and its Session Ledger directory goes with it. 0 = off. One setting for the database and the ledger; nothing is deleted for 24 hours after the sweep is first armed. /retention reads and sets it. See 18 · Operations.
database.retention_daysnumbernoneLegacy fallback: read only when no config layer has a retention section, and only when > 0. (database.vacuum is no longer read.)
ledger.retention_daysnumbernoneIgnored since retention.days; a config that still sets it loads with one warning at boot.
compressstringsafePrompt compression of tool results, safe (the default) or off. safe runs five lossless stages (ANSI strip → fold of identical lines → the session directory written ./ → a result identical to an earlier one becomes [same output as <tool-use id>] → a run of lines found in an earlier result becomes [↑<n> lines same as <tool-use id>:L<a>-L<b>]), on the copy of the request sent to the provider only — the stored session is never changed and the tideline cuts on the same turns to within the token estimate, and never earlier. Files and images are never touched. Overridden by OC_COMPRESS; an unknown value is read as the default and logs one warning.
subagentobjectnoneDefault native sub-agent model as subagent.model = provider/model (e.g. {"subagent":{"model":"openai/gpt-5-mini"}}). The model a session's sub-agent children run when the session sets no /subagent override and the fleet router pins none (env.CLAUDE_CODE_SUBAGENT_MODEL, applied while the subscription slot is live); empty (unset) leaves children on the spawning session's own model. A value without a / is rejected. Since 2026-10-21 a set subagent.model is the default ahead of the fleet router's pin.
subagent.effortstringnoneReasoning effort sub-agents run at — the model's own level name, as for effort. Applies to subagent.model, or to the router's sub-agent model when subagent.model is unset; when both name the same model and this is unset, the ~/.claude/settings.json effort is kept.
subagent.forceboolfalsetrue makes the task tool ignore a per-call model: and run the sub-agent default — the same as CLAUDE_CODE_SUBAGENT_MODEL_FORCE=1 in ~/.claude/settings.json (either one forces).
subagent.max_concurrentnumbernone (0..=64)Sub-agents that may run at once in a session's whole tree. Unset: the work mode's own limit, else none. A set value wins in every mode, Model included; 0 means no sub-agents. See 23.
subagent.max_per_turnnumbernone (1..=1000)Sub-agents one turn may start before you are asked whether to go on. Unset: the work mode's own limit, else none.
subagent.max_depthnumber4 (1..=4)How deep sub-agents may nest. Unset: the work mode's own limit, else 4.
workflows.enabledbooltrueWhether the host-run workflow conductor and goal mode are available at all. false turns the conductor off for the session.
workflows.max_concurrent_agentsnumber8 (1..=1024)Concurrency ceiling: how many agents a single workflow run may execute at once. A value outside 1..=1024 is rejected at load.
workflows.agent_budgetnumber128 (1..=1024)Total number of agents a single run may spawn before it stops. A value outside 1..=1024 is rejected at load.
workflows.max_run_minutesnumber120Wall-clock cap on a single run, in minutes.
workflows.agent_timeout_minutesnumber20 (0 = off, else 1..=1440)Per-child await bound: how long the host waits on one sub-agent (a single agent() call) before it cancels that child alone and returns it to the script as success:false with stop_reason: "timeout" — the run and its other agents keep going. 0 disables the bound (only the run's max_run_minutes then applies). A non-zero value outside 1..=1440 is rejected at load.
workflows.orchestratestringoffoff | always. always wraps every prompt in the goal workflow (goal mode): the prompt launches a background goal run and the turn returns at once, with the run's outcome arriving later as a workflow result in the session; off runs each prompt as a plain turn. This is a config key only — Claude Code's ultracode setting does NOT switch it on. Since work modes, always with no mode set is read as mode: "goal" (23); a set mode wins.
skills.modestringallSkill discovery mode: all (every discovered skill is a candidate) or allowlist (only skills whose id is in skills.enabled are candidates; every other skill is disabled and costs zero prompt tokens). This is the project tier — the per-skill user toggle lives in ~/.oceancode/skill-state.json (oceancode skill enable/disable). See 09 · Capabilities.
skills.disabledarray of stringsnoneQualified skill ids the project turns off. A project can disable a skill but can never re-enable one the user disabled — the user tier is resolved first.
skills.enabledarray of stringsnoneThe allowlist consulted only when skills.mode = "allowlist": the skill ids that stay enabled — each a stable <tier>.<eco>:<name> id (see 09 · Capabilities) or a bare name (matching every copy of that name).
skills.rosterstringnamesHow the system prompt lists skills: names (one line of names, no descriptions — the default since 2026-10-21) or full (an <available_skills> element with name, description and location per skill — the default before). The skill tool loads any enabled skill by name either way.
jevobjecton with a keyThe TypeSafe Jev decision layer, on whenever a TypeSafe key resolves (oceancode key typesafe <key>, else OC_TYPESAFE_API_KEY, else TYPESAFE_API_KEY): enabled (an opt-out — false in either the global or the project config turns it off), endpoint (default https://api.typesafe.ai/v1/systemone), model (versioned id), budgets, one mode per decision point (permissions, output_view, supervisor, triage, visibility, check, guidance, snippets, effort, work_mode = off/shadow/act; unset → the point's default: act for check, guidance, snippets, effort, work_mode (asked only under the Auto work mode), off for the other five), supervisor_max_continuations, prewarm, thresholds (including check_pass, check_remaining, supervisor_no_progress, guidance_yes, guidance_no, effort_confidence, work_mode_confidence). A project config may set only enabled and the modes. Deprecated, accepted with one warning and never read: tools (alias tool_tiers) and relevance (points retired 2026-10-21), supervisor_every_steps, and the thresholds tools_confidence, tools_min_p, relevance_needs, relevance_min_p, relevance_rerank, permission_scope, supervisor_looping, supervisor_loop_progress. See 13 · Jev decisions.
updateobjectauto-check on, stableSelf-updater settings: auto_check (bool, default true) checks for a newer release on boot; channel (stable / beta, default stable) selects release visibility; endpoint (string, unset → GitHub Releases) overrides the release-metadata source. Overridable per run by OC_NO_UPDATE_CHECK / OC_UPDATE_CHANNEL. See 17 · Distribution and updates.
queueobjectdefault_delivery: queuePrompt-queue defaults: default_delivery (queue — after the live turn, or steer — into the live turn) is how a prompt with no explicit delivery is admitted.
jobsobjectmax_concurrent: 4, spill_max_bytes: 5242880Background-job limits for the bash background:true / monitor / loop / scheduler tools: max_concurrent running jobs and spill_max_bytes per-job output-spill cap. There is no job timeout: a job runs until it ends or job_kill, unless the run has a wall clock (OC_MAX_MINUTES), which reaps it.
checkpointsobjectenabled: falseWhole-tree snapshots: enabled takes one before every edit/write/apply_patch/bash call for the HTTP /session/{id}/undo·/redo routes (about 1.8 s per call on a 40k-file project; the user's own .git is never touched). /rewind does not need it: the file tools keep a copy of each file before they change it.
contextobjectdurable_rules: trueContext-epoch options: durable_rules injects each entered directory's rule file once as a durable message so it survives context compaction.
model_fallbackarray of stringsnoneOrdered provider/model routes tried, in order, after the primary model fails. Paired with fallback.
fallbackobjectcooldown_seconds: 60Provider-fallback options: cooldown_seconds is how long a model_fallback route is skipped after it fails.

Environment variables

Set these in the shell before launching. A slash command or an oceancode run flag, where one exists, overrides the environment for that session (see 08 · Bounding a long run).

VariableMeaningDefault
OC_CONFIGAbsolute path to the global config file, overriding its default location.unset → <config-dir>/oceancode/oceancode.json
OC_CONFIG_DIRDirectory that holds the project oceancode.jsonc / oceancode.json. When set (non-blank), the project config is read from $OC_CONFIG_DIR instead of <cwd>/.oceancode/, so config can live outside the repo — a read-only checkout, or a benchmark board that grades the whole workspace tree (B6). Only the project tier moves; the user and managed tiers are unaffected.unset → <cwd>/.oceancode/
OC_MANAGED_CONFIGAbsolute path to the managed (admin/enterprise) config file, overriding its OS default. It is the highest-precedence layer, so it overrides the project and global files. See 12 · Permissions and sandbox.unset → macOS /Library/Application Support/oceancode/managed_config.json, Linux /etc/oceancode/managed_config.json
OC_REQUIREMENTS_PUBKEYTrusted ed25519 public key (64 hex chars) that a managed requirements.json signature is verified against; an unsigned or tampered file is refused, never applied.unset → no key; managed requirements are not enforced
OC_SERVER_USERNAMEBasic-auth username the HTTP server accepts.oceancode
OC_SERVER_PASSWORDBasic-auth password. Empty disables auth; a non-loopback bind refuses to start without it.unset (auth off)
OC_MODELS_URLOverride URL for the models catalog.the built-in models.dev URL
OC_MODELS_PATHPath to the local models-catalog cache file.a file under the cache dir
OC_DISABLE_MODELS_FETCHAny non-empty value skips fetching the remote models catalog (offline).unset (fetch on)
OC_NO_UPDATE_CHECKAny non-empty value suppresses the boot-time check for a newer release. The check is also skipped on first run and when update.auto_check is false; the first launch is telemetry-free regardless. See 17 · Distribution and updates.unset (check on)
OC_UPDATE_CHANNELForce the release channel for oceancode update: stable or beta. Overrides the update.channel config key for that run.unset → update.channel (default stable)
OC_INSTALL_DIRInstall / uninstall destination directory for the installers and oceancode uninstall.unset → $HOME/.local/bin (Windows %USERPROFILE%\.oceancode\bin)
OC_MINISIGN_SECRET_KEYRelease lane only — path to the minisign secret-key file scripts/sign/sign-artifacts.sh signs artifacts with. Read by the release scripts, never by the running binary; never committed.unset
OC_WINDOWS_CERT_THUMBPRINTRelease lane only — Authenticode code-signing certificate thumbprint scripts/sign/authenticode-windows.ps1 uses. Read by the release scripts, never by the running binary.unset
OC_TUICompatibility only. pager is accepted and changes nothing (grok is refused as unknown) — oceancode always starts Ocean pager; ocean fails with "the native TUI was removed; oceancode starts Ocean pager". --tui takes the same values.unset → Ocean pager
OC_PAGER_BINAbsolute path to the Ocean pager binary (ocean-pager) that oceancode execs.unset → beside oceancode, then PATH
OC_PAGER_HOMESet by oceancode for the pager it execs: the pager's state directory. Read by ocean-pager, not the engine; every pager variable is in 19 · Ocean pager.<data>/oceancode/pager
OC_RG_BINAbsolute path to a ripgrep (rg) binary. The bash tool rewrites a plain recursive grep -r … to rg and puts a directory holding that binary as rg first on the child PATH (a symlink/copy shim under <data dir>/bin/ when the file is named otherwise). The pager passes its embedded ripgrep automatically; set this only to override it or on a machine without one (Windows).unset → the pager's embedded rg, then rg beside oceancode, then rg on PATH
OC_MAX_MINUTESWall-clock bound for a run, in minutes. Background jobs the run starts (bash background:true, monitor, loop, scheduler) are reaped with it; unset, they run until they finish or job_kill.unset (no clock bound)
OC_MAX_USDSpend bound for a run, in US dollars.unset (no budget bound)
OC_MAX_STEPSPer-turn step cap at the root, 1–1000. A turn boundary the run auto-continues past, not a stop.300
OC_MAX_SUBAGENT_STEPSPer-turn step cap for a sub-agent. Sub-agents stop at it.300
OC_PLANoff disables the planning discipline for the run: no todo directive in the system prompt on either route, no plan-missing reminder, and a settled turn with open todos is not worked off. The PLAN panel, /plan and any todo block the model writes keep working. See 05 · Plan mode and todos.unset (on)
OC_COMPRESSPrompt compression profile for the run, safe or off; overrides the compress config key. An unknown value is read as the default and logs one warning.unset → the compress key (default safe)
OC_READ_STEERBy default cat <paths>, head [-n N], tail [-n N] and sed -n '<range>p' on files that exist under the command's working directory are answered by the read tool without starting a shell: line numbers, paging, truncation guards, the .env deny and freshness tracking apply exactly as for a direct read. refuse restores the old refusal (the error names the exact read call by absolute path); off runs pure reads in the shell as typed. Pipes, redirects, chains, globs, missing paths, tail -f and sed -i always run. POSIX shells only.unset (serve)
OC_MAX_OUTPUT_TOKENSOverrides the model's per-request output-token cap, clamped to the model's own limit.the model's published maximum
OC_EXPERIMENTAL_BACKGROUND_SUBAGENTS0 or false disables background sub-agents (the task tool's background: true); on by default since 2026-10-13. Foreground and background sub-agent runs alike now emit spawned/finished lifecycle frames — foreground runs also stream progress frames — that the Ocean pager renders as a live sub-agent roster.unset (on)
OC_WEBSEARCH_PROVIDERForce the web-search provider: exa or parallel.chosen per session
OC_MCP_META_TOOLS1 swaps the flat MCP tool catalog for the search_tool/use_tool meta-dispatch once the connected tool count passes 64. Above 128 tools the swap always happens (providers reject a longer tools array). See 11 · MCP servers.unset (off below 128; forced on at 129+)
OC_MCP_WAIT_SECONDSWhole seconds a prompt's first model request waits for the MCP servers configured at boot to finish connecting, so their tools are in that request instead of arriving in the next one (a tool list that grows between two steps of a prompt re-writes the provider's cache). 0 never waits; a server still connecting at the bound is not waited for. Sub-agents never wait. See 11 · MCP servers.5
OC_LOGEngine log level for the redacting tracing subscriber: trace, debug, info, warn, or error. Overrides the obs.log_level config key; an unrecognized value logs a one-line notice and falls back to info. Secret-shaped values are masked before any log write. See 18 · Operations.unset → obs.log_level (default info)
OC_TERMINALSet to 1 by the app in every shell and tool it spawns, so tools can detect they run under oceancode. Exported, not read.set by the app
OC_HOOK_EVENTSet by the app on every hook command handler to the firing event's name (PreToolUse, Stop, …). Exported, not read. See 10 · Hooks.set per hook invocation
OC_PROJECT_DIRSet by the app on every hook command handler to the project directory (also exported as CLAUDE_PROJECT_DIR, and used as the handler's working directory). Exported, not read. See 10 · Hooks.set per hook invocation
OC_MODEL_FORMATLegacy tool-result format switch; no longer read — every result renders in the native markdown format.inert
OC_TUNNEL_TOKENPlatform build. The OceanTunnel session token, read at the highest priority — above OCEAN_TUNNEL_TOKEN, then ocean.tunnel_token_file, then the inline ocean.tunnel_token. It supplies a token; it does not turn platform mode on. See 15 · Platform mode.unset
OCEAN_TUNNEL_TOKENDeprecated: still read as a legacy fallback for OC_TUNNEL_TOKEN (logs one deprecation warning per process); set OC_TUNNEL_TOKEN instead. See 15 · Platform mode.unset
OC_SSO_TOKENPlatform build. A per-request gateway SSO session token. When set, the route layer sends it as the X-Ocean-SSO-Token request header (no Bearer prefix) on the configured https gateway host only, leaving the wallet Authorization: Bearer (your ozk_ key) intact; read at runtime, never persisted. NOTE: the inference gateway does not yet read X-Ocean-SSO-Token, so it is ignored server-side until that lands. To store one, use oceancode login --sso-token. See 15 · Platform mode.unset
OC_JEVoff, shadow or act: overrides every Jev decision point's mode (off turns the layer off whatever the config says). It never supplies a key — without one the layer stays off.unset → the config
OC_JEV_ENDPOINTOverrides jev.endpoint (the Jev POST URL). The only way to use plain http, and only to a loopback host (127.0.0.1, localhost, ::1).unset → jev.endpoint, else https://api.typesafe.ai/v1/systemone
OC_TYPESAFE_API_KEYThe TypeSafe API key when none is stored (oceancode key typesafe wins), sent only to api.typesafe.ai (never to another host); never in config; stripped from child processes like every *KEY* variable. The direct API without a key keeps the layer off.unset
TYPESAFE_API_KEYThe same key under the name TypeSafe's own SDKs read; OC_TYPESAFE_API_KEY wins over it.unset

Test and bench knobs

These steer test, benchmark, and profiling runs; they are not part of normal operation.

VariableMeaningDefault
OC_DETERMINISTIC1 pins ids, clocks, and other non-determinism for reproducible runs and replay.unset
OC_METRICS_ADDRhost:port to serve runtime gauges (uptime, worker/task counts) for profiling.unset (nothing listens)
OC_TEST_HOMEOverrides the home directory used for path resolution, for tests.the real home directory
OC_CACHE_HINTS_MUTATEToggles prompt-cache-hint mutation, for cache experiments.unset
OC_CACHE_KEEPALIVE_MINUTESMinutes between prompt-cache keep-alive touches. While a step waits (a sub-agent, a long bash) or the session idles, the engine re-sends the last request with max_tokens: 1 at this interval so the provider's cached prefix is read again and its one-hour clock restarts — a cache read instead of the full re-write a cold return pays (about 1:80 on Fable 5.1: 0.025× read against a 2× one-hour write, ~$0.06 against ~$5 on a 250k prefix). 0 or off disables it. Each touch is a session.cache.touched event and its cost joins the session's spend.50
OC_CACHE_KEEPALIVE_MAXTouches per request before the keep-alive gives up (≈ 40 h at the default interval; a model's break-even against one 2× re-write is 2× ÷ its cache-read price: 80 touches on Fable 5.1, 20 on a 0.1× model).48
OC_CONFORMANCE_TARGET_URLTarget server URL for the conformance harness.unset
OC_TEST_TIMEOUT_SCALEMultiplies harness timeouts (ocean-testkit, dev-only); floored at 1.0, so it can only lengthen, never shorten, a timeout.unset (1.0)
OC_LIVE_CONFIRM1 arms the money-gated live benchmark drivers (scripts/bench/task11-stratified.sh, swebench-parity.sh, marathon-month-gate.sh, run-official-board.sh) to spend against a real model; unset, each refuses to spend and only --self-tests. Never set by check.sh.unset (never spends)
OC_SQLITE_CACHE_KBPer-connection SQLite page-cache size in KiB (PRAGMA cache_size = -<kb>), applied to every writer and read-pool connection. A soak/measurement knob for isolating engine memory from the box's page cache; leave unset in normal use.unset → SQLite default (≈64 MB)
OC_READ_POOL_SIZENumber of connections in the session store's read pool. A soak/measurement knob to bound per-connection memory when profiling; leave unset in normal use.unset → available_parallelism()
OC_PAGER_DIALECT_COVERAGE_OKNot read from the environment: the sentinel line the shared ACP dialect's coverage test prints (ocean-acp pager_dialect_coverage_ok in extensions/dialect.rs: methods=<n> implemented=<n> unmapped=0 — every Implemented ext method has a dispatch arm). Listed because the name has the OC_ shape this table is checked against.—
OC_JEV_FIXTURE_DIRDirectory the Jev policy-table tests read their recorded fixtures from, instead of each crate's tests/fixtures/jev (read by ocean_jev::testkit::load_fixture; set by scripts/gates/check-jev.mjs --self-test to a planted copy). Test-only; the binary never reads it.unset (the crate's own fixtures)
OC_LLM_CACHE_DIAGAnthropic cache diagnostics are on by default: every request opts in, first with a null previous ID, then with that session’s previous response ID. 0 disables them. The API reports structural divergence, pending or unavailable comparisons; token usage determines whether the cache hit. IDs reset on restart or session deletion.1
OC_LLM_DUMPDirectory to write every provider-native request body into as <seq>.json (a process-wide counter), so two consecutive steps can be diffed byte for byte in a prompt-cache audit (read by ocean_llm::route::client). Diagnostic; bodies contain the whole context — use a private directory and delete it afterwards.unset (off)
OC_TOOL_REPLAYPath of a recording ({"<tool call id>": {"ok": bool, "text": string}}); the tool registry then answers every call from it by the model's call id instead of running the tool (an unrecorded id is an error result), so a recorded bash or edit never runs again. Compiled in only with ocean-agent's test-util feature (cargo build --release -p ocean-cli --features test-util, which scripts/probes/real-replay-probe.sh does into target/replay-bin) — the shipping build never reads it. An unreadable or malformed recording stops the process.unset

Claude Code settings mirror

On the subscription route (claude-code/… models, run through the claude CLI) OceanCode follows Claude Code's own settings, so both tools start the same way. It reads three files, lowest precedence first, and merges them per key (modelSettings per model):

TierPath
user~/.claude/settings.json
project<project>/.claude/settings.json
local<project>/.claude/settings.local.json
KeyWhat OceanCode does with it
modelWith no model in oceancode.json and claude on this machine, the catalog default and every new session are pinned to claude-code/<model> — the id verbatim, [1m] suffix included (--model claude-fable-5-1[1m]). An explicit model in oceancode.json wins.
effortLevel, modelSettings.<model>.effortLevelThe effective effort (modelSettings over effortLevel, matched with and without the [1m] suffix) becomes the pinned variant and reaches the CLI as --effort <level> — low, medium, high, xhigh or max; any other value is shown but not passed. ultracode plays no part: since Claude Code 2.1.284 it is its own toggle at any effort level, so the written effort (the fleet router's max) is what the row, the pinned variant and the wire carry (2026-09-29)
ultracodeDrives the status bar's ⚡ ultracode on mark (and the persisted preference). /ultracode still toggles it by hand until the next settings change. Claude Code honours the same key ("ultracode": true makes every Claude Code session ultracode).
env.CLAUDE_CODE_SUBAGENT_MODELThe sub-agent model the fleet router pins. Applied on the native route while the subscription slot is live (2026-09-29): shown on the identity row as sub-agents <name> and the model a session's children run, as anthropic/<id> at that id's modelSettings effort — unless /subagent overrides it per session (the override holds until the router pushes a new value, then it is cleared). A router push re-seeds running sessions without a restart.
env.CLAUDE_CODE_SUBAGENT_MODEL_FORCE"1" marks the router's sub-agent model as forced. Reported (GET /claude/settings) and read alongside the model; not enforced — an explicit model on a task call still outranks the router's default.
alwaysThinkingEnabledReported (GET /claude/settings); not yet acted on.
hooksSee 10 · Hooks.

Live. The engine watches both .claude directories. Saving any of the three files re-reads the mirror and the hooks within about a quarter second: sessions still on the previously mirrored model move to the new one, except a session whose agent has its own agents.<id> row (a model you picked by hand in /models is kept), and the UI shows Claude Code settings reloaded — <model> · effort <level> · ultracode on|off when a mirrored value changed (the fleet router rewrites the file periodically; an unchanged rewrite is silent). A save of oceancode.json is live too: the pager toasts Settings applied: … with each value that moved, and an open session still on its agent row's old value follows the row (19).

Nothing is mirrored when claude is not installed (the settings are still read and reported) or when the files name no model. Managed (enterprise) settings are not read. The watcher follows the .claude directories that exist when the engine starts — a project .claude/ created afterwards is read at the next start (or /hooks → r).

Reasoning effort per provider

Set the effort in oceancode.json for every role, on any provider: effort (the main session), subagent.effort (sub-agents) and agents.<id>.effort (the effort a session runs at after Shift+Tab to that agent, clamped to the model's levels; with agents.<id>.model also set, a task call naming that model runs at it too). Option+Tab (or F3) in the pager steps the current session's effort through the model's levels; the next Shift+Tab loads the agent's default again. A write to the user or the project oceancode.json applies without a restart: running sessions keep their model and effort, new sessions and the next sub-agent get the new values.

Every model is offered its own reasoning levels, taken from models.dev reasoning_options: the model's effort list as listed (e.g. minimal…high on Gemini 3 Flash, low/high/max on GLM-5.3); on/off for a model that can only switch thinking on and off; low/medium/high for a model that takes only a thinking budget (1024 / 8192 / 24576 tokens, clamped into the model's range). A toggle model also offers off. Models without models.dev data (seed and config entries) fall back to the built-in Claude and GPT-5 tiers. The level you pick is sent as named — never mapped to a different one — and a level the model does not list sends nothing.

Protocol / providerRequest field sent
Anthropic Messagesthinking: {type: "adaptive"} + output_config.effort (Claude 4.6+); budget-token thinking on older Claude
OpenAI Responses (openai)reasoning.effort (+ reasoning.summary: auto)
OpenAI Chat, provider openaireasoning_effort
OpenAI-compatible chat (xAI, Z.AI, DeepSeek, Groq, Cerebras, OpenRouter, …)reasoning_effort; a toggle model also sends thinking: {type: "enabled"}, and off sends only thinking: {type: "disabled"}
Gemini (Google AI Studio)generationConfig.thinkingConfig.thinkingLevel (MINIMAL/LOW/MEDIUM/HIGH, Gemini 3+) or thinkingConfig.thinkingBudget (Gemini 2.5; off = 0 where the model allows it)
Bedrock, Azure, GitHub Copilot, Cloudflarenothing yet — no effort menu is shown

See also

Planned: TI-34

The docs assistant is not available yet. You can hand these docs to your own assistant instead.