# opencode User Guide

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)"

    ```bash
    curl -fsSL https://opencode.ai/install | bash
    ```

=== "npm"

    ```bash
    npm install -g opencode-ai
    ```

=== "Homebrew (macOS)"

    ```bash
    brew install opencode
    ```

=== "Windows (Scoop)"

    ```powershell
    scoop install opencode
    ```

Once installed, open a terminal in a project you want to work on and start opencode:

```bash
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:

```bash
opencode auth login
```

```text
┌  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`:

```text
> 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 models` to list every model from every provider you have authenticated. Switch models inside the TUI any time with the `<leader> m` keybind (the leader key is `Ctrl+x` by 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)"

    ```bash
    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"

    ```bash
    npm install -g opencode-ai
    # or
    pnpm add -g opencode-ai
    # or
    bun add -g opencode-ai
    # or
    yarn global add opencode-ai
    ```

=== "Homebrew"

    ```bash
    brew install opencode
    ```

=== "Chocolatey / Scoop (Windows)"

    ```powershell
    choco install opencode
    # or
    scoop install opencode
    ```

### 2.3 Verify the install

```bash
opencode --version
```

```text
1.16.0
```

```bash
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 the `OPENCODE_GIT_BASH_PATH` environment variable.

### 2.4 Upgrading

```bash
opencode upgrade
```

```text
┌  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:

```bash
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, set `OPENCODE_ALWAYS_NOTIFY_UPDATE=true`.

### 2.5 Uninstalling

```bash
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:

```bash
opencode uninstall --dry-run
```

Keep your config and/or session data while removing the binary:

```bash
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

```bash
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:

```bash
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:

```bash
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

```bash
opencode auth list
```

```text
┌  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:

```bash
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 run `auth login` if the key is already in your environment.

### 3.4 Browsing available models

```bash
opencode models
```

```text
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`:

```bash
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](#11-customizing-the-tui)).

> [!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](#appendix-a-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 `@`:

```text
> 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](#10-running-opencode-as-a-server)), 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

```bash
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:

```bash
git diff | opencode run "Review this diff and flag any bugs"
```

Pipe output to a file or another tool:

```bash
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:

```bash
opencode run --continue "Now add tests for that change"
```

Continue a specific session and branch it so the original is untouched:

```bash
opencode run --session ses_abc123 --fork "Try a different approach using streams"
```

### 5.4 Choosing a model and effort

```bash
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

```bash
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-permissions` to auto-approve instead, but only in trusted, sandboxed environments.

### 5.6 Running a slash-command from the CLI

```bash
opencode run --command review "src/auth.ts"
```

This invokes the `review` command (a custom command you have defined — see [§7](#7-custom-commands)) 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

```bash
opencode agent list
```

```text
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

```bash
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):

```bash
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:

```text
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:

```markdown
---
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:

```bash
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`:

```markdown
---
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:

```bash
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](https://modelcontextprotocol.io) 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

```bash
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:

```json
{
  "mcp": {
    "filesystem": {
      "type": "local",
      "command": ["opencode", "x", "@modelcontextprotocol/server-filesystem"]
    }
  }
}
```

A remote server with OAuth:

```json
{
  "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 `oauth` block if the server requires a pre-registered client; otherwise opencode attempts dynamic client registration automatically.

### 8.2 Listing and checking servers

```bash
opencode mcp list
```

```text
┌  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

```bash
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:

```bash
opencode mcp auth list
```

Remove stored credentials for a server:

```bash
opencode mcp logout my-server
```

### 8.4 Debugging a connection

```bash
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

```bash
opencode plugin <module>
```

`plug` is an alias. Install into the global config or force-replace an existing version:

```bash
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 `--pure` flag (or set `OPENCODE_PURE=1`):
>
> ```bash
> 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

```bash
opencode serve
```

```text
opencode server listening on http://127.0.0.1:4096
```

Control the bind address and port through the network options:

```bash
opencode serve --port 4096 --hostname 0.0.0.0
```

> [!CAUTION]
> When `OPENCODE_SERVER_PASSWORD` is 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 via `OPENCODE_SERVER_USERNAME`) before binding to anything other than localhost.

### 10.2 Web interface

```bash
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

```bash
# 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)

```bash
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`, and `tui` keys inside `opencode.json`. opencode now migrates these into `tui.json` automatically the first time it runs, backing up the original. If you still have them in `opencode.json`, move them to `tui.json`.

### 11.1 Example `tui.json`

```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`, and `subagent_done`. You can map each to a custom sound file under `attention.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.

```json
{
  "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:

1. Global config: `opencode.json` / `opencode.jsonc` in your config directory
2. A custom file pointed to by `OPENCODE_CONFIG`
3. Project files: `opencode.json` walking up from your working directory to the repo root
4. `.opencode/opencode.json` directories discovered up the tree
5. Inline config via `OPENCODE_CONFIG_CONTENT`
6. 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.json` with the schema reference so your editor gives you autocomplete:
>
> ```json
> { "$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](#8-connecting-mcp-servers)) |
| `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`:

```json
{
  "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 `edit` or `bash` to `allow` lets the agent change files or run shell commands without confirmation. Use `ask` (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)

```json
{
  "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

```bash
opencode session list
```

```text
Session ID            Title                          Updated
──────────────────────────────────────────────────────────────
ses_abc123…           Add --verbose flag             Today 14:22
ses_def456…           Refactor auth service          Yesterday
```

Limit the count or get JSON:

```bash
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

```bash
opencode session delete ses_abc123
```

### 13.3 Usage statistics

```bash
opencode stats
```

```text
┌────────────────────────────────────────────────────────┐
│                       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) |

```bash
opencode stats --days 7 --models 5 --project ""
```

### 13.4 Exporting a session

```bash
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:

```bash
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

```bash
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_share` action, or set `"share": "auto"` in config to share automatically.
- From the CLI: add `--share` to `opencode 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 --sanitize` if you need a redacted copy instead. Sharing can be disabled organization-wide via `OPENCODE_DISABLE_SHARE`.

### 13.7 Inspecting the local database

opencode stores sessions in a local SQLite database. Power users can query it directly:

```bash
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 db` as 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:

```bash
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:

```yaml
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:

```text
/oc summarize this thread
```

```text
/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 (`/oc` alone) 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 a `PROMPT` input. Image attachments in comments are downloaded and passed to the agent. Sessions from agent runs can be shared automatically (controlled by the `SHARE` input).

### 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:

```bash
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.

```bash
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 login` and 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:

```bash
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). Set `OPENCODE_EXPERIMENTAL=true` to 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](#101-headless-server).

### `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](#114-remapping-keys)). 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`).

---

_Generated June 2026 from anomalyco/opencode at 3cf1cef. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
