@khalilgharbaoui/opencode-claude-code-plugin 0.17.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +61 -26
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/skills/claude-code-plugin/SKILL.md +441 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khalilgharbaoui/opencode-claude-code-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Claude Code CLI provider plugin for opencode",
|
|
5
5
|
"author": "Khalil Gharbaoui",
|
|
6
6
|
"type": "module",
|
|
@@ -14,13 +14,14 @@
|
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
|
-
"dist"
|
|
17
|
+
"dist",
|
|
18
|
+
"skills"
|
|
18
19
|
],
|
|
19
20
|
"scripts": {
|
|
20
21
|
"build": "tsup",
|
|
21
22
|
"dev": "tsup --watch",
|
|
22
23
|
"typecheck": "tsc --noEmit",
|
|
23
|
-
"test": "tsx --test test-bridge.ts test-broker.ts test-proxy-mcp.ts test-proxy-task.ts test-auto-continue.ts test-has-new-user-content.ts test-get-claude-user-message.ts test-logger.ts test-cli-args.ts test-session-manager.ts test-compaction-model.ts test-tool-mapping.ts test-cwd-resolution.ts test-todo-ledger.ts test-session-affinity.ts test-config-models.ts test-ask-user-question.ts test-claude-session-wrapper.ts test-spawn-env.ts test-respawn.ts test-startup-diagnostics.ts test-subagent-hint.ts test-exit-plan-mode-question.ts test-compress-tool.ts test-agent-models.ts test-side-question.ts test-btw-command.ts test-effort-sessions.ts test-tool-block-index.ts test-skill-bridge.ts"
|
|
24
|
+
"test": "tsx --test test-bridge.ts test-broker.ts test-proxy-mcp.ts test-proxy-task.ts test-auto-continue.ts test-has-new-user-content.ts test-get-claude-user-message.ts test-logger.ts test-cli-args.ts test-session-manager.ts test-compaction-model.ts test-tool-mapping.ts test-cwd-resolution.ts test-todo-ledger.ts test-session-affinity.ts test-config-models.ts test-ask-user-question.ts test-claude-session-wrapper.ts test-spawn-env.ts test-respawn.ts test-startup-diagnostics.ts test-subagent-hint.ts test-exit-plan-mode-question.ts test-compress-tool.ts test-agent-models.ts test-side-question.ts test-btw-command.ts test-effort-sessions.ts test-tool-block-index.ts test-skill-bridge.ts test-configure-skill.ts"
|
|
24
25
|
},
|
|
25
26
|
"dependencies": {
|
|
26
27
|
"@ai-sdk/provider": "^3.0.8",
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claude-code-plugin
|
|
3
|
+
description: Configure and troubleshoot the opencode-claude-code-plugin, the opencode provider that runs Anthropic Claude models through the Claude Code CLI. Use when the user wants to install, set up, change or debug this plugin, meaning anything under provider.claude-code.options in opencode.json (accounts, proxyTools, cwd, permissions, MCP bridging, timeouts, logging), subagent model or effort, model ids and variants, /btw, the skill bridge, upgrades, or reading plugin.log. Not for opencode's own general configuration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configuring the Claude Code plugin
|
|
7
|
+
|
|
8
|
+
This plugin is `@khalilgharbaoui/opencode-claude-code-plugin`. It registers one or more
|
|
9
|
+
`claude-code*` providers and routes inference through the `claude` CLI, not opencode's
|
|
10
|
+
native Anthropic provider. Headless `--print` is the default. Subscription headless
|
|
11
|
+
usage draws on Agent SDK credit/extra usage under Anthropic's billing policy, not a
|
|
12
|
+
promise of free or normal interactive-plan usage. API-key/cloud billing depends on
|
|
13
|
+
the CLI's authentication. Confirm the user's intended account and billing method.
|
|
14
|
+
|
|
15
|
+
This file ships with the package, so upgrading that package updates the bundled
|
|
16
|
+
reference without a separate skill install. Do not copy it into a personal skill
|
|
17
|
+
directory: a user override can shadow the bundled version. Match guidance to the
|
|
18
|
+
version actually loaded, not a newer checkout. `test-configure-skill.ts` checks name
|
|
19
|
+
coverage against source declarations; it does not verify defaults or runtime
|
|
20
|
+
semantics or regenerate prose. For behavior, inspect the matching version's
|
|
21
|
+
`src/types.ts`, consumers in `src/index.ts` / `src/claude-code-language-model.ts`, and
|
|
22
|
+
the relevant module. Comments and README can lag the implementation.
|
|
23
|
+
|
|
24
|
+
## Ground rules
|
|
25
|
+
|
|
26
|
+
1. **Config lives in opencode's config, not in a plugin file.** Start at
|
|
27
|
+
`provider.claude-code.options`. Global defaults usually live in
|
|
28
|
+
`~/.config/opencode/opencode.json[c]`; project `opencode.json[c]` and `.opencode/`
|
|
29
|
+
files can override them. Check `OPENCODE_CONFIG`, `OPENCODE_CONFIG_DIR` and
|
|
30
|
+
`XDG_CONFIG_HOME` before selecting a file. With `accounts`, the seed options are
|
|
31
|
+
inherited; an existing `provider.claude-code-<account>.options` can override them.
|
|
32
|
+
2. **Provider options are read once, at opencode startup.** After any change the user must fully
|
|
33
|
+
quit and relaunch opencode. A plain `/new` session is not enough, and every other
|
|
34
|
+
opencode window still open keeps running the old configuration and the old plugin
|
|
35
|
+
code. Include serve/GUI processes. Say this every time you change something.
|
|
36
|
+
Bridged MCP config has a limited next-turn hot reload, not general config reload.
|
|
37
|
+
3. **Edit minimally.** Keep the user's comments in `.jsonc`, keep key order, change only
|
|
38
|
+
the keys asked for, and re-parse afterwards. Use surgical text edits or a
|
|
39
|
+
JSONC-aware edit API. This package already depends on `jsonc-parser`: its `modify`
|
|
40
|
+
and `applyEdits` preserve unrelated text; `parse` must be checked for errors
|
|
41
|
+
(`allowTrailingComma: true` for JSONC). Never strip comments with regex or round-trip
|
|
42
|
+
JSONC through `JSON.stringify`; that can corrupt URLs or erase comments.
|
|
43
|
+
4. **Never edit `dist/`, `node_modules/`, or `~/.cache/opencode/packages/`** to change
|
|
44
|
+
behavior. Build output and installer caches are not configuration.
|
|
45
|
+
5. **No credentials exposure.** Never read or print auth files, tokens, keys, a full
|
|
46
|
+
environment dump, or generated MCP configs. Check credential presence only, not
|
|
47
|
+
values. Config, diffs and logs can contain secrets or private prompts; inspect only
|
|
48
|
+
relevant fields and redact before displaying or sharing. Leave secret references
|
|
49
|
+
such as `{env:NAME}` intact. Do not initiate login/account switching without approval.
|
|
50
|
+
6. **No paid probes or risky changes without explicit approval.** Do not run inference
|
|
51
|
+
(`claude -p`, `opencode run`, `/btw`), enable extra usage, change billing, grant broad
|
|
52
|
+
tool permissions, or enable experimental flags as a routine verification step.
|
|
53
|
+
Explain consequences first, including `Question`, `planModeQuestion`, `Compress`,
|
|
54
|
+
`interactive`, skill/MCP bridging and fast models. Ask in ordinary text if a decision
|
|
55
|
+
is needed; do not use the known-broken question form to configure itself.
|
|
56
|
+
|
|
57
|
+
## Procedure
|
|
58
|
+
|
|
59
|
+
1. Identify install source/version, config scope, account/provider and requested change.
|
|
60
|
+
Inspect relevant config layers without exposing secrets. Preserve unrelated work.
|
|
61
|
+
2. If installation is requested, add the scoped package to the existing `plugin` array,
|
|
62
|
+
not a replacement array. Preserve pins and `file://` installs unless upgrading was
|
|
63
|
+
requested. A local checkout entry is `file:///abs/path/to/opencode-claude-code-plugin`.
|
|
64
|
+
3. Edit only the needed options/agent keys. Do not populate every default or invent
|
|
65
|
+
plugin-level options, `apiKey`, model metadata, or derived account fields.
|
|
66
|
+
4. Validate syntax and the opencode schema (`https://opencode.ai/config.json` when
|
|
67
|
+
needed). Schema validation alone does not validate this plugin's free-form options;
|
|
68
|
+
check this reference and source for names, types, units and enums.
|
|
69
|
+
5. Review the minimal, redacted diff. Report what changed and any unverified behavior.
|
|
70
|
+
6. Tell the user to fully restart opencode. Prefer offline checks below; get approval
|
|
71
|
+
before launching another opencode process, which may also start configured MCPs.
|
|
72
|
+
|
|
73
|
+
## Options reference
|
|
74
|
+
|
|
75
|
+
Use `provider.claude-code.options` unless intentionally overriding an expanded account.
|
|
76
|
+
Defaults below describe normal headless opencode use when the key is absent.
|
|
77
|
+
|
|
78
|
+
| Option | Type | Default | What it does |
|
|
79
|
+
|---|---|---|---|
|
|
80
|
+
| `cliPath` | string | `"claude"` | Executable, not a shell command with flags. Use an absolute path for a non-PATH install. The opencode config hook supplies this default; only direct `createClaudeCode()` use falls back to `CLAUDE_CLI_PATH`. Account providers wrap it; never select a generated wrapper yourself. |
|
|
81
|
+
| `accounts` | string[] | unset | Unset keeps provider `claude-code`. Any array, including `[]`, expands to `claude-code-default` plus normalized, deduplicated names. Non-default accounts use `~/.claude-<name>`; default uses the CLI's normal environment/auth. |
|
|
82
|
+
| `defaultSubagentModel` | string | unset | Seed-config default for discovered `mode: subagent` agents without a full `provider/model` pin; `forceModel` takes precedence. Keeps the caller's account. Unknown ids warn and keep the inherited model. Not independently read per expanded account. |
|
|
83
|
+
| `cwd` | string | automatic | Pin an absolute existing directory. Otherwise: session directory from SDK, usable `process.cwd()`, captured project directory, final `process.cwd()` fallback. Startup diagnostics cannot show the per-call session tier. |
|
|
84
|
+
| `skipPermissions` | boolean | `true` | Pass `--dangerously-skip-permissions` to headless Claude, even with proxies enabled. Proxied calls still use opencode permissions, but unproxied CLI tools do not. `false` removes the bypass flag; it does not by itself create human approval prompts. |
|
|
85
|
+
| `permissionMode` | `acceptEdits` / `auto` / `bypassPermissions` / `default` / `dontAsk` / `plan` | unset | Headless `--permission-mode`, not version-gated: verify the installed CLI supports the value. Does not negate `skipPermissions: true`; never assume `plan` makes that combination read-only. Not forwarded by the current interactive spawn path. |
|
|
86
|
+
| `controlRequestBehavior` | `allow` / `deny` | `allow` | Automatically answer CLI `can_use_tool` requests if emitted. Not an opencode permission prompt or a sandbox; bypass/pre-allowed tools may never ask. `AskUserQuestion` defaults to deny. |
|
|
87
|
+
| `controlRequestToolBehaviors` | object of tool name to `allow`/`deny` | unset | Case-insensitive per-tool override of the above (`Bash`, `Read`, `mcp__github__list_prs`). Do not allow `AskUserQuestion`: that can let headless Claude self-answer. |
|
|
88
|
+
| `controlRequestDenyMessage` | string | built-in text | Override ordinary deny text. `AskUserQuestion` always uses its own stop-and-wait message. |
|
|
89
|
+
| `proxyTools` | string[] | `["Bash", "Edit", "Write", "WebFetch", "Task"]` | Case-insensitive replacement list, not additive and not a capability allowlist. Known entries expose `mcp__opencode_proxy__<name>`; omitted/unknown tools are not disabled. `Task` also brings `task_batch`; `[]` disables this list, not MCP proxying. See the proxy table for exceptions. |
|
|
90
|
+
| `extraDisallowedTools` | string[] | unset | Claude built-ins to switch off outright with `--disallowedTools`, for tools that have no proxy (`["NotebookEdit"]`). Removes the capability rather than routing it. |
|
|
91
|
+
| `proxyToolTimeoutMs` | object of proxy tool name to ms | unset | Positive deadlines, case-insensitive keys. Fallback 10 min (including dynamic MCP tools); `task` and `task_batch` 60 min each; `question` 30 min. Set both task keys to override both. Zero/negative values do not disable deadlines; values above 2147483647 are clamped. Bash `input.timeout` raises the resolved deadline, but executor/client ceilings still apply. `compress` is intercepted without a deadline. |
|
|
92
|
+
| `planModeQuestion` | boolean | `false` | Bridge `ExitPlanMode` approval to opencode's `question` and return a real CLI tool result. Requires a live question registry entry; otherwise keeps text fallback. Keep off on affected opencode builds: the form has failed to render (anomalyco/opencode#36604). Prose yes/no is not a verified CLI plan-mode unlock. |
|
|
93
|
+
| `webSearch` | `"claude"` / `"disabled"` / `"<opencode tool name>"` | `"claude"` | Default: CLI search with the query rendered as text. Custom target forwards a tool call to an existing opencode tool accepting `query`; this is mapping, not the authenticated proxy replacement, so do not assume CLI search is suppressed. `"disabled"` disallows headless `WebSearch`. |
|
|
94
|
+
| `bridgeOpencodeMcp` | boolean | `true` | Discover/translate disk MCP config plus runtime enabled status. False stops this bridge, not explicit `mcpConfig`, the built-in-tool proxy, or Claude's own MCP settings. Only bridge trusted servers. |
|
|
95
|
+
| `mcpConfig` | string or string[] | unset | Extra `--mcp-config` paths or inline JSON passed alongside the bridged config. |
|
|
96
|
+
| `strictMcpConfig` | boolean | `false` | Headless `--strict-mcp-config`: use only explicitly supplied MCP configs, ignoring other MCP sources, not all settings/credentials/hooks. The interactive wrapper adds it whenever it passes MCP paths, independently of this option. |
|
|
97
|
+
| `hotReloadMcp` | boolean | `true` | With bridging on, compare merged MCP config/status at turn start and respawn on drift after pending proxy calls resolve. Keeps the session via headless `--resume`. Does not reload arbitrary provider options or watch explicit `mcpConfig` contents. |
|
|
98
|
+
| `proxyOpencodeMcpTools` | boolean | `true` | When bridge and live tool discovery succeed, route discovered MCP tools through opencode's executor. Disabled/unavailable discovery falls back to direct CLI bridging. Do not promise exactly-once side effects across failures/retries or opencode versions; verify routing before using write-capable tools. |
|
|
99
|
+
| `multiStepContinuation` | boolean | `true` | Append a system-prompt hint to chain tool calls in one turn instead of stopping between subtasks. |
|
|
100
|
+
| `autoContinueIncompleteTurns` | boolean or `"smart"` | `"smart"` | `true`/`"smart"` enable the same bounded heuristic only when stop reason is missing. Any stop reason (even `max_tokens`), error, abort or latched question stops it. Current measured CLIs always report a reason; not a guaranteed auto-resume. |
|
|
101
|
+
| `compactionModel` | string | `"claude-haiku-4-5"` | `/compact` uses a fresh short-lived headless process without the usual bridge/proxy/skill wiring. Nonblank `CLAUDE_CODE_COMPACTION_MODEL` wins. This is inference and can be billed. |
|
|
102
|
+
| `ignoreAnthropicApiKey` | boolean | `false` | Strip `ANTHROPIC_API_KEY` and `ANTHROPIC_AUTH_TOKEN` from headless/interactive spawn env, allowing stored auth to be used. Does not log in, change the parent env, or guarantee subscription billing if other CLI/cloud auth is configured. Warns at startup when either nonempty variable is present, regardless of the flag. |
|
|
103
|
+
| `idleProcessTimeoutMs` | number | unset | Kill a conversation's idle `claude` worker this many ms after a finished turn. The session id is kept, so the next message resumes transparently. `0` or unset keeps workers until LRU eviction (16 processes). Values above `2147483647` are ignored. Not applied to the interactive transport. |
|
|
104
|
+
| `bridgeOpencodeSkills` | boolean | `false` | Opt-in user skill staging for ordinary headless streams, as `opencode-skills:<name>`. Requires the CLI's `--help` to advertise `--plugin-dir`; otherwise no-op. Adds prompt overhead and exposes skill instructions to Claude. Bundled skill staging does not require this opt-in, but still requires flag support and successful discovery/staging. |
|
|
105
|
+
| `interactive` | boolean | unset (headless) | Experimental PTY transport; explicit boolean wins over `CLAUDE_CODE_INTERACTIVE_TRANSPORT`. Needs `Bun.Terminal`; otherwise headless fallback. Compaction stays headless. Does not wire the headless proxy server/skill bridge/disallowed-tools controls; no equivalent opencode permission guarantee or `/btw`. Never enable to bypass a billing/access restriction. |
|
|
106
|
+
| `interactiveBypass` | boolean | `false` | Deprecated no-op. The TUI asks for a manual safety confirmation on `bypassPermissions`, so the plugin never passes it. |
|
|
107
|
+
| `interactiveAllowTools` | string[] | `["Bash", "Edit", "Write", "Read", "WebFetch"]` | With `interactive`: replaces the built-in pre-allow list. MCP wildcards from discovered bridge names plus `mcp__opencode_proxy__*` are added even with `[]`. Not a capability denylist; review permissions before enabling. |
|
|
108
|
+
| `interactiveSystemPrompt` | boolean | `true` | With `interactive`: append the plugin's own prompt. opencode's forwarded system prompt is deliberately not sent on this transport (it can trip Claude's third-party usage gate). `false` is for diagnostics only. |
|
|
109
|
+
| `logging` | object | see below | File and TUI logging policy. |
|
|
110
|
+
| `name` | string | unset | Low-level `createClaudeCode()` provider identity fallback after `providerID`, not the opencode display-name setting. Display name lives at `provider.<id>.name`; account expansion supplies its own label. Leave this option unset. |
|
|
111
|
+
| `providerID` | string | derived | Config hook writes the actual provider id (`claude-code` or `claude-code-work`). Do not override manually. |
|
|
112
|
+
| `account` | string | unset/derived | Account expansion supplies this to generate its runtime wrapper. Prefer `accounts` over hand-wiring it. |
|
|
113
|
+
| `configDir` | string | unset/derived | Generated account directory, also used for interactive env/transcript lookup. Not a standalone headless auth switch: headless account selection comes from the wrapper's env. Do not hand-wire it. |
|
|
114
|
+
|
|
115
|
+
### `logging` object
|
|
116
|
+
|
|
117
|
+
| Key | Values | Default | Effect |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| `file` | boolean | `false` | Persist entries that pass `level`. Logs can contain prompts/tool data/CLI arguments; enable temporarily with consent, not as a credential dump. |
|
|
120
|
+
| `dir` | path | `~/.local/share/opencode-claude-code/` | Where `plugin.log` goes. |
|
|
121
|
+
| `mode` | `"silent"` / `"debug"` | `"silent"` | After level filtering: silent routes lower levels only to the file if enabled; WARN/ERROR go to stderr/TUI too. Debug echoes all emitted levels to stderr, but does not lower the threshold. |
|
|
122
|
+
| `level` | `debug` / `info` / `notice` / `warn` / `error` | `"info"` | Minimum level emitted anywhere. |
|
|
123
|
+
|
|
124
|
+
## Environment variables
|
|
125
|
+
|
|
126
|
+
Set variables in the environment that launches opencode, then fully restart it.
|
|
127
|
+
Precedence is per variable, not a blanket env-over-config rule. CLI-owned variables
|
|
128
|
+
are passed through; their final effect depends on the installed CLI. Never print
|
|
129
|
+
their secret values. Arbitrary MCP `{env:NAME}` placeholders are outside this list.
|
|
130
|
+
|
|
131
|
+
| Variable | Effect |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `CLAUDE_CLI_PATH` | Direct factory fallback for absent `cliPath`. Normal opencode registration supplies `"claude"`; set the option explicitly there. |
|
|
134
|
+
| `CLAUDE_CONFIG_DIR` | CLI auth/settings/session directory. Non-default account wrappers override it; default headless account inherits it if set. Login is a user-approved interactive action, never a diagnostic probe. |
|
|
135
|
+
| `CLAUDE_CODE_EFFORT_LEVEL` | Shell-level CLI effort. Request variant/agent effort wins on a normal spawn. Compaction omits request/agent effort, but still inherits the shell env. |
|
|
136
|
+
| `CLAUDE_CODE_DISABLE_THINKING` | CLI-owned, conventionally `1` to disable thinking. Plugin leaves it intact and suppresses its own thinking flags/summary defaults if enabled. |
|
|
137
|
+
| `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING` | CLI-owned adaptive-thinking control. Either disable variable suppresses the plugin's own thinking flags/summary defaults, not just adaptive flags. Empty/`0`/`false`/`no`/`off` are false, case-insensitive. |
|
|
138
|
+
| `CLAUDE_CODE_SHOW_THINKING_SUMMARIES` | Headless spawn fills in `1` only if unset and neither disable flag is enabled. Any explicit value is preserved and suppresses the plugin's `--thinking-display` override; `0` requests suppression from the CLI. |
|
|
139
|
+
| `CLAUDE_CODE_COMPACTION_MODEL` | Nonblank, trimmed value wins over `compactionModel`. |
|
|
140
|
+
| `CLAUDE_CODE_DISABLE_FAST_MODE` | CLI-owned kill switch, conventionally `1`; plugin does not interpret it or change picker prices. Use the non-fast id if fast mode is disabled. |
|
|
141
|
+
| `CLAUDE_CODE_INTERACTIVE_TRANSPORT` | Fallback when `interactive` is absent: `1` enables; empty/`0`/`false`/`no`/`off` disable (case-insensitive). Explicit `interactive: false` wins. |
|
|
142
|
+
| `CLAUDE_CODE_INTERACTIVE_BYPASS` | Deprecated no-op, like `interactiveBypass`. |
|
|
143
|
+
| `CLAUDE_CODE_START_WATCHDOG_MS` | Positive integer ms before a headless start or proxy-result continuation is considered silent; default 90000 for missing/invalid/nonpositive values. First expiry respawns, second errors. Bookkeeping-only output is not progress. Keep within timer range; do not lower for routine config checks. |
|
|
144
|
+
| `OPENCODE_CLAUDE_CODE_LOG_FILE` | Overrides `logging.file`: trimmed `0/false/no/off` are false; any other nonempty value is true; empty falls back to config. Prefer `1` or `0`. |
|
|
145
|
+
| `OPENCODE_CLAUDE_CODE_LOG_DIR` | Overrides `logging.dir`. |
|
|
146
|
+
| `OPENCODE_CLAUDE_CODE_LOG_LEVEL` | Overrides `logging.level`. Invalid values fall through to config. |
|
|
147
|
+
| `DEBUG` | A value containing `opencode-claude-code` promotes `logging.mode` to debug, not `logging.level`. Preserve other debug namespaces. |
|
|
148
|
+
| `OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP=1` | Skip the one-time removal of a stale unscoped `opencode-claude-code-plugin` install from opencode's package cache. |
|
|
149
|
+
| `ANTHROPIC_API_KEY` | CLI API authentication input, stripped when `ignoreAnthropicApiKey` is true; otherwise may change billing away from stored subscription auth. Never display it. |
|
|
150
|
+
| `ANTHROPIC_AUTH_TOKEN` | CLI auth-token input; same strip/warning rule. Never display it. |
|
|
151
|
+
| `OPENCODE_CONFIG` | Explicit config file, also read by the disk MCP bridge before project layers. |
|
|
152
|
+
| `OPENCODE_CONFIG_DIR` | Additional `.opencode`-style config/skill root. The plugin's direct agent-file fallback does not use it; agents must reach the config hook or a supported agent directory. |
|
|
153
|
+
| `OPENCODE_WORKTREE` | Overrides the disk MCP bridge's project walk-up boundary. |
|
|
154
|
+
| `XDG_CONFIG_HOME` | Global MCP/skill/AGENTS discovery root (`<value>/opencode`); defaults to the home `.config`. Direct agent-file fallback still uses `~/.config/opencode/agent(s)`. |
|
|
155
|
+
| `XDG_CACHE_HOME` | Account wrapper/cache-cleanup root override; do not assume the default cache path when upgrading. |
|
|
156
|
+
| `HOME` | Home expansion and direct agent-file discovery (other paths also use OS homedir). Do not change it to switch accounts. |
|
|
157
|
+
| `USERPROFILE` | Home fallback where `HOME` is absent. |
|
|
158
|
+
| `OPENCODE_VERSION` | Startup diagnostics version fallback, not a capability override. |
|
|
159
|
+
|
|
160
|
+
## Recipes
|
|
161
|
+
|
|
162
|
+
### Minimum install
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{ "plugin": ["@khalilgharbaoui/opencode-claude-code-plugin"] }
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Everything else is optional. Models appear in the picker without extra config.
|
|
169
|
+
|
|
170
|
+
### Two accounts
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"provider": { "claude-code": { "options": { "accounts": ["personal", "work"] } } }
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Creates `claude-code-default`, `claude-code-personal`, `claude-code-work`; default
|
|
179
|
+
models have no suffix, other accounts have `@<account>` (`claude-opus-5@work`). Names
|
|
180
|
+
normalize to lowercase hyphen-separated ids, so choose distinct simple names.
|
|
181
|
+
After the user approves login, they authenticate each non-default account interactively,
|
|
182
|
+
for example `CLAUDE_CONFIG_DIR="$HOME/.claude-work" claude auth login`, using the chosen
|
|
183
|
+
binary. Never copy credentials between accounts. The generated wrapper strips the model
|
|
184
|
+
suffix and sets the config dir. Existing `CLAUDE.md`, `settings.json`, `skills/`,
|
|
185
|
+
`agents/`, `commands/`, `plugins/` in `~/.claude` are symlinked only when targets are
|
|
186
|
+
missing; existing targets stay untouched. This shares capabilities/settings, not an
|
|
187
|
+
isolation boundary. Auth/session files are not part of the shared list.
|
|
188
|
+
|
|
189
|
+
### Subagents on one model, on the caller's account
|
|
190
|
+
|
|
191
|
+
opencode's agent config cannot say "inherit the account, change the model", because the
|
|
192
|
+
account is the provider and the model is only a `--model` flag. The plugin closes that gap.
|
|
193
|
+
|
|
194
|
+
Per agent, in `~/.config/opencode/agents/<name>.md` or `.opencode/agents/<name>.md`
|
|
195
|
+
(`agent/` singular also works), no `model:` key:
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
---
|
|
199
|
+
description: Designs and builds UI work
|
|
200
|
+
mode: subagent
|
|
201
|
+
forceModel: claude-haiku-4-5
|
|
202
|
+
reasoningEffort: high
|
|
203
|
+
---
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Or once for every discovered subagent without a full provider/model pin:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{ "provider": { "claude-code": { "options": { "defaultSubagentModel": "claude-opus-5" } } } }
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Rules, in order: `forceModel` wins; else `mode: subagent` with `defaultSubagentModel`
|
|
213
|
+
set; else untouched. An agent with `model: <provider>/<id>` is left exactly as written,
|
|
214
|
+
account and all (`model: claude-code-work/claude-opus-5@work` pins the account too).
|
|
215
|
+
Undeclared built-ins are not discovered; a user definition with a built-in name can
|
|
216
|
+
enter the registry and is subject to these rules. This is not a built-in-name denylist.
|
|
217
|
+
`reasoningEffort` in the agent file beats the effort the call arrived with; compaction is
|
|
218
|
+
exempt. Effort and model are part of the CLI session key, so a changed agent respawns
|
|
219
|
+
rather than sharing a process.
|
|
220
|
+
|
|
221
|
+
Only grant `permission.task` for approved target agents if delegation is wanted.
|
|
222
|
+
`permission.todowrite: "allow"` is needed for subagent todos; opencode otherwise denies
|
|
223
|
+
them by default. Ask before broadening permissions. Use the singular `agent` config
|
|
224
|
+
object for inline definitions, with `forceModel`/`reasoningEffort` under `options` if
|
|
225
|
+
the opencode schema requires it. Markdown fallback reads top-level scalar fields only.
|
|
226
|
+
|
|
227
|
+
### Agent keys
|
|
228
|
+
|
|
229
|
+
| Key | Behavior |
|
|
230
|
+
|---|---|
|
|
231
|
+
| `mode` | Only exactly `subagent` qualifies for `defaultSubagentModel`; `primary`/`all` do not. |
|
|
232
|
+
| `model` | Full `provider/model` pins bypass plugin model overrides, not the separate effort override. |
|
|
233
|
+
| `forceModel` | Registered bare model id, preserving the caller's account even if an account suffix is supplied. Works for any discovered agent mode. |
|
|
234
|
+
| `reasoningEffort` | `minimal`, `low`, `medium`, `high`, `xhigh`, `max`; invalid declarations warn and keep inherited effort. `minimal` maps to CLI `low`. Compaction skips this override. |
|
|
235
|
+
|
|
236
|
+
### Route a tool through opencode, or switch one off
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{ "proxyTools": ["Bash", "Edit", "Write", "WebFetch", "Task"], "extraDisallowedTools": ["NotebookEdit"] }
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Options fragments in recipes belong inside `provider.claude-code.options`, not at
|
|
243
|
+
the config root. Preserve other wanted proxies when changing this replacement list.
|
|
244
|
+
`Read`, `Glob` and `Grep` have tool mappings/disallowed-name entries but no selectable
|
|
245
|
+
proxy definitions in this version, just like `NotebookEdit` has no proxy. Adding them
|
|
246
|
+
to `proxyTools` warns and leaves the built-ins unproxied. Use `extraDisallowedTools`
|
|
247
|
+
only to deliberately remove a capability; omission from `proxyTools` is not denial.
|
|
248
|
+
|
|
249
|
+
The proxy's loopback endpoint has bearer, Host, Origin and Content-Type guards.
|
|
250
|
+
Never weaken them, publish its token or relax the generated MCP file's `0600` mode.
|
|
251
|
+
Restart all old processes after a security upgrade; changing files cannot patch them.
|
|
252
|
+
|
|
253
|
+
### Proxy tool names
|
|
254
|
+
|
|
255
|
+
Names below become `mcp__opencode_proxy__<name>`; input config is case-insensitive.
|
|
256
|
+
|
|
257
|
+
| Tool | Selection and behavior |
|
|
258
|
+
|---|---|
|
|
259
|
+
| `bash` | `"Bash"`, default; replaces CLI Bash with opencode execution. |
|
|
260
|
+
| `edit` | `"Edit"`, default; replaces CLI Edit. |
|
|
261
|
+
| `write` | `"Write"`, default; replaces CLI Write. |
|
|
262
|
+
| `webfetch` | `"WebFetch"`, default; replaces CLI WebFetch. |
|
|
263
|
+
| `task` | `"Task"`, default; disables CLI Agent and dispatches opencode subagents under its permissions. |
|
|
264
|
+
| `task_batch` | Included with Task; one MCP call fans out two or more independent task inputs concurrently. Separate task calls were measured serial on CLI 2.1.258. |
|
|
265
|
+
| `question` | `"Question"`, opt-in; replaces AskUserQuestion only if the live opencode registry has question. Requires `permission.question`; form rendering is broken on affected versions, so keep off. |
|
|
266
|
+
| `compress` | `"Compress"`, opt-in; in-process summary/reset interceptor, no opencode permission prompt and no built-in replacement. Discards prior CLI detail on a later eligible turn, retaining the summary, not the full transcript. Keep off unless explicitly requested; end-to-end reset remains unverified live. |
|
|
267
|
+
|
|
268
|
+
### Let Claude load the user's opencode skills
|
|
269
|
+
|
|
270
|
+
```json
|
|
271
|
+
{ "bridgeOpencodeSkills": true }
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Use only after approval when `Skill("<name>")` fails for a trusted opencode skill.
|
|
275
|
+
Headless bridged names are `opencode-skills:<name>`, including this bundled skill as
|
|
276
|
+
`opencode-skills:claude-code-plugin`. The package also registers its skill directory
|
|
277
|
+
with opencode's `skills.paths`; older opencode versions may not support that surface.
|
|
278
|
+
The native Claude bridge needs `--plugin-dir` support and is wired into ordinary
|
|
279
|
+
headless streaming calls, not interactive, compaction or direct `doGenerate` calls.
|
|
280
|
+
The bundled skill does not require `bridgeOpencodeSkills: true`; that option adds
|
|
281
|
+
the user's skills. Reusing a process does not load a new skill catalog.
|
|
282
|
+
|
|
283
|
+
User roots: `.opencode/skills` walking from cwd to filesystem root, home `.opencode/skills`,
|
|
284
|
+
`OPENCODE_CONFIG_DIR/skills`, then `XDG_CONFIG_HOME/opencode/skills` (home `.config`
|
|
285
|
+
fallback). First name wins; enabled user bridging can shadow bundled names. Only immediate
|
|
286
|
+
`<name>/SKILL.md` directories are collected. Arbitrary `skills.paths`, `skills.urls`,
|
|
287
|
+
singular `skill/`, `~/.agents/skills` and `~/.claude/skills` are not scanned by this
|
|
288
|
+
bridge; Claude can already discover its own skills independently. Broad bridging can
|
|
289
|
+
duplicate advertised skill context and exposes every discovered skill, not just one.
|
|
290
|
+
|
|
291
|
+
### Free idle workers
|
|
292
|
+
|
|
293
|
+
```json
|
|
294
|
+
{ "idleProcessTimeoutMs": 900000 }
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Fifteen minutes after a turn ends with no new message, that conversation's `claude`
|
|
298
|
+
process exits; the next message resumes the same conversation.
|
|
299
|
+
|
|
300
|
+
### Different `/compact` model
|
|
301
|
+
|
|
302
|
+
```json
|
|
303
|
+
{ "compactionModel": "claude-sonnet-5" }
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
This is more expensive per token than the Haiku default, not a cost-saving recipe.
|
|
307
|
+
|
|
308
|
+
### Debug logging
|
|
309
|
+
|
|
310
|
+
```json
|
|
311
|
+
{ "logging": { "file": true } }
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Default destination: `~/.local/share/opencode-claude-code/plugin.log` (respect the
|
|
315
|
+
configured/env directory). INFO is enough for startup diagnostics. Add
|
|
316
|
+
`"level": "debug"` only if needed for lower-level events; `mode: "debug"` alone does
|
|
317
|
+
not do that. Capture a bounded, redacted excerpt, then disable temporary logging and
|
|
318
|
+
restart. Logs rotate above 5 MB to `plugin.log.1`, which can also contain private data.
|
|
319
|
+
|
|
320
|
+
### Upgrade the plugin
|
|
321
|
+
|
|
322
|
+
A published version does not reach a running opencode. First distinguish an npm pin,
|
|
323
|
+
npm latest resolution, and a local `file://` install. Preserve a pin unless the user
|
|
324
|
+
requested changing it. Some opencode versions freeze latest in
|
|
325
|
+
`~/.cache/opencode/packages/@khalilgharbaoui/opencode-claude-code-plugin@latest/`.
|
|
326
|
+
Inspect the actual cache location/package identity and get approval before removing
|
|
327
|
+
only that stale package directory, never the whole cache or auth/session directories.
|
|
328
|
+
Respect platform/XDG paths. Then fully relaunch. A `file://` install uses the checkout's
|
|
329
|
+
`dist/`: rebuild with `npm run build` and restart after approval, not cache deletion.
|
|
330
|
+
No manual skill copy/update is needed. Do not publish or release as part of configuring.
|
|
331
|
+
|
|
332
|
+
## Models and variants
|
|
333
|
+
|
|
334
|
+
### Registered model ids
|
|
335
|
+
|
|
336
|
+
Registered ids: `claude-haiku-4-5`, `claude-sonnet-4-5`, `claude-sonnet-4-6`,
|
|
337
|
+
`claude-sonnet-5`, `claude-opus-4-5`, `claude-opus-4-6`, `claude-opus-4-7`,
|
|
338
|
+
`claude-opus-4-8`, `claude-opus-4-8-fast`, `claude-opus-5`, `claude-opus-5-fast`,
|
|
339
|
+
`claude-fable-5`, `claude-fable-5-1`, `claude-mythos-5`, `claude-mythos-5-1`.
|
|
340
|
+
|
|
341
|
+
### Variants and costs
|
|
342
|
+
|
|
343
|
+
- Display names end in a `(N×)` list-price multiplier relative to Haiku: 1× haiku,
|
|
344
|
+
3× sonnet, 5× opus, 10× fable, mythos and fast-mode opus. It is display only.
|
|
345
|
+
- Every model except Haiku has reasoning variants `low`, `medium`, `high`, `xhigh`,
|
|
346
|
+
`max`, picked in opencode's model selector. A variant becomes
|
|
347
|
+
`CLAUDE_CODE_EFFORT_LEVEL` on the spawned CLI unless an agent effort wins. For direct
|
|
348
|
+
AI-SDK calls, `ClaudeCodeCallOptions.reasoningEffort` supports the same levels plus
|
|
349
|
+
`minimal` (mapped to `low`); it is not a provider startup option.
|
|
350
|
+
- The `-fast` ids are this plugin's own markers. They spawn the base model with
|
|
351
|
+
`--settings '{"fastMode":true}'` (Claude Code 2.1.220+). Fast mode fails soft: an
|
|
352
|
+
ineligible account runs at standard speed and the plugin logs a warning naming the
|
|
353
|
+
reason. Switch to a non-fast id rather than silently enabling paid usage credits.
|
|
354
|
+
Review eligibility/billing with the user; the enabled state needs live verification
|
|
355
|
+
on their account. CLI floors are gates, not proof of model access.
|
|
356
|
+
- `claude-mythos-5` and `claude-mythos-5-1` are limited availability (Project Glasswing).
|
|
357
|
+
Without access `claude --model` errors; use the corresponding `claude-fable-*`.
|
|
358
|
+
- Ordinary calls can pass through unregistered ids; availability and opencode model
|
|
359
|
+
registration still need checking. `forceModel`/`defaultSubagentModel` reject those ids.
|
|
360
|
+
- Registry costs are USD per million tokens, not subscription quota or a billing
|
|
361
|
+
guarantee. Fast entries have fast pricing; other entries use standard rates. There
|
|
362
|
+
is no above-200K tier in this registry; do not invent `cost.tiers` or
|
|
363
|
+
`cost.experimentalOver200K`. 4.5 models have 200K context/64K output, later registered
|
|
364
|
+
models have 1M/128K. Recheck vendor pricing/access separately when changing models.
|
|
365
|
+
|
|
366
|
+
## Verify and diagnose
|
|
367
|
+
|
|
368
|
+
Offline first: validate edited JSON/JSONC without starting opencode; inspect installed
|
|
369
|
+
package metadata. `claude --version` / `claude --help` on the trusted configured binary
|
|
370
|
+
and `opencode --version` do not request model inference. Do not invoke a model merely
|
|
371
|
+
to test configuration. A paid smoke test requires explicit approval and a bounded task.
|
|
372
|
+
|
|
373
|
+
If diagnostic logging was approved, find the newest matching
|
|
374
|
+
`NOTICE: claude-code plugin ready` entry for the restarted process (INFO threshold
|
|
375
|
+
includes NOTICE). Do not paste the entire log or raw spawn arguments.
|
|
376
|
+
|
|
377
|
+
Fields: `plugin` (version actually loaded), `opencode`, `cwd.resolved` and `cwd.source`
|
|
378
|
+
(`configured`, `process`, `captured`, `unresolved`), `providers`, `accounts`,
|
|
379
|
+
`proxyTools`, `mcpServers`, `interactiveTransport`, `planModeQuestion`,
|
|
380
|
+
`anthropicApiKeyInEnv`, `claudeCli.path` and `.version`
|
|
381
|
+
(`not detected` means the binary did not answer `--version`, which also disables
|
|
382
|
+
version-gated flags). Cwd is a startup fallback snapshot, not the per-session spawn
|
|
383
|
+
directory. MCP names are disk discovery, not proof of live connectivity. Interactive
|
|
384
|
+
status is a preference report, not proof that Bun PTY transport was used. Check a
|
|
385
|
+
relevant, redacted spawn/bridge entry for actual routing after an approved normal turn.
|
|
386
|
+
|
|
387
|
+
Useful log lines to search for (redact payloads): `spawning new claude process`,
|
|
388
|
+
`bridged opencode skills into claude`, `interrupt sent for aborted turn`, `btw:`,
|
|
389
|
+
`rendering opencode-side tool result as text`, `proxy-mcp tool call received`,
|
|
390
|
+
`evicting idle claude process`, `fast mode` warnings.
|
|
391
|
+
|
|
392
|
+
Version requirements: Claude Code CLI 2.1.142+ recommended (thinking summaries),
|
|
393
|
+
2.1.220+ for fast mode, 2.1.258+ for `/btw`. Check with `claude --version`.
|
|
394
|
+
|
|
395
|
+
Only if a proxy security check is specifically requested: identify the exact local
|
|
396
|
+
proxy port first, not every opencode listener. An unauthenticated `initialize` with
|
|
397
|
+
the correct `127.0.0.1:<port>` Host, no Origin and JSON Content-Type should get `401`.
|
|
398
|
+
`200` on a confirmed proxy endpoint is unsafe; restart/upgrade. Other status codes
|
|
399
|
+
alone do not prove it patched. Never call `tools/call` or obtain the bearer to probe.
|
|
400
|
+
|
|
401
|
+
`/btw <question>` needs an existing headless Claude conversation and CLI 2.1.258+.
|
|
402
|
+
It asks through the side channel and keeps the answer in the conversation (inline
|
|
403
|
+
when possible); it is excluded from Claude's normal turn history. It is still
|
|
404
|
+
inference: zero reported usage for the aside does not mean free. User-defined `btw`
|
|
405
|
+
commands are preserved. Do not use it as an automatic diagnostic probe.
|
|
406
|
+
|
|
407
|
+
## Troubleshooting
|
|
408
|
+
|
|
409
|
+
| Symptom | Cause | Fix |
|
|
410
|
+
|---|---|---|
|
|
411
|
+
| A config change did nothing | Options are read at startup; another opencode window is still running the old process | Fully quit every opencode window and relaunch |
|
|
412
|
+
| New plugin version or model not in the picker after upgrading | Frozen `@latest` in opencode's package cache | Remove the cache dir (recipe "Upgrade the plugin") and relaunch |
|
|
413
|
+
| `/btw` shows "Queued" or "requires an idle Claude Code session" | Plugin older than 0.15.2, or a window started before the current build | Upgrade and restart. `/btw` also needs Claude Code 2.1.258+ |
|
|
414
|
+
| Model calls `Skill("x")` and gets `Unknown skill` | Wrong namespace, unsupported flag/transport, unscanned root, or user bridging off | Check catalog/`--help`/transport; enable `bridgeOpencodeSkills` only with approval |
|
|
415
|
+
| `Subagent failed (task_id …): Tool execution aborted` while the child finished fine | Bug fixed in 0.15.1 | Upgrade |
|
|
416
|
+
| A `subtask: true` command's subagent output is "lost" | Bug fixed in 0.15.4 | Upgrade |
|
|
417
|
+
| Two subagents run one after another | The CLI serialises MCP calls | Plugin 0.17.0+; the model must use `mcp__opencode_proxy__task_batch` |
|
|
418
|
+
| Esc does not stop Claude; aborted turns keep running | Plugin older than 0.16.0 | Upgrade |
|
|
419
|
+
| Under `opencode serve` or the web UI every project spawns Claude in the server's launch dir | Plugin older than 0.16.0 | Upgrade, or pin `cwd` |
|
|
420
|
+
| 400 `Third-party apps now draw from your extra usage…` | Subscription/account usage gate, including disabled extra usage or an exhausted window | Explain waiting, account choice and billing options; do not enable paid usage, switch auth or change transport without approval |
|
|
421
|
+
| Warning that a fast turn ran at standard speed | Fast mode ineligible (usage credits off, cooldown, not first-party) | Prefer non-fast id; paid usage changes require approval |
|
|
422
|
+
| `claude --model claude-mythos-*` errors | Limited-availability model | Use `claude-fable-5` or `claude-fable-5-1` |
|
|
423
|
+
| Startup warning about `ANTHROPIC_API_KEY` | CLI may prefer env credentials | Confirm billing intent; strip only with approval, without displaying the key |
|
|
424
|
+
| A question form never renders and the turn hangs | Known affected opencode TUI versions with `"Question"` or `planModeQuestion: true` | Keep both off until a tested upstream fix; prose fallback can ask/wait but does not prove plan-mode unlock |
|
|
425
|
+
| No thinking summary | CLI version, explicit disable/summary env, or no thinking text emitted | Check version and nonsecret flag presence; do not override deliberate user suppression |
|
|
426
|
+
| `⚙ invalid` rows for `todowrite` inside a subagent | Subagent lacks `permission.todowrite: "allow"` | Grant it on the agent definition with approval |
|
|
427
|
+
| Other `⚙ invalid` or `⚙ unknown` tool rows | A Claude tool the plugin does not map for this version | Note plugin version, CLI version and the tool name; upgrade or report |
|
|
428
|
+
| `AGENTS.md` appears twice in Claude's system prompt | Plugin older than 0.16.0 | Upgrade |
|
|
429
|
+
|
|
430
|
+
## Do not
|
|
431
|
+
|
|
432
|
+
- Do not enable `planModeQuestion` or `"Question"` by default; both depend on an
|
|
433
|
+
opencode form broken on measured versions. Recheck upstream, do not assume a fix.
|
|
434
|
+
- Do not "fix" the `-fast` model ids by passing Anthropic-looking names; the real ones are
|
|
435
|
+
retired and the `--settings` opt-in is the only headless path.
|
|
436
|
+
- Do not add long-context `cost.tiers` to a model; Claude 4.6+ bills the full 1M window
|
|
437
|
+
at standard rates.
|
|
438
|
+
- Do not set `name`, `providerID`, `account` or `configDir` by hand when `accounts` is
|
|
439
|
+
in use; expansion writes them.
|
|
440
|
+
- Do not point `cliPath` at the generated account wrapper in
|
|
441
|
+
`~/.cache/opencode-claude-code-plugin/`; the plugin generates and selects it.
|