@khalilgharbaoui/opencode-claude-code-plugin 0.29.2 → 0.31.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 +42 -7
- package/dist/index.d.ts +27 -0
- package/dist/index.js +317 -32
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/skills/claude-code-plugin/SKILL.md +59 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khalilgharbaoui/opencode-claude-code-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "Claude Code CLI provider plugin for opencode",
|
|
5
5
|
"author": "Khalil Gharbaoui",
|
|
6
6
|
"type": "module",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"build": "tsup",
|
|
22
22
|
"dev": "tsup --watch",
|
|
23
23
|
"typecheck": "tsc --noEmit",
|
|
24
|
-
"test": "OPENCODE_CLAUDE_CODE_LOG_FILE=0 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-permission-presets.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-turn-stats.ts test-cli-events.ts test-cli-events-stream.ts test-result-fallback.ts test-doctor.ts test-configure-skill.ts test-unattended-replay.ts test-process-lifecycle.ts test-account-failover.ts test-host-tools.ts test-v2-entrypoint.ts test-v2-client.ts test-tmp-dir.ts test-cleanup-stale.ts test-account-wrapper.ts test-runtime-status-sessions.ts test-index-hooks.ts test-silent-turn.ts test-mcp-tool-result-name.ts test-model-fallback.ts test-do-generate.ts"
|
|
24
|
+
"test": "OPENCODE_CLAUDE_CODE_LOG_FILE=0 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-permission-presets.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-context-usage.ts test-skill-bridge.ts test-turn-stats.ts test-cli-events.ts test-cli-events-stream.ts test-result-fallback.ts test-doctor.ts test-configure-skill.ts test-unattended-replay.ts test-process-lifecycle.ts test-account-failover.ts test-host-tools.ts test-v2-entrypoint.ts test-v2-client.ts test-tmp-dir.ts test-cleanup-stale.ts test-account-wrapper.ts test-runtime-status-sessions.ts test-index-hooks.ts test-silent-turn.ts test-mcp-tool-result-name.ts test-model-fallback.ts test-do-generate.ts"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@ai-sdk/provider": "^3.0.8",
|
|
@@ -110,6 +110,7 @@ Defaults below describe normal headless opencode use when the key is absent.
|
|
|
110
110
|
| `failoverAccounts` | string[] | unset/derived | Account expansion supplies the resolved account list so a limited account can offer the others. Do not hand-wire it; set `accounts` instead. |
|
|
111
111
|
| `baseCliPath` | string | unset/derived | The `cliPath` before the per-account wrapper substitution, so a failover can build another account's wrapper on the same binary. Supplied by the config hook. Do not hand-wire it. |
|
|
112
112
|
| `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. |
|
|
113
|
+
| `defaultSubagentCacheTtl` | string | unset | Prompt cache TTL (`5m` / `1h`) for discovered `mode: subagent` agents that declare no `cacheTtl`; the agent's own value takes precedence. Unset leaves the CLI's default (1 hour on a subscription). Unknown values warn and change nothing. Headless spawns only (not compaction, not the interactive transport). |
|
|
113
114
|
| `fallbackModels` | string[] | unset | Ordered models to try when the model a turn would run on is refused. Default for agents declaring no `fallbackModels`; a per-agent list replaces it rather than extending it. Same account throughout, never a switch. Armed only by the CLI refusing the model (`model_not_found`) or by a usage limit when `accountFailover` has no other account to offer; with another account the switch form wins. Entries must be registered model ids, unknown ones warn and are skipped, the current model is dropped from its own chain, each entry is tried at most once per turn, and an exhausted chain surfaces the original error. Never on compaction, title stubs or the interactive transport. Writes a `▌ **model fallback:**` note that transcript rebuilds strip. Not independently read per expanded account. |
|
|
114
115
|
| `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. |
|
|
115
116
|
| `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. Ignored when `permissionMode` is `"plan"`, which always drops the flag. |
|
|
@@ -292,13 +293,17 @@ description: Designs and builds UI work
|
|
|
292
293
|
mode: subagent
|
|
293
294
|
forceModel: claude-haiku-4-5
|
|
294
295
|
reasoningEffort: high
|
|
296
|
+
cacheTtl: 5m
|
|
295
297
|
---
|
|
296
298
|
```
|
|
297
299
|
|
|
298
300
|
Or once for every discovered subagent without a full provider/model pin:
|
|
299
301
|
|
|
300
302
|
```json
|
|
301
|
-
{ "provider": { "claude-code": { "options": {
|
|
303
|
+
{ "provider": { "claude-code": { "options": {
|
|
304
|
+
"defaultSubagentModel": "claude-opus-5",
|
|
305
|
+
"defaultSubagentCacheTtl": "5m"
|
|
306
|
+
} } } }
|
|
302
307
|
```
|
|
303
308
|
|
|
304
309
|
Rules, in order: `forceModel` wins; else `mode: subagent` with `defaultSubagentModel`
|
|
@@ -307,8 +312,19 @@ account and all (`model: claude-code-work/claude-opus-5@work` pins the account t
|
|
|
307
312
|
Undeclared built-ins are not discovered; a user definition with a built-in name can
|
|
308
313
|
enter the registry and is subject to these rules. This is not a built-in-name denylist.
|
|
309
314
|
`reasoningEffort` in the agent file beats the effort the call arrived with; compaction is
|
|
310
|
-
exempt. Effort and
|
|
311
|
-
rather than sharing a process.
|
|
315
|
+
exempt. Effort, model and cache TTL are part of the CLI session key, so a changed agent
|
|
316
|
+
respawns rather than sharing a process.
|
|
317
|
+
|
|
318
|
+
`cacheTtl` sets the prompt cache TTL of that agent's own `claude` process, as
|
|
319
|
+
`CLAUDE_CODE_PROMPT_CACHE_TTL` at spawn. Unset (the default) leaves the CLI deciding,
|
|
320
|
+
which is 1 hour on a subscription. Claude Code also has a per-agent
|
|
321
|
+
`experimental.cacheTtl` and a `CLAUDE_CODE_SUBAGENT_PROMPT_CACHE_TTL`: neither does
|
|
322
|
+
anything here, because both apply only to subagents the CLI runs through its own `Task`
|
|
323
|
+
tool, and this plugin disallows that tool by default so opencode runs the subagent
|
|
324
|
+
instead. An opencode subagent is a separate `claude --print` process, which the CLI
|
|
325
|
+
counts as a main conversation. Use `cacheTtl: 5m` on short-lived workers that never
|
|
326
|
+
re-read the cache they wrote, since a 1-hour write is billed above a 5-minute one and
|
|
327
|
+
both come out of the same usage limit; leave a long-lived main session at the default.
|
|
312
328
|
|
|
313
329
|
Only grant `permission.task` for approved target agents if delegation is wanted.
|
|
314
330
|
`permission.todowrite: "allow"` is needed for subagent todos; opencode otherwise denies
|
|
@@ -324,6 +340,7 @@ the opencode schema requires it. Markdown fallback reads top-level scalar fields
|
|
|
324
340
|
| `model` | Full `provider/model` pins bypass plugin model overrides, not the separate effort override. |
|
|
325
341
|
| `forceModel` | Registered bare model id, preserving the caller's account even if an account suffix is supplied. Works for any discovered agent mode. |
|
|
326
342
|
| `reasoningEffort` | `minimal`, `low`, `medium`, `high`, `xhigh`, `max`; invalid declarations warn and keep inherited effort. `minimal` maps to CLI `low`. Compaction skips this override. |
|
|
343
|
+
| `cacheTtl` | `5m` or `1h`; anything else warns and leaves the CLI's default alone. Exported as `CLAUDE_CODE_PROMPT_CACHE_TTL`, beating a shell export of the same name. Works for any discovered agent mode; compaction skips it. |
|
|
327
344
|
| `fallbackModels` | Ordered registered bare model ids to try when this agent's model is refused. Both YAML spellings (`[a, b]` or a `- ` block). Replaces the provider-level `fallbackModels` rather than extending it. Keeps the caller's account; an entry carrying `@account` has it stripped. Unknown ids warn and are skipped. |
|
|
328
345
|
|
|
329
346
|
### Degrade to another model instead of failing
|
|
@@ -373,6 +390,17 @@ The proxy's loopback endpoint has bearer, Host, Origin and Content-Type guards.
|
|
|
373
390
|
Never weaken them, publish its token or relax the generated MCP file's `0600` mode.
|
|
374
391
|
Restart all old processes after a security upgrade; changing files cannot patch them.
|
|
375
392
|
|
|
393
|
+
Proxying a tool costs **one extra Claude Code API call per `claude` process**: a proxied
|
|
394
|
+
tool is an MCP tool, Claude Code 2.1.280 defers MCP tools behind `ToolSearch`, so the
|
|
395
|
+
model spends a request finding it before the first proxied call. Built-ins are never
|
|
396
|
+
deferred. Measured on 2.1.280 (`docs/agents-history.md`, `#g166`): 3 API calls with
|
|
397
|
+
`Bash` proxied against 2 without, and it is paid once per process, not per call (two
|
|
398
|
+
commands measured 4 against 3, one `ToolSearch` either way). It is not caused by a large
|
|
399
|
+
tool list. Never suggest `ENABLE_TOOL_SEARCH=0` to avoid it: that inlines every tool
|
|
400
|
+
definition into each prompt and measured 2.5 to 4 times the cost. Say the extra call is
|
|
401
|
+
inherent to the CLI's MCP flow and weigh it against the permission prompts and audit log
|
|
402
|
+
proxying buys.
|
|
403
|
+
|
|
376
404
|
### Make a provider read-only
|
|
377
405
|
|
|
378
406
|
```json
|
|
@@ -547,15 +575,15 @@ No manual skill copy/update is needed. Do not publish or release as part of conf
|
|
|
547
575
|
### Registered model ids
|
|
548
576
|
|
|
549
577
|
Registered ids: `claude-haiku-4-5`, `claude-sonnet-4-5`, `claude-sonnet-4-6`,
|
|
550
|
-
`claude-sonnet-5`, `claude-
|
|
551
|
-
`claude-opus-4-
|
|
552
|
-
`claude-opus-5-
|
|
553
|
-
`claude-mythos-5`, `claude-mythos-5-1`.
|
|
578
|
+
`claude-sonnet-5`, `claude-sonnet-5-5`, `claude-opus-4-5`, `claude-opus-4-6`,
|
|
579
|
+
`claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-4-8-fast`, `claude-opus-5`,
|
|
580
|
+
`claude-opus-5-fast`, `claude-opus-5-5`, `claude-opus-5-5-fast`, `claude-fable-5`,
|
|
581
|
+
`claude-fable-5-1`, `claude-mythos-5`, `claude-mythos-5-1`.
|
|
554
582
|
|
|
555
583
|
### Variants and costs
|
|
556
584
|
|
|
557
585
|
- Display names end in a `(N×)` list-price multiplier relative to Haiku: 1× haiku,
|
|
558
|
-
3× sonnet, 4× opus 5.5, 5× other opus, 8× fast-mode opus 5.5, 10× fable, mythos
|
|
586
|
+
2× sonnet 5 and 5.5, 3× sonnet 4.5/4.6, 4× opus 5.5, 5× other opus, 8× fast-mode opus 5.5, 10× fable, mythos
|
|
559
587
|
and fast-mode opus 5 / 4.8. It is display only.
|
|
560
588
|
- Every model except Haiku has reasoning variants `low`, `medium`, `high`, `xhigh`,
|
|
561
589
|
`max`, picked in opencode's model selector. A variant becomes
|
|
@@ -568,6 +596,9 @@ Registered ids: `claude-haiku-4-5`, `claude-sonnet-4-5`, `claude-sonnet-4-6`,
|
|
|
568
596
|
reason. Switch to a non-fast id rather than silently enabling paid usage credits.
|
|
569
597
|
Review eligibility/billing with the user; the enabled state needs live verification
|
|
570
598
|
on their account. CLI floors are gates, not proof of model access.
|
|
599
|
+
- `claude-sonnet-5-5` needs Claude Code 2.1.284+ to run on its real limits. An older CLI
|
|
600
|
+
still serves it on fallback limits (200k context, an estimated cost), and the plugin
|
|
601
|
+
logs a WARN naming the model and the floor: the fix is `claude update`.
|
|
571
602
|
- `claude-mythos-5` and `claude-mythos-5-1` are limited availability (Project Glasswing).
|
|
572
603
|
Without access `claude --model` errors; use the corresponding `claude-fable-*`.
|
|
573
604
|
- Ordinary calls can pass through unregistered ids; availability and opencode model
|
|
@@ -632,13 +663,29 @@ proxy URL (`401, good`; anything else is flagged unsafe). Prefer it over asking
|
|
|
632
663
|
prompt. A user-defined `claude-code-doctor` command is never overwritten. The name has
|
|
633
664
|
no space in it: opencode would read the second word as an argument.
|
|
634
665
|
|
|
666
|
+
It also prints an **MCP config entries Claude Code skipped** section, but only when the
|
|
667
|
+
CLI refused an entry in an `--mcp-config` it was given. Read it whenever MCP tools are
|
|
668
|
+
missing: a skipped server is absent from the CLI's server list rather than listed
|
|
669
|
+
broken, so nothing else hints at it. A skipped `opencode_proxy` is the plugin's own
|
|
670
|
+
server, not the user's config, and means every proxied tool call in the session fails.
|
|
671
|
+
|
|
672
|
+
`/claude-code-doctor usage` adds a **Plan usage** section: the CLI's own `/cost` answer
|
|
673
|
+
(subscription vs API key, 5-hour and 7-day window use, reset times, what is driving
|
|
674
|
+
them). Measured free on 2.1.280 (`num_turns: 0`, `$0`, no API call), so suggest it for
|
|
675
|
+
"how much have I used" and limit questions. It is opt-in only because it starts a
|
|
676
|
+
short-lived `claude`, which runs the user's `SessionStart` hooks and takes a few
|
|
677
|
+
seconds; say that when suggesting it. The plain command stays instant and says how to
|
|
678
|
+
ask. Do not propose `--bare` to skip the hooks: it never reads OAuth, so it reports
|
|
679
|
+
nothing about a subscription.
|
|
680
|
+
|
|
635
681
|
Claude Code stream events the plugin now surfaces without debug logging: a rate-limit
|
|
636
682
|
rejection, a context compaction the CLI did on its own, a `result` subtype other than
|
|
637
683
|
`success` (which now finishes the turn as an error, not a clean stop), and a failed
|
|
638
684
|
CLI-executed tool (forwarded with the error flag, so the row renders as failed). A
|
|
639
|
-
failed MCP server at session start
|
|
640
|
-
|
|
641
|
-
|
|
685
|
+
failed MCP server at session start, an `--mcp-config` entry the CLI skipped, and an
|
|
686
|
+
`apiKeySource` that means API-key billing each warn once per identity per process.
|
|
687
|
+
None of these are actions the plugin may take on the user's behalf; enabling paid
|
|
688
|
+
usage or changing auth still needs approval.
|
|
642
689
|
|
|
643
690
|
`/btw <question>` needs an existing headless Claude conversation and CLI 2.1.258+.
|
|
644
691
|
It asks through the side channel and keeps the answer in the conversation (inline
|
|
@@ -696,6 +743,7 @@ Prefer the doctor: it needs no logging change and no restart.
|
|
|
696
743
|
| Claude "forgot" the earlier part of a long conversation | Claude Code compacted its own context | Look for the `▌ **context compacted:**` note in the transcript |
|
|
697
744
|
| Claude forgot the whole conversation at once | Claude Code cleared it (`/clear` sent as a message, or a plan-mode exit that clears context) | Look for the `▌ **claude code reset:**` note. The plugin does not replay history there on purpose; a new opencode session gets a clean slate |
|
|
698
745
|
| Wanting the per-turn cost in the chat | Not shown by default | Set `turnStats: true` and restart opencode |
|
|
746
|
+
| opencode auto-compacts a Claude session far below the model's window, often several times in a row after tool-heavy turns | Plugin older than this fix reported the CLI's turn-summed usage (every API call's cache reads added up) as the context size | Upgrade and relaunch. opencode's per-message tokens are now the last call's context, so its cost figure for a multi-call turn is lower than the real one; the real cost is in `turnStats` and `providerMetadata["claude-code"].costUsd` |
|
|
699
747
|
| Turn ends with an error naming an exit code or signal and a stderr tail | The `claude` child died mid-turn without emitting its terminal `result` | Read the quoted stderr; that is the CLI's own reason. Older builds reported this as a normal stop, so a truncated answer looked finished |
|
|
700
748
|
| An answer is cut off with no error, in a window with many open chats | Plugin older than this fix: LRU eviction could kill a process mid-turn | Upgrade. Eviction now takes the oldest idle process and skips the round when all 8 are busy; the 30-minute idle timer spares a busy worker too |
|
|
701
749
|
| A `claude` worker lingers after its chat was deleted, or after opencode quit | Plugin older than this release | Upgrade. Deleting a chat now releases its workers; every retained worker is killed when opencode exits |
|