@khalilgharbaoui/opencode-claude-code-plugin 0.7.0 → 0.8.1

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 CHANGED
@@ -23,7 +23,7 @@ claude --version
23
23
 
24
24
  That's it. Restart opencode, pick a `claude-code` model, done.
25
25
 
26
- The plugin self-registers the `claude-code` provider, all current Claude Code models (Haiku 4.5, Sonnet 4.5/4.6, Opus 4.5/4.6/4.7/4.8) with reasoning variants (`low` / `medium` / `high` / `xhigh` / `max`), and sensible defaults for tool proxying. You don't need to write a `provider` block at all unless you want to override something.
26
+ The plugin self-registers the `claude-code` provider, all current Claude Code models (Haiku 4.5, Sonnet 4.5/4.6, Opus 4.5/4.6/4.7/4.8, Fable 5, Mythos 5) with reasoning variants (`low` / `medium` / `high` / `xhigh` / `max`), and sensible defaults for tool proxying. You don't need to write a `provider` block at all unless you want to override something.
27
27
 
28
28
  ---
29
29
 
@@ -66,18 +66,24 @@ In your `opencode.json`, point at the local build with a `file://` URL:
66
66
 
67
67
  The plugin auto-registers the following. They appear in the model picker without any extra config.
68
68
 
69
- | ID | Display name | Context | Output | Reasoning variants |
70
- |---|---|---|---|---|
71
- | `claude-haiku-4-5` | Claude Code Haiku 4.5 | 200k | 8,192 | – |
72
- | `claude-sonnet-4-5` | Claude Code Sonnet 4.5 | 1M | 16,384 | low/medium/high/xhigh/max |
73
- | `claude-sonnet-4-6` | Claude Code Sonnet 4.6 | 1M | 16,384 | low/medium/high/xhigh/max |
74
- | `claude-opus-4-5` | Claude Code Opus 4.5 | 1M | 16,384 | low/medium/high/xhigh/max |
75
- | `claude-opus-4-6` | Claude Code Opus 4.6 | 1M | 16,384 | low/medium/high/xhigh/max |
76
- | `claude-opus-4-7` | Claude Code Opus 4.7 | 1M | 16,384 | low/medium/high/xhigh/max |
77
- | `claude-opus-4-8` | Claude Code Opus 4.8 | 1M | 16,384 | low/medium/high/xhigh/max |
69
+ | ID | Display name | Context | Output | Reasoning variants | Price × |
70
+ |---|---|---|---|---|---|
71
+ | `claude-haiku-4-5` | Claude Haiku 4.5 | 200k | 8,192 | – | 1× |
72
+ | `claude-sonnet-4-5` | Claude Sonnet 4.5 | 1M | 16,384 | low/medium/high/xhigh/max | 3× |
73
+ | `claude-sonnet-4-6` | Claude Sonnet 4.6 | 1M | 16,384 | low/medium/high/xhigh/max | 3× |
74
+ | `claude-opus-4-5` | Claude Opus 4.5 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
75
+ | `claude-opus-4-6` | Claude Opus 4.6 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
76
+ | `claude-opus-4-7` | Claude Opus 4.7 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
77
+ | `claude-opus-4-8` | Claude Opus 4.8 | 1M | 16,384 | low/medium/high/xhigh/max | 5× |
78
+ | `claude-fable-5` | Claude Fable 5 | 1M | 16,384 | low/medium/high/xhigh/max | 10× |
79
+ | `claude-mythos-5` | Claude Mythos 5 | 1M | 16,384 | low/medium/high/xhigh/max | 10× |
80
+
81
+ `claude-mythos-5` is Mythos-class like Fable 5 but without safety classifiers, and is **limited availability via [Project Glasswing](https://anthropic.com/glasswing)**. It's registered unconditionally; if your Claude account lacks access, `claude --model claude-mythos-5` just errors. Use `claude-fable-5` (generally available) otherwise.
78
82
 
79
83
  Capabilities for every model: text + image input, text output, tool use, attachments. No temperature control, no PDF/audio/video, no interleaved streaming.
80
84
 
85
+ **Price ×** is each model's per-token list price relative to Haiku, the cheapest model. It's derived exactly from Anthropic's published pricing — input and output ratios both come out the same (Haiku $1/$5 = 1×, Sonnet $3/$15 = 3×, Opus 4.8 $5/$25 = 5×, Fable 5 / Mythos 5 $10/$50 = 10×), so **Fable 5 and Mythos 5 cost 2× Opus 4.8**. The same multiplier is shown as a `(N×)` suffix on the display name in opencode's model picker, since opencode has no dedicated multiplier field. On a flat Max/Pro subscription it doubles as a rough guide to how fast each model drains your usage limit.
86
+
81
87
  The model ID is passed straight through to `claude --model`, so anything Claude Code accepts works.
82
88
 
83
89
  ### Picking a variant
@@ -86,6 +92,34 @@ Variants set the underlying reasoning effort. They're regular opencode model var
86
92
 
87
93
  ---
88
94
 
95
+ ## Billing change: June 15, 2026 (Agent SDK credit)
96
+
97
+ This plugin drives Claude Code headlessly (`claude --print`), which Anthropic bills as [`claude -p` / Agent SDK usage](https://support.claude.com/en/articles/15036540-use-the-claude-agent-sdk-with-your-claude-plan). Starting **June 15, 2026**, on subscription plans that usage no longer counts toward your normal plan limits — it draws from a separate monthly **Agent SDK credit**:
98
+
99
+ | Plan | Monthly credit |
100
+ |---|---|
101
+ | Pro | $20 |
102
+ | Max 5x | $100 |
103
+ | Max 20x | $200 |
104
+ | Team Standard | $20/seat |
105
+ | Team Premium | $100/seat |
106
+ | Enterprise (Standard seats) | none |
107
+
108
+ What this means for plugin users:
109
+
110
+ - **Claim the credit once.** It's a one-time opt-in via your Claude account (claim emails started going out June 8, 2026); after that it refreshes every billing cycle. Unused credit does not roll over.
111
+ - **When the credit runs out, plugin requests stop** until the next billing cycle — unless you enable usage credits in your Claude account, in which case overflow is billed at standard API rates.
112
+ - **The credit is denominated in dollars at standard API rates**, so the Price × column above maps directly to how fast each model drains it — Fable 5 / Mythos 5 burn it 10× faster than Haiku, 2× faster than Opus 4.8.
113
+ - **API-key auth is unaffected.** If your `claude` CLI authenticates with an Anthropic API key / Console billing instead of a subscription, nothing changes — pay-as-you-go as before.
114
+ - **Interactive Claude Code in your terminal is unaffected.** The change targets programmatic usage only: the Agent SDK, `claude -p`, Claude Code GitHub Actions, and third-party apps like this plugin.
115
+
116
+ Two related dates:
117
+
118
+ - **June 15, 2026** also retires the original Claude 4 model IDs `claude-sonnet-4-20250514` and `claude-opus-4-20250514` from the API. The plugin doesn't register either, but model IDs pass straight through to `claude --model` — if you've configured one of these as an override, migrate to `claude-sonnet-4-6` / `claude-opus-4-8` before then.
119
+ - **June 22, 2026** is the last day [Fable 5 is included at no extra cost](https://platform.claude.com/docs/en/about-claude/models/introducing-claude-fable-5-and-claude-mythos-5) on Pro, Max, Team, and seat-based Enterprise plans. From June 23, `claude-fable-5` requires usage credits (Anthropic says it aims to fold it back into plans once capacity allows). `claude-mythos-5` is unaffected — it's Glasswing access-gated either way.
120
+
121
+ ---
122
+
89
123
  ## Configuration
90
124
 
91
125
  The minimum config is just the `plugin` entry above. Everything below is optional override that goes in a `provider.claude-code` block.
@@ -245,7 +279,7 @@ Claude Code ships a built-in `WebSearch` tool. The `webSearch` option controls w
245
279
 
246
280
  | `webSearch` value | Behavior | When to use |
247
281
  |---|---|---|
248
- | `"claude"` (default) | Claude CLI runs WebSearch internally via Anthropic. Zero setup, no extra cost, no API key. | Most users. |
282
+ | `"claude"` (default) | Claude CLI runs WebSearch internally via Anthropic. Zero setup, no extra cost, no API key. The query is shown in the transcript as a `> Web search:` line (opencode has no `WebSearch` tool registry entry, so a raw tool row would render as `⚙ invalid`). | Most users. |
249
283
  | `"<opencode-tool-name>"` (e.g. `"websearch_web_search_exa"`) | Forward to that opencode-side tool with `executed:false`. Requires the corresponding MCP server to be configured in opencode (e.g. [exa-mcp-server](https://github.com/exa-labs/exa-mcp-server)). | You want a specific search backend (Exa, Tavily, Brave) and have the MCP wired up in opencode. |
250
284
  | `"disabled"` | `WebSearch` is added to `--disallowedTools` so the model can't call it. | Compliance/security scenarios where outbound search isn't allowed. |
251
285
 
package/dist/index.js CHANGED
@@ -210,6 +210,12 @@ function clearLedger(sessionId) {
210
210
  }
211
211
 
212
212
  // src/tool-mapping.ts
213
+ function isWebSearchTool(name) {
214
+ return name === "WebSearch" || name === "web_search";
215
+ }
216
+ function isWebSearchHandledByCli(route) {
217
+ return !route || route === "claude" || route === "disabled";
218
+ }
213
219
  function mapToolInput(name, input) {
214
220
  if (!input) return input;
215
221
  switch (name) {
@@ -326,7 +332,7 @@ function mapTool(name, input, opts) {
326
332
  const mappedInput = mapToolInput(name, input);
327
333
  return { name: "todowrite", input: mappedInput, executed: false };
328
334
  }
329
- if (name === "WebSearch" || name === "web_search") {
335
+ if (isWebSearchTool(name)) {
330
336
  const mappedInput = input?.query ? { query: input.query } : input;
331
337
  const route = opts?.webSearch;
332
338
  if (route && route !== "claude" && route !== "disabled") {
@@ -334,7 +340,7 @@ function mapTool(name, input, opts) {
334
340
  return { name: route, input: mappedInput, executed: false };
335
341
  }
336
342
  log.debug("WebSearch executed by Claude CLI", { mappedInput });
337
- return { name: "WebSearch", input: mappedInput, executed: true };
343
+ return { name: "WebSearch", input: mappedInput, executed: true, skip: true };
338
344
  }
339
345
  if (name === "TaskOutput") {
340
346
  if (!input) return { name: "bash", executed: false };
@@ -3495,6 +3501,17 @@ ${plan}
3495
3501
 
3496
3502
  ---
3497
3503
  **Do you want to proceed with this plan?** (yes/no)
3504
+ `
3505
+ });
3506
+ endTextBlock();
3507
+ } else if (isWebSearchTool(tc.name) && isWebSearchHandledByCli(self.config.webSearch)) {
3508
+ const query = typeof parsedInput?.query === "string" ? parsedInput.query : JSON.stringify(parsedInput);
3509
+ const searchId = startTextBlock();
3510
+ controller.enqueue({
3511
+ type: "text-delta",
3512
+ id: searchId,
3513
+ delta: `
3514
+ > **Web search:** ${query}
3498
3515
  `
3499
3516
  });
3500
3517
  endTextBlock();
@@ -3654,6 +3671,18 @@ ${plan}
3654
3671
 
3655
3672
  ---
3656
3673
  **Do you want to proceed with this plan?** (yes/no)
3674
+ `
3675
+ });
3676
+ endTextBlock();
3677
+ } else if (isWebSearchTool(block.name) && isWebSearchHandledByCli(self.config.webSearch)) {
3678
+ toolCallsById.delete(block.id);
3679
+ const query = typeof parsedInput?.query === "string" ? parsedInput.query : JSON.stringify(parsedInput);
3680
+ const searchId = startTextBlock();
3681
+ controller.enqueue({
3682
+ type: "text-delta",
3683
+ id: searchId,
3684
+ delta: `
3685
+ > **Web search:** ${query}
3657
3686
  `
3658
3687
  });
3659
3688
  endTextBlock();
@@ -4128,7 +4157,7 @@ function defineModel(opts) {
4128
4157
  id: opts.id,
4129
4158
  providerID: PROVIDER_ID,
4130
4159
  api: { id: opts.id, url: "", npm: NPM },
4131
- name: opts.name,
4160
+ name: `${opts.name} (${opts.multiplier}\xD7)`,
4132
4161
  family: opts.family,
4133
4162
  capabilities: { ...baseCapabilities, reasoning: opts.reasoning },
4134
4163
  cost: {
@@ -4146,7 +4175,8 @@ function defineModel(opts) {
4146
4175
  }
4147
4176
  var haikuCost = { input: 1e-6, output: 5e-6, cacheRead: 1e-7, cacheWrite: 125e-8 };
4148
4177
  var sonnetCost = { input: 3e-6, output: 15e-6, cacheRead: 3e-7, cacheWrite: 375e-8 };
4149
- var opusCost = { input: 15e-6, output: 75e-6, cacheRead: 15e-7, cacheWrite: 1875e-8 };
4178
+ var opusCost = { input: 5e-6, output: 25e-6, cacheRead: 5e-7, cacheWrite: 625e-8 };
4179
+ var fableCost = { input: 1e-5, output: 5e-5, cacheRead: 1e-6, cacheWrite: 125e-7 };
4150
4180
  function toConfigModel(model) {
4151
4181
  const inputMods = [];
4152
4182
  const outputMods = [];
@@ -4188,6 +4218,7 @@ var defaultModels = {
4188
4218
  context: 2e5,
4189
4219
  output: 8192,
4190
4220
  cost: haikuCost,
4221
+ multiplier: 1,
4191
4222
  releaseDate: "2024-10-22"
4192
4223
  }),
4193
4224
  "claude-sonnet-4-5": defineModel({
@@ -4198,6 +4229,7 @@ var defaultModels = {
4198
4229
  context: 1e6,
4199
4230
  output: 16384,
4200
4231
  cost: sonnetCost,
4232
+ multiplier: 3,
4201
4233
  releaseDate: "2025-04-14"
4202
4234
  }),
4203
4235
  "claude-sonnet-4-6": defineModel({
@@ -4208,6 +4240,7 @@ var defaultModels = {
4208
4240
  context: 1e6,
4209
4241
  output: 16384,
4210
4242
  cost: sonnetCost,
4243
+ multiplier: 3,
4211
4244
  releaseDate: "2025-06-19"
4212
4245
  }),
4213
4246
  "claude-opus-4-5": defineModel({
@@ -4218,6 +4251,7 @@ var defaultModels = {
4218
4251
  context: 1e6,
4219
4252
  output: 16384,
4220
4253
  cost: opusCost,
4254
+ multiplier: 5,
4221
4255
  releaseDate: "2025-04-14"
4222
4256
  }),
4223
4257
  "claude-opus-4-6": defineModel({
@@ -4228,6 +4262,7 @@ var defaultModels = {
4228
4262
  context: 1e6,
4229
4263
  output: 16384,
4230
4264
  cost: opusCost,
4265
+ multiplier: 5,
4231
4266
  releaseDate: "2025-06-19"
4232
4267
  }),
4233
4268
  "claude-opus-4-7": defineModel({
@@ -4238,6 +4273,7 @@ var defaultModels = {
4238
4273
  context: 1e6,
4239
4274
  output: 16384,
4240
4275
  cost: opusCost,
4276
+ multiplier: 5,
4241
4277
  releaseDate: "2025-07-16"
4242
4278
  }),
4243
4279
  "claude-opus-4-8": defineModel({
@@ -4248,7 +4284,34 @@ var defaultModels = {
4248
4284
  context: 1e6,
4249
4285
  output: 16384,
4250
4286
  cost: opusCost,
4287
+ multiplier: 5,
4251
4288
  releaseDate: "2026-05-28"
4289
+ }),
4290
+ "claude-fable-5": defineModel({
4291
+ id: "claude-fable-5",
4292
+ name: "Claude Fable 5",
4293
+ family: "fable",
4294
+ reasoning: true,
4295
+ context: 1e6,
4296
+ output: 16384,
4297
+ cost: fableCost,
4298
+ multiplier: 10,
4299
+ releaseDate: "2026-06-09"
4300
+ }),
4301
+ // Mythos 5 shares Fable 5's capabilities and pricing without the safety
4302
+ // classifiers; limited availability via Project Glasswing. `claude --model
4303
+ // claude-mythos-5` simply errors for accounts without access, so it's safe to
4304
+ // register unconditionally.
4305
+ "claude-mythos-5": defineModel({
4306
+ id: "claude-mythos-5",
4307
+ name: "Claude Mythos 5",
4308
+ family: "mythos",
4309
+ reasoning: true,
4310
+ context: 1e6,
4311
+ output: 16384,
4312
+ cost: fableCost,
4313
+ multiplier: 10,
4314
+ releaseDate: "2026-06-09"
4252
4315
  })
4253
4316
  };
4254
4317