@khalilgharbaoui/opencode-claude-code-plugin 0.29.2 → 0.30.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khalilgharbaoui/opencode-claude-code-plugin",
3
- "version": "0.29.2",
3
+ "version": "0.30.0",
4
4
  "description": "Claude Code CLI provider plugin for opencode",
5
5
  "author": "Khalil Gharbaoui",
6
6
  "type": "module",
@@ -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": { "defaultSubagentModel": "claude-opus-5" } } } }
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 model are part of the CLI session key, so a changed agent respawns
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
@@ -632,13 +660,29 @@ proxy URL (`401, good`; anything else is flagged unsafe). Prefer it over asking
632
660
  prompt. A user-defined `claude-code-doctor` command is never overwritten. The name has
633
661
  no space in it: opencode would read the second word as an argument.
634
662
 
663
+ It also prints an **MCP config entries Claude Code skipped** section, but only when the
664
+ CLI refused an entry in an `--mcp-config` it was given. Read it whenever MCP tools are
665
+ missing: a skipped server is absent from the CLI's server list rather than listed
666
+ broken, so nothing else hints at it. A skipped `opencode_proxy` is the plugin's own
667
+ server, not the user's config, and means every proxied tool call in the session fails.
668
+
669
+ `/claude-code-doctor usage` adds a **Plan usage** section: the CLI's own `/cost` answer
670
+ (subscription vs API key, 5-hour and 7-day window use, reset times, what is driving
671
+ them). Measured free on 2.1.280 (`num_turns: 0`, `$0`, no API call), so suggest it for
672
+ "how much have I used" and limit questions. It is opt-in only because it starts a
673
+ short-lived `claude`, which runs the user's `SessionStart` hooks and takes a few
674
+ seconds; say that when suggesting it. The plain command stays instant and says how to
675
+ ask. Do not propose `--bare` to skip the hooks: it never reads OAuth, so it reports
676
+ nothing about a subscription.
677
+
635
678
  Claude Code stream events the plugin now surfaces without debug logging: a rate-limit
636
679
  rejection, a context compaction the CLI did on its own, a `result` subtype other than
637
680
  `success` (which now finishes the turn as an error, not a clean stop), and a failed
638
681
  CLI-executed tool (forwarded with the error flag, so the row renders as failed). A
639
- failed MCP server at session start and an `apiKeySource` that means API-key billing
640
- each warn once per process. None of these are actions the plugin may take on the user's
641
- behalf; enabling paid usage or changing auth still needs approval.
682
+ failed MCP server at session start, an `--mcp-config` entry the CLI skipped, and an
683
+ `apiKeySource` that means API-key billing each warn once per identity per process.
684
+ None of these are actions the plugin may take on the user's behalf; enabling paid
685
+ usage or changing auth still needs approval.
642
686
 
643
687
  `/btw <question>` needs an existing headless Claude conversation and CLI 2.1.258+.
644
688
  It asks through the side channel and keeps the answer in the conversation (inline