opencode is an AI coding agent that runs in your terminal. You point it at a project, type what you want in plain language, and it reads your code, edits files, runs commands, and works alongside you — all from a fast, keyboard-driven terminal interface (TUI). It is provider-agnostic: you bring your own model (Anthropic, OpenAI, Google, GitHub Copilot, OpenRouter, local models, and more) or use the hosted opencode Zen gateway.
This guide covers everything you need to install opencode, drive it from the terminal, connect a model, work across sessions, extend it with agents, custom commands, MCP servers, and plugins, automate it in CI with the GitHub agent, and troubleshoot the things that commonly go wrong.
Note
opencode is the CLI/TUI documented here. It is part of a larger ecosystem that also includes a desktop app, an editor extension, an SDK, and a hosted console. Those companion products are described in the Admin Guide. This guide is for the person sitting at a terminal getting work done.
1. Quick Start
Get from zero to your first AI-assisted change in about two minutes.
macOS / Linux (curl)
curl -fsSL https://opencode.ai/install | bash
npm
npm install -g opencode-ai
Homebrew (macOS)
brew install opencode
Windows (Scoop)
scoop install opencode
Once installed, open a terminal in a project you want to work on and start opencode:
cd ~/code/my-project
opencode
The first time you run it, you will need to connect a model provider. Run the login flow and pick a provider:
opencode auth login
┌ Add credential
│
◆ Select provider
│ ● opencode recommended
│ ○ Anthropic
│ ○ OpenAI ChatGPT Plus/Pro or API key
│ ○ Google
│ ○ OpenRouter
└
Pick a provider, follow the prompts (OAuth in your browser, or paste an API key), and you are ready. Back in the TUI, type a request and press Enter:
> Add a --verbose flag to the CLI that prints the resolved config path
opencode reads the relevant files, proposes edits, asks permission before running anything risky, and shows you a live stream of what it is doing.
Tip
Not sure what model you have access to? Run
opencode modelsto list every model from every provider you have authenticated. Switch models inside the TUI any time with the<leader> mkeybind (the leader key isCtrl+xby default).
2. Installation
2.1 Requirements
| Requirement | Detail |
|---|---|
| Operating system | macOS, Linux, or Windows |
| Terminal | A modern terminal emulator with 256-color and mouse support |
| Model access | An account or API key with at least one supported provider (or opencode Zen) |
| Git (recommended) | Project-scoped config, agents, and the GitHub agent assume a git repository |
sqlite3 (optional) |
Only needed if you want to open an interactive DB shell with opencode db |
opencode ships as a self-contained binary built on the Bun runtime — you do not need to install Node.js or Bun separately for the curl/Homebrew/Scoop installs. The npm/pnpm/bun/yarn packages install the opencode-ai package globally.
2.2 Installation methods
opencode tracks how it was installed so that opencode upgrade and opencode uninstall use the matching mechanism. Supported methods:
curl (script)
curl -fsSL https://opencode.ai/install | bash
Installs a standalone binary into ~/.opencode/bin and adds it to your shell PATH.
npm / pnpm / bun / yarn
npm install -g opencode-ai
# or
pnpm add -g opencode-ai
# or
bun add -g opencode-ai
# or
yarn global add opencode-ai
Homebrew
brew install opencode
Chocolatey / Scoop (Windows)
choco install opencode
# or
scoop install opencode
2.3 Verify the install
opencode --version
1.16.0
opencode --help
The help banner lists every available command. If opencode is not found after a curl install, restart your shell or ensure ~/.opencode/bin is on your PATH.
Important
On native Windows, opencode falls back to Git Bash utilities (such as
less) for some features. If you have Git for Windows installed, opencode discovers it automatically. You can point opencode at a specific Git Bash with theOPENCODE_GIT_BASH_PATHenvironment variable.
2.4 Upgrading
opencode upgrade
┌ Upgrade
│ Using method: curl
│ From 1.16.0 → 1.16.1
◇ Upgrade complete
└ Done
Upgrade to a specific version, or force a particular install method:
opencode upgrade 1.16.1
opencode upgrade --method npm
If the detected method is unknown (for example, opencode lives somewhere managed by a package manager opencode cannot detect), it asks before proceeding.
Note
opencode checks for updates automatically. To turn this off, set the environment variable
OPENCODE_DISABLE_AUTOUPDATE=true. To always be notified about available updates, setOPENCODE_ALWAYS_NOTIFY_UPDATE=true.
2.5 Uninstalling
opencode uninstall
This removes opencode's data, cache, config, and state directories, cleans the PATH entry from your shell config (for curl installs), and runs the matching package-manager uninstall when applicable. Preview without deleting anything:
opencode uninstall --dry-run
Keep your config and/or session data while removing the binary:
opencode uninstall --keep-config --keep-data
| Flag | Alias | Effect |
|---|---|---|
--keep-config |
-c |
Preserve configuration files |
--keep-data |
-d |
Preserve session data and snapshots |
--dry-run |
Show what would be removed without removing | |
--force |
-f |
Skip the confirmation prompt |
3. Connecting a Model Provider
opencode never ships its own model. Before it can do anything useful you must connect at least one provider. Credentials are stored locally in auth.json inside opencode's data directory.
3.1 Logging in
opencode auth login
auth is an alias for the providers command, so opencode providers login is identical. The interactive flow lets you pick a provider and then either run an OAuth flow (browser-based) or paste an API key, depending on what the provider supports.
Skip the interactive selection by passing the provider and/or method directly:
opencode auth login --provider anthropic
opencode auth login --provider openai --method "API Key"
Tip
Several providers print extra setup hints during login:
- opencode (Zen): create a key at
https://opencode.ai/auth- OpenAI: works with a ChatGPT Plus/Pro subscription or an API key
- Vercel AI Gateway: create a token at
https://vercel.link/ai-gateway-token- Amazon Bedrock: uses a bearer token or the standard AWS credential chain (
AWS_PROFILE,AWS_REGION, IAM roles, EKS IRSA)- Cloudflare AI Gateway: configure
CLOUDFLARE_GATEWAY_ID,CLOUDFLARE_ACCOUNT_ID,CLOUDFLARE_API_TOKEN
3.2 Provider login methods
| Provider | Typical auth | Notes |
|---|---|---|
opencode |
API key | The hosted Zen gateway — one key, many models. Recommended for getting started. |
anthropic |
OAuth or API key | Claude models |
openai |
OAuth (ChatGPT) or API key | GPT models |
google |
API key | Gemini models |
github-copilot |
OAuth | Use your Copilot subscription |
openrouter |
API key | Aggregator across many models |
vercel |
API key | Vercel AI Gateway |
amazon-bedrock |
Bearer token / AWS chain | See note above |
snowflake-cortex |
Account + PAT | Prompts for account identifier and a programmatic access token |
| Any other | API key | Choose Other, enter a provider id, then configure it in opencode.json |
You can also authenticate against a self-hosted auth provider that exposes a /.well-known/opencode endpoint:
opencode auth login https://auth.example.com
opencode reads the well-known document, runs its auth.command, and stores the resulting token under the provider key.
3.3 Listing and removing credentials
opencode auth list
┌ Credentials ~/.local/share/opencode/auth.json
│ Anthropic oauth
│ OpenAI api
└ 2 credentials
┌ Environment
│ Anthropic ANTHROPIC_API_KEY
└ 1 environment variable
The command shows both stored credentials and any provider environment variables it detects active in your shell. Remove a stored credential interactively:
opencode auth logout
Note
Provider API keys set via environment variables (for example
ANTHROPIC_API_KEY,OPENAI_API_KEY) are picked up automatically — you do not have to runauth loginif the key is already in your environment.
3.4 Browsing available models
opencode models
opencode/claude-sonnet-4-6
opencode/gpt-5.5
anthropic/claude-opus-4-8
openai/gpt-5.5
google/gemini-3-pro
Filter by provider, see full metadata (including costs), or refresh the catalog from models.dev:
opencode models anthropic
opencode models --verbose
opencode models --refresh
The model catalog is sourced from models.dev. opencode-prefixed providers are listed first.
4. The Terminal Interface (TUI)
Running opencode with no arguments opens the interactive TUI in your current directory. This is the primary way to use opencode.
4.1 Anatomy of a session
The TUI shows your conversation with the agent in the main pane and an input prompt at the bottom. As the agent works, it streams its actions inline: each tool it uses (reading a file, editing, running a shell command, searching) appears as a labeled event, and the agent's prose responses render as Markdown.
You type a request, press Enter, and the agent goes to work. You can keep typing follow-ups, interrupt it, switch models or agents, review diffs, and manage sessions — all without leaving the keyboard.
4.2 The leader key
Many shortcuts are triggered through a leader key — a prefix you press, release, then follow with another key. The default leader is Ctrl+x. For example, <leader> m means: press Ctrl+x, release, then press m to open the model list.
There is a short timeout (2 seconds by default) to complete a leader sequence. You can change the leader key and timeout in your TUI config (see §11).
Tip
Press the which-key panel shortcut (
Ctrl+Alt+k) to see available leader bindings as you type them. opencode shows you what each pending key does.
4.3 Essential keybindings
These are the default bindings you will use most. All are configurable.
Session & conversation
| Action | Default key | Description |
|---|---|---|
| New session | <leader> n |
Start a fresh conversation |
| List sessions | <leader> l |
Browse and switch sessions |
| Session timeline | <leader> g |
View the session's history timeline |
| Rename session | Ctrl+r |
Rename the current session |
| Compact session | <leader> c |
Summarize/compact the conversation to free context |
| Interrupt | Esc |
Stop the agent mid-response |
| Export session | <leader> x |
Open the session transcript in your editor |
| Share session | (unbound by default) | Create a shareable link |
Models, agents, and variants
| Action | Default key | Description |
|---|---|---|
| List models | <leader> m |
Pick a model |
| Cycle recent models | F2 / Shift+F2 |
Next / previous recently used model |
| List agents | <leader> a |
Pick a primary agent |
| Cycle agents | Tab / Shift+Tab |
Next / previous agent |
| Cycle variants | Ctrl+t |
Cycle model reasoning-effort variants |
Navigation & viewing
| Action | Default key | Description |
|---|---|---|
| Command palette | Ctrl+p |
List and run available commands |
| Toggle sidebar | <leader> b |
Show/hide the sidebar |
| List themes | <leader> t |
Switch color theme |
| Open external editor | <leader> e |
Edit your prompt in $EDITOR |
| Scroll messages | PageUp / PageDown |
Page through the transcript |
| First / last message | Ctrl+g / Ctrl+Alt+g |
Jump to start / end |
| Copy message | <leader> y |
Copy the focused message |
| Undo / redo message | <leader> u / <leader> r |
Revert or re-apply the agent's last change |
Application
| Action | Default key | Description |
|---|---|---|
| Exit | Ctrl+c, Ctrl+d, or <leader> q |
Quit opencode |
| Suspend (POSIX) | Ctrl+z |
Suspend to the shell (disabled on native Windows) |
| Toggle help | (unbound by default) | Open the help dialog |
Note
The full set of bindings — including the dozens of text-editing shortcuts for the prompt input (word motions, selection, undo/redo, line operations) — is listed in the keybinding reference at the end of this guide.
4.4 Mentioning files and running shell snippets in prompts
Inside the prompt you can reference files with @:
> Refactor @src/auth.ts to use the new SessionService and update @src/cli/index.ts
Typing @ triggers a file autocomplete. The mentioned files are attached as context for the agent.
4.5 Attaching to a running server
If you have a headless opencode server running (see §10), you can drive it interactively from another terminal. Inside the TUI this is the "attach" workflow; from the command line, opencode run --interactive --attach connects an interactive session to a remote server.
5. Running opencode Non-Interactively (opencode run)
opencode run sends a single prompt, streams the result to stdout, and exits when the session goes idle. This is the workhorse for scripting, automation, and one-off questions.
5.1 Basic usage
opencode run "Explain what src/server/server.ts does"
The agent processes the request and streams its work and final answer to your terminal. Pipe input in from stdin:
git diff | opencode run "Review this diff and flag any bugs"
Pipe output to a file or another tool:
opencode run "List every public API endpoint and its HTTP method" > endpoints.txt
5.2 run options
| Option | Alias | Description |
|---|---|---|
--continue |
-c |
Continue the last session |
--session <id> |
-s |
Continue a specific session by id |
--fork |
Fork the session before continuing (requires --continue or --session) |
|
--share |
Share the session and print a link | |
--model <provider/model> |
-m |
Choose the model, e.g. anthropic/claude-opus-4-8 |
--agent <name> |
Use a specific primary agent | |
--variant <name> |
Model reasoning-effort variant (e.g. high, max, minimal) |
|
--format <default|json> |
Human-formatted output, or raw JSON events for scripting | |
--file <path> |
-f |
Attach one or more files to the message (repeatable) |
--title <text> |
Set the session title (truncated prompt if no value) | |
--command <name> |
Run a slash-command; use the message for its arguments | |
--thinking |
Show the model's thinking/reasoning blocks | |
--interactive |
-i |
Run in the direct interactive split-footer mode |
--attach <url> |
Attach to a running server, e.g. http://localhost:4096 |
|
--dir <path> |
Directory to run in (or remote path when attaching) | |
--port <n> |
Port for the local server (random if omitted) | |
--username <name> |
-u |
Basic-auth username when attaching (default opencode) |
--password <pw> |
-p |
Basic-auth password when attaching |
--dangerously-skip-permissions |
Auto-approve any permission not explicitly denied — dangerous |
5.3 Continuing and forking sessions
Pick up where you left off:
opencode run --continue "Now add tests for that change"
Continue a specific session and branch it so the original is untouched:
opencode run --session ses_abc123 --fork "Try a different approach using streams"
5.4 Choosing a model and effort
opencode run -m anthropic/claude-opus-4-8 --variant high "Design the migration plan"
The --variant controls provider-specific reasoning effort. Common values are minimal, high, and max, but the exact set depends on the model.
5.5 Machine-readable output
opencode run --format json "Summarize the README" > out.jsonl
In JSON mode, opencode emits one JSON object per line for each event (text, tool_use, step_start, step_finish, error, …), each stamped with a timestamp and session id. This is the format to parse in scripts and pipelines.
Warning
In non-interactive
run, the agent cannot ask you questions or pause for planning — those permissions are denied automatically so the run never blocks waiting for input. By default, any other permission the agent requests (for example, an undeclared shell command) is auto-rejected and logged. Pass--dangerously-skip-permissionsto auto-approve instead, but only in trusted, sandboxed environments.
5.6 Running a slash-command from the CLI
opencode run --command review "src/auth.ts"
This invokes the review command (a custom command you have defined — see §7) and passes src/auth.ts as its arguments.
6. Agents
An agent is a named persona with its own system prompt, allowed permissions, and (optionally) a pinned model. opencode ships with built-in agents and lets you define your own. Agents come in three modes:
| Mode | Meaning |
|---|---|
primary |
Acts as a main agent you talk to directly |
subagent |
Can be invoked by another agent to handle a delegated task |
all |
Can act in both roles |
6.1 Listing agents
opencode agent list
build (primary)
{}
plan (all)
{ "edit": "deny", "bash": "deny" }
Each agent prints its name, mode, and its permission map. Built-in (native) agents are listed first.
6.2 Creating an agent
opencode agent create
The interactive flow asks where to save it (global or current project), what the agent should do, which permissions to allow, and which mode to use. opencode uses your model to generate the agent's identifier and system prompt for you.
Create one fully non-interactively (useful in scripts):
opencode agent create \
--description "Review code for security issues only; never edit files" \
--mode subagent \
--permissions "read,grep,glob" \
--model anthropic/claude-opus-4-8
The --permissions flag (alias --tools) takes a comma-separated subset of:
bash, read, edit, glob, grep, webfetch, task, todowrite, websearch, lsp, skill
Anything you omit is set to deny. Permissions are keyed by capability, not raw tool name — for example, edit gates the write/edit/patch tools together.
6.3 How agents are stored
A created agent is a Markdown file with YAML frontmatter:
---
description: When to use this agent (shown to other agents for delegation)
mode: subagent
permission:
edit: deny
bash: deny
---
You are a security reviewer. You read code and report vulnerabilities...
opencode loads agents from agent/ or agents/ directories — globally in your config directory, or per-project under .opencode/agents/. The filename (minus .md) becomes the agent name.
6.4 Using an agent
In the TUI, cycle agents with Tab / Shift+Tab or pick one with <leader> a. From the CLI:
opencode run --agent plan "Outline the steps to add OAuth without writing code"
Tip
A common pattern is a read-only plan agent (edit and bash denied) that you use to design a change, then switch to a build agent with full permissions to execute it.
7. Custom Commands
Commands are reusable prompt templates you trigger by name. They live as Markdown files in command/ or commands/ directories (globally or under .opencode/commands/), where the filename becomes the command name.
A command file is a Markdown template — its body is the prompt, and its frontmatter can pin a model, agent, and other options. Templates support:
- File references with
@path— the file's contents are inlined into the prompt. - Shell substitution with
!`command`— the command runs and its output is inlined.
Example commands/review.md:
---
description: Security-focused code review
---
Review the following file for security issues. Be specific and cite line numbers.
@$ARGUMENTS
Current branch: !`git branch --show-current`
Run it from the TUI's command palette (Ctrl+p) or from the CLI:
opencode run --command review src/auth.ts
Note
Commands, agents, and plugins are all auto-discovered from your project's
.opencode/directory and merged with your global config. This means a repository can ship its own opencode workflow that every contributor gets automatically.
8. Connecting MCP Servers
opencode is a Model Context Protocol client. MCP servers give the agent extra tools — filesystem access, web APIs, databases, internal services, and so on. Servers can be local (a command opencode runs) or remote (an HTTP URL, optionally OAuth-protected).
8.1 Adding a server
opencode mcp add
The wizard asks for a name, whether the server is local or remote, the command or URL, and (for remote servers) whether it needs OAuth. Your answers are written into opencode.json (project or global, your choice), preserving any comments in the file.
A local server entry looks like this:
{
"mcp": {
"filesystem": {
"type": "local",
"command": ["opencode", "x", "@modelcontextprotocol/server-filesystem"]
}
}
}
A remote server with OAuth:
{
"mcp": {
"my-server": {
"type": "remote",
"url": "https://example.com/mcp",
"oauth": {
"clientId": "your-client-id",
"clientSecret": "your-client-secret"
}
}
}
}
Note
Remote MCP servers support OAuth by default. You only need the
oauthblock if the server requires a pre-registered client; otherwise opencode attempts dynamic client registration automatically.
8.2 Listing and checking servers
opencode mcp list
┌ MCP Servers
│ ✓ filesystem connected
│ opencode x @modelcontextprotocol/server-filesystem
│ ⚠ my-server needs authentication
│ https://example.com/mcp
└ 2 server(s)
Status icons: ✓ connected, ○ disabled / not initialized, ⚠ needs authentication, ✗ failed or needs client registration.
8.3 Authenticating an OAuth server
opencode mcp auth my-server
opencode opens your browser to complete the OAuth flow (and prints the URL if it cannot open a browser automatically). List OAuth-capable servers and their status:
opencode mcp auth list
Remove stored credentials for a server:
opencode mcp logout my-server
8.4 Debugging a connection
opencode mcp debug my-server
This probes the server over HTTP, reports the status code and any WWW-Authenticate header, inspects stored tokens (and whether they are expired), and walks through the OAuth discovery flow without completing authorization — invaluable when a server "needs authentication" but you are not sure why.
9. Plugins
Plugins extend opencode itself — adding hooks, new providers, themes, or behavior — and are distributed as npm packages or local files.
9.1 Installing a plugin
opencode plugin <module>
plug is an alias. Install into the global config or force-replace an existing version:
opencode plugin my-org/opencode-plugin-foo --global
opencode plugin my-org/opencode-plugin-foo --force
opencode installs the npm package, reads its manifest to detect what it provides (a server plugin, a TUI plugin, or TUI themes), and updates the appropriate config file (opencode.json for server plugins, tui.json for TUI plugins/themes).
| Flag | Alias | Description |
|---|---|---|
--global |
-g |
Install into the global config instead of the project |
--force |
-f |
Replace an existing plugin version |
9.2 Auto-discovered local plugins
Drop a .ts or .js file into your project's .opencode/plugin/ (or plugins/) directory and opencode loads it automatically — no install step. This is the fastest way to prototype a plugin or ship a project-specific one.
Tip
Run opencode without any external plugins for a clean, reproducible session with the global
--pureflag (or setOPENCODE_PURE=1):opencode --pure
10. Running opencode as a Server
opencode can run headless and expose an HTTP API. This powers editor extensions, the desktop app, remote/attach workflows, and the Agent Client Protocol (ACP).
10.1 Headless server
opencode serve
opencode server listening on http://127.0.0.1:4096
Control the bind address and port through the network options:
opencode serve --port 4096 --hostname 0.0.0.0
Caution
When
OPENCODE_SERVER_PASSWORDis not set, the server is unsecured — anyone who can reach the port can drive your agent and access your files. opencode prints a warning in this case. Set a password (and optionally a username viaOPENCODE_SERVER_USERNAME) before binding to anything other than localhost.
10.2 Web interface
opencode web
This starts the server and opens a browser-based interface, printing local and network URLs. When bound to 0.0.0.0, it lists each non-internal network address so you can reach it from another device on your LAN.
10.3 Attaching the CLI to a server
# Non-interactive against a remote server
opencode run --attach http://localhost:4096 "What changed in the last session?"
# Interactive against a remote server
opencode run --interactive --attach http://localhost:4096
Provide credentials with --username / --password (or the OPENCODE_SERVER_USERNAME / OPENCODE_SERVER_PASSWORD environment variables), and target a working directory on the remote with --dir.
10.4 ACP (Agent Client Protocol)
opencode acp
Starts an ACP server over stdin/stdout so ACP-compatible clients (for example, certain editors) can drive opencode as their agent backend. --cwd sets the working directory.
11. Customizing the TUI
TUI-specific settings — theme, keybindings, scroll behavior, notification sounds — live in a dedicated tui.json file (not opencode.json). opencode looks for tui.json in your global config directory and in project .opencode/ directories, merging them so the closest file wins.
Important
Earlier versions kept
theme,keybinds, andtuikeys insideopencode.json. opencode now migrates these intotui.jsonautomatically the first time it runs, backing up the original. If you still have them inopencode.json, move them totui.json.
11.1 Example tui.json
{
"$schema": "https://opencode.ai/tui.json",
"theme": "opencode",
"leader_timeout": 2000,
"scroll_speed": 1,
"diff_style": "auto",
"mouse": true,
"keybinds": {
"leader": "ctrl+x",
"session_new": "<leader>n",
"model_list": "<leader>m"
},
"attention": {
"enabled": true,
"notifications": true,
"sound": true,
"volume": 0.4
}
}
11.2 TUI settings
| Key | Type | Default | Description |
|---|---|---|---|
theme |
string | opencode |
Color theme name |
keybinds |
object | — | Per-action key overrides (see appendix) |
leader_timeout |
integer (ms) | 2000 |
Time allowed to complete a leader sequence |
mouse |
boolean | true |
Enable mouse capture |
scroll_speed |
number | — | Scroll speed multiplier (≥ 0.001) |
scroll_acceleration |
object | — | { "enabled": true } to accelerate scrolling |
diff_style |
auto | stacked |
auto |
auto adapts to terminal width; stacked always shows a single column |
prompt.max_height |
integer | — | Max height of the prompt textarea |
prompt.max_width |
integer | auto |
— | Home-screen prompt width cap |
attention.notifications |
boolean | true |
Desktop notifications when the agent needs you |
attention.sound |
boolean | true |
Play a sound on attention events |
attention.volume |
number 0–1 | 0.4 |
Notification sound volume |
attention.sound_pack |
string | opencode.default |
Named sound pack |
plugin |
array | — | TUI plugins to load |
Note
Notification sounds fire on different events —
done,error,permission,question, andsubagent_done. You can map each to a custom sound file underattention.sounds.
11.3 Changing the theme
The fastest way is in the TUI: press <leader> t to browse and apply themes live. To pin one, set theme in tui.json.
11.4 Remapping keys
Override any binding in tui.json under keybinds. A binding value can be a single chord ("ctrl+r"), a comma-separated list ("ctrl+c,ctrl+d"), a list of chords, false/"none" to disable, or an object for advanced options. Unknown keybind names are ignored with a warning, so a typo will not break startup.
{
"keybinds": {
"session_compact": "ctrl+k",
"terminal_suspend": "none"
}
}
12. Configuration (opencode.json)
Beyond the TUI, opencode reads project and global configuration from opencode.json (or opencode.jsonc, which allows comments). This file controls models, providers, agents, commands, permissions, MCP servers, instructions, and more.
12.1 Where config lives and how it merges
opencode merges config from several sources, with later sources overriding earlier ones:
- Global config:
opencode.json/opencode.jsoncin your config directory - A custom file pointed to by
OPENCODE_CONFIG - Project files:
opencode.jsonwalking up from your working directory to the repo root .opencode/opencode.jsondirectories discovered up the tree- Inline config via
OPENCODE_CONFIG_CONTENT - System-managed config (for centrally managed installs)
Array fields like instructions are concatenated and de-duplicated across sources rather than replaced.
Tip
opencode seeds a new global
opencode.jsonwith the schema reference so your editor gives you autocomplete:{ "$schema": "https://opencode.ai/config.json" }
12.2 Common config keys
| Key | Description |
|---|---|
model |
Default model, as provider/model |
provider |
Per-provider overrides (custom endpoints, names, options) |
enabled_providers / disabled_providers |
Allow- or deny-list providers |
agent |
Inline agent definitions (merged with files in agent/) |
command |
Inline command definitions |
mcp |
MCP server definitions (see §8) |
permission |
Permission rules for tools (allow/deny/ask) |
tools |
Enable/disable tools by name (shorthand that maps onto permission) |
instructions |
Extra instruction files/snippets always given to the agent |
plugin |
Plugin specs to load |
share |
Sharing mode (auto to share every session automatically) |
username |
Display name used in transcripts (defaults to your system username) |
compaction |
Auto-compaction settings (auto, prune) |
12.3 Permissions
Permissions decide what the agent may do without asking. They are expressed per capability with an action of allow, deny, or ask:
{
"permission": {
"edit": "ask",
"bash": "ask",
"webfetch": "allow"
}
}
The tools shorthand maps booleans onto permissions (true → allow, false → deny); note that write, edit, and patch all collapse onto the single edit permission.
Caution
Setting
editorbashtoallowlets the agent change files or run shell commands without confirmation. Useask(the safe default behavior in interactive mode) unless you are in a throwaway sandbox.
12.4 Variable substitution
Config values support two substitutions:
{env:VAR_NAME}— replaced with an environment variable's value{file:./path}— replaced with the contents of a file (relative to the config file, or~/...for your home directory)
{
"provider": {
"my-gateway": {
"options": { "apiKey": "{env:MY_GATEWAY_KEY}" }
}
},
"instructions": ["{file:./CONVENTIONS.md}"]
}
12.5 Project instructions
opencode reads project instruction files (such as AGENTS.md) and your configured instructions so the agent always knows your conventions. Anything you would otherwise repeat in every prompt — coding standards, architecture notes, "always run the linter" — belongs here.
13. Sessions: History, Stats, Export & Import
Every conversation is a session, persisted locally so you can resume, inspect, share, and analyze it.
13.1 Listing sessions
opencode session list
Session ID Title Updated
──────────────────────────────────────────────────────────────
ses_abc123… Add --verbose flag Today 14:22
ses_def456… Refactor auth service Yesterday
Limit the count or get JSON:
opencode session list --max-count 20
opencode session list --format json
Long lists are paged through your pager (less, or more on Windows) automatically.
13.2 Deleting a session
opencode session delete ses_abc123
13.3 Usage statistics
opencode stats
┌────────────────────────────────────────────────────────┐
│ OVERVIEW │
├────────────────────────────────────────────────────────┤
│ Sessions 142 │
│ Messages 1,873 │
│ Days 30 │
└────────────────────────────────────────────────────────┘
stats aggregates token usage and cost across your sessions, plus tool-usage and model-usage breakdowns. Scope and detail are controllable:
| Option | Description |
|---|---|
--days <n> |
Limit to the last N days (0 = today only; omit for all time) |
--tools <n> |
Show only the top N tools |
--models [n] |
Show model statistics (optionally top N) |
--project <id> |
Filter to a project (empty string = current project) |
opencode stats --days 7 --models 5 --project ""
13.4 Exporting a session
opencode export > session.json
With no session id, opencode prompts you to pick one. Redact sensitive content (file text, paths, tool output) for safe sharing:
opencode export ses_abc123 --sanitize > session.redacted.json
The diagnostic data and transcript are written to stdout as JSON; status messages go to stderr, so piping to a file gives you clean JSON.
13.5 Importing a session
opencode import ./session.json
opencode import https://opencode.ai/share/abc123
Import accepts a local JSON file or a share URL, reconstructs the session locally, and stores it in your database.
13.6 Sharing sessions
Share a session to get a public link (handy for asking for help or showing your work):
- In the TUI: bind and press the
session_shareaction, or set"share": "auto"in config to share automatically. - From the CLI: add
--sharetoopencode run.
A shared session prints a URL like https://opencode.ai/s/<id>.
Warning
Sharing publishes the session transcript — including file snippets and tool output — to a public URL. Review what is in a session before sharing, and use
opencode export --sanitizeif you need a redacted copy instead. Sharing can be disabled organization-wide viaOPENCODE_DISABLE_SHARE.
13.7 Inspecting the local database
opencode stores sessions in a local SQLite database. Power users can query it directly:
opencode db path # print the DB file path
opencode db "SELECT id, title FROM session" # run a query (TSV by default)
opencode db "SELECT * FROM session" --format json
opencode db # open an interactive sqlite3 shell
Caution
The database is opencode's own storage. Reading is safe; writing or altering schema can corrupt your sessions. Treat
opencode dbas read-only unless you know exactly what you are doing.
14. The GitHub Agent
opencode can run inside GitHub Actions and respond to issues and pull requests — summarizing threads, reviewing code, and implementing changes that it pushes as commits or PRs.
14.1 Installing it
From inside a git repository:
opencode github install
The installer opens the GitHub App install page, waits for you to install opencode-agent on the repo, asks which provider and model to use, and writes a .github/workflows/opencode.yml workflow file. It then prints next steps.
14.2 What the workflow looks like
The generated workflow triggers on issue and PR-review comments and runs the agent when a comment mentions it:
name: opencode
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
opencode:
if: |
contains(github.event.comment.body, ' /oc') ||
startsWith(github.event.comment.body, '/oc') ||
contains(github.event.comment.body, ' /opencode') ||
startsWith(github.event.comment.body, '/opencode')
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
pull-requests: read
issues: read
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-opus-4-8
After committing the workflow and adding the provider's API key as a repository or org secret, you trigger the agent.
14.3 Using it
In any issue or PR comment, mention the agent:
/oc summarize this thread
/opencode implement the fix described above and open a PR
- On an issue, the agent creates a new branch, does the work, and opens a PR that closes the issue.
- On a pull request, it works on the PR's branch (local or fork) and pushes its changes, then comments with a summary.
- A bare mention (
/ocalone) on a PR review comment asks the agent to review the commented lines; on an issue thread it summarizes the thread.
The agent adds an 👀 reaction while it works and removes it when done, and only acts for users with write access to the repo.
Note
The GitHub agent also supports scheduled and manual (
workflow_dispatch) runs, where you supply the prompt via aPROMPTinput. Image attachments in comments are downloaded and passed to the agent. Sessions from agent runs can be shared automatically (controlled by theSHAREinput).
14.4 Checking out a PR locally
To review or continue a PR on your own machine, opencode can fetch it and start a session — importing the linked opencode session if the PR description contains one:
opencode pr 1234
This requires the gh CLI installed and authenticated. It checks out the PR (adding a fork remote if needed) and launches opencode.
15. The opencode Console (Zen Accounts)
If you use the hosted opencode Zen gateway or belong to an organization, the console command manages your account and org selection from the terminal.
opencode console login # log in to the console (device-code flow)
opencode console logout # log out of an account
opencode console switch # switch the active organization
opencode console orgs # list your orgs
opencode console open # open the active console account in a browser
login walks you through a device-code flow: opencode shows a URL and a code, opens your browser, and polls until you authorize. Once you have an active org, opencode can pull org-managed configuration and provider access automatically.
Note
Zen lets you use many models behind a single key and (for organizations) centrally managed providers and config. If you authenticate as a provider with
opencode auth loginand pick opencode, you are using Zen.
16. Global Flags
These flags work with any command:
| Flag | Alias | Description |
|---|---|---|
--help |
-h |
Show help for opencode or a subcommand |
--version |
-v |
Print the version number |
--print-logs |
Print logs to stderr | |
--log-level <level> |
DEBUG, INFO, WARN, or ERROR |
|
--pure |
Run without external plugins |
Generate a shell completion script:
opencode completion >> ~/.bashrc # or your shell's rc file
17. Useful Environment Variables
opencode reads a number of environment variables. The ones most relevant to daily use:
| Variable | Purpose |
|---|---|
OPENCODE_CONFIG |
Path to a specific config file to load |
OPENCODE_CONFIG_DIR |
Additional config directory to load from |
OPENCODE_CONFIG_CONTENT |
Inline JSON config (highest project precedence) |
OPENCODE_DISABLE_PROJECT_CONFIG |
Ignore project-level config |
OPENCODE_PERMISSION |
Inline JSON permission overrides |
OPENCODE_PURE |
Run without external plugins (same as --pure) |
OPENCODE_SERVER_PASSWORD / OPENCODE_SERVER_USERNAME |
Auth for serve / web / attach |
OPENCODE_DISABLE_AUTOUPDATE |
Turn off automatic update checks |
OPENCODE_ALWAYS_NOTIFY_UPDATE |
Always notify when an update is available |
OPENCODE_DISABLE_AUTOCOMPACT |
Disable automatic conversation compaction |
OPENCODE_DISABLE_PRUNE |
Disable context pruning |
OPENCODE_DISABLE_SHARE |
Disable session sharing entirely |
OPENCODE_DISABLE_MOUSE |
Disable mouse capture in the TUI |
OPENCODE_GIT_BASH_PATH |
Path to Git Bash (Windows) |
OPENCODE_TUI_CONFIG |
Path to a specific tui.json |
Provider keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, …) |
Auto-detected provider credentials |
Note
Variables prefixed
OPENCODE_EXPERIMENTAL_…toggle experimental features (workspaces, session switcher, file watcher, and others). SetOPENCODE_EXPERIMENTAL=trueto opt into the experimental set, or enable individual flags. Experimental features may change or be removed.
18. Troubleshooting
Error: You must provide a message or a command
Cause: You ran opencode run with no prompt, no --command, and nothing piped on stdin.
Solution: Provide a prompt: opencode run "your request", pipe input (cat file | opencode run "..."), or use --command.
Prevention: In scripts, always pass an explicit message or pipe content.
Error: --fork requires --continue or --session
Cause: --fork was used without specifying which session to fork.
Solution: Add --continue (to fork the last session) or --session <id> (to fork a specific one).
Error: Session not found
Cause: The session id passed to --session, session delete, or export does not exist locally.
Solution: Run opencode session list to find the correct id. If the session lives on another machine or a share, opencode import it first.
Error: Invalid model <value>. Model must be in the format "provider/model"
Cause: A model was passed without the provider/ prefix (commonly in the GitHub agent's model: input or --model).
Solution: Use the full id, e.g. anthropic/claude-opus-4-8, not claude-opus-4-8. List valid ids with opencode models.
Error: Provider not found: <id>
Cause: You filtered opencode models <provider> (or referenced a provider) that you have not authenticated or that does not exist.
Solution: Run opencode auth list to see configured providers and opencode auth login to add one. Refresh the catalog with opencode models --refresh.
Error: Comments must mention /opencode or /oc
Cause: The GitHub agent ran on a comment that does not mention it.
Solution: Include /oc or /opencode in the comment. You can customize the trigger phrases via the workflow's MENTIONS input.
Error: User <name> does not have write permissions
Cause: The GitHub agent was triggered by a user without write access to the repository.
Solution: Only repository collaborators with write or admin permission can run the agent. Grant access or have an authorized user trigger it.
Error: PROMPT input is required for ... events
Cause: A scheduled or workflow_dispatch (or issues) GitHub run started without a PROMPT, which those event types require.
Solution: Supply a PROMPT input in the workflow for non-comment triggers.
Error: PROMPT_TOO_LARGE / "Input exceeds context window of this model"
Cause: The prompt (often plus attached files) is larger than the model's context window.
Solution: In the TUI, compact the session (<leader> c) or start a new one (<leader> n). Attach fewer/smaller files, or switch to a model with a larger context window (<leader> m). The error lists the files in the prompt and their sizes.
Error: Unauthorized: request was blocked by a gateway or proxy...
Cause: A provider request returned 401/403 from a gateway — usually a missing or expired token.
Solution: Re-authenticate: opencode auth login <your provider URL>. Check that any required environment variables (API keys, gateway tokens) are set.
Error: Could not find git repository. Please run this command from a git repository.
Cause: opencode github install or opencode pr was run outside a git repo (or one without a GitHub origin).
Solution: cd into a cloned git repository whose origin points at GitHub.
Error: Could not fetch an OIDC token. Make sure to add 'id-token: write' to your workflow permissions.
Cause: The GitHub workflow is missing the id-token: write permission the agent needs to exchange an app token.
Solution: Add permissions: { id-token: write, ... } to the job (the generated workflow includes it).
Warning: OPENCODE_SERVER_PASSWORD is not set; server is unsecured.
Cause: You started serve/web without a password.
Solution: Set OPENCODE_SERVER_PASSWORD (and optionally OPENCODE_SERVER_USERNAME) before exposing the server beyond localhost. See §10.1.
opencode enters an auto-compaction loop / stops responding
Cause: The session repeatedly compacts when context is tight.
Solution: Start a fresh session (<leader> n). As a workaround you can disable automatic compaction with OPENCODE_DISABLE_AUTOCOMPACT=true, though long sessions may then hit context limits.
Startup hangs in a project with .opencode/node_modules/
Cause: A large node_modules directory under .opencode/ slows project scanning.
Solution: Keep .opencode/node_modules/ out of the way; opencode writes a .gitignore in config dirs to exclude installed plugin dependencies. Remove stray node_modules you did not intend to commit.
Ctrl+Z suspends opencode instead of editing text (Linux)
Cause: Ctrl+Z is bound to terminal suspend by default on POSIX systems.
Solution: Remap terminal_suspend to "none" and/or input_undo to your preference in tui.json (see §11.4). On native Windows this is handled automatically.
Cannot paste from the clipboard
Cause: Terminal or platform clipboard integration, or a copy-on-select conflict.
Solution: Paste is bound to Ctrl+v by default. On Windows, opencode disables copy-on-select by default; you can toggle this with OPENCODE_EXPERIMENTAL_DISABLE_COPY_ON_SELECT.
19. Frequently Asked Questions
Q: Do I need an OpenAI/Anthropic API key, or can I use my existing subscription? You can use either. OpenAI works with a ChatGPT Plus/Pro subscription via OAuth or with an API key; GitHub Copilot uses your Copilot subscription; Anthropic supports OAuth or an API key. You can also use the hosted opencode Zen gateway with a single key.
Q: Which models can I use?
Any model from any provider you have authenticated. The catalog comes from models.dev. Run opencode models to list them, and switch any time with <leader> m.
Q: How do I change the model for a single run?
opencode run -m provider/model "your prompt", or in the TUI press <leader> m. Set a default with model in opencode.json.
Q: Where is my data stored?
Locally. Sessions live in a SQLite database (find it with opencode db path); credentials in auth.json; config in your config directory. Nothing is sent anywhere except to the model provider you chose (and to the share service if you explicitly share a session).
Q: Is opencode safe to let edit my files and run commands?
By default, in interactive mode, opencode asks before edits and shell commands. You control this per capability via permission/tools config and per agent. Avoid --dangerously-skip-permissions outside sandboxes.
Q: How do I stop the agent mid-task?
Press Esc in the TUI to interrupt. In run, send Ctrl+c.
Q: My context filled up — what do I do?
Compact the session with <leader> c, or start a new one with <leader> n. opencode also auto-compacts; you can disable that with OPENCODE_DISABLE_AUTOCOMPACT.
Q: Can I use opencode without internet access to a cloud model?
Yes, if you connect a local/self-hosted model endpoint as a provider (for example, an OpenAI-compatible local server). Configure it under provider in opencode.json.
Q: How do I share a session with a teammate?
Use --share on opencode run, the share keybind in the TUI, or "share": "auto". You will get a public URL. Use opencode export --sanitize if you need a redacted copy instead.
Q: How do I add a tool the agent doesn't have?
Connect an MCP server (opencode mcp add) to give the agent new tools, or write a plugin (opencode plugin <module>).
Q: What's the difference between an agent and a command? An agent is a persona (system prompt + permissions + model) you converse with. A command is a reusable prompt template you trigger by name. You can combine them: a command can specify which agent runs it.
Q: How do I run opencode in CI?
Use the GitHub agent (opencode github install) for issue/PR automation, or opencode run --format json in any pipeline for scripted, machine-readable runs.
Q: How do I completely remove opencode?
opencode uninstall (add --keep-config/--keep-data to preserve those). It removes data, cache, config, and state directories and the PATH entry.
Q: Why does opencode want to write a .gitignore in my config directory?
When it installs the @opencode-ai/plugin dependency into a .opencode directory, it ignores node_modules, lockfiles, and the generated package.json so they are not committed.
Q: Can I disable telemetry/sharing across my org?
Set OPENCODE_DISABLE_SHARE to disable sharing. Organization-managed installs can also enforce config centrally (see the Admin Guide).
Appendix A: Keybinding Reference
All bindings are overridable under keybinds in tui.json. The leader key defaults to Ctrl+x; <leader> below means "press the leader, then the key shown."
Application
| Action | Key | Description |
|---|---|---|
app_exit |
ctrl+c, ctrl+d, <leader>q |
Exit the application |
command_list |
ctrl+p |
List available commands |
terminal_suspend |
ctrl+z |
Suspend terminal (disabled on Windows) |
which_key_toggle |
ctrl+alt+k |
Toggle the which-key panel |
Sessions
| Action | Key | Description |
|---|---|---|
session_new |
<leader>n |
Create a new session |
session_list |
<leader>l |
List all sessions |
session_timeline |
<leader>g |
Show session timeline |
session_rename |
ctrl+r |
Rename session |
session_delete |
ctrl+d |
Delete session |
session_interrupt |
escape |
Interrupt the current response |
session_compact |
<leader>c |
Compact the session |
session_export |
<leader>x |
Export session to editor |
session_background |
ctrl+b |
Background synchronous subagents |
session_pin_toggle |
ctrl+f |
Pin/unpin in the session list |
session_quick_switch_1…9 |
<leader>1…<leader>9 |
Switch to a quick-slot session |
session_parent / session_child_first |
up / <leader>down |
Move to parent / first child session |
Models, agents, variants
| Action | Key | Description |
|---|---|---|
model_list |
<leader>m |
List available models |
model_cycle_recent |
f2 |
Next recently used model |
model_cycle_recent_reverse |
shift+f2 |
Previous recently used model |
agent_list |
<leader>a |
List agents |
agent_cycle / agent_cycle_reverse |
tab / shift+tab |
Next / previous agent |
variant_cycle |
ctrl+t |
Cycle model variants |
Messages & viewing
| Action | Key | Description |
|---|---|---|
messages_page_up / messages_page_down |
pageup / pagedown |
Scroll a page |
messages_first / messages_last |
ctrl+g / ctrl+alt+g |
First / last message |
messages_copy |
<leader>y |
Copy message |
messages_undo / messages_redo |
<leader>u / <leader>r |
Undo / redo a change |
messages_toggle_conceal |
<leader>h |
Toggle code-block concealment |
Appearance & panels
| Action | Key | Description |
|---|---|---|
theme_list |
<leader>t |
Switch theme |
sidebar_toggle |
<leader>b |
Toggle sidebar |
editor_open |
<leader>e |
Open external editor |
status_view |
<leader>s |
View status |
Diff viewer
| Action | Key | Description |
|---|---|---|
diff_close |
escape, q |
Close diff viewer |
diff_toggle |
enter, space |
Toggle item |
diff_next_file / diff_previous_file |
n / p |
Next / previous file |
diff_toggle_view |
v |
Split vs. unified |
diff_toggle_file_tree |
b |
Toggle file tree |
Prompt input (selection of common bindings)
| Action | Key | Description |
|---|---|---|
input_submit |
return |
Submit input |
input_newline |
shift+return, ctrl+j |
Insert a newline |
input_paste |
ctrl+v |
Paste from clipboard |
input_word_forward / input_word_backward |
alt+f / alt+b |
Move by word |
input_delete_word_backward |
ctrl+w |
Delete previous word |
input_undo / input_redo |
ctrl+- / ctrl+. |
Undo / redo in the input |
history_previous / history_next |
up / down |
Cycle prompt history |
Note
This is a representative subset. The complete list of input-editing bindings (visual-line motions, buffer home/end, selection variants) is defined in opencode and surfaced in the which-key panel (
Ctrl+Alt+k).