diff --git a/.opencode/plugins/README.md b/.opencode/plugins/README.md index 715994c..fe02690 100644 --- a/.opencode/plugins/README.md +++ b/.opencode/plugins/README.md @@ -5,7 +5,7 @@ Working examples of OpenCode plugins. Drop-in to any project — pure JS, no npm | Plugin | What it does | |---|---| | [`protect-secrets.js`](protect-secrets.js) | Blocks any tool call (read/write/bash) touching `.env*`, `secrets/`, `credentials*`, SSH keys, `.npmrc`, `.pypirc`. | -| [`audit-log.js`](audit-log.js) | Appends a one-line JSON record of every successful tool call to `.opencode/audit.jsonl`. | +| [`audit-log.js`](audit-log.js) | Appends a one-line JSON record of every completed tool call to `.opencode/audit.jsonl`. | ## How they load @@ -25,7 +25,7 @@ tail -f .opencode/audit.jsonl # watch tool calls live Sample line: ```json -{"ts":"2026-05-18T19:30:12.451Z","tool":"edit","ok":true,"input_keys":["file_path","old_string","new_string"]} +{"ts":"2026-06-08T19:30:12.451Z","tool":"edit","arg_keys":["filePath","oldString","newString"],"title":"src/api/auth.ts"} ``` ## Disabling temporarily diff --git a/.opencode/plugins/audit-log.js b/.opencode/plugins/audit-log.js index bba1a1d..2d7c2c2 100644 --- a/.opencode/plugins/audit-log.js +++ b/.opencode/plugins/audit-log.js @@ -1,6 +1,6 @@ // .opencode/plugins/audit-log.js // -// Append a JSONL record of every successful tool call to .opencode/audit.jsonl. +// Append a JSONL record of every completed tool call to .opencode/audit.jsonl. // Useful as an after-the-fact paper trail of what the agent did this session. // // Toggle off by deleting this file or by gating with an env var: @@ -15,19 +15,16 @@ export const AuditLog = async ({ directory }) => { await mkdir(dirname(logPath), { recursive: true }); return { - event: async ({ event }) => { - if (event?.type !== "tool.execute.after") return; - + // `tool.execute.after` is a top-level hook with an (input, output) signature, + // fired once a tool call completes. `input.tool`/`input.args` describe the + // call; `output.title` is OpenCode's short summary of the result. + "tool.execute.after": async (input, output) => { const record = { ts: new Date().toISOString(), - tool: event.tool, - ok: !event.error, - // Capture small inputs only — full inputs can be huge (file content, diffs) - input_keys: event.input ? Object.keys(event.input) : [], - // Truncate long error messages - error: event.error - ? String(event.error).slice(0, 240) - : undefined, + tool: input.tool, + // Capture argument keys only — full args can be huge (file content, diffs) + arg_keys: input.args ? Object.keys(input.args) : [], + title: output?.title, }; await appendFile(logPath, JSON.stringify(record) + "\n"); diff --git a/.opencode/plugins/protect-secrets.js b/.opencode/plugins/protect-secrets.js index a6e4bc6..600b4c3 100644 --- a/.opencode/plugins/protect-secrets.js +++ b/.opencode/plugins/protect-secrets.js @@ -7,27 +7,30 @@ const SENSITIVE = /(^|\/)(\.env(\..*)?|secrets|credentials|id_rsa|id_ed25519|\.npmrc|\.pypirc)(\b|\/)/i; -function pathFromInput(toolName, input) { - if (!input || typeof input !== "object") return ""; +// Pull the most likely path/command field out of a tool's arguments. +// `read`/`edit`/`write` use `filePath`; `bash` uses `command`; others vary. +function targetFromArgs(args) { + if (!args || typeof args !== "object") return ""; return ( - input.path ?? - input.file_path ?? - input.filePath ?? - input.target ?? - input.command ?? // for bash tool, scan the command line itself + args.filePath ?? + args.path ?? + args.file_path ?? + args.target ?? + args.command ?? // bash: scan the command line itself "" ); } export const ProtectSecrets = async () => { return { - event: async ({ event }) => { - if (event?.type !== "tool.execute.before") return; - - const candidate = pathFromInput(event.tool, event.input); + // `tool.execute.before` is a top-level hook with an (input, output) signature. + // `input.tool` is the tool name; `output.args` holds its (mutable) arguments. + // Throwing here aborts the tool call before it runs. + "tool.execute.before": async (input, output) => { + const candidate = targetFromArgs(output?.args); if (candidate && SENSITIVE.test(String(candidate))) { throw new Error( - `[protect-secrets] blocked ${event.tool} on sensitive path: ${candidate}` + `[protect-secrets] blocked ${input.tool} on sensitive path: ${candidate}` ); } }, diff --git a/README.md b/README.md index 51c8507..ea50e94 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ A practical guide to [OpenCode](https://opencode.ai) — from your first prompt to custom agents, skills, plugins, and MCP integrations. Built around clear mental models and real examples, not marketing. [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) -[![OpenCode v1.15.4](https://img.shields.io/badge/OpenCode-v1.15.4-7C3AED?style=flat-square)](https://github.com/anomalyco/opencode/releases) -[![Last reviewed](https://img.shields.io/badge/last%20reviewed-May%202026-22c55e?style=flat-square)](#updates--deprecations) +[![OpenCode v1.16.2](https://img.shields.io/badge/OpenCode-v1.16.2-7C3AED?style=flat-square)](https://github.com/anomalyco/opencode/releases) +[![Last reviewed](https://img.shields.io/badge/last%20reviewed-June%202026-22c55e?style=flat-square)](#updates--deprecations) [![PRs welcome](https://img.shields.io/badge/PRs-welcome-ff69b4?style=flat-square)](CONTRIBUTING.md) ```bash @@ -115,7 +115,7 @@ scoop install opencode # Windows choco install opencode # Windows sudo pacman -S opencode # Arch paru -S opencode-bin # Arch (AUR) -mise use -g opencode # mise users +mise use -g github:anomalyco/opencode # mise users nix run nixpkgs#opencode # Nix ``` @@ -201,7 +201,7 @@ Per-agent model override: { "agent": { "plan": { "model": "anthropic/claude-haiku-4-5" }, - "deep-thinker": { "model": "openai/gpt-5", "reasoningEffort": "high" } + "deep-thinker": { "model": "openai/gpt-5", "options": { "reasoningEffort": "high" } } } } ``` @@ -217,23 +217,23 @@ A curated, pay-as-you-go AI gateway. The OpenCode team tests and tunes models fo /models # browse the lineup ``` -**Pricing snapshot** *(verified 2026-05-18; check [opencode.ai/docs/zen](https://opencode.ai/docs/zen) for current)* +**Pricing snapshot** *(verified 2026-06-08; check [opencode.ai/docs/zen](https://opencode.ai/docs/zen) for current)* | Model ID | Input / Output (per MTok) | Reach for it when… | |---|---|---| -| `opencode/claude-opus-4-7` | $5 / $25 | Complex reasoning, large refactors | +| `opencode/claude-opus-4-8` | $5 / $25 | Flagship reasoning — complex refactors, large multi-file work | | `opencode/claude-sonnet-4-6` | $3 / $15 | Balanced everyday coding | | `opencode/claude-haiku-4-5` | $1 / $5 | Fast, lightweight tasks | | `opencode/gpt-5.5` *(≤272K)* | $5 / $30 | Long-context, OpenAI ecosystem | | `opencode/gpt-5.4-mini` | $0.75 / $4.50 | Cost-efficient frontier | | `opencode/gemini-3.1-pro` | $2 / $12 | Multimodal, Google ecosystem | -| `opencode/qwen3.6-plus` | $0.50 / $3 | Budget-friendly heavy lifting | +| `opencode/qwen3.7-plus` | $0.40 / $1.60 | Budget-friendly heavy lifting | -**Free tier** *(rotating, time-limited, for community feedback):* `deepseek-v4-flash-free`, `minimax-m2.5-free`, `nemotron-3-super-free`, `big-pickle` *(stealth)*. +**Free tier** *(rotating, time-limited, for community feedback):* `big-pickle` *(stealth)*, `deepseek-v4-flash-free`, `mimo-v2.5-free`, `nemotron-3-ultra-free`. -> 40+ models total — full list, cached-read/write rates, GPT 5 Codex variants, GLM, Kimi, Claude Opus 4.5/4.6/4.1, etc.: [opencode.ai/docs/zen](https://opencode.ai/docs/zen) · Deeper guide: [`docs/zen.md`](docs/zen.md). +> 50+ models total — full list, cached-read/write rates, GPT-5 Codex variants, Gemini, GLM, Kimi, MiniMax, Grok, and the Claude Opus 4.8/4.7/4.5/4.1 line: [opencode.ai/docs/zen](https://opencode.ai/docs/zen) · Deeper guide: [`docs/zen.md`](docs/zen.md). -> 💡 **Pattern: cheap explorer / strong executor.** Use a cheap model (`qwen3.6-plus`, `gpt-5.4-mini`) for `explore` and `scout` subagents that read a lot, and a stronger one (`claude-sonnet-4-6` or `claude-opus-4-7`) for the main `build` agent that does the editing. +> 💡 **Pattern: cheap explorer / strong executor.** Use a cheap model (`qwen3.7-plus`, `gpt-5.4-mini`) for `explore` and `scout` subagents that read a lot, and a stronger one (`claude-sonnet-4-6` or `claude-opus-4-8`) for the main `build` agent that does the editing. --- @@ -362,7 +362,7 @@ opencode github install # add a workflow file to your repo opencode pr 123 # check out PR #123 and start a session ``` -Useful `run` flags: `--continue` / `--session ` (resume), `--share` (publish), `--format json` (machine-readable), `--file ` (attach), `--dangerously-skip-permissions` (auto-approve everything not `deny` — **CI only**). +Useful `run` flags: `--continue` / `--session ` (resume), `--fork` (branch a session), `--share` (publish), `--format json` (machine-readable), `--file ` (attach), `--replay` (interactive replay, v1.16+), `--dangerously-skip-permissions` (auto-approve everything not `deny` — **CI only**). Sessions, stats, sharing: @@ -529,7 +529,7 @@ Plus npm packages via the `plugin` array in `opencode.json`: Auto-installed via Bun, cached under `~/.cache/opencode/node_modules/`. -Plugins receive `{ project, directory, worktree, client, $ }` and return event handlers. `$` is the Bun shell. Events span tools, files, sessions, messages, permissions, LSP, TUI — ~25 total. +Plugins receive `{ project, directory, worktree, client, $ }` and return hooks. `$` is the Bun shell. Two shapes: typed hooks like `tool.execute.before`/`shell.env` that get `(input, output)`, and a generic `event` handler for the lifecycle stream (files, sessions, messages, permissions, LSP, TUI — ~26 events). This repo ships two working examples in [`.opencode/plugins/`](.opencode/plugins/): @@ -588,11 +588,11 @@ Filename → agent name. `frontend-engineer.md` → `@frontend-engineer` (subage | `subagent` | `@` mentions only (runs in a child session) | | `all` | Both | -Bash permissions accept a **glob-pattern map** (`{"*": "ask", "git status*": "allow", "rm -rf*": "deny"}`) — most-specific match wins. +Bash permissions accept a **glob-pattern map** (`{"*": "ask", "git status*": "allow", "rm -rf*": "deny"}`) — rules match in order and the **last matching rule wins**, so list the catch-all `*` first. > 📐 This repo ships **drop-in specialist prompts** in [`specialized-agents/`](specialized-agents/) — backend, frontend, code reviewer, security reviewer, tech lead, database, UX. Copy any of them into `.opencode/agents/.md` to use. -> 📚 Deep dive — full frontmatter key list, all 17 permission keys, JSON-form alternative: [`docs/agents.md`](docs/agents.md) · [`docs/reference/permissions.md`](docs/reference/permissions.md). +> 📚 Deep dive — full frontmatter key list, all 15 permission keys, JSON-form alternative: [`docs/agents.md`](docs/agents.md) · [`docs/reference/permissions.md`](docs/reference/permissions.md). --- @@ -671,16 +671,22 @@ Set `bash` permission to `"ask"` at the project level, or use the glob form to w *[→ Full changelog in `docs/reference/changelog.md`](docs/reference/changelog.md)* -**Current release:** **v1.15.4** *(2026-05-17)*. Run `opencode upgrade` to get it. +**Current release:** **v1.16.2** *(2026-06-05)*. Run `opencode upgrade` to get it. -**Recent highlights:** +**New in v1.16:** -- 🆕 **Agent Skills compatibility** — auto-discoverable workflows via `SKILL.md` (Claude Code-compatible). -- 🆕 **Glob-pattern bash permissions** — fine-grained allow/ask/deny per command pattern. -- 🆕 **Remote MCP with auto-OAuth** — Dynamic Client Registration handled out of the box. -- 🆕 **Desktop app (beta)** — macOS, Windows, Linux at [opencode.ai/download](https://opencode.ai/download). -- 🆕 **ACP server (`opencode acp`)** — Agent Client Protocol for editor integrations. -- 🆕 **Managed configs** — macOS `/Library/Application Support/opencode/`, Linux `/etc/opencode/`, Windows `%ProgramData%\opencode`, plus macOS MDM preferences. +- 🆕 **File-based agents & skill discovery** — drop-in agent markdown files and `SKILL.md` discovery are GA; scaffold an agent with `opencode agent create`. +- 🆕 **Workspace cloning & session mobility** — managed workspace clones keep dirty/untracked files, and you can move sessions between workspaces and directories. +- 🆕 **`opencode run --replay`** — interactively replay a run as it streams. +- 🆕 **OpenAI models via AWS Bedrock** — plus GitHub Copilot token-based usage tracking. +- ⚡ **~38% faster startup**, and a desktop app refresh (color themes, thinking-level selector, Servers tab). + +**Still recent (v1.15):** + +- **Glob-pattern bash permissions** — fine-grained allow/ask/deny per command pattern (rules match in order, last match wins). +- **Remote MCP with auto-OAuth** — Dynamic Client Registration handled out of the box. +- **ACP server (`opencode acp`)** — Agent Client Protocol for editor integrations. +- **Managed configs** — macOS `/Library/Application Support/opencode/`, Linux `/etc/opencode/`, Windows `%ProgramData%\opencode`, plus macOS MDM preferences. - 📝 **AGENTS.md** is canonical; `CLAUDE.md` is now a fallback only. > 💡 Source of truth: [GitHub releases](https://github.com/anomalyco/opencode/releases). @@ -705,4 +711,4 @@ Set `bash` permission to `"ask"` at the project level, or use the glob form to w > Features, pricing, and availability change frequently. Always check the [official OpenCode documentation](https://opencode.ai/docs/) for the most current information. -*Last reviewed 2026-05-18 · OpenCode v1.15.4 · Spotted something stale? [Open an issue](../../issues) or send a PR — see [`CONTRIBUTING.md`](CONTRIBUTING.md).* +*Last reviewed 2026-06-08 · OpenCode v1.16.2 · Spotted something stale? [Open an issue](../../issues) or send a PR — see [`CONTRIBUTING.md`](CONTRIBUTING.md).* diff --git a/docs/agents.md b/docs/agents.md index 5f0fc27..d39186d 100644 --- a/docs/agents.md +++ b/docs/agents.md @@ -25,6 +25,8 @@ Two locations, same format: | Project | `.opencode/agents/.md` | | Global | `~/.config/opencode/agents/.md` | +> 🆕 File-based agent loading is GA as of v1.16. Scaffold one interactively with `opencode agent create` (it prompts for location, description, mode, model, and permissions), or just write the markdown by hand. + ```markdown --- description: Senior frontend engineer — Tailwind + React + TypeScript expert @@ -61,10 +63,10 @@ Verified against the [config JSON schema's `AgentConfig`](https://opencode.ai/co | `model` | `provider/model-id` | Per-agent model override | | `temperature` · `top_p` | number | Sampling controls | | `permission` | object | Per-tool `allow`/`ask`/`deny` (see below) | -| `tools` | object | Boolean per tool — `{"websearch": false}` | +| `tools` | object | *Deprecated — prefer `permission`.* Boolean per tool — `{"websearch": false}` | | `prompt` *(JSON form only)* | string | System prompt; alternative to markdown body | -| `maxSteps` | number | Hard cap on agent steps in one invocation | -| `steps` | array | Scripted step sequence (advanced) | +| `steps` | number | Max agentic iterations before a forced text-only response | +| `maxSteps` | number | *Deprecated — use `steps`.* | | `disable` | boolean | Disable an agent entirely | | `hidden` | boolean | Hide from the UI but keep available | | `color` | string | UI accent color | @@ -100,7 +102,6 @@ Permission keys (verified against `PermissionConfig` in the [config JSON schema] | `todowrite` | the in-session todo list | | `question` | the `question` tool | | `external_directory` | files outside the project root | -| `repo_clone` · `repo_overview` | repo-level operations | | `webfetch` · `websearch` | network access | | `lsp` | language server tools | | `skill` | agent skill loading | @@ -110,18 +111,18 @@ Three values everywhere: `"allow"` (no prompt) · `"ask"` (prompt user) · `"den ### Glob-pattern bash -The `bash` key can be a single value or a glob-map. **Order matters**: most specific patterns first. +The `bash` key can be a single value or a glob-map. **Order matters**: rules are matched in order and the **last matching rule wins**, so put the catch-all `*` first and the more specific overrides after it. ```json { "permission": { "bash": { - "rm -rf*": "deny", - "git push --force*": "deny", + "*": "ask", "git status*": "allow", "git diff*": "allow", "pnpm test*": "allow", - "*": "ask" + "git push --force*": "deny", + "rm -rf*": "deny" } } } @@ -136,9 +137,9 @@ Use this to keep an agent productive (no constant prompting for safe reads) whil "agent": { "explore": { "model": "opencode/qwen3.6-plus" }, "scout": { "model": "opencode/qwen3.6-plus" }, - "plan": { "model": "opencode/claude-opus-4-7" }, + "plan": { "model": "opencode/claude-opus-4-8" }, "build": { "model": "opencode/claude-sonnet-4-6" }, - "deep-thinker": { "model": "openai/gpt-5", "reasoningEffort": "high" } + "deep-thinker": { "model": "openai/gpt-5", "options": { "reasoningEffort": "high" } } } } ``` @@ -150,6 +151,8 @@ If unspecified: ## Tools per agent +> ⚠️ The `tools` map is **deprecated** in favor of the `permission` field (set a tool to `"deny"` to disable it). It still works and remains the simplest way to gate MCP tools by glob, but prefer `permission` for new configs. + The `tools` map enables/disables individual tools by name, including MCP tools (use glob patterns): ```json @@ -224,6 +227,6 @@ permission: ## Drop-in specialists -This repo ships 10 production-ready prompts in [`specialized-agents/`](../specialized-agents/). Copy any of them to `.opencode/agents/.md` to use as a starting point. +This repo ships 7 production-ready prompts in [`specialized-agents/`](../specialized-agents/) — backend, frontend, code reviewer, security reviewer, tech lead, database, and UX. Copy any of them to `.opencode/agents/.md` to use as a starting point. > 📚 Full agent reference: [opencode.ai/docs/agents](https://opencode.ai/docs/agents). diff --git a/docs/commands.md b/docs/commands.md index 7f9f389..c0e81ff 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -114,7 +114,7 @@ Invoke with: `/scaffold-component UserAvatar` description: Deep architectural review (isolated context) agent: build subtask: true -model: opencode/claude-opus-4-7 +model: opencode/claude-opus-4-8 --- You are reviewing the architectural integrity of $ARGUMENTS. @@ -157,7 +157,7 @@ If a command always runs with a particular model or agent, put it in the frontma --- description: Long, deep refactor planning (Opus only) agent: plan -model: opencode/claude-opus-4-7 +model: opencode/claude-opus-4-8 --- ``` diff --git a/docs/mcp.md b/docs/mcp.md index e9e4dfa..a94bdf9 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -123,15 +123,18 @@ For servers that require pre-registered credentials: } ``` -### Managing OAuth from the CLI +### Managing servers from the CLI ```bash +opencode mcp add # interactively register a local or remote server +opencode mcp list # show servers and auth status opencode mcp auth sentry # complete or refresh OAuth flow opencode mcp logout sentry # forget stored credentials opencode mcp debug sentry # diagnose connection issues -opencode mcp list # show servers and auth status ``` +`opencode mcp add` walks you through type, command/URL, and headers, then writes the entry to your config — the no-hand-editing alternative to the JSON blocks above. + ## Token budget warning MCP tools land in the model's tool surface every turn. Heavy servers (e.g., a full GitHub MCP with dozens of tools) can easily eat 10K+ tokens of context — purely for tool *descriptions* the model may never actually call. diff --git a/docs/migration.md b/docs/migration.md index 5b9737d..b86b90c 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -114,9 +114,11 @@ OpenCode equivalent (`.opencode/plugins/protect-env.js`): ```javascript export const ProtectEnv = async () => { return { - event: async ({ event }) => { - if (event.type === "tool.execute.before" && event.tool === "edit") { - if ((event.input?.path ?? "").includes(".env")) { + // `tool.execute.before` is a top-level hook: (input, output). `input.tool` + // names the tool; `output.args` holds its arguments. Throw to block. + "tool.execute.before": async (input, output) => { + if (input.tool === "edit" || input.tool === "write") { + if ((output?.args?.filePath ?? "").includes(".env")) { throw new Error("Plugin blocked: cannot write .env"); } } @@ -226,4 +228,4 @@ Migration is mostly muscle-memory adjustment, not config porting. --- -*Last reviewed: 2026-05-18 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* +*Last reviewed: 2026-06-08 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* diff --git a/docs/plugins.md b/docs/plugins.md index 1c9a965..c379f95 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -57,7 +57,7 @@ opencode plugin --global opencode-wakatime ## Plugin API -A plugin is a default-export async function returning an object of event handlers: +A plugin is a default-export async function returning an object of **hooks**. There are two shapes: typed hooks like `tool.execute.before` that receive `(input, output)`, and a generic `event` handler that receives the lifecycle event stream: ```javascript // .opencode/plugins/notify-on-idle.js @@ -82,13 +82,24 @@ export const NotifyOnIdle = async ({ project, client, $, directory, worktree }) | `client` | OpenCode SDK client — call back into OpenCode from inside the plugin | | `$` | Bun shell — run commands; supports tagged-template syntax | -### Available events +### Hooks and events + +Two distinct shapes — don't confuse them. **Typed hooks** are top-level keys called with `(input, output)`; use them to inspect or mutate one operation (and `throw` to block it). The generic **`event`** handler receives a read-only lifecycle stream you match on `event.type`. Verified against the [Plugins doc](https://opencode.ai/docs/plugins): -| Category | Events | +**Typed hooks** — `"hook.name": async (input, output) => { … }`: + +| Hook | Fires | Key fields | +|---|---|---| +| `tool.execute.before` | Before a tool runs | `input.tool`; `output.args` (mutable) — `throw` to block | +| `tool.execute.after` | After a tool completes | `input.tool`, `input.args`; `output.title` / `output.output` | +| `shell.env` | Resolving shell environment | `input.cwd`; `output.env` (mutable) | + +**Event stream** — `event: async ({ event }) => { if (event.type === …) }`: + +| Category | `event.type` values | |---|---| -| **Tools** | `tool.execute.before`, `tool.execute.after` | | **Files** | `file.edited`, `file.watcher.updated` | | **Sessions** | `session.created`, `session.updated`, `session.compacted`, `session.idle`, `session.status`, `session.error`, `session.diff`, `session.deleted` | | **Messages** | `message.updated`, `message.removed`, `message.part.updated`, `message.part.removed` | @@ -96,11 +107,11 @@ Verified against the [Plugins doc](https://opencode.ai/docs/plugins): | **Permissions** | `permission.asked`, `permission.replied` | | **LSP** | `lsp.client.diagnostics`, `lsp.updated` | | **Server / installation** | `server.connected`, `installation.updated` | -| **Shell** | `shell.env` | | **Todo** | `todo.updated` | | **TUI** | `tui.prompt.append`, `tui.command.execute`, `tui.toast.show` | +| **Experimental** | `experimental.session.compacting` | -> 📚 Each event carries event-specific payload. Full reference: [opencode.ai/docs/plugins](https://opencode.ai/docs/plugins). +> 📚 Each hook/event carries its own payload. Full reference: [opencode.ai/docs/plugins](https://opencode.ai/docs/plugins). ## Common patterns @@ -140,18 +151,15 @@ export const AuditLog = async ({ directory }) => { const logPath = `${directory}/.opencode/audit.jsonl`; return { - event: async ({ event }) => { - if (event.type === "tool.execute.after") { - await appendFile( - logPath, - JSON.stringify({ - ts: new Date().toISOString(), - tool: event.tool, - input: event.input, - success: !event.error, - }) + "\n" - ); - } + "tool.execute.after": async (input, output) => { + await appendFile( + logPath, + JSON.stringify({ + ts: new Date().toISOString(), + tool: input.tool, + title: output?.title, + }) + "\n" + ); }, }; }; @@ -175,14 +183,14 @@ export const NotifyOnIdle = async ({ $ }) => { ### 4. Block sensitive paths -Prevent any edits to `.env` files or `secrets/` directories: +Prevent any edit to `.env` files or `secrets/` directories. `tool.execute.before` is a top-level hook — throwing aborts the call before it runs: ```javascript -export const ProtectSecrets = async ({ client }) => { +export const ProtectSecrets = async () => { return { - event: async ({ event }) => { - if (event.type === "tool.execute.before" && event.tool === "edit") { - const path = event.input?.path ?? ""; + "tool.execute.before": async (input, output) => { + if (input.tool === "edit" || input.tool === "write") { + const path = output?.args?.filePath ?? ""; if (/\.env|secrets\//i.test(path)) { throw new Error(`Plugin blocked: ${path} is a protected path`); } diff --git a/docs/quickstart.md b/docs/quickstart.md index 21f4974..216796f 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -14,9 +14,10 @@ curl -fsSL https://opencode.ai/install | bash npm i -g opencode-ai@latest brew install anomalyco/tap/opencode scoop install opencode +choco install opencode sudo pacman -S opencode paru -S opencode-bin -mise use -g opencode +mise use -g github:anomalyco/opencode nix run nixpkgs#opencode ``` @@ -104,9 +105,9 @@ Run `opencode auth login` and pick a provider. Re-run `/connect` from inside the ```bash opencode upgrade # latest -opencode upgrade v1.15.0 # specific version +opencode upgrade v1.16.0 # specific version ``` --- -*Last reviewed: 2026-05-18 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* +*Last reviewed: 2026-06-08 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* diff --git a/docs/reference/changelog.md b/docs/reference/changelog.md index 11eb77f..09cfca3 100644 --- a/docs/reference/changelog.md +++ b/docs/reference/changelog.md @@ -4,16 +4,30 @@ This document tracks **what's new at a high level** — the things that change how you use OpenCode. Bug fixes and small polish items aren't listed here. -## v1.15.x — May 2026 +## v1.16.x — June 2026 Current stable line. Run `opencode upgrade` to get the latest. -**Verified latest release:** `v1.15.4`, published 2026-05-17 17:44 UTC ([GitHub release](https://github.com/anomalyco/opencode/releases/tag/v1.15.4)). +**Verified latest release:** `v1.16.2`, published 2026-06-05 ([GitHub release](https://github.com/anomalyco/opencode/releases/tag/v1.16.2)). The headline features shipped in `v1.16.0` the same day. + +**Highlights:** + +- **File-based agent loading & skill discovery** — drop-in agent markdown files and `SKILL.md` discovery are GA; scaffold an agent with `opencode agent create`. +- **Managed workspace cloning** — clones keep dirty and untracked files intact. +- **Session mobility** — move sessions between workspaces and directories. +- **`opencode run --replay`** — interactive replay of a run as it streams. +- **OpenAI models via AWS Bedrock**, plus GitHub Copilot token-based usage tracking. +- **~38% faster startup**, and a desktop app refresh (color themes, thinking-level selector, Servers tab, in-app updates). +- **GitHub extension** now requires an existing git author identity before committing. + +## v1.15.x — May 2026 + +**Latest:** `v1.15.4`, published 2026-05-17 17:44 UTC ([GitHub release](https://github.com/anomalyco/opencode/releases/tag/v1.15.4)). **Highlights:** - **Agent Skills compatibility** — discoverable workflows via `SKILL.md` folders; compatible with Claude Code skill format. -- **Glob-pattern bash permissions** — fine-grained `allow`/`ask`/`deny` per command pattern, with most-specific wins. +- **Glob-pattern bash permissions** — fine-grained `allow`/`ask`/`deny` per command pattern; rules match in order with the last match winning (list `*` first). - **Managed configs** — `/Library/Application Support/opencode/` (macOS), `/etc/opencode/` (Linux), `%ProgramData%\opencode` (Windows), plus macOS MDM preferences for enterprise rollouts. - **ACP server** (`opencode acp`) — Agent Client Protocol server for editor integrations. - **Remote MCP with auto-OAuth** — Dynamic Client Registration (RFC 7591) handled automatically. @@ -61,4 +75,4 @@ For the current state, check the [GitHub repo](https://github.com/anomalyco/open --- -*Last reviewed: 2026-05-18 · For the authoritative list, see [GitHub releases](https://github.com/anomalyco/opencode/releases) · Canonical docs: [opencode.ai/docs](https://opencode.ai/docs/).* +*Last reviewed: 2026-06-08 · For the authoritative list, see [GitHub releases](https://github.com/anomalyco/opencode/releases) · Canonical docs: [opencode.ai/docs](https://opencode.ai/docs/).* diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 7cd58f5..4c122c6 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -71,6 +71,8 @@ opencode run --agent plan --model anthropic/claude-haiku-4-5 "audit src/ for mis | `--port` | Port for the local server backing this run | | `--variant ` | Model variant | | `--thinking` | Show thinking blocks | +| `--replay` | Interactively replay the run as it streams *(v1.16+)* | +| `--replay-limit ` | How much recent history to show when replaying | | `--command ` | Run a saved command | | `--dangerously-skip-permissions` | Auto-approve everything that isn't explicitly denied. **CI only.** | @@ -283,7 +285,7 @@ Update OpenCode to the latest or a specific version. ```bash opencode upgrade -opencode upgrade v1.15.0 +opencode upgrade v1.16.0 opencode upgrade --method brew # force the install method ``` diff --git a/docs/reference/faq.md b/docs/reference/faq.md index 19253f2..dffd8b8 100644 --- a/docs/reference/faq.md +++ b/docs/reference/faq.md @@ -249,4 +249,4 @@ export EDITOR='nvim' # Neovim --- -*Last reviewed: 2026-05-18 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* +*Last reviewed: 2026-06-08 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* diff --git a/docs/reference/further-reading.md b/docs/reference/further-reading.md index cdf816c..7541855 100644 --- a/docs/reference/further-reading.md +++ b/docs/reference/further-reading.md @@ -66,4 +66,4 @@ These aren't OpenCode-specific, but the patterns transfer. --- -*Last reviewed: 2026-05-18 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* +*Last reviewed: 2026-06-08 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* diff --git a/docs/reference/permissions.md b/docs/reference/permissions.md index 51824d5..12a796c 100644 --- a/docs/reference/permissions.md +++ b/docs/reference/permissions.md @@ -12,7 +12,7 @@ Every permission accepts one of: | `"ask"` | User is prompted to approve each use | | `"deny"` | Tool is blocked outright | -For `bash` (and any rule-style permission), you can also pass a **glob-pattern map** keyed by command pattern — most-specific wins, `*` is the catch-all. +For `bash` (and any rule-style permission), you can also pass a **glob-pattern map** keyed by command pattern. Rules are matched in order and the **last matching rule wins**, so list the catch-all `*` first and put more specific overrides after it. ## Permission keys → what they gate @@ -26,13 +26,13 @@ For `bash` (and any rule-style permission), you can also pass a **glob-pattern m | `todowrite` | in-session todo list | | `question` | the `question` tool | | `external_directory` | files outside the project root | -| `repo_clone` | cloning dependency repos into OpenCode's cache (used by `scout`) | -| `repo_overview` | repo-summary operations | | `webfetch` · `websearch` | network access | | `lsp` | language-server tools | | `skill` | loading agent skills | | `doom_loop` | runaway-loop safeguards | +That's the full set — **15 keys** (`read`, `edit`, `glob`, `grep`, `list`, `bash`, `task`, `external_directory`, `todowrite`, `question`, `webfetch`, `websearch`, `lsp`, `doom_loop`, `skill`), per the config schema. + > Note: `write` and `apply_patch` are both gated under the `edit` key, not separately. ## Built-in tool list @@ -116,12 +116,12 @@ The `bash` key accepts a glob-pattern map. Patterns are matched against the full { "permission": { "bash": { - "rm -rf*": "deny", - "git push --force*": "deny", + "*": "ask", "git status*": "allow", "git diff*": "allow", "pnpm test*": "allow", - "*": "ask" + "git push --force*": "deny", + "rm -rf*": "deny" } } } @@ -129,7 +129,7 @@ The `bash` key accepts a glob-pattern map. Patterns are matched against the full **Matching rules:** -- Patterns are evaluated by specificity — most specific match wins; `*` is the catch-all. +- Rules are matched in order and the **last matching rule wins**. Put the catch-all `*` **first**, then list more specific overrides after it — a trailing `*` would override everything above it. - `*` matches zero or more characters (including spaces). - `?` matches exactly one character. - Literal text matches exactly. diff --git a/docs/skills.md b/docs/skills.md index 3b80f76..030036e 100644 --- a/docs/skills.md +++ b/docs/skills.md @@ -58,11 +58,11 @@ version bump before doing anything destructive. | Key | Required | Constraints | |---|---|---| -| `name` | yes | `^[a-z0-9]+(-[a-z0-9]+)*$`, 1–64 chars — lowercase alphanumeric with single hyphens | +| `name` | yes | `^[a-z0-9]+(-[a-z0-9]+)*$`, 1–64 chars — lowercase alphanumeric with single hyphens. **Must match the folder name** that contains `SKILL.md`. | | `description` | yes | 1–1024 chars. **This is the discovery signal** — write it carefully. | | `license` | no | SPDX identifier ideal | | `compatibility` | no | `opencode`, `claude-code`, or both | -| `metadata` | no | Arbitrary structured metadata | +| `metadata` | no | String-to-string map (keys and values are both strings) | ### Why the `description` matters @@ -84,16 +84,18 @@ Anatomy of a good description: ## Where skills live -OpenCode searches multiple locations: +OpenCode searches six locations — three project-local, three global: | Location | Scope | |---|---| | `.opencode/skills//SKILL.md` | Project | +| `.claude/skills//SKILL.md` | Project — Claude Code compatibility | +| `.agents/skills//SKILL.md` | Project — Agent-format compatibility | | `~/.config/opencode/skills//SKILL.md` | Global | -| `.claude/skills//SKILL.md` | Claude Code compatibility | -| `.agents/skills//SKILL.md` | Agent-format compatibility | +| `~/.claude/skills//SKILL.md` | Global — Claude Code compatibility | +| `~/.agents/skills//SKILL.md` | Global — Agent-format compatibility | -Project skills take precedence over global. Same-named skills in different locations: project wins. +For the project paths, OpenCode traverses upward from the working directory to the git worktree root, so a skill in a parent folder is still found. Project skills take precedence over global; same-named skills resolve project-first. ## Permissions diff --git a/docs/tui.md b/docs/tui.md index e8be6da..71096a4 100644 --- a/docs/tui.md +++ b/docs/tui.md @@ -43,6 +43,7 @@ Use the **leader key** (default `ctrl+x`) for session-level actions, and readlin | Key | Action | |---|---| | `Tab` | Cycle primary agents (`build` ↔ `plan` ↔ custom primaries) | +| `shift+tab` | Cycle primary agents in reverse | | `Esc` | Cancel / dismiss | | `ctrl+c` / `ctrl+d` | Exit | @@ -113,6 +114,8 @@ Drop a `tui.json` next to your `opencode.json`: "theme": "tokyonight", "leader_timeout": 2000, "scroll_speed": 3, + "diff_style": "auto", + "mouse": true, "keybinds": { "command_list": "ctrl+p", "messages_copy": ["y", "ctrl+shift+c"], @@ -129,6 +132,8 @@ Drop a `tui.json` next to your `opencode.json`: Set a binding to `"none"` or `false` to disable. Arrays bind multiple shortcuts to the same action. +Other top-level keys worth knowing: `diff_style` (`"auto"` adapts to terminal width, `"stacked"` forces single-column diffs), `mouse` (capture toggle, default `true`), and `scroll_acceleration` (macOS-style smooth scroll that overrides `scroll_speed`). The `attention` block also takes `sound_pack` (default `"opencode.default"`) and a `sounds` map for per-event overrides (`default`, `question`, `permission`, `error`, `done`, `subagent_done`). + ## Themes Set the theme in `tui.json` or with `/themes` interactively. diff --git a/docs/workflows.md b/docs/workflows.md index 7164a53..3c211c3 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -159,6 +159,8 @@ Same idea on Buildkite, CircleCI, Jenkins — install the CLI, set the env var, `--dangerously-skip-permissions` is available for fully unattended runs — use it with care. +> 🔧 **Native GitHub path.** Beyond the raw `curl | bash` recipe, OpenCode ships first-class GitHub commands: `opencode github install` wires up the GitHub App and workflow so `/opencode` (or `/oc`) mentions trigger the agent on issues and PRs, and `opencode pr ` checks out a PR branch locally and opens a session. As of v1.16, the GitHub extension refuses to commit without an existing git author identity — in Actions the runner already configures `user.name`/`user.email`, so the comment-only recipes above are unaffected. + ## 7. Visual iteration Goal: implement UI to match a mock. @@ -184,4 +186,4 @@ Two-three iteration rounds usually produces a close visual match. Multimodal mod --- -*Last reviewed: 2026-05-18 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* +*Last reviewed: 2026-06-08 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* diff --git a/docs/zen.md b/docs/zen.md index 56304ed..0b91f69 100644 --- a/docs/zen.md +++ b/docs/zen.md @@ -2,7 +2,7 @@ > **Mental model:** Zen is OpenCode's curated, pay-as-you-go AI gateway. The OpenCode team tests and benchmarks models for coding-agent workloads and ships a focused lineup with consistent pricing. > -> *(Beta — verified against [opencode.ai/docs/zen](https://opencode.ai/docs/zen) on 2026-05-18. Pricing and model availability change frequently; check the docs before quoting numbers.)* +> *(Beta — verified against [opencode.ai/docs/zen](https://opencode.ai/docs/zen) on 2026-06-08. Pricing and model availability change frequently; check the docs before quoting numbers.)* ## When to reach for Zen vs. direct providers @@ -43,21 +43,21 @@ In `opencode.json`, reference a Zen model with the `opencode/` prefix: } ``` -> Slug format: keep the dots in the upstream model name where they exist (`gpt-5.5`, `gemini-3.1-pro`, `qwen3.6-plus`, `minimax-m2.5`); Anthropic IDs use hyphens (`claude-opus-4-7`, `claude-sonnet-4-6`). +> Slug format: keep the dots in the upstream model name where they exist (`gpt-5.5`, `gemini-3.1-pro`, `qwen3.7-plus`, `minimax-m2.7`); Anthropic IDs use hyphens (`claude-opus-4-8`, `claude-sonnet-4-6`). ## Available models -Selected lineup below. **For the full list (40+ entries, latest pricing, cached-read/write rates, and endpoint URLs), see [opencode.ai/docs/zen](https://opencode.ai/docs/zen).** +Selected lineup below. **For the full list (50+ entries, latest pricing, cached-read/write rates, and endpoint URLs), see [opencode.ai/docs/zen](https://opencode.ai/docs/zen).** ### Anthropic family | Model ID | Input / Output (per MTok) | Notes | |---|---|---| -| `opencode/claude-opus-4-7` | $5 / $25 | Flagship reasoning — complex refactors, multi-file work | +| `opencode/claude-opus-4-8` | $5 / $25 | Flagship reasoning — complex refactors, multi-file work | | `opencode/claude-sonnet-4-6` | $3 / $15 | Workhorse — most coding work lives here | | `opencode/claude-haiku-4-5` | $1 / $5 | Cheap, fast — title generation, simple Q&A | -Older versions (`claude-opus-4-6`, `claude-opus-4-5`, `claude-sonnet-4-5`, `claude-sonnet-4`, `claude-3-5-haiku`) are also available — see the full list. +Older versions (`claude-opus-4-7`, `claude-opus-4-6`, `claude-opus-4-5`, `claude-opus-4-1`, `claude-sonnet-4-5`, `claude-sonnet-4`, `claude-3-5-haiku`) are also available — see the full list. ### OpenAI family @@ -66,6 +66,7 @@ Older versions (`claude-opus-4-6`, `claude-opus-4-5`, `claude-sonnet-4-5`, `clau | `opencode/gpt-5.5` *(≤272K)* | $5 / $30 | Long-context flagship | | `opencode/gpt-5.5` *(>272K)* | $10 / $45 | Same model, beyond-window pricing | | `opencode/gpt-5.5-pro` | $30 / $180 | Pro variant | +| `opencode/gpt-5.4` *(≤272K)* | $2.50 / $15 | Mid-tier frontier | | `opencode/gpt-5.4-mini` | $0.75 / $4.50 | Cost-efficient frontier | | `opencode/gpt-5.4-nano` | $0.20 / $1.25 | Cheap, fast, narrow tasks | | `opencode/gpt-5.3-codex` · `opencode/gpt-5.2-codex` | $1.75 / $14 | Codex-tuned variants | @@ -76,22 +77,24 @@ GPT 5.1 / 5 / 5-codex / 5-nano are also available with their own pricing. | Model ID | Input / Output (per MTok) | Notes | |---|---|---| +| `opencode/gemini-3.5-flash` | $1.50 / $9 | Newest fast Gemini | | `opencode/gemini-3.1-pro` *(≤200K)* | $2 / $12 | Multimodal flagship | -| `opencode/gemini-3-flash` | $0.50 / $3 | Fast Gemini variant | -| `opencode/qwen3.6-plus` | $0.50 / $3 | Budget-friendly heavy lifting | -| `opencode/qwen3.5-plus` | $0.20 / $1.20 | Even cheaper | +| `opencode/gemini-3-flash` | $0.50 / $3 | Cheaper Gemini variant | +| `opencode/qwen3.7-max` | $2.50 / $7.50 | Qwen flagship | +| `opencode/qwen3.7-plus` | $0.40 / $1.60 | Budget-friendly heavy lifting | | `opencode/kimi-k2.6` | $0.95 / $4 | Moonshot lineup | | `opencode/glm-5.1` | $1.40 / $4.40 | Zhipu lineup | | `opencode/minimax-m2.7` | $0.30 / $1.20 | MiniMax current | +| `opencode/grok-build-0.1` | $1 / $2 | xAI coding model | ### Free tier (rotating, time-limited) For community feedback during model rollout: -- `opencode/deepseek-v4-flash-free` -- `opencode/minimax-m2.5-free` -- `opencode/nemotron-3-super-free` - `opencode/big-pickle` *(stealth model)* +- `opencode/deepseek-v4-flash-free` +- `opencode/mimo-v2.5-free` +- `opencode/nemotron-3-ultra-free` Great for learning OpenCode without burning a budget. @@ -128,7 +131,7 @@ For complex tasks, plan with the smartest model, then hand the atomic plan to a ```json { "agent": { - "plan": { "model": "opencode/claude-opus-4-7" }, + "plan": { "model": "opencode/claude-opus-4-8" }, "build": { "model": "opencode/claude-sonnet-4-6" } } } @@ -180,4 +183,4 @@ Both are gateways. Zen is **curated** — the OpenCode team picks and tunes mode --- -*Last reviewed: 2026-05-18 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* +*Last reviewed: 2026-06-08 · Canonical source: [opencode.ai/docs](https://opencode.ai/docs/).* diff --git a/mcp-servers/README.md b/mcp-servers/README.md index b03e48a..812f276 100644 --- a/mcp-servers/README.md +++ b/mcp-servers/README.md @@ -19,6 +19,8 @@ If everything you need is already in local files, you probably don't need MCP yet. +> 💡 Each walkthrough below shows the `opencode.json` entry to hand-edit. To register a server interactively instead, run `opencode mcp add` and answer the prompts. + ## Cost of adding a server MCP tools land in the model's tool surface every turn. A heavy server (say, a full GitHub integration with 40 tools) can eat 10K+ tokens of context **just to describe the available tools**. Don't add a server you won't use, and disable tools you don't need with the `tools` map: diff --git a/opencode.json b/opencode.json index 3575b89..45cd4f9 100644 --- a/opencode.json +++ b/opencode.json @@ -21,11 +21,11 @@ "wc *": "allow", "head *": "allow", "tail *": "allow", - "rm -rf*": "deny", + "curl *": "ask", "rm *": "ask", + "rm -rf*": "deny", "git push --force*": "deny", "git reset --hard*": "deny", - "curl *": "ask", "npm publish*": "deny" }, "webfetch": "ask", diff --git a/specialized-agents/system-prompts/tech-lead-prompt.md b/specialized-agents/system-prompts/tech-lead-prompt.md index cb69e60..e63082d 100644 --- a/specialized-agents/system-prompts/tech-lead-prompt.md +++ b/specialized-agents/system-prompts/tech-lead-prompt.md @@ -1,7 +1,7 @@ --- description: Tech lead — makes architectural decisions, sequences work, surfaces trade-offs across teams. Plans more than it implements. mode: all -model: anthropic/claude-opus-4-7 +model: anthropic/claude-opus-4-8 temperature: 0.3 permission: edit: ask