# Config

Create `opencode.jsonc` in your project to configure OpenCode. Add the schema for editor validation, then set only the options you need.

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

You can also ask OpenCode to update this file for you.

## Format

OpenCode supports JSON and JSONC. Use JSONC when you want comments or trailing commas.

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  // Use this model by default.
  "model": "anthropic/claude-sonnet-5-5",
}
```

## Locations

Put managed, machine-wide settings in the system configuration directory:

| Platform | Directory                               |
| -------- | --------------------------------------- |
| macOS    | `/Library/Application Support/opencode` |
| Linux    | `/etc/opencode`                         |
| Windows  | `%ProgramData%\opencode`                |

The system directory works like the global directory. Besides
`opencode.json(c)`, it loads `agents/`, `commands/`, `skills/`, and `plugins/`
for every user on the machine:

```text
/etc/opencode/
├── opencode.json
├── agents/review.md
├── commands/release.md
└── skills/deploy/SKILL.md
```

On macOS, OpenCode also reads managed preferences that MDM tools deploy for the
`ai.opencode.managed` domain. A user-specific profile replaces the
machine-wide one:

```text
/Library/Managed Preferences/<user>/ai.opencode.managed.plist
/Library/Managed Preferences/ai.opencode.managed.plist
```

Managed settings have the highest precedence, so users and projects cannot
override the values they set, and managed preferences override the system
directory. Settings alone cannot stop users from adding providers, MCP servers,
agents, or plugins; use [policies](/policies#precedence) in managed
configuration to enforce restrictions.

Put user settings for every project in the global configuration:

```text
~/.config/opencode/opencode.json(c)
```

Put project settings in either of these files:

```text
/home/user/projects/my-app/opencode.json(c)
/home/user/projects/my-app/.opencode/opencode.json(c)
```

OpenCode searches from the current directory to the filesystem root. It first
merges direct `opencode.json(c)` files from the farthest directory to the
closest, then merges files inside `.opencode` directories in the same order.
This means every discovered `.opencode` config overrides every direct config.
Use one form throughout a directory tree unless you need that behavior.

For example, start OpenCode from `/home/user/projects/acme/packages/web`:

```text
/etc/opencode/opencode.json
~/.config/opencode/opencode.json

/home/user/projects/acme/
├── opencode.json
└── packages/
    └── web/
        ├── opencode.json
        └── src/
```

OpenCode applies these files from lowest to highest precedence:

1. `~/.config/opencode/opencode.json`
2. `/home/user/projects/acme/opencode.json`
3. `/home/user/projects/acme/packages/web/opencode.json`
4. `/etc/opencode/opencode.json`

The package config overrides matching settings from the repository config,
which overrides the global config. The system config overrides all of them.
Settings that do not conflict are preserved. [Policies](/policies#precedence)
from global and project files evaluate in the reverse order, and system
policies outrank all of them.

## Schema

The complete OpenCode configuration schema is available at
[opencode.ai/config.json](https://opencode.ai/config.json).

Add the `$schema` field to your configuration file to enable validation and
autocomplete in editors that support JSON Schema:

```json title="opencode.json"
{
  "$schema": "https://opencode.ai/config.json"
}
```

Use the schema as the source of truth for available fields, accepted values,
and nested configuration shapes.

### Shell

Set the shell used by the terminal and shell tools.

```jsonc
{
  "shell": "/bin/zsh",
}
```

### Model

Set the default model in `provider/model` format. The root default currently
does not retain a `#variant`; agent and command model references can select one.

```jsonc
{
  "model": "anthropic/claude-sonnet-5-5",
}
```

See the [models guide](/models) for model selection and local models.

### Agent

Choose the primary agent used when a session does not select one explicitly.

```jsonc
{
  "default_agent": "build",
}
```

See the [agents guide](/agents) for built-in and custom
agents.

### Updates

Control update checks from the global config. Set `update` to `"disable"` to
skip them, `"notify"` to show available updates before installing them, or
`"auto"` to install updates automatically. When omitted, `update` defaults to `"notify"`.

Automatic installation does not restart a running server. Restart it manually to activate the installed update.
Project-level values are ignored.

```jsonc
{
  "update": "notify",
}
```

### Username

Set a username. OpenCode accepts this field but does not display it in
conversations.

```jsonc
{
  "username": "alice",
}
```

### Permissions

Define ordered rules that allow, deny, or ask before an agent uses a tool on a
matching resource.

```jsonc
{
  "permissions": [
    {
      "action": "shell",
      "resource": "git push *",
      "effect": "ask",
    },
  ],
}
```

See the [permissions guide](/permissions) for rule matching and available actions.

### Policies

Allow or deny use of a provider, hard-deny a permission check, or block an MCP
server, skill, or plugin, with ordered statements that broader configuration can
override.

```jsonc
{
  "policies": [
    { "action": "provider.use", "resource": "*", "effect": "deny" },
    { "action": "provider.use", "resource": "anthropic", "effect": "allow" },
    { "action": "tool.use", "resource": "shell:git push *", "effect": "deny" },
  ],
}
```

See the [policies guide](/policies) for matching, precedence across configuration
files, and Console-managed policy.

### Agents

Override built-in agents or define specialized agents with their own model,
instructions, mode, and permissions.

```jsonc
{
  "agents": {
    "reviewer": {
      "description": "Review changes without editing files",
      "mode": "subagent",
      "system": "Focus on correctness, security, and missing tests.",
      "permissions": [{ "action": "edit", "resource": "*", "effect": "deny" }],
    },
  },
}
```

See the [agents guide](/agents) for all agent options and file-based agents.

### Snapshots

Enable or disable filesystem snapshots used by undo and revert behavior.

```jsonc
{
  "snapshots": false,
}
```

See the [snapshots guide](/snapshots) for undo and redo behavior.

### Watcher

Ignore files and directories that should not trigger filesystem updates.

```jsonc
{
  "watcher": {
    "ignore": ["dist/**", "coverage/**"],
  },
}
```

### Formatter

Format files after the `write`, `edit`, or `patch` tools change them. Set
`formatter` to `true` to enable available built-in formatters.

```jsonc
{
  "formatter": true,
}
```

See the [formatters guide](/formatters) for built-ins and custom formatters.

### Media

Control how oversized images loaded by the `read` tool are resized or rejected
before they are sent to a model.

```jsonc
{
  "media": {
    "image": {
      "auto_resize": true,
      "max_width": 2000,
      "max_height": 2000,
      "max_base64_bytes": 5242880,
    },
  },
}
```

See the [attachments guide](/attachments) for image processing and limits.

### Output

Set the maximum number of lines and bytes retained from a tool result.

```jsonc
{
  "tool_output": {
    "max_lines": 2000,
    "max_bytes": 51200,
  },
}
```

### Search

Choose how OpenCode searches the web. Use `"random"` to select an available
provider automatically.

```jsonc
{
  "websearch": {
    "provider": "random",
  },
}
```

See the [web search guide](/websearch) for providers, credentials, selection,
rate limits, and disabling search.

### MCP

Configure local and remote Model Context Protocol servers. Global
`mcp.timeout` values apply to servers defined in configuration files; each
server's `timeout` overrides them.

```jsonc
{
  "mcp": {
    "servers": {
      "playwright": {
        "type": "local",
        "command": ["bunx", "@playwright/mcp"],
      },
    },
  },
}
```

See the [MCP guide](/mcp-servers) for remote servers, OAuth, environment variables, and timeouts.

### Compaction

Control automatic context compaction and how much recent context it preserves.

```jsonc
{
  "compaction": {
    "auto": true,
    "keep": {
      "tokens": 15000,
    },
    "buffer": "15%",
  },
}
```

`buffer` is the share of the model's context window kept free before automatic compaction starts.

Local summaries remain the default. Opt into native provider compaction for both
automatic and manual requests with a provider or model policy:

```jsonc
{
  "providers": {
    "openai": {
      "settings": { "compaction": { "type": "native" } },
      "models": {
        "gpt-6.1-sol": { "settings": { "compaction": { "type": "summary" } } },
      },
    },
  },
}
```

A model setting overrides the provider setting. Automatic compaction uses the
selected model's usable input budget. Provider checkpoints keep recent user messages within the same
`compaction.keep.tokens` budget that local summaries use for their retained tail.
Top-level `compaction.auto: false` disables new automatic compaction without
discarding installed checkpoints. See the [compaction guide](/compaction) for
budgeting and overflow recovery.

### Warming

Keep recently active model sessions warm with periodic transient requests.
Warming is disabled by default; set it to `true` to use the four-minute idle
interval and 30-minute active window.

```jsonc
{
  "warming": {
    "prompt": "Do not perform any work. Reply with exactly: OK",
    "interval": "4 minutes",
    "duration": "30 minutes",
  },
}
```

See the [warming guide](/warming) for request behavior, customization,
and cost considerations.

### Skills

Add directories or URLs that OpenCode should search for agent skills.

```jsonc
{
  "skills": ["./team-skills", "https://example.com/.well-known/skills/"],
}
```

See the [skills guide](/skills) for skill structure and automatic discovery under `.opencode/skills/`.

### Commands

Define reusable slash commands as named prompt templates.

```jsonc
{
  "commands": {
    "review": {
      "description": "Review the current changes",
      "template": "Review the current diff for correctness and missing tests.",
    },
  },
}
```

See the [commands guide](/commands) for arguments, models, agents, and file-based commands.

### Instructions

Declare additional instruction files, globs, or HTTP(S) URLs. OpenCode loads
them alongside discovered `AGENTS.md` files.

```jsonc
{
  "instructions": ["CONTRIBUTING.md", "docs/guidelines/*.md"],
}
```

See the [instructions guide](/instructions) for project instructions and `AGENTS.md`.

### References

Make local directories or Git repositories available as named supporting
context.

```jsonc
{
  "references": {
    "docs": {
      "path": "../product-docs",
      "description": "Product behavior and terminology",
    },
    "effect": {
      "repository": "Effect-TS/effect",
      "branch": "main",
    },
  },
}
```

See the [references guide](/references) for shorthand, visibility, and path resolution.

### Worktrees

Set the parent directory for new local worktrees. OpenCode appends the requested or generated worktree name.

```jsonc
{
  "worktree": {
    "directory": "../worktrees",
  },
}
```

Relative paths resolve against the project's saved canonical checkout. This applies to global and project
configuration alike; absolute paths are used as-is, and `~/` resolves
against the user's home directory.

For example, this global configuration places new worktrees under each project's own `.lane/trees/` directory:

```jsonc
{
  "worktree": {
    "directory": ".lane/trees",
  },
}
```

Without this setting, creation uses the server's data directory under `worktree/<first-six-project-ID-characters>`.
Worktree creation and refresh load configuration from the project's saved canonical checkout, including when other
clones share its project ID. Changing it does not move existing worktrees.

Git is the built-in default. A [plugin](/build/plugins/server#worktrees) that registers a strategy automatically becomes the
default in that plugin runtime. Project operations use the canonical checkout's runtime. Strategy-specific options
belong to that plugin, not the `worktree` config object.

### Plugins

Load plugins from packages or local plugin directories. Use the object form when a plugin
accepts options.

```jsonc
{
  "plugins": [
    "opencode-example-plugin",
    {
      "package": "./plugins/local",
      "options": {
        "enabled": true,
      },
    },
  ],
}
```

See the [plugins guide](/plugins) for plugin loading and configuration.

### Providers

Configure providers and add or override their models, request settings,
headers, and model variants.

```jsonc
{
  "providers": {
    "openai": {
      "models": {
        "gpt-6.1-sol-custom": {
          "modelID": "gpt-6.1-sol",
          "name": "GPT-6.1 Sol Custom",
          "limit": {
            "context": 200000,
            "output": 32000,
          },
        },
      },
    },
  },
}
```

Provider `settings.transport: "websocket"` selects its session WebSocket.

See the [providers guide](/providers) for credentials, custom endpoints, provider packages, the WebSocket transport, and model configuration.

## Variables

You can use variable substitution in your config files to reference environment variables and file contents. Place references inside JSON strings.

### Env vars

Use `{env:VARIABLE_NAME}` to substitute environment variables:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "model": "{env:OPENCODE_MODEL}",
  "providers": {
    "anthropic": {
      "settings": {
        "apiKey": "{env:ANTHROPIC_API_KEY}",
      },
    },
  },
}
```

If the environment variable is not set, it will be replaced with an empty string.

### Files

Use `{file:path/to/file}` to substitute the contents of a file:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "settings": {
        "apiKey": "{file:~/.secrets/openai-key}",
      },
    },
  },
}
```

File paths can be:

- Relative to the config file directory
- Absolute, or starting with `~/` for your home directory

If the file does not exist, it will be replaced with an empty string.

These are useful for:

- Keeping sensitive data like API keys in separate files.
- Sharing common configuration snippets across multiple config files.

## Experimental

<Callout type="warning">
  Experimental settings may change, break, or be removed in any release without notice. Don't rely on them for stable
  workflows.
</Callout>

All experimental settings live under the `experimental` key:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "todo": true,
    "subagent_depth": 2,
    "background_compaction": true,
    "image_generate": { "model": "openai/gpt-image-2" },
    "location_idle_timeout": "4 hours",
  },
}
```

### Todos

Set `todo` to `true` to give agents a `todowrite` tool for tracking multi-step work. Defaults to `false`.

### Subagent depth

`subagent_depth` sets how deeply subagents can start their own subagents. Defaults to `1`, so a subagent cannot
start another subagent.

### Background compaction

Set `background_compaction` to `true` to write the compaction summary in the background before it is needed, so
automatic compaction doesn't pause the session. Defaults to `false`. See
[Compaction](/compaction#background-compaction) for how it works.

```jsonc
{
  "experimental": {
    "background_compaction": true,
  },
}
```

### Image generation

`image_generate` sets the default model for the [`experimental_image_generate`](/tools#image-generate) tool, as
`providerID/modelID`, optionally with `#variant`. When that model isn't available or can't handle a request, OpenCode
picks another image model automatically.

```jsonc
{
  "experimental": {
    "image_generate": {
      "model": "openai/gpt-image-2",
    },
  },
}
```

### Location idle timeout

`location_idle_timeout` controls how long a project location can go without session activity before OpenCode unloads
its services. It takes a duration such as `"2 hours"` and defaults to `"60 minutes"`. Running sessions and background
jobs keep a location loaded. Set it to `false` to never unload idle locations. Project config can override the global
value.

```jsonc
{
  "experimental": {
    "location_idle_timeout": false,
  },
}
```

### Deprecated policies

`experimental.policies` is deprecated. Use top-level [`policies`](/policies) instead. The old key still works and
merges into `policies`.