docs: expand user guides
This commit is contained in:
parent
e2eed76101
commit
f6f0a5c10f
20 changed files with 3149 additions and 52 deletions
288
packages/docs/agents.mdx
Normal file
288
packages/docs/agents.mdx
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
---
|
||||
title: "Agents"
|
||||
description: "Configure and use primary agents and subagents in OpenCode."
|
||||
---
|
||||
|
||||
Agents combine a system prompt, model preference, tool permissions, and display
|
||||
metadata into a reusable assistant profile. OpenCode includes agents for common
|
||||
workflows, and you can override them or add your own in configuration or
|
||||
Markdown files.
|
||||
|
||||
## Modes
|
||||
|
||||
An agent's `mode` controls where it can run:
|
||||
|
||||
| Mode | Behavior |
|
||||
| --- | --- |
|
||||
| `primary` | Can be selected as the main agent for a session. It cannot be launched as a subagent. |
|
||||
| `subagent` | Can run in a child session through the `subagent` tool, but cannot be selected as the main agent. |
|
||||
| `all` | Can be used either way. This is the default for a custom agent when `mode` is omitted. |
|
||||
|
||||
In the TUI, press <kbd>Tab</kbd> and <kbd>Shift</kbd>+<kbd>Tab</kbd> to cycle
|
||||
through visible primary and `all` agents, or use `/agents` to choose one.
|
||||
|
||||
Subagents run in child sessions with fresh context. A primary agent can invoke
|
||||
one with the `subagent` tool, either in the foreground or in the background.
|
||||
You can also `@` mention a visible subagent to ask the current agent to delegate
|
||||
work to it:
|
||||
|
||||
```text
|
||||
@explore find where authentication errors are handled
|
||||
```
|
||||
|
||||
The parent agent's `subagent` permission controls which agents it may launch.
|
||||
The child currently uses its own configured permissions, not a restricted copy
|
||||
of the parent's permissions.
|
||||
|
||||
## Built-in agents
|
||||
|
||||
| Agent | Mode | Purpose |
|
||||
| --- | --- | --- |
|
||||
| **Build** (`build`) | `primary` | Default coding agent. Tools are allowed by default, sensitive environment-file reads ask for approval, and access outside the workspace asks for approval. |
|
||||
| **Plan** (`plan`) | `primary` | Planning agent. File edits are denied except for OpenCode plan files. Shell commands are not generally denied. |
|
||||
| **General** (`general`) | `subagent` | General-purpose research and multi-step work. It has broad tool access but cannot launch more subagents. |
|
||||
| **Explore** (`explore`) | `subagent` | Read-only code and web exploration using `read`, `glob`, `grep`, `webfetch`, and `websearch`. |
|
||||
|
||||
OpenCode also has hidden `compaction`, `title`, and `summary` system agents.
|
||||
They run internal maintenance tasks and are not selectable. There is no built-in
|
||||
`scout` agent in V2.
|
||||
|
||||
You can override a built-in agent with an entry of the same ID. Set
|
||||
`disabled: true` to remove one.
|
||||
|
||||
## Default agent
|
||||
|
||||
Set the primary agent used when a session has not selected one:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"default_agent": "reviewer"
|
||||
}
|
||||
```
|
||||
|
||||
The configured agent must exist, must not have `mode: "subagent"`, and must not
|
||||
be hidden. If it is unavailable, OpenCode falls back to `build`, then to the
|
||||
first visible agent that can run as a primary agent. This selection does not
|
||||
rewrite the agent already stored on an existing session.
|
||||
|
||||
## Configure agents
|
||||
|
||||
### JSON or JSONC
|
||||
|
||||
Use the plural `agents` field in any [OpenCode configuration file](/config):
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"default_agent": "reviewer",
|
||||
"agents": {
|
||||
"reviewer": {
|
||||
"description": "Reviews changes for correctness, security, and missing tests",
|
||||
"mode": "all",
|
||||
"model": "anthropic/claude-sonnet-4-5#high",
|
||||
"system": "Review the current changes. Report findings before any summary.",
|
||||
"color": "warning",
|
||||
"steps": 8,
|
||||
"permissions": [
|
||||
{ "action": "edit", "resource": "*", "effect": "deny" },
|
||||
{ "action": "shell", "resource": "*", "effect": "deny" }
|
||||
]
|
||||
},
|
||||
"build": {
|
||||
"permissions": [
|
||||
{ "action": "shell", "resource": "git push *", "effect": "ask" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Agent definitions merge in configuration order. Later scalar fields replace
|
||||
earlier values, request maps merge by key, and permission rules are appended.
|
||||
Global `permissions` are applied to every agent before its agent-specific rules,
|
||||
so a later agent rule can refine a global rule.
|
||||
|
||||
### Markdown files
|
||||
|
||||
The recommended file locations are:
|
||||
|
||||
```text
|
||||
~/.config/opencode/agents/<name>.md
|
||||
.opencode/agents/<name>.md
|
||||
```
|
||||
|
||||
OpenCode discovers project `.opencode` directories from the current directory
|
||||
up to the project root. The path below `agents/` becomes the agent ID, so
|
||||
`.opencode/agents/team/reviewer.md` defines `team/reviewer`.
|
||||
|
||||
Frontmatter uses the same fields as an entry under `agents`. The Markdown body
|
||||
becomes `system`:
|
||||
|
||||
```md title=".opencode/agents/reviewer.md"
|
||||
---
|
||||
description: Reviews changes without modifying files
|
||||
mode: subagent
|
||||
model: anthropic/claude-sonnet-4-5#high
|
||||
color: warning
|
||||
steps: 8
|
||||
permissions:
|
||||
- action: edit
|
||||
resource: "*"
|
||||
effect: deny
|
||||
- action: shell
|
||||
resource: "*"
|
||||
effect: deny
|
||||
---
|
||||
|
||||
Review for correctness, security, regressions, and missing tests.
|
||||
List findings in severity order with file and line references.
|
||||
```
|
||||
|
||||
For compatibility with older layouts, V2 also discovers Markdown under
|
||||
`agent/`, and treats files under `mode/` or `modes/` as primary agents. Prefer
|
||||
`agents/` for new files.
|
||||
|
||||
## Options
|
||||
|
||||
### `description`
|
||||
|
||||
Explains the agent's purpose. It is optional, but strongly recommended for
|
||||
subagents because OpenCode includes it in the subagent catalog shown to the
|
||||
model.
|
||||
|
||||
### `mode`
|
||||
|
||||
Accepts `primary`, `subagent`, or `all`. The default is `all`.
|
||||
|
||||
### `model`
|
||||
|
||||
Selects a model using `provider/model` with an optional `#variant`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"agents": {
|
||||
"reviewer": {
|
||||
"model": "anthropic/claude-sonnet-4-5#high"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The equivalent expanded form is:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"agents": {
|
||||
"reviewer": {
|
||||
"model": {
|
||||
"providerID": "anthropic",
|
||||
"model": "claude-sonnet-4-5",
|
||||
"variant": "high"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The TUI uses this as the preferred model when the agent is selected. A child
|
||||
session uses its subagent's configured model, or inherits the parent session's
|
||||
model when none is configured. In the API, the session's selected model is
|
||||
stored separately; creating or switching a primary session with only an agent
|
||||
ID does not itself change that session model.
|
||||
|
||||
### `system`
|
||||
|
||||
Sets the agent's system prompt. A non-empty value replaces OpenCode's
|
||||
provider-specific base prompt for that agent. Project instructions, skills,
|
||||
references, and other instruction sources are still added separately.
|
||||
|
||||
For a Markdown agent, use the document body instead of a `system` frontmatter
|
||||
field.
|
||||
|
||||
### `permissions`
|
||||
|
||||
Permissions are an ordered array of rules:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"agents": {
|
||||
"orchestrator": {
|
||||
"permissions": [
|
||||
{ "action": "subagent", "resource": "*", "effect": "deny" },
|
||||
{ "action": "subagent", "resource": "explore", "effect": "allow" },
|
||||
{ "action": "shell", "resource": "git *", "effect": "ask" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each rule has:
|
||||
|
||||
| Field | Meaning |
|
||||
| --- | --- |
|
||||
| `action` | Tool or permission action, with `*` wildcards supported. |
|
||||
| `resource` | The path, command, agent ID, or other resource matched by the action. Wildcards are supported. |
|
||||
| `effect` | `allow`, `ask`, or `deny`. |
|
||||
|
||||
The last matching rule wins. Important V2 action names include `shell` for
|
||||
shell commands, `edit` for all edit/write/patch tools, and `subagent` for child
|
||||
agents. Other tools generally use their tool name, such as `read`, `glob`,
|
||||
`grep`, `webfetch`, `websearch`, and `skill`.
|
||||
|
||||
<Tip>
|
||||
Put broad wildcard rules first and exceptions afterward. For example, deny
|
||||
all subagents first, then allow `explore`.
|
||||
</Tip>
|
||||
|
||||
`~` and `$HOME` are expanded in filesystem resources for `read`, `edit`, and
|
||||
`external_directory`. Shell resources are raw command text and are not
|
||||
expanded.
|
||||
|
||||
### `steps`
|
||||
|
||||
Sets a positive maximum number of model steps. On the final allowed step,
|
||||
OpenCode removes tools and asks the model to summarize its work in text. New
|
||||
user input resets the allowance.
|
||||
|
||||
### `hidden`
|
||||
|
||||
When `true`, removes the agent from normal selectors, `@` autocomplete, and the
|
||||
subagent catalog advertised to models. It is a visibility setting, not a
|
||||
security boundary.
|
||||
|
||||
### `color`
|
||||
|
||||
Sets the agent's UI color. Use a six-digit hex color such as `#ff6b6b`, or one
|
||||
of `primary`, `secondary`, `accent`, `success`, `warning`, `error`, or `info`.
|
||||
|
||||
### `disabled`
|
||||
|
||||
When `true`, removes the agent definition at that point in configuration
|
||||
loading. This works for built-in and custom agents.
|
||||
|
||||
### `request`
|
||||
|
||||
The V2 schema accepts per-agent request `headers` and JSON `body` overlays:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"agents": {
|
||||
"reviewer": {
|
||||
"request": {
|
||||
"headers": { "x-agent": "reviewer" },
|
||||
"body": { "temperature": 0.1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Warning>
|
||||
The current V2 session runner preserves these overlays on the agent
|
||||
definition but does not yet apply them to model requests. Configure effective
|
||||
request settings on the provider, model, or model variant instead. Do not use
|
||||
legacy top-level agent fields such as `temperature`, `top_p`, `prompt`,
|
||||
`permission`, `tools`, `disable`, or `maxSteps` in new V2 configuration.
|
||||
</Warning>
|
||||
168
packages/docs/attachments.mdx
Normal file
168
packages/docs/attachments.mdx
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
---
|
||||
title: "Attachments"
|
||||
description: "Attach supported files and images to V2 prompts and configure image processing."
|
||||
---
|
||||
|
||||
OpenCode can add local context to a prompt as text or image media. Current V2
|
||||
sessions make these attachment types visible to the model:
|
||||
|
||||
| Input | Model receives |
|
||||
| --- | --- |
|
||||
| UTF-8 text file | The filename and decoded text |
|
||||
| Directory | A non-recursive listing of its immediate files and directories |
|
||||
| PNG, JPEG, GIF, or WebP | Image media |
|
||||
|
||||
SVG files are treated as text, not image media. PDF, AVIF, BMP, audio, video,
|
||||
and other binary prompt attachments are not currently included in the model
|
||||
request. Some clients may let you select a PDF, but V2 does not yet make that
|
||||
PDF visible to the model.
|
||||
|
||||
<Warning>
|
||||
Use a model that supports image input before attaching an image. OpenCode
|
||||
passes supported image media to the selected provider, but the provider and
|
||||
model still enforce their own formats, dimensions, file counts, and size
|
||||
limits. A text-only model may reject the request.
|
||||
</Warning>
|
||||
|
||||
## Add attachments
|
||||
|
||||
### TUI
|
||||
|
||||
Type `@` followed by a filename and select the result to attach a project file.
|
||||
This is the preferred way to add source code and other text files:
|
||||
|
||||
```text
|
||||
Explain the error handling in @src/server.ts
|
||||
```
|
||||
|
||||
Paste an image from the clipboard with the configured paste key, `Ctrl+V` by
|
||||
default. You can also drag a supported image into a terminal that exposes the
|
||||
dropped file path to the TUI. The TUI reads PNG, JPEG, GIF, and WebP as image
|
||||
attachments; a dropped SVG is inserted as text.
|
||||
|
||||
### Desktop and web
|
||||
|
||||
Use **Attach file**, paste, or drag and drop. Attach UTF-8 text or a PNG, JPEG,
|
||||
GIF, or WebP image. The desktop file picker limits one selection to 20 MiB in
|
||||
total; the server also applies the per-attachment limit described below.
|
||||
|
||||
### CLI
|
||||
|
||||
Pass `--file` or `-f` to `opencode2 run`. Repeat the flag for multiple files:
|
||||
|
||||
```bash
|
||||
opencode2 run -f src/server.ts -f screenshot.png "Explain the failure"
|
||||
```
|
||||
|
||||
The run command accepts at most 100 file flags and reads at most 10 MiB per
|
||||
file. Use it for text files and the four supported image formats; other binary
|
||||
files do not become model context.
|
||||
|
||||
### API
|
||||
|
||||
The V2 prompt and command payloads accept a `files` array. Each item requires a
|
||||
`uri` and can include `name` and `description`:
|
||||
|
||||
```bash
|
||||
opencode2 api post /api/session/ses_example/prompt --data '{
|
||||
"text": "Review this file",
|
||||
"files": [
|
||||
{
|
||||
"uri": "file:///home/me/project/src/server.ts",
|
||||
"name": "server.ts",
|
||||
"description": "Request handler"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
Use an absolute `file:` URL for a file available to the server, or an inline
|
||||
data URL:
|
||||
|
||||
```json
|
||||
{
|
||||
"text": "What is wrong with this layout?",
|
||||
"files": [
|
||||
{
|
||||
"uri": "data:image/png;base64,<base64-data>",
|
||||
"name": "layout.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
HTTP and HTTPS attachment URLs are not supported. OpenCode materializes each
|
||||
attachment before admitting the prompt and rejects invalid URLs, unreadable
|
||||
paths, non-files other than directories, and attachments over 20 MiB decoded.
|
||||
For a text `file:` URL, optional positive `start` and `end` query parameters
|
||||
select one-based lines:
|
||||
|
||||
```text
|
||||
file:///home/me/project/src/server.ts?start=20&end=60
|
||||
```
|
||||
|
||||
The server infers the media type from the bytes. A supplied filename or data
|
||||
URL media type does not make an unsupported binary format model-visible.
|
||||
|
||||
## Configure image processing
|
||||
|
||||
Configure image normalization in `opencode.json` or `opencode.jsonc`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"attachments": {
|
||||
"image": {
|
||||
"auto_resize": true,
|
||||
"max_width": 2000,
|
||||
"max_height": 2000,
|
||||
"max_base64_bytes": 5242880
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
All fields are optional:
|
||||
|
||||
| Field | Default | Behavior |
|
||||
| --- | ---: | --- |
|
||||
| `auto_resize` | `true` | Resize an image that exceeds any configured limit. If `false`, reject it. |
|
||||
| `max_width` | `2000` | Maximum width in pixels. Must be a positive integer. |
|
||||
| `max_height` | `2000` | Maximum height in pixels. Must be a positive integer. |
|
||||
| `max_base64_bytes` | `5242880` | Maximum byte length of the Base64-encoded image string. Must be a positive integer. |
|
||||
|
||||
<Note>
|
||||
In the current V2 runtime, these settings apply to image media produced by
|
||||
the built-in `read` tool. Images attached directly through the TUI, desktop,
|
||||
web, CLI, or API bypass this normalization. Resize direct attachments before
|
||||
adding them if the provider requires smaller media.
|
||||
</Note>
|
||||
|
||||
The `read` tool recognizes PNG, JPEG, GIF, and WebP by their contents and will
|
||||
ingest at most 20 MiB of source image bytes. It decodes the image and compares
|
||||
its width, height, and encoded Base64 length with all three configured limits.
|
||||
|
||||
When `auto_resize` is `true`, OpenCode preserves the aspect ratio, scales the
|
||||
image down to the dimension limits, and tries progressively smaller PNG and
|
||||
JPEG encodings until the Base64 limit is met. The resulting media type can
|
||||
therefore change to PNG or JPEG. If no encoding fits, the tool call fails.
|
||||
|
||||
When `auto_resize` is `false`, exceeding any limit fails the tool call without
|
||||
modifying the image. An image that cannot be decoded also fails. If the image
|
||||
resizer cannot be loaded, the `read` tool returns the
|
||||
original image instead, so these settings are processing limits rather than an
|
||||
upload or security boundary.
|
||||
|
||||
## Limits and provider behavior
|
||||
|
||||
- Direct prompt attachments are limited to 20 MiB decoded per item by the V2
|
||||
server. Client-specific limits can be lower.
|
||||
- `max_base64_bytes` counts the encoded Base64 characters in bytes, not the
|
||||
decoded file size and not the complete `data:` URL.
|
||||
- Text attachments are inserted into the prompt as text and do not require a
|
||||
multimodal model. Large text read through the `read` tool has separate
|
||||
paging and truncation limits.
|
||||
- Image attachments use provider-native image input. Provider errors can still
|
||||
occur when OpenCode's limits pass but the selected model's limits do not.
|
||||
- PDFs and other unsupported binary prompt attachments should be converted to
|
||||
text or supported images before attaching them.
|
||||
164
packages/docs/commands.mdx
Normal file
164
packages/docs/commands.mdx
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
---
|
||||
title: "Commands"
|
||||
description: "Create reusable slash commands from configuration or Markdown files."
|
||||
---
|
||||
|
||||
Custom commands turn a named prompt template into a slash command. Type the
|
||||
command in the TUI, followed by any arguments:
|
||||
|
||||
```text
|
||||
/review src/auth
|
||||
```
|
||||
|
||||
## Configure with JSON
|
||||
|
||||
Add commands under the plural `commands` key in any OpenCode JSON or JSONC
|
||||
[configuration file](/config). Each entry's key is the command name and
|
||||
`template` is required.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"commands": {
|
||||
"review": {
|
||||
"description": "Review code for correctness and missing tests",
|
||||
"template": "Review $ARGUMENTS. Report bugs first, then missing tests.",
|
||||
"agent": "plan",
|
||||
"model": "anthropic/claude-sonnet-4-5#high"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Run it with:
|
||||
|
||||
```text
|
||||
/review src/auth
|
||||
```
|
||||
|
||||
## Configure with Markdown
|
||||
|
||||
OpenCode discovers `.md` command files in both the singular `command/` and
|
||||
plural `commands/` directories:
|
||||
|
||||
```text
|
||||
~/.config/opencode/commands/ # Global
|
||||
.opencode/commands/ # Project
|
||||
```
|
||||
|
||||
The equivalent `command/` paths also work. Files may be nested; for example,
|
||||
`.opencode/commands/team/review.md` defines `/team/review`. Files with other
|
||||
extensions, including `.mdx`, are not discovered.
|
||||
|
||||
```md title=".opencode/commands/review.md"
|
||||
---
|
||||
description: Review code for correctness and missing tests
|
||||
agent: plan
|
||||
model: anthropic/claude-sonnet-4-5#high
|
||||
---
|
||||
|
||||
Review $ARGUMENTS. Report bugs first, then missing tests.
|
||||
```
|
||||
|
||||
The file body, with surrounding whitespace removed, is the command template.
|
||||
JSON and Markdown commands share one registry. Project definitions take
|
||||
precedence over global definitions, and a later definition can override a
|
||||
built-in or earlier command with the same name. Changes are reloaded
|
||||
automatically.
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Required | Behavior |
|
||||
| --- | --- | --- |
|
||||
| `template` | JSON only | Prompt template. In a Markdown command, the file body supplies it. |
|
||||
| `description` | No | Text shown with the command in autocomplete. |
|
||||
| `agent` | No | Agent selected before the prompt runs. |
|
||||
| `model` | No | Model override in `provider/model` or `provider/model#variant` format. |
|
||||
| `subtask` | No | Accepted as a boolean, but currently has no execution effect in V2. |
|
||||
|
||||
The four optional fields can be used in JSON or YAML frontmatter. Do not put
|
||||
`template` in frontmatter because the Markdown body always supplies it.
|
||||
|
||||
## Arguments
|
||||
|
||||
Use `$ARGUMENTS` for the complete argument string:
|
||||
|
||||
```md title=".opencode/commands/component.md"
|
||||
---
|
||||
description: Create a component
|
||||
---
|
||||
|
||||
Create a typed React component named $ARGUMENTS.
|
||||
```
|
||||
|
||||
```text
|
||||
/component Button
|
||||
```
|
||||
|
||||
Use `$1`, `$2`, and higher numbers for parsed positional arguments. Single and
|
||||
double quotes group text containing spaces and are removed during parsing.
|
||||
|
||||
```md title=".opencode/commands/check.md"
|
||||
---
|
||||
description: Check one area with a specific focus
|
||||
---
|
||||
|
||||
Check $1. Focus on $2.
|
||||
```
|
||||
|
||||
```text
|
||||
/check src/auth "error handling and missing tests"
|
||||
```
|
||||
|
||||
The highest-numbered positional placeholder present in the template consumes
|
||||
that argument and all remaining arguments. For example, if a template contains
|
||||
only `$1`, then `$1` receives the full parsed argument list. Missing positions
|
||||
become empty strings.
|
||||
|
||||
If a template contains neither positional placeholders nor `$ARGUMENTS`,
|
||||
OpenCode appends non-empty arguments to the template after a blank line.
|
||||
|
||||
## Shell interpolation
|
||||
|
||||
Wrap a shell command in `!` followed by backticks to insert its output before
|
||||
the prompt is submitted:
|
||||
|
||||
```md title=".opencode/commands/review-diff.md"
|
||||
---
|
||||
description: Review the current diff
|
||||
---
|
||||
|
||||
Review this diff:
|
||||
|
||||
!`git diff --stat && git diff`
|
||||
```
|
||||
|
||||
OpenCode runs each interpolation with the configured shell in the active
|
||||
project location and inserts its combined output into the template. Argument
|
||||
interpolation happens first, so avoid placing untrusted arguments inside shell
|
||||
interpolations.
|
||||
|
||||
<Warning>
|
||||
Shell interpolations run when the command is evaluated, outside the agent's
|
||||
tool permission flow. Only use commands from sources you trust.
|
||||
</Warning>
|
||||
|
||||
No other template interpolation is performed. In particular, an `@path`
|
||||
written into a stored template remains ordinary prompt text; V2 does not
|
||||
automatically attach that file.
|
||||
|
||||
## Agent, model, and execution
|
||||
|
||||
Running a command evaluates its arguments and shell blocks, submits the result
|
||||
as a durable user prompt in the current session, and schedules normal model
|
||||
execution.
|
||||
|
||||
If `agent` is set, it overrides the agent selected when the command was
|
||||
invoked and becomes the session's active agent. If `model` is set, it overrides
|
||||
the model. Otherwise, a model configured on the command's agent takes
|
||||
precedence over the model selected at invocation.
|
||||
|
||||
Although `subtask` is accepted in JSON and frontmatter, V2 currently ignores
|
||||
it: commands run in the current session and do not create a child session.
|
||||
Selecting an agent whose mode is `subagent` also does not turn the command into
|
||||
a subtask.
|
||||
151
packages/docs/compaction.mdx
Normal file
151
packages/docs/compaction.mdx
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
---
|
||||
title: "Context compaction"
|
||||
description: "Configure and run context compaction in OpenCode V2."
|
||||
---
|
||||
|
||||
Compaction replaces the active model context from an older part of a session
|
||||
with a generated checkpoint. The checkpoint contains a structured summary and
|
||||
a serialized tail of recent context, so the agent can continue with more room
|
||||
in the model's context window.
|
||||
|
||||
Compaction is lossy, but it does not delete the earlier durable session
|
||||
messages. After a successful compaction, V2 builds model requests from the
|
||||
latest completed checkpoint and the messages that follow it.
|
||||
|
||||
## Automatic compaction
|
||||
|
||||
Automatic compaction is enabled by default. Before a model call, V2 estimates
|
||||
the size of the final system prompt, messages, and advertised tools. It starts
|
||||
compaction when:
|
||||
|
||||
```text
|
||||
estimated tokens > context limit - max(requested output tokens, buffer)
|
||||
```
|
||||
|
||||
The estimate is approximate: V2 JSON-serializes the request and assumes four
|
||||
characters per token. When compaction succeeds, V2 rebuilds the request from
|
||||
the new checkpoint and retries the step without promoting the input again.
|
||||
|
||||
V2 also recognizes provider errors classified as context overflow. If an
|
||||
overflow occurs before the provider produces assistant output or other retry
|
||||
evidence, V2 can compact and retry that step once. This recovery is attempted
|
||||
even when `auto` is `false`; `auto` controls only the preflight size check. A
|
||||
second overflow after recovery is returned as an error.
|
||||
|
||||
## Manual compaction
|
||||
|
||||
In the TUI, run:
|
||||
|
||||
```text
|
||||
/compact
|
||||
```
|
||||
|
||||
`/summarize` is an alias. The default keybind is `<leader>c`, configured as
|
||||
`session_compact`.
|
||||
|
||||
A manual request is durably admitted and wakes the session runner. It can
|
||||
compact short histories that would not trigger automatic compaction. If the
|
||||
session is busy, compaction runs at the next safe drain boundary before later
|
||||
steered or queued prompts are promoted. Repeated requests while one is pending
|
||||
coalesce into that pending request. Whether compaction completes or fails, the
|
||||
barrier is then settled so later prompts can proceed.
|
||||
|
||||
The CLI has no separate `compact` subcommand. Use the TUI command or the server
|
||||
API. For example:
|
||||
|
||||
```bash
|
||||
opencode2 api v2.session.compact \
|
||||
--param sessionID=ses_example \
|
||||
--data '{}'
|
||||
```
|
||||
|
||||
The equivalent raw request is:
|
||||
|
||||
```bash
|
||||
opencode2 api post /api/session/ses_example/compact --data '{}'
|
||||
```
|
||||
|
||||
`POST /api/session/:sessionID/compact` returns the admitted compaction input;
|
||||
it does not wait for summary generation. Clients can call
|
||||
`client.session.compact({ sessionID })` and then wait for the session or follow
|
||||
the `session.compaction.*` events. Supplying an optional message `id` makes an
|
||||
exact retry idempotent, but reusing an ID owned by another record returns a
|
||||
conflict.
|
||||
|
||||
## Configuration
|
||||
|
||||
Add `compaction` to any [OpenCode configuration file](/config):
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"compaction": {
|
||||
"auto": true,
|
||||
"prune": false,
|
||||
"keep": {
|
||||
"tokens": 8000
|
||||
},
|
||||
"buffer": 20000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Default | V2 behavior |
|
||||
| --- | ---: | --- |
|
||||
| `auto` | `true` | Runs the preflight context-size check. It does not disable manual compaction or one-shot provider-overflow recovery. |
|
||||
| `prune` | None | Accepted by the V2 schema, but currently has no runtime effect. V2 does not prune old tool outputs in place. |
|
||||
| `keep.tokens` | `8000` | Approximate number of tokens from the newest serialized conversation context to retain beside the summary. |
|
||||
| `buffer` | `20000` | Token reserve used by the automatic threshold. The requested model output allowance wins when it is larger. |
|
||||
|
||||
`keep.tokens` and `buffer` accept non-negative integers. Larger `keep.tokens`
|
||||
preserves more recent detail but leaves less room for future work. Larger
|
||||
`buffer` triggers preflight compaction earlier.
|
||||
|
||||
## Checkpoint contents
|
||||
|
||||
V2 uses the session's selected or default model to generate the summary, with
|
||||
tools disabled and at most 4096 output tokens. The summary records the
|
||||
objective, important details, completed and active work, blockers, next moves,
|
||||
and relevant files.
|
||||
|
||||
The newest serialized context up to `keep.tokens` is retained separately. This
|
||||
is not a byte-for-byte transcript: tool output is limited to 2000 characters,
|
||||
and file or media attachments become textual descriptors rather than embedded
|
||||
data. On later compactions, V2 updates the previous summary and carries forward
|
||||
its retained recent context before selecting a new tail.
|
||||
|
||||
The completed checkpoint is presented to the model as historical conversation
|
||||
context, explicitly not as new instructions. Running and failed compactions are
|
||||
not included in model context.
|
||||
|
||||
## Instructions and checkpoints
|
||||
|
||||
Conversation compaction and the durable instruction checkpoint are separate.
|
||||
Before each model step, V2 compares live instruction sources with what that
|
||||
session's model was last told. Ordinary changes are durable chronological
|
||||
system updates and do not rewrite the established instruction baseline.
|
||||
|
||||
After a completed compaction, the next model step creates a fresh instruction
|
||||
baseline from current sources. If a source is temporarily unavailable, V2
|
||||
restates the last-applied value instead of treating it as removed. Session
|
||||
movement and a committed revert reset the instruction checkpoint as well. See
|
||||
[Instructions](/instructions) for source ordering and update behavior.
|
||||
|
||||
## Current limitations
|
||||
|
||||
- `prune` is reserved configuration; V1-style in-place tool-output pruning is
|
||||
not implemented in V2.
|
||||
- Compaction requires a resolvable model with a positive catalog context limit.
|
||||
There is no separate compaction-model setting or fallback model.
|
||||
- Summary generation can fail if the summary prompt itself cannot fit beside
|
||||
its output allowance, the model returns no summary, or the provider fails.
|
||||
- Automatic and overflow compaction need older conversation context that can be
|
||||
replaced. A provider overflow can still surface when there is no compressible
|
||||
head or fixed instructions and tool schemas dominate the request.
|
||||
- Overflow recovery retries only once per step. Token estimation is heuristic,
|
||||
so it cannot prevent every provider-specific overflow.
|
||||
- Earlier durable messages remain stored even though they are no longer in the
|
||||
active model context.
|
||||
|
||||
V1 used additional tail-turn and pruning behavior. Those V1 details are only
|
||||
migration context; the settings and behavior on this page describe V2.
|
||||
|
|
@ -44,8 +44,12 @@ Project-specific configuration can use either form:
|
|||
```
|
||||
|
||||
When OpenCode starts, it searches for configuration files from the current
|
||||
directory upward to the project root. The files are merged, and configuration
|
||||
closer to the current directory takes precedence.
|
||||
directory upward to the project root. It merges direct `opencode.json(c)` files
|
||||
from the project root toward the current directory, then does the same for
|
||||
files inside `.opencode` directories. A `.opencode` config therefore overrides
|
||||
every direct config, even when the direct config is closer to the current
|
||||
directory. Avoid mixing the two forms across one project hierarchy unless this
|
||||
precedence is intentional.
|
||||
|
||||
For example, consider a monorepo with OpenCode started from
|
||||
`/home/user/projects/acme/packages/web`:
|
||||
|
|
@ -67,9 +71,9 @@ OpenCode applies these files from lowest to highest precedence:
|
|||
2. `/home/user/projects/acme/opencode.json`
|
||||
3. `/home/user/projects/acme/packages/web/opencode.json`
|
||||
|
||||
Settings in the package config override matching settings from the repository
|
||||
config, which override matching settings from the global config. Settings that
|
||||
do not conflict are preserved from every file.
|
||||
In this direct-config example, the package config overrides matching settings
|
||||
from the repository config, which overrides matching settings from the global
|
||||
config. Settings that do not conflict are preserved from every file.
|
||||
|
||||
## Schema
|
||||
|
||||
|
|
@ -100,16 +104,16 @@ Set the shell used by the terminal and shell tools.
|
|||
|
||||
### Model
|
||||
|
||||
Set the default model in `provider/model` format. Add `#variant` to select a
|
||||
specific model variant.
|
||||
Set the default model in `provider/model` format. The root default currently
|
||||
does not retain a `#variant`; select variants in the TUI or on an agent or command.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"model": "anthropic/claude-sonnet-4-5#high"
|
||||
"model": "anthropic/claude-sonnet-4-5"
|
||||
}
|
||||
```
|
||||
|
||||
See the [models guide](https://opencode.ai/docs/models/) for model selection
|
||||
See the [models guide](/models) for model selection
|
||||
and local models.
|
||||
|
||||
### Default agent
|
||||
|
|
@ -122,13 +126,15 @@ Choose the primary agent used when a session does not select one explicitly.
|
|||
}
|
||||
```
|
||||
|
||||
See the [agents guide](https://opencode.ai/docs/agents/) for built-in and custom
|
||||
See the [agents guide](/agents) for built-in and custom
|
||||
agents.
|
||||
|
||||
### Autoupdate
|
||||
|
||||
Control automatic updates. Set this to `false` to disable updates or `"notify"`
|
||||
to receive update notifications.
|
||||
Control automatic updates from the global config. Set this to `false` to
|
||||
disable updates. The current beta treats `true` and `"notify"` identically and
|
||||
automatically installs compatible non-major updates; project-level values are
|
||||
ignored.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -138,8 +144,8 @@ to receive update notifications.
|
|||
|
||||
### Sharing
|
||||
|
||||
Control whether sessions can be shared manually, shared automatically, or not
|
||||
shared at all.
|
||||
Set the intended session sharing policy. V2 accepts this field, but session
|
||||
sharing is not implemented yet.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -147,11 +153,12 @@ shared at all.
|
|||
}
|
||||
```
|
||||
|
||||
See the [sharing guide](https://opencode.ai/docs/share/) for more details.
|
||||
See the [sharing guide](/sharing) for more details.
|
||||
|
||||
### Username
|
||||
|
||||
Set the username displayed in conversations.
|
||||
Set a username for future display behavior. V2 accepts this field but does not
|
||||
currently display it in conversations.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -168,7 +175,7 @@ matching resource.
|
|||
{
|
||||
"permissions": [
|
||||
{
|
||||
"action": "bash",
|
||||
"action": "shell",
|
||||
"resource": "git push *",
|
||||
"effect": "ask"
|
||||
}
|
||||
|
|
@ -176,8 +183,7 @@ matching resource.
|
|||
}
|
||||
```
|
||||
|
||||
See the [permissions guide](https://opencode.ai/docs/permissions/) for rule
|
||||
matching and available actions.
|
||||
See the [permissions guide](/permissions) for rule matching and available actions.
|
||||
|
||||
### Agents
|
||||
|
||||
|
|
@ -199,12 +205,11 @@ instructions, mode, and permissions.
|
|||
}
|
||||
```
|
||||
|
||||
See the [agents guide](https://opencode.ai/docs/agents/) for all agent options
|
||||
and file-based agents.
|
||||
See the [agents guide](/agents) for all agent options and file-based agents.
|
||||
|
||||
### Snapshots
|
||||
|
||||
Enable or disable the snapshots used by undo and revert behavior.
|
||||
Enable or disable filesystem snapshots used by undo and revert behavior.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -212,6 +217,8 @@ Enable or disable the snapshots used by undo and revert behavior.
|
|||
}
|
||||
```
|
||||
|
||||
See the [snapshots guide](/snapshots) for undo and redo behavior.
|
||||
|
||||
### Watcher
|
||||
|
||||
Ignore files and directories that should not trigger filesystem updates.
|
||||
|
|
@ -226,8 +233,8 @@ Ignore files and directories that should not trigger filesystem updates.
|
|||
|
||||
### Formatter
|
||||
|
||||
Enable built-in formatters, disable formatting entirely, or configure formatter
|
||||
commands by name.
|
||||
Define formatter settings for compatibility and future use. V2 accepts this
|
||||
field, but it does not run formatters yet.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -240,12 +247,12 @@ commands by name.
|
|||
}
|
||||
```
|
||||
|
||||
See the [formatters guide](https://opencode.ai/docs/formatters/) for built-in
|
||||
formatters and custom commands.
|
||||
See the [formatters guide](/formatters) for accepted fields and current limitations.
|
||||
|
||||
### LSP
|
||||
|
||||
Enable built-in language servers, disable them, or configure servers by name.
|
||||
Define language server settings for compatibility and future use. V2 accepts
|
||||
this field, but it does not start language servers yet.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -258,12 +265,12 @@ Enable built-in language servers, disable them, or configure servers by name.
|
|||
}
|
||||
```
|
||||
|
||||
See the [LSP guide](https://opencode.ai/docs/lsp/) for language server setup.
|
||||
See the [LSP guide](/lsp) for accepted fields and current limitations.
|
||||
|
||||
### Attachments
|
||||
|
||||
Control how oversized image attachments are resized or rejected before they are
|
||||
sent to a model.
|
||||
Control how oversized images loaded by the `read` tool are resized or rejected
|
||||
before they are sent to a model.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -278,6 +285,8 @@ sent to a model.
|
|||
}
|
||||
```
|
||||
|
||||
See the [attachments guide](/attachments) for image processing and limits.
|
||||
|
||||
### Tool output
|
||||
|
||||
Set the maximum number of lines and bytes retained from a tool result.
|
||||
|
|
@ -309,8 +318,7 @@ be overridden by an individual server.
|
|||
}
|
||||
```
|
||||
|
||||
See the [MCP guide](https://opencode.ai/docs/mcp-servers/) for remote servers,
|
||||
OAuth, environment variables, and timeouts.
|
||||
See the [MCP guide](/mcp) for remote servers, OAuth, environment variables, and timeouts.
|
||||
|
||||
### Compaction
|
||||
|
||||
|
|
@ -328,6 +336,8 @@ Control automatic context compaction and how much recent context it preserves.
|
|||
}
|
||||
```
|
||||
|
||||
See the [compaction guide](/compaction) for automatic context management.
|
||||
|
||||
### Skills
|
||||
|
||||
Add directories or URLs that OpenCode should search for agent skills.
|
||||
|
|
@ -338,8 +348,7 @@ Add directories or URLs that OpenCode should search for agent skills.
|
|||
}
|
||||
```
|
||||
|
||||
See the [skills guide](https://opencode.ai/docs/skills/) for skill structure and
|
||||
automatic discovery under `.opencode/skills/`.
|
||||
See the [skills guide](/skills) for skill structure and automatic discovery under `.opencode/skills/`.
|
||||
|
||||
### Commands
|
||||
|
||||
|
|
@ -356,12 +365,12 @@ Define reusable slash commands as named prompt templates.
|
|||
}
|
||||
```
|
||||
|
||||
See the [commands guide](https://opencode.ai/docs/commands/) for arguments,
|
||||
models, agents, and file-based commands.
|
||||
See the [commands guide](/commands) for arguments, models, agents, and file-based commands.
|
||||
|
||||
### Instructions
|
||||
|
||||
Load additional instruction files, globs, or URLs into the agent's context.
|
||||
Declare additional instruction files, globs, or URLs. V2 accepts this field,
|
||||
but does not load these entries yet; use `AGENTS.md` for active instructions.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
|
|
@ -369,8 +378,7 @@ Load additional instruction files, globs, or URLs into the agent's context.
|
|||
}
|
||||
```
|
||||
|
||||
See the [rules guide](https://opencode.ai/docs/rules/) for project instructions
|
||||
and `AGENTS.md`.
|
||||
See the [instructions guide](/instructions) for project instructions and `AGENTS.md`.
|
||||
|
||||
### References
|
||||
|
||||
|
|
@ -392,8 +400,7 @@ context.
|
|||
}
|
||||
```
|
||||
|
||||
See the [references guide](https://opencode.ai/docs/references/) for shorthand,
|
||||
visibility, and path resolution.
|
||||
See the [references guide](/references) for shorthand, visibility, and path resolution.
|
||||
|
||||
### Plugins
|
||||
|
||||
|
|
@ -440,5 +447,4 @@ headers, and model variants.
|
|||
}
|
||||
```
|
||||
|
||||
See the [providers guide](https://opencode.ai/docs/providers/) for credentials,
|
||||
custom endpoints, provider packages, and model configuration.
|
||||
See the [providers guide](/providers) for credentials, custom endpoints, provider packages, and model configuration.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,32 @@
|
|||
"groups": [
|
||||
{
|
||||
"group": "Get started",
|
||||
"pages": ["index", "config", "plugins", "troubleshooting"]
|
||||
"pages": ["index", "config", "troubleshooting"]
|
||||
},
|
||||
{
|
||||
"group": "Migrate from V1",
|
||||
"pages": ["migrate-v1"]
|
||||
},
|
||||
{
|
||||
"group": "Configure",
|
||||
"pages": [
|
||||
"models",
|
||||
"providers",
|
||||
"agents",
|
||||
"permissions",
|
||||
"sharing",
|
||||
"snapshots",
|
||||
"commands",
|
||||
"skills",
|
||||
"instructions",
|
||||
"mcp",
|
||||
"attachments",
|
||||
"compaction",
|
||||
"formatters",
|
||||
"lsp",
|
||||
"references",
|
||||
"plugins"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
93
packages/docs/formatters.mdx
Normal file
93
packages/docs/formatters.mdx
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
---
|
||||
title: "Formatters"
|
||||
description: "Configure formatter settings and understand formatter support in OpenCode V2."
|
||||
---
|
||||
|
||||
OpenCode V2 accepts formatter configuration, but it does not yet include a
|
||||
formatter runtime. File writes and edits are not automatically formatted.
|
||||
|
||||
<Warning>
|
||||
V2 currently has no built-in formatters. The built-in formatter list and
|
||||
automatic post-edit formatting documented for V1 do not apply to V2.
|
||||
</Warning>
|
||||
|
||||
## Configuration
|
||||
|
||||
The `formatter` field accepts a boolean or an object keyed by formatter name:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"formatter": {
|
||||
"prettier": {
|
||||
"disabled": false,
|
||||
"command": ["prettier", "--write", "$FILE"],
|
||||
"environment": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"extensions": [".js", ".jsx", ".ts", ".tsx"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This example is valid V2 configuration, but V2 does not currently execute the
|
||||
command.
|
||||
|
||||
Each named formatter entry supports these optional fields:
|
||||
|
||||
| Field | Type | Current V2 behavior |
|
||||
| --- | --- | --- |
|
||||
| `disabled` | `boolean` | Accepted, but there is no runtime formatter to enable or disable. |
|
||||
| `command` | `string[]` | Accepted as an argument array, but not executed. |
|
||||
| `environment` | `Record<string, string>` | Accepts string environment variable names and values, but they are not applied. |
|
||||
| `extensions` | `string[]` | Accepted without extension-specific validation, but files are not matched against it. |
|
||||
|
||||
All entry fields are optional. The schema therefore also accepts an empty entry
|
||||
such as `"prettier": {}`.
|
||||
|
||||
## Enable and disable
|
||||
|
||||
The schema accepts all of the following forms:
|
||||
|
||||
```jsonc
|
||||
// Omit `formatter`, or use false, when formatting is not requested.
|
||||
{
|
||||
"formatter": false
|
||||
}
|
||||
```
|
||||
|
||||
```jsonc
|
||||
// Reserved for enabling all built-ins once a V2 runtime provides them.
|
||||
{
|
||||
"formatter": true
|
||||
}
|
||||
```
|
||||
|
||||
```jsonc
|
||||
// Configure named entries or mark one as disabled.
|
||||
{
|
||||
"formatter": {
|
||||
"prettier": { "disabled": true },
|
||||
"custom": {
|
||||
"command": ["custom-fmt", "$FILE"],
|
||||
"extensions": [".foo"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
At present, omitted, `false`, `true`, and object forms have the same runtime
|
||||
result: V2 runs no formatter. `disabled` is retained as configuration data but
|
||||
does not control an executable formatter.
|
||||
|
||||
## Commands and placeholders
|
||||
|
||||
`command` is an array of strings, not a shell command string. `$FILE` is the V1
|
||||
file-path placeholder and is often retained in migrated configuration. V2 does
|
||||
not currently substitute `$FILE` or define another formatter placeholder.
|
||||
|
||||
Likewise, V2 does not currently use `extensions` to select commands, merge
|
||||
`environment` into a child process, discover formatter executables or project
|
||||
configuration, or run multiple matching formatters. These behaviors will only
|
||||
be available after a V2 formatter runtime is implemented.
|
||||
|
|
@ -3,6 +3,11 @@ title: "Intro"
|
|||
description: "Get started with OpenCode."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
These docs are for the beta version of OpenCode, which will become OpenCode 2.0. The beta is still changing: we may
|
||||
wipe your data, things may break, and APIs, configuration, and plugin APIs may change.
|
||||
</Warning>
|
||||
|
||||
[**OpenCode**](https://opencode.ai) is an open source AI coding agent. It's available as a terminal-based interface or
|
||||
desktop app.
|
||||
|
||||
|
|
@ -70,9 +75,9 @@ Arch Linux installation is not available in beta.
|
|||
### Windows
|
||||
|
||||
<Tip>
|
||||
For the best experience on Windows, use [Windows Subsystem for Linux
|
||||
(WSL)](https://opencode.ai/docs/windows-wsl). It provides better performance and full compatibility with OpenCode's
|
||||
features.
|
||||
For the best experience on Windows, install [Windows Subsystem for Linux
|
||||
(WSL)](https://learn.microsoft.com/windows/wsl/install), open your Linux distribution, and use one of the beta package
|
||||
manager commands above.
|
||||
</Tip>
|
||||
|
||||
<Tabs>
|
||||
|
|
@ -110,7 +115,8 @@ If you'd like easy access to all the best coding models you can try out
|
|||
You can also try [OpenCode Go](https://opencode.ai/go) a $10/month subscription
|
||||
plan that grants you access to the best open source models.
|
||||
|
||||
See the current [provider directory](https://opencode.ai/docs/providers#directory).
|
||||
Use `/models` to browse the providers and models available to your project. See [Providers](/providers) for connection and
|
||||
configuration details.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -148,8 +154,10 @@ Use `/undo` when a change isn't what you wanted.
|
|||
/undo
|
||||
```
|
||||
|
||||
OpenCode reverts the changes and restores your original message so you can revise it. Run `/undo` multiple times to undo
|
||||
multiple changes, or use `/redo` to reapply them.
|
||||
OpenCode stages a conversation revert and restores your original message so you can revise it. In a Git repository, it
|
||||
also restores file changes when snapshots were captured successfully. Run `/undo` multiple times to move the conversation
|
||||
boundary back, or use `/redo` to restore the staged conversation and files. See [Snapshots and undo](/snapshots) for
|
||||
limitations and safety details.
|
||||
|
||||
```text
|
||||
/redo
|
||||
|
|
@ -160,5 +168,5 @@ multiple changes, or use `/redo` to reapply them.
|
|||
## Customize
|
||||
|
||||
Make OpenCode your own by [picking a theme](https://opencode.ai/docs/themes), [customizing
|
||||
keybinds](https://opencode.ai/docs/keybinds), [configuring formatters](https://opencode.ai/docs/formatters), [creating
|
||||
commands](https://opencode.ai/docs/commands), or editing the [OpenCode config](https://opencode.ai/docs/config).
|
||||
keybinds](https://opencode.ai/docs/keybinds), [configuring formatters](/formatters), [creating commands](/commands), or
|
||||
editing the [OpenCode config](/config).
|
||||
|
|
|
|||
124
packages/docs/instructions.mdx
Normal file
124
packages/docs/instructions.mdx
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
title: "Instructions"
|
||||
description: "Give OpenCode global, project, and directory-specific guidance."
|
||||
---
|
||||
|
||||
Instructions are privileged context that guide an agent throughout a session.
|
||||
V2 combines built-in context, discovered `AGENTS.md` files, and dynamic sources
|
||||
such as skill, reference, MCP, and session context into a durable instruction
|
||||
baseline.
|
||||
|
||||
## AGENTS.md
|
||||
|
||||
Use `AGENTS.md` for persistent guidance such as build commands, architecture,
|
||||
code conventions, and verification requirements. Commit project files so the
|
||||
whole team receives the same instructions.
|
||||
|
||||
V2 loads:
|
||||
|
||||
1. The global file at `$XDG_CONFIG_HOME/opencode/AGENTS.md`, normally
|
||||
`~/.config/opencode/AGENTS.md`.
|
||||
2. Every `AGENTS.md` from the current Location up to and including the project
|
||||
root.
|
||||
|
||||
For example, when the Location is `packages/web`, OpenCode can load all three
|
||||
project files below:
|
||||
|
||||
```text
|
||||
my-project/
|
||||
├── AGENTS.md
|
||||
└── packages/
|
||||
├── AGENTS.md
|
||||
└── web/
|
||||
└── AGENTS.md
|
||||
```
|
||||
|
||||
The files are combined rather than selecting a single winner. They are rendered
|
||||
in this order: global, then project files from the Location toward the project
|
||||
root. OpenCode does not resolve conflicts between their contents, so keep broad
|
||||
guidance global and put scoped guidance in the relevant project directory.
|
||||
|
||||
If the Location is outside the project root, only the global file is loaded.
|
||||
Setting `OPENCODE_DISABLE_PROJECT_CONFIG=1` also skips project `AGENTS.md`
|
||||
discovery but does not disable the global file.
|
||||
|
||||
<Note>
|
||||
Current V2 discovery only recognizes `AGENTS.md`. The `CLAUDE.md` fallback
|
||||
and related precedence described by older OpenCode documentation do not apply.
|
||||
</Note>
|
||||
|
||||
### Nested instructions
|
||||
|
||||
An `AGENTS.md` below the Location is not part of the initial upward scan. When
|
||||
the read tool successfully reads a file or lists a directory, OpenCode discovers
|
||||
`AGENTS.md` files from that target upward to, but not including, the Location.
|
||||
It adds newly discovered files to the session in nearest-first order.
|
||||
|
||||
Each nested file is injected once per session and recorded in durable session
|
||||
history. Reading the same area again does not inject it again. Consequently,
|
||||
editing an already injected nested `AGENTS.md` does not replace its earlier
|
||||
session entry automatically; start a new session if the updated text must apply
|
||||
immediately.
|
||||
|
||||
## Config entries
|
||||
|
||||
The V2 config schema accepts an `instructions` array of strings:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"instructions": [
|
||||
"CONTRIBUTING.md",
|
||||
"docs/guidelines/*.md",
|
||||
"https://example.com/shared-instructions.md"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Configuration is loaded from global through project-local files. If more than
|
||||
one config defines `instructions`, the highest-precedence, closest config's
|
||||
entire array is selected; arrays are not merged.
|
||||
|
||||
<Warning>
|
||||
V2 currently parses and retains this field but does not resolve its entries
|
||||
into instruction sources. Local files, glob patterns, and HTTP or HTTPS URLs
|
||||
in `instructions` therefore do not reach the model yet. Use `AGENTS.md` for
|
||||
active V2 instructions. URL fetching and timeout behavior documented for V1
|
||||
are not supported by the current V2 implementation.
|
||||
</Warning>
|
||||
|
||||
See [Config](/config) for config locations and general precedence.
|
||||
|
||||
## Ordering
|
||||
|
||||
The selected agent or provider system prompt is sent first. OpenCode then sends
|
||||
the session's instruction baseline, composed in this order:
|
||||
|
||||
1. Built-in environment and date context.
|
||||
2. Ambient `AGENTS.md` discovery.
|
||||
3. Available skill, reference, and MCP guidance.
|
||||
4. Session-specific instruction entries supplied through the API.
|
||||
|
||||
These sources are combined; ordering is not an override mechanism. Nested
|
||||
`AGENTS.md` files discovered by reads are chronological session entries rather
|
||||
than part of the baseline.
|
||||
|
||||
## Changes
|
||||
|
||||
Before each model step, V2 compares live instruction sources with what that
|
||||
session's model was last told:
|
||||
|
||||
- A new or changed ambient `AGENTS.md` aggregate is announced as a system update
|
||||
that replaces the previous ambient aggregate.
|
||||
- Removing all ambient files announces that the previous ambient instructions
|
||||
no longer apply.
|
||||
- A temporary read or discovery failure preserves the session's last known
|
||||
instructions instead of treating them as deleted. If no baseline exists yet,
|
||||
the first model step waits until required sources are available.
|
||||
- Completed conversation compaction creates a fresh baseline from the current
|
||||
sources. Moving a session or committing a revert also resets its instruction
|
||||
checkpoint so the next step establishes a new baseline.
|
||||
|
||||
Updates are durable session history. OpenCode does not rewrite the original
|
||||
baseline on every change; it records the change so subsequent model steps see
|
||||
both the established baseline and the chronological update.
|
||||
105
packages/docs/lsp.mdx
Normal file
105
packages/docs/lsp.mdx
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
title: "LSP"
|
||||
description: "Configure language servers and understand LSP support in OpenCode V2."
|
||||
---
|
||||
|
||||
Language Server Protocol (LSP) integrations can provide code diagnostics,
|
||||
symbols, definitions, references, and other language-aware context.
|
||||
|
||||
<Warning>
|
||||
OpenCode V2 does not yet have an LSP runtime or built-in language servers.
|
||||
The `lsp` configuration is accepted and preserved, but it does not currently
|
||||
start or download servers, expose an LSP tool, or add diagnostics to file tool
|
||||
results.
|
||||
</Warning>
|
||||
|
||||
## Built-in servers
|
||||
|
||||
There are no built-in LSP servers in the current V2 implementation. Setting
|
||||
`lsp` to `true` declares that built-ins should be enabled, but has no runtime
|
||||
effect until V2 provides a server registry and LSP runtime.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"lsp": true
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The `lsp` field accepts a boolean or an object keyed by server name:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"lsp": {
|
||||
"custom-typescript": {
|
||||
"command": ["typescript-language-server", "--stdio"],
|
||||
"extensions": [".ts", ".tsx"],
|
||||
"env": {
|
||||
"TSS_LOG": "-level verbose"
|
||||
},
|
||||
"initialization": {
|
||||
"preferences": {
|
||||
"importModuleSpecifierPreference": "relative"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Each enabled server entry has this shape:
|
||||
|
||||
| Property | Type | Required | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `command` | `string[]` | Yes | Executable followed by any arguments. |
|
||||
| `extensions` | `string[]` | No | File extensions associated with the server, including the leading dot. |
|
||||
| `disabled` | `boolean` | No | Disables the entry when `true`. |
|
||||
| `env` | `Record<string, string>` | No | Environment variables for the server process. The property is named `env`, not `environment`. |
|
||||
| `initialization` | `Record<string, unknown>` | No | Server-specific options for the LSP `initialize` request. |
|
||||
|
||||
The only entry that may omit `command` is the disable-only form:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"lsp": {
|
||||
"typescript": {
|
||||
"disabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Server names are arbitrary. The V2 schema permits `extensions` to be omitted,
|
||||
including for a custom server, although a future runtime will need a way to
|
||||
associate that server with files.
|
||||
|
||||
## Disable LSP
|
||||
|
||||
Omit `lsp` when no configuration is needed. Set it to `false` to explicitly
|
||||
disable the whole integration, including when a lower-priority configuration
|
||||
set it to `true` or supplied an object:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"lsp": false
|
||||
}
|
||||
```
|
||||
|
||||
Use `{ "disabled": true }` under a server name to disable one server while
|
||||
retaining the object form. `OPENCODE_DISABLE_LSP_DOWNLOAD` is not used by V2;
|
||||
V2 currently performs no automatic LSP downloads.
|
||||
|
||||
## Current usage
|
||||
|
||||
V2 loads and validates the configuration shape for compatibility and future
|
||||
integration. It does not currently use LSP when reading, writing, editing, or
|
||||
patching files, and those tools do not notify a language server or return LSP
|
||||
diagnostics.
|
||||
|
||||
For reliable feedback today, have the agent run the project's lint, typecheck,
|
||||
test, or compiler commands. Record those commands in an `AGENTS.md` file or a
|
||||
skill so the agent knows when and where to run them.
|
||||
254
packages/docs/mcp.mdx
Normal file
254
packages/docs/mcp.mdx
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
---
|
||||
title: "MCP servers"
|
||||
description: "Connect local and remote Model Context Protocol servers to OpenCode."
|
||||
---
|
||||
|
||||
OpenCode can connect to [Model Context Protocol](https://modelcontextprotocol.io/) servers and make their tools, prompts, and instructions available to agents. MCP tools consume model context, so enable only the servers you need.
|
||||
|
||||
## Configure servers
|
||||
|
||||
Define each server by a unique name under `mcp.servers` in your [OpenCode configuration](/config). V2 does not place server names directly under `mcp`.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"my-server": {
|
||||
"type": "local",
|
||||
"command": ["npx", "-y", "example-mcp-server"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Servers connect automatically unless `disabled` is `true`. There is no V2 `enabled` field.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"my-server": {
|
||||
"type": "local",
|
||||
"command": ["npx", "-y", "example-mcp-server"],
|
||||
"disabled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As with other configuration, a server in a higher-precedence project config replaces a server with the same name from a lower-precedence config. Use different names when you need separate connections or accounts.
|
||||
|
||||
## Local servers
|
||||
|
||||
A local server is a command that OpenCode starts using the MCP stdio transport.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"everything": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-everything"
|
||||
],
|
||||
"cwd": ".",
|
||||
"environment": {
|
||||
"LOG_LEVEL": "info",
|
||||
"MCP_API_KEY": "{env:MCP_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `type` | Yes | Must be `"local"`. |
|
||||
| `command` | Yes | Executable followed by its arguments. |
|
||||
| `cwd` | No | Process working directory. Relative paths resolve from the workspace directory; the workspace is the default. |
|
||||
| `environment` | No | String environment variables added to the inherited OpenCode process environment. |
|
||||
| `disabled` | No | Set to `true` to prevent the server from connecting. Defaults to `false`. |
|
||||
| `timeout` | No | Per-server timeout overrides. |
|
||||
|
||||
Use `{env:NAME}` to substitute an environment variable while loading config. Shell expressions such as `$NAME` are not expanded in JSON strings.
|
||||
|
||||
## Remote servers
|
||||
|
||||
A remote server uses the MCP Streamable HTTP transport. Its `url` must be a valid absolute URL.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"context7": {
|
||||
"type": "remote",
|
||||
"url": "https://mcp.context7.com/mcp",
|
||||
"oauth": false,
|
||||
"headers": {
|
||||
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `type` | Yes | Must be `"remote"`. |
|
||||
| `url` | Yes | Streamable HTTP endpoint. |
|
||||
| `headers` | No | String HTTP headers sent to the MCP endpoint. |
|
||||
| `oauth` | No | OAuth client settings, or `false` to disable OAuth support. |
|
||||
| `disabled` | No | Set to `true` to prevent the server from connecting. Defaults to `false`. |
|
||||
| `timeout` | No | Per-server timeout overrides. |
|
||||
|
||||
Use `oauth: false` for a server that exclusively uses an API key or another header-based credential.
|
||||
|
||||
## OAuth
|
||||
|
||||
OAuth support is enabled for remote servers unless `oauth` is `false`. OpenCode discovers the authorization server, uses PKCE, refreshes tokens, and attempts dynamic client registration when the server supports it. OAuth credentials are stored outside project configuration.
|
||||
|
||||
For a server that supports dynamic client registration, only the remote server is required:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"sentry": {
|
||||
"type": "remote",
|
||||
"url": "https://mcp.sentry.dev/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When the server reports `needs authentication`, start the browser authorization flow:
|
||||
|
||||
```bash
|
||||
opencode2 mcp auth sentry
|
||||
```
|
||||
|
||||
The command prints the authorization URL and waits for the redirect to OpenCode's loopback callback server.
|
||||
|
||||
If the provider issued client credentials, configure them using V2's snake_case field names:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"company-tools": {
|
||||
"type": "remote",
|
||||
"url": "https://mcp.example.com/mcp",
|
||||
"oauth": {
|
||||
"client_id": "{env:MCP_CLIENT_ID}",
|
||||
"client_secret": "{env:MCP_CLIENT_SECRET}",
|
||||
"scope": "tools:read tools:execute",
|
||||
"callback_port": 19876,
|
||||
"redirect_uri": "http://127.0.0.1:19876/callback"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| OAuth field | Description |
|
||||
| --- | --- |
|
||||
| `client_id` | Pre-registered OAuth client ID. If omitted, OpenCode attempts dynamic client registration. |
|
||||
| `client_secret` | Client secret for a pre-registered client. |
|
||||
| `scope` | Space-delimited scopes to request. |
|
||||
| `callback_port` | Local callback port, from `1` through `65535`. An available ephemeral port is used by default. |
|
||||
| `redirect_uri` | Pre-registered loopback redirect URI. Its path and port must reach the local callback listener. |
|
||||
|
||||
Remove stored credentials with:
|
||||
|
||||
```bash
|
||||
opencode2 mcp logout sentry
|
||||
```
|
||||
|
||||
## Timeouts
|
||||
|
||||
Timeouts are positive integer milliseconds. Configure defaults under `mcp.timeout`; a server's `timeout` fields override matching defaults.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"timeout": {
|
||||
"startup": 45000,
|
||||
"catalog": 30000,
|
||||
"execution": 600000
|
||||
},
|
||||
"servers": {
|
||||
"slow-tools": {
|
||||
"type": "remote",
|
||||
"url": "https://mcp.example.com/mcp",
|
||||
"timeout": {
|
||||
"catalog": 60000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Timeout | Default | Applies to |
|
||||
| --- | --- | --- |
|
||||
| `startup` | 30 seconds | Establishing the transport and initializing the server. |
|
||||
| `catalog` | 30 seconds | Listing tools, prompts, resources, and resource templates. |
|
||||
| `execution` | 12 hours | Calling tools, getting prompts, and reading resources. |
|
||||
|
||||
## Names and permissions
|
||||
|
||||
OpenCode combines the server name and MCP tool name as `<server>_<tool>`. Characters other than letters, numbers, `_`, and `-` are replaced with `_`; for example, server `context 7` and tool `resolve.library/id` become `context_7_resolve_library_id`. MCP prompts appear as slash commands named `<server>:<prompt>` using the same normalization.
|
||||
|
||||
Choose short server names that remain unique after normalization. Under the default Code Mode, MCP tools are grouped by the normalized server name.
|
||||
|
||||
Use permission actions to hide or deny a server's tools without stopping its connection:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"permissions": [
|
||||
{
|
||||
"action": "context7_*",
|
||||
"resource": "*",
|
||||
"effect": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## CLI commands
|
||||
|
||||
V2 provides these MCP management commands:
|
||||
|
||||
```bash
|
||||
# Add a local server to the project config
|
||||
opencode2 mcp add everything --env LOG_LEVEL=info -- npx -y @modelcontextprotocol/server-everything
|
||||
|
||||
# Add a remote server to the project config
|
||||
opencode2 mcp add context7 --url https://mcp.context7.com/mcp --header 'CONTEXT7_API_KEY={env:CONTEXT7_API_KEY}'
|
||||
|
||||
# Add to the global config instead
|
||||
opencode2 mcp add context7 --global --url https://mcp.context7.com/mcp
|
||||
|
||||
# List configured servers and connection status
|
||||
opencode2 mcp list
|
||||
|
||||
# Authenticate or remove OAuth credentials
|
||||
opencode2 mcp auth context7
|
||||
opencode2 mcp logout context7
|
||||
```
|
||||
|
||||
`mcp add` accepts either `--url` for a remote server or a command after `--` for a local server, not both. Use `--header NAME=VALUE` only with remote servers and `--env NAME=VALUE` only with local servers. Edit the config directly for OAuth, timeout, working-directory, or enablement settings.
|
||||
89
packages/docs/migrate-v1.mdx
Normal file
89
packages/docs/migrate-v1.mdx
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
title: "Overview"
|
||||
description: "Move from OpenCode V1 to the OpenCode 2.0 beta."
|
||||
---
|
||||
|
||||
<Warning>
|
||||
OpenCode 2.0 is in beta. Back up important configuration and data before migrating. Beta data may be wiped, features may
|
||||
break, and configuration and plugin APIs may change.
|
||||
</Warning>
|
||||
|
||||
During the beta, OpenCode V1 and V2 use different executable names. You can keep using `opencode` for V1 while trying V2
|
||||
with `opencode2`.
|
||||
|
||||
## Install the beta
|
||||
|
||||
Install the beta from the `next` distribution tag:
|
||||
|
||||
```bash
|
||||
npm install -g @opencode-ai/cli@next
|
||||
```
|
||||
|
||||
Start it in your project with:
|
||||
|
||||
```bash
|
||||
opencode2
|
||||
```
|
||||
|
||||
## Back up your configuration
|
||||
|
||||
Before making changes, back up your global and project configuration files:
|
||||
|
||||
```text
|
||||
~/.config/opencode/opencode.json(c)
|
||||
<project>/opencode.json(c)
|
||||
<project>/.opencode/opencode.json(c)
|
||||
```
|
||||
|
||||
V2 reads these same locations. It detects V1-shaped configuration and translates supported fields in memory without
|
||||
rewriting the source file. Keep shared files in their V1 shape while evaluating both versions; V1 does not understand the
|
||||
native plural V2 fields and may silently ignore them.
|
||||
|
||||
## Update configuration
|
||||
|
||||
Automatic translation is a compatibility aid, not a guarantee that every V1 setting behaves identically. Convert your
|
||||
configuration to the native V2 shape only when you no longer need V1 to read those same files.
|
||||
|
||||
<Note>
|
||||
Do not mix V1 and V2 field names in one file. Back up the V1 file, update the complete working file to the V2 shape, and
|
||||
validate it against the current schema. Restore the V1 copy before using V1 again.
|
||||
</Note>
|
||||
|
||||
The main field changes are:
|
||||
|
||||
| V1 | V2 |
|
||||
| --- | --- |
|
||||
| `permission` | `permissions` |
|
||||
| `agent` and `mode` | `agents` |
|
||||
| `snapshot` | `snapshots` |
|
||||
| `attachment` | `attachments` |
|
||||
| `command` | `commands` |
|
||||
| `reference` | `references` |
|
||||
| `plugin` | `plugins` |
|
||||
| `provider` | `providers` |
|
||||
| Servers directly under `mcp` | Servers under `mcp.servers` |
|
||||
| `skills.paths` and `skills.urls` | A single `skills` array |
|
||||
|
||||
Permission actions also changed: `bash` is now `shell`, `task` is now `subagent`, and `write` and `patch` are now `edit`.
|
||||
See [Permissions](/permissions) for the ordered V2 rule format.
|
||||
|
||||
V1-only fields including `logLevel`, `server`, `layout`, `disabled_providers`, `enabled_providers`, and `small_model` are
|
||||
not carried into the native V2 configuration. Remove them and use the current [Config](/config) and
|
||||
[Providers](/providers) guides to configure their replacements where applicable.
|
||||
|
||||
## Review extensions
|
||||
|
||||
V2 continues to discover file-based agents, commands, and skills from OpenCode configuration directories. Their schemas
|
||||
have changed, so review each extension against the current [Agents](/agents), [Commands](/commands), and
|
||||
[Skills](/skills) guides.
|
||||
|
||||
<Warning>
|
||||
V1 plugins are not guaranteed to work with V2. The plugin API is changing during beta; review and port each plugin using
|
||||
the [V2 plugin guide](/plugins).
|
||||
</Warning>
|
||||
|
||||
## Verify your setup
|
||||
|
||||
Start `opencode2` in a project and verify your model, provider credentials, agents, permissions, MCP servers, and plugins
|
||||
before relying on the beta for regular work. Keep your V1 setup and backups until you have confirmed the V2 behavior you
|
||||
need, and do not point V1 at configuration that you have converted to the native V2 shape.
|
||||
223
packages/docs/models.mdx
Normal file
223
packages/docs/models.mdx
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
---
|
||||
title: "Models"
|
||||
description: "Select, configure, and customize models in OpenCode 2.0."
|
||||
---
|
||||
|
||||
OpenCode builds its model catalog from [Models.dev](https://models.dev), provider integrations, and your configuration.
|
||||
Only enabled models whose provider is available for the current project appear in the model picker.
|
||||
|
||||
Connect a provider with `/connect` in the TUI, or configure a provider and its credentials in `opencode.json`.
|
||||
|
||||
## Select a model
|
||||
|
||||
Open the model picker with `/models` or the default `<leader>m` keybind. Use `/variants` to choose a variant for the
|
||||
current model, or press `ctrl+t` to cycle through its variants.
|
||||
|
||||
A model reference has this form:
|
||||
|
||||
```text
|
||||
provider/model#variant
|
||||
```
|
||||
|
||||
The variant is optional. OpenCode splits at the first `/`, so model IDs may contain additional slashes:
|
||||
|
||||
```text
|
||||
openai/gpt-5.2
|
||||
openai/gpt-5.2#high
|
||||
openrouter/anthropic/claude-sonnet-4.5#high
|
||||
```
|
||||
|
||||
Use the catalog IDs shown by `/models`, not a provider's display name. Omit `#variant` to use the model's base settings.
|
||||
|
||||
### Command line
|
||||
|
||||
Select a model for a non-interactive run with `--model` or `-m`:
|
||||
|
||||
```bash
|
||||
opencode2 run --model openai/gpt-5.2 "Explain this repository"
|
||||
opencode2 run -m openai/gpt-5.2#high "Review the current changes"
|
||||
```
|
||||
|
||||
<Note>
|
||||
`opencode2 run` accepts `provider/model#variant`. The current `opencode2 mini --model` option accepts only
|
||||
`provider/model`; choose its variant from the interactive interface.
|
||||
</Note>
|
||||
|
||||
## Set the default
|
||||
|
||||
Set `model` in `opencode.json` or `opencode.jsonc`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"model": "anthropic/claude-sonnet-4-5"
|
||||
}
|
||||
```
|
||||
|
||||
The explicit object form is equivalent:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"model": {
|
||||
"providerID": "openrouter",
|
||||
"model": "anthropic/claude-sonnet-4.5"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Root, agent, and command `model` fields accept these same selection forms. See [Config](/config) for configuration
|
||||
locations and precedence.
|
||||
|
||||
The configured model becomes the catalog default when its provider is available and the model is enabled. Otherwise,
|
||||
session execution falls back to the newest available supported model. An explicit model already selected on a session
|
||||
takes precedence over the default; switching models changes that session and does not rewrite your config.
|
||||
|
||||
## Variants
|
||||
|
||||
Variants are named request overlays for one model, commonly used for reasoning effort or token budgets. Available names
|
||||
are model-specific and are derived from current catalog metadata. Do not assume that names such as `low`, `high`, or
|
||||
`max` exist for every model; `/variants` shows the valid choices.
|
||||
|
||||
Add a variant, or override a catalog variant with the same ID, under the model's `variants` array:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"models": {
|
||||
"gpt-5.2": {
|
||||
"settings": {
|
||||
"reasoningEffort": "medium"
|
||||
},
|
||||
"variants": [
|
||||
{
|
||||
"id": "fast",
|
||||
"settings": {
|
||||
"reasoningEffort": "low"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "deep",
|
||||
"settings": {
|
||||
"reasoningEffort": "high",
|
||||
"reasoningSummary": "auto"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"deep-review": {
|
||||
"description": "Review with high reasoning effort",
|
||||
"template": "Review the current changes for correctness and missing tests.",
|
||||
"model": "openai/gpt-5.2#deep"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Variant entries support `settings`, `headers`, and `body`. Selecting one deeply overlays its values on the effective
|
||||
provider and model configuration. An unknown variant fails model resolution instead of silently using the base model.
|
||||
|
||||
<Warning>
|
||||
V2 uses `providers` (plural) and an array of `{ "id": "..." }` variant entries. The V1 `provider` key and
|
||||
object-shaped `variants` configuration are not the V2 format.
|
||||
</Warning>
|
||||
|
||||
## Configure a model
|
||||
|
||||
Provider and model entries can supply three kinds of request configuration:
|
||||
|
||||
- `settings` contains provider-package options such as `baseURL`, `reasoningEffort`, or `thinkingConfig`.
|
||||
- `headers` adds HTTP request headers.
|
||||
- `body` adds provider-specific fields to the request body.
|
||||
|
||||
These values are provider-specific JSON. OpenCode applies provider values first, then model values, then the selected
|
||||
variant. Nested `settings` and `body` objects are merged; later array and scalar values replace earlier values. Header
|
||||
names are matched case-insensitively.
|
||||
|
||||
You can also map a friendly catalog ID to a different API model ID with `modelID`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"model": "openai/coding-default",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"models": {
|
||||
"coding-default": {
|
||||
"modelID": "gpt-5.2",
|
||||
"name": "Coding default",
|
||||
"capabilities": {
|
||||
"tools": true,
|
||||
"input": ["text", "image"],
|
||||
"output": ["text"]
|
||||
},
|
||||
"limit": {
|
||||
"context": 200000,
|
||||
"output": 32000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here `openai/coding-default` is the selectable catalog reference, while `gpt-5.2` is sent to the provider. When adding a
|
||||
model that is not already in the catalog, set accurate `capabilities` and `limit` values so OpenCode can expose tools and
|
||||
enforce the correct context limits. Set `disabled: true` on a model entry to hide it from the available catalog.
|
||||
|
||||
## Local and compatible models
|
||||
|
||||
For an OpenAI-compatible server, define a provider package, endpoint, and at least one model:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"model": "local/coder",
|
||||
"providers": {
|
||||
"local": {
|
||||
"name": "Local server",
|
||||
"package": "aisdk:@ai-sdk/openai-compatible",
|
||||
"settings": {
|
||||
"baseURL": "http://127.0.0.1:1234/v1"
|
||||
},
|
||||
"models": {
|
||||
"coder": {
|
||||
"modelID": "model-name-on-server",
|
||||
"capabilities": {
|
||||
"tools": true,
|
||||
"input": ["text"],
|
||||
"output": ["text"]
|
||||
},
|
||||
"limit": {
|
||||
"context": 32768,
|
||||
"output": 8192
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use the server's real model name, limits, modalities, and tool support. OpenCode cannot infer these for a model you add
|
||||
manually. If the endpoint requires a key, add `apiKey` to provider `settings` using an environment substitution such as
|
||||
`"apiKey": "{env:LOCAL_API_KEY}"`; do not commit secrets.
|
||||
|
||||
## Caveats
|
||||
|
||||
- Provider and model IDs are case-sensitive. Provider IDs cannot contain `/` or `#`; model IDs cannot contain `#`.
|
||||
- The selector object uses `model`, while a provider catalog entry uses `modelID` for the upstream API identifier.
|
||||
- The root `model` currently sets the default provider and model only. Although its selection shape accepts a variant,
|
||||
the V2 catalog default does not retain it; select a variant in the TUI, with `opencode2 run`, or on an agent or command.
|
||||
- Model options are provider-specific. A setting accepted by one provider package may be ignored or rejected by another.
|
||||
- Catalog data, credentials, and config are location-scoped. A model available in one project may be unavailable in
|
||||
another.
|
||||
- Configuration files are watched and normally reload automatically, but an in-flight model request keeps the settings
|
||||
with which it started.
|
||||
209
packages/docs/permissions.mdx
Normal file
209
packages/docs/permissions.mdx
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
---
|
||||
title: "Permissions"
|
||||
description: "Configure ordered V2 rules for tool access, approvals, and agent overrides."
|
||||
---
|
||||
|
||||
Permissions control whether an agent may perform an action on a resource. V2
|
||||
configuration uses the plural `permissions` field and an ordered array of rules.
|
||||
|
||||
<Warning>
|
||||
The V1 object syntax uses different field and action names. Do not use
|
||||
`permission`, `bash`, or `task` in V2 configuration; use `permissions`,
|
||||
`shell`, and `subagent`.
|
||||
</Warning>
|
||||
|
||||
## Rule schema
|
||||
|
||||
Each rule has three required string fields:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permissions": [
|
||||
{ "action": "*", "resource": "*", "effect": "ask" },
|
||||
{ "action": "read", "resource": "*", "effect": "allow" },
|
||||
{ "action": "read", "resource": "*.env", "effect": "deny" },
|
||||
{ "action": "shell", "resource": "git status *", "effect": "allow" },
|
||||
{ "action": "shell", "resource": "git push *", "effect": "deny" },
|
||||
{ "action": "edit", "resource": "packages/docs/*.mdx", "effect": "allow" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `action` matches a tool permission action.
|
||||
- `resource` matches the value the tool is trying to use, such as a path,
|
||||
command, URL, query, or agent ID.
|
||||
- `effect` is `"allow"`, `"deny"`, or `"ask"`.
|
||||
|
||||
`allow` proceeds without prompting, `deny` blocks the operation, and `ask`
|
||||
waits for a user decision. If no rule matches, the result is `ask`.
|
||||
|
||||
## Matching and order
|
||||
|
||||
Both `action` and `resource` support simple wildcards:
|
||||
|
||||
- `*` matches zero or more characters, including `/`.
|
||||
- `?` matches exactly one character.
|
||||
- All other characters are literal.
|
||||
|
||||
Matches cover the entire value. Slashes are normalized, and matching is
|
||||
case-insensitive on Windows. For shell convenience, a pattern ending in
|
||||
`" *"` also matches the command without arguments: `"git status *"` matches
|
||||
both `git status` and `git status --short`.
|
||||
|
||||
The **last matching rule wins**. Put broad rules first and exceptions later.
|
||||
Rules from lower-priority configuration files are loaded first. OpenCode then
|
||||
appends all global rules before agent-specific rules, so a matching agent rule
|
||||
overrides a global rule.
|
||||
|
||||
Some operations check several resources at once, such as a patch touching
|
||||
multiple files. OpenCode denies the operation if any resource resolves to
|
||||
`deny`; otherwise it asks if any resolves to `ask`; otherwise it allows it.
|
||||
|
||||
## Actions and resources
|
||||
|
||||
V2 action names are strings, so plugins may introduce additional actions. The
|
||||
current built-in actions use these resources:
|
||||
|
||||
| Action | Resource matched |
|
||||
| --- | --- |
|
||||
| `read` | Location-relative path for an internal file or directory; canonical absolute path for an external target |
|
||||
| `edit` | Target path for `edit`, `write`, and `patch`; all three tools share this action |
|
||||
| `glob` | The requested glob pattern |
|
||||
| `grep` | The requested regular expression, not the search path |
|
||||
| `shell` | The complete raw shell command string |
|
||||
| `subagent` | The target agent ID |
|
||||
| `skill` | The skill ID |
|
||||
| `question` | `*` |
|
||||
| `webfetch` | The requested URL |
|
||||
| `websearch` | The search query |
|
||||
| `external_directory` | A canonical external directory boundary, normally ending in `/*` |
|
||||
| `<server>_<tool>` | `*` for an MCP tool; unsupported characters in both names become `_` |
|
||||
| `execute` | `*`; controls availability of the Code Mode dispatcher, while each nested tool still enforces its own permission |
|
||||
|
||||
Built-in agent policy also reserves `plan_enter` and `plan_exit` for plan-mode
|
||||
transitions. `doom_loop` and `lsp` are not current V2 Core permission actions.
|
||||
|
||||
## External directories
|
||||
|
||||
An external path requires a separate `external_directory` decision before the
|
||||
tool's own `read` or `edit` decision. This applies to external paths used by
|
||||
`read`, `edit`, `write`, and `patch`, and to an external `shell` working
|
||||
directory.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permissions": [
|
||||
{
|
||||
"action": "external_directory",
|
||||
"resource": "~/projects/reference/*",
|
||||
"effect": "allow"
|
||||
},
|
||||
{
|
||||
"action": "read",
|
||||
"resource": "~/projects/reference/*",
|
||||
"effect": "allow"
|
||||
},
|
||||
{
|
||||
"action": "edit",
|
||||
"resource": "~/projects/reference/*",
|
||||
"effect": "deny"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
For `external_directory`, `read`, and `edit` resources, a leading `~`, `~/`,
|
||||
`$HOME`, or `$HOME/` is expanded when configuration loads. Shell resources are
|
||||
raw command text and are **not** home-expanded.
|
||||
|
||||
<Warning>
|
||||
`shell` runs with the host user's filesystem, process, and network authority.
|
||||
Its resource is raw text, not a parsed command. External command arguments
|
||||
produce only best-effort warnings; `external_directory` is enforced for the
|
||||
working directory, not every path embedded in a command. Prefer a narrow
|
||||
shell allowlist over patterns intended to identify every dangerous command.
|
||||
</Warning>
|
||||
|
||||
Relative mutation paths cannot escape the active Location, and symlink escapes
|
||||
from inside it are rejected. Explicit external paths are canonicalized before
|
||||
matching, so authorize only trusted directory boundaries.
|
||||
|
||||
## Defaults
|
||||
|
||||
The evaluator's fallback is `ask`, but shipped agents include ordered defaults:
|
||||
|
||||
| Agent | Effective default policy |
|
||||
| --- | --- |
|
||||
| `build` | Allows most actions; asks for external directories and `.env` reads; allows questions and entering plan mode; denies exiting plan mode |
|
||||
| `plan` | Uses the same base, allows questions and exiting plan mode, and denies edits except OpenCode plan files |
|
||||
| `general` | Uses the base policy but cannot launch another subagent; questions and plan transitions remain denied |
|
||||
| `explore` | Denies everything except `read`, `glob`, `grep`, `webfetch`, and `websearch`; cannot launch subagents and asks for external directories |
|
||||
| Hidden maintenance agents | Deny all actions |
|
||||
|
||||
The base read rules are ordered as follows:
|
||||
|
||||
```jsonc
|
||||
[
|
||||
{ "action": "read", "resource": "*", "effect": "allow" },
|
||||
{ "action": "read", "resource": "*.env", "effect": "ask" },
|
||||
{ "action": "read", "resource": "*.env.*", "effect": "ask" },
|
||||
{ "action": "read", "resource": "*.env.example", "effect": "allow" }
|
||||
]
|
||||
```
|
||||
|
||||
OpenCode also permits its managed tool-output and temporary directories where
|
||||
needed. These exceptions do not grant general external-directory access.
|
||||
|
||||
## Agent overrides
|
||||
|
||||
Configure shared policy at the top level and append narrower rules to a named
|
||||
agent under `agents.<id>.permissions`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"permissions": [
|
||||
{ "action": "shell", "resource": "*", "effect": "ask" },
|
||||
{ "action": "shell", "resource": "git diff *", "effect": "allow" },
|
||||
{ "action": "shell", "resource": "git status *", "effect": "allow" }
|
||||
],
|
||||
"agents": {
|
||||
"reviewer": {
|
||||
"description": "Review code without changing it",
|
||||
"mode": "subagent",
|
||||
"permissions": [
|
||||
{ "action": "edit", "resource": "*", "effect": "deny" },
|
||||
{ "action": "shell", "resource": "git diff *", "effect": "allow" },
|
||||
{ "action": "shell", "resource": "git status *", "effect": "allow" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Agent rules do not replace the global array; they are appended after it. A
|
||||
custom subagent executes with its own permissions, not a permission subset
|
||||
derived from the parent agent.
|
||||
|
||||
## Approval choices
|
||||
|
||||
When an `ask` rule matches, clients can reply with:
|
||||
|
||||
- **Allow once** (`once`): approve only the pending request.
|
||||
- **Allow always** (`always`): approve this request and save the patterns
|
||||
proposed by the tool for the current project.
|
||||
- **Reject** (`reject`): reject the request. Rejecting also rejects other
|
||||
pending permission requests in the same session; clients may attach feedback.
|
||||
|
||||
Saved approvals are durable and project-scoped. They are additional `allow`
|
||||
rules, but they can never override a configured `deny`. The proposed saved
|
||||
pattern may be broader than the displayed resource: several tools propose `*`,
|
||||
shell proposes the exact command text, and skills and subagents propose their
|
||||
IDs. Review the confirmation carefully and remove saved approvals that are no
|
||||
longer needed.
|
||||
|
||||
For non-interactive runs, `opencode2 run --auto` replies `once` to permission
|
||||
requests. It does not save approvals, and explicit `deny` rules remain enforced.
|
||||
Without `--auto`, a non-interactive run rejects permission requests.
|
||||
|
|
@ -2,3 +2,368 @@
|
|||
title: "Plugins"
|
||||
description: "Extend OpenCode with plugins."
|
||||
---
|
||||
|
||||
Plugins extend OpenCode in-process. They can transform agents, models, commands,
|
||||
integrations, references, skills, and tools; intercept model requests and tool
|
||||
execution; and call a location-scoped subset of the V2 client.
|
||||
|
||||
<Warning>
|
||||
The V2 plugin API is beta. Entrypoints, hooks, draft shapes, and configuration
|
||||
may change before the stable release. Use only the `/v2` exports described on
|
||||
this page; the root `@opencode-ai/plugin` API is the legacy API.
|
||||
</Warning>
|
||||
|
||||
## Load plugins
|
||||
|
||||
Plugins can be loaded from npm packages, explicit local paths, or config
|
||||
directories. Each module must have one default export containing a unique
|
||||
plugin `id` and either a Promise `setup` function or an Effect `effect`
|
||||
function.
|
||||
|
||||
### Configuration
|
||||
|
||||
Add ordered entries to the plural `plugins` field in `opencode.json(c)`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"plugins": [
|
||||
"opencode-acme-plugin@1.2.0",
|
||||
"@acme/opencode-plugin",
|
||||
"./plugins/local.ts",
|
||||
{
|
||||
"package": "./plugins/reviewer.ts",
|
||||
"options": {
|
||||
"agent": "reviewer",
|
||||
"strict": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
A string is either a package specifier or a local path. Local paths must start
|
||||
with `./` or `../` and resolve relative to the configuration file containing
|
||||
the entry. Absolute paths and `file://` URLs are also supported. Both scoped
|
||||
packages and versioned package specifiers are supported.
|
||||
|
||||
Use the object form to pass JSON configuration to the plugin. OpenCode passes
|
||||
`options` unchanged as `ctx.options`; omitted options become an empty object.
|
||||
The plugin owns validation and defaults for its options.
|
||||
|
||||
See [Config](/config#locations) for configuration locations and precedence.
|
||||
Entries from all applicable files are processed from lowest to highest
|
||||
precedence rather than replacing the entire array.
|
||||
|
||||
### Local discovery
|
||||
|
||||
OpenCode automatically scans both of these directories in every discovered
|
||||
OpenCode config directory:
|
||||
|
||||
```text
|
||||
.opencode/plugin/
|
||||
.opencode/plugins/
|
||||
```
|
||||
|
||||
The equivalent global directories are
|
||||
`~/.config/opencode/plugin/` and `~/.config/opencode/plugins/`. Direct `.ts` and
|
||||
`.js` children are loaded. An immediate child directory is also loaded as a
|
||||
package when OpenCode can resolve a string `exports`, `module`, or `main`
|
||||
entrypoint, or an `index.ts` or `index.js` file.
|
||||
|
||||
A `plugin/` directory beside a project-root `opencode.json` is not discovered
|
||||
automatically. Put it under `.opencode/`, or add its file explicitly with a
|
||||
relative config entry.
|
||||
|
||||
### Enable and disable
|
||||
|
||||
A string beginning with `-` removes a previously selected target. `*` matches
|
||||
everything, and a suffix of `.*` matches an ID or target prefix. Directives are
|
||||
applied in order:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"plugins": [
|
||||
"-opencode.provider.*",
|
||||
"opencode.provider.openai",
|
||||
"-./plugin/old.ts",
|
||||
"-*",
|
||||
"./plugins/only-this-one.ts"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Use the same package specifier or resolved local target to remove an external
|
||||
plugin. Built-in and embedded plugins can be selected by their plugin ID.
|
||||
Explicit config directives run after local auto-discovery, so they can disable
|
||||
discovered plugins.
|
||||
|
||||
User plugins are activated in configured order between OpenCode's internal
|
||||
plugin phases. Hooks run sequentially in registration order, and later hooks
|
||||
observe earlier mutations. Do not depend on the internal phase ordering while
|
||||
the API is beta.
|
||||
|
||||
### Installation and dependencies
|
||||
|
||||
OpenCode installs bare package entries and their production dependencies into
|
||||
an isolated cache. Package installation does not run lifecycle scripts.
|
||||
Published packages should expose their plugin entrypoint and include every
|
||||
runtime import in `dependencies`.
|
||||
|
||||
Local files and local package directories are imported directly. OpenCode does
|
||||
**not** install their dependencies. Install dependencies in a `package.json`
|
||||
visible from the plugin file, for example:
|
||||
|
||||
```sh
|
||||
cd .opencode
|
||||
bun add @opencode-ai/plugin@1.17.15 effect@4.0.0-beta.83
|
||||
```
|
||||
|
||||
`effect` is required for Effect plugins and for the `Schema` values used by
|
||||
typed tools. A Promise plugin that does not define tools may only need
|
||||
`@opencode-ai/plugin`. Match these versions to the OpenCode release you target.
|
||||
|
||||
Configuration and discovered plugin files under watched config directories are
|
||||
reloaded when they change. Reloading replaces the active plugin generation and
|
||||
releases its scoped registrations. Restart OpenCode after changing an npm
|
||||
package version or a local dependency when no watched file changed.
|
||||
|
||||
## Create a plugin
|
||||
|
||||
The Promise API is the simplest option. Export the result of `Plugin.define`
|
||||
as the module default:
|
||||
|
||||
```ts title=".opencode/plugins/reviewer.ts"
|
||||
import { Plugin } from "@opencode-ai/plugin/v2"
|
||||
|
||||
export default Plugin.define({
|
||||
id: "acme.reviewer",
|
||||
setup: async (ctx) => {
|
||||
const description =
|
||||
typeof ctx.options.description === "string"
|
||||
? ctx.options.description
|
||||
: "Reviews code for regressions"
|
||||
|
||||
await ctx.agent.transform((agents) => {
|
||||
agents.update("reviewer", (agent) => {
|
||||
agent.description = description
|
||||
agent.mode = "subagent"
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
`setup` runs each time the plugin is activated for a Location. Register
|
||||
long-lived behavior during setup; do not wait there on an infinite event
|
||||
stream.
|
||||
|
||||
### Effect plugins
|
||||
|
||||
Use the Effect entrypoint when the implementation benefits from Effect
|
||||
composition, fibers, or scoped resources:
|
||||
|
||||
```ts title=".opencode/plugins/reviewer-effect.ts"
|
||||
import { Plugin } from "@opencode-ai/plugin/v2/effect"
|
||||
import { Effect } from "effect"
|
||||
|
||||
export default Plugin.define({
|
||||
id: "acme.reviewer-effect",
|
||||
effect: (ctx) =>
|
||||
Effect.gen(function* () {
|
||||
yield* ctx.agent.transform((agents) => {
|
||||
agents.update("reviewer", (agent) => {
|
||||
agent.description = "Reviews code for regressions"
|
||||
agent.mode = "subagent"
|
||||
})
|
||||
})
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
The plugin effect is scoped. Finalizers, scoped fibers, and registrations are
|
||||
released when the plugin reloads or unloads. OpenCode deliberately isolates the
|
||||
effect from its private Core services; use only the public `ctx` capabilities.
|
||||
|
||||
## Context
|
||||
|
||||
Promise methods return Promises; the equivalent Effect methods return
|
||||
`Effect`. Read and action methods use the same inputs and location-aware
|
||||
responses as the V2 client APIs.
|
||||
|
||||
| Capability | Available operations |
|
||||
| --- | --- |
|
||||
| `ctx.agent` | `list`, `transform`, `reload` |
|
||||
| `ctx.catalog.provider` | `list`, `get` |
|
||||
| `ctx.catalog.model` | `list`, `default` |
|
||||
| `ctx.catalog` | `transform`, `reload` |
|
||||
| `ctx.command` | `list`, `transform`, `reload` |
|
||||
| `ctx.integration` | `list`, `get`, `connect`, `attempt`, `transform`, `reload`, and connection lookup/resolution |
|
||||
| `ctx.plugin` | `list` currently active plugin IDs |
|
||||
| `ctx.reference` | `list`, `transform`, `reload` |
|
||||
| `ctx.session` | `create`, `get`, `prompt`, `command`, `interrupt`, and `hook` |
|
||||
| `ctx.skill` | `list`, `transform`, `reload` |
|
||||
| `ctx.tool` | `transform` and `hook` |
|
||||
| `ctx.aisdk` | `hook` |
|
||||
| `ctx.event` | `subscribe` to the current public server event stream |
|
||||
| `ctx.options` | Readonly options from the matching config object |
|
||||
|
||||
Unlike the legacy API, V2 does not provide `$`, `directory`, `worktree`, or a
|
||||
general SDK client on the context. A plugin is Location-scoped, and the exposed
|
||||
domain clients apply that Location by default.
|
||||
|
||||
### Transform hooks
|
||||
|
||||
Transforms synchronously edit a draft whenever a stateful domain is built.
|
||||
Registering or disposing a transform rebuilds the domain from fresh state and
|
||||
runs all active transforms in order. Call the domain's `reload()` method when
|
||||
external data captured by a transform changes.
|
||||
|
||||
| Transform | Draft operations |
|
||||
| --- | --- |
|
||||
| `agent.transform` | `list`, `get`, `default`, `update`, `remove` |
|
||||
| `catalog.transform` | Provider `list`, `get`, `update`, `remove`; model `get`, `update`, `remove`; default model `get`, `set` |
|
||||
| `command.transform` | `list`, `get`, `update`, `remove` |
|
||||
| `integration.transform` | Integration `list`, `get`, `update`, `remove`; method `list`, `update`, `remove` |
|
||||
| `reference.transform` | `add`, `remove`, `list` |
|
||||
| `skill.transform` | `source`, `list` |
|
||||
| `tool.transform` | `add` |
|
||||
|
||||
Hook registrations are owned by the plugin scope. Transform and runtime hook
|
||||
calls also return a `Registration` with `dispose` for explicit cleanup. Tool
|
||||
contributions currently remain until the owning plugin scope closes, so prefer
|
||||
scope cleanup for plugin-wide teardown while this API is beta.
|
||||
|
||||
### Runtime hooks
|
||||
|
||||
Runtime hooks intercept live operations. Their event objects expose specific
|
||||
mutable fields:
|
||||
|
||||
| Hook | Mutable fields |
|
||||
| --- | --- |
|
||||
| `ctx.aisdk.hook("sdk", callback)` | `sdk`, after inspecting `model`, `package`, and `options` |
|
||||
| `ctx.aisdk.hook("language", callback)` | `language`, after inspecting `model`, `sdk`, and `options` |
|
||||
| `ctx.session.hook("request", callback)` | `system`, `messages`, and the `tools` record immediately before model dispatch |
|
||||
| `ctx.tool.hook("execute.before", callback)` | `input`, before the selected tool executes |
|
||||
| `ctx.tool.hook("execute.after", callback)` | `result`, `output`, and `outputPaths`, after execution settles |
|
||||
|
||||
For example, remove a tool from selected model requests and normalize another
|
||||
tool's input:
|
||||
|
||||
```ts title=".opencode/plugins/guards.ts"
|
||||
import { Plugin } from "@opencode-ai/plugin/v2"
|
||||
|
||||
export default Plugin.define({
|
||||
id: "acme.guards",
|
||||
setup: async (ctx) => {
|
||||
await ctx.session.hook("request", (event) => {
|
||||
delete event.tools.write
|
||||
})
|
||||
|
||||
await ctx.tool.hook("execute.before", (event) => {
|
||||
if (event.tool !== "lookup" || typeof event.input !== "object" || event.input === null) return
|
||||
event.input = { ...event.input, source: "plugin" }
|
||||
})
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
A hook failure fails the operation it intercepts. Keep runtime hooks fast and
|
||||
handle expected errors inside the callback.
|
||||
|
||||
## Add a tool
|
||||
|
||||
Use `Tool.make` with Effect schemas. Promise tools use async executors:
|
||||
|
||||
```ts title=".opencode/plugins/greeting.ts"
|
||||
import { Plugin } from "@opencode-ai/plugin/v2"
|
||||
import { Tool } from "@opencode-ai/plugin/v2/tool"
|
||||
import { Schema } from "effect"
|
||||
|
||||
const greeting = Tool.make({
|
||||
description: "Create a greeting",
|
||||
input: Schema.Struct({ name: Schema.String }),
|
||||
output: Schema.String,
|
||||
execute: async ({ name }) => `Hello, ${name}!`,
|
||||
})
|
||||
|
||||
export default Plugin.define({
|
||||
id: "acme.greeting",
|
||||
setup: async (ctx) => {
|
||||
await ctx.tool.transform((tools) => {
|
||||
tools.add("greeting", greeting)
|
||||
})
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
Unsupported characters in tool and group names are normalized to underscores.
|
||||
The resulting exposed key must begin with a letter and contain at most 64
|
||||
letters, digits, underscores, or hyphens. `tools.add` also accepts
|
||||
`{ group, deferred }`:
|
||||
|
||||
- `group` prefixes and groups the exposed tool name.
|
||||
- `deferred: true` makes the tool available through the deferred `execute`
|
||||
tool instead of exposing it directly.
|
||||
|
||||
The executor receives a second context argument containing `sessionID`,
|
||||
`agent`, `assistantMessageID`, and `toolCallID`. Use
|
||||
`Tool.withPermission(tool, "permission-name")` to assign a permission key.
|
||||
Effect plugins import the helper from `@opencode-ai/plugin/v2/effect/tool` and
|
||||
return an `Effect` from `execute`.
|
||||
|
||||
## Types
|
||||
|
||||
`Plugin.define` infers the context and callbacks. The Promise root also
|
||||
re-exports the canonical `Agent`, `Command`, `Connection`, `Credential`,
|
||||
`Integration`, `Model`, `Provider`, `Reference`, and `Skill` schema namespaces.
|
||||
Import narrower API types from their public subpaths when needed:
|
||||
|
||||
```ts
|
||||
import { Plugin, Model } from "@opencode-ai/plugin/v2"
|
||||
import type { Context } from "@opencode-ai/plugin/v2/plugin"
|
||||
import type { AgentDraft } from "@opencode-ai/plugin/v2/agent"
|
||||
import type { ToolExecuteBeforeEvent } from "@opencode-ai/plugin/v2/tool"
|
||||
```
|
||||
|
||||
Effect equivalents live below `@opencode-ai/plugin/v2/effect`, such as
|
||||
`@opencode-ai/plugin/v2/effect/plugin` and
|
||||
`@opencode-ai/plugin/v2/effect/tool`. Avoid importing types or runtime values
|
||||
from `@opencode-ai/core` or `@opencode-ai/server`; those are private host
|
||||
implementation details.
|
||||
|
||||
## Publish a package
|
||||
|
||||
A package plugin uses the same default export as a local plugin. A minimal
|
||||
manifest is:
|
||||
|
||||
```json title="package.json"
|
||||
{
|
||||
"name": "opencode-acme-plugin",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": "./src/index.ts",
|
||||
"dependencies": {
|
||||
"@opencode-ai/plugin": "1.17.15",
|
||||
"effect": "4.0.0-beta.83"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use versions compatible with the OpenCode release you target and test the
|
||||
installed package, not only a workspace-linked copy. Because the plugin API is
|
||||
beta, publish compatible plugin updates when V2 entrypoints or contracts
|
||||
change.
|
||||
|
||||
## Verify loading
|
||||
|
||||
List active plugin IDs for the current Location through the V2 API:
|
||||
|
||||
```sh
|
||||
opencode2 api get /api/plugin
|
||||
```
|
||||
|
||||
If a plugin is absent, check the server log described in
|
||||
[Troubleshooting](/troubleshooting#read-logs). Invalid modules and setup failures are
|
||||
logged; one failing package does not prevent unrelated valid packages from
|
||||
being resolved.
|
||||
|
|
|
|||
272
packages/docs/providers.mdx
Normal file
272
packages/docs/providers.mdx
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
---
|
||||
title: "Providers"
|
||||
description: "Connect LLM providers and configure endpoints, packages, models, and variants."
|
||||
---
|
||||
|
||||
OpenCode builds its provider and model catalog from [Models.dev](https://models.dev), then applies the `providers`
|
||||
overlays from your [configuration](/config). A provider needs both a usable runtime package and, when required, an
|
||||
active connection.
|
||||
|
||||
## Connect a provider
|
||||
|
||||
Run `/connect` in the TUI, choose an integration, and complete one of the methods it offers:
|
||||
|
||||
```text
|
||||
/connect
|
||||
```
|
||||
|
||||
An integration may support an API key, OAuth, environment variables, or a combination of them. API keys and OAuth
|
||||
tokens entered through `/connect` are stored by the OpenCode service in its database. Run `/connect` again to replace
|
||||
or remove a stored credential.
|
||||
|
||||
Providers from Models.dev also declare their standard environment variables. A non-empty declared variable is exposed
|
||||
as an environment connection automatically, so common providers usually need no config:
|
||||
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY="your-key"
|
||||
```
|
||||
|
||||
For a custom provider, `env` declares the variables that can supply its key:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"env": ["ACME_API_KEY"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When several credential sources exist, OpenCode uses the stored credential first, then the first non-empty variable in
|
||||
`env`, then `settings.apiKey`. Use config substitution instead of committing a literal key:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"settings": {
|
||||
"apiKey": "{env:ACME_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Warning>Do not commit API keys or authorization headers to your repository.</Warning>
|
||||
|
||||
## Configure providers
|
||||
|
||||
The `providers` object is keyed by provider ID. Each provider accepts these fields:
|
||||
|
||||
| Field | Purpose |
|
||||
| --- | --- |
|
||||
| `name` | Display name. |
|
||||
| `env` | Ordered environment variable names that provide a connection. |
|
||||
| `package` | Runtime provider package. |
|
||||
| `settings` | JSON settings passed to the runtime package, such as `baseURL`. |
|
||||
| `headers` | String-valued HTTP headers added to requests. |
|
||||
| `body` | JSON fields merged into request bodies. |
|
||||
| `models` | Models to add or override, keyed by catalog model ID. |
|
||||
|
||||
Configuration files are applied from lowest to highest precedence. `settings` and `body` are deep-merged. Headers are
|
||||
merged case-insensitively. At request time, provider values are inherited by the model, model values override them, and
|
||||
the selected variant is applied last.
|
||||
|
||||
### Custom endpoint
|
||||
|
||||
Override `settings.baseURL` to send an existing provider through a proxy or compatible endpoint. Its existing package,
|
||||
models, and connection continue to apply:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"anthropic": {
|
||||
"settings": {
|
||||
"baseURL": "https://llm-proxy.example.com/anthropic"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`settings` is package-specific. A field only has an effect when the selected package supports it.
|
||||
|
||||
### Custom headers and body
|
||||
|
||||
Headers and body fields can be set at provider, model, or variant scope:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"headers": {
|
||||
"X-Gateway-Tenant": "engineering"
|
||||
},
|
||||
"body": {
|
||||
"metadata": {
|
||||
"application": "opencode"
|
||||
}
|
||||
},
|
||||
"models": {
|
||||
"gpt-5.2": {
|
||||
"headers": {
|
||||
"X-Model-Policy": "coding"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These are request overlays, not a generic authentication scheme. Prefer `/connect`, `env`, or `settings.apiKey` for
|
||||
provider credentials unless the endpoint explicitly requires a custom header.
|
||||
|
||||
## Custom providers and packages
|
||||
|
||||
For an OpenAI-compatible service, use the V2 native compatible package. The model map is explicit because a custom
|
||||
provider has no Models.dev catalog entries:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"model": "acme/qwen3-coder",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"name": "Acme Gateway",
|
||||
"env": ["ACME_API_KEY"],
|
||||
"package": "@opencode-ai/llm/providers/openai-compatible",
|
||||
"settings": {
|
||||
"baseURL": "https://llm.acme.example/v1"
|
||||
},
|
||||
"models": {
|
||||
"qwen3-coder": {
|
||||
"name": "Qwen 3 Coder",
|
||||
"capabilities": {
|
||||
"tools": true,
|
||||
"input": ["text"],
|
||||
"output": ["text"]
|
||||
},
|
||||
"limit": {
|
||||
"context": 131072,
|
||||
"output": 32768
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Omit `env` for an endpoint that does not require authentication. The native compatible package requires
|
||||
`settings.baseURL` and uses bearer authentication when a key is available.
|
||||
|
||||
The `package` field supports two runtime contracts:
|
||||
|
||||
| Form | Contract |
|
||||
| --- | --- |
|
||||
| `"@opencode-ai/llm/providers/openai-compatible"` | A V2 native package exporting `model(modelID, settings)`. An npm specifier or absolute `file://` URL may use the same contract. |
|
||||
| `"aisdk:@ai-sdk/openai-compatible"` | An AI SDK provider package. The `aisdk:` prefix is required. |
|
||||
|
||||
Native packages receive the merged `settings` plus the resolved `apiKey`, `headers`, `body`, and `limits`. AI SDK
|
||||
packages receive their merged provider options. Use a package's own documentation for accepted settings; OpenCode does
|
||||
not validate package-specific keys.
|
||||
|
||||
`package` may also be set on one model to override the provider package for that model.
|
||||
|
||||
## Models
|
||||
|
||||
`models` adds a model or overlays an existing catalog model. The object key is the model ID used in OpenCode. Set
|
||||
`modelID` when the upstream API expects a different ID:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"model": "openai/coding",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"models": {
|
||||
"coding": {
|
||||
"modelID": "gpt-5.2",
|
||||
"name": "GPT-5.2 Coding",
|
||||
"family": "gpt-5",
|
||||
"limit": {
|
||||
"context": 200000,
|
||||
"input": 180000,
|
||||
"output": 32000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A model supports `modelID`, `family`, `name`, `package`, `settings`, `headers`, `body`, `capabilities`, `variants`,
|
||||
`cost`, `disabled`, and `limit`. If supplied, `capabilities` requires `tools`, `input`, and `output`. `limit` may set
|
||||
`context`, `input`, and `output`. Cost values are USD per million tokens:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"cost": {
|
||||
"input": 3,
|
||||
"output": 15,
|
||||
"cache": {
|
||||
"read": 0.3,
|
||||
"write": 3.75
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Set `disabled: true` on a model to remove it from the available model list. V2 does not define provider-level
|
||||
whitelist or blacklist fields.
|
||||
|
||||
## Variants
|
||||
|
||||
Variants are named request overlays for one model. They can override `settings`, `headers`, and `body`; the selected
|
||||
package determines which values are meaningful.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"models": {
|
||||
"gpt-5.2": {
|
||||
"variants": [
|
||||
{
|
||||
"id": "fast",
|
||||
"settings": {
|
||||
"reasoningEffort": "low"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "deep",
|
||||
"settings": {
|
||||
"reasoningEffort": "high",
|
||||
"reasoningSummary": "auto"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Choose a variant with the TUI variant picker or `/variants`. Explicit CLI, agent, and command model references use
|
||||
`provider/model#variant`; for example:
|
||||
|
||||
```bash
|
||||
opencode2 run --model openai/gpt-5.2#deep "Review this project"
|
||||
```
|
||||
|
||||
The current V2 top-level `model` default does not retain a `#variant` selection, so choose the variant separately.
|
||||
Selecting an ID that is not defined for the model fails instead of silently using the default request settings.
|
||||
177
packages/docs/references.mdx
Normal file
177
packages/docs/references.mdx
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
---
|
||||
title: "References"
|
||||
description: "Make local directories and Git repositories available as project context."
|
||||
---
|
||||
|
||||
References give OpenCode named access to directories outside the current
|
||||
project. Use them for documentation, shared libraries, examples, or source from
|
||||
another repository.
|
||||
|
||||
Configure references by alias in `opencode.json` or `opencode.jsonc`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"references": {
|
||||
"docs": {
|
||||
"path": "../product-docs",
|
||||
"description": "Use for product behavior and terminology"
|
||||
},
|
||||
"effect": {
|
||||
"repository": "Effect-TS/effect",
|
||||
"branch": "main",
|
||||
"description": "Use for Effect implementation details"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Local directories
|
||||
|
||||
Use `path` for a local directory:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"references": {
|
||||
"design-system": {
|
||||
"path": "../design-system",
|
||||
"description": "Use when working with components or design tokens"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Relative paths resolve from the directory containing the config file that
|
||||
defines them. Absolute paths and home-relative paths such as `~/docs` are also
|
||||
supported.
|
||||
|
||||
The string shorthand is useful when no other fields are needed:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"references": {
|
||||
"docs": "../docs",
|
||||
"shared": "~/work/shared"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Note>
|
||||
A shorthand string is treated as a local path only when it starts with `.`,
|
||||
`/`, or `~`. Use `./docs`, not `docs`; a bare `docs` value is interpreted as
|
||||
a Git repository.
|
||||
</Note>
|
||||
|
||||
## Git repositories
|
||||
|
||||
Use `repository` for a remote Git repository. GitHub `owner/repo` shorthand,
|
||||
Git URLs, host/path forms, and SCP-style remotes are supported.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"references": {
|
||||
"effect": {
|
||||
"repository": "Effect-TS/effect",
|
||||
"branch": "main"
|
||||
},
|
||||
"internal-sdk": {
|
||||
"repository": "git@gitlab.example.com:platform/sdk.git",
|
||||
"branch": "release/v2"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Without `branch`, OpenCode checks out and refreshes the remote's default
|
||||
branch. Branch names may contain letters, numbers, `/`, `_`, `.`, and `-`, but
|
||||
cannot start with `-` or contain `..`. Local `file:` repositories are not
|
||||
supported.
|
||||
|
||||
Git references also support shorthand:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"references": {
|
||||
"effect": "Effect-TS/effect",
|
||||
"sdk": "gitlab.com/platform/sdk"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Cloning and storage
|
||||
|
||||
OpenCode normalizes a remote and stores one checkout under its global data
|
||||
directory at `opencode/repos/<host>/<repository-path>`. On a typical Linux
|
||||
installation, for example, `Effect-TS/effect` is stored at:
|
||||
|
||||
```text
|
||||
~/.local/share/opencode/repos/github.com/Effect-TS/effect
|
||||
```
|
||||
|
||||
Missing repositories are cloned. Existing checkouts are fetched and reset to
|
||||
the requested branch, or to the remote default branch when `branch` is omitted.
|
||||
Materialization runs asynchronously when references load or reload, so a new
|
||||
reference can appear before its checkout is ready. Clone and refresh failures
|
||||
are logged and do not stop other references from loading.
|
||||
|
||||
<Warning>
|
||||
The cache has one checkout per normalized remote, not one per branch. Do not
|
||||
configure the same repository at multiple branches; only one branch can be
|
||||
exposed. Avoid editing cached checkouts because a refresh resets them.
|
||||
</Warning>
|
||||
|
||||
## Description and visibility
|
||||
|
||||
`description` tells agents when a reference is relevant. References with a
|
||||
description are included in agent instructions with their alias and resolved
|
||||
path. References without one remain available in `@` autocomplete but are not
|
||||
advertised automatically.
|
||||
|
||||
Set `hidden` to `true` to remove a reference from TUI `@` autocomplete:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"references": {
|
||||
"internal": {
|
||||
"path": "../internal",
|
||||
"description": "Use for internal service behavior",
|
||||
"hidden": true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`hidden` controls only autocomplete visibility. It does not remove the
|
||||
reference from the reference API or agent instructions when a description is
|
||||
present.
|
||||
|
||||
## Use references
|
||||
|
||||
Type `@` in the TUI and select a reference alias to attach its root directory:
|
||||
|
||||
```text
|
||||
Compare the current implementation with @effect
|
||||
```
|
||||
|
||||
The attachment provides a non-recursive listing of the root's immediate files
|
||||
and directories. V2 currently attaches references by root alias;
|
||||
`@alias/path` is not a reference-specific file browser. Ask the agent to
|
||||
inspect a particular path when more detail is needed.
|
||||
|
||||
References do not grant extra tool permissions. Access outside the active
|
||||
Location remains subject to the agent's normal tool rules and the
|
||||
`external_directory` permission. Editing a reference additionally requires the
|
||||
applicable edit permission.
|
||||
|
||||
## Fields
|
||||
|
||||
| Field | Local | Git | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `path` | Required | No | Local directory path |
|
||||
| `repository` | No | Required | Remote Git repository |
|
||||
| `branch` | No | Optional | Branch to fetch and check out |
|
||||
| `description` | Optional | Optional | Guidance describing when agents should use it |
|
||||
| `hidden` | Optional | Optional | Hide it from TUI `@` autocomplete |
|
||||
|
||||
An alias cannot be empty or contain `/`, `\`, whitespace, a backtick, or a
|
||||
comma.
|
||||
39
packages/docs/sharing.mdx
Normal file
39
packages/docs/sharing.mdx
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
title: "Session sharing"
|
||||
description: "Understand the current beta status of session sharing in OpenCode V2."
|
||||
---
|
||||
|
||||
Session sharing is not yet available in OpenCode V2. V2 does not currently
|
||||
publish sessions, upload conversation history to a sharing service, or create
|
||||
public links.
|
||||
|
||||
<Warning>
|
||||
The V2 TUI registers `/share`, but it currently only reports that sharing is unavailable. There is no functional
|
||||
share/unshare command or server API endpoint.
|
||||
</Warning>
|
||||
|
||||
## Configuration
|
||||
|
||||
The V2 configuration schema accepts a `share` field with three values:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"share": "manual"
|
||||
}
|
||||
```
|
||||
|
||||
- `"manual"` represents sharing only when explicitly requested.
|
||||
- `"auto"` represents automatically sharing new sessions.
|
||||
- `"disabled"` represents preventing session sharing.
|
||||
|
||||
These values are parsed but are not acted on by the current V2 runtime. In
|
||||
particular, setting `"auto"` does not publish sessions. If `share` is omitted,
|
||||
V2 leaves the sharing policy unspecified.
|
||||
|
||||
## Beta limitations
|
||||
|
||||
V2 currently provides no public session viewer, share URL, history sync,
|
||||
retention controls, or unshare/delete operation. Until those surfaces are
|
||||
implemented in the V2 server and protocol, keep using sessions locally and do
|
||||
not treat the `share` configuration field as a privacy or publishing control.
|
||||
228
packages/docs/skills.mdx
Normal file
228
packages/docs/skills.mdx
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
---
|
||||
title: "Skills"
|
||||
description: "Add reusable, on-demand instructions to OpenCode."
|
||||
---
|
||||
|
||||
Skills are Markdown instructions that OpenCode can advertise to an agent and
|
||||
load when they are relevant. A skill can include supporting scripts,
|
||||
references, and other files in the same directory.
|
||||
|
||||
## Create a skill
|
||||
|
||||
Create one directory per skill with a `SKILL.md` file:
|
||||
|
||||
```text
|
||||
.opencode/skills/
|
||||
└── git-release/
|
||||
├── SKILL.md
|
||||
├── scripts/
|
||||
│ └── changelog.ts
|
||||
└── references/
|
||||
└── release-policy.md
|
||||
```
|
||||
|
||||
```markdown title=".opencode/skills/git-release/SKILL.md"
|
||||
---
|
||||
name: Git Release
|
||||
description: Prepare release notes, version bumps, and GitHub releases
|
||||
metadata:
|
||||
opencode/slash: "true"
|
||||
---
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Read `references/release-policy.md`.
|
||||
2. Summarize merged changes since the previous tag.
|
||||
3. Propose the version bump before changing files.
|
||||
4. Run `scripts/changelog.ts` only after the user approves the version.
|
||||
```
|
||||
|
||||
Paths in a skill are relative to the directory containing `SKILL.md`.
|
||||
|
||||
## Discovery
|
||||
|
||||
OpenCode automatically adds the following source directories:
|
||||
|
||||
| Scope | Sources |
|
||||
| --- | --- |
|
||||
| Global | `~/.config/opencode/skill`, `~/.config/opencode/skills` |
|
||||
| Global compatibility | `~/.claude/skills`, `~/.agents/skills` |
|
||||
| Project | `.opencode/skill`, `.opencode/skills` |
|
||||
| Project compatibility | `.claude/skills`, `.agents/skills` |
|
||||
|
||||
For project sources, OpenCode searches from the current directory upward to
|
||||
the project root and includes matching directories at every level.
|
||||
|
||||
Within each source directory, OpenCode discovers:
|
||||
|
||||
- Markdown files at the source root, such as `skills/git-release.md`
|
||||
- `SKILL.md` files at any depth, such as `skills/git-release/SKILL.md`
|
||||
|
||||
The directory form is recommended because it gives the skill a private base
|
||||
directory for supporting files.
|
||||
|
||||
## Configure sources
|
||||
|
||||
Use the `skills` array in any `opencode.json` or `opencode.jsonc` to add local
|
||||
directories or HTTP catalogs:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"skills": [
|
||||
"./team-skills",
|
||||
"~/shared/opencode-skills",
|
||||
"/opt/company-skills",
|
||||
"https://example.com/opencode/skills/"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Relative paths are resolved from the active OpenCode working directory, not
|
||||
from the directory containing the config file. Paths beginning with `~/` use
|
||||
the current user's home directory. Only `http://` and `https://` values are
|
||||
treated as URL sources.
|
||||
|
||||
Every discovered config document contributes its `skills` entries; the arrays
|
||||
are additive rather than replacing one another.
|
||||
|
||||
### HTTP catalogs
|
||||
|
||||
An HTTP source is a base URL containing an `index.json`:
|
||||
|
||||
```json title="index.json"
|
||||
{
|
||||
"skills": [
|
||||
{
|
||||
"name": "git-release",
|
||||
"version": "3",
|
||||
"files": [
|
||||
"git-release.md",
|
||||
"references/release-policy.md"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
OpenCode downloads those files from
|
||||
`<base-url>/git-release/<file>`. File paths must be safe, relative,
|
||||
same-origin paths. Each entry must include either `SKILL.md` or a Markdown file
|
||||
named after the index entry, such as `git-release.md`.
|
||||
|
||||
Use the named Markdown form for HTTP catalogs. Each downloaded skill directory
|
||||
is itself a source root, so `git-release.md` produces the ID `git-release`; a
|
||||
root-level `SKILL.md` produces the literal ID `SKILL` in the current V2
|
||||
implementation. Increment `version` when files change so OpenCode refreshes
|
||||
the cached copy.
|
||||
|
||||
## Frontmatter
|
||||
|
||||
V2 reads these fields:
|
||||
|
||||
| Field | Purpose |
|
||||
| --- | --- |
|
||||
| `name` | Display name; defaults to the path-derived ID |
|
||||
| `description` | Summary shown to the model and command catalog |
|
||||
| `slash` | Set to `false` to hide the skill from the V2 slash-command catalog |
|
||||
| `metadata.opencode/slash` | Boolean or `"true"`/`"false"`; overrides `slash` |
|
||||
| `metadata.opencode/autoinvoke` | Set to `false` to omit the skill from model-facing discovery |
|
||||
|
||||
Frontmatter, `name`, and `description` are optional at runtime. However, a
|
||||
clear `description` is strongly recommended: skills without one are not
|
||||
advertised to the model. `license`, `compatibility`, and other metadata may be
|
||||
included for portability, but V2 does not interpret them.
|
||||
|
||||
`opencode/autoinvoke: false` only removes the skill from the model's available
|
||||
skills list. The skill remains registered and can still be activated explicitly
|
||||
by its ID.
|
||||
|
||||
## IDs and validation
|
||||
|
||||
The skill ID comes from its path, not its frontmatter:
|
||||
|
||||
| File | ID |
|
||||
| --- | --- |
|
||||
| `<source>/git-release.md` | `git-release` |
|
||||
| `<source>/git-release/SKILL.md` | `git-release` |
|
||||
| `<source>/teams/release/SKILL.md` | `release` |
|
||||
|
||||
IDs are exact and case-sensitive. V2 currently does not enforce the Agent
|
||||
Skills name regex, length limits, a match between `name` and the directory, or
|
||||
a maximum description length. The frontmatter `name` is only a display label.
|
||||
|
||||
For portable, predictable skills, use a unique lowercase kebab-case ID of 1-64
|
||||
characters and keep it aligned with the directory name:
|
||||
|
||||
```text
|
||||
^[a-z0-9]+(-[a-z0-9]+)*$
|
||||
```
|
||||
|
||||
## Precedence
|
||||
|
||||
Skills are keyed by ID. If several sources define the same ID, the later source
|
||||
wins. Sources are registered in this order, from lower to higher precedence:
|
||||
|
||||
1. Built-in skills
|
||||
2. `.claude/skills` sources, global first and then from the current directory upward
|
||||
3. `.agents/skills` sources, global first and then from the current directory upward
|
||||
4. `~/.config/opencode/skill` and `~/.config/opencode/skills`
|
||||
5. Project `.opencode/skill` and `.opencode/skills`, from the project root toward the current directory
|
||||
6. Explicit `skills` config entries, in config priority and array order
|
||||
|
||||
Within one `.opencode` directory, `skills` has precedence over `skill`. Avoid
|
||||
duplicate IDs unless an override is intentional.
|
||||
|
||||
## Runtime loading
|
||||
|
||||
At each model step, OpenCode advertises permitted skills that have a
|
||||
description and do not set `opencode/autoinvoke` to `false`. The advertisement
|
||||
contains only each skill's ID, name, and description; it does not add every
|
||||
skill body to the prompt.
|
||||
|
||||
When the model calls the `skill` tool with an exact ID, OpenCode:
|
||||
|
||||
1. Resolves the current winning definition for that ID
|
||||
2. Checks the `skill` permission for the selected agent
|
||||
3. Adds the Markdown body, without frontmatter, to the conversation
|
||||
4. Provides the skill's base directory and a sample of up to ten supporting file paths
|
||||
|
||||
Supporting file contents are not loaded automatically. The agent can read a
|
||||
referenced file when the skill instructs it to do so. The supporting-file
|
||||
sample is available for directory-based `SKILL.md` skills; flat Markdown skills
|
||||
receive no neighboring file list.
|
||||
|
||||
In the V2 CLI, skills appear as `/id` commands unless `slash` resolves to
|
||||
`false`. Selecting one appends the skill body as a skill message and resumes
|
||||
the session.
|
||||
|
||||
## Permissions
|
||||
|
||||
Permission rules use the `skill` action and the skill ID as the resource. Rules
|
||||
are evaluated in order, with the last matching rule winning:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"permissions": [
|
||||
{ "action": "skill", "resource": "*", "effect": "allow" },
|
||||
{ "action": "skill", "resource": "internal-*", "effect": "deny" },
|
||||
{ "action": "skill", "resource": "experimental-*", "effect": "ask" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`deny` removes matching skills from model-facing discovery and rejects skill
|
||||
tool loading. `ask` advertises the skill but requests approval when the model
|
||||
loads it. The same rules can be placed under an individual
|
||||
`agents.<id>.permissions` array.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If a skill is missing or loads the wrong content:
|
||||
|
||||
1. Confirm the file is either a root-level `*.md` or a nested file named exactly `SKILL.md`.
|
||||
2. Check the path-derived ID rather than the frontmatter `name`.
|
||||
3. Add a `description` if the skill should be advertised to the model.
|
||||
4. Check `opencode/autoinvoke` and the selected agent's `skill` permissions.
|
||||
5. Look for a later source defining the same ID.
|
||||
6. For HTTP catalogs, verify `index.json`, same-origin file paths, and a changed `version`.
|
||||
109
packages/docs/snapshots.mdx
Normal file
109
packages/docs/snapshots.mdx
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
title: "Snapshots and undo"
|
||||
description: "Understand filesystem snapshots, undo, redo, and message reverts in OpenCode V2."
|
||||
---
|
||||
|
||||
OpenCode snapshots let the default interactive TUI roll back conversation history and related file changes. They are a
|
||||
convenience for revising recent work, not a replacement for Git commits or backups.
|
||||
|
||||
## Configuration
|
||||
|
||||
Snapshots are enabled by default. Set `snapshots` to `false` in your [configuration](/config#snapshots) to stop capturing
|
||||
filesystem state:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"snapshots": false
|
||||
}
|
||||
```
|
||||
|
||||
Filesystem snapshots require a Git repository. With snapshots disabled, unavailable, or missing, undo can still stage a
|
||||
conversation rollback, but it has no captured file state to restore. Disabling snapshots does not delete snapshots that
|
||||
were already stored.
|
||||
|
||||
## What is captured
|
||||
|
||||
For each model step, OpenCode attempts to capture the worktree immediately before the model call and after a cleanly
|
||||
completed step. It records the paths changed between those two points on the assistant message.
|
||||
|
||||
Snapshots use a separate internal Git object database in the OpenCode data directory. They do not create commits, move
|
||||
branches, or intentionally modify your repository's Git index. Capture is limited to the session's active directory, which
|
||||
may be a subdirectory of the repository.
|
||||
|
||||
Within that directory, snapshots include tracked files and untracked files that are not ignored by Git. An individual
|
||||
untracked file larger than 2 MiB is excluded. Ignored files, files outside the active directory, and changes to Git
|
||||
metadata are not captured.
|
||||
|
||||
During undo, OpenCode does not check out an entire tree. It restores only paths attributed to cleanly completed assistant
|
||||
steps after the selected conversation boundary. Each path is restored to its state before the first affected step.
|
||||
|
||||
## Undo
|
||||
|
||||
Wait for the session to become idle, then run:
|
||||
|
||||
```text
|
||||
/undo
|
||||
```
|
||||
|
||||
The TUI finds the latest non-empty user message and stages a revert at that message:
|
||||
|
||||
- The selected user message and every later message are hidden, but not deleted yet.
|
||||
- The selected message's text, attachments, and agent mentions are placed in the composer for revision.
|
||||
- Captured files changed by the affected assistant steps are restored to their earlier contents. Files created by those
|
||||
steps are removed when they did not exist in the earlier snapshot.
|
||||
- A summary shows the staged message count and restored paths.
|
||||
|
||||
Running `/undo` again moves the staged boundary to an earlier user message. OpenCode keeps the filesystem state from
|
||||
immediately before the first undo as the redo baseline, so repeated undos form one wider staged revert rather than a redo
|
||||
stack.
|
||||
|
||||
<Warning>
|
||||
Sending a new prompt while an undo is staged commits the revert. The hidden message range is removed from the active
|
||||
session history, the currently reverted files are kept, and redo is no longer available.
|
||||
</Warning>
|
||||
|
||||
## Redo
|
||||
|
||||
While a revert is staged, run:
|
||||
|
||||
```text
|
||||
/redo
|
||||
```
|
||||
|
||||
Redo clears the staged boundary, makes the hidden messages visible again, and restores affected files to their exact state
|
||||
immediately before the first undo. It does not rerun the model. After multiple undos, one redo restores the whole staged
|
||||
range; there is no step-by-step redo stack.
|
||||
|
||||
## Revert a message
|
||||
|
||||
The TUI's **Message Actions** menu also provides **Revert**. It stages the selected message as the conversation boundary
|
||||
and uses the same file restoration and redo behavior, but it does not copy that message into the composer.
|
||||
|
||||
For a conversation-and-files rollback, select a user message. If an assistant message is selected, that message is hidden,
|
||||
but only file changes attributed to later assistant steps are restored; the selected assistant message's own file changes
|
||||
are not included.
|
||||
|
||||
## Limitations and safety
|
||||
|
||||
- Capture is best effort. A failed capture is logged and the model step continues, so conversation rollback may have no
|
||||
matching file rollback.
|
||||
- Interrupted or failed steps do not receive a completed end snapshot. File changes made before the failure may remain.
|
||||
- Shell commands can change databases, services, processes, network resources, Git state, ignored build output, or files
|
||||
outside the active directory. Undo and redo do not reverse those side effects.
|
||||
- Undo overwrites the current contents of affected paths with older contents. Redo likewise overwrites those paths with
|
||||
the pre-undo state, including edits made after running undo.
|
||||
- Other processes can edit the worktree between capture and restore. The server rejects revert operations while the
|
||||
session is actively running, but it cannot protect against external editors or commands.
|
||||
- Snapshot objects can contain complete contents of tracked and non-ignored untracked files. They are stored locally in
|
||||
the OpenCode data directory; do not treat snapshots as secret-free metadata.
|
||||
- Undo is not secure erasure. Committing a revert removes messages from the active projection, not from durable session
|
||||
history or existing snapshot storage.
|
||||
|
||||
Review the staged file summary and your Git diff before continuing. Commit or back up important work independently before
|
||||
using undo on a dirty worktree.
|
||||
|
||||
<Note>
|
||||
`/undo` and `/redo` are interactive commands in the default V2 TUI. The non-interactive `run` command and the minimal
|
||||
interactive interface do not provide these slash commands.
|
||||
</Note>
|
||||
Loading…
Add table
Add a link
Reference in a new issue