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:
- Runtime config: opencode.ai/config.json
- TUI config: opencode.ai/tui.json
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.
- 1. Remote Config
- 2. Global Config
- 3. OPENCODE_CONFIG Env Var
- 4. Project Config
- 5. .opencode/ Directory Config
- 6. OPENCODE_CONFIG_CONTENT Env Var
- 7. Managed Config (Admin-Controlled)
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.
Stored at ~/.config/opencode/opencode.json. This is your personal user-level config that applies across all projects.
{
"model": "openai/gpt-5.2",
"autoupdate": false
}
Set the OPENCODE_CONFIG environment variable to point to a custom config file path. This overrides the global config location.
export OPENCODE_CONFIG=/path/to/custom-opencode.json
A file named opencode.json placed in the project root directory. This is the most common way to configure opencode per-project.
{
"model": "anthropic/claude-sonnet-4-5",
"small_model": "anthropic/claude-haiku-4-5"
}
The .opencode/ directory inside a project can contain subdirectories for specific configuration domains:
.opencode/
agents/
commands/
modes/
plugins/
skills/
themes/
tools/
Each subdirectory provides a flat structure of configuration files that extend rather than replace the base config.
The OPENCODE_CONFIG_CONTENT environment variable accepts an inline JSON string that is parsed and merged last among user-settable sources.
export OPENCODE_CONFIG_CONTENT='{"model": "openai/gpt-5.1-codex"}'
This is useful for CI/CD pipelines or ephemeral environments where you do not want to write a config file to disk.
System-wide admin configuration that cannot be overridden by the user. Applied on top of everything else.
Managed settings are stored in OS-specific locations:
| OS | Path |
|---|---|
| macOS | /Library/Application Support/opencode/ |
| Linux | /etc/opencode/ |
| Windows | %ProgramData%\opencode |
On macOS, administrators can deploy managed settings via a configuration profile (.mobileconfig) using the ai.opencode.managed PayloadType.
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
| Option | Type | Default | Description |
|---|---|---|---|
theme | string | "catppuccin-frappe" | UI color theme |
scroll_speed | number | 3 | Lines scrolled per scroll event |
mouse | boolean | true | Enable mouse support in the TUI |
attention | boolean | true | Highlight areas that need user attention |
diff_style | string | "compact" | Diff display style ("compact" or "full") |
keybinds | object | {} | Custom keybinding overrides |
leader | string | "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:
OPENCODE_TUI_CONFIGenvironment variable- Project root
tui.json - 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.