Vendor opencode source for docker build

This commit is contained in:
southseact-3d
2026-02-07 20:54:46 +00:00
parent b30ff1cfa4
commit efda260214
3195 changed files with 387717 additions and 1 deletions

View File

@@ -0,0 +1,67 @@
---
title: Migrating to 1.0
description: What's new in OpenCode 1.0.
---
OpenCode 1.0 is a complete rewrite of the TUI.
We moved from the go+bubbletea based TUI which had performance and capability issues to an in-house framework (OpenTUI) written in zig+solidjs.
The new TUI works like the old one since it connects to the same opencode server.
---
## Upgrading
You should not be autoupgraded to 1.0 if you are currently using a previous
version. However some older versions of OpenCode always grab latest.
To upgrade manually, run
```bash
$ opencode upgrade 1.0.0
```
To downgrade back to 0.x, run
```bash
$ opencode upgrade 0.15.31
```
---
## UX changes
The session history is more compressed, only showing full details of the edit and bash tool.
We added a command bar which almost everything flows through. Press ctrl+p to bring it up in any context and see everything you can do.
Added a session sidebar (can be toggled) with useful information.
We removed some functionality that we weren't sure anyone actually used. If something important is missing please open an issue and we'll add it back quickly.
---
## Breaking changes
### Keybinds renamed
- messages_revert -> messages_undo
- switch_agent -> agent_cycle
- switch_agent_reverse -> agent_cycle_reverse
- switch_mode -> agent_cycle
- switch_mode_reverse -> agent_cycle_reverse
### Keybinds removed
- messages_layout_toggle
- messages_next
- messages_previous
- file_diff_toggle
- file_search
- file_close
- file_list
- app_help
- project_init
- tool_details
- thinking_blocks

View File

@@ -0,0 +1,156 @@
---
title: ACP Support
description: Use OpenCode in any ACP-compatible editor.
---
OpenCode supports the [Agent Client Protocol](https://agentclientprotocol.com) or (ACP), allowing you to use it directly in compatible editors and IDEs.
:::tip
For a list of editors and tools that support ACP, check out the [ACP progress report](https://zed.dev/blog/acp-progress-report#available-now).
:::
ACP is an open protocol that standardizes communication between code editors and AI coding agents.
---
## Configure
To use OpenCode via ACP, configure your editor to run the `opencode acp` command.
The command starts OpenCode as an ACP-compatible subprocess that communicates with your editor over JSON-RPC via stdio.
Below are examples for popular editors that support ACP.
---
### Zed
Add to your [Zed](https://zed.dev) configuration (`~/.config/zed/settings.json`):
```json title="~/.config/zed/settings.json"
{
"agent_servers": {
"OpenCode": {
"command": "opencode",
"args": ["acp"]
}
}
}
```
To open it, use the `agent: new thread` action in the **Command Palette**.
You can also bind a keyboard shortcut by editing your `keymap.json`:
```json title="keymap.json"
[
{
"bindings": {
"cmd-alt-o": [
"agent::NewExternalAgentThread",
{
"agent": {
"custom": {
"name": "OpenCode",
"command": {
"command": "opencode",
"args": ["acp"]
}
}
}
}
]
}
}
]
```
---
### JetBrains IDEs
Add to your [JetBrains IDE](https://www.jetbrains.com/) acp.json according to the [documentation](https://www.jetbrains.com/help/ai-assistant/acp.html):
```json title="acp.json"
{
"agent_servers": {
"OpenCode": {
"command": "/absolute/path/bin/opencode",
"args": ["acp"]
}
}
}
```
To open it, use the new 'OpenCode' agent in the AI Chat agent selector.
---
### Avante.nvim
Add to your [Avante.nvim](https://github.com/yetone/avante.nvim) configuration:
```lua
{
acp_providers = {
["opencode"] = {
command = "opencode",
args = { "acp" }
}
}
}
```
If you need to pass environment variables:
```lua {6-8}
{
acp_providers = {
["opencode"] = {
command = "opencode",
args = { "acp" },
env = {
OPENCODE_API_KEY = os.getenv("OPENCODE_API_KEY")
}
}
}
}
```
---
### CodeCompanion.nvim
To use OpenCode as an ACP agent in [CodeCompanion.nvim](https://github.com/olimorris/codecompanion.nvim), add the following to your Neovim config:
```lua
require("codecompanion").setup({
interactions = {
chat = {
adapter = {
name = "opencode",
model = "claude-sonnet-4",
},
},
},
})
```
This config sets up CodeCompanion to use OpenCode as the ACP agent for chat.
If you need to pass environment variables (like `OPENCODE_API_KEY`), refer to [Configuring Adapters: Environment Variables](https://codecompanion.olimorris.dev/getting-started#setting-an-api-key) in the CodeCompanion.nvim documentation for full details.
## Support
OpenCode works the same via ACP as it does in the terminal. All features are supported:
:::note
Some built-in slash commands like `/undo` and `/redo` are currently unsupported.
:::
- Built-in tools (file operations, terminal commands, etc.)
- Custom tools and slash commands
- MCP servers configured in your OpenCode config
- Project-specific rules from `AGENTS.md`
- Custom formatters and linters
- Agents and permissions system

View File

@@ -0,0 +1,747 @@
---
title: Agents
description: Configure and use specialized agents.
---
Agents are specialized AI assistants that can be configured for specific tasks and workflows. They allow you to create focused tools with custom prompts, models, and tool access.
:::tip
Use the plan agent to analyze code and review suggestions without making any code changes.
:::
You can switch between agents during a session or invoke them with the `@` mention.
---
## Types
There are two types of agents in OpenCode; primary agents and subagents.
---
### Primary agents
Primary agents are the main assistants you interact with directly. You can cycle through them using the **Tab** key, or your configured `switch_agent` keybind. These agents handle your main conversation. Tool access is configured via permissions — for example, Build has all tools enabled while Plan is restricted.
:::tip
You can use the **Tab** key to switch between primary agents during a session.
:::
OpenCode comes with two built-in primary agents, **Build** and **Plan**. We'll
look at these below.
---
### Subagents
Subagents are specialized assistants that primary agents can invoke for specific tasks. You can also manually invoke them by **@ mentioning** them in your messages.
OpenCode comes with two built-in subagents, **General** and **Explore**. We'll look at this below.
---
## Built-in
OpenCode comes with two built-in primary agents and two built-in subagents.
---
### Use build
_Mode_: `primary`
Build is the **default** primary agent with all tools enabled. This is the standard agent for development work where you need full access to file operations and system commands.
---
### Use plan
_Mode_: `primary`
A restricted agent designed for planning and analysis. We use a permission system to give you more control and prevent unintended changes.
By default, all of the following are set to `ask`:
- `file edits`: All writes, patches, and edits
- `bash`: All bash commands
This agent is useful when you want the LLM to analyze code, suggest changes, or create plans without making any actual modifications to your codebase.
---
### Use general
_Mode_: `subagent`
A general-purpose agent for researching complex questions and executing multi-step tasks. Has full tool access (except todo), so it can make file changes when needed. Use this to run multiple units of work in parallel.
---
### Use explore
_Mode_: `subagent`
A fast, read-only agent for exploring codebases. Cannot modify files. Use this when you need to quickly find files by patterns, search code for keywords, or answer questions about the codebase.
---
### Use compaction
_Mode_: `primary`
Hidden system agent that compacts long context into a smaller summary. It runs automatically when needed and is not selectable in the UI.
---
### Use title
_Mode_: `primary`
Hidden system agent that generates short session titles. It runs automatically and is not selectable in the UI.
---
### Use summary
_Mode_: `primary`
Hidden system agent that creates session summaries. It runs automatically and is not selectable in the UI.
---
## Usage
1. For primary agents, use the **Tab** key to cycle through them during a session. You can also use your configured `switch_agent` keybind.
2. Subagents can be invoked:
- **Automatically** by primary agents for specialized tasks based on their descriptions.
- Manually by **@ mentioning** a subagent in your message. For example.
```txt frame="none"
@general help me search for this function
```
3. **Navigation between sessions**: When subagents create their own child sessions, you can navigate between the parent session and all child sessions using:
- **\<Leader>+Right** (or your configured `session_child_cycle` keybind) to cycle forward through parent → child1 → child2 → ... → parent
- **\<Leader>+Left** (or your configured `session_child_cycle_reverse` keybind) to cycle backward through parent ← child1 ← child2 ← ... ← parent
This allows you to seamlessly switch between the main conversation and specialized subagent work.
---
## Configure
You can customize the built-in agents or create your own through configuration. Agents can be configured in two ways:
---
### JSON
Configure agents in your `opencode.json` config file:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"mode": "primary",
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "{file:./prompts/build.txt}",
"tools": {
"write": true,
"edit": true,
"bash": true
}
},
"plan": {
"mode": "primary",
"model": "anthropic/claude-haiku-4-20250514",
"tools": {
"write": false,
"edit": false,
"bash": false
}
},
"code-reviewer": {
"description": "Reviews code for best practices and potential issues",
"mode": "subagent",
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
"tools": {
"write": false,
"edit": false
}
}
}
}
```
---
### Markdown
You can also define agents using markdown files. Place them in:
- Global: `~/.config/opencode/agents/`
- Per-project: `.opencode/agents/`
```markdown title="~/.config/opencode/agents/review.md"
---
description: Reviews code for quality and best practices
mode: subagent
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
tools:
write: false
edit: false
bash: false
---
You are in code review mode. Focus on:
- Code quality and best practices
- Potential bugs and edge cases
- Performance implications
- Security considerations
Provide constructive feedback without making direct changes.
```
The markdown file name becomes the agent name. For example, `review.md` creates a `review` agent.
---
## Options
Let's look at these configuration options in detail.
---
### Description
Use the `description` option to provide a brief description of what the agent does and when to use it.
```json title="opencode.json"
{
"agent": {
"review": {
"description": "Reviews code for best practices and potential issues"
}
}
}
```
This is a **required** config option.
---
### Temperature
Control the randomness and creativity of the LLM's responses with the `temperature` config.
Lower values make responses more focused and deterministic, while higher values increase creativity and variability.
```json title="opencode.json"
{
"agent": {
"plan": {
"temperature": 0.1
},
"creative": {
"temperature": 0.8
}
}
}
```
Temperature values typically range from 0.0 to 1.0:
- **0.0-0.2**: Very focused and deterministic responses, ideal for code analysis and planning
- **0.3-0.5**: Balanced responses with some creativity, good for general development tasks
- **0.6-1.0**: More creative and varied responses, useful for brainstorming and exploration
```json title="opencode.json"
{
"agent": {
"analyze": {
"temperature": 0.1,
"prompt": "{file:./prompts/analysis.txt}"
},
"build": {
"temperature": 0.3
},
"brainstorm": {
"temperature": 0.7,
"prompt": "{file:./prompts/creative.txt}"
}
}
}
```
If no temperature is specified, OpenCode uses model-specific defaults; typically 0 for most models, 0.55 for Qwen models.
---
### Max steps
Control the maximum number of agentic iterations an agent can perform before being forced to respond with text only. This allows users who wish to control costs to set a limit on agentic actions.
If this is not set, the agent will continue to iterate until the model chooses to stop or the user interrupts the session.
```json title="opencode.json"
{
"agent": {
"quick-thinker": {
"description": "Fast reasoning with limited iterations",
"prompt": "You are a quick thinker. Solve problems with minimal steps.",
"steps": 5
}
}
}
```
When the limit is reached, the agent receives a special system prompt instructing it to respond with a summarization of its work and recommended remaining tasks.
:::caution
The legacy `maxSteps` field is deprecated. Use `steps` instead.
:::
---
### Disable
Set to `true` to disable the agent.
```json title="opencode.json"
{
"agent": {
"review": {
"disable": true
}
}
}
```
---
### Prompt
Specify a custom system prompt file for this agent with the `prompt` config. The prompt file should contain instructions specific to the agent's purpose.
```json title="opencode.json"
{
"agent": {
"review": {
"prompt": "{file:./prompts/code-review.txt}"
}
}
}
```
This path is relative to where the config file is located. So this works for both the global OpenCode config and the project specific config.
---
### Model
Use the `model` config to override the model for this agent. Useful for using different models optimized for different tasks. For example, a faster model for planning, a more capable model for implementation.
:::tip
If you dont specify a model, primary agents use the [model globally configured](/docs/config#models) while subagents will use the model of the primary agent that invoked the subagent.
:::
```json title="opencode.json"
{
"agent": {
"plan": {
"model": "anthropic/claude-haiku-4-20250514"
}
}
}
```
The model ID in your OpenCode config uses the format `provider/model-id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex.
---
### Tools
Control which tools are available in this agent with the `tools` config. You can enable or disable specific tools by setting them to `true` or `false`.
```json title="opencode.json" {3-6,9-12}
{
"$schema": "https://opencode.ai/config.json",
"tools": {
"write": true,
"bash": true
},
"agent": {
"plan": {
"tools": {
"write": false,
"bash": false
}
}
}
}
```
:::note
The agent-specific config overrides the global config.
:::
You can also use wildcards to control multiple tools at once. For example, to disable all tools from an MCP server:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"readonly": {
"tools": {
"mymcp_*": false,
"write": false,
"edit": false
}
}
}
}
```
[Learn more about tools](/docs/tools).
---
### Permissions
You can configure permissions to manage what actions an agent can take. Currently, the permissions for the `edit`, `bash`, and `webfetch` tools can be configured to:
- `"ask"` — Prompt for approval before running the tool
- `"allow"` — Allow all operations without approval
- `"deny"` — Disable the tool
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "deny"
}
}
```
You can override these permissions per agent.
```json title="opencode.json" {3-5,8-10}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "deny"
},
"agent": {
"build": {
"permission": {
"edit": "ask"
}
}
}
}
```
You can also set permissions in Markdown agents.
```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
edit: deny
bash:
"*": ask
"git diff": allow
"git log*": allow
"grep *": allow
webfetch: deny
---
Only analyze code and suggest changes.
```
You can set permissions for specific bash commands.
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"permission": {
"bash": {
"git push": "ask",
"grep *": "allow"
}
}
}
}
}
```
This can take a glob pattern.
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"permission": {
"bash": {
"git *": "ask"
}
}
}
}
}
```
And you can also use the `*` wildcard to manage permissions for all commands.
Since the last matching rule takes precedence, put the `*` wildcard first and specific rules after.
```json title="opencode.json" {8}
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"build": {
"permission": {
"bash": {
"*": "ask",
"git status *": "allow"
}
}
}
}
}
```
[Learn more about permissions](/docs/permissions).
---
### Mode
Control the agent's mode with the `mode` config. The `mode` option is used to determine how the agent can be used.
```json title="opencode.json"
{
"agent": {
"review": {
"mode": "subagent"
}
}
}
```
The `mode` option can be set to `primary`, `subagent`, or `all`. If no `mode` is specified, it defaults to `all`.
---
### Hidden
Hide a subagent from the `@` autocomplete menu with `hidden: true`. Useful for internal subagents that should only be invoked programmatically by other agents via the Task tool.
```json title="opencode.json"
{
"agent": {
"internal-helper": {
"mode": "subagent",
"hidden": true
}
}
}
```
This only affects user visibility in the autocomplete menu. Hidden agents can still be invoked by the model via the Task tool if permissions allow.
:::note
Only applies to `mode: subagent` agents.
:::
---
### Task permissions
Control which subagents an agent can invoke via the Task tool with `permission.task`. Uses glob patterns for flexible matching.
```json title="opencode.json"
{
"agent": {
"orchestrator": {
"mode": "primary",
"permission": {
"task": {
"*": "deny",
"orchestrator-*": "allow",
"code-reviewer": "ask"
}
}
}
}
}
```
When set to `deny`, the subagent is removed from the Task tool description entirely, so the model won't attempt to invoke it.
:::tip
Rules are evaluated in order, and the **last matching rule wins**. In the example above, `orchestrator-planner` matches both `*` (deny) and `orchestrator-*` (allow), but since `orchestrator-*` comes after `*`, the result is `allow`.
:::
:::tip
Users can always invoke any subagent directly via the `@` autocomplete menu, even if the agent's task permissions would deny it.
:::
---
### Color
Customize the agent's visual appearance in the UI with the `color` option. This affects how the agent appears in the interface.
Use a valid hex color (e.g., `#FF5733`) or theme color: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, `info`.
```json title="opencode.json"
{
"agent": {
"creative": {
"color": "#ff6b6b"
},
"code-reviewer": {
"color": "accent"
}
}
}
```
---
### Top P
Control response diversity with the `top_p` option. Alternative to temperature for controlling randomness.
```json title="opencode.json"
{
"agent": {
"brainstorm": {
"top_p": 0.9
}
}
}
```
Values range from 0.0 to 1.0. Lower values are more focused, higher values more diverse.
---
### Additional
Any other options you specify in your agent configuration will be **passed through directly** to the provider as model options. This allows you to use provider-specific features and parameters.
For example, with OpenAI's reasoning models, you can control the reasoning effort:
```json title="opencode.json" {6,7}
{
"agent": {
"deep-thinker": {
"description": "Agent that uses high reasoning effort for complex problems",
"model": "openai/gpt-5",
"reasoningEffort": "high",
"textVerbosity": "low"
}
}
}
```
These additional options are model and provider-specific. Check your provider's documentation for available parameters.
:::tip
Run `opencode models` to see a list of the available models.
:::
---
## Create agents
You can create new agents using the following command:
```bash
opencode agent create
```
This interactive command will:
1. Ask where to save the agent; global or project-specific.
2. Description of what the agent should do.
3. Generate an appropriate system prompt and identifier.
4. Let you select which tools the agent can access.
5. Finally, create a markdown file with the agent configuration.
---
## Use cases
Here are some common use cases for different agents.
- **Build agent**: Full development work with all tools enabled
- **Plan agent**: Analysis and planning without making changes
- **Review agent**: Code review with read-only access plus documentation tools
- **Debug agent**: Focused on investigation with bash and read tools enabled
- **Docs agent**: Documentation writing with file operations but no system commands
---
## Examples
Here are some example agents you might find useful.
:::tip
Do you have an agent you'd like to share? [Submit a PR](https://github.com/anomalyco/opencode).
:::
---
### Documentation agent
```markdown title="~/.config/opencode/agents/docs-writer.md"
---
description: Writes and maintains project documentation
mode: subagent
tools:
bash: false
---
You are a technical writer. Create clear, comprehensive documentation.
Focus on:
- Clear explanations
- Proper structure
- Code examples
- User-friendly language
```
---
### Security auditor
```markdown title="~/.config/opencode/agents/security-auditor.md"
---
description: Performs security audits and identifies vulnerabilities
mode: subagent
tools:
write: false
edit: false
---
You are a security expert. Focus on identifying potential security issues.
Look for:
- Input validation vulnerabilities
- Authentication and authorization flaws
- Data exposure risks
- Dependency vulnerabilities
- Configuration security issues
```

View File

@@ -0,0 +1,603 @@
---
title: CLI
description: OpenCode CLI options and commands.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
The OpenCode CLI by default starts the [TUI](/docs/tui) when run without any arguments.
```bash
opencode
```
But it also accepts commands as documented on this page. This allows you to interact with OpenCode programmatically.
```bash
opencode run "Explain how closures work in JavaScript"
```
---
### tui
Start the OpenCode terminal user interface.
```bash
opencode [project]
```
#### Flags
| Flag | Short | Description |
| ------------ | ----- | ----------------------------------------------------------------------- |
| `--continue` | `-c` | Continue the last session |
| `--session` | `-s` | Session ID to continue |
| `--fork` | | Fork the session when continuing (use with `--continue` or `--session`) |
| `--prompt` | | Prompt to use |
| `--model` | `-m` | Model to use in the form of provider/model |
| `--agent` | | Agent to use |
| `--port` | | Port to listen on |
| `--hostname` | | Hostname to listen on |
---
## Commands
The OpenCode CLI also has the following commands.
---
### agent
Manage agents for OpenCode.
```bash
opencode agent [command]
```
---
### attach
Attach a terminal to an already running OpenCode backend server started via `serve` or `web` commands.
```bash
opencode attach [url]
```
This allows using the TUI with a remote OpenCode backend. For example:
```bash
# Start the backend server for web/mobile access
opencode web --port 4096 --hostname 0.0.0.0
# In another terminal, attach the TUI to the running backend
opencode attach http://10.20.30.40:4096
```
#### Flags
| Flag | Short | Description |
| ----------- | ----- | --------------------------------- |
| `--dir` | | Working directory to start TUI in |
| `--session` | `-s` | Session ID to continue |
---
#### create
Create a new agent with custom configuration.
```bash
opencode agent create
```
This command will guide you through creating a new agent with a custom system prompt and tool configuration.
---
#### list
List all available agents.
```bash
opencode agent list
```
---
### auth
Command to manage credentials and login for providers.
```bash
opencode auth [command]
```
---
#### login
OpenCode is powered by the provider list at [Models.dev](https://models.dev), so you can use `opencode auth login` to configure API keys for any provider you'd like to use. This is stored in `~/.local/share/opencode/auth.json`.
```bash
opencode auth login
```
When OpenCode starts up it loads the providers from the credentials file. And if there are any keys defined in your environments or a `.env` file in your project.
---
#### list
Lists all the authenticated providers as stored in the credentials file.
```bash
opencode auth list
```
Or the short version.
```bash
opencode auth ls
```
---
#### logout
Logs you out of a provider by clearing it from the credentials file.
```bash
opencode auth logout
```
---
### github
Manage the GitHub agent for repository automation.
```bash
opencode github [command]
```
---
#### install
Install the GitHub agent in your repository.
```bash
opencode github install
```
This sets up the necessary GitHub Actions workflow and guides you through the configuration process. [Learn more](/docs/github).
---
#### run
Run the GitHub agent. This is typically used in GitHub Actions.
```bash
opencode github run
```
##### Flags
| Flag | Description |
| --------- | -------------------------------------- |
| `--event` | GitHub mock event to run the agent for |
| `--token` | GitHub personal access token |
---
### mcp
Manage Model Context Protocol servers.
```bash
opencode mcp [command]
```
---
#### add
Add an MCP server to your configuration.
```bash
opencode mcp add
```
This command will guide you through adding either a local or remote MCP server.
---
#### list
List all configured MCP servers and their connection status.
```bash
opencode mcp list
```
Or use the short version.
```bash
opencode mcp ls
```
---
#### auth
Authenticate with an OAuth-enabled MCP server.
```bash
opencode mcp auth [name]
```
If you don't provide a server name, you'll be prompted to select from available OAuth-capable servers.
You can also list OAuth-capable servers and their authentication status.
```bash
opencode mcp auth list
```
Or use the short version.
```bash
opencode mcp auth ls
```
---
#### logout
Remove OAuth credentials for an MCP server.
```bash
opencode mcp logout [name]
```
---
#### debug
Debug OAuth connection issues for an MCP server.
```bash
opencode mcp debug <name>
```
---
### models
List all available models from configured providers.
```bash
opencode models [provider]
```
This command displays all models available across your configured providers in the format `provider/model`.
This is useful for figuring out the exact model name to use in [your config](/docs/config/).
You can optionally pass a provider ID to filter models by that provider.
```bash
opencode models anthropic
```
#### Flags
| Flag | Description |
| ----------- | ------------------------------------------------------------ |
| `--refresh` | Refresh the models cache from models.dev |
| `--verbose` | Use more verbose model output (includes metadata like costs) |
Use the `--refresh` flag to update the cached model list. This is useful when new models have been added to a provider and you want to see them in OpenCode.
```bash
opencode models --refresh
```
---
### run
Run opencode in non-interactive mode by passing a prompt directly.
```bash
opencode run [message..]
```
This is useful for scripting, automation, or when you want a quick answer without launching the full TUI. For example.
```bash "opencode run"
opencode run Explain the use of context in Go
```
You can also attach to a running `opencode serve` instance to avoid MCP server cold boot times on every run:
```bash
# Start a headless server in one terminal
opencode serve
# In another terminal, run commands that attach to it
opencode run --attach http://localhost:4096 "Explain async/await in JavaScript"
```
#### Flags
| Flag | Short | Description |
| ------------ | ----- | ----------------------------------------------------------------------- |
| `--command` | | The command to run, use message for args |
| `--continue` | `-c` | Continue the last session |
| `--session` | `-s` | Session ID to continue |
| `--fork` | | Fork the session when continuing (use with `--continue` or `--session`) |
| `--share` | | Share the session |
| `--model` | `-m` | Model to use in the form of provider/model |
| `--agent` | | Agent to use |
| `--file` | `-f` | File(s) to attach to message |
| `--format` | | Format: default (formatted) or json (raw JSON events) |
| `--title` | | Title for the session (uses truncated prompt if no value provided) |
| `--attach` | | Attach to a running opencode server (e.g., http://localhost:4096) |
| `--port` | | Port for the local server (defaults to random port) |
---
### serve
Start a headless OpenCode server for API access. Check out the [server docs](/docs/server) for the full HTTP interface.
```bash
opencode serve
```
This starts an HTTP server that provides API access to opencode functionality without the TUI interface. Set `OPENCODE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `opencode`).
#### Flags
| Flag | Description |
| ------------ | ------------------------------------------ |
| `--port` | Port to listen on |
| `--hostname` | Hostname to listen on |
| `--mdns` | Enable mDNS discovery |
| `--cors` | Additional browser origin(s) to allow CORS |
---
### session
Manage OpenCode sessions.
```bash
opencode session [command]
```
---
#### list
List all OpenCode sessions.
```bash
opencode session list
```
##### Flags
| Flag | Short | Description |
| ------------- | ----- | ------------------------------------ |
| `--max-count` | `-n` | Limit to N most recent sessions |
| `--format` | | Output format: table or json (table) |
---
### stats
Show token usage and cost statistics for your OpenCode sessions.
```bash
opencode stats
```
#### Flags
| Flag | Description |
| ----------- | --------------------------------------------------------------------------- |
| `--days` | Show stats for the last N days (all time) |
| `--tools` | Number of tools to show (all) |
| `--models` | Show model usage breakdown (hidden by default). Pass a number to show top N |
| `--project` | Filter by project (all projects, empty string: current project) |
---
### export
Export session data as JSON.
```bash
opencode export [sessionID]
```
If you don't provide a session ID, you'll be prompted to select from available sessions.
---
### import
Import session data from a JSON file or OpenCode share URL.
```bash
opencode import <file>
```
You can import from a local file or an OpenCode share URL.
```bash
opencode import session.json
opencode import https://opncd.ai/s/abc123
```
---
### web
Start a headless OpenCode server with a web interface.
```bash
opencode web
```
This starts an HTTP server and opens a web browser to access OpenCode through a web interface. Set `OPENCODE_SERVER_PASSWORD` to enable HTTP basic auth (username defaults to `opencode`).
#### Flags
| Flag | Description |
| ------------ | ------------------------------------------ |
| `--port` | Port to listen on |
| `--hostname` | Hostname to listen on |
| `--mdns` | Enable mDNS discovery |
| `--cors` | Additional browser origin(s) to allow CORS |
---
### acp
Start an ACP (Agent Client Protocol) server.
```bash
opencode acp
```
This command starts an ACP server that communicates via stdin/stdout using nd-JSON.
#### Flags
| Flag | Description |
| ------------ | --------------------- |
| `--cwd` | Working directory |
| `--port` | Port to listen on |
| `--hostname` | Hostname to listen on |
---
### uninstall
Uninstall OpenCode and remove all related files.
```bash
opencode uninstall
```
#### Flags
| Flag | Short | Description |
| --------------- | ----- | ------------------------------------------- |
| `--keep-config` | `-c` | Keep configuration files |
| `--keep-data` | `-d` | Keep session data and snapshots |
| `--dry-run` | | Show what would be removed without removing |
| `--force` | `-f` | Skip confirmation prompts |
---
### upgrade
Updates opencode to the latest version or a specific version.
```bash
opencode upgrade [target]
```
To upgrade to the latest version.
```bash
opencode upgrade
```
To upgrade to a specific version.
```bash
opencode upgrade v0.1.48
```
#### Flags
| Flag | Short | Description |
| ---------- | ----- | ----------------------------------------------------------------- |
| `--method` | `-m` | The installation method that was used; curl, npm, pnpm, bun, brew |
---
## Global Flags
The opencode CLI takes the following global flags.
| Flag | Short | Description |
| -------------- | ----- | ------------------------------------ |
| `--help` | `-h` | Display help |
| `--version` | `-v` | Print version number |
| `--print-logs` | | Print logs to stderr |
| `--log-level` | | Log level (DEBUG, INFO, WARN, ERROR) |
---
## Environment variables
OpenCode can be configured using environment variables.
| Variable | Type | Description |
| ------------------------------------- | ------- | ------------------------------------------------- |
| `OPENCODE_AUTO_SHARE` | boolean | Automatically share sessions |
| `OPENCODE_GIT_BASH_PATH` | string | Path to Git Bash executable on Windows |
| `OPENCODE_CONFIG` | string | Path to config file |
| `OPENCODE_CONFIG_DIR` | string | Path to config directory |
| `OPENCODE_CONFIG_CONTENT` | string | Inline json config content |
| `OPENCODE_DISABLE_AUTOUPDATE` | boolean | Disable automatic update checks |
| `OPENCODE_DISABLE_PRUNE` | boolean | Disable pruning of old data |
| `OPENCODE_DISABLE_TERMINAL_TITLE` | boolean | Disable automatic terminal title updates |
| `OPENCODE_PERMISSION` | string | Inlined json permissions config |
| `OPENCODE_DISABLE_DEFAULT_PLUGINS` | boolean | Disable default plugins |
| `OPENCODE_DISABLE_LSP_DOWNLOAD` | boolean | Disable automatic LSP server downloads |
| `OPENCODE_ENABLE_EXPERIMENTAL_MODELS` | boolean | Enable experimental models |
| `OPENCODE_DISABLE_AUTOCOMPACT` | boolean | Disable automatic context compaction |
| `OPENCODE_DISABLE_CLAUDE_CODE` | boolean | Disable reading from `.claude` (prompt + skills) |
| `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT` | boolean | Disable reading `~/.claude/CLAUDE.md` |
| `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` | boolean | Disable loading `.claude/skills` |
| `OPENCODE_DISABLE_MODELS_FETCH` | boolean | Disable fetching models from remote sources |
| `OPENCODE_FAKE_VCS` | string | Fake VCS provider for testing purposes |
| `OPENCODE_DISABLE_FILETIME_CHECK` | boolean | Disable file time checking for optimization |
| `OPENCODE_CLIENT` | string | Client identifier (defaults to `cli`) |
| `OPENCODE_ENABLE_EXA` | boolean | Enable Exa web search tools |
| `OPENCODE_SERVER_PASSWORD` | string | Enable basic auth for `serve`/`web` |
| `OPENCODE_SERVER_USERNAME` | string | Override basic auth username (default `opencode`) |
| `OPENCODE_MODELS_URL` | string | Custom URL for fetching models configuration |
---
### Experimental
These environment variables enable experimental features that may change or be removed.
| Variable | Type | Description |
| ----------------------------------------------- | ------- | --------------------------------------- |
| `OPENCODE_EXPERIMENTAL` | boolean | Enable all experimental features |
| `OPENCODE_EXPERIMENTAL_ICON_DISCOVERY` | boolean | Enable icon discovery |
| `OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT` | boolean | Disable copy on select in TUI |
| `OPENCODE_EXPERIMENTAL_BASH_DEFAULT_TIMEOUT_MS` | number | Default timeout for bash commands in ms |
| `OPENCODE_EXPERIMENTAL_OUTPUT_TOKEN_MAX` | number | Max output tokens for LLM responses |
| `OPENCODE_EXPERIMENTAL_FILEWATCHER` | boolean | Enable file watcher for entire dir |
| `OPENCODE_EXPERIMENTAL_OXFMT` | boolean | Enable oxfmt formatter |
| `OPENCODE_EXPERIMENTAL_LSP_TOOL` | boolean | Enable experimental LSP tool |
| `OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER` | boolean | Disable file watcher |
| `OPENCODE_EXPERIMENTAL_EXA` | boolean | Enable experimental Exa features |
| `OPENCODE_EXPERIMENTAL_LSP_TY` | boolean | Enable experimental LSP type checking |
| `OPENCODE_EXPERIMENTAL_MARKDOWN` | boolean | Enable experimental markdown features |
| `OPENCODE_EXPERIMENTAL_PLAN_MODE` | boolean | Enable plan mode |

View File

@@ -0,0 +1,323 @@
---
title: Commands
description: Create custom commands for repetitive tasks.
---
Custom commands let you specify a prompt you want to run when that command is executed in the TUI.
```bash frame="none"
/my-command
```
Custom commands are in addition to the built-in commands like `/init`, `/undo`, `/redo`, `/share`, `/help`. [Learn more](/docs/tui#commands).
---
## Create command files
Create markdown files in the `commands/` directory to define custom commands.
Create `.opencode/commands/test.md`:
```md title=".opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```
The frontmatter defines command properties. The content becomes the template.
Use the command by typing `/` followed by the command name.
```bash frame="none"
"/test"
```
---
## Configure
You can add custom commands through the OpenCode config or by creating markdown files in the `commands/` directory.
---
### JSON
Use the `command` option in your OpenCode [config](/docs/config):
```json title="opencode.jsonc" {4-12}
{
"$schema": "https://opencode.ai/config.json",
"command": {
// This becomes the name of the command
"test": {
// This is the prompt that will be sent to the LLM
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
// This is shown as the description in the TUI
"description": "Run tests with coverage",
"agent": "build",
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
```
Now you can run this command in the TUI:
```bash frame="none"
/test
```
---
### Markdown
You can also define commands using markdown files. Place them in:
- Global: `~/.config/opencode/commands/`
- Per-project: `.opencode/commands/`
```markdown title="~/.config/opencode/commands/test.md"
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```
The markdown file name becomes the command name. For example, `test.md` lets
you run:
```bash frame="none"
/test
```
---
## Prompt config
The prompts for the custom commands support several special placeholders and syntax.
---
### Arguments
Pass arguments to commands using the `$ARGUMENTS` placeholder.
```md title=".opencode/commands/component.md"
---
description: Create a new component
---
Create a new React component named $ARGUMENTS with TypeScript support.
Include proper typing and basic structure.
```
Run the command with arguments:
```bash frame="none"
/component Button
```
And `$ARGUMENTS` will be replaced with `Button`.
You can also access individual arguments using positional parameters:
- `$1` - First argument
- `$2` - Second argument
- `$3` - Third argument
- And so on...
For example:
```md title=".opencode/commands/create-file.md"
---
description: Create a new file with content
---
Create a file named $1 in the directory $2
with the following content: $3
```
Run the command:
```bash frame="none"
/create-file config.json src "{ \"key\": \"value\" }"
```
This replaces:
- `$1` with `config.json`
- `$2` with `src`
- `$3` with `{ "key": "value" }`
---
### Shell output
Use _!`command`_ to inject [bash command](/docs/tui#bash-commands) output into your prompt.
For example, to create a custom command that analyzes test coverage:
```md title=".opencode/commands/analyze-coverage.md"
---
description: Analyze test coverage
---
Here are the current test results:
!`npm test`
Based on these results, suggest improvements to increase coverage.
```
Or to review recent changes:
```md title=".opencode/commands/review-changes.md"
---
description: Review recent changes
---
Recent git commits:
!`git log --oneline -10`
Review these changes and suggest any improvements.
```
Commands run in your project's root directory and their output becomes part of the prompt.
---
### File references
Include files in your command using `@` followed by the filename.
```md title=".opencode/commands/review-component.md"
---
description: Review component
---
Review the component in @src/components/Button.tsx.
Check for performance issues and suggest improvements.
```
The file content gets included in the prompt automatically.
---
## Options
Let's look at the configuration options in detail.
---
### Template
The `template` option defines the prompt that will be sent to the LLM when the command is executed.
```json title="opencode.json"
{
"command": {
"test": {
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes."
}
}
}
```
This is a **required** config option.
---
### Description
Use the `description` option to provide a brief description of what the command does.
```json title="opencode.json"
{
"command": {
"test": {
"description": "Run tests with coverage"
}
}
}
```
This is shown as the description in the TUI when you type in the command.
---
### Agent
Use the `agent` config to optionally specify which [agent](/docs/agents) should execute this command.
If this is a [subagent](/docs/agents/#subagents) the command will trigger a subagent invocation by default.
To disable this behavior, set `subtask` to `false`.
```json title="opencode.json"
{
"command": {
"review": {
"agent": "plan"
}
}
}
```
This is an **optional** config option. If not specified, defaults to your current agent.
---
### Subtask
Use the `subtask` boolean to force the command to trigger a [subagent](/docs/agents/#subagents) invocation.
This is useful if you want the command to not pollute your primary context and will **force** the agent to act as a subagent,
even if `mode` is set to `primary` on the [agent](/docs/agents) configuration.
```json title="opencode.json"
{
"command": {
"analyze": {
"subtask": true
}
}
}
```
This is an **optional** config option.
---
### Model
Use the `model` config to override the default model for this command.
```json title="opencode.json"
{
"command": {
"analyze": {
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
```
This is an **optional** config option.
---
## Built-in
opencode includes several built-in commands like `/init`, `/undo`, `/redo`, `/share`, `/help`; [learn more](/docs/tui#commands).
:::note
Custom commands can override built-in commands.
:::
If you define a custom command with the same name, it will override the built-in command.

View File

@@ -0,0 +1,685 @@
---
title: Config
description: Using the OpenCode JSON config.
---
You can configure OpenCode using a JSON config file.
---
## Format
OpenCode supports both **JSON** and **JSONC** (JSON with Comments) formats.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
// Theme configuration
"theme": "opencode",
"model": "anthropic/claude-sonnet-4-5",
"autoupdate": true,
}
```
---
## Locations
You can place your config in a couple of different locations and they have a
different order of precedence.
:::note
Configuration files are **merged together**, not replaced.
:::
Configuration files are merged together, not replaced. Settings from the following config locations are combined. Later configs override earlier ones only for conflicting keys. Non-conflicting settings from all configs are preserved.
For example, if your global config sets `theme: "opencode"` and `autoupdate: true`, and your project config sets `model: "anthropic/claude-sonnet-4-5"`, the final configuration will include all three settings.
---
### Precedence order
Config sources are loaded in this order (later sources override earlier ones):
1. **Remote config** (from `.well-known/opencode`) - organizational defaults
2. **Global config** (`~/.config/opencode/opencode.json`) - user preferences
3. **Custom config** (`OPENCODE_CONFIG` env var) - custom overrides
4. **Project config** (`opencode.json` in project) - project-specific settings
5. **`.opencode` directories** - agents, commands, plugins
6. **Inline config** (`OPENCODE_CONFIG_CONTENT` env var) - runtime overrides
This means project configs can override global defaults, and global configs can override remote organizational defaults.
:::note
The `.opencode` and `~/.config/opencode` directories use **plural names** for subdirectories: `agents/`, `commands/`, `modes/`, `plugins/`, `skills/`, `tools/`, and `themes/`. Singular names (e.g., `agent/`) are also supported for backwards compatibility.
:::
---
### Remote
Organizations can provide default configuration via the `.well-known/opencode` endpoint. This is fetched automatically when you authenticate with a provider that supports it.
Remote config is loaded first, serving as the base layer. All other config sources (global, project) can override these defaults.
For example, if your organization provides MCP servers that are disabled by default:
```json title="Remote config from .well-known/opencode"
{
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": false
}
}
}
```
You can enable specific servers in your local config:
```json title="opencode.json"
{
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": true
}
}
}
```
---
### Global
Place your global OpenCode config in `~/.config/opencode/opencode.json`. Use global config for user-wide preferences like themes, providers, or keybinds.
Global config overrides remote organizational defaults.
---
### Per project
Add `opencode.json` in your project root. Project config has the highest precedence among standard config files - it overrides both global and remote configs.
:::tip
Place project specific config in the root of your project.
:::
When OpenCode starts up, it looks for a config file in the current directory or traverse up to the nearest Git directory.
This is also safe to be checked into Git and uses the same schema as the global one.
---
### Custom path
Specify a custom config file path using the `OPENCODE_CONFIG` environment variable.
```bash
export OPENCODE_CONFIG=/path/to/my/custom-config.json
opencode run "Hello world"
```
Custom config is loaded between global and project configs in the precedence order.
---
### Custom directory
Specify a custom config directory using the `OPENCODE_CONFIG_DIR`
environment variable. This directory will be searched for agents, commands,
modes, and plugins just like the standard `.opencode` directory, and should
follow the same structure.
```bash
export OPENCODE_CONFIG_DIR=/path/to/my/config-directory
opencode run "Hello world"
```
The custom directory is loaded after the global config and `.opencode` directories, so it **can override** their settings.
---
## Schema
The config file has a schema that's defined in [**`opencode.ai/config.json`**](https://opencode.ai/config.json).
Your editor should be able to validate and autocomplete based on the schema.
---
### TUI
You can configure TUI-specific settings through the `tui` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tui": {
"scroll_speed": 3,
"scroll_acceleration": {
"enabled": true
},
"diff_style": "auto"
}
}
```
Available options:
- `scroll_acceleration.enabled` - Enable macOS-style scroll acceleration. **Takes precedence over `scroll_speed`.**
- `scroll_speed` - Custom scroll speed multiplier (default: `3`, minimum: `1`). Ignored if `scroll_acceleration.enabled` is `true`.
- `diff_style` - Control diff rendering. `"auto"` adapts to terminal width, `"stacked"` always shows single column.
[Learn more about using the TUI here](/docs/tui).
---
### Server
You can configure server settings for the `opencode serve` and `opencode web` commands through the `server` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"server": {
"port": 4096,
"hostname": "0.0.0.0",
"mdns": true,
"mdnsDomain": "myproject.local",
"cors": ["http://localhost:5173"]
}
}
```
Available options:
- `port` - Port to listen on.
- `hostname` - Hostname to listen on. When `mdns` is enabled and no hostname is set, defaults to `0.0.0.0`.
- `mdns` - Enable mDNS service discovery. This allows other devices on the network to discover your OpenCode server.
- `mdnsDomain` - Custom domain name for mDNS service. Defaults to `opencode.local`. Useful for running multiple instances on the same network.
- `cors` - Additional origins to allow for CORS when using the HTTP server from a browser-based client. Values must be full origins (scheme + host + optional port), eg `https://app.example.com`.
[Learn more about the server here](/docs/server).
---
### Tools
You can manage the tools an LLM can use through the `tools` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tools": {
"write": false,
"bash": false
}
}
```
[Learn more about tools here](/docs/tools).
---
### Models
You can configure the providers and models you want to use in your OpenCode config through the `provider`, `model` and `small_model` options.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {},
"model": "anthropic/claude-sonnet-4-5",
"small_model": "anthropic/claude-haiku-4-5"
}
```
The `small_model` option configures a separate model for lightweight tasks like title generation. By default, OpenCode tries to use a cheaper model if one is available from your provider, otherwise it falls back to your main model.
Provider options can include `timeout` and `setCacheKey`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"anthropic": {
"options": {
"timeout": 600000,
"setCacheKey": true
}
}
}
}
```
- `timeout` - Request timeout in milliseconds (default: 300000). Set to `false` to disable.
- `setCacheKey` - Ensure a cache key is always set for designated provider.
You can also configure [local models](/docs/models#local). [Learn more](/docs/models).
---
#### Provider-Specific Options
Some providers support additional configuration options beyond the generic `timeout` and `apiKey` settings.
##### Amazon Bedrock
Amazon Bedrock supports AWS-specific configuration:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"amazon-bedrock": {
"options": {
"region": "us-east-1",
"profile": "my-aws-profile",
"endpoint": "https://bedrock-runtime.us-east-1.vpce-xxxxx.amazonaws.com"
}
}
}
}
```
- `region` - AWS region for Bedrock (defaults to `AWS_REGION` env var or `us-east-1`)
- `profile` - AWS named profile from `~/.aws/credentials` (defaults to `AWS_PROFILE` env var)
- `endpoint` - Custom endpoint URL for VPC endpoints. This is an alias for the generic `baseURL` option using AWS-specific terminology. If both are specified, `endpoint` takes precedence.
:::note
Bearer tokens (`AWS_BEARER_TOKEN_BEDROCK` or `/connect`) take precedence over profile-based authentication. See [authentication precedence](/docs/providers#authentication-precedence) for details.
:::
[Learn more about Amazon Bedrock configuration](/docs/providers#amazon-bedrock).
---
### Themes
You can configure the theme you want to use in your OpenCode config through the `theme` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"theme": ""
}
```
[Learn more here](/docs/themes).
---
### Agents
You can configure specialized agents for specific tasks through the `agent` option.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"code-reviewer": {
"description": "Reviews code for best practices and potential issues",
"model": "anthropic/claude-sonnet-4-5",
"prompt": "You are a code reviewer. Focus on security, performance, and maintainability.",
"tools": {
// Disable file modification tools for review-only agent
"write": false,
"edit": false,
},
},
},
}
```
You can also define agents using markdown files in `~/.config/opencode/agents/` or `.opencode/agents/`. [Learn more here](/docs/agents).
---
### Default agent
You can set the default agent using the `default_agent` option. This determines which agent is used when none is explicitly specified.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"default_agent": "plan"
}
```
The default agent must be a primary agent (not a subagent). This can be a built-in agent like `"build"` or `"plan"`, or a [custom agent](/docs/agents) you've defined. If the specified agent doesn't exist or is a subagent, OpenCode will fall back to `"build"` with a warning.
This setting applies across all interfaces: TUI, CLI (`opencode run`), desktop app, and GitHub Action.
---
### Sharing
You can configure the [share](/docs/share) feature through the `share` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "manual"
}
```
This takes:
- `"manual"` - Allow manual sharing via commands (default)
- `"auto"` - Automatically share new conversations
- `"disabled"` - Disable sharing entirely
By default, sharing is set to manual mode where you need to explicitly share conversations using the `/share` command.
---
### Commands
You can configure custom commands for repetitive tasks through the `command` option.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"command": {
"test": {
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
"description": "Run tests with coverage",
"agent": "build",
"model": "anthropic/claude-haiku-4-5",
},
"component": {
"template": "Create a new React component named $ARGUMENTS with TypeScript support.\nInclude proper typing and basic structure.",
"description": "Create a new component",
},
},
}
```
You can also define commands using markdown files in `~/.config/opencode/commands/` or `.opencode/commands/`. [Learn more here](/docs/commands).
---
### Keybinds
You can customize your keybinds through the `keybinds` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {}
}
```
[Learn more here](/docs/keybinds).
---
### Autoupdate
OpenCode will automatically download any new updates when it starts up. You can disable this with the `autoupdate` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"autoupdate": false
}
```
If you don't want updates but want to be notified when a new version is available, set `autoupdate` to `"notify"`.
Notice that this only works if it was not installed using a package manager such as Homebrew.
---
### Formatters
You can configure code formatters through the `formatter` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"disabled": true
},
"custom-prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "development"
},
"extensions": [".js", ".ts", ".jsx", ".tsx"]
}
}
}
```
[Learn more about formatters here](/docs/formatters).
---
### Permissions
By default, opencode **allows all operations** without requiring explicit approval. You can change this using the `permission` option.
For example, to ensure that the `edit` and `bash` tools require user approval:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "ask",
"bash": "ask"
}
}
```
[Learn more about permissions here](/docs/permissions).
---
### Compaction
You can control context compaction behavior through the `compaction` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"compaction": {
"auto": true,
"prune": true
}
}
```
- `auto` - Automatically compact the session when context is full (default: `true`).
- `prune` - Remove old tool outputs to save tokens (default: `true`).
---
### Watcher
You can configure file watcher ignore patterns through the `watcher` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"watcher": {
"ignore": ["node_modules/**", "dist/**", ".git/**"]
}
}
```
Patterns follow glob syntax. Use this to exclude noisy directories from file watching.
---
### MCP servers
You can configure MCP servers you want to use through the `mcp` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {}
}
```
[Learn more here](/docs/mcp-servers).
---
### Plugins
[Plugins](/docs/plugins) extend OpenCode with custom tools, hooks, and integrations.
Place plugin files in `.opencode/plugins/` or `~/.config/opencode/plugins/`. You can also load plugins from npm through the `plugin` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "@my-org/custom-plugin"]
}
```
[Learn more here](/docs/plugins).
---
### Instructions
You can configure the instructions for the model you're using through the `instructions` option.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```
This takes an array of paths and glob patterns to instruction files. [Learn more
about rules here](/docs/rules).
---
### Disabled providers
You can disable providers that are loaded automatically through the `disabled_providers` option. This is useful when you want to prevent certain providers from being loaded even if their credentials are available.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"disabled_providers": ["openai", "gemini"]
}
```
:::note
The `disabled_providers` takes priority over `enabled_providers`.
:::
The `disabled_providers` option accepts an array of provider IDs. When a provider is disabled:
- It won't be loaded even if environment variables are set.
- It won't be loaded even if API keys are configured through the `/connect` command.
- The provider's models won't appear in the model selection list.
---
### Enabled providers
You can specify an allowlist of providers through the `enabled_providers` option. When set, only the specified providers will be enabled and all others will be ignored.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"enabled_providers": ["anthropic", "openai"]
}
```
This is useful when you want to restrict OpenCode to only use specific providers rather than disabling them one by one.
:::note
The `disabled_providers` takes priority over `enabled_providers`.
:::
If a provider appears in both `enabled_providers` and `disabled_providers`, the `disabled_providers` takes priority for backwards compatibility.
---
### Experimental
The `experimental` key contains options that are under active development.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"experimental": {}
}
```
:::caution
Experimental options are not stable. They may change or be removed without notice.
:::
---
## Variables
You can use variable substitution in your config files to reference environment variables and file contents.
---
### Env vars
Use `{env:VARIABLE_NAME}` to substitute environment variables:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"model": "{env:OPENCODE_MODEL}",
"provider": {
"anthropic": {
"models": {},
"options": {
"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:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["./custom-instructions.md"],
"provider": {
"openai": {
"options": {
"apiKey": "{file:~/.secrets/openai-key}"
}
}
}
}
```
File paths can be:
- Relative to the config file directory
- Or absolute paths starting with `/` or `~`
These are useful for:
- Keeping sensitive data like API keys in separate files.
- Including large instruction files without cluttering your config.
- Sharing common configuration snippets across multiple config files.

View File

@@ -0,0 +1,170 @@
---
title: Custom Tools
description: Create tools the LLM can call in opencode.
---
Custom tools are functions you create that the LLM can call during conversations. They work alongside opencode's [built-in tools](/docs/tools) like `read`, `write`, and `bash`.
---
## Creating a tool
Tools are defined as **TypeScript** or **JavaScript** files. However, the tool definition can invoke scripts written in **any language** — TypeScript or JavaScript is only used for the tool definition itself.
---
### Location
They can be defined:
- Locally by placing them in the `.opencode/tools/` directory of your project.
- Or globally, by placing them in `~/.config/opencode/tools/`.
---
### Structure
The easiest way to create tools is using the `tool()` helper which provides type-safety and validation.
```ts title=".opencode/tools/database.ts" {1}
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Query the project database",
args: {
query: tool.schema.string().describe("SQL query to execute"),
},
async execute(args) {
// Your database logic here
return `Executed query: ${args.query}`
},
})
```
The **filename** becomes the **tool name**. The above creates a `database` tool.
---
#### Multiple tools per file
You can also export multiple tools from a single file. Each export becomes **a separate tool** with the name **`<filename>_<exportname>`**:
```ts title=".opencode/tools/math.ts"
import { tool } from "@opencode-ai/plugin"
export const add = tool({
description: "Add two numbers",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args) {
return args.a + args.b
},
})
export const multiply = tool({
description: "Multiply two numbers",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args) {
return args.a * args.b
},
})
```
This creates two tools: `math_add` and `math_multiply`.
---
### Arguments
You can use `tool.schema`, which is just [Zod](https://zod.dev), to define argument types.
```ts "tool.schema"
args: {
query: tool.schema.string().describe("SQL query to execute")
}
```
You can also import [Zod](https://zod.dev) directly and return a plain object:
```ts {6}
import { z } from "zod"
export default {
description: "Tool description",
args: {
param: z.string().describe("Parameter description"),
},
async execute(args, context) {
// Tool implementation
return "result"
},
}
```
---
### Context
Tools receive context about the current session:
```ts title=".opencode/tools/project.ts" {8}
import { tool } from "@opencode-ai/plugin"
export default tool({
description: "Get project information",
args: {},
async execute(args, context) {
// Access context information
const { agent, sessionID, messageID, directory, worktree } = context
return `Agent: ${agent}, Session: ${sessionID}, Message: ${messageID}, Directory: ${directory}, Worktree: ${worktree}`
},
})
```
Use `context.directory` for the session working directory.
Use `context.worktree` for the git worktree root.
---
## Examples
### Write a tool in Python
You can write your tools in any language you want. Here's an example that adds two numbers using Python.
First, create the tool as a Python script:
```python title=".opencode/tools/add.py"
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
```
Then create the tool definition that invokes it:
```ts title=".opencode/tools/python-add.ts" {10}
import { tool } from "@opencode-ai/plugin"
import path from "path"
export default tool({
description: "Add two numbers using Python",
args: {
a: tool.schema.number().describe("First number"),
b: tool.schema.number().describe("Second number"),
},
async execute(args, context) {
const script = path.join(context.worktree, ".opencode/tools/add.py")
const result = await Bun.$`python3 ${script} ${args.a} ${args.b}`.text()
return result.trim()
},
})
```
Here we are using the [`Bun.$`](https://bun.com/docs/runtime/shell) utility to run the Python script.

View File

@@ -0,0 +1,76 @@
---
title: Ecosystem
description: Projects and integrations built with OpenCode.
---
A collection of community projects built on OpenCode.
:::note
Want to add your OpenCode related project to this list? Submit a PR.
:::
You can also check out [awesome-opencode](https://github.com/awesome-opencode/awesome-opencode) and [opencode.cafe](https://opencode.cafe), a community that aggregates the ecosystem and community.
---
## Plugins
| Name | Description |
| --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| [opencode-daytona](https://github.com/jamesmurdza/daytona/blob/main/guides/typescript/opencode/README.md) | Automatically run OpenCode sessions in isolated Daytona sandboxes with git sync and live previews |
| [opencode-helicone-session](https://github.com/H2Shami/opencode-helicone-session) | Automatically inject Helicone session headers for request grouping |
| [opencode-type-inject](https://github.com/nick-vi/opencode-type-inject) | Auto-inject TypeScript/Svelte types into file reads with lookup tools |
| [opencode-openai-codex-auth](https://github.com/numman-ali/opencode-openai-codex-auth) | Use your ChatGPT Plus/Pro subscription instead of API credits |
| [opencode-gemini-auth](https://github.com/jenslys/opencode-gemini-auth) | Use your existing Gemini plan instead of API billing |
| [opencode-antigravity-auth](https://github.com/NoeFabris/opencode-antigravity-auth) | Use Antigravity's free models instead of API billing |
| [opencode-devcontainers](https://github.com/athal7/opencode-devcontainers) | Multi-branch devcontainer isolation with shallow clones and auto-assigned ports |
| [opencode-google-antigravity-auth](https://github.com/shekohex/opencode-google-antigravity-auth) | Google Antigravity OAuth Plugin, with support for Google Search, and more robust API handling |
| [opencode-dynamic-context-pruning](https://github.com/Tarquinen/opencode-dynamic-context-pruning) | Optimize token usage by pruning obsolete tool outputs |
| [opencode-websearch-cited](https://github.com/ghoulr/opencode-websearch-cited.git) | Add native websearch support for supported providers with Google grounded style |
| [opencode-pty](https://github.com/shekohex/opencode-pty.git) | Enables AI agents to run background processes in a PTY, send interactive input to them. |
| [opencode-shell-strategy](https://github.com/JRedeker/opencode-shell-strategy) | Instructions for non-interactive shell commands - prevents hangs from TTY-dependent operations |
| [opencode-wakatime](https://github.com/angristan/opencode-wakatime) | Track OpenCode usage with Wakatime |
| [opencode-md-table-formatter](https://github.com/franlol/opencode-md-table-formatter/tree/main) | Clean up markdown tables produced by LLMs |
| [opencode-morph-fast-apply](https://github.com/JRedeker/opencode-morph-fast-apply) | 10x faster code editing with Morph Fast Apply API and lazy edit markers |
| [oh-my-opencode](https://github.com/code-yeongyu/oh-my-opencode) | Background agents, pre-built LSP/AST/MCP tools, curated agents, Claude Code compatible |
| [opencode-notificator](https://github.com/panta82/opencode-notificator) | Desktop notifications and sound alerts for OpenCode sessions |
| [opencode-notifier](https://github.com/mohak34/opencode-notifier) | Desktop notifications and sound alerts for permission, completion, and error events |
| [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer) | AI-powered automatic Zellij session naming based on OpenCode context |
| [opencode-skillful](https://github.com/zenobi-us/opencode-skillful) | Allow OpenCode agents to lazy load prompts on demand with skill discovery and injection |
| [opencode-supermemory](https://github.com/supermemoryai/opencode-supermemory) | Persistent memory across sessions using Supermemory |
| [@plannotator/opencode](https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin) | Interactive plan review with visual annotation and private/offline sharing |
| [@openspoon/subtask2](https://github.com/spoons-and-mirrors/subtask2) | Extend opencode /commands into a powerful orchestration system with granular flow control |
| [opencode-scheduler](https://github.com/different-ai/opencode-scheduler) | Schedule recurring jobs using launchd (Mac) or systemd (Linux) with cron syntax |
| [micode](https://github.com/vtemian/micode) | Structured Brainstorm → Plan → Implement workflow with session continuity |
| [octto](https://github.com/vtemian/octto) | Interactive browser UI for AI brainstorming with multi-question forms |
| [opencode-background-agents](https://github.com/kdcokenny/opencode-background-agents) | Claude Code-style background agents with async delegation and context persistence |
| [opencode-notify](https://github.com/kdcokenny/opencode-notify) | Native OS notifications for OpenCode know when tasks complete |
| [opencode-workspace](https://github.com/kdcokenny/opencode-workspace) | Bundled multi-agent orchestration harness 16 components, one install |
| [opencode-worktree](https://github.com/kdcokenny/opencode-worktree) | Zero-friction git worktrees for OpenCode |
---
## Projects
| Name | Description |
| ------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- |
| [kimaki](https://github.com/remorses/kimaki) | Discord bot to control OpenCode sessions, built on the SDK |
| [opencode.nvim](https://github.com/NickvanDyke/opencode.nvim) | Neovim plugin for editor-aware prompts, built on the API |
| [portal](https://github.com/hosenur/portal) | Mobile-first web UI for OpenCode over Tailscale/VPN |
| [opencode plugin template](https://github.com/zenobi-us/opencode-plugin-template/) | Template for building OpenCode plugins |
| [opencode.nvim](https://github.com/sudo-tee/opencode.nvim) | Neovim frontend for opencode - a terminal-based AI coding agent |
| [ai-sdk-provider-opencode-sdk](https://github.com/ben-vargas/ai-sdk-provider-opencode-sdk) | Vercel AI SDK provider for using OpenCode via @opencode-ai/sdk |
| [OpenChamber](https://github.com/btriapitsyn/openchamber) | Web / Desktop App and VS Code Extension for OpenCode |
| [OpenCode-Obsidian](https://github.com/mtymek/opencode-obsidian) | Obsidian plugin that embedds OpenCode in Obsidian's UI |
| [OpenWork](https://github.com/different-ai/openwork) | An open-source alternative to Claude Cowork, powered by OpenCode |
| [ocx](https://github.com/kdcokenny/ocx) | OpenCode extension manager with portable, isolated profiles. |
| [CodeNomad](https://github.com/NeuralNomadsAI/CodeNomad) | Desktop, Web, Mobile and Remote Client App for OpenCode |
---
## Agents
| Name | Description |
| ----------------------------------------------------------------- | ------------------------------------------------------------ |
| [Agentic](https://github.com/Cluster444/agentic) | Modular AI agents and commands for structured development |
| [opencode-agents](https://github.com/darrenhinde/opencode-agents) | Configs, prompts, agents, and plugins for enhanced workflows |

View File

@@ -0,0 +1,170 @@
---
title: Enterprise
description: Using OpenCode securely in your organization.
---
import config from "../../../config.mjs"
export const email = `mailto:${config.email}`
OpenCode Enterprise is for organizations that want to ensure that their code and data never leaves their infrastructure. It can do this by using a centralized config that integrates with your SSO and internal AI gateway.
:::note
OpenCode does not store any of your code or context data.
:::
To get started with OpenCode Enterprise:
1. Do a trial internally with your team.
2. **<a href={email}>Contact us</a>** to discuss pricing and implementation options.
---
## Trial
OpenCode is open source and does not store any of your code or context data, so your developers can simply [get started](/docs/) and carry out a trial.
---
### Data handling
**OpenCode does not store your code or context data.** All processing happens locally or through direct API calls to your AI provider.
This means that as long as you are using a provider you trust, or an internal
AI gateway, you can use OpenCode securely.
The only caveat here is the optional `/share` feature.
---
#### Sharing conversations
If a user enables the `/share` feature, the conversation and the data associated with it are sent to the service we use to host these share pages at opencode.ai.
The data is currently served through our CDN's edge network, and is cached on the edge near your users.
We recommend you disable this for your trial.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"share": "disabled"
}
```
[Learn more about sharing](/docs/share).
---
### Code ownership
**You own all code produced by OpenCode.** There are no licensing restrictions or ownership claims.
---
## Pricing
We use a per-seat model for OpenCode Enterprise. If you have your own LLM gateway, we do not charge for tokens used. For further details about pricing and implementation options, **<a href={email}>contact us</a>**.
---
## Deployment
Once you have completed your trial and you are ready to use OpenCode at
your organization, you can **<a href={email}>contact us</a>** to discuss
pricing and implementation options.
---
### Central Config
We can set up OpenCode to use a single central config for your entire organization.
This centralized config can integrate with your SSO provider and ensures all users access only your internal AI gateway.
---
### SSO integration
Through the central config, OpenCode can integrate with your organization's SSO provider for authentication.
This allows OpenCode to obtain credentials for your internal AI gateway through your existing identity management system.
---
### Internal AI gateway
With the central config, OpenCode can also be configured to use only your internal AI gateway.
You can also disable all other AI providers, ensuring all requests go through your organization's approved infrastructure.
---
### Self-hosting
While we recommend disabling the share pages to ensure your data never leaves
your organization, we can also help you self-host them on your infrastructure.
This is currently on our roadmap. If you're interested, **<a href={email}>let us know</a>**.
---
## FAQ
<details>
<summary>What is OpenCode Enterprise?</summary>
OpenCode Enterprise is for organizations that want to ensure that their code and data never leaves their infrastructure. It can do this by using a centralized config that integrates with your SSO and internal AI gateway.
</details>
<details>
<summary>How do I get started with OpenCode Enterprise?</summary>
Simply start with an internal trial with your team. OpenCode by default does not store your code or context data, making it easy to get started.
Then **<a href={email}>contact us</a>** to discuss pricing and implementation options.
</details>
<details>
<summary>How does enterprise pricing work?</summary>
We offer per-seat enterprise pricing. If you have your own LLM gateway, we do not charge for tokens used. For further details, **<a href={email}>contact us</a>** for a custom quote based on your organization's needs.
</details>
<details>
<summary>Is my data secure with OpenCode Enterprise?</summary>
Yes. OpenCode does not store your code or context data. All processing happens locally or through direct API calls to your AI provider. With central config and SSO integration, your data remains secure within your organization's infrastructure.
</details>
<details>
<summary>Can we use our own private NPM registry?</summary>
OpenCode supports private npm registries through Bun's native `.npmrc` file support. If your organization uses a private registry, such as JFrog Artifactory, Nexus, or similar, ensure developers are authenticated before running OpenCode.
To set up authentication with your private registry:
```bash
npm login --registry=https://your-company.jfrog.io/api/npm/npm-virtual/
```
This creates `~/.npmrc` with authentication details. OpenCode will automatically
pick this up.
:::caution
You must be logged into the private registry before running OpenCode.
:::
Alternatively, you can manually configure a `.npmrc` file:
```bash title="~/.npmrc"
registry=https://your-company.jfrog.io/api/npm/npm-virtual/
//your-company.jfrog.io/api/npm/npm-virtual/:_authToken=${NPM_AUTH_TOKEN}
```
Developers must be logged into the private registry before running OpenCode to ensure packages can be installed from your enterprise registry.
</details>

View File

@@ -0,0 +1,130 @@
---
title: Formatters
description: OpenCode uses language specific formatters.
---
OpenCode automatically formats files after they are written or edited using language-specific formatters. This ensures that the code that is generated follows the code styles of your project.
---
## Built-in
OpenCode comes with several built-in formatters for popular languages and frameworks. Below is a list of the formatters, supported file extensions, and commands or config options it needs.
| Formatter | Extensions | Requirements |
| -------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| gofmt | .go | `gofmt` command available |
| mix | .ex, .exs, .eex, .heex, .leex, .neex, .sface | `mix` command available |
| prettier | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://prettier.io/docs/en/index.html) | `prettier` dependency in `package.json` |
| biome | .js, .jsx, .ts, .tsx, .html, .css, .md, .json, .yaml, and [more](https://biomejs.dev/) | `biome.json(c)` config file |
| zig | .zig, .zon | `zig` command available |
| clang-format | .c, .cpp, .h, .hpp, .ino, and [more](https://clang.llvm.org/docs/ClangFormat.html) | `.clang-format` config file |
| ktlint | .kt, .kts | `ktlint` command available |
| ruff | .py, .pyi | `ruff` command available with config |
| rustfmt | .rs | `rustfmt` command available |
| cargofmt | .rs | `cargo fmt` command available |
| uv | .py, .pyi | `uv` command available |
| rubocop | .rb, .rake, .gemspec, .ru | `rubocop` command available |
| standardrb | .rb, .rake, .gemspec, .ru | `standardrb` command available |
| htmlbeautifier | .erb, .html.erb | `htmlbeautifier` command available |
| air | .R | `air` command available |
| dart | .dart | `dart` command available |
| ocamlformat | .ml, .mli | `ocamlformat` command available and `.ocamlformat` config file |
| terraform | .tf, .tfvars | `terraform` command available |
| gleam | .gleam | `gleam` command available |
| nixfmt | .nix | `nixfmt` command available |
| shfmt | .sh, .bash | `shfmt` command available |
| pint | .php | `laravel/pint` dependency in `composer.json` |
| oxfmt (Experimental) | .js, .jsx, .ts, .tsx | `oxfmt` dependency in `package.json` and an [experimental env variable flag](/docs/cli/#experimental) |
| ormolu | .hs | `ormolu` command available |
So if your project has `prettier` in your `package.json`, OpenCode will automatically use it.
---
## How it works
When OpenCode writes or edits a file, it:
1. Checks the file extension against all enabled formatters.
2. Runs the appropriate formatter command on the file.
3. Applies the formatting changes automatically.
This process happens in the background, ensuring your code styles are maintained without any manual steps.
---
## Configure
You can customize formatters through the `formatter` section in your OpenCode config.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"formatter": {}
}
```
Each formatter configuration supports the following:
| Property | Type | Description |
| ------------- | -------- | ------------------------------------------------------- |
| `disabled` | boolean | Set this to `true` to disable the formatter |
| `command` | string[] | The command to run for formatting |
| `environment` | object | Environment variables to set when running the formatter |
| `extensions` | string[] | File extensions this formatter should handle |
Let's look at some examples.
---
### Disabling formatters
To disable **all** formatters globally, set `formatter` to `false`:
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"formatter": false
}
```
To disable a **specific** formatter, set `disabled` to `true`:
```json title="opencode.json" {5}
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"disabled": true
}
}
}
```
---
### Custom formatters
You can override the built-in formatters or add new ones by specifying the command, environment variables, and file extensions:
```json title="opencode.json" {4-14}
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"command": ["npx", "prettier", "--write", "$FILE"],
"environment": {
"NODE_ENV": "development"
},
"extensions": [".js", ".ts", ".jsx", ".tsx"]
},
"custom-markdown-formatter": {
"command": ["deno", "fmt", "$FILE"],
"extensions": [".md"]
}
}
}
```
The **`$FILE` placeholder** in the command will be replaced with the path to the file being formatted.

View File

@@ -0,0 +1,321 @@
---
title: GitHub
description: Use OpenCode in GitHub issues and pull-requests.
---
OpenCode integrates with your GitHub workflow. Mention `/opencode` or `/oc` in your comment, and OpenCode will execute tasks within your GitHub Actions runner.
---
## Features
- **Triage issues**: Ask OpenCode to look into an issue and explain it to you.
- **Fix and implement**: Ask OpenCode to fix an issue or implement a feature. And it will work in a new branch and submits a PR with all the changes.
- **Secure**: OpenCode runs inside your GitHub's runners.
---
## Installation
Run the following command in a project that is in a GitHub repo:
```bash
opencode github install
```
This will walk you through installing the GitHub app, creating the workflow, and setting up secrets.
---
### Manual Setup
Or you can set it up manually.
1. **Install the GitHub app**
Head over to [**github.com/apps/opencode-agent**](https://github.com/apps/opencode-agent). Make sure it's installed on the target repository.
2. **Add the workflow**
Add the following workflow file to `.github/workflows/opencode.yml` in your repo. Make sure to set the appropriate `model` and required API keys in `env`.
```yml title=".github/workflows/opencode.yml" {24,26}
name: opencode
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
if: |
contains(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
persist-credentials: false
- name: Run OpenCode
uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
# share: true
# github_token: xxxx
```
3. **Store the API keys in secrets**
In your organization or project **settings**, expand **Secrets and variables** on the left and select **Actions**. And add the required API keys.
---
## Configuration
- `model`: The model to use with OpenCode. Takes the format of `provider/model`. This is **required**.
- `agent`: The agent to use. Must be a primary agent. Falls back to `default_agent` from config or `"build"` if not found.
- `share`: Whether to share the OpenCode session. Defaults to **true** for public repositories.
- `prompt`: Optional custom prompt to override the default behavior. Use this to customize how OpenCode processes requests.
- `token`: Optional GitHub access token for performing operations such as creating comments, committing changes, and opening pull requests. By default, OpenCode uses the installation access token from the OpenCode GitHub App, so commits, comments, and pull requests appear as coming from the app.
Alternatively, you can use the GitHub Action runner's [built-in `GITHUB_TOKEN`](https://docs.github.com/en/actions/tutorials/authenticate-with-github_token) without installing the OpenCode GitHub App. Just make sure to grant the required permissions in your workflow:
```yaml
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
```
You can also use a [personal access tokens](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)(PAT) if preferred.
---
## Supported Events
OpenCode can be triggered by the following GitHub events:
| Event Type | Triggered By | Details |
| ----------------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `issue_comment` | Comment on an issue or PR | Mention `/opencode` or `/oc` in your comment. OpenCode reads context and can create branches, open PRs, or reply. |
| `pull_request_review_comment` | Comment on specific code lines in a PR | Mention `/opencode` or `/oc` while reviewing code. OpenCode receives file path, line numbers, and diff context. |
| `issues` | Issue opened or edited | Automatically trigger OpenCode when issues are created or modified. Requires `prompt` input. |
| `pull_request` | PR opened or updated | Automatically trigger OpenCode when PRs are opened, synchronized, or reopened. Useful for automated reviews. |
| `schedule` | Cron-based schedule | Run OpenCode on a schedule. Requires `prompt` input. Output goes to logs and PRs (no issue to comment on). |
| `workflow_dispatch` | Manual trigger from GitHub UI | Trigger OpenCode on demand via Actions tab. Requires `prompt` input. Output goes to logs and PRs. |
### Schedule Example
Run OpenCode on a schedule to perform automated tasks:
```yaml title=".github/workflows/opencode-scheduled.yml"
name: Scheduled OpenCode Task
on:
schedule:
- cron: "0 9 * * 1" # Every Monday at 9am UTC
jobs:
opencode:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Run OpenCode
uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
prompt: |
Review the codebase for any TODO comments and create a summary.
If you find issues worth addressing, open an issue to track them.
```
For scheduled events, the `prompt` input is **required** since there's no comment to extract instructions from. Scheduled workflows run without a user context to permission-check, so the workflow must grant `contents: write` and `pull-requests: write` if you expect OpenCode to create branches or PRs.
---
### Pull Request Example
Automatically review PRs when they are opened or updated:
```yaml title=".github/workflows/opencode-review.yml"
name: opencode-review
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
jobs:
review:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: read
issues: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: anomalyco/opencode/github@latest
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
model: anthropic/claude-sonnet-4-20250514
use_github_token: true
prompt: |
Review this pull request:
- Check for code quality issues
- Look for potential bugs
- Suggest improvements
```
For `pull_request` events, if no `prompt` is provided, OpenCode defaults to reviewing the pull request.
---
### Issues Triage Example
Automatically triage new issues. This example filters to accounts older than 30 days to reduce spam:
```yaml title=".github/workflows/opencode-triage.yml"
name: Issue Triage
on:
issues:
types: [opened]
jobs:
triage:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
issues: write
steps:
- name: Check account age
id: check
uses: actions/github-script@v7
with:
script: |
const user = await github.rest.users.getByUsername({
username: context.payload.issue.user.login
});
const created = new Date(user.data.created_at);
const days = (Date.now() - created) / (1000 * 60 * 60 * 24);
return days >= 30;
result-encoding: string
- uses: actions/checkout@v6
if: steps.check.outputs.result == 'true'
with:
persist-credentials: false
- uses: anomalyco/opencode/github@latest
if: steps.check.outputs.result == 'true'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
with:
model: anthropic/claude-sonnet-4-20250514
prompt: |
Review this issue. If there's a clear fix or relevant docs:
- Provide documentation links
- Add error handling guidance for code examples
Otherwise, do not comment.
```
For `issues` events, the `prompt` input is **required** since there's no comment to extract instructions from.
---
## Custom prompts
Override the default prompt to customize OpenCode's behavior for your workflow.
```yaml title=".github/workflows/opencode.yml"
- uses: anomalyco/opencode/github@latest
with:
model: anthropic/claude-sonnet-4-5
prompt: |
Review this pull request:
- Check for code quality issues
- Look for potential bugs
- Suggest improvements
```
This is useful for enforcing specific review criteria, coding standards, or focus areas relevant to your project.
---
## Examples
Here are some examples of how you can use OpenCode in GitHub.
- **Explain an issue**
Add this comment in a GitHub issue.
```
/opencode explain this issue
```
OpenCode will read the entire thread, including all comments, and reply with a clear explanation.
- **Fix an issue**
In a GitHub issue, say:
```
/opencode fix this
```
And OpenCode will create a new branch, implement the changes, and open a PR with the changes.
- **Review PRs and make changes**
Leave the following comment on a GitHub PR.
```
Delete the attachment from S3 when the note is removed /oc
```
OpenCode will implement the requested change and commit it to the same PR.
- **Review specific code lines**
Leave a comment directly on code lines in the PR's "Files" tab. OpenCode automatically detects the file, line numbers, and diff context to provide precise responses.
```
[Comment on specific lines in Files tab]
/oc add error handling here
```
When commenting on specific lines, OpenCode receives:
- The exact file being reviewed
- The specific lines of code
- The surrounding diff context
- Line number information
This allows for more targeted requests without needing to specify file paths or line numbers manually.

View File

@@ -0,0 +1,195 @@
---
title: GitLab
description: Use OpenCode in GitLab issues and merge requests.
---
OpenCode integrates with your GitLab workflow through your GitLab CI/CD pipeline or with GitLab Duo.
In both cases, OpenCode will run on your GitLab runners.
---
## GitLab CI
OpenCode works in a regular GitLab pipeline. You can build it into a pipeline as a [CI component](https://docs.gitlab.com/ee/ci/components/)
Here we are using a community-created CI/CD component for OpenCode — [nagyv/gitlab-opencode](https://gitlab.com/nagyv/gitlab-opencode).
---
### Features
- **Use custom configuration per job**: Configure OpenCode with a custom configuration directory, for example `./config/#custom-directory` to enable or disable functionality per OpenCode invocation.
- **Minimal setup**: The CI component sets up OpenCode in the background, you only need to create the OpenCode configuration and the initial prompt.
- **Flexible**: The CI component supports several inputs for customizing its behavior
---
### Setup
1. Store your OpenCode authentication JSON as a File type CI environment variables under **Settings** > **CI/CD** > **Variables**. Make sure to mark them as "Masked and hidden".
2. Add the following to your `.gitlab-ci.yml` file.
```yaml title=".gitlab-ci.yml"
include:
- component: $CI_SERVER_FQDN/nagyv/gitlab-opencode/opencode@2
inputs:
config_dir: ${CI_PROJECT_DIR}/opencode-config
auth_json: $OPENCODE_AUTH_JSON # The variable name for your OpenCode authentication JSON
command: optional-custom-command
message: "Your prompt here"
```
For more inputs and use cases [check out the docs](https://gitlab.com/explore/catalog/nagyv/gitlab-opencode) for this component.
---
## GitLab Duo
OpenCode integrates with your GitLab workflow.
Mention `@opencode` in a comment, and OpenCode will execute tasks within your GitLab CI pipeline.
---
### Features
- **Triage issues**: Ask OpenCode to look into an issue and explain it to you.
- **Fix and implement**: Ask OpenCode to fix an issue or implement a feature.
It will create a new branch and raise a merge request with the changes.
- **Secure**: OpenCode runs on your GitLab runners.
---
### Setup
OpenCode runs in your GitLab CI/CD pipeline, here's what you'll need to set it up:
:::tip
Check out the [**GitLab docs**](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for up to date instructions.
:::
1. Configure your GitLab environment
2. Set up CI/CD
3. Get an AI model provider API key
4. Create a service account
5. Configure CI/CD variables
6. Create a flow config file, here's an example:
<details>
<summary>Flow configuration</summary>
```yaml
image: node:22-slim
commands:
- echo "Installing opencode"
- npm install --global opencode-ai
- echo "Installing glab"
- export GITLAB_TOKEN=$GITLAB_TOKEN_OPENCODE
- apt-get update --quiet && apt-get install --yes curl wget gpg git && rm --recursive --force /var/lib/apt/lists/*
- curl --silent --show-error --location "https://raw.githubusercontent.com/upciti/wakemeops/main/assets/install_repository" | bash
- apt-get install --yes glab
- echo "Configuring glab"
- echo $GITLAB_HOST
- echo "Creating OpenCode auth configuration"
- mkdir --parents ~/.local/share/opencode
- |
cat > ~/.local/share/opencode/auth.json << EOF
{
"anthropic": {
"type": "api",
"key": "$ANTHROPIC_API_KEY"
}
}
EOF
- echo "Configuring git"
- git config --global user.email "opencode@gitlab.com"
- git config --global user.name "OpenCode"
- echo "Testing glab"
- glab issue list
- echo "Running OpenCode"
- |
opencode run "
You are an AI assistant helping with GitLab operations.
Context: $AI_FLOW_CONTEXT
Task: $AI_FLOW_INPUT
Event: $AI_FLOW_EVENT
Please execute the requested task using the available GitLab tools.
Be thorough in your analysis and provide clear explanations.
<important>
Please use the glab CLI to access data from GitLab. The glab CLI has already been authenticated. You can run the corresponding commands.
If you are asked to summarize an MR or issue or asked to provide more information then please post back a note to the MR/Issue so that the user can see it.
You don't need to commit or push up changes, those will be done automatically based on the file changes you make.
</important>
"
- git checkout --branch $CI_WORKLOAD_REF origin/$CI_WORKLOAD_REF
- echo "Checking for git changes and pushing if any exist"
- |
if ! git diff --quiet || ! git diff --cached --quiet || [ --not --zero "$(git ls-files --others --exclude-standard)" ]; then
echo "Git changes detected, adding and pushing..."
git add .
if git diff --cached --quiet; then
echo "No staged changes to commit"
else
echo "Committing changes to branch: $CI_WORKLOAD_REF"
git commit --message "Codex changes"
echo "Pushing changes up to $CI_WORKLOAD_REF"
git push https://gitlab-ci-token:$GITLAB_TOKEN@$GITLAB_HOST/gl-demo-ultimate-dev-ai-epic-17570/test-java-project.git $CI_WORKLOAD_REF
echo "Changes successfully pushed"
fi
else
echo "No git changes detected, skipping push"
fi
variables:
- ANTHROPIC_API_KEY
- GITLAB_TOKEN_OPENCODE
- GITLAB_HOST
```
</details>
You can refer to the [GitLab CLI agents docs](https://docs.gitlab.com/user/duo_agent_platform/agent_assistant/) for detailed instructions.
---
### Examples
Here are some examples of how you can use OpenCode in GitLab.
:::tip
You can configure to use a different trigger phrase than `@opencode`.
:::
- **Explain an issue**
Add this comment in a GitLab issue.
```
@opencode explain this issue
```
OpenCode will read the issue and reply with a clear explanation.
- **Fix an issue**
In a GitLab issue, say:
```
@opencode fix this
```
OpenCode will create a new branch, implement the changes, and open a merge request with the changes.
- **Review merge requests**
Leave the following comment on a GitLab merge request.
```
@opencode review this merge request
```
OpenCode will review the merge request and provide feedback.

View File

@@ -0,0 +1,48 @@
---
title: IDE
description: The OpenCode extension for VS Code, Cursor, and other IDEs
---
OpenCode integrates with VS Code, Cursor, or any IDE that supports a terminal. Just run `opencode` in the terminal to get started.
---
## Usage
- **Quick Launch**: Use `Cmd+Esc` (Mac) or `Ctrl+Esc` (Windows/Linux) to open OpenCode in a split terminal view, or focus an existing terminal session if one is already running.
- **New Session**: Use `Cmd+Shift+Esc` (Mac) or `Ctrl+Shift+Esc` (Windows/Linux) to start a new OpenCode terminal session, even if one is already open. You can also click the OpenCode button in the UI.
- **Context Awareness**: Automatically share your current selection or tab with OpenCode.
- **File Reference Shortcuts**: Use `Cmd+Option+K` (Mac) or `Alt+Ctrl+K` (Linux/Windows) to insert file references. For example, `@File#L37-42`.
---
## Installation
To install OpenCode on VS Code and popular forks like Cursor, Windsurf, VSCodium:
1. Open VS Code
2. Open the integrated terminal
3. Run `opencode` - the extension installs automatically
If on the other hand you want to use your own IDE when you run `/editor` or `/export` from the TUI, you'll need to set `export EDITOR="code --wait"`. [Learn more](/docs/tui/#editor-setup).
---
### Manual Install
Search for **OpenCode** in the Extension Marketplace and click **Install**.
---
### Troubleshooting
If the extension fails to install automatically:
- Ensure youre running `opencode` in the integrated terminal.
- Confirm the CLI for your IDE is installed:
- For VS Code: `code` command
- For Cursor: `cursor` command
- For Windsurf: `windsurf` command
- For VSCodium: `codium` command
- If not, run `Cmd+Shift+P` (Mac) or `Ctrl+Shift+P` (Windows/Linux) and search for "Shell Command: Install 'code' command in PATH" (or the equivalent for your IDE)
- Ensure VS Code has permission to install extensions

View File

@@ -0,0 +1,359 @@
---
title: Intro
description: Get started with OpenCode.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
import config from "../../../config.mjs"
export const console = config.console
[**OpenCode**](/) is an open source AI coding agent. It's available as a terminal-based interface, desktop app, or IDE extension.
![OpenCode TUI with the opencode theme](../../assets/lander/screenshot.png)
Let's get started.
---
#### Prerequisites
To use OpenCode in your terminal, you'll need:
1. A modern terminal emulator like:
- [WezTerm](https://wezterm.org), cross-platform
- [Alacritty](https://alacritty.org), cross-platform
- [Ghostty](https://ghostty.org), Linux and macOS
- [Kitty](https://sw.kovidgoyal.net/kitty/), Linux and macOS
2. API keys for the LLM providers you want to use.
---
## Install
The easiest way to install OpenCode is through the install script.
```bash
curl -fsSL https://opencode.ai/install | bash
```
You can also install it with the following commands:
- **Using Node.js**
<Tabs>
<TabItem label="npm">
```bash
npm install -g opencode-ai
```
</TabItem>
<TabItem label="Bun">
```bash
bun install -g opencode-ai
```
</TabItem>
<TabItem label="pnpm">
```bash
pnpm install -g opencode-ai
```
</TabItem>
<TabItem label="Yarn">
```bash
yarn global add opencode-ai
```
</TabItem>
</Tabs>
- **Using Homebrew on macOS and Linux**
```bash
brew install anomalyco/tap/opencode
```
> We recommend using the OpenCode tap for the most up to date releases. The official `brew install opencode` formula is maintained by the Homebrew team and is updated less frequently.
- **Using Paru on Arch Linux**
```bash
paru -S opencode-bin
```
#### Windows
:::tip[Recommended: Use WSL]
For the best experience on Windows, we recommend using [Windows Subsystem for Linux (WSL)](/docs/windows-wsl). It provides better performance and full compatibility with OpenCode's features.
:::
- **Using Chocolatey**
```bash
choco install opencode
```
- **Using Scoop**
```bash
scoop install opencode
```
- **Using NPM**
```bash
npm install -g opencode-ai
```
- **Using Mise**
```bash
mise use -g github:anomalyco/opencode
```
- **Using Docker**
```bash
docker run -it --rm ghcr.io/anomalyco/opencode
```
Support for installing OpenCode on Windows using Bun is currently in progress.
You can also grab the binary from the [Releases](https://github.com/anomalyco/opencode/releases).
---
## Configure
With OpenCode you can use any LLM provider by configuring their API keys.
If you are new to using LLM providers, we recommend using [OpenCode Zen](/docs/zen).
It's a curated list of models that have been tested and verified by the OpenCode
team.
1. Run the `/connect` command in the TUI, select opencode, and head to [opencode.ai/auth](https://opencode.ai/auth).
```txt
/connect
```
2. Sign in, add your billing details, and copy your API key.
3. Paste your API key.
```txt
┌ API key
└ enter
```
Alternatively, you can select one of the other providers. [Learn more](/docs/providers#directory).
---
## Initialize
Now that you've configured a provider, you can navigate to a project that
you want to work on.
```bash
cd /path/to/project
```
And run OpenCode.
```bash
opencode
```
Next, initialize OpenCode for the project by running the following command.
```bash frame="none"
/init
```
This will get OpenCode to analyze your project and create an `AGENTS.md` file in
the project root.
:::tip
You should commit your project's `AGENTS.md` file to Git.
:::
This helps OpenCode understand the project structure and the coding patterns
used.
---
## Usage
You are now ready to use OpenCode to work on your project. Feel free to ask it
anything!
If you are new to using an AI coding agent, here are some examples that might
help.
---
### Ask questions
You can ask OpenCode to explain the codebase to you.
:::tip
Use the `@` key to fuzzy search for files in the project.
:::
```txt frame="none" "@packages/functions/src/api/index.ts"
How is authentication handled in @packages/functions/src/api/index.ts
```
This is helpful if there's a part of the codebase that you didn't work on.
---
### Add features
You can ask OpenCode to add new features to your project. Though we first recommend asking it to create a plan.
1. **Create a plan**
OpenCode has a _Plan mode_ that disables its ability to make changes and
instead suggest _how_ it'll implement the feature.
Switch to it using the **Tab** key. You'll see an indicator for this in the lower right corner.
```bash frame="none" title="Switch to Plan mode"
<TAB>
```
Now let's describe what we want it to do.
```txt frame="none"
When a user deletes a note, we'd like to flag it as deleted in the database.
Then create a screen that shows all the recently deleted notes.
From this screen, the user can undelete a note or permanently delete it.
```
You want to give OpenCode enough details to understand what you want. It helps
to talk to it like you are talking to a junior developer on your team.
:::tip
Give OpenCode plenty of context and examples to help it understand what you
want.
:::
2. **Iterate on the plan**
Once it gives you a plan, you can give it feedback or add more details.
```txt frame="none"
We'd like to design this new screen using a design I've used before.
[Image #1] Take a look at this image and use it as a reference.
```
:::tip
Drag and drop images into the terminal to add them to the prompt.
:::
OpenCode can scan any images you give it and add them to the prompt. You can
do this by dragging and dropping an image into the terminal.
3. **Build the feature**
Once you feel comfortable with the plan, switch back to _Build mode_ by
hitting the **Tab** key again.
```bash frame="none"
<TAB>
```
And asking it to make the changes.
```bash frame="none"
Sounds good! Go ahead and make the changes.
```
---
### Make changes
For more straightforward changes, you can ask OpenCode to directly build it
without having to review the plan first.
```txt frame="none" "@packages/functions/src/settings.ts" "@packages/functions/src/notes.ts"
We need to add authentication to the /settings route. Take a look at how this is
handled in the /notes route in @packages/functions/src/notes.ts and implement
the same logic in @packages/functions/src/settings.ts
```
You want to make sure you provide a good amount of detail so OpenCode makes the right
changes.
---
### Undo changes
Let's say you ask OpenCode to make some changes.
```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```
But you realize that it is not what you wanted. You **can undo** the changes
using the `/undo` command.
```bash frame="none"
/undo
```
OpenCode will now revert the changes you made and show your original message
again.
```txt frame="none" "@packages/functions/src/api/index.ts"
Can you refactor the function in @packages/functions/src/api/index.ts?
```
From here you can tweak the prompt and ask OpenCode to try again.
:::tip
You can run `/undo` multiple times to undo multiple changes.
:::
Or you **can redo** the changes using the `/redo` command.
```bash frame="none"
/redo
```
---
## Share
The conversations that you have with OpenCode can be [shared with your
team](/docs/share).
```bash frame="none"
/share
```
This will create a link to the current conversation and copy it to your clipboard.
:::note
Conversations are not shared by default.
:::
Here's an [example conversation](https://opencode.ai/s/4XP1fce5) with OpenCode.
---
## Customize
And that's it! You are now a pro at using OpenCode.
To make it your own, we recommend [picking a theme](/docs/themes), [customizing the keybinds](/docs/keybinds), [configuring code formatters](/docs/formatters), [creating custom commands](/docs/commands), or playing around with the [OpenCode config](/docs/config).

View File

@@ -0,0 +1,192 @@
---
title: Keybinds
description: Customize your keybinds.
---
OpenCode has a list of keybinds that you can customize through the OpenCode config.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {
"leader": "ctrl+x",
"app_exit": "ctrl+c,ctrl+d,<leader>q",
"editor_open": "<leader>e",
"theme_list": "<leader>t",
"sidebar_toggle": "<leader>b",
"scrollbar_toggle": "none",
"username_toggle": "none",
"status_view": "<leader>s",
"tool_details": "none",
"session_export": "<leader>x",
"session_new": "<leader>n",
"session_list": "<leader>l",
"session_timeline": "<leader>g",
"session_fork": "none",
"session_rename": "none",
"session_share": "none",
"session_unshare": "none",
"session_interrupt": "escape",
"session_compact": "<leader>c",
"session_child_cycle": "<leader>right",
"session_child_cycle_reverse": "<leader>left",
"session_parent": "<leader>up",
"messages_page_up": "pageup,ctrl+alt+b",
"messages_page_down": "pagedown,ctrl+alt+f",
"messages_line_up": "ctrl+alt+y",
"messages_line_down": "ctrl+alt+e",
"messages_half_page_up": "ctrl+alt+u",
"messages_half_page_down": "ctrl+alt+d",
"messages_first": "ctrl+g,home",
"messages_last": "ctrl+alt+g,end",
"messages_next": "none",
"messages_previous": "none",
"messages_copy": "<leader>y",
"messages_undo": "<leader>u",
"messages_redo": "<leader>r",
"messages_last_user": "none",
"messages_toggle_conceal": "<leader>h",
"model_list": "<leader>m",
"model_cycle_recent": "f2",
"model_cycle_recent_reverse": "shift+f2",
"model_cycle_favorite": "none",
"model_cycle_favorite_reverse": "none",
"variant_cycle": "ctrl+t",
"command_list": "ctrl+p",
"agent_list": "<leader>a",
"agent_cycle": "tab",
"agent_cycle_reverse": "shift+tab",
"input_clear": "ctrl+c",
"input_paste": "ctrl+v",
"input_submit": "return",
"input_newline": "shift+return,ctrl+return,alt+return,ctrl+j",
"input_move_left": "left,ctrl+b",
"input_move_right": "right,ctrl+f",
"input_move_up": "up",
"input_move_down": "down",
"input_select_left": "shift+left",
"input_select_right": "shift+right",
"input_select_up": "shift+up",
"input_select_down": "shift+down",
"input_line_home": "ctrl+a",
"input_line_end": "ctrl+e",
"input_select_line_home": "ctrl+shift+a",
"input_select_line_end": "ctrl+shift+e",
"input_visual_line_home": "alt+a",
"input_visual_line_end": "alt+e",
"input_select_visual_line_home": "alt+shift+a",
"input_select_visual_line_end": "alt+shift+e",
"input_buffer_home": "home",
"input_buffer_end": "end",
"input_select_buffer_home": "shift+home",
"input_select_buffer_end": "shift+end",
"input_delete_line": "ctrl+shift+d",
"input_delete_to_line_end": "ctrl+k",
"input_delete_to_line_start": "ctrl+u",
"input_backspace": "backspace,shift+backspace",
"input_delete": "ctrl+d,delete,shift+delete",
"input_undo": "ctrl+-,super+z",
"input_redo": "ctrl+.,super+shift+z",
"input_word_forward": "alt+f,alt+right,ctrl+right",
"input_word_backward": "alt+b,alt+left,ctrl+left",
"input_select_word_forward": "alt+shift+f,alt+shift+right",
"input_select_word_backward": "alt+shift+b,alt+shift+left",
"input_delete_word_forward": "alt+d,alt+delete,ctrl+delete",
"input_delete_word_backward": "ctrl+w,ctrl+backspace,alt+backspace",
"history_previous": "up",
"history_next": "down",
"terminal_suspend": "ctrl+z",
"terminal_title_toggle": "none",
"tips_toggle": "<leader>h",
"display_thinking": "none"
}
}
```
---
## Leader key
OpenCode uses a `leader` key for most keybinds. This avoids conflicts in your terminal.
By default, `ctrl+x` is the leader key and most actions require you to first press the leader key and then the shortcut. For example, to start a new session you first press `ctrl+x` and then press `n`.
You don't need to use a leader key for your keybinds but we recommend doing so.
---
## Disable keybind
You can disable a keybind by adding the key to your config with a value of "none".
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"keybinds": {
"session_compact": "none"
}
}
```
---
## Desktop prompt shortcuts
The OpenCode desktop app prompt input supports common Readline/Emacs-style shortcuts for editing text. These are built-in and currently not configurable via `opencode.json`.
| Shortcut | Action |
| -------- | ---------------------------------------- |
| `ctrl+a` | Move to start of current line |
| `ctrl+e` | Move to end of current line |
| `ctrl+b` | Move cursor back one character |
| `ctrl+f` | Move cursor forward one character |
| `alt+b` | Move cursor back one word |
| `alt+f` | Move cursor forward one word |
| `ctrl+d` | Delete character under cursor |
| `ctrl+k` | Kill to end of line |
| `ctrl+u` | Kill to start of line |
| `ctrl+w` | Kill previous word |
| `alt+d` | Kill next word |
| `ctrl+t` | Transpose characters |
| `ctrl+g` | Cancel popovers / abort running response |
---
## Shift+Enter
Some terminals don't send modifier keys with Enter by default. You may need to configure your terminal to send `Shift+Enter` as an escape sequence.
### Windows Terminal
Open your `settings.json` at:
```
%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json
```
Add this to the root-level `actions` array:
```json
"actions": [
{
"command": {
"action": "sendInput",
"input": "\u001b[13;2u"
},
"id": "User.sendInput.ShiftEnterCustom"
}
]
```
Add this to the root-level `keybindings` array:
```json
"keybindings": [
{
"keys": "shift+enter",
"id": "User.sendInput.ShiftEnterCustom"
}
]
```
Save the file and restart Windows Terminal or open a new tab.

View File

@@ -0,0 +1,188 @@
---
title: LSP Servers
description: OpenCode integrates with your LSP servers.
---
OpenCode integrates with your Language Server Protocol (LSP) to help the LLM interact with your codebase. It uses diagnostics to provide feedback to the LLM.
---
## Built-in
OpenCode comes with several built-in LSP servers for popular languages:
| LSP Server | Extensions | Requirements |
| ------------------ | ------------------------------------------------------------------- | ------------------------------------------------------------ |
| astro | .astro | Auto-installs for Astro projects |
| bash | .sh, .bash, .zsh, .ksh | Auto-installs bash-language-server |
| clangd | .c, .cpp, .cc, .cxx, .c++, .h, .hpp, .hh, .hxx, .h++ | Auto-installs for C/C++ projects |
| csharp | .cs | `.NET SDK` installed |
| clojure-lsp | .clj, .cljs, .cljc, .edn | `clojure-lsp` command available |
| dart | .dart | `dart` command available |
| deno | .ts, .tsx, .js, .jsx, .mjs | `deno` command available (auto-detects deno.json/deno.jsonc) |
| elixir-ls | .ex, .exs | `elixir` command available |
| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue | `eslint` dependency in project |
| fsharp | .fs, .fsi, .fsx, .fsscript | `.NET SDK` installed |
| gleam | .gleam | `gleam` command available |
| gopls | .go | `go` command available |
| hls | .hs, .lhs | `haskell-language-server-wrapper` command available |
| jdtls | .java | `Java SDK (version 21+)` installed |
| kotlin-ls | .kt, .kts | Auto-installs for Kotlin projects |
| lua-ls | .lua | Auto-installs for Lua projects |
| nixd | .nix | `nixd` command available |
| ocaml-lsp | .ml, .mli | `ocamllsp` command available |
| oxlint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts, .vue, .astro, .svelte | `oxlint` dependency in project |
| php intelephense | .php | Auto-installs for PHP projects |
| prisma | .prisma | `prisma` command available |
| pyright | .py, .pyi | `pyright` dependency installed |
| ruby-lsp (rubocop) | .rb, .rake, .gemspec, .ru | `ruby` and `gem` commands available |
| rust | .rs | `rust-analyzer` command available |
| sourcekit-lsp | .swift, .objc, .objcpp | `swift` installed (`xcode` on macOS) |
| svelte | .svelte | Auto-installs for Svelte projects |
| terraform | .tf, .tfvars | Auto-installs from GitHub releases |
| tinymist | .typ, .typc | Auto-installs from GitHub releases |
| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependency in project |
| vue | .vue | Auto-installs for Vue projects |
| yaml-ls | .yaml, .yml | Auto-installs Red Hat yaml-language-server |
| zls | .zig, .zon | `zig` command available |
LSP servers are automatically enabled when one of the above file extensions are detected and the requirements are met.
:::note
You can disable automatic LSP server downloads by setting the `OPENCODE_DISABLE_LSP_DOWNLOAD` environment variable to `true`.
:::
---
## How It Works
When opencode opens a file, it:
1. Checks the file extension against all enabled LSP servers.
2. Starts the appropriate LSP server if not already running.
---
## Configure
You can customize LSP servers through the `lsp` section in your opencode config.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"lsp": {}
}
```
Each LSP server supports the following:
| Property | Type | Description |
| ---------------- | -------- | ------------------------------------------------- |
| `disabled` | boolean | Set this to `true` to disable the LSP server |
| `command` | string[] | The command to start the LSP server |
| `extensions` | string[] | File extensions this LSP server should handle |
| `env` | object | Environment variables to set when starting server |
| `initialization` | object | Initialization options to send to the LSP server |
Let's look at some examples.
---
### Environment variables
Use the `env` property to set environment variables when starting the LSP server:
```json title="opencode.json" {5-7}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"rust": {
"env": {
"RUST_LOG": "debug"
}
}
}
}
```
---
### Initialization options
Use the `initialization` property to pass initialization options to the LSP server. These are server-specific settings sent during the LSP `initialize` request:
```json title="opencode.json" {5-9}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript": {
"initialization": {
"preferences": {
"importModuleSpecifierPreference": "relative"
}
}
}
}
}
```
:::note
Initialization options vary by LSP server. Check your LSP server's documentation for available options.
:::
---
### Disabling LSP servers
To disable **all** LSP servers globally, set `lsp` to `false`:
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"lsp": false
}
```
To disable a **specific** LSP server, set `disabled` to `true`:
```json title="opencode.json" {5}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript": {
"disabled": true
}
}
}
```
---
### Custom LSP servers
You can add custom LSP servers by specifying the command and file extensions:
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"custom-lsp": {
"command": ["custom-lsp-server", "--stdio"],
"extensions": [".custom"]
}
}
}
```
---
## Additional Information
### PHP Intelephense
PHP Intelephense offers premium features through a license key. You can provide a license key by placing (only) the key in a text file at:
- On macOS/Linux: `$HOME/intelephense/licence.txt`
- On Windows: `%USERPROFILE%/intelephense/licence.txt`
The file should contain only the license key with no additional content.

View File

@@ -0,0 +1,511 @@
---
title: MCP servers
description: Add local and remote MCP tools.
---
You can add external tools to OpenCode using the _Model Context Protocol_, or MCP. OpenCode supports both local and remote servers.
Once added, MCP tools are automatically available to the LLM alongside built-in tools.
---
#### Caveats
When you use an MCP server, it adds to the context. This can quickly add up if you have a lot of tools. So we recommend being careful with which MCP servers you use.
:::tip
MCP servers add to your context, so you want to be careful with which ones you enable.
:::
Certain MCP servers, like the GitHub MCP server, tend to add a lot of tokens and can easily exceed the context limit.
---
## Enable
You can define MCP servers in your [OpenCode Config](https://opencode.ai/docs/config/) under `mcp`. Add each MCP with a unique name. You can refer to that MCP by name when prompting the LLM.
```jsonc title="opencode.jsonc" {6}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"name-of-mcp-server": {
// ...
"enabled": true,
},
"name-of-other-mcp-server": {
// ...
},
},
}
```
You can also disable a server by setting `enabled` to `false`. This is useful if you want to temporarily disable a server without removing it from your config.
---
### Overriding remote defaults
Organizations can provide default MCP servers via their `.well-known/opencode` endpoint. These servers may be disabled by default, allowing users to opt-in to the ones they need.
To enable a specific server from your organization's remote config, add it to your local config with `enabled: true`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"jira": {
"type": "remote",
"url": "https://jira.example.com/mcp",
"enabled": true
}
}
}
```
Your local config values override the remote defaults. See [config precedence](/docs/config#precedence-order) for more details.
---
## Local
Add local MCP servers using `type` to `"local"` within the MCP object.
```jsonc title="opencode.jsonc" {15}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-local-mcp-server": {
"type": "local",
// Or ["bun", "x", "my-mcp-command"]
"command": ["npx", "-y", "my-mcp-command"],
"enabled": true,
"environment": {
"MY_ENV_VAR": "my_env_var_value",
},
},
},
}
```
The command is how the local MCP server is started. You can also pass in a list of environment variables as well.
For example, here's how you can add the test [`@modelcontextprotocol/server-everything`](https://www.npmjs.com/package/@modelcontextprotocol/server-everything) MCP server.
```jsonc title="opencode.jsonc"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"mcp_everything": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-everything"],
},
},
}
```
And to use it I can add `use the mcp_everything tool` to my prompts.
```txt "mcp_everything"
use the mcp_everything tool to add the number 3 and 4
```
---
#### Options
Here are all the options for configuring a local MCP server.
| Option | Type | Required | Description |
| ------------- | ------- | -------- | ----------------------------------------------------------------------------------- |
| `type` | String | Y | Type of MCP server connection, must be `"local"`. |
| `command` | Array | Y | Command and arguments to run the MCP server. |
| `environment` | Object | | Environment variables to set when running the server. |
| `enabled` | Boolean | | Enable or disable the MCP server on startup. |
| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). |
---
## Remote
Add remote MCP servers by setting `type` to `"remote"`.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-remote-mcp": {
"type": "remote",
"url": "https://my-mcp-server.com",
"enabled": true,
"headers": {
"Authorization": "Bearer MY_API_KEY"
}
}
}
}
```
The `url` is the URL of the remote MCP server and with the `headers` option you can pass in a list of headers.
---
#### Options
| Option | Type | Required | Description |
| --------- | ------- | -------- | ----------------------------------------------------------------------------------- |
| `type` | String | Y | Type of MCP server connection, must be `"remote"`. |
| `url` | String | Y | URL of the remote MCP server. |
| `enabled` | Boolean | | Enable or disable the MCP server on startup. |
| `headers` | Object | | Headers to send with the request. |
| `oauth` | Object | | OAuth authentication configuration. See [OAuth](#oauth) section below. |
| `timeout` | Number | | Timeout in ms for fetching tools from the MCP server. Defaults to 5000 (5 seconds). |
---
## OAuth
OpenCode automatically handles OAuth authentication for remote MCP servers. When a server requires authentication, OpenCode will:
1. Detect the 401 response and initiate the OAuth flow
2. Use **Dynamic Client Registration (RFC 7591)** if supported by the server
3. Store tokens securely for future requests
---
### Automatic
For most OAuth-enabled MCP servers, no special configuration is needed. Just configure the remote server:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-oauth-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp"
}
}
}
```
If the server requires authentication, OpenCode will prompt you to authenticate when you first try to use it. If not, you can [manually trigger the flow](#authenticating) with `opencode mcp auth <server-name>`.
---
### Pre-registered
If you have client credentials from the MCP server provider, you can configure them:
```json title="opencode.json" {7-11}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-oauth-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"oauth": {
"clientId": "{env:MY_MCP_CLIENT_ID}",
"clientSecret": "{env:MY_MCP_CLIENT_SECRET}",
"scope": "tools:read tools:execute"
}
}
}
}
```
---
### Authenticating
You can manually trigger authentication or manage credentials.
Authenticate with a specific MCP server:
```bash
opencode mcp auth my-oauth-server
```
List all MCP servers and their auth status:
```bash
opencode mcp list
```
Remove stored credentials:
```bash
opencode mcp logout my-oauth-server
```
The `mcp auth` command will open your browser for authorization. After you authorize, OpenCode will store the tokens securely in `~/.local/share/opencode/mcp-auth.json`.
---
#### Disabling OAuth
If you want to disable automatic OAuth for a server (e.g., for servers that use API keys instead), set `oauth` to `false`:
```json title="opencode.json" {7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-api-key-server": {
"type": "remote",
"url": "https://mcp.example.com/mcp",
"oauth": false,
"headers": {
"Authorization": "Bearer {env:MY_API_KEY}"
}
}
}
}
```
---
#### OAuth Options
| Option | Type | Description |
| -------------- | --------------- | -------------------------------------------------------------------------------- |
| `oauth` | Object \| false | OAuth config object, or `false` to disable OAuth auto-detection. |
| `clientId` | String | OAuth client ID. If not provided, dynamic client registration will be attempted. |
| `clientSecret` | String | OAuth client secret, if required by the authorization server. |
| `scope` | String | OAuth scopes to request during authorization. |
#### Debugging
If a remote MCP server is failing to authenticate, you can diagnose issues with:
```bash
# View auth status for all OAuth-capable servers
opencode mcp auth list
# Debug connection and OAuth flow for a specific server
opencode mcp debug my-oauth-server
```
The `mcp debug` command shows the current auth status, tests HTTP connectivity, and attempts the OAuth discovery flow.
---
## Manage
Your MCPs are available as tools in OpenCode, alongside built-in tools. So you can manage them through the OpenCode config like any other tool.
---
### Global
This means that you can enable or disable them globally.
```json title="opencode.json" {14}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp-foo": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-foo"]
},
"my-mcp-bar": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-bar"]
}
},
"tools": {
"my-mcp-foo": false
}
}
```
We can also use a glob pattern to disable all matching MCPs.
```json title="opencode.json" {14}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp-foo": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-foo"]
},
"my-mcp-bar": {
"type": "local",
"command": ["bun", "x", "my-mcp-command-bar"]
}
},
"tools": {
"my-mcp*": false
}
}
```
Here we are using the glob pattern `my-mcp*` to disable all MCPs.
---
### Per agent
If you have a large number of MCP servers you may want to only enable them per agent and disable them globally. To do this:
1. Disable it as a tool globally.
2. In your [agent config](/docs/agents#tools), enable the MCP server as a tool.
```json title="opencode.json" {11, 14-18}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-mcp": {
"type": "local",
"command": ["bun", "x", "my-mcp-command"],
"enabled": true
}
},
"tools": {
"my-mcp*": false
},
"agent": {
"my-agent": {
"tools": {
"my-mcp*": true
}
}
}
}
```
---
#### Glob patterns
The glob pattern uses simple regex globbing patterns:
- `*` matches zero or more of any character (e.g., `"my-mcp*"` matches `my-mcp_search`, `my-mcp_list`, etc.)
- `?` matches exactly one character
- All other characters match literally
:::note
MCP server tools are registered with server name as prefix, so to disable all tools for a server simply use:
```
"mymcpservername_*": false
```
:::
---
## Examples
Below are examples of some common MCP servers. You can submit a PR if you want to document other servers.
---
### Sentry
Add the [Sentry MCP server](https://mcp.sentry.dev) to interact with your Sentry projects and issues.
```json title="opencode.json" {4-8}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"sentry": {
"type": "remote",
"url": "https://mcp.sentry.dev/mcp",
"oauth": {}
}
}
}
```
After adding the configuration, authenticate with Sentry:
```bash
opencode mcp auth sentry
```
This will open a browser window to complete the OAuth flow and connect OpenCode to your Sentry account.
Once authenticated, you can use Sentry tools in your prompts to query issues, projects, and error data.
```txt "use sentry"
Show me the latest unresolved issues in my project. use sentry
```
---
### Context7
Add the [Context7 MCP server](https://github.com/upstash/context7) to search through docs.
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp"
}
}
}
```
If you have signed up for a free account, you can use your API key and get higher rate-limits.
```json title="opencode.json" {7-9}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp",
"headers": {
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
}
}
}
}
```
Here we are assuming that you have the `CONTEXT7_API_KEY` environment variable set.
Add `use context7` to your prompts to use Context7 MCP server.
```txt "use context7"
Configure a Cloudflare Worker script to cache JSON API responses for five minutes. use context7
```
Alternatively, you can add something like this to your [AGENTS.md](/docs/rules/).
```md title="AGENTS.md"
When you need to search docs, use `context7` tools.
```
---
### Grep by Vercel
Add the [Grep by Vercel](https://grep.app) MCP server to search through code snippets on GitHub.
```json title="opencode.json" {4-7}
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"gh_grep": {
"type": "remote",
"url": "https://mcp.grep.app"
}
}
}
```
Since we named our MCP server `gh_grep`, you can add `use the gh_grep tool` to your prompts to get the agent to use it.
```txt "use the gh_grep tool"
What's the right way to set a custom domain in an SST Astro component? use the gh_grep tool
```
Alternatively, you can add something like this to your [AGENTS.md](/docs/rules/).
```md title="AGENTS.md"
If you are unsure how to do something, use `gh_grep` to search code examples from GitHub.
```

View File

@@ -0,0 +1,223 @@
---
title: Models
description: Configuring an LLM provider and model.
---
OpenCode uses the [AI SDK](https://ai-sdk.dev/) and [Models.dev](https://models.dev) to support **75+ LLM providers** and it supports running local models.
---
## Providers
Most popular providers are preloaded by default. If you've added the credentials for a provider through the `/connect` command, they'll be available when you start OpenCode.
Learn more about [providers](/docs/providers).
---
## Select a model
Once you've configured your provider you can select the model you want by typing in:
```bash frame="none"
/models
```
---
## Recommended models
There are a lot of models out there, with new models coming out every week.
:::tip
Consider using one of the models we recommend.
:::
However, there are only a few of them that are good at both generating code and tool calling.
Here are several models that work well with OpenCode, in no particular order. (This is not an exhaustive list nor is it necessarily up to date):
- GPT 5.2
- GPT 5.1 Codex
- Claude Opus 4.5
- Claude Sonnet 4.5
- Minimax M2.1
- Gemini 3 Pro
---
## Set a default
To set one of these as the default model, you can set the `model` key in your
OpenCode config.
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"model": "lmstudio/google/gemma-3n-e4b"
}
```
Here the full ID is `provider_id/model_id`. For example, if you're using [OpenCode Zen](/docs/zen), you would use `opencode/gpt-5.1-codex` for GPT 5.1 Codex.
If you've configured a [custom provider](/docs/providers#custom), the `provider_id` is key from the `provider` part of your config, and the `model_id` is the key from `provider.models`.
---
## Configure models
You can globally configure a model's options through the config.
```jsonc title="opencode.jsonc" {7-12,19-24}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"models": {
"gpt-5": {
"options": {
"reasoningEffort": "high",
"textVerbosity": "low",
"reasoningSummary": "auto",
"include": ["reasoning.encrypted_content"],
},
},
},
},
"anthropic": {
"models": {
"claude-sonnet-4-5-20250929": {
"options": {
"thinking": {
"type": "enabled",
"budgetTokens": 16000,
},
},
},
},
},
},
}
```
Here we're configuring global settings for two built-in models: `gpt-5` when accessed via the `openai` provider, and `claude-sonnet-4-20250514` when accessed via the `anthropic` provider.
The built-in provider and model names can be found on [Models.dev](https://models.dev).
You can also configure these options for any agents that you are using. The agent config overrides any global options here. [Learn more](/docs/agents/#additional).
You can also define custom variants that extend built-in ones. Variants let you configure different settings for the same model without creating duplicate entries:
```jsonc title="opencode.jsonc" {6-21}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"opencode": {
"models": {
"gpt-5": {
"variants": {
"high": {
"reasoningEffort": "high",
"textVerbosity": "low",
"reasoningSummary": "auto",
},
"low": {
"reasoningEffort": "low",
"textVerbosity": "low",
"reasoningSummary": "auto",
},
},
},
},
},
},
}
```
---
## Variants
Many models support multiple variants with different configurations. OpenCode ships with built-in default variants for popular providers.
### Built-in variants
OpenCode ships with default variants for many providers:
**Anthropic**:
- `high` - High thinking budget (default)
- `max` - Maximum thinking budget
**OpenAI**:
Varies by model but roughly:
- `none` - No reasoning
- `minimal` - Minimal reasoning effort
- `low` - Low reasoning effort
- `medium` - Medium reasoning effort
- `high` - High reasoning effort
- `xhigh` - Extra high reasoning effort
**Google**:
- `low` - Lower effort/token budget
- `high` - Higher effort/token budget
:::tip
This list is not comprehensive. Many other providers have built-in defaults too.
:::
### Custom variants
You can override existing variants or add your own:
```jsonc title="opencode.jsonc" {7-18}
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"models": {
"gpt-5": {
"variants": {
"thinking": {
"reasoningEffort": "high",
"textVerbosity": "low",
},
"fast": {
"disabled": true,
},
},
},
},
},
},
}
```
### Cycle variants
Use the keybind `variant_cycle` to quickly switch between variants. [Learn more](/docs/keybinds).
---
## Loading models
When OpenCode starts up, it checks for models in the following priority order:
1. The `--model` or `-m` command line flag. The format is the same as in the config file: `provider_id/model_id`.
2. The model list in the OpenCode config.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"model": "anthropic/claude-sonnet-4-20250514"
}
```
The format here is `provider/model`.
3. The last used model.
4. The first model using an internal priority.

View File

@@ -0,0 +1,331 @@
---
title: Modes
description: Different modes for different use cases.
---
:::caution
Modes are now configured through the `agent` option in the opencode config. The
`mode` option is now deprecated. [Learn more](/docs/agents).
:::
Modes in opencode allow you to customize the behavior, tools, and prompts for different use cases.
It comes with two built-in modes: **build** and **plan**. You can customize
these or configure your own through the opencode config.
You can switch between modes during a session or configure them in your config file.
---
## Built-in
opencode comes with two built-in modes.
---
### Build
Build is the **default** mode with all tools enabled. This is the standard mode for development work where you need full access to file operations and system commands.
---
### Plan
A restricted mode designed for planning and analysis. In plan mode, the following tools are disabled by default:
- `write` - Cannot create new files
- `edit` - Cannot modify existing files, except for files located at `.opencode/plans/*.md` to detail the plan itself
- `patch` - Cannot apply patches
- `bash` - Cannot execute shell commands
This mode is useful when you want the AI to analyze code, suggest changes, or create plans without making any actual modifications to your codebase.
---
## Switching
You can switch between modes during a session using the _Tab_ key. Or your configured `switch_mode` keybind.
See also: [Formatters](/docs/formatters) for information about code formatting configuration.
---
## Configure
You can customize the built-in modes or create your own through configuration. Modes can be configured in two ways:
### JSON Configuration
Configure modes in your `opencode.json` config file:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"mode": {
"build": {
"model": "anthropic/claude-sonnet-4-20250514",
"prompt": "{file:./prompts/build.txt}",
"tools": {
"write": true,
"edit": true,
"bash": true
}
},
"plan": {
"model": "anthropic/claude-haiku-4-20250514",
"tools": {
"write": false,
"edit": false,
"bash": false
}
}
}
}
```
### Markdown Configuration
You can also define modes using markdown files. Place them in:
- Global: `~/.config/opencode/modes/`
- Project: `.opencode/modes/`
```markdown title="~/.config/opencode/modes/review.md"
---
model: anthropic/claude-sonnet-4-20250514
temperature: 0.1
tools:
write: false
edit: false
bash: false
---
You are in code review mode. Focus on:
- Code quality and best practices
- Potential bugs and edge cases
- Performance implications
- Security considerations
Provide constructive feedback without making direct changes.
```
The markdown file name becomes the mode name (e.g., `review.md` creates a `review` mode).
Let's look at these configuration options in detail.
---
### Model
Use the `model` config to override the default model for this mode. Useful for using different models optimized for different tasks. For example, a faster model for planning, a more capable model for implementation.
```json title="opencode.json"
{
"mode": {
"plan": {
"model": "anthropic/claude-haiku-4-20250514"
}
}
}
```
---
### Temperature
Control the randomness and creativity of the AI's responses with the `temperature` config. Lower values make responses more focused and deterministic, while higher values increase creativity and variability.
```json title="opencode.json"
{
"mode": {
"plan": {
"temperature": 0.1
},
"creative": {
"temperature": 0.8
}
}
}
```
Temperature values typically range from 0.0 to 1.0:
- **0.0-0.2**: Very focused and deterministic responses, ideal for code analysis and planning
- **0.3-0.5**: Balanced responses with some creativity, good for general development tasks
- **0.6-1.0**: More creative and varied responses, useful for brainstorming and exploration
```json title="opencode.json"
{
"mode": {
"analyze": {
"temperature": 0.1,
"prompt": "{file:./prompts/analysis.txt}"
},
"build": {
"temperature": 0.3
},
"brainstorm": {
"temperature": 0.7,
"prompt": "{file:./prompts/creative.txt}"
}
}
}
```
If no temperature is specified, opencode uses model-specific defaults (typically 0 for most models, 0.55 for Qwen models).
---
### Prompt
Specify a custom system prompt file for this mode with the `prompt` config. The prompt file should contain instructions specific to the mode's purpose.
```json title="opencode.json"
{
"mode": {
"review": {
"prompt": "{file:./prompts/code-review.txt}"
}
}
}
```
This path is relative to where the config file is located. So this works for
both the global opencode config and the project specific config.
---
### Tools
Control which tools are available in this mode with the `tools` config. You can enable or disable specific tools by setting them to `true` or `false`.
```json
{
"mode": {
"readonly": {
"tools": {
"write": false,
"edit": false,
"bash": false,
"read": true,
"grep": true,
"glob": true
}
}
}
}
```
If no tools are specified, all tools are enabled by default.
---
#### Available tools
Here are all the tools can be controlled through the mode config.
| Tool | Description |
| ----------- | ----------------------- |
| `bash` | Execute shell commands |
| `edit` | Modify existing files |
| `write` | Create new files |
| `read` | Read file contents |
| `grep` | Search file contents |
| `glob` | Find files by pattern |
| `list` | List directory contents |
| `patch` | Apply patches to files |
| `todowrite` | Manage todo lists |
| `todoread` | Read todo lists |
| `webfetch` | Fetch web content |
---
## Custom modes
You can create your own custom modes by adding them to the configuration. Here are examples using both approaches:
### Using JSON configuration
```json title="opencode.json" {4-14}
{
"$schema": "https://opencode.ai/config.json",
"mode": {
"docs": {
"prompt": "{file:./prompts/documentation.txt}",
"tools": {
"write": true,
"edit": true,
"bash": false,
"read": true,
"grep": true,
"glob": true
}
}
}
}
```
### Using markdown files
Create mode files in `.opencode/modes/` for project-specific modes or `~/.config/opencode/modes/` for global modes:
```markdown title=".opencode/modes/debug.md"
---
temperature: 0.1
tools:
bash: true
read: true
grep: true
write: false
edit: false
---
You are in debug mode. Your primary goal is to help investigate and diagnose issues.
Focus on:
- Understanding the problem through careful analysis
- Using bash commands to inspect system state
- Reading relevant files and logs
- Searching for patterns and anomalies
- Providing clear explanations of findings
Do not make any changes to files. Only investigate and report.
```
```markdown title="~/.config/opencode/modes/refactor.md"
---
model: anthropic/claude-sonnet-4-20250514
temperature: 0.2
tools:
edit: true
read: true
grep: true
glob: true
---
You are in refactoring mode. Focus on improving code quality without changing functionality.
Priorities:
- Improve code readability and maintainability
- Apply consistent naming conventions
- Reduce code duplication
- Optimize performance where appropriate
- Ensure all tests continue to pass
```
---
### Use cases
Here are some common use cases for different modes.
- **Build mode**: Full development work with all tools enabled
- **Plan mode**: Analysis and planning without making changes
- **Review mode**: Code review with read-only access plus documentation tools
- **Debug mode**: Focused on investigation with bash and read tools enabled
- **Docs mode**: Documentation writing with file operations but no system commands
You might also find different models are good for different use cases.

View File

@@ -0,0 +1,57 @@
---
title: Network
description: Configure proxies and custom certificates.
---
OpenCode supports standard proxy environment variables and custom certificates for enterprise network environments.
---
## Proxy
OpenCode respects standard proxy environment variables.
```bash
# HTTPS proxy (recommended)
export HTTPS_PROXY=https://proxy.example.com:8080
# HTTP proxy (if HTTPS not available)
export HTTP_PROXY=http://proxy.example.com:8080
# Bypass proxy for local server (required)
export NO_PROXY=localhost,127.0.0.1
```
:::caution
The TUI communicates with a local HTTP server. You must bypass the proxy for this connection to prevent routing loops.
:::
You can configure the server's port and hostname using [CLI flags](/docs/cli#run).
---
### Authenticate
If your proxy requires basic authentication, include credentials in the URL.
```bash
export HTTPS_PROXY=http://username:password@proxy.example.com:8080
```
:::caution
Avoid hardcoding passwords. Use environment variables or secure credential storage.
:::
For proxies requiring advanced authentication like NTLM or Kerberos, consider using an LLM Gateway that supports your authentication method.
---
## Custom certificates
If your enterprise uses custom CAs for HTTPS connections, configure OpenCode to trust them.
```bash
export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
```
This works for both proxy connections and direct API access.

View File

@@ -0,0 +1,237 @@
---
title: Permissions
description: Control which actions require approval to run.
---
OpenCode uses the `permission` config to decide whether a given action should run automatically, prompt you, or be blocked.
As of `v1.1.1`, the legacy `tools` boolean config is deprecated and has been merged into `permission`. The old `tools` config is still supported for backwards compatibility.
---
## Actions
Each permission rule resolves to one of:
- `"allow"` — run without approval
- `"ask"` — prompt for approval
- `"deny"` — block the action
---
## Configuration
You can set permissions globally (with `*`), and override specific tools.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"*": "ask",
"bash": "allow",
"edit": "deny"
}
}
```
You can also set all permissions at once:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": "allow"
}
```
---
## Granular Rules (Object Syntax)
For most permissions, you can use an object to apply different actions based on the tool input.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"npm *": "allow",
"rm *": "deny",
"grep *": "allow"
},
"edit": {
"*": "deny",
"packages/web/src/content/docs/*.mdx": "allow"
}
}
}
```
Rules are evaluated by pattern match, with the **last matching rule winning**. A common pattern is to put the catch-all `"*"` rule first, and more specific rules after it.
### Wildcards
Permission patterns use simple wildcard matching:
- `*` matches zero or more of any character
- `?` matches exactly one character
- All other characters match literally
### Home Directory Expansion
You can use `~` or `$HOME` at the start of a pattern to reference your home directory. This is particularly useful for [`external_directory`](#external-directories) rules.
- `~/projects/*` -> `/Users/username/projects/*`
- `$HOME/projects/*` -> `/Users/username/projects/*`
- `~` -> `/Users/username`
### External Directories
Use `external_directory` to allow tool calls that touch paths outside the working directory where OpenCode was started. This applies to any tool that takes a path as input (for example `read`, `edit`, `list`, `glob`, `grep`, and many `bash` commands).
Home expansion (like `~/...`) only affects how a pattern is written. It does not make an external path part of the current workspace, so paths outside the working directory must still be allowed via `external_directory`.
For example, this allows access to everything under `~/projects/personal/`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
}
}
}
```
Any directory allowed here inherits the same defaults as the current workspace. Since [`read` defaults to `allow`](#defaults), reads are also allowed for entries under `external_directory` unless overridden. Add explicit rules when a tool should be restricted in these paths, such as blocking edits while keeping reads:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"external_directory": {
"~/projects/personal/**": "allow"
},
"edit": {
"~/projects/personal/**": "deny"
}
}
}
```
Keep the list focused on trusted paths, and layer extra allow or deny rules as needed for other tools (for example `bash`).
---
## Available Permissions
OpenCode permissions are keyed by tool name, plus a couple of safety guards:
- `read` — reading a file (matches the file path)
- `edit` — all file modifications (covers `edit`, `write`, `patch`, `multiedit`)
- `glob` — file globbing (matches the glob pattern)
- `grep` — content search (matches the regex pattern)
- `list` — listing files in a directory (matches the directory path)
- `bash` — running shell commands (matches parsed commands like `git status --porcelain`)
- `task` — launching subagents (matches the subagent type)
- `skill` — loading a skill (matches the skill name)
- `lsp` — running LSP queries (currently non-granular)
- `todoread`, `todowrite` — reading/updating the todo list
- `webfetch` — fetching a URL (matches the URL)
- `websearch`, `codesearch` — web/code search (matches the query)
- `external_directory` — triggered when a tool touches paths outside the project working directory
- `doom_loop` — triggered when the same tool call repeats 3 times with identical input
---
## Defaults
If you dont specify anything, OpenCode starts from permissive defaults:
- Most permissions default to `"allow"`.
- `doom_loop` and `external_directory` default to `"ask"`.
- `read` is `"allow"`, but `.env` files are denied by default:
```json title="opencode.json"
{
"permission": {
"read": {
"*": "allow",
"*.env": "deny",
"*.env.*": "deny",
"*.env.example": "allow"
}
}
}
```
---
## What “Ask” Does
When OpenCode prompts for approval, the UI offers three outcomes:
- `once` — approve just this request
- `always` — approve future requests matching the suggested patterns (for the rest of the current OpenCode session)
- `reject` — deny the request
The set of patterns that `always` would approve is provided by the tool (for example, bash approvals typically whitelist a safe command prefix like `git status*`).
---
## Agents
You can override permissions per agent. Agent permissions are merged with the global config, and agent rules take precedence. [Learn more](/docs/agents#permissions) about agent permissions.
:::note
Refer to the [Granular Rules (Object Syntax)](#granular-rules-object-syntax) section above for more detailed pattern matching examples.
:::
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "deny",
"git push *": "deny",
"grep *": "allow"
}
},
"agent": {
"build": {
"permission": {
"bash": {
"*": "ask",
"git *": "allow",
"git commit *": "ask",
"git push *": "deny",
"grep *": "allow"
}
}
}
}
}
```
You can also configure agent permissions in Markdown:
```markdown title="~/.config/opencode/agents/review.md"
---
description: Code review without edits
mode: subagent
permission:
edit: deny
bash: ask
webfetch: deny
---
Only analyze code and suggest changes.
```
:::tip
Use pattern matching for commands with arguments. `"grep *"` allows `grep pattern file.txt`, while `"grep"` alone would block it. Commands like `git status` work for default behavior but require explicit permission (like `"git status *"`) when arguments are passed.
:::

View File

@@ -0,0 +1,385 @@
---
title: Plugins
description: Write your own plugins to extend OpenCode.
---
Plugins allow you to extend OpenCode by hooking into various events and customizing behavior. You can create plugins to add new features, integrate with external services, or modify OpenCode's default behavior.
For examples, check out the [plugins](/docs/ecosystem#plugins) created by the community.
---
## Use a plugin
There are two ways to load plugins.
---
### From local files
Place JavaScript or TypeScript files in the plugin directory.
- `.opencode/plugins/` - Project-level plugins
- `~/.config/opencode/plugins/` - Global plugins
Files in these directories are automatically loaded at startup.
---
### From npm
Specify npm packages in your config file.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime", "@my-org/custom-plugin"]
}
```
Both regular and scoped npm packages are supported.
Browse available plugins in the [ecosystem](/docs/ecosystem#plugins).
---
### How plugins are installed
**npm plugins** are installed automatically using Bun at startup. Packages and their dependencies are cached in `~/.cache/opencode/node_modules/`.
**Local plugins** are loaded directly from the plugin directory. To use external packages, you must create a `package.json` within your config directory (see [Dependencies](#dependencies)), or publish the plugin to npm and [add it to your config](/docs/config#plugins).
---
### Load order
Plugins are loaded from all sources and all hooks run in sequence. The load order is:
1. Global config (`~/.config/opencode/opencode.json`)
2. Project config (`opencode.json`)
3. Global plugin directory (`~/.config/opencode/plugins/`)
4. Project plugin directory (`.opencode/plugins/`)
Duplicate npm packages with the same name and version are loaded once. However, a local plugin and an npm plugin with similar names are both loaded separately.
---
## Create a plugin
A plugin is a **JavaScript/TypeScript module** that exports one or more plugin
functions. Each function receives a context object and returns a hooks object.
---
### Dependencies
Local plugins and custom tools can use external npm packages. Add a `package.json` to your config directory with the dependencies you need.
```json title=".opencode/package.json"
{
"dependencies": {
"shescape": "^2.1.0"
}
}
```
OpenCode runs `bun install` at startup to install these. Your plugins and tools can then import them.
```ts title=".opencode/plugins/my-plugin.ts"
import { escape } from "shescape"
export const MyPlugin = async (ctx) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "bash") {
output.args.command = escape(output.args.command)
}
},
}
}
```
---
### Basic structure
```js title=".opencode/plugins/example.js"
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
console.log("Plugin initialized!")
return {
// Hook implementations go here
}
}
```
The plugin function receives:
- `project`: The current project information.
- `directory`: The current working directory.
- `worktree`: The git worktree path.
- `client`: An opencode SDK client for interacting with the AI.
- `$`: Bun's [shell API](https://bun.com/docs/runtime/shell) for executing commands.
---
### TypeScript support
For TypeScript plugins, you can import types from the plugin package:
```ts title="my-plugin.ts" {1}
import type { Plugin } from "@opencode-ai/plugin"
export const MyPlugin: Plugin = async ({ project, client, $, directory, worktree }) => {
return {
// Type-safe hook implementations
}
}
```
---
### Events
Plugins can subscribe to events as seen below in the Examples section. Here is a list of the different events available.
#### Command Events
- `command.executed`
#### File Events
- `file.edited`
- `file.watcher.updated`
#### Installation Events
- `installation.updated`
#### LSP Events
- `lsp.client.diagnostics`
- `lsp.updated`
#### Message Events
- `message.part.removed`
- `message.part.updated`
- `message.removed`
- `message.updated`
#### Permission Events
- `permission.asked`
- `permission.replied`
#### Server Events
- `server.connected`
#### Session Events
- `session.created`
- `session.compacted`
- `session.deleted`
- `session.diff`
- `session.error`
- `session.idle`
- `session.status`
- `session.updated`
#### Todo Events
- `todo.updated`
#### Shell Events
- `shell.env`
#### Tool Events
- `tool.execute.after`
- `tool.execute.before`
#### TUI Events
- `tui.prompt.append`
- `tui.command.execute`
- `tui.toast.show`
---
## Examples
Here are some examples of plugins you can use to extend opencode.
---
### Send notifications
Send notifications when certain events occur:
```js title=".opencode/plugins/notification.js"
export const NotificationPlugin = async ({ project, client, $, directory, worktree }) => {
return {
event: async ({ event }) => {
// Send notification on session completion
if (event.type === "session.idle") {
await $`osascript -e 'display notification "Session completed!" with title "opencode"'`
}
},
}
}
```
We are using `osascript` to run AppleScript on macOS. Here we are using it to send notifications.
:::note
If youre using the OpenCode desktop app, it can send system notifications automatically when a response is ready or when a session errors.
:::
---
### .env protection
Prevent opencode from reading `.env` files:
```javascript title=".opencode/plugins/env-protection.js"
export const EnvProtection = async ({ project, client, $, directory, worktree }) => {
return {
"tool.execute.before": async (input, output) => {
if (input.tool === "read" && output.args.filePath.includes(".env")) {
throw new Error("Do not read .env files")
}
},
}
}
```
---
### Inject environment variables
Inject environment variables into all shell execution (AI tools and user terminals):
```javascript title=".opencode/plugins/inject-env.js"
export const InjectEnvPlugin = async () => {
return {
"shell.env": async (input, output) => {
output.env.MY_API_KEY = "secret"
output.env.PROJECT_ROOT = input.cwd
},
}
}
```
---
### Custom tools
Plugins can also add custom tools to opencode:
```ts title=".opencode/plugins/custom-tools.ts"
import { type Plugin, tool } from "@opencode-ai/plugin"
export const CustomToolsPlugin: Plugin = async (ctx) => {
return {
tool: {
mytool: tool({
description: "This is a custom tool",
args: {
foo: tool.schema.string(),
},
async execute(args, context) {
const { directory, worktree } = context
return `Hello ${args.foo} from ${directory} (worktree: ${worktree})`
},
}),
},
}
}
```
The `tool` helper creates a custom tool that opencode can call. It takes a Zod schema function and returns a tool definition with:
- `description`: What the tool does
- `args`: Zod schema for the tool's arguments
- `execute`: Function that runs when the tool is called
Your custom tools will be available to opencode alongside built-in tools.
---
### Logging
Use `client.app.log()` instead of `console.log` for structured logging:
```ts title=".opencode/plugins/my-plugin.ts"
export const MyPlugin = async ({ client }) => {
await client.app.log({
body: {
service: "my-plugin",
level: "info",
message: "Plugin initialized",
extra: { foo: "bar" },
},
})
}
```
Levels: `debug`, `info`, `warn`, `error`. See [SDK documentation](https://opencode.ai/docs/sdk) for details.
---
### Compaction hooks
Customize the context included when a session is compacted:
```ts title=".opencode/plugins/compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"
export const CompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Inject additional context into the compaction prompt
output.context.push(`
## Custom Context
Include any state that should persist across compaction:
- Current task status
- Important decisions made
- Files being actively worked on
`)
},
}
}
```
The `experimental.session.compacting` hook fires before the LLM generates a continuation summary. Use it to inject domain-specific context that the default compaction prompt would miss.
You can also replace the compaction prompt entirely by setting `output.prompt`:
```ts title=".opencode/plugins/custom-compaction.ts"
import type { Plugin } from "@opencode-ai/plugin"
export const CustomCompactionPlugin: Plugin = async (ctx) => {
return {
"experimental.session.compacting": async (input, output) => {
// Replace the entire compaction prompt
output.prompt = `
You are generating a continuation prompt for a multi-agent swarm session.
Summarize:
1. The current task and its status
2. Which files are being modified and by whom
3. Any blockers or dependencies between agents
4. The next steps to complete the work
Format as a structured prompt that a new agent can use to resume work.
`
},
}
}
```
When `output.prompt` is set, it completely replaces the default compaction prompt. The `output.context` array is ignored in this case.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
---
title: Rules
description: Set custom instructions for opencode.
---
You can provide custom instructions to opencode by creating an `AGENTS.md` file. This is similar to Cursor's rules. It contains instructions that will be included in the LLM's context to customize its behavior for your specific project.
---
## Initialize
To create a new `AGENTS.md` file, you can run the `/init` command in opencode.
:::tip
You should commit your project's `AGENTS.md` file to Git.
:::
This will scan your project and all its contents to understand what the project is about and generate an `AGENTS.md` file with it. This helps opencode to navigate the project better.
If you have an existing `AGENTS.md` file, this will try to add to it.
---
## Example
You can also just create this file manually. Here's an example of some things you can put into an `AGENTS.md` file.
```markdown title="AGENTS.md"
# SST v3 Monorepo Project
This is an SST v3 monorepo with TypeScript. The project uses bun workspaces for package management.
## Project Structure
- `packages/` - Contains all workspace packages (functions, core, web, etc.)
- `infra/` - Infrastructure definitions split by service (storage.ts, api.ts, web.ts)
- `sst.config.ts` - Main SST configuration with dynamic imports
## Code Standards
- Use TypeScript with strict mode enabled
- Shared code goes in `packages/core/` with proper exports configuration
- Functions go in `packages/functions/`
- Infrastructure should be split into logical files in `infra/`
## Monorepo Conventions
- Import shared modules using workspace names: `@my-app/core/example`
```
We are adding project-specific instructions here and this will be shared across your team.
---
## Types
opencode also supports reading the `AGENTS.md` file from multiple locations. And this serves different purposes.
### Project
Place an `AGENTS.md` in your project root for project-specific rules. These only apply when you are working in this directory or its sub-directories.
### Global
You can also have global rules in a `~/.config/opencode/AGENTS.md` file. This gets applied across all opencode sessions.
Since this isn't committed to Git or shared with your team, we recommend using this to specify any personal rules that the LLM should follow.
### Claude Code Compatibility
For users migrating from Claude Code, OpenCode supports Claude Code's file conventions as fallbacks:
- **Project rules**: `CLAUDE.md` in your project directory (used if no `AGENTS.md` exists)
- **Global rules**: `~/.claude/CLAUDE.md` (used if no `~/.config/opencode/AGENTS.md` exists)
- **Skills**: `~/.claude/skills/` — see [Agent Skills](/docs/skills/) for details
To disable Claude Code compatibility, set one of these environment variables:
```bash
export OPENCODE_DISABLE_CLAUDE_CODE=1 # Disable all .claude support
export OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1 # Disable only ~/.claude/CLAUDE.md
export OPENCODE_DISABLE_CLAUDE_CODE_SKILLS=1 # Disable only .claude/skills
```
---
## Precedence
When opencode starts, it looks for rule files in this order:
1. **Local files** by traversing up from the current directory (`AGENTS.md`, `CLAUDE.md`)
2. **Global file** at `~/.config/opencode/AGENTS.md`
3. **Claude Code file** at `~/.claude/CLAUDE.md` (unless disabled)
The first matching file wins in each category. For example, if you have both `AGENTS.md` and `CLAUDE.md`, only `AGENTS.md` is used. Similarly, `~/.config/opencode/AGENTS.md` takes precedence over `~/.claude/CLAUDE.md`.
---
## Custom Instructions
You can specify custom instruction files in your `opencode.json` or the global `~/.config/opencode/opencode.json`. This allows you and your team to reuse existing rules rather than having to duplicate them to AGENTS.md.
Example:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["CONTRIBUTING.md", "docs/guidelines.md", ".cursor/rules/*.md"]
}
```
You can also use remote URLs to load instructions from the web.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["https://raw.githubusercontent.com/my-org/shared-rules/main/style.md"]
}
```
Remote instructions are fetched with a 5 second timeout.
All instruction files are combined with your `AGENTS.md` files.
---
## Referencing External Files
While opencode doesn't automatically parse file references in `AGENTS.md`, you can achieve similar functionality in two ways:
### Using opencode.json
The recommended approach is to use the `instructions` field in `opencode.json`:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"instructions": ["docs/development-standards.md", "test/testing-guidelines.md", "packages/*/AGENTS.md"]
}
```
### Manual Instructions in AGENTS.md
You can teach opencode to read external files by providing explicit instructions in your `AGENTS.md`. Here's a practical example:
```markdown title="AGENTS.md"
# TypeScript Project Rules
## External File Loading
CRITICAL: When you encounter a file reference (e.g., @rules/general.md), use your Read tool to load it on a need-to-know basis. They're relevant to the SPECIFIC task at hand.
Instructions:
- Do NOT preemptively load all references - use lazy loading based on actual need
- When loaded, treat content as mandatory instructions that override defaults
- Follow references recursively when needed
## Development Guidelines
For TypeScript code style and best practices: @docs/typescript-guidelines.md
For React component architecture and hooks patterns: @docs/react-patterns.md
For REST API design and error handling: @docs/api-standards.md
For testing strategies and coverage requirements: @test/testing-guidelines.md
## General Guidelines
Read the following file immediately as it's relevant to all workflows: @rules/general-guidelines.md.
```
This approach allows you to:
- Create modular, reusable rule files
- Share rules across projects via symlinks or git submodules
- Keep AGENTS.md concise while referencing detailed guidelines
- Ensure opencode loads files only when needed for the specific task
:::tip
For monorepos or projects with shared standards, using `opencode.json` with glob patterns (like `packages/*/AGENTS.md`) is more maintainable than manual instructions.
:::

View File

@@ -0,0 +1,391 @@
---
title: SDK
description: Type-safe JS client for opencode server.
---
import config from "../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`
The opencode JS/TS SDK provides a type-safe client for interacting with the server.
Use it to build integrations and control opencode programmatically.
[Learn more](/docs/server) about how the server works. For examples, check out the [projects](/docs/ecosystem#projects) built by the community.
---
## Install
Install the SDK from npm:
```bash
npm install @opencode-ai/sdk
```
---
## Create client
Create an instance of opencode:
```javascript
import { createOpencode } from "@opencode-ai/sdk"
const { client } = await createOpencode()
```
This starts both a server and a client
#### Options
| Option | Type | Description | Default |
| ---------- | ------------- | ------------------------------ | ----------- |
| `hostname` | `string` | Server hostname | `127.0.0.1` |
| `port` | `number` | Server port | `4096` |
| `signal` | `AbortSignal` | Abort signal for cancellation | `undefined` |
| `timeout` | `number` | Timeout in ms for server start | `5000` |
| `config` | `Config` | Configuration object | `{}` |
---
## Config
You can pass a configuration object to customize behavior. The instance still picks up your `opencode.json`, but you can override or add configuration inline:
```javascript
import { createOpencode } from "@opencode-ai/sdk"
const opencode = await createOpencode({
hostname: "127.0.0.1",
port: 4096,
config: {
model: "anthropic/claude-3-5-sonnet-20241022",
},
})
console.log(`Server running at ${opencode.server.url}`)
opencode.server.close()
```
## Client only
If you already have a running instance of opencode, you can create a client instance to connect to it:
```javascript
import { createOpencodeClient } from "@opencode-ai/sdk"
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
})
```
#### Options
| Option | Type | Description | Default |
| --------------- | ---------- | -------------------------------- | ----------------------- |
| `baseUrl` | `string` | URL of the server | `http://localhost:4096` |
| `fetch` | `function` | Custom fetch implementation | `globalThis.fetch` |
| `parseAs` | `string` | Response parsing method | `auto` |
| `responseStyle` | `string` | Return style: `data` or `fields` | `fields` |
| `throwOnError` | `boolean` | Throw errors instead of return | `false` |
---
## Types
The SDK includes TypeScript definitions for all API types. Import them directly:
```typescript
import type { Session, Message, Part } from "@opencode-ai/sdk"
```
All types are generated from the server's OpenAPI specification and available in the <a href={typesUrl}>types file</a>.
---
## Errors
The SDK can throw errors that you can catch and handle:
```typescript
try {
await client.session.get({ path: { id: "invalid-id" } })
} catch (error) {
console.error("Failed to get session:", (error as Error).message)
}
```
---
## APIs
The SDK exposes all server APIs through a type-safe client.
---
### Global
| Method | Description | Response |
| ----------------- | ------------------------------- | ------------------------------------ |
| `global.health()` | Check server health and version | `{ healthy: true, version: string }` |
---
#### Examples
```javascript
const health = await client.global.health()
console.log(health.data.version)
```
---
### App
| Method | Description | Response |
| -------------- | ------------------------- | ------------------------------------------- |
| `app.log()` | Write a log entry | `boolean` |
| `app.agents()` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> |
---
#### Examples
```javascript
// Write a log entry
await client.app.log({
body: {
service: "my-app",
level: "info",
message: "Operation completed",
},
})
// List available agents
const agents = await client.app.agents()
```
---
### Project
| Method | Description | Response |
| ------------------- | ------------------- | --------------------------------------------- |
| `project.list()` | List all projects | <a href={typesUrl}><code>Project[]</code></a> |
| `project.current()` | Get current project | <a href={typesUrl}><code>Project</code></a> |
---
#### Examples
```javascript
// List all projects
const projects = await client.project.list()
// Get current project
const currentProject = await client.project.current()
```
---
### Path
| Method | Description | Response |
| ------------ | ---------------- | ---------------------------------------- |
| `path.get()` | Get current path | <a href={typesUrl}><code>Path</code></a> |
---
#### Examples
```javascript
// Get current path information
const pathInfo = await client.path.get()
```
---
### Config
| Method | Description | Response |
| -------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `config.get()` | Get config info | <a href={typesUrl}><code>Config</code></a> |
| `config.providers()` | List providers and default models | `{ providers: `<a href={typesUrl}><code>Provider[]</code></a>`, default: { [key: string]: string } }` |
---
#### Examples
```javascript
const config = await client.config.get()
const { providers, default: defaults } = await client.config.providers()
```
---
### Sessions
| Method | Description | Notes |
| ---------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `session.list()` | List sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `session.get({ path })` | Get session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.children({ path })` | List child sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `session.create({ body })` | Create session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.delete({ path })` | Delete session | Returns `boolean` |
| `session.update({ path, body })` | Update session properties | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.init({ path, body })` | Analyze app and create `AGENTS.md` | Returns `boolean` |
| `session.abort({ path })` | Abort a running session | Returns `boolean` |
| `session.share({ path })` | Share session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.unshare({ path })` | Unshare session | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.summarize({ path, body })` | Summarize session | Returns `boolean` |
| `session.messages({ path })` | List messages in a session | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}[]` |
| `session.message({ path })` | Get message details | Returns `{ info: `<a href={typesUrl}><code>Message</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}` |
| `session.prompt({ path, body })` | Send prompt message | `body.noReply: true` returns UserMessage (context only). Default returns <a href={typesUrl}><code>AssistantMessage</code></a> with AI response |
| `session.command({ path, body })` | Send command to session | Returns `{ info: `<a href={typesUrl}><code>AssistantMessage</code></a>`, parts: `<a href={typesUrl}><code>Part[]</code></a>`}` |
| `session.shell({ path, body })` | Run a shell command | Returns <a href={typesUrl}><code>AssistantMessage</code></a> |
| `session.revert({ path, body })` | Revert a message | Returns <a href={typesUrl}><code>Session</code></a> |
| `session.unrevert({ path })` | Restore reverted messages | Returns <a href={typesUrl}><code>Session</code></a> |
| `postSessionByIdPermissionsByPermissionId({ path, body })` | Respond to a permission request | Returns `boolean` |
---
#### Examples
```javascript
// Create and manage sessions
const session = await client.session.create({
body: { title: "My session" },
})
const sessions = await client.session.list()
// Send a prompt message
const result = await client.session.prompt({
path: { id: session.id },
body: {
model: { providerID: "anthropic", modelID: "claude-3-5-sonnet-20241022" },
parts: [{ type: "text", text: "Hello!" }],
},
})
// Inject context without triggering AI response (useful for plugins)
await client.session.prompt({
path: { id: session.id },
body: {
noReply: true,
parts: [{ type: "text", text: "You are a helpful assistant." }],
},
})
```
---
### Files
| Method | Description | Response |
| ------------------------- | ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `find.text({ query })` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` |
| `find.files({ query })` | Find files and directories by name | `string[]` (paths) |
| `find.symbols({ query })` | Find workspace symbols | <a href={typesUrl}><code>Symbol[]</code></a> |
| `file.read({ query })` | Read a file | `{ type: "raw" \| "patch", content: string }` |
| `file.status({ query? })` | Get status for tracked files | <a href={typesUrl}><code>File[]</code></a> |
`find.files` supports a few optional query fields:
- `type`: `"file"` or `"directory"`
- `directory`: override the project root for the search
- `limit`: max results (1200)
---
#### Examples
```javascript
// Search and read files
const textResults = await client.find.text({
query: { pattern: "function.*opencode" },
})
const files = await client.find.files({
query: { query: "*.ts", type: "file" },
})
const directories = await client.find.files({
query: { query: "packages", type: "directory", limit: 20 },
})
const content = await client.file.read({
query: { path: "src/index.ts" },
})
```
---
### TUI
| Method | Description | Response |
| ------------------------------ | ------------------------- | --------- |
| `tui.appendPrompt({ body })` | Append text to the prompt | `boolean` |
| `tui.openHelp()` | Open the help dialog | `boolean` |
| `tui.openSessions()` | Open the session selector | `boolean` |
| `tui.openThemes()` | Open the theme selector | `boolean` |
| `tui.openModels()` | Open the model selector | `boolean` |
| `tui.submitPrompt()` | Submit the current prompt | `boolean` |
| `tui.clearPrompt()` | Clear the prompt | `boolean` |
| `tui.executeCommand({ body })` | Execute a command | `boolean` |
| `tui.showToast({ body })` | Show toast notification | `boolean` |
---
#### Examples
```javascript
// Control TUI interface
await client.tui.appendPrompt({
body: { text: "Add this to prompt" },
})
await client.tui.showToast({
body: { message: "Task completed", variant: "success" },
})
```
---
### Auth
| Method | Description | Response |
| ------------------- | ------------------------------ | --------- |
| `auth.set({ ... })` | Set authentication credentials | `boolean` |
---
#### Examples
```javascript
await client.auth.set({
path: { id: "anthropic" },
body: { type: "api", key: "your-api-key" },
})
```
---
### Events
| Method | Description | Response |
| ------------------- | ------------------------- | ------------------------- |
| `event.subscribe()` | Server-sent events stream | Server-sent events stream |
---
#### Examples
```javascript
// Listen to real-time events
const events = await client.event.subscribe()
for await (const event of events.stream) {
console.log("Event:", event.type, event.properties)
}
```

View File

@@ -0,0 +1,287 @@
---
title: Server
description: Interact with opencode server over HTTP.
---
import config from "../../../config.mjs"
export const typesUrl = `${config.github}/blob/dev/packages/sdk/js/src/gen/types.gen.ts`
The `opencode serve` command runs a headless HTTP server that exposes an OpenAPI endpoint that an opencode client can use.
---
### Usage
```bash
opencode serve [--port <number>] [--hostname <string>] [--cors <origin>]
```
#### Options
| Flag | Description | Default |
| --------------- | ----------------------------------- | ---------------- |
| `--port` | Port to listen on | `4096` |
| `--hostname` | Hostname to listen on | `127.0.0.1` |
| `--mdns` | Enable mDNS discovery | `false` |
| `--mdns-domain` | Custom domain name for mDNS service | `opencode.local` |
| `--cors` | Additional browser origins to allow | `[]` |
`--cors` can be passed multiple times:
```bash
opencode serve --cors http://localhost:5173 --cors https://app.example.com
```
---
### Authentication
Set `OPENCODE_SERVER_PASSWORD` to protect the server with HTTP basic auth. The username defaults to `opencode`, or set `OPENCODE_SERVER_USERNAME` to override it. This applies to both `opencode serve` and `opencode web`.
```bash
OPENCODE_SERVER_PASSWORD=your-password opencode serve
```
---
### How it works
When you run `opencode` it starts a TUI and a server. Where the TUI is the
client that talks to the server. The server exposes an OpenAPI 3.1 spec
endpoint. This endpoint is also used to generate an [SDK](/docs/sdk).
:::tip
Use the opencode server to interact with opencode programmatically.
:::
This architecture lets opencode support multiple clients and allows you to interact with opencode programmatically.
You can run `opencode serve` to start a standalone server. If you have the
opencode TUI running, `opencode serve` will start a new server.
---
#### Connect to an existing server
When you start the TUI it randomly assigns a port and hostname. You can instead pass in the `--hostname` and `--port` [flags](/docs/cli). Then use this to connect to its server.
The [`/tui`](#tui) endpoint can be used to drive the TUI through the server. For example, you can prefill or run a prompt. This setup is used by the OpenCode [IDE](/docs/ide) plugins.
---
## Spec
The server publishes an OpenAPI 3.1 spec that can be viewed at:
```
http://<hostname>:<port>/doc
```
For example, `http://localhost:4096/doc`. Use the spec to generate clients or inspect request and response types. Or view it in a Swagger explorer.
---
## APIs
The opencode server exposes the following APIs.
---
### Global
| Method | Path | Description | Response |
| ------ | ---------------- | ------------------------------ | ------------------------------------ |
| `GET` | `/global/health` | Get server health and version | `{ healthy: true, version: string }` |
| `GET` | `/global/event` | Get global events (SSE stream) | Event stream |
---
### Project
| Method | Path | Description | Response |
| ------ | ------------------ | ----------------------- | --------------------------------------------- |
| `GET` | `/project` | List all projects | <a href={typesUrl}><code>Project[]</code></a> |
| `GET` | `/project/current` | Get the current project | <a href={typesUrl}><code>Project</code></a> |
---
### Path & VCS
| Method | Path | Description | Response |
| ------ | ------- | ------------------------------------ | ------------------------------------------- |
| `GET` | `/path` | Get the current path | <a href={typesUrl}><code>Path</code></a> |
| `GET` | `/vcs` | Get VCS info for the current project | <a href={typesUrl}><code>VcsInfo</code></a> |
---
### Instance
| Method | Path | Description | Response |
| ------ | ------------------- | ---------------------------- | --------- |
| `POST` | `/instance/dispose` | Dispose the current instance | `boolean` |
---
### Config
| Method | Path | Description | Response |
| ------- | ------------------- | --------------------------------- | ---------------------------------------------------------------------------------------- |
| `GET` | `/config` | Get config info | <a href={typesUrl}><code>Config</code></a> |
| `PATCH` | `/config` | Update config | <a href={typesUrl}><code>Config</code></a> |
| `GET` | `/config/providers` | List providers and default models | `{ providers: `<a href={typesUrl}>Provider[]</a>`, default: { [key: string]: string } }` |
---
### Provider
| Method | Path | Description | Response |
| ------ | -------------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------- |
| `GET` | `/provider` | List all providers | `{ all: `<a href={typesUrl}>Provider[]</a>`, default: {...}, connected: string[] }` |
| `GET` | `/provider/auth` | Get provider authentication methods | `{ [providerID: string]: `<a href={typesUrl}>ProviderAuthMethod[]</a>` }` |
| `POST` | `/provider/{id}/oauth/authorize` | Authorize a provider using OAuth | <a href={typesUrl}><code>ProviderAuthAuthorization</code></a> |
| `POST` | `/provider/{id}/oauth/callback` | Handle OAuth callback for a provider | `boolean` |
---
### Sessions
| Method | Path | Description | Notes |
| -------- | ---------------------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- |
| `GET` | `/session` | List all sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `POST` | `/session` | Create a new session | body: `{ parentID?, title? }`, returns <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/status` | Get session status for all sessions | Returns `{ [sessionID: string]: `<a href={typesUrl}>SessionStatus</a>` }` |
| `GET` | `/session/:id` | Get session details | Returns <a href={typesUrl}><code>Session</code></a> |
| `DELETE` | `/session/:id` | Delete a session and all its data | Returns `boolean` |
| `PATCH` | `/session/:id` | Update session properties | body: `{ title? }`, returns <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/:id/children` | Get a session's child sessions | Returns <a href={typesUrl}><code>Session[]</code></a> |
| `GET` | `/session/:id/todo` | Get the todo list for a session | Returns <a href={typesUrl}><code>Todo[]</code></a> |
| `POST` | `/session/:id/init` | Analyze app and create `AGENTS.md` | body: `{ messageID, providerID, modelID }`, returns `boolean` |
| `POST` | `/session/:id/fork` | Fork an existing session at a message | body: `{ messageID? }`, returns <a href={typesUrl}><code>Session</code></a> |
| `POST` | `/session/:id/abort` | Abort a running session | Returns `boolean` |
| `POST` | `/session/:id/share` | Share a session | Returns <a href={typesUrl}><code>Session</code></a> |
| `DELETE` | `/session/:id/share` | Unshare a session | Returns <a href={typesUrl}><code>Session</code></a> |
| `GET` | `/session/:id/diff` | Get the diff for this session | query: `messageID?`, returns <a href={typesUrl}><code>FileDiff[]</code></a> |
| `POST` | `/session/:id/summarize` | Summarize the session | body: `{ providerID, modelID }`, returns `boolean` |
| `POST` | `/session/:id/revert` | Revert a message | body: `{ messageID, partID? }`, returns `boolean` |
| `POST` | `/session/:id/unrevert` | Restore all reverted messages | Returns `boolean` |
| `POST` | `/session/:id/permissions/:permissionID` | Respond to a permission request | body: `{ response, remember? }`, returns `boolean` |
---
### Messages
| Method | Path | Description | Notes |
| ------ | --------------------------------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET` | `/session/:id/message` | List messages in a session | query: `limit?`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}[]` |
| `POST` | `/session/:id/message` | Send a message and wait for response | body: `{ messageID?, model?, agent?, noReply?, system?, tools?, parts }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `GET` | `/session/:id/message/:messageID` | Get message details | Returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `POST` | `/session/:id/prompt_async` | Send a message asynchronously (no wait) | body: same as `/session/:id/message`, returns `204 No Content` |
| `POST` | `/session/:id/command` | Execute a slash command | body: `{ messageID?, agent?, model?, command, arguments }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
| `POST` | `/session/:id/shell` | Run a shell command | body: `{ agent, model?, command }`, returns `{ info: `<a href={typesUrl}>Message</a>`, parts: `<a href={typesUrl}>Part[]</a>`}` |
---
### Commands
| Method | Path | Description | Response |
| ------ | ---------- | ----------------- | --------------------------------------------- |
| `GET` | `/command` | List all commands | <a href={typesUrl}><code>Command[]</code></a> |
---
### Files
| Method | Path | Description | Response |
| ------ | ------------------------ | ---------------------------------- | ------------------------------------------------------------------------------------------- |
| `GET` | `/find?pattern=<pat>` | Search for text in files | Array of match objects with `path`, `lines`, `line_number`, `absolute_offset`, `submatches` |
| `GET` | `/find/file?query=<q>` | Find files and directories by name | `string[]` (paths) |
| `GET` | `/find/symbol?query=<q>` | Find workspace symbols | <a href={typesUrl}><code>Symbol[]</code></a> |
| `GET` | `/file?path=<path>` | List files and directories | <a href={typesUrl}><code>FileNode[]</code></a> |
| `GET` | `/file/content?path=<p>` | Read a file | <a href={typesUrl}><code>FileContent</code></a> |
| `GET` | `/file/status` | Get status for tracked files | <a href={typesUrl}><code>File[]</code></a> |
#### `/find/file` query parameters
- `query` (required) — search string (fuzzy match)
- `type` (optional) — limit results to `"file"` or `"directory"`
- `directory` (optional) — override the project root for the search
- `limit` (optional) — max results (1200)
- `dirs` (optional) — legacy flag (`"false"` returns only files)
---
### Tools (Experimental)
| Method | Path | Description | Response |
| ------ | ------------------------------------------- | ---------------------------------------- | -------------------------------------------- |
| `GET` | `/experimental/tool/ids` | List all tool IDs | <a href={typesUrl}><code>ToolIDs</code></a> |
| `GET` | `/experimental/tool?provider=<p>&model=<m>` | List tools with JSON schemas for a model | <a href={typesUrl}><code>ToolList</code></a> |
---
### LSP, Formatters & MCP
| Method | Path | Description | Response |
| ------ | ------------ | -------------------------- | -------------------------------------------------------- |
| `GET` | `/lsp` | Get LSP server status | <a href={typesUrl}><code>LSPStatus[]</code></a> |
| `GET` | `/formatter` | Get formatter status | <a href={typesUrl}><code>FormatterStatus[]</code></a> |
| `GET` | `/mcp` | Get MCP server status | `{ [name: string]: `<a href={typesUrl}>MCPStatus</a>` }` |
| `POST` | `/mcp` | Add MCP server dynamically | body: `{ name, config }`, returns MCP status object |
---
### Agents
| Method | Path | Description | Response |
| ------ | -------- | ------------------------- | ------------------------------------------- |
| `GET` | `/agent` | List all available agents | <a href={typesUrl}><code>Agent[]</code></a> |
---
### Logging
| Method | Path | Description | Response |
| ------ | ------ | ------------------------------------------------------------ | --------- |
| `POST` | `/log` | Write log entry. Body: `{ service, level, message, extra? }` | `boolean` |
---
### TUI
| Method | Path | Description | Response |
| ------ | ----------------------- | ------------------------------------------- | ---------------------- |
| `POST` | `/tui/append-prompt` | Append text to the prompt | `boolean` |
| `POST` | `/tui/open-help` | Open the help dialog | `boolean` |
| `POST` | `/tui/open-sessions` | Open the session selector | `boolean` |
| `POST` | `/tui/open-themes` | Open the theme selector | `boolean` |
| `POST` | `/tui/open-models` | Open the model selector | `boolean` |
| `POST` | `/tui/submit-prompt` | Submit the current prompt | `boolean` |
| `POST` | `/tui/clear-prompt` | Clear the prompt | `boolean` |
| `POST` | `/tui/execute-command` | Execute a command (`{ command }`) | `boolean` |
| `POST` | `/tui/show-toast` | Show toast (`{ title?, message, variant }`) | `boolean` |
| `GET` | `/tui/control/next` | Wait for the next control request | Control request object |
| `POST` | `/tui/control/response` | Respond to a control request (`{ body }`) | `boolean` |
---
### Auth
| Method | Path | Description | Response |
| ------ | ----------- | --------------------------------------------------------------- | --------- |
| `PUT` | `/auth/:id` | Set authentication credentials. Body must match provider schema | `boolean` |
---
### Events
| Method | Path | Description | Response |
| ------ | -------- | ----------------------------------------------------------------------------- | ------------------------- |
| `GET` | `/event` | Server-sent events stream. First event is `server.connected`, then bus events | Server-sent events stream |
---
### Docs
| Method | Path | Description | Response |
| ------ | ------ | ------------------------- | --------------------------- |
| `GET` | `/doc` | OpenAPI 3.1 specification | HTML page with OpenAPI spec |

View File

@@ -0,0 +1,128 @@
---
title: Share
description: Share your OpenCode conversations.
---
OpenCode's share feature allows you to create public links to your OpenCode conversations, so you can collaborate with teammates or get help from others.
:::note
Shared conversations are publicly accessible to anyone with the link.
:::
---
## How it works
When you share a conversation, OpenCode:
1. Creates a unique public URL for your session
2. Syncs your conversation history to our servers
3. Makes the conversation accessible via the shareable link — `opncd.ai/s/<share-id>`
---
## Sharing
OpenCode supports three sharing modes that control how conversations are shared:
---
### Manual (default)
By default, OpenCode uses manual sharing mode. Sessions are not shared automatically, but you can manually share them using the `/share` command:
```
/share
```
This will generate a unique URL that'll be copied to your clipboard.
To explicitly set manual mode in your [config file](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opncd.ai/config.json",
"share": "manual"
}
```
---
### Auto-share
You can enable automatic sharing for all new conversations by setting the `share` option to `"auto"` in your [config file](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opncd.ai/config.json",
"share": "auto"
}
```
With auto-share enabled, every new conversation will automatically be shared and a link will be generated.
---
### Disabled
You can disable sharing entirely by setting the `share` option to `"disabled"` in your [config file](/docs/config):
```json title="opencode.json"
{
"$schema": "https://opncd.ai/config.json",
"share": "disabled"
}
```
To enforce this across your team for a given project, add it to the `opencode.json` in your project and check into Git.
---
## Un-sharing
To stop sharing a conversation and remove it from public access:
```
/unshare
```
This will remove the share link and delete the data related to the conversation.
---
## Privacy
There are a few things to keep in mind when sharing a conversation.
---
### Data retention
Shared conversations remain accessible until you explicitly unshare them. This
includes:
- Full conversation history
- All messages and responses
- Session metadata
---
### Recommendations
- Only share conversations that don't contain sensitive information.
- Review conversation content before sharing.
- Unshare conversations when collaboration is complete.
- Avoid sharing conversations with proprietary code or confidential data.
- For sensitive projects, disable sharing entirely.
---
## For enterprises
For enterprise deployments, the share feature can be:
- **Disabled** entirely for security compliance
- **Restricted** to users authenticated through SSO only
- **Self-hosted** on your own infrastructure
[Learn more](/docs/enterprise) about using opencode in your organization.

View File

@@ -0,0 +1,222 @@
---
title: "Agent Skills"
description: "Define reusable behavior via SKILL.md definitions"
---
Agent skills let OpenCode discover reusable instructions from your repo or home directory.
Skills are loaded on-demand via the native `skill` tool—agents see available skills and can load the full content when needed.
---
## Place files
Create one folder per skill name and put a `SKILL.md` inside it.
OpenCode searches these locations:
- Project config: `.opencode/skills/<name>/SKILL.md`
- Global config: `~/.config/opencode/skills/<name>/SKILL.md`
- Project Claude-compatible: `.claude/skills/<name>/SKILL.md`
- Global Claude-compatible: `~/.claude/skills/<name>/SKILL.md`
- Project agent-compatible: `.agents/skills/<name>/SKILL.md`
- Global agent-compatible: `~/.agents/skills/<name>/SKILL.md`
---
## Understand discovery
For project-local paths, OpenCode walks up from your current working directory until it reaches the git worktree.
It loads any matching `skills/*/SKILL.md` in `.opencode/` and any matching `.claude/skills/*/SKILL.md` or `.agents/skills/*/SKILL.md` along the way.
Global definitions are also loaded from `~/.config/opencode/skills/*/SKILL.md`, `~/.claude/skills/*/SKILL.md`, and `~/.agents/skills/*/SKILL.md`.
---
## Write frontmatter
Each `SKILL.md` must start with YAML frontmatter.
Only these fields are recognized:
- `name` (required)
- `description` (required)
- `license` (optional)
- `compatibility` (optional)
- `metadata` (optional, string-to-string map)
Unknown frontmatter fields are ignored.
---
## Validate names
`name` must:
- Be 164 characters
- Be lowercase alphanumeric with single hyphen separators
- Not start or end with `-`
- Not contain consecutive `--`
- Match the directory name that contains `SKILL.md`
Equivalent regex:
```text
^[a-z0-9]+(-[a-z0-9]+)*$
```
---
## Follow length rules
`description` must be 1-1024 characters.
Keep it specific enough for the agent to choose correctly.
---
## Use an example
Create `.opencode/skills/git-release/SKILL.md` like this:
```markdown
---
name: git-release
description: Create consistent releases and changelogs
license: MIT
compatibility: opencode
metadata:
audience: maintainers
workflow: github
---
## What I do
- Draft release notes from merged PRs
- Propose a version bump
- Provide a copy-pasteable `gh release create` command
## When to use me
Use this when you are preparing a tagged release.
Ask clarifying questions if the target versioning scheme is unclear.
```
---
## Recognize tool description
OpenCode lists available skills in the `skill` tool description.
Each entry includes the skill name and description:
```xml
<available_skills>
<skill>
<name>git-release</name>
<description>Create consistent releases and changelogs</description>
</skill>
</available_skills>
```
The agent loads a skill by calling the tool:
```
skill({ name: "git-release" })
```
---
## Configure permissions
Control which skills agents can access using pattern-based permissions in `opencode.json`:
```json
{
"permission": {
"skill": {
"*": "allow",
"pr-review": "allow",
"internal-*": "deny",
"experimental-*": "ask"
}
}
}
```
| Permission | Behavior |
| ---------- | ----------------------------------------- |
| `allow` | Skill loads immediately |
| `deny` | Skill hidden from agent, access rejected |
| `ask` | User prompted for approval before loading |
Patterns support wildcards: `internal-*` matches `internal-docs`, `internal-tools`, etc.
---
## Override per agent
Give specific agents different permissions than the global defaults.
**For custom agents** (in agent frontmatter):
```yaml
---
permission:
skill:
"documents-*": "allow"
---
```
**For built-in agents** (in `opencode.json`):
```json
{
"agent": {
"plan": {
"permission": {
"skill": {
"internal-*": "allow"
}
}
}
}
}
```
---
## Disable the skill tool
Completely disable skills for agents that shouldn't use them:
**For custom agents**:
```yaml
---
tools:
skill: false
---
```
**For built-in agents**:
```json
{
"agent": {
"plan": {
"tools": {
"skill": false
}
}
}
}
```
When disabled, the `<available_skills>` section is omitted entirely.
---
## Troubleshoot loading
If a skill does not show up:
1. Verify `SKILL.md` is spelled in all caps
2. Check that frontmatter includes `name` and `description`
3. Ensure skill names are unique across all locations
4. Check permissions—skills with `deny` are hidden from agents

View File

@@ -0,0 +1,369 @@
---
title: Themes
description: Select a built-in theme or define your own.
---
With OpenCode you can select from one of several built-in themes, use a theme that adapts to your terminal theme, or define your own custom theme.
By default, OpenCode uses our own `opencode` theme.
---
## Terminal requirements
For themes to display correctly with their full color palette, your terminal must support **truecolor** (24-bit color). Most modern terminals support this by default, but you may need to enable it:
- **Check support**: Run `echo $COLORTERM` - it should output `truecolor` or `24bit`
- **Enable truecolor**: Set the environment variable `COLORTERM=truecolor` in your shell profile
- **Terminal compatibility**: Ensure your terminal emulator supports 24-bit color (most modern terminals like iTerm2, Alacritty, Kitty, Windows Terminal, and recent versions of GNOME Terminal do)
Without truecolor support, themes may appear with reduced color accuracy or fall back to the nearest 256-color approximation.
---
## Built-in themes
OpenCode comes with several built-in themes.
| Name | Description |
| ---------------------- | ---------------------------------------------------------------------------- |
| `system` | Adapts to your terminals background color |
| `tokyonight` | Based on the [Tokyonight](https://github.com/folke/tokyonight.nvim) theme |
| `everforest` | Based on the [Everforest](https://github.com/sainnhe/everforest) theme |
| `ayu` | Based on the [Ayu](https://github.com/ayu-theme) dark theme |
| `catppuccin` | Based on the [Catppuccin](https://github.com/catppuccin) theme |
| `catppuccin-macchiato` | Based on the [Catppuccin](https://github.com/catppuccin) theme |
| `gruvbox` | Based on the [Gruvbox](https://github.com/morhetz/gruvbox) theme |
| `kanagawa` | Based on the [Kanagawa](https://github.com/rebelot/kanagawa.nvim) theme |
| `nord` | Based on the [Nord](https://github.com/nordtheme/nord) theme |
| `matrix` | Hacker-style green on black theme |
| `one-dark` | Based on the [Atom One](https://github.com/Th3Whit3Wolf/one-nvim) Dark theme |
And more, we are constantly adding new themes.
---
## System theme
The `system` theme is designed to automatically adapt to your terminal's color scheme. Unlike traditional themes that use fixed colors, the _system_ theme:
- **Generates gray scale**: Creates a custom gray scale based on your terminal's background color, ensuring optimal contrast.
- **Uses ANSI colors**: Leverages standard ANSI colors (0-15) for syntax highlighting and UI elements, which respect your terminal's color palette.
- **Preserves terminal defaults**: Uses `none` for text and background colors to maintain your terminal's native appearance.
The system theme is for users who:
- Want OpenCode to match their terminal's appearance
- Use custom terminal color schemes
- Prefer a consistent look across all terminal applications
---
## Using a theme
You can select a theme by bringing up the theme select with the `/theme` command. Or you can specify it in your [config](/docs/config).
```json title="opencode.json" {3}
{
"$schema": "https://opencode.ai/config.json",
"theme": "tokyonight"
}
```
---
## Custom themes
OpenCode supports a flexible JSON-based theme system that allows users to create and customize themes easily.
---
### Hierarchy
Themes are loaded from multiple directories in the following order where later directories override earlier ones:
1. **Built-in themes** - These are embedded in the binary
2. **User config directory** - Defined in `~/.config/opencode/themes/*.json` or `$XDG_CONFIG_HOME/opencode/themes/*.json`
3. **Project root directory** - Defined in the `<project-root>/.opencode/themes/*.json`
4. **Current working directory** - Defined in `./.opencode/themes/*.json`
If multiple directories contain a theme with the same name, the theme from the directory with higher priority will be used.
---
### Creating a theme
To create a custom theme, create a JSON file in one of the theme directories.
For user-wide themes:
```bash no-frame
mkdir -p ~/.config/opencode/themes
vim ~/.config/opencode/themes/my-theme.json
```
And for project-specific themes.
```bash no-frame
mkdir -p .opencode/themes
vim .opencode/themes/my-theme.json
```
---
### JSON format
Themes use a flexible JSON format with support for:
- **Hex colors**: `"#ffffff"`
- **ANSI colors**: `3` (0-255)
- **Color references**: `"primary"` or custom definitions
- **Dark/light variants**: `{"dark": "#000", "light": "#fff"}`
- **No color**: `"none"` - Uses the terminal's default color or transparent
---
### Color definitions
The `defs` section is optional and it allows you to define reusable colors that can be referenced in the theme.
---
### Terminal defaults
The special value `"none"` can be used for any color to inherit the terminal's default color. This is particularly useful for creating themes that blend seamlessly with your terminal's color scheme:
- `"text": "none"` - Uses terminal's default foreground color
- `"background": "none"` - Uses terminal's default background color
---
### Example
Here's an example of a custom theme:
```json title="my-theme.json"
{
"$schema": "https://opencode.ai/theme.json",
"defs": {
"nord0": "#2E3440",
"nord1": "#3B4252",
"nord2": "#434C5E",
"nord3": "#4C566A",
"nord4": "#D8DEE9",
"nord5": "#E5E9F0",
"nord6": "#ECEFF4",
"nord7": "#8FBCBB",
"nord8": "#88C0D0",
"nord9": "#81A1C1",
"nord10": "#5E81AC",
"nord11": "#BF616A",
"nord12": "#D08770",
"nord13": "#EBCB8B",
"nord14": "#A3BE8C",
"nord15": "#B48EAD"
},
"theme": {
"primary": {
"dark": "nord8",
"light": "nord10"
},
"secondary": {
"dark": "nord9",
"light": "nord9"
},
"accent": {
"dark": "nord7",
"light": "nord7"
},
"error": {
"dark": "nord11",
"light": "nord11"
},
"warning": {
"dark": "nord12",
"light": "nord12"
},
"success": {
"dark": "nord14",
"light": "nord14"
},
"info": {
"dark": "nord8",
"light": "nord10"
},
"text": {
"dark": "nord4",
"light": "nord0"
},
"textMuted": {
"dark": "nord3",
"light": "nord1"
},
"background": {
"dark": "nord0",
"light": "nord6"
},
"backgroundPanel": {
"dark": "nord1",
"light": "nord5"
},
"backgroundElement": {
"dark": "nord1",
"light": "nord4"
},
"border": {
"dark": "nord2",
"light": "nord3"
},
"borderActive": {
"dark": "nord3",
"light": "nord2"
},
"borderSubtle": {
"dark": "nord2",
"light": "nord3"
},
"diffAdded": {
"dark": "nord14",
"light": "nord14"
},
"diffRemoved": {
"dark": "nord11",
"light": "nord11"
},
"diffContext": {
"dark": "nord3",
"light": "nord3"
},
"diffHunkHeader": {
"dark": "nord3",
"light": "nord3"
},
"diffHighlightAdded": {
"dark": "nord14",
"light": "nord14"
},
"diffHighlightRemoved": {
"dark": "nord11",
"light": "nord11"
},
"diffAddedBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"diffRemovedBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"diffContextBg": {
"dark": "nord1",
"light": "nord5"
},
"diffLineNumber": {
"dark": "nord2",
"light": "nord4"
},
"diffAddedLineNumberBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"diffRemovedLineNumberBg": {
"dark": "#3B4252",
"light": "#E5E9F0"
},
"markdownText": {
"dark": "nord4",
"light": "nord0"
},
"markdownHeading": {
"dark": "nord8",
"light": "nord10"
},
"markdownLink": {
"dark": "nord9",
"light": "nord9"
},
"markdownLinkText": {
"dark": "nord7",
"light": "nord7"
},
"markdownCode": {
"dark": "nord14",
"light": "nord14"
},
"markdownBlockQuote": {
"dark": "nord3",
"light": "nord3"
},
"markdownEmph": {
"dark": "nord12",
"light": "nord12"
},
"markdownStrong": {
"dark": "nord13",
"light": "nord13"
},
"markdownHorizontalRule": {
"dark": "nord3",
"light": "nord3"
},
"markdownListItem": {
"dark": "nord8",
"light": "nord10"
},
"markdownListEnumeration": {
"dark": "nord7",
"light": "nord7"
},
"markdownImage": {
"dark": "nord9",
"light": "nord9"
},
"markdownImageText": {
"dark": "nord7",
"light": "nord7"
},
"markdownCodeBlock": {
"dark": "nord4",
"light": "nord0"
},
"syntaxComment": {
"dark": "nord3",
"light": "nord3"
},
"syntaxKeyword": {
"dark": "nord9",
"light": "nord9"
},
"syntaxFunction": {
"dark": "nord8",
"light": "nord8"
},
"syntaxVariable": {
"dark": "nord7",
"light": "nord7"
},
"syntaxString": {
"dark": "nord14",
"light": "nord14"
},
"syntaxNumber": {
"dark": "nord15",
"light": "nord15"
},
"syntaxType": {
"dark": "nord7",
"light": "nord7"
},
"syntaxOperator": {
"dark": "nord9",
"light": "nord9"
},
"syntaxPunctuation": {
"dark": "nord4",
"light": "nord0"
}
}
}
```

View File

@@ -0,0 +1,379 @@
---
title: Tools
description: Manage the tools an LLM can use.
---
Tools allow the LLM to perform actions in your codebase. OpenCode comes with a set of built-in tools, but you can extend it with [custom tools](/docs/custom-tools) or [MCP servers](/docs/mcp-servers).
By default, all tools are **enabled** and don't need permission to run. You can control tool behavior through [permissions](/docs/permissions).
---
## Configure
Use the `permission` field to control tool behavior. You can allow, deny, or require approval for each tool.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "deny",
"bash": "ask",
"webfetch": "allow"
}
}
```
You can also use wildcards to control multiple tools at once. For example, to require approval for all tools from an MCP server:
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"mymcp_*": "ask"
}
}
```
[Learn more](/docs/permissions) about configuring permissions.
---
## Built-in
Here are all the built-in tools available in OpenCode.
---
### bash
Execute shell commands in your project environment.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"bash": "allow"
}
}
```
This tool allows the LLM to run terminal commands like `npm install`, `git status`, or any other shell command.
---
### edit
Modify existing files using exact string replacements.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "allow"
}
}
```
This tool performs precise edits to files by replacing exact text matches. It's the primary way the LLM modifies code.
---
### write
Create new files or overwrite existing ones.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "allow"
}
}
```
Use this to allow the LLM to create new files. It will overwrite existing files if they already exist.
:::note
The `write` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `patch`, `multiedit`).
:::
---
### read
Read file contents from your codebase.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": "allow"
}
}
```
This tool reads files and returns their contents. It supports reading specific line ranges for large files.
---
### grep
Search file contents using regular expressions.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"grep": "allow"
}
}
```
Fast content search across your codebase. Supports full regex syntax and file pattern filtering.
---
### glob
Find files by pattern matching.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"glob": "allow"
}
}
```
Search for files using glob patterns like `**/*.js` or `src/**/*.ts`. Returns matching file paths sorted by modification time.
---
### list
List files and directories in a given path.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"list": "allow"
}
}
```
This tool lists directory contents. It accepts glob patterns to filter results.
---
### lsp (experimental)
Interact with your configured LSP servers to get code intelligence features like definitions, references, hover info, and call hierarchy.
:::note
This tool is only available when `OPENCODE_EXPERIMENTAL_LSP_TOOL=true` (or `OPENCODE_EXPERIMENTAL=true`).
:::
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"lsp": "allow"
}
}
```
Supported operations include `goToDefinition`, `findReferences`, `hover`, `documentSymbol`, `workspaceSymbol`, `goToImplementation`, `prepareCallHierarchy`, `incomingCalls`, and `outgoingCalls`.
To configure which LSP servers are available for your project, see [LSP Servers](/docs/lsp).
---
### patch
Apply patches to files.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"edit": "allow"
}
}
```
This tool applies patch files to your codebase. Useful for applying diffs and patches from various sources.
:::note
The `patch` tool is controlled by the `edit` permission, which covers all file modifications (`edit`, `write`, `patch`, `multiedit`).
:::
---
### skill
Load a [skill](/docs/skills) (a `SKILL.md` file) and return its content in the conversation.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"skill": "allow"
}
}
```
---
### todowrite
Manage todo lists during coding sessions.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"todowrite": "allow"
}
}
```
Creates and updates task lists to track progress during complex operations. The LLM uses this to organize multi-step tasks.
:::note
This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions)
:::
---
### todoread
Read existing todo lists.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"todoread": "allow"
}
}
```
Reads the current todo list state. Used by the LLM to track what tasks are pending or completed.
:::note
This tool is disabled for subagents by default, but you can enable it manually. [Learn more](/docs/agents/#permissions)
:::
---
### webfetch
Fetch web content.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"webfetch": "allow"
}
}
```
Allows the LLM to fetch and read web pages. Useful for looking up documentation or researching online resources.
---
### websearch
Search the web for information.
:::note
This tool is only available when using the OpenCode provider or when the `OPENCODE_ENABLE_EXA` environment variable is set to any truthy value (e.g., `true` or `1`).
To enable when launching OpenCode:
```bash
OPENCODE_ENABLE_EXA=1 opencode
```
:::
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"websearch": "allow"
}
}
```
Performs web searches using Exa AI to find relevant information online. Useful for researching topics, finding current events, or gathering information beyond the training data cutoff.
No API key is required — the tool connects directly to Exa AI's hosted MCP service without authentication.
:::tip
Use `websearch` when you need to find information (discovery), and `webfetch` when you need to retrieve content from a specific URL (retrieval).
:::
---
### question
Ask the user questions during execution.
```json title="opencode.json" {4}
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"question": "allow"
}
}
```
This tool allows the LLM to ask the user questions during a task. It's useful for:
- Gathering user preferences or requirements
- Clarifying ambiguous instructions
- Getting decisions on implementation choices
- Offering choices about what direction to take
Each question includes a header, the question text, and a list of options. Users can select from the provided options or type a custom answer. When there are multiple questions, users can navigate between them before submitting all answers.
---
## Custom tools
Custom tools let you define your own functions that the LLM can call. These are defined in your config file and can execute arbitrary code.
[Learn more](/docs/custom-tools) about creating custom tools.
---
## MCP servers
MCP (Model Context Protocol) servers allow you to integrate external tools and services. This includes database access, API integrations, and third-party services.
[Learn more](/docs/mcp-servers) about configuring MCP servers.
---
## Internals
Internally, tools like `grep`, `glob`, and `list` use [ripgrep](https://github.com/BurntSushi/ripgrep) under the hood. By default, ripgrep respects `.gitignore` patterns, which means files and directories listed in your `.gitignore` will be excluded from searches and listings.
---
### Ignore patterns
To include files that would normally be ignored, create a `.ignore` file in your project root. This file can explicitly allow certain paths.
```text title=".ignore"
!node_modules/
!dist/
!build/
```
For example, this `.ignore` file allows ripgrep to search within `node_modules/`, `dist/`, and `build/` directories even if they're listed in `.gitignore`.

View File

@@ -0,0 +1,300 @@
---
title: Troubleshooting
description: Common issues and how to resolve them.
---
To debug issues with OpenCode, start by checking the logs and local data it stores on disk.
---
## Logs
Log files are written to:
- **macOS/Linux**: `~/.local/share/opencode/log/`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode\log`
Log files are named with timestamps (e.g., `2025-01-09T123456.log`) and the most recent 10 log files are kept.
You can set the log level with the `--log-level` command-line option to get more detailed debug information. For example, `opencode --log-level DEBUG`.
---
## Storage
opencode stores session data and other application data on disk at:
- **macOS/Linux**: `~/.local/share/opencode/`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.local\share\opencode`
This directory contains:
- `auth.json` - Authentication data like API keys, OAuth tokens
- `log/` - Application logs
- `project/` - Project-specific data like session and message data
- If the project is within a Git repo, it is stored in `./<project-slug>/storage/`
- If it is not a Git repo, it is stored in `./global/storage/`
---
## Desktop app
OpenCode Desktop runs a local OpenCode server (the `opencode-cli` sidecar) in the background. Most issues are caused by a misbehaving plugin, a corrupted cache, or a bad server setting.
### Quick checks
- Fully quit and relaunch the app.
- If the app shows an error screen, click **Restart** and copy the error details.
- macOS only: `OpenCode` menu -> **Reload Webview** (helps if the UI is blank/frozen).
---
### Disable plugins
If the desktop app is crashing on launch, hanging, or behaving strangely, start by disabling plugins.
#### Check the global config
Open your global config file and look for a `plugin` key.
- **macOS/Linux**: `~/.config/opencode/opencode.jsonc` (or `~/.config/opencode/opencode.json`)
- **macOS/Linux** (older installs): `~/.local/share/opencode/opencode.jsonc`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\opencode.jsonc`
If you have plugins configured, temporarily disable them by removing the key or setting it to an empty array:
```jsonc
{
"$schema": "https://opencode.ai/config.json",
"plugin": [],
}
```
#### Check plugin directories
OpenCode can also load local plugins from disk. Temporarily move these out of the way (or rename the folder) and restart the desktop app:
- **Global plugins**
- **macOS/Linux**: `~/.config/opencode/plugins/`
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.config\opencode\plugins`
- **Project plugins** (only if you use per-project config)
- `<your-project>/.opencode/plugins/`
If the app starts working again, re-enable plugins one at a time to find which one is causing the issue.
---
### Clear the cache
If disabling plugins doesn't help (or a plugin install is stuck), clear the cache so OpenCode can rebuild it.
1. Quit OpenCode Desktop completely.
2. Delete the cache directory:
- **macOS**: Finder -> `Cmd+Shift+G` -> paste `~/.cache/opencode`
- **Linux**: delete `~/.cache/opencode` (or run `rm -rf ~/.cache/opencode`)
- **Windows**: Press `WIN+R` and paste `%USERPROFILE%\.cache\opencode`
3. Restart OpenCode Desktop.
---
### Fix server connection issues
OpenCode Desktop can either start its own local server (default) or connect to a server URL you configured.
If you see a **"Connection Failed"** dialog (or the app never gets past the splash screen), check for a custom server URL.
#### Clear the desktop default server URL
From the Home screen, click the server name (with the status dot) to open the Server picker. In the **Default server** section, click **Clear**.
#### Remove `server.port` / `server.hostname` from your config
If your `opencode.json(c)` contains a `server` section, temporarily remove it and restart the desktop app.
#### Check environment variables
If you have `OPENCODE_PORT` set in your environment, the desktop app will try to use that port for the local server.
- Unset `OPENCODE_PORT` (or pick a free port) and restart.
---
### Linux: Wayland / X11 issues
On Linux, some Wayland setups can cause blank windows or compositor errors.
- If you're on Wayland and the app is blank/crashing, try launching with `OC_ALLOW_WAYLAND=1`.
- If that makes things worse, remove it and try launching under an X11 session instead.
---
### Windows: WebView2 runtime
On Windows, OpenCode Desktop requires the Microsoft Edge **WebView2 Runtime**. If the app opens to a blank window or won't start, install/update WebView2 and try again.
---
### Windows: General performance issues
If you're experiencing slow performance, file access issues, or terminal problems on Windows, try using [WSL (Windows Subsystem for Linux)](/docs/windows-wsl). WSL provides a Linux environment that works more seamlessly with OpenCode's features.
---
### Notifications not showing
OpenCode Desktop only shows system notifications when:
- notifications are enabled for OpenCode in your OS settings, and
- the app window is not focused.
---
### Reset desktop app storage (last resort)
If the app won't start and you can't clear settings from inside the UI, reset the desktop app's saved state.
1. Quit OpenCode Desktop.
2. Find and delete these files (they live in the OpenCode Desktop app data directory):
- `opencode.settings.dat` (desktop default server URL)
- `opencode.global.dat` and `opencode.workspace.*.dat` (UI state like recent servers/projects)
To find the directory quickly:
- **macOS**: Finder -> `Cmd+Shift+G` -> `~/Library/Application Support` (then search for the filenames above)
- **Linux**: search under `~/.local/share` for the filenames above
- **Windows**: Press `WIN+R` -> `%APPDATA%` (then search for the filenames above)
---
## Getting help
If you're experiencing issues with OpenCode:
1. **Report issues on GitHub**
The best way to report bugs or request features is through our GitHub repository:
[**github.com/anomalyco/opencode/issues**](https://github.com/anomalyco/opencode/issues)
Before creating a new issue, search existing issues to see if your problem has already been reported.
2. **Join our Discord**
For real-time help and community discussion, join our Discord server:
[**opencode.ai/discord**](https://opencode.ai/discord)
---
## Common issues
Here are some common issues and how to resolve them.
---
### OpenCode won't start
1. Check the logs for error messages
2. Try running with `--print-logs` to see output in the terminal
3. Ensure you have the latest version with `opencode upgrade`
---
### Authentication issues
1. Try re-authenticating with the `/connect` command in the TUI
2. Check that your API keys are valid
3. Ensure your network allows connections to the provider's API
---
### Model not available
1. Check that you've authenticated with the provider
2. Verify the model name in your config is correct
3. Some models may require specific access or subscriptions
If you encounter `ProviderModelNotFoundError` you are most likely incorrectly
referencing a model somewhere.
Models should be referenced like so: `<providerId>/<modelId>`
Examples:
- `openai/gpt-4.1`
- `openrouter/google/gemini-2.5-flash`
- `opencode/kimi-k2`
To figure out what models you have access to, run `opencode models`
---
### ProviderInitError
If you encounter a ProviderInitError, you likely have an invalid or corrupted configuration.
To resolve this:
1. First, verify your provider is set up correctly by following the [providers guide](/docs/providers)
2. If the issue persists, try clearing your stored configuration:
```bash
rm -rf ~/.local/share/opencode
```
On Windows, press `WIN+R` and delete: `%USERPROFILE%\.local\share\opencode`
3. Re-authenticate with your provider using the `/connect` command in the TUI.
---
### AI_APICallError and provider package issues
If you encounter API call errors, this may be due to outdated provider packages. opencode dynamically installs provider packages (OpenAI, Anthropic, Google, etc.) as needed and caches them locally.
To resolve provider package issues:
1. Clear the provider package cache:
```bash
rm -rf ~/.cache/opencode
```
On Windows, press `WIN+R` and delete: `%USERPROFILE%\.cache\opencode`
2. Restart opencode to reinstall the latest provider packages
This will force opencode to download the most recent versions of provider packages, which often resolves compatibility issues with model parameters and API changes.
---
### Copy/paste not working on Linux
Linux users need to have one of the following clipboard utilities installed for copy/paste functionality to work:
**For X11 systems:**
```bash
apt install -y xclip
# or
apt install -y xsel
```
**For Wayland systems:**
```bash
apt install -y wl-clipboard
```
**For headless environments:**
```bash
apt install -y xvfb
# and run:
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
export DISPLAY=:99.0
```
opencode will detect if you're using Wayland and prefer `wl-clipboard`, otherwise it will try to find clipboard tools in order of: `xclip` and `xsel`.

View File

@@ -0,0 +1,390 @@
---
title: TUI
description: Using the OpenCode terminal user interface.
---
import { Tabs, TabItem } from "@astrojs/starlight/components"
OpenCode provides an interactive terminal interface or TUI for working on your projects with an LLM.
Running OpenCode starts the TUI for the current directory.
```bash
opencode
```
Or you can start it for a specific working directory.
```bash
opencode /path/to/project
```
Once you're in the TUI, you can prompt it with a message.
```text
Give me a quick summary of the codebase.
```
---
## File references
You can reference files in your messages using `@`. This does a fuzzy file search in the current working directory.
:::tip
You can also use `@` to reference files in your messages.
:::
```text "@packages/functions/src/api/index.ts"
How is auth handled in @packages/functions/src/api/index.ts?
```
The content of the file is added to the conversation automatically.
---
## Bash commands
Start a message with `!` to run a shell command.
```bash frame="none"
!ls -la
```
The output of the command is added to the conversation as a tool result.
---
## Commands
When using the OpenCode TUI, you can type `/` followed by a command name to quickly execute actions. For example:
```bash frame="none"
/help
```
Most commands also have keybind using `ctrl+x` as the leader key, where `ctrl+x` is the default leader key. [Learn more](/docs/keybinds).
Here are all available slash commands:
---
### connect
Add a provider to OpenCode. Allows you to select from available providers and add their API keys.
```bash frame="none"
/connect
```
---
### compact
Compact the current session. _Alias_: `/summarize`
```bash frame="none"
/compact
```
**Keybind:** `ctrl+x c`
---
### details
Toggle tool execution details.
```bash frame="none"
/details
```
**Keybind:** `ctrl+x d`
---
### editor
Open external editor for composing messages. Uses the editor set in your `EDITOR` environment variable. [Learn more](#editor-setup).
```bash frame="none"
/editor
```
**Keybind:** `ctrl+x e`
---
### exit
Exit OpenCode. _Aliases_: `/quit`, `/q`
```bash frame="none"
/exit
```
**Keybind:** `ctrl+x q`
---
### export
Export current conversation to Markdown and open in your default editor. Uses the editor set in your `EDITOR` environment variable. [Learn more](#editor-setup).
```bash frame="none"
/export
```
**Keybind:** `ctrl+x x`
---
### help
Show the help dialog.
```bash frame="none"
/help
```
**Keybind:** `ctrl+x h`
---
### init
Create or update `AGENTS.md` file. [Learn more](/docs/rules).
```bash frame="none"
/init
```
**Keybind:** `ctrl+x i`
---
### models
List available models.
```bash frame="none"
/models
```
**Keybind:** `ctrl+x m`
---
### new
Start a new session. _Alias_: `/clear`
```bash frame="none"
/new
```
**Keybind:** `ctrl+x n`
---
### redo
Redo a previously undone message. Only available after using `/undo`.
:::tip
Any file changes will also be restored.
:::
Internally, this uses Git to manage the file changes. So your project **needs to
be a Git repository**.
```bash frame="none"
/redo
```
**Keybind:** `ctrl+x r`
---
### sessions
List and switch between sessions. _Aliases_: `/resume`, `/continue`
```bash frame="none"
/sessions
```
**Keybind:** `ctrl+x l`
---
### share
Share current session. [Learn more](/docs/share).
```bash frame="none"
/share
```
**Keybind:** `ctrl+x s`
---
### themes
List available themes.
```bash frame="none"
/theme
```
**Keybind:** `ctrl+x t`
---
### thinking
Toggle the visibility of thinking/reasoning blocks in the conversation. When enabled, you can see the model's reasoning process for models that support extended thinking.
:::note
This command only controls whether thinking blocks are **displayed** - it does not enable or disable the model's reasoning capabilities. To toggle actual reasoning capabilities, use `ctrl+t` to cycle through model variants.
:::
```bash frame="none"
/thinking
```
---
### undo
Undo last message in the conversation. Removes the most recent user message, all subsequent responses, and any file changes.
:::tip
Any file changes made will also be reverted.
:::
Internally, this uses Git to manage the file changes. So your project **needs to
be a Git repository**.
```bash frame="none"
/undo
```
**Keybind:** `ctrl+x u`
---
### unshare
Unshare current session. [Learn more](/docs/share#un-sharing).
```bash frame="none"
/unshare
```
---
## Editor setup
Both the `/editor` and `/export` commands use the editor specified in your `EDITOR` environment variable.
<Tabs>
<TabItem label="Linux/macOS">
```bash
# Example for nano or vim
export EDITOR=nano
export EDITOR=vim
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
export EDITOR="code --wait"
```
To make it permanent, add this to your shell profile;
`~/.bashrc`, `~/.zshrc`, etc.
</TabItem>
<TabItem label="Windows (CMD)">
```bash
set EDITOR=notepad
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
set EDITOR=code --wait
```
To make it permanent, use **System Properties** > **Environment
Variables**.
</TabItem>
<TabItem label="Windows (PowerShell)">
```powershell
$env:EDITOR = "notepad"
# For GUI editors, VS Code, Cursor, VSCodium, Windsurf, Zed, etc.
# include --wait
$env:EDITOR = "code --wait"
```
To make it permanent, add this to your PowerShell profile.
</TabItem>
</Tabs>
Popular editor options include:
- `code` - Visual Studio Code
- `cursor` - Cursor
- `windsurf` - Windsurf
- `nvim` - Neovim editor
- `vim` - Vim editor
- `nano` - Nano editor
- `notepad` - Windows Notepad
- `subl` - Sublime Text
:::note
Some editors like VS Code need to be started with the `--wait` flag.
:::
Some editors need command-line arguments to run in blocking mode. The `--wait` flag makes the editor process block until closed.
---
## Configure
You can customize TUI behavior through your OpenCode config file.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
"tui": {
"scroll_speed": 3,
"scroll_acceleration": {
"enabled": true
}
}
}
```
### Options
- `scroll_acceleration` - Enable macOS-style scroll acceleration for smooth, natural scrolling. When enabled, scroll speed increases with rapid scrolling gestures and stays precise for slower movements. **This setting takes precedence over `scroll_speed` and overrides it when enabled.**
- `scroll_speed` - Controls how fast the TUI scrolls when using scroll commands (minimum: `1`). Defaults to `3`. **Note: This is ignored if `scroll_acceleration.enabled` is set to `true`.**
---
## Customization
You can customize various aspects of the TUI view using the command palette (`ctrl+x h` or `/help`). These settings persist across restarts.
---
#### Username display
Toggle whether your username appears in chat messages. Access this through:
- Command palette: Search for "username" or "hide username"
- The setting persists automatically and will be remembered across TUI sessions

View File

@@ -0,0 +1,142 @@
---
title: Web
description: Using OpenCode in your browser.
---
OpenCode can run as a web application in your browser, providing the same powerful AI coding experience without needing a terminal.
![OpenCode Web - New Session](../../assets/web/web-homepage-new-session.png)
## Getting Started
Start the web interface by running:
```bash
opencode web
```
This starts a local server on `127.0.0.1` with a random available port and automatically opens OpenCode in your default browser.
:::caution
If `OPENCODE_SERVER_PASSWORD` is not set, the server will be unsecured. This is fine for local use but should be set for network access.
:::
:::tip[Windows Users]
For the best experience, run `opencode web` from [WSL](/docs/windows-wsl) rather than PowerShell. This ensures proper file system access and terminal integration.
:::
---
## Configuration
You can configure the web server using command line flags or in your [config file](/docs/config).
### Port
By default, OpenCode picks an available port. You can specify a port:
```bash
opencode web --port 4096
```
### Hostname
By default, the server binds to `127.0.0.1` (localhost only). To make OpenCode accessible on your network:
```bash
opencode web --hostname 0.0.0.0
```
When using `0.0.0.0`, OpenCode will display both local and network addresses:
```
Local access: http://localhost:4096
Network access: http://192.168.1.100:4096
```
### mDNS Discovery
Enable mDNS to make your server discoverable on the local network:
```bash
opencode web --mdns
```
This automatically sets the hostname to `0.0.0.0` and advertises the server as `opencode.local`.
You can customize the mDNS domain name to run multiple instances on the same network:
```bash
opencode web --mdns --mdns-domain myproject.local
```
### CORS
To allow additional domains for CORS (useful for custom frontends):
```bash
opencode web --cors https://example.com
```
### Authentication
To protect access, set a password using the `OPENCODE_SERVER_PASSWORD` environment variable:
```bash
OPENCODE_SERVER_PASSWORD=secret opencode web
```
The username defaults to `opencode` but can be changed with `OPENCODE_SERVER_USERNAME`.
---
## Using the Web Interface
Once started, the web interface provides access to your OpenCode sessions.
### Sessions
View and manage your sessions from the homepage. You can see active sessions and start new ones.
![OpenCode Web - Active Session](../../assets/web/web-homepage-active-session.png)
### Server Status
Click "See Servers" to view connected servers and their status.
![OpenCode Web - See Servers](../../assets/web/web-homepage-see-servers.png)
---
## Attaching a Terminal
You can attach a terminal TUI to a running web server:
```bash
# Start the web server
opencode web --port 4096
# In another terminal, attach the TUI
opencode attach http://localhost:4096
```
This allows you to use both the web interface and terminal simultaneously, sharing the same sessions and state.
---
## Config File
You can also configure server settings in your `opencode.json` config file:
```json
{
"server": {
"port": 4096,
"hostname": "0.0.0.0",
"mdns": true,
"cors": ["https://example.com"]
}
}
```
Command line flags take precedence over config file settings.

View File

@@ -0,0 +1,112 @@
---
title: Windows (WSL)
description: Run OpenCode on Windows using WSL for the best experience.
---
import { Steps } from "@astrojs/starlight/components"
While OpenCode can run directly on Windows, we recommend using [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/install) for the best experience. WSL provides a Linux environment that works seamlessly with OpenCode's features.
:::tip[Why WSL?]
WSL offers better file system performance, full terminal support, and compatibility with development tools that OpenCode relies on.
:::
---
## Setup
<Steps>
1. **Install WSL**
If you haven't already, [install WSL](https://learn.microsoft.com/en-us/windows/wsl/install) using the official Microsoft guide.
2. **Install OpenCode in WSL**
Once WSL is set up, open your WSL terminal and install OpenCode using one of the [installation methods](/docs/).
```bash
curl -fsSL https://opencode.ai/install | bash
```
3. **Use OpenCode from WSL**
Navigate to your project directory (access Windows files via `/mnt/c/`, `/mnt/d/`, etc.) and run OpenCode.
```bash
cd /mnt/c/Users/YourName/project
opencode
```
</Steps>
---
## Desktop App + WSL Server
If you prefer using the OpenCode Desktop app but want to run the server in WSL:
1. **Start the server in WSL** with `--hostname 0.0.0.0` to allow external connections:
```bash
opencode serve --hostname 0.0.0.0 --port 4096
```
2. **Connect the Desktop app** to `http://localhost:4096`
:::note
If `localhost` does not work in your setup, connect using the WSL IP address instead (from WSL: `hostname -I`) and use `http://<wsl-ip>:4096`.
:::
:::caution
When using `--hostname 0.0.0.0`, set `OPENCODE_SERVER_PASSWORD` to secure the server.
:::
```bash
OPENCODE_SERVER_PASSWORD=your-password opencode serve --hostname 0.0.0.0
```
---
## Web Client + WSL
For the best web experience on Windows:
1. **Run `opencode web` in the WSL terminal** rather than PowerShell:
```bash
opencode web --hostname 0.0.0.0
```
2. **Access from your Windows browser** at `http://localhost:<port>` (OpenCode prints the URL)
Running `opencode web` from WSL ensures proper file system access and terminal integration while still being accessible from your Windows browser.
---
## Accessing Windows Files
WSL can access all your Windows files through the `/mnt/` directory:
- `C:` drive → `/mnt/c/`
- `D:` drive → `/mnt/d/`
- And so on...
Example:
```bash
cd /mnt/c/Users/YourName/Documents/project
opencode
```
:::tip
For the smoothest experience, consider cloning/copying your repo into the WSL filesystem (for example under `~/code/`) and running OpenCode there.
:::
---
## Tips
- Keep OpenCode running in WSL for projects stored on Windows drives - file access is seamless
- Use VS Code's [WSL extension](https://code.visualstudio.com/docs/remote/wsl) alongside OpenCode for an integrated development workflow
- Your OpenCode config and sessions are stored within the WSL environment at `~/.local/share/opencode/`

View File

@@ -0,0 +1,254 @@
---
title: Zen
description: Curated list of models provided by OpenCode.
---
import config from "../../../config.mjs"
export const console = config.console
export const email = `mailto:${config.email}`
OpenCode Zen is a list of tested and verified models provided by the OpenCode team.
:::note
OpenCode Zen is currently in beta.
:::
Zen works like any other provider in OpenCode. You login to OpenCode Zen and get
your API key. It's **completely optional** and you don't need to use it to use
OpenCode.
---
## Background
There are a large number of models out there but only a few of
these models work well as coding agents. Additionally, most providers are
configured very differently; so you get very different performance and quality.
:::tip
We tested a select group of models and providers that work well with OpenCode.
:::
So if you are using a model through something like OpenRouter, you can never be
sure if you are getting the best version of the model you want.
To fix this, we did a couple of things:
1. We tested a select group of models and talked to their teams about how to
best run them.
2. We then worked with a few providers to make sure these were being served
correctly.
3. Finally, we benchmarked the combination of the model/provider and came up
with a list that we feel good recommending.
OpenCode Zen is an AI gateway that gives you access to these models.
---
## How it works
OpenCode Zen works like any other provider in OpenCode.
1. You sign in to **<a href={console}>OpenCode Zen</a>**, add your billing
details, and copy your API key.
2. You run the `/connect` command in the TUI, select OpenCode Zen, and paste your API key.
3. Run `/models` in the TUI to see the list of models we recommend.
You are charged per request and you can add credits to your account.
---
## Endpoints
You can also access our models through the following API endpoints.
| Model | Model ID | Endpoint | AI SDK Package |
| ------------------ | ------------------ | -------------------------------------------------- | --------------------------- |
| GPT 5.2 | gpt-5.2 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.2 Codex | gpt-5.2-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 | gpt-5.1 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex | gpt-5.1-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex Max | gpt-5.1-codex-max | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5.1 Codex Mini | gpt-5.1-codex-mini | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 | gpt-5 | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 Codex | gpt-5-codex | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| GPT 5 Nano | gpt-5-nano | `https://opencode.ai/zen/v1/responses` | `@ai-sdk/openai` |
| Claude Sonnet 4.5 | claude-sonnet-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Sonnet 4 | claude-sonnet-4 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Haiku 4.5 | claude-haiku-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Haiku 3.5 | claude-3-5-haiku | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.6 | claude-opus-4-6 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.5 | claude-opus-4-5 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Claude Opus 4.1 | claude-opus-4-1 | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| Gemini 3 Pro | gemini-3-pro | `https://opencode.ai/zen/v1/models/gemini-3-pro` | `@ai-sdk/google` |
| Gemini 3 Flash | gemini-3-flash | `https://opencode.ai/zen/v1/models/gemini-3-flash` | `@ai-sdk/google` |
| MiniMax M2.1 | minimax-m2.1 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| MiniMax M2.1 Free | minimax-m2.1-free | `https://opencode.ai/zen/v1/messages` | `@ai-sdk/anthropic` |
| GLM 4.7 | glm-4.7 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| GLM 4.7 Free | glm-4.7-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| GLM 4.6 | glm-4.6 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2.5 | kimi-k2.5 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2.5 Free | kimi-k2.5-free | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2 Thinking | kimi-k2-thinking | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Kimi K2 | kimi-k2 | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Qwen3 Coder 480B | qwen3-coder | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
| Big Pickle | big-pickle | `https://opencode.ai/zen/v1/chat/completions` | `@ai-sdk/openai-compatible` |
The [model id](/docs/config/#models) in your OpenCode config
uses the format `opencode/<model-id>`. For example, for GPT 5.2 Codex, you would
use `opencode/gpt-5.2-codex` in your config.
---
### Models
You can fetch the full list of available models and their metadata from:
```
https://opencode.ai/zen/v1/models
```
---
## Pricing
We support a pay-as-you-go model. Below are the prices **per 1M tokens**.
| Model | Input | Output | Cached Read | Cached Write |
| --------------------------------- | ------ | ------ | ----------- | ------------ |
| Big Pickle | Free | Free | Free | - |
| MiniMax M2.1 Free | Free | Free | Free | - |
| MiniMax M2.1 | $0.30 | $1.20 | $0.10 | - |
| GLM 4.7 Free | Free | Free | Free | - |
| GLM 4.7 | $0.60 | $2.20 | $0.10 | - |
| GLM 4.6 | $0.60 | $2.20 | $0.10 | - |
| Kimi K2.5 Free | Free | Free | Free | - |
| Kimi K2.5 | $0.60 | $3.00 | $0.08 | - |
| Kimi K2 Thinking | $0.40 | $2.50 | - | - |
| Kimi K2 | $0.40 | $2.50 | - | - |
| Qwen3 Coder 480B | $0.45 | $1.50 | - | - |
| Claude Sonnet 4.5 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 |
| Claude Sonnet 4.5 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 |
| Claude Sonnet 4 (≤ 200K tokens) | $3.00 | $15.00 | $0.30 | $3.75 |
| Claude Sonnet 4 (> 200K tokens) | $6.00 | $22.50 | $0.60 | $7.50 |
| Claude Haiku 4.5 | $1.00 | $5.00 | $0.10 | $1.25 |
| Claude Haiku 3.5 | $0.80 | $4.00 | $0.08 | $1.00 |
| Claude Opus 4.6 (≤ 200K tokens) | $5.00 | $25.00 | $0.50 | $6.25 |
| Claude Opus 4.6 (> 200K tokens) | $10.00 | $37.50 | $1.00 | $12.50 |
| Claude Opus 4.5 | $5.00 | $25.00 | $0.50 | $6.25 |
| Claude Opus 4.1 | $15.00 | $75.00 | $1.50 | $18.75 |
| Gemini 3 Pro (≤ 200K tokens) | $2.00 | $12.00 | $0.20 | - |
| Gemini 3 Pro (> 200K tokens) | $4.00 | $18.00 | $0.40 | - |
| Gemini 3 Flash | $0.50 | $3.00 | $0.05 | - |
| GPT 5.2 | $1.75 | $14.00 | $0.175 | - |
| GPT 5.2 Codex | $1.75 | $14.00 | $0.175 | - |
| GPT 5.1 | $1.07 | $8.50 | $0.107 | - |
| GPT 5.1 Codex | $1.07 | $8.50 | $0.107 | - |
| GPT 5.1 Codex Max | $1.25 | $10.00 | $0.125 | - |
| GPT 5.1 Codex Mini | $0.25 | $2.00 | $0.025 | - |
| GPT 5 | $1.07 | $8.50 | $0.107 | - |
| GPT 5 Codex | $1.07 | $8.50 | $0.107 | - |
| GPT 5 Nano | Free | Free | Free | - |
You might notice _Claude Haiku 3.5_ in your usage history. This is a [low cost model](/docs/config/#models) that's used to generate the titles of your sessions.
:::note
Credit card fees are passed along at cost (4.4% + $0.30 per transaction); we don't charge anything beyond that.
:::
The free models:
- GLM 4.7 Free is available on OpenCode for a limited time. The team is using this time to collect feedback and improve the model.
- Kimi K2.5 Free is available on OpenCode for a limited time. The team is using this time to collect feedback and improve the model.
- MiniMax M2.1 Free is available on OpenCode for a limited time. The team is using this time to collect feedback and improve the model.
- Big Pickle is a stealth model that's free on OpenCode for a limited time. The team is using this time to collect feedback and improve the model.
<a href={email}>Contact us</a> if you have any questions.
---
### Auto-reload
If your balance goes below $5, Zen will automatically reload $20.
You can change the auto-reload amount. You can also disable auto-reload entirely.
---
### Monthly limits
You can also set a monthly usage limit for the entire workspace and for each
member of your team.
For example, let's say you set a monthly usage limit to $20, Zen will not use
more than $20 in a month. But if you have auto-reload enabled, Zen might end up
charging you more than $20 if your balance goes below $5.
---
## Privacy
All our models are hosted in the US. Our providers follow a zero-retention policy and do not use your data for model training, with the following exceptions:
- Big Pickle: During its free period, collected data may be used to improve the model.
- GLM 4.7 Free: During its free period, collected data may be used to improve the model.
- Kimi K2.5 Free: During its free period, collected data may be used to improve the model.
- MiniMax M2.1 Free: During its free period, collected data may be used to improve the model.
- OpenAI APIs: Requests are retained for 30 days in accordance with [OpenAI's Data Policies](https://platform.openai.com/docs/guides/your-data).
- Anthropic APIs: Requests are retained for 30 days in accordance with [Anthropic's Data Policies](https://docs.anthropic.com/en/docs/claude-code/data-usage).
---
## For Teams
Zen also works great for teams. You can invite teammates, assign roles, curate
the models your team uses, and more.
:::note
Workspaces are currently free for teams as a part of the beta.
:::
Managing your workspace is currently free for teams as a part of the beta. We'll be
sharing more details on the pricing soon.
---
### Roles
You can invite teammates to your workspace and assign roles:
- **Admin**: Manage models, members, API keys, and billing
- **Member**: Manage only their own API keys
Admins can also set monthly spending limits for each member to keep costs under control.
---
### Model access
Admins can enable or disable specific models for the workspace. Requests made to a disabled model will return an error.
This is useful for cases where you want to disable the use of a model that
collects data.
---
### Bring your own key
You can use your own OpenAI or Anthropic API keys while still accessing other models in Zen.
When you use your own keys, tokens are billed directly by the provider, not by Zen.
For example, your organization might already have a key for OpenAI or Anthropic
and you want to use that instead of the one that Zen provides.
---
## Goals
We created OpenCode Zen to:
1. **Benchmark** the best models/providers for coding agents.
2. Have access to the **highest quality** options and not downgrade performance or route to cheaper providers.
3. Pass along any **price drops** by selling at cost; so the only markup is to cover our processing fees.
4. Have **no lock-in** by allowing you to use it with any other coding agent. And always let you use any other provider with OpenCode as well.