@khalilgharbaoui/opencode-claude-code-plugin 0.58.0 → 0.60.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/dist/index.d.ts +29 -4
- package/dist/index.js +555 -84
- package/dist/index.js.map +1 -1
- package/dist/tui.js +72 -0
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +20 -4
package/package.json
CHANGED
|
@@ -119,7 +119,7 @@ Defaults below describe normal headless opencode use when the key is absent.
|
|
|
119
119
|
| `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. |
|
|
120
120
|
| `accountInProcess` | boolean | unset/derived | Set by the config hook on Windows, where there is no per-account wrapper script: the spawn exports `CLAUDE_CONFIG_DIR` itself and strips the `@<account>` marker off `--model`. Do not hand-wire it. |
|
|
121
121
|
| `subagentDispatch` | `"ask"` / `"off"` | `"off"` | **Opt-in: only an explicit `"ask"` raises the form**, so unset and `"off"` are identical and a dispatch is handed to opencode exactly as it is today. With `"ask"`, a proxied `task` or `task_batch` call is held at the drain and the turn ends on opencode's native `question` form asking how the subagents should run; the real `task` calls are released, with the answer applied, on the next step of the SAME opencode turn. Always exactly one question first (`Same as last time` when this conversation has one, `Default`, four curated model/effort combos, `Customise…`), so the common answer is one click. `Customise…` opens a second form with one row per agent type plus one account row when more than one account is offered. That account row also offers `Per type…` when the dispatch has more than one agent type, and a type row with more than one task offers `Per task…`; either one opens a third form, and asking for both gives one third form carrying the per-type account rows followed by the per-task rows. Every row takes a typed answer too: a model id, an effort level, an `@account`, or any combination (`claude-opus-5-5 max @worker`); anything unrecognised keeps that row's default with a NOTICE. **The account is choosable at three widths and the narrowest wins**: the dispatch (`Account` row), the agent type (`Per type…` or `@name` on the type's row) and one task (`@name` on its row in the third form). Every account answer, typed ones included, is checked against the same same-group candidate list. The answer applies to each child's own `claude` spawn (`--model`, `CLAUDE_CODE_EFFORT_LEVEL`, and the account's wrapper and `CLAUDE_CONFIG_DIR`) and beats `forceModel`, `defaultSubagentModel` and the inherited effort, because it is about this dispatch. A child is matched to its task by the dispatching session, the subagent type and the task prompt, verified against `parentID`. A dismissed or unanswered form dispatches with the defaults and writes one `▌ **subagent dispatch:**` note; the dispatch is never lost. Never on compaction turns, never inside a child session (a subagent follows the choice its own parent made for it), and only where opencode's registry has the `question` entry. `Same as last time` is per opencode session and per agent type and is kept in `$XDG_STATE_HOME/opencode-claude-code-plugin/subagent-dispatch.json` (`0600`, capped at 128 sessions and 32 agent types each, pruned at 30 days, merged rather than overwritten between opencode processes, deleted with the session), so it survives an opencode restart; only the model id, effort level and account name are stored. A remembered model this install no longer has, or an account no longer configured or no longer in the group, is dropped from the row and named in one note. Both transports, both opencode majors. |
|
|
122
|
-
| `subagentDispatchCrossGroup` | boolean | `false` | Let `subagentDispatch`'s account row offer accounts outside the dispatching account's own `accountGroups` group. **Off by default and never implied by anything else**: a subagent is handed the task text the main agent writes, which can quote the conversation, and it reads the repository, so offering another group is offering that group the conversation by another route. Does nothing when `accountGroups` is unset, where every account is already one group, or when `subagentDispatch` is off. |
|
|
122
|
+
| `subagentDispatchCrossGroup` | boolean | `false` | Let `subagentDispatch`'s account row offer accounts outside the dispatching account's own `accountGroups` group, and on opencode 2 let a `task` call's own `model` name one. **Off by default and never implied by anything else**: a subagent is handed the task text the main agent writes, which can quote the conversation, and it reads the repository, so offering another group is offering that group the conversation by another route. Does nothing when `accountGroups` is unset, where every account is already one group, or when `subagentDispatch` is off. |
|
|
123
123
|
| `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. |
|
|
124
124
|
| `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 and interactive spawns, never compaction. |
|
|
125
125
|
| `defaultSubagentMaxTurns` | number | unset | `--max-turns` for discovered `mode: subagent` agents that declare no `maxTurns`; the agent's own value wins. Counted by the CLI per user message, so safe on a reused process. CLI 2.1.280+; headless only (print-only flag, the interactive transport WARNs once). Part of the session key. |
|
|
@@ -202,6 +202,12 @@ reports "the plugin printed garbage over my opencode UI", the answer is to upgra
|
|
|
202
202
|
turn logging off; and when they ask where a WARN went in the TUI, point them at opencode's
|
|
203
203
|
own log or the toast rather than at stderr.
|
|
204
204
|
|
|
205
|
+
On opencode 2 the plugin runs in a separate process whose stderr nobody sees, so WARN and
|
|
206
|
+
ERROR also go to the plugin's own sidebar half over the RPC channel opencode 2 gives a
|
|
207
|
+
plugin between its two halves, and the sidebar half raises the same `claude-code` toast
|
|
208
|
+
under the same limits, in the window the warning came from (measured on 2.0.31). When a 2.x
|
|
209
|
+
user asks where a warning went, it is that toast and the plugin log file; stderr is a pipe.
|
|
210
|
+
|
|
205
211
|
## Environment variables
|
|
206
212
|
|
|
207
213
|
Set variables in the environment that launches opencode, then fully restart it.
|
|
@@ -291,7 +297,7 @@ Same package, same config. 2.x's native key is `plugins` (plural), but it still
|
|
|
291
297
|
- Check the major first with `opencode --version`. `plugin` is read by both majors (recorded in `docs/agents-history.md` #g39); `plugins` is read by 2.x only.
|
|
292
298
|
- Provider settings, lowest precedence first: `provider.claude-code.options` (1.x's spelling, still read on 2.x), `provider.claude-code.settings`, `providers.claude-code.settings` (2.x's own), and the plugin entry's own `options`, which wins over all three. Any option of this plugin can sit in any of them; the plugin entry is the usual home for `accounts`: `{"package": "@khalilgharbaoui/opencode-claude-code-plugin", "options": {"accounts": ["work"]}}`.
|
|
293
299
|
- A local checkout is loaded by pointing `plugins` at its **`dist`** directory, never the repository root: 2.x resolves a configured plugin path as `<dir>/server` or `<dir>/index`.
|
|
294
|
-
- Known 2.x differences:
|
|
300
|
+
- Known 2.x differences: a `task` call can carry its own `model` (2.x's `subagent` tool takes one; 1.x's `task` does not), there is no todo panel (2.x has no `todowrite` tool, so the sidebar's progress bar is always the time estimate), `bridgeMcpOauthTokens` finds nothing (2.x's plugin API can activate a stored credential but not read one), and Claude's `EnterPlanMode`, `ExitPlanMode` and `NotebookEdit` calls get no tool row (2.x rejects an unknown tool name). Everything else behaves as on 1.x, including `/btw` answered inside the running turn, a permission prompt not counting against a proxied call's deadline, a stopped turn releasing its parked proxied calls, and warnings shown as toasts: the plugin reads busy and idle off opencode 2's event stream (`session.execution.*`) and sends warnings over its plugin RPC channel (measured on 2.0.22 and 2.0.31). Do not set `hostApi`; the 2.x entrypoint sets it, and forcing it on 1.x breaks every proxied tool call.
|
|
295
301
|
- Every form the plugin raises is answered through 2.x's own `Form` surface rather than a question tool, which changes nothing the operator does. The account-switch form and the plan-mode approval were measured live on 2.0.22, and the `subagentDispatch` form (including `Customise…`, `Per type…` accounts and `Same as last time` across a restart) on 2026-10-08. The by-hand account carry and the `accountGroups` guard were measured live there the same day: both behave exactly as on 1.x.
|
|
296
302
|
|
|
297
303
|
#### V2 MCP and Code Mode
|
|
@@ -645,8 +651,9 @@ Or once for every discovered subagent without a full provider/model pin:
|
|
|
645
651
|
} } } }
|
|
646
652
|
```
|
|
647
653
|
|
|
648
|
-
Rules, in order:
|
|
649
|
-
|
|
654
|
+
Rules, in order: on opencode 2 a model named for that dispatch in the conversation
|
|
655
|
+
(the `task` call's `model`) wins over everything here; else `forceModel` wins; else
|
|
656
|
+
`mode: subagent` with `defaultSubagentModel` set; else untouched. An agent with `model: <provider>/<id>` is left exactly as written,
|
|
650
657
|
account and all (`model: claude-code-work/claude-opus-5@work` pins the account too).
|
|
651
658
|
Undeclared built-ins are not discovered; a user definition with a built-in name can
|
|
652
659
|
enter the registry and is subject to these rules. This is not a built-in-name denylist.
|
|
@@ -721,6 +728,8 @@ What happens, in order:
|
|
|
721
728
|
Rules worth stating to a user:
|
|
722
729
|
|
|
723
730
|
- A dispatch answer beats `forceModel`, `defaultSubagentModel` and the inherited effort.
|
|
731
|
+
- A task whose `task` call names its own `model` (opencode 2) is not asked about, and a
|
|
732
|
+
dispatch whose every task names one raises no form: the user already chose.
|
|
724
733
|
- Any row takes a typed answer: a registered model id, an effort level, an `@account`,
|
|
725
734
|
or any combination (`claude-opus-5-5 max @worker`). Unrecognised text keeps that row's
|
|
726
735
|
default with a NOTICE.
|
|
@@ -875,6 +884,13 @@ rejects what the previous turn left pending and tells the CLI. The process exiti
|
|
|
875
884
|
chat being deleted, or opencode exiting rejects the rest. That is why `task` and
|
|
876
885
|
`task_batch` carry no default deadline and a subagent runs to completion.
|
|
877
886
|
|
|
887
|
+
On opencode 2, `task` and each `task_batch.tasks` item take an optional `model`: opencode's exact `providerID/modelID` reference with an optional `#variant` (`claude-code/claude-sonnet-5-5#high`; on a multi-account install `claude-code-<account>/<model>@<account>`). The model is told to set it only when the user asked for a particular model, and only with an id the user gave. The proxy forwards it unchanged to opencode's own `subagent` tool, which resolves it against the models it has; omitted, opencode picks the model as usual, and `task_id` and `background` behave as before. What the plugin adds on top (h #g254):
|
|
888
|
+
|
|
889
|
+
- An explicit model beats the agent's `forceModel` and `defaultSubagentModel`, and a named `#variant` beats its `reasoningEffort` (opencode's own order). The child's prologue finds the request by parent session, agent type and first message, the dispatch form's rule, and applies it only while the child runs on exactly that model.
|
|
890
|
+
- A task that names a model is left out of the `subagentDispatch` form; a dispatch whose every task names one raises no form.
|
|
891
|
+
- A model on a plugin account outside the dispatching account's `accountGroups` group is refused before any task of the call starts; `subagentDispatchCrossGroup: true` lifts it. A model on any other provider is opencode's own routing and is not checked.
|
|
892
|
+
- opencode 1's `task` has no such field: the plugin reads the live `task` schema, leaves `model` out there, and refuses a call or a whole batch that sets it anyway, before dispatch.
|
|
893
|
+
|
|
878
894
|
Three timers remain and are distinct from that: the optional per-tool deadlines
|
|
879
895
|
(`proxyToolTimeoutMs`, a backstop the user chooses), the start and inactivity
|
|
880
896
|
watchdogs (for a process that is alive but silent, which emits nothing to listen to; a
|