mirror of
https://github.com/anomalyco/opencode.git
synced 2026-10-16 11:20:42 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d08c92dbbb |
No files matched your search
+2223
-566
File diff suppressed because it is too large.
Load diff
@@ -22,11 +22,12 @@ legacy OpenCode, or migrating from V1.
|
||||
Use only <https://opencode.ai/v2/docs/> documentation as the source of truth for V2.
|
||||
Do not use <https://opencode.ai/docs/>, which documents V1, and do not use
|
||||
general web search to resolve a V2 documentation question when the V2 docs or
|
||||
linked pages cover it. The schema served from
|
||||
<https://opencode.ai/config.json> may describe V1 even though V2 configuration
|
||||
files include that URL for editor integration. Never use it to infer V2 field
|
||||
names or shapes. If V2 documentation is missing or contradictory, state the
|
||||
uncertainty or ask for clarification instead of falling back to V1.
|
||||
linked pages cover it. The native V2 schema is
|
||||
<https://opencode.ai/v2/config.json>. The schema at
|
||||
<https://opencode.ai/config.json> also accepts V1 fields for compatibility, so
|
||||
do not use it to infer V2 field names or shapes. If V2 documentation is missing
|
||||
or contradictory, state the uncertainty or ask for clarification instead of
|
||||
falling back to V1.
|
||||
|
||||
V1 documentation and syntax may be consulted only when the user explicitly
|
||||
asks about V1 or when needed as migration input. Outputs and recommendations
|
||||
@@ -74,7 +75,7 @@ autocomplete:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
}
|
||||
```
|
||||
|
||||
@@ -101,8 +102,9 @@ preferences, especially themes and keybindings.
|
||||
|
||||
Do not guess field names or shapes. Fetch the V2 configuration guide and its
|
||||
linked topic guide as the source of truth, and preserve unrelated settings when
|
||||
editing an existing file. Keep the published `$schema` URL in configuration
|
||||
examples, but do not fetch it to determine the V2 configuration shape.
|
||||
editing an existing file. Use the V2 `$schema` URL for native V2 examples;
|
||||
leave `https://opencode.ai/config.json` in existing files that still use V1
|
||||
syntax.
|
||||
|
||||
See the [full configuration guide](https://opencode.ai/v2/docs/config) for
|
||||
every field, examples, config locations, and links to dedicated feature guides.
|
||||
@@ -145,8 +147,9 @@ V1 config files and `.opencode/` definitions are intended to remain compatible.
|
||||
The only intentional breaking changes are the server API and plugin API. Native
|
||||
V2 config uses more ergonomic shapes, but conversion is optional. When the user
|
||||
requests conversion, inspect the complete configuration, preserve behavior and
|
||||
unrelated settings, and apply only the relevant migrations from the guide. For
|
||||
plugin migrations, fetch and follow both the migration guide and the full
|
||||
unrelated settings, and apply only the relevant migrations from the guide. Update
|
||||
`$schema` to `https://opencode.ai/v2/config.json` when a file is fully converted.
|
||||
For plugin migrations, fetch and follow both the migration guide and the full
|
||||
[plugins guide](https://opencode.ai/v2/docs/build/plugins). If non-API V1
|
||||
functionality fails in V2, use the `report` skill to file it as a compatibility
|
||||
bug.
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
import { isDeepStrictEqual, parseArgs } from "node:util"
|
||||
import { Schema } from "effect"
|
||||
import { Config } from "../src/config.js"
|
||||
|
||||
// Generates the JSON schemas for `opencode.json`:
|
||||
// - `--v2`: the strict schema generated from `Config.Info`, served at https://opencode.ai/v2/config.json.
|
||||
// - `--compat`: the schema served at https://opencode.ai/config.json. Core still loads V1 configs and configs that
|
||||
// mix V1 and V2 keys, so this schema accepts both. V1 keys come from `config-v1.json`, a frozen snapshot of the
|
||||
// last V1 schema, and keys only V1 accepts are marked deprecated.
|
||||
const args = parseArgs({
|
||||
options: { v2: { type: "string" }, compat: { type: "string" }, check: { type: "boolean" } },
|
||||
}).values
|
||||
if (!args.v2 && !args.compat) throw new Error("Pass --v2 and/or --compat output paths")
|
||||
|
||||
type Json = { [key: string]: unknown }
|
||||
interface ObjectSchema {
|
||||
description?: string
|
||||
properties?: Record<string, Json>
|
||||
required?: string[]
|
||||
additionalProperties?: boolean | Json
|
||||
}
|
||||
|
||||
// Core merges V1 and V2 members inside these objects; every other value must be entirely V1 or entirely V2.
|
||||
// See `packages/core/src/config/normalize.ts` and the "Migrate from V1" guide.
|
||||
const mixedObjects = new Set(["mcp", "compaction", "experimental"])
|
||||
|
||||
const generated = Schema.toJsonSchemaDocument(Config.Info, { onExcessProperty: "error" })
|
||||
const v1: { $defs: Record<string, Json> } = await Bun.file(new URL("./config-v1.json", import.meta.url)).json()
|
||||
|
||||
const v2 = {
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema",
|
||||
$id: "https://opencode.ai/v2/config.json",
|
||||
...generated.schema,
|
||||
$defs: generated.definitions,
|
||||
allowComments: true,
|
||||
allowTrailingCommas: true,
|
||||
}
|
||||
|
||||
const compat = {
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema",
|
||||
$id: "https://opencode.ai/config.json",
|
||||
...mergeObjects(
|
||||
generated.definitions[definitionName(String(generated.schema.$ref))] as ObjectSchema,
|
||||
prefixV1Refs(v1.$defs.Config) as ObjectSchema,
|
||||
(key) => mixedObjects.has(key),
|
||||
),
|
||||
$defs: {
|
||||
...generated.definitions,
|
||||
...Object.fromEntries(
|
||||
Object.entries(v1.$defs)
|
||||
.filter(([name]) => name !== "Config")
|
||||
.map(([name, schema]) => [v1Definition(name), prefixV1Refs(schema)]),
|
||||
),
|
||||
},
|
||||
allowComments: true,
|
||||
allowTrailingCommas: true,
|
||||
}
|
||||
|
||||
const outputs = [
|
||||
...(args.v2 ? [{ path: args.v2, document: v2 }] : []),
|
||||
...(args.compat ? [{ path: args.compat, document: compat }] : []),
|
||||
].map((output) => ({ path: output.path, content: `${JSON.stringify(output.document, null, 2)}\n` }))
|
||||
|
||||
if (args.check) {
|
||||
const stale = await Promise.all(
|
||||
outputs.map(async (output) => (await Bun.file(output.path).text()) !== output.content),
|
||||
)
|
||||
if (stale.some(Boolean)) {
|
||||
console.error("Generated config schemas are stale. Run `bun run generate` from services/www.")
|
||||
process.exit(1)
|
||||
}
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
await Promise.all(outputs.map((output) => Bun.write(output.path, output.content)))
|
||||
|
||||
// Merges a V2 object schema with its V1 counterpart. A member declared by only one version is checked against the
|
||||
// other version's `additionalProperties` schema as well, so V1 records such as `mcp` still accept their entries.
|
||||
// Members only V1 accepts are marked deprecated; members whose shapes differ accept either shape.
|
||||
function mergeObjects(current: ObjectSchema, legacy: ObjectSchema, mixed: (key: string) => boolean): ObjectSchema {
|
||||
const currentExtra = extraProperties(current)
|
||||
const legacyExtra = extraProperties(legacy)
|
||||
const keys = new Set([...Object.keys(current.properties ?? {}), ...Object.keys(legacy.properties ?? {})])
|
||||
const required = (current.required ?? []).filter((key) => legacy.required?.includes(key))
|
||||
return {
|
||||
...(legacy.description ? { description: legacy.description } : {}),
|
||||
type: "object",
|
||||
properties: Object.fromEntries(
|
||||
[...keys].map((key) => {
|
||||
const next = current.properties?.[key] ?? currentExtra
|
||||
const prev = legacy.properties?.[key] ?? legacyExtra
|
||||
if (!next) return [key, { ...prev, deprecated: true }]
|
||||
if (!prev) return [key, next]
|
||||
// Prefer the V1 copy of an identical shape because it carries descriptions.
|
||||
if (isDeepStrictEqual(withoutDescriptions(prev), withoutDescriptions(next))) return [key, prev]
|
||||
if (mixed(key)) return [key, mergeObjects(next, prev, () => false)]
|
||||
return [key, { anyOf: [next, prev] }]
|
||||
}),
|
||||
),
|
||||
...(required.length ? { required } : {}),
|
||||
additionalProperties:
|
||||
currentExtra && legacyExtra ? { anyOf: [currentExtra, legacyExtra] } : (currentExtra ?? legacyExtra ?? false),
|
||||
} as ObjectSchema
|
||||
}
|
||||
|
||||
function extraProperties(schema: ObjectSchema) {
|
||||
return typeof schema.additionalProperties === "object" ? schema.additionalProperties : undefined
|
||||
}
|
||||
|
||||
function definitionName(ref: string) {
|
||||
return ref.slice("#/$defs/".length)
|
||||
}
|
||||
|
||||
// V1 definitions are namespaced so they cannot collide with V2 definitions.
|
||||
function v1Definition(name: string) {
|
||||
return `V1.${name}`
|
||||
}
|
||||
|
||||
function prefixV1Refs(value: unknown): unknown {
|
||||
if (Array.isArray(value)) return value.map(prefixV1Refs)
|
||||
if (!value || typeof value !== "object") return value
|
||||
return Object.fromEntries(
|
||||
Object.entries(value).map(([key, item]) =>
|
||||
key === "$ref" && typeof item === "string" && item.startsWith("#/$defs/")
|
||||
? [key, `#/$defs/${v1Definition(definitionName(item))}`]
|
||||
: [key, prefixV1Refs(item)],
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
function withoutDescriptions(value: unknown): unknown {
|
||||
if (Array.isArray(value)) return value.map(withoutDescriptions)
|
||||
if (!value || typeof value !== "object") return value
|
||||
return Object.fromEntries(
|
||||
Object.entries(value)
|
||||
.filter(([key]) => key !== "description")
|
||||
.map(([key, item]) => [key, withoutDescriptions(item)]),
|
||||
)
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -3,3 +3,4 @@
|
||||
dist/
|
||||
node_modules/
|
||||
public/cli.json
|
||||
public/config.json
|
||||
@@ -6,6 +6,7 @@ The standard Astro website for OpenCode. The only deployment-specific path is th
|
||||
- `src/docs/` is the self-contained documentation feature rendered under `/docs`.
|
||||
- `/install` proxies the current installer.
|
||||
- `/openapi.json` serves the generated OpenAPI specification.
|
||||
- `/config.json` serves the strict V2 `opencode.json` schema. `bun run generate` also regenerates the V1-compatible schema that the console app serves at the root `https://opencode.ai/config.json`.
|
||||
|
||||
The deployment currently sets `base: "/v2"`. The `v2.opencode.ai` alias is handled by a Cloudflare Redirect Rule outside this project.
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
"dev": "bun run generate && astro dev --host --port 3000",
|
||||
"build": "bun run generate && astro build && bun script/pagefind.ts && bun run validate && bun script/prepare-cloudflare.ts",
|
||||
"deploy": "wrangler deploy --config dist/server/wrangler.json",
|
||||
"generate": "bun script/generate-openapi.ts && bun --cwd ../../packages/cli script/schema.ts ../../services/www/public/cli.json",
|
||||
"check:generated": "bun script/generate-openapi.ts --check",
|
||||
"generate": "bun script/generate-openapi.ts && bun --cwd ../../packages/cli script/schema.ts ../../services/www/public/cli.json && bun --cwd ../../packages/schema script/config-schema.ts --v2 ../../services/www/public/config.json --compat ../../packages/console/app/public/config.json",
|
||||
"check:generated": "bun script/generate-openapi.ts --check && bun --cwd ../../packages/schema script/config-schema.ts --compat ../../packages/console/app/public/config.json --check",
|
||||
"validate": "bun script/validate-links.ts",
|
||||
"typecheck": "astro check"
|
||||
},
|
||||
|
||||
@@ -65,7 +65,7 @@ Define agents under `agents` in any [OpenCode configuration file](/config):
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"agents": {
|
||||
"reviewer": {
|
||||
"description": "Reviews current changes",
|
||||
@@ -85,7 +85,7 @@ Set the primary agent used when a session has not selected one:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"default_agent": "writer",
|
||||
"agents": {
|
||||
"writer": { "mode": "primary" },
|
||||
|
||||
@@ -79,7 +79,7 @@ Configure image normalization in `opencode.json` or `opencode.jsonc`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"media": {
|
||||
"image": {
|
||||
"auto_resize": true,
|
||||
|
||||
@@ -34,7 +34,7 @@ plugins.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"plugins": [
|
||||
"opencode-acme-effect-plugin",
|
||||
"opencode-acme-effect-plugin@1.2.0",
|
||||
|
||||
@@ -23,7 +23,7 @@ or plugin directories from other locations, add them to `plugins` in `opencode.j
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"plugins": [
|
||||
"opencode-acme-plugin",
|
||||
"opencode-acme-plugin@1.2.0",
|
||||
|
||||
@@ -53,7 +53,7 @@ Define commands under `commands` in any OpenCode JSON or JSONC [configuration fi
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"commands": {
|
||||
"review": {
|
||||
"description": "Review code for correctness",
|
||||
|
||||
@@ -26,7 +26,7 @@ Automatic compaction is on by default:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"compaction": {
|
||||
"auto": true,
|
||||
"keep": { "tokens": 15000 },
|
||||
@@ -69,7 +69,7 @@ Add `compaction` to any [OpenCode configuration file](/config):
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"compaction": {
|
||||
"auto": false,
|
||||
"keep": { "tokens": 24000 },
|
||||
@@ -94,7 +94,7 @@ provider or model with `settings.compaction`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"settings": { "compaction": { "type": "native" } },
|
||||
|
||||
@@ -6,7 +6,7 @@ Create `opencode.jsonc` in your project to configure OpenCode. Add the schema fo
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
}
|
||||
```
|
||||
@@ -19,7 +19,7 @@ OpenCode supports JSON and JSONC. Use JSONC when you want comments or trailing c
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
// Use this model by default.
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
}
|
||||
@@ -71,20 +71,24 @@ which overrides the global config. Settings that do not conflict are preserved.
|
||||
## Schema
|
||||
|
||||
The complete OpenCode configuration schema is available at
|
||||
[opencode.ai/config.json](https://opencode.ai/config.json).
|
||||
[opencode.ai/v2/config.json](https://opencode.ai/v2/config.json).
|
||||
|
||||
Add the `$schema` field to your configuration file to enable validation and
|
||||
autocomplete in editors that support JSON Schema:
|
||||
|
||||
```json title="opencode.json"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json"
|
||||
"$schema": "https://opencode.ai/v2/config.json"
|
||||
}
|
||||
```
|
||||
|
||||
Use the schema as the source of truth for available fields, accepted values,
|
||||
and nested configuration shapes.
|
||||
|
||||
Files that still use V1 syntax can keep `https://opencode.ai/config.json`. That
|
||||
schema accepts V1, native V2, and mixed configuration files, and marks V1-only
|
||||
fields as deprecated.
|
||||
|
||||
### Shell
|
||||
|
||||
Set the shell used by the terminal and shell tools.
|
||||
|
||||
@@ -418,7 +418,7 @@ the [model](/models) using the format `opencode-go/<model-id>`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "opencode-go/kimi-k3",
|
||||
}
|
||||
```
|
||||
|
||||
@@ -130,7 +130,7 @@ use the format `opencode/<model-id>`:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "opencode/gpt-5.5",
|
||||
}
|
||||
```
|
||||
|
||||
@@ -7,7 +7,7 @@ them. Formatters are disabled by default, so enable them in your configuration:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"formatter": true,
|
||||
}
|
||||
```
|
||||
@@ -20,7 +20,7 @@ available.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"formatter": true,
|
||||
}
|
||||
```
|
||||
@@ -31,7 +31,7 @@ resets them to the built-ins.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"formatter": {},
|
||||
}
|
||||
```
|
||||
@@ -86,7 +86,7 @@ formatter needs both `command` and `extensions` to run.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"formatter": {
|
||||
"prettier": {
|
||||
"environment": {
|
||||
@@ -183,7 +183,7 @@ formatting that a lower-priority file enabled, set it to `false`.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"formatter": false,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -104,7 +104,7 @@ The V2 config schema accepts an `instructions` array, but V2 does not currently
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"instructions": ["CONTRIBUTING.md", "docs/guidelines/*.md", "https://example.com/instructions.md"],
|
||||
}
|
||||
```
|
||||
|
||||
@@ -31,7 +31,7 @@ To configure a server by hand, give it a unique name under `mcp.servers`. V2 doe
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"my-server": {
|
||||
@@ -86,7 +86,7 @@ Use configuration for process options such as a working directory or environment
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"everything": {
|
||||
@@ -136,7 +136,7 @@ Use configuration when the server needs headers or other options. Store secrets
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"context7": {
|
||||
@@ -182,7 +182,7 @@ For dynamic registration, configure only the server URL:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"sentry": {
|
||||
@@ -204,7 +204,7 @@ When a provider gives you client credentials, use V2's snake_case OAuth fields:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"company-tools": {
|
||||
@@ -244,7 +244,7 @@ Timeouts are positive integer milliseconds. Set defaults under `mcp.timeout`; a
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"mcp": {
|
||||
"timeout": {
|
||||
"startup": 45000,
|
||||
@@ -276,7 +276,7 @@ OpenCode opens every server with the classic MCP `initialize` handshake by defau
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"mcp": {
|
||||
"servers": {
|
||||
"modern": {
|
||||
|
||||
@@ -69,13 +69,24 @@ The recommended migration path is to ask OpenCode to update the configuration fo
|
||||
|
||||
```text
|
||||
Migrate my OpenCode configuration, including file-based definitions, from the V1 format to the native V2 format.
|
||||
Preserve its behavior and all unrelated settings.
|
||||
Preserve its behavior and all unrelated settings. When a config file is fully converted, update its $schema to
|
||||
https://opencode.ai/v2/config.json.
|
||||
```
|
||||
|
||||
OpenCode can inspect the complete file, apply the relevant changes below, and avoid rewriting settings that do not need to
|
||||
change. Conversion does not need to happen all at once: supported V1 and native V2 fields may coexist at the top level.
|
||||
When both forms set the same canonical value, a valid native V2 value takes precedence regardless of JSON key order.
|
||||
|
||||
The schema at `https://opencode.ai/config.json` accepts V1, native V2, and mixed files, and marks V1-only fields as
|
||||
deprecated. Once a file is fully converted, switch to the strict native V2 schema:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"permissions": [{ "action": "shell", "resource": "git push *", "effect": "ask" }],
|
||||
}
|
||||
```
|
||||
|
||||
Nested mixing is intentionally bounded. OpenCode recognizes mixed V1 and V2 members within `mcp`, `compaction`, and
|
||||
`experimental`, but it does not recursively infer formats inside individual agents, providers, commands, or models. Keep
|
||||
each of those nested entries entirely in one format. Supported V1 syntax remains quiet by itself; malformed values,
|
||||
|
||||
@@ -43,7 +43,7 @@ Set `model` in `opencode.json` or `opencode.jsonc` to choose the default for new
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "anthropic/claude-sonnet-4-5",
|
||||
}
|
||||
```
|
||||
@@ -73,7 +73,7 @@ Define new variants, or replace catalog variants with the same ID, in the model'
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"models": {
|
||||
@@ -153,7 +153,7 @@ Use `modelID` to give an API model a friendlier catalog ID:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "openai/coding-default",
|
||||
"providers": {
|
||||
"openai": {
|
||||
@@ -243,7 +243,7 @@ With Ollama listening at `http://127.0.0.1:11434`, select a discovered model wit
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "ollama/gemma3:4b",
|
||||
}
|
||||
```
|
||||
@@ -277,7 +277,7 @@ provider ID:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "lmstudio/google/gemma-4-26b-a4b",
|
||||
}
|
||||
```
|
||||
@@ -309,7 +309,7 @@ With vLLM listening at `http://127.0.0.1:8000`, select a discovered model with t
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "vllm/Qwen/Qwen3-Coder-30B-A3B-Instruct",
|
||||
}
|
||||
```
|
||||
@@ -346,7 +346,7 @@ For another OpenAI-compatible server, define its provider package, endpoint, and
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "local/coder",
|
||||
"providers": {
|
||||
"local": {
|
||||
|
||||
@@ -11,7 +11,7 @@ inspection, and always block pushes. Add these ordered rules to `opencode.jsonc`
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"permissions": [
|
||||
{ "action": "shell", "resource": "*", "effect": "ask" },
|
||||
{ "action": "shell", "resource": "git status *", "effect": "allow" },
|
||||
@@ -142,7 +142,7 @@ A path outside both the active Location and its non-root project worktree needs
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"permissions": [
|
||||
{ "action": "external_directory", "resource": "~/projects/reference/*", "effect": "allow" },
|
||||
{ "action": "read", "resource": "~/projects/reference/*", "effect": "allow" },
|
||||
@@ -179,7 +179,7 @@ Enable the experimental portable shell scanner with:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"experimental": {
|
||||
"portable_shell_scanner": true,
|
||||
},
|
||||
@@ -232,7 +232,7 @@ Put shared rules at the top level and narrower rules under
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"permissions": [
|
||||
{ "action": "shell", "resource": "*", "effect": "ask" },
|
||||
{ "action": "shell", "resource": "git status *", "effect": "allow" },
|
||||
|
||||
@@ -8,7 +8,7 @@ Add published packages, versioned packages, scoped packages, or local plugin dir
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"plugins": [
|
||||
"opencode-acme-plugin",
|
||||
"opencode-acme-plugin@1.2.0",
|
||||
|
||||
@@ -17,7 +17,7 @@ Deny one provider everywhere by adding a statement to `opencode.jsonc`:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"experimental": {
|
||||
"policies": [{ "action": "provider.use", "resource": "openai", "effect": "deny" }],
|
||||
},
|
||||
|
||||
@@ -34,7 +34,7 @@ runtime package, endpoint, and first model together.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"name": "Acme",
|
||||
@@ -73,7 +73,7 @@ models, and connection still apply.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"anthropic": {
|
||||
"settings": {
|
||||
@@ -92,7 +92,7 @@ Use `headers` for additional HTTP headers and `body` for JSON fields that should
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"headers": {
|
||||
@@ -112,7 +112,7 @@ Both fields can also be set on a model or variant when only part of a provider's
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"models": {
|
||||
@@ -141,7 +141,7 @@ WebSocket transport, `chunkTimeout` bounds the gap between frames instead and de
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"anthropic": {
|
||||
"settings": {
|
||||
@@ -163,7 +163,7 @@ implement the OpenAI request format.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"package": "@opencode/ai/providers/openai-compatible",
|
||||
@@ -207,7 +207,7 @@ You can also use an npm package such as `@acme/opencode-provider` or an absolute
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"package": "@acme/opencode-provider",
|
||||
@@ -224,7 +224,7 @@ ID sent to the provider.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "openai/coding",
|
||||
"providers": {
|
||||
"openai": {
|
||||
@@ -265,7 +265,7 @@ once, then connect an API key or use the Microsoft Entra ID session from the Azu
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"azure": {
|
||||
"settings": {
|
||||
@@ -336,7 +336,7 @@ kept.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"azure": {
|
||||
"models": {
|
||||
@@ -375,7 +375,7 @@ identity token file, or container credential URI activates the provider; a regio
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"amazon-bedrock": {
|
||||
"settings": {
|
||||
@@ -392,7 +392,7 @@ VPC endpoint, set `baseURL` while keeping the same profile and region.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"amazon-bedrock": {
|
||||
"settings": {
|
||||
@@ -419,7 +419,7 @@ gcloud auth application-default login
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"google-vertex": {
|
||||
"settings": {
|
||||
@@ -489,7 +489,7 @@ model requests.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"ollama": {
|
||||
"settings": {
|
||||
@@ -511,7 +511,7 @@ LM Studio and vLLM also have built-in local discovery. Their default endpoints a
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"lmstudio": {
|
||||
"settings": { "baseURL": "http://gpu-host:1234/v1" },
|
||||
@@ -534,7 +534,7 @@ OpenRouter account, then refer to models with the full OpenRouter model ID after
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "openrouter/anthropic/claude-sonnet-4",
|
||||
}
|
||||
```
|
||||
@@ -544,7 +544,7 @@ This preserves OpenRouter request and reasoning behavior.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"openrouter": {
|
||||
"settings": {
|
||||
@@ -563,7 +563,7 @@ The configuration key becomes the provider prefix and each `models` key becomes
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"model": "company/coder",
|
||||
"providers": {
|
||||
"company": {
|
||||
@@ -607,7 +607,7 @@ sessions.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"providers": {
|
||||
"openai": {
|
||||
"settings": { "transport": "http" },
|
||||
|
||||
@@ -8,7 +8,7 @@ your client when you need it.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"references": {
|
||||
"docs": {
|
||||
"path": "../product-docs",
|
||||
|
||||
@@ -67,7 +67,7 @@ Add more local directories or HTTP catalogs with the `skills` array in any `open
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"skills": [
|
||||
"./team-skills",
|
||||
"~/shared/opencode-skills",
|
||||
|
||||
@@ -103,7 +103,7 @@ filesystem capture.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"snapshots": false,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -10,7 +10,7 @@ Enable warming in any [OpenCode configuration file](/config):
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"warming": true,
|
||||
}
|
||||
```
|
||||
@@ -26,7 +26,7 @@ window:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"warming": {
|
||||
"prompt": "Do not perform any work. Reply with exactly: OK",
|
||||
"interval": "5 minutes",
|
||||
|
||||
@@ -34,7 +34,7 @@ Set a provider in `opencode.jsonc` to skip the selection prompt.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"websearch": {
|
||||
"provider": "tavily",
|
||||
},
|
||||
@@ -45,7 +45,7 @@ Use `"random"` to choose an available provider automatically. Each session keeps
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"websearch": {
|
||||
"provider": "random",
|
||||
},
|
||||
@@ -70,7 +70,7 @@ Web searches use the `websearch` permission action and the search query as the r
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"permissions": [
|
||||
{
|
||||
"action": "websearch",
|
||||
@@ -89,7 +89,7 @@ Set `websearch` to `false` to remove the web search tool from model requests.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"$schema": "https://opencode.ai/v2/config.json",
|
||||
"websearch": false,
|
||||
}
|
||||
```
|
||||
Reference in new issue
Block a user