Skip to main content

Config File

opencode uses either JSON or JSONC (JSON with Comments) for all configuration files. Two separate config schemas exist: one for server and runtime settings (opencode.json) and one for terminal UI settings (tui.json).

The JSON Schema for each can be referenced via $schema for editor autocompletion and validation:

Minimal Config

{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-5",
"autoupdate": true,
"server": {
"port": 4096
}
}

This config sets the primary model, enables automatic updates, and binds the HTTP server to port 4096.

Configuration Precedence

opencode loads configuration from up to seven sources and merges them together. Later sources override earlier sources only for conflicting keys; all non-conflicting keys from every source are preserved.

Fetched from https://your-domain.com/.well-known/opencode during authentication. Organizations can enforce default settings this way.

Not configurable by the end user — it is applied before user configs.

Config Merging Behavior

Config sources are merged using shallow-to-deep object merging. Primitive values from later sources replace earlier ones. Arrays and objects are merged at the top level only.

Example: If the global config has { "model": "a", "autoupdate": true } and the project config has { "model": "b", "permissions": { "bash": "allow" } }, the merged result is:

{
"model": "b",
"autoupdate": true,
"permissions": {
"bash": "allow"
}
}

The model key was overridden by the project config, but autoupdate and permissions from other sources are preserved.

TUI Config (tui.json)

TUI-specific settings are stored in a separate file called tui.json. This keeps terminal UI preferences isolated from runtime configuration.

By default, opencode looks for tui.json in the same locations as opencode.json. Use the OPENCODE_TUI_CONFIG environment variable to specify a custom path.

{
"$schema": "https://opencode.ai/tui.json",
"theme": "tokyonight",
"scroll_speed": 3,
"mouse": true,
"attention": true,
"diff_style": "compact",
"keybinds": {
"leader": "ctrl+x",
"command_list": "ctrl+p"
}
}

TUI Config Options

OptionTypeDefaultDescription
themestring"catppuccin-frappe"UI color theme
scroll_speednumber3Lines scrolled per scroll event
mousebooleantrueEnable mouse support in the TUI
attentionbooleantrueHighlight areas that need user attention
diff_stylestring"compact"Diff display style ("compact" or "full")
keybindsobject{}Custom keybinding overrides
leaderstring"ctrl+x"Leader key prefix for multi-key shortcuts

Remote Configuration for Organizations

Organizations can distribute default configuration by serving a JSON file at /.well-known/opencode on their authentication domain. When a user authenticates (e.g., via opencode auth login), opencode fetches this remote config and applies it as the first layer in the precedence chain.

This is ideal for enforcing:

  • Allowed models or providers
  • Permission defaults
  • Base URLs for internal proxy services
  • Theme preferences for team consistency

Example .well-known/opencode response:

{
"permission": {
"webfetch": "deny"
},
"provider": {
"anthropic": {
"options": {
"baseURL": "https://internal-proxy.company.com/v1"
}
}
}
}

Variable Substitution

Configuration values support runtime variable substitution using two syntax forms:

Environment Variables

Use {env:VARIABLE_NAME} to inject environment variable values at runtime.

{
"provider": {
"anthropic": {
"apiKey": "{env:ANTHROPIC_API_KEY}"
}
}
}

File Contents

Use {file:path/to/file} to read the contents of a file and inject them as the value.

{
"provider": {
"anthropic": {
"apiKey": "{file:/etc/secrets/anthropic-key}"
}
}
}

Variables are resolved at startup. If an environment variable is undefined or a file path does not exist, opencode will log a warning and leave the value as-is.

Schema Validation

Both configuration schemas are strictly validated on load. If you use the $schema key, most editors (VS Code, IntelliJ, etc.) provide inline validation, autocomplete, and hover documentation.

{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-5"
}

You can also use the CLI to validate your config:

opencode config validate

Common Configuration Patterns

Minimal Project Setup

{
"$schema": "https://opencode.ai/config.json",
"model": "openai/gpt-5.2",
"small_model": "openai/gpt-5.1-codex"
}

Full Project with Permissions and Providers

{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-5",
"small_model": "anthropic/claude-haiku-4-5",
"autoupdate": true,
"server": {
"port": 4096
},
"permission": {
"edit": "allow",
"bash": "ask",
"webfetch": "deny"
},
"provider": {
"anthropic": {
"options": {
"baseURL": "https://api.anthropic.com/v1",
"timeout": 600000,
"chunkTimeout": 30000,
"setCacheKey": true
}
}
}
}

TUI Config Location Precedence

The tui.json file follows a similar but simplified precedence chain:

  1. OPENCODE_TUI_CONFIG environment variable
  2. Project root tui.json
  3. Global config ~/.config/opencode/tui.json

Unlike opencode.json, TUI configs are not merged by default. The highest-precedence file is used in its entirety.

Checking Active Configuration

To see the full merged configuration that opencode is currently using:

opencode config show

This displays the resolved configuration after all layers have been merged, including variable substitution results.