Course · OpenCode
Config reference
This page collects every OpenCode config field this course writes, with what it controls, its type, its default, and the lesson that introduces it. Two files are involved: opencode.json is OpenCode’s main config file, a project copy at your repository root with a global copy at ~/.config/opencode/opencode.json, and tui.json is the separate settings file for the terminal interface, with the same two locations: tui.json beside the project’s opencode.json, and ~/.config/opencode/tui.json globally. Defaults and field shapes are as of October 2026 - where this page and the config documentation disagree, trust the doc, except where a row links the source file it was checked against.
opencode.json fields
Section titled “opencode.json fields”| Field | Controls | Type | Default | Introduced in |
|---|---|---|---|---|
model |
the default model, as provider/model |
string | none; unset, OpenCode uses the last model you used, then its own priority order (models documentation) | Bring your own model |
provider |
custom providers and per-provider model options | object | none; unset, the built-in providers you have credentials for are available | Wire up multiple providers |
permission.read |
reading a file | "allow" | "ask" | "deny" or path map |
allow, except .env files: ask as of October 2026 (v1.18.32; agent.ts), which the permissions documentation describes as deny; .env.example remains allowed. A bare string such as "allow" replaces this map. If you rely on a block, set { "*.env": "deny", "*.env.*": "deny", "*.env.example": "allow" } |
Per-tool, per-agent |
permission.edit |
file changes (the edit, write, and patch tools) | "allow" | "ask" | "deny" or path map |
"allow" |
Per-tool, per-agent |
permission.bash |
running shell commands | "allow" | "ask" | "deny" or command map |
"allow" |
Per-tool, per-agent |
permission.glob |
finding files by name pattern | "allow" | "ask" | "deny" or pattern map |
"allow" |
Per-tool, per-agent |
permission.grep |
searching file contents | "allow" | "ask" | "deny" or pattern map |
"allow" |
Per-tool, per-agent |
permission.list |
listing a directory | "allow" | "ask" | "deny" or pattern map |
"allow" |
Per-tool, per-agent |
permission.task |
launching a subagent | "allow" | "ask" | "deny" or subagent map |
"allow" |
The three built-in subagents |
permission.skill |
loading a skill | "allow" | "ask" | "deny" or glob map |
"allow" |
Gate which agents run it |
permission.lsp |
language-server queries | "allow" | "ask" | "deny" |
"allow" |
The LSP channel |
compaction.auto |
summarizing the session automatically when the context window fills | boolean | true |
Undo, redo & compact |
compaction.prune |
removing old tool output to save tokens | boolean | false |
Undo, redo & compact |
compaction.reserved |
the token buffer kept free so compaction itself does not overflow | number | none documented; unset, OpenCode reserves the smaller of 20,000 tokens and the model’s output limit (session source) | Undo, redo & compact |
instructions |
extra instruction files or glob patterns loaded alongside AGENTS.md |
string[] | none documented; unset, no extra instruction files load | Point at more instruction files |
mcp |
MCP (Model Context Protocol) servers that give the agent external tools | object | none documented; unset, no MCP servers are configured | MCP servers |
agent |
custom agents and overrides for built-in ones (model, prompt, permissions) | object | none documented; unset, only the built-in agents exist | Write a custom subagent |
The permission.* rows are the keys this course sets. The keys name the tools the agent actually calls, and the documented list (permissions documentation, as of October 2026) has thirteen of them: read, edit, glob, grep, bash, task, skill, lsp, question, webfetch, websearch, external_directory, and doom_loop. The config schema accepts two more the doc page doesn’t list yet: list, directory listing - distinct from glob’s pattern-based search - and todowrite (permission schema, as of October 2026). Left unset, most keys default to allow; doom_loop and external_directory default to ask. These are the base defaults: built-in agents layer their own rules on top, and your config applies after both. The plan agent denies the edit tools outside its plan files, denies launching the general subagent, and does not gate bash (as of October 2026, v1.18.32; agent.ts; the agents documentation says plan sets edits and bash to ask). doom_loop triggers when the same tool call repeats three times with identical input, and external_directory triggers when a tool touches a path outside the project directory. A map value matches what the tool acts on: a file path for read and edit, the subagent type for task, the skill name for skill. The permissions documentation calls lsp non-granular for now, so the table shows it with a single action. permission.bash’s map matches flat command strings, not filesystem globs; that grammar and the last-match-wins ordering rule are covered in the per-tool, per-agent treatment.
How OpenCode merges config sources
Section titled “How OpenCode merges config sources”opencode.json is not one file but a stack of sources. Config sources are loaded in this order, later sources overriding earlier ones (as of October 2026; config documentation):
- Remote config (
.well-known/opencode) - organizational defaults - Global (
~/.config/opencode/opencode.json) - user preferences - Custom (
OPENCODE_CONFIGenv var) - custom overrides - Project (
opencode.jsonin the project) - project-specific settings .opencodedirectories - agents, commands, plugins- Inline (
OPENCODE_CONFIG_CONTENTenv var) - runtime overrides - Managed config files (
/Library/Application Support/opencode/on macOS,/etc/opencode/on Linux,%ProgramData%\opencodeon Windows) - macOS managed preferences (
.mobileconfigvia MDM, mobile device management) - highest priority, not user-overridable
In practice: a project opencode.json overrides your global file where both set the same key. Objects merge key by key, and instructions lists from all sources combine instead of replacing each other (as of October 2026, v1.18.32; config source). The the managed layers override everything - an administrator’s MDM-deployed settings win no matter what you write.
tui.json fields
Section titled “tui.json fields”The merge order above is for opencode.json. For tui.json, the project file overrides the global one where both set the same key, and the OPENCODE_TUI_CONFIG environment variable points OpenCode at a custom file, which overrides the global file but not the project files (as of October 2026; config documentation and the TUI config source).
| Field | Controls | Type | Default | Introduced in |
|---|---|---|---|---|
theme |
the terminal interface’s color theme | string | "opencode" |
Keybinds & themes |
keybinds |
keyboard shortcuts, merged with the built-in defaults | object | see keybinds docs | Leader key & command palette |
leader_timeout |
how long OpenCode waits for the next key after the leader key | number (ms) | 2000 (keybinds docs) |
Leader key & command palette |