OpenCode Config Reference (opencode.json)

Updated by

Independent reference, not affiliated with Anomaly. Tables are generated from the OpenCode source at v1.18.33 (v1.18.33). Official documentation: opencode.ai.

OpenCode reads opencode.json or opencode.jsonc from ~/.config/opencode, from every directory between the project root and the working directory, and from .opencode/ folders, then deep-merges them with the nearest file winning. Both names are parsed as JSONC. The schema is published at https://opencode.ai/config.json, and unknown keys are silently ignored.

Where is opencode.json located?#

Sources merge from lowest to highest precedence, so a later row overrides an earlier one:

Order (low → high)SourceWhere
1Remote well-known config`<url>/.well-known/opencode` for each org you logged in to with `opencode auth login <url>`
2Global config~/.config/opencode/config.json, then opencode.json, then opencode.jsonc
3OPENCODE_CONFIGthe file the variable points to
4Project configopencode.json and opencode.jsonc from the worktree root down to the working directory; nearer files win
5.opencode directoriesopencode.json then opencode.jsonc in each .opencode/ up to the worktree root, ~/.opencode and $OPENCODE_CONFIG_DIR
6OPENCODE_CONFIG_CONTENTinline JSON in the variable
7Console organization configconfig of the active OpenCode Console organization
8Managed config directory/Library/Application Support/opencode (macOS), %ProgramData%\opencode (Windows), /etc/opencode (Linux)
9macOS managed preferencesMDM-deployed .mobileconfig profile; overrides everything above

The global directory is $XDG_CONFIG_HOME/opencode, ~/.config/opencode by default. Project files are looked up from the working directory up to the worktree root and applied from the root down. Within one directory opencode.jsonc loads after opencode.json, so it wins when both exist. The same config directories also supply Markdown agents from agent/ or agents/, Markdown commands from command/ or commands/, and plugin files from plugin/ or plugins/.

Merging is a deep merge: nested objects combine key by key and arrays are replaced, except instructions, which concatenates and removes duplicates, and plugin, which collects entries from every file and keeps one copy per package.

Which environment variables change config loading?#

VariableEffect
OPENCODE_CONFIGpath of an extra config file merged after the global config
OPENCODE_CONFIG_CONTENTinline JSON config merged after all files
OPENCODE_CONFIG_DIRextra config directory (agents, commands, plugins, opencode.json)
OPENCODE_DISABLE_PROJECT_CONFIGskip project opencode.json files and project .opencode directories
OPENCODE_PERMISSIONJSON merged into `permission` after every config source
OPENCODE_DISABLE_AUTOCOMPACTforces `compaction.auto` to false
OPENCODE_DISABLE_PRUNEforces `compaction.prune` to false

Two substitutions run on the raw text of every config file before parsing: {env:NAME} inserts an environment variable (empty when unset) and {file:path} inserts a file's contents.

opencode.json vs opencode.jsonc#

Both are parsed by the same JSONC parser, which accepts comments and trailing commas, so the extension changes nothing about syntax. The difference is precedence within a directory (.jsonc wins) and how OpenCode writes settings changed from the app: global changes go to the first of opencode.jsonc, opencode.json, config.json that exists, and a .jsonc file is edited in place so its comments survive.

What are all the opencode.json keys?#

KeyTypeDescription
$schemastringJSON schema reference for configuration validation
agentobject (agent name → agent)Agent configuration, see https://opencode.ai/docs/agents
attachmentobjectAttachment processing configuration, including image size limits and resizing behavior
attachment.imageobject—
attachment.image.auto_resizeboolean—
attachment.image.max_base64_bytesinteger—
attachment.image.max_heightinteger—
attachment.image.max_widthinteger—
autosharebooleanDeprecated. Use 'share' field instead. Share newly created sessions automatically
autoupdateboolean | notifyAutomatically update to the latest version. Set to true to auto-update, false to disable, or 'notify' to show update notifications
commandobject (command name → command)Command configuration, see https://opencode.ai/docs/commands
compactionobject—
compaction.autobooleanEnable automatic compaction when context is full (default: true)
compaction.preserve_recent_tokensintegerMaximum number of tokens from recent turns to preserve verbatim after compaction
compaction.prunebooleanEnable pruning of old tool outputs (default: false)
compaction.reservedintegerToken buffer for compaction. Leaves enough window to avoid overflow during compaction.
compaction.tail_turnsintegerMaximum number of recent user turns, including their following assistant/tool responses, to keep verbatim during compaction. By default retention is limited only by the preserved token budget.
default_agentstringDefault agent to use when none is specified. Must be a primary agent. Falls back to 'build' if not set or if the specified agent is invalid.
disabled_providersstring[]Disable providers that are loaded automatically
enabled_providersstring[]When set, ONLY these providers will be enabled. All other providers will be ignored
enterpriseobject—
enterprise.urlstringEnterprise URL
experimentalobject—
experimental.batch_toolbooleanEnable the batch tool
experimental.continue_loop_on_denybooleanContinue the agent loop when a tool call is denied
experimental.disable_paste_summaryboolean—
experimental.mcp_timeoutintegerTimeout in milliseconds for model context protocol (MCP) requests
experimental.openTelemetrybooleanEnable OpenTelemetry spans for AI SDK calls (using the 'experimental_telemetry' flag)
experimental.policiesobject[]Policy statements applied to supported resources, such as provider access
experimental.primary_toolsstring[]Tools that should only be available to primary agents.
formatterboolean | objectEnable or configure formatters. Omit or set to false to disable, true to enable built-ins, or an object to enable built-ins with overrides.
instructionsstring[]Additional instruction files or patterns to include
layoutauto | stretchDeprecated. Always uses stretch layout.
logLevelDEBUG | INFO | WARN | ERRORLog level
lspboolean | objectEnable or configure LSP servers. Omit or set to false to disable, true to enable built-ins, or an object to enable built-ins with overrides.
mcpobject (server name → server)MCP (Model Context Protocol) server configurations
modeobject (agent name → agent)Deprecated. Use `agent` field instead.
modelstringModel to use in the format of provider/model, eg anthropic/claude-2
permissionask | allow | deny | object—
plugin(string | [string, object])[]—
providerobject (provider id → provider)Custom provider configurations and model overrides
referenceobjectDeprecated. Use 'references' field instead. Named git or local directory references
referencesobjectNamed git or local directory references
serverobjectServer configuration for opencode serve and web commands
server.corsstring[]—
server.hostnamestring—
server.mdnsboolean—
server.mdnsDomainstring—
server.portinteger—
sharemanual | auto | disabledControl sharing behavior:'manual' allows manual sharing via commands, 'auto' enables automatic sharing, 'disabled' disables all sharing
shellstringDefault shell to use for terminal and bash tool
skillsobjectAdditional skill folder paths
skills.pathsstring[]—
skills.urlsstring[]—
small_modelstringSmall model to use for tasks like title generation in the format of provider/model
snapshotbooleanEnable or disable snapshot tracking. When false, filesystem snapshots are not recorded and undoing or reverting will not undo/redo file changes. Defaults to true.
subagent_depthintegerMaximum subagent nesting depth. Defaults to 1, which prevents subagents from launching subagents.
tool_outputobjectThresholds for truncating tool output. When output exceeds either limit, the full text is written to the truncation directory and a preview is returned.
tool_output.max_bytesintegerMaximum bytes of tool output before it is truncated and saved to disk (default: 51200)
tool_output.max_linesintegerMaximum lines of tool output before it is truncated and saved to disk (default: 2000)
toolsobject (tool → boolean)—
usernamestringCustom username to display in conversations instead of system username
watcherobject—
watcher.ignorestring[]—

theme, keybinds and tui are not opencode.json keys in this release: OpenCode drops them when it loads the file and migrates them to a tui.json beside it.

theme, keybinds and tui in opencode.json are dropped when it loads and migrated to tui.json
tui.json keyDescription
theme—
keybinds—
plugin—
plugin_enabled—
leader_timeoutLeader key timeout in milliseconds
attentionAttention notification and sound settings
promptPrompt size settings
scroll_speedTUI scroll speed
scroll_accelerationScroll acceleration settings
diff_styleControl diff rendering style: 'auto' adapts to terminal width, 'stacked' always shows single column
cursorTerminal cursor settings
mouseEnable or disable mouse capture (default: true)

How do I configure agents?#

Each entry under agent is keyed by agent name. A name matching a built-in agent overrides it; any other name creates an agent. Keys OpenCode does not recognise inside an agent are moved into its options.

Built-in agent names: plan, build, general, explore, title, summary, compaction
KeyTypeDescription
colorstring | primary | secondary | accent | success | warning | error | infoHex color code (e.g., #FF5733) or theme color (e.g., primary)
descriptionstringDescription of when to use the agent
disableboolean—
hiddenbooleanHide this subagent from the @ autocomplete menu (default: false, only applies to mode: subagent)
maxStepsintegerDeprecated. Use 'steps' field instead.
modesubagent | primary | all—
modelstring—
optionsobject—
permissionask | allow | deny | object—
promptstring—
stepsintegerMaximum number of agentic iterations before forcing text-only response
temperaturenumber—
toolsobjectDeprecated. Use 'permission' field instead
top_pnumber—
variantstringDefault model variant for this agent (applies only when using the agent's configured model).

How do I add a provider or a custom model?#

Each entry under provider is keyed by provider id. options accepts any extra keys beyond the ones listed; models is keyed by model id and accepts the model fields (name, limit, cost, modalities, options, headers, variants and others).

KeyTypeDescription
apistring—
blackliststring[]—
envstring[]—
idstring—
modelsobject—
namestring—
npmstring—
optionsobject—
options.apiKeystring—
options.baseURLstring—
options.chunkTimeoutinteger | falseTimeout in milliseconds between streamed SSE chunks for this provider (default: 300000). If no chunk arrives within this window, the request is aborted. Set to false to disable timeout.
options.enterpriseUrlstringGitHub Enterprise URL for copilot authentication
options.headerTimeoutinteger | falseTimeout in milliseconds to wait for response headers (default: 300000). Set to false to disable timeout.
options.setCacheKeybooleanEnable promptCacheKey for this provider (default false)
options.timeoutinteger | falseTimeout in milliseconds for full requests to this provider. Set to false to disable timeout.
whiteliststring[]—
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "local": {
      "npm": "@ai-sdk/openai-compatible",
      "options": { "baseURL": "http://localhost:11434/v1" },
      "models": { "qwen3-coder": { "name": "Qwen3 Coder" } }
    }
  },
  "model": "local/qwen3-coder"
}

How do I configure MCP servers?#

Each entry under mcp is keyed by server name and is either a local server started as a subprocess or a remote server reached over HTTP. { "enabled": false } on its own disables a server defined in another config file.

KeyTypeRequiredDescription
commandstring[]yesCommand and arguments to run the MCP server
cwdstringnoWorking directory for the MCP server process. Relative paths resolve from the workspace directory.
enabledbooleannoEnable or disable the MCP server on startup
environmentobjectnoEnvironment variables to set when running the MCP server
timeoutintegernoTimeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.
typelocalyesType of MCP server connection
KeyTypeRequiredDescription
enabledbooleannoEnable or disable the MCP server on startup
headersobjectnoHeaders to send with the request
oauthobject | falsenoOAuth authentication configuration for the MCP server. Set to false to disable OAuth auto-detection.
timeoutintegernoTimeout in ms for MCP server requests. Defaults to 5000 (5 seconds) if not specified.
typeremoteyesType of MCP server connection
urlstringyesURL of the remote MCP server

Can OpenCode 1.x read an OpenCode 2 config?#

Partly. 1.x lowers several OpenCode 2 keys to their 1.x names, ignores keys with no 1.x meaning, and refuses a v2 permissions array outright.

OpenCode 2 key1.x keyWhat 1.x does
permissions—config rejected with an error: "V2 permissions are not supported by OpenCode V1"
snapshotssnapshottranslated; the v1 key wins if both are set
mediaattachmenttranslated; the v1 key wins if both are set
compaction.keep.tokenscompaction.preserve_recent_tokenstranslated; the v1 key wins if both are set
compaction.buffercompaction.reservedtranslated; the v1 key wins if both are set
experimental.subagent_depthsubagent_depthtranslated; the v1 key wins if both are set
agentsagenttranslated; entries already under the v1 key win
commandscommandtranslated; entries already under the v1 key win
mcp.timeoutexperimental.mcp_timeouttranslated; the v1 key wins if both are set
plugins—ignored with a warning (no v1 equivalent)
providers—ignored with a warning (no v1 equivalent)
websearch—ignored with a warning (no v1 equivalent)
warming—ignored with a warning (no v1 equivalent)

Frequently asked questions#

Where is the OpenCode config file?#

The global file is ~/.config/opencode/opencode.json (or opencode.jsonc, or the older config.json). A project file is opencode.json or opencode.jsonc in the repository, at any level from the root to the working directory, or inside a .opencode/ folder. OPENCODE_CONFIG adds one more file and OPENCODE_CONFIG_DIR one more directory.

Should I use opencode.json or opencode.jsonc?#

Either. OpenCode parses both as JSONC, so comments and trailing commas work in both. If a directory has both, opencode.jsonc is merged last and wins on conflicting keys. Editing settings from the app preserves comments only in a .jsonc file, because a .json file is rewritten as plain JSON.

What is the OpenCode config merge order?#

From lowest to highest: remote well-known config from opencode auth login, the global config, OPENCODE_CONFIG, project files from the repository root down to the working directory, .opencode/ folders, OPENCODE_CONFIG_CONTENT, Console organization config, the system managed directory, and finally macOS MDM managed preferences, which override everything.

Where is the OpenCode config schema?#

At https://opencode.ai/config.json. OpenCode writes "$schema": "https://opencode.ai/config.json" into any config file it loads that lacks one, and creates the global file with only that line on first run, so editors that read $schema get completion and validation without setup. Keybinds and themes are validated against a separate schema, https://opencode.ai/tui.json, in tui.json.

Why does OpenCode ignore a key in opencode.json?#

Unknown keys are dropped silently when the file is decoded, so a typo produces no error. theme, keybinds and tui moved to tui.json. OpenCode 2 names such as plugins, providers, websearch and warming are ignored with a warning in the log, while permissions makes the whole file fail to load.

How do I configure MCP servers in opencode.json?#

Add an entry under mcp: { "type": "local", "command": ["npx", "-y", "my-server"] } for a subprocess, or { "type": "remote", "url": "https://..." } for HTTP. The default request timeout is 5000 ms, enabled: false keeps a server defined but stopped, and remote servers detect OAuth automatically unless oauth is false.

Sources

Release-by-release changes: OpenCode version tracker. All OpenCode pages: OpenCode reference index.