> configuration

opencode is configured through JSON files that merge from broad to specific: a global ~/.config/opencode/opencode.json, a per-project ./opencode.json, plus environment variables and inline overrides. Add the $schema line for autocomplete, then set model, permissions, instructions, and providers. TUI-only settings (theme, keybinds, scroll) live separately in tui.json.

// configuration

5 commands

// faq

Where does opencode look for its config?

In precedence order (later wins): a remote .well-known/opencode, the global ~/.config/opencode/opencode.json, a file named by OPENCODE_CONFIG, the project ./opencode.json, the .opencode/ directory, and finally inline JSON in OPENCODE_CONFIG_CONTENT. They merge key-by-key rather than replacing each other wholesale.

How do I keep API keys out of my committed config?

Use variable substitution: {env:VAR} reads an environment variable and {file:path} reads a file, so you can write "apiKey": "{file:~/.secrets/openai}" instead of pasting the key. Note this is opencode's own substitution, not shell expansion, so $VAR does not work — only the {env:...} form.

Why isn't my config change taking effect?

The usual culprit is precedence: a project ./opencode.json or an OPENCODE_CONFIG_CONTENT environment variable overrides your global file for the keys they set. Also check you edited the right file — theme and keybinds belong in tui.json, not opencode.json. Start opencode with --print-logs to see which sources loaded.

What is the difference between opencode.json and tui.json?

opencode.json controls agent behavior — model, providers, permissions, instructions, MCP servers. tui.json controls the terminal interface — theme, keybinds, leader key, scroll speed, diff style. Setting a TUI option like theme in opencode.json has no effect; it must go in tui.json.