@khalilgharbaoui/opencode-claude-code-plugin 0.19.0 → 0.21.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 +92 -22
- package/dist/index.d.ts +76 -14
- package/dist/index.js +389 -84
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/skills/claude-code-plugin/SKILL.md +66 -18
package/README.md
CHANGED
|
@@ -288,7 +288,7 @@ model: claude-code-work/claude-opus-5@work
|
|
|
288
288
|
| `defaultSubagentModel` | string | – | Model that plugin-discovered `mode: subagent` agents run on when their own definition pins nothing. The caller's account is kept; only the model name changes. An agent's own `forceModel` wins over it, and an unknown id is refused rather than spawned. Unset means no implicit override at all. See [Subagents: your account, their model](#subagents-your-account-their-model). |
|
|
289
289
|
| `proxyTools` | string[] | `["Bash", "Edit", "Write", "WebFetch", "Task"]` | Claude built-in tools to route through opencode's executor + permission UI. Opt-in extras: `"Question"`, `"Compress"`. See [Selective tool proxy](#selective-tool-proxy). |
|
|
290
290
|
| `extraDisallowedTools` | string[] | – | Extra Claude built-ins to switch off with `--disallowedTools`, on top of what `proxyTools` implies. Claude's names, e.g. `["NotebookEdit"]`. See [Closing a tool with no proxy](#closing-a-tool-with-no-proxy). |
|
|
291
|
-
| `proxyToolTimeoutMs` | `Record<string, number>` | – |
|
|
291
|
+
| `proxyToolTimeoutMs` | `Record<string, number>` | – | Optional wall-clock backstop per proxy tool, in ms, keyed by proxy tool name (`bash`, `task`, …). A call normally ends on an event the plugin listens for (result, abort, next message, process exit, chat deletion), not on a timer; see [How a proxied call ends](#how-a-proxied-call-ends). Defaults: 10 min flat, `task` / `task_batch` → none, `question` → 30 min. `0` disables a tool's deadline; negative or non-numeric values are ignored. For `bash`, the call's own `input.timeout` is honoured on top (`max(resolved, input.timeout)`). See [Per-tool proxy timeouts](#per-tool-proxy-timeouts). |
|
|
292
292
|
| `planModeQuestion` | boolean | `false` | Route `ExitPlanMode` approval through opencode's native `question` tool instead of a text "(yes/no)" prompt. Opt-in, and currently unreachable on the default headless transport, which is not offered an `ExitPlanMode` tool at all. See [Plan mode](#plan-mode). |
|
|
293
293
|
| `controlRequestBehavior` | `allow` \| `deny` | `allow` | Default response when `skipPermissions: false` and Claude sends a `can_use_tool` control request. |
|
|
294
294
|
| `controlRequestToolBehaviors` | `Record<string, "allow" \| "deny">` | – | Per-tool override for `can_use_tool`. Example: `{ "Bash": "deny", "Read": "allow" }`. |
|
|
@@ -297,14 +297,16 @@ model: claude-code-work/claude-opus-5@work
|
|
|
297
297
|
| `mcpConfig` | string \| string[] | – | Extra `--mcp-config` paths/JSON passed alongside the bridged config. |
|
|
298
298
|
| `strictMcpConfig` | boolean | `false` | Pass `--strict-mcp-config` so Claude loads **only** the configured servers and ignores `~/.claude/settings.json`. |
|
|
299
299
|
| `hotReloadMcp` | boolean | `true` | With MCP bridging on, compare the merged MCP config and runtime status at the start of each turn and respawn the `claude` process when they drifted, so a server you just enabled or disabled becomes visible without restarting opencode or opening a new chat. Eviction waits for pending proxy calls, never happening mid tool-call, and the session id is preserved for `--resume`. Set `false` to keep a cached subprocess until the chat is reset. It does not reload other provider options and does not watch the contents of files named in `mcpConfig`. |
|
|
300
|
-
| `proxyOpencodeMcpTools` | boolean | `true` |
|
|
300
|
+
| `proxyOpencodeMcpTools` | boolean | `true` | **Currently has no effect on opencode 1.18.31: its discovery step finds nothing to route.** Measured on 2026-09-19 with five MCP servers connected, opencode's tool registry returned only built-in and plugin-declared tools, so the server-name match this option depends on matches nothing. Your MCP servers still work, through the direct `--mcp-config` bridge; what is lost is only the routing of those calls through opencode's permissions and rendering. Left on by default because it is harmless and will resume working if the registry regains them. To forward a specific non-MCP opencode tool meanwhile, use [`proxyOpencodeTools`](#options-reference). Original intent: route the MCP tools discovered from opencode through the in-process `opencode_proxy` server instead of bridging them straight into Claude's `--mcp-config`. With both layers pointed at the same server, direct bridging executes every call twice, once in Claude's own MCP child process and once in opencode; proxying keeps opencode as the single execution site while preserving its permission prompts and tool rows. Falls back to direct bridging when discovery is unavailable, so do not treat it as an exactly-once guarantee for write-capable tools. |
|
|
301
|
+
| `proxyOpencodeTools` | string[] | `[]` | Forward named opencode tools through the proxy by their registry id, for tools another opencode plugin declares directly and that therefore belong to no MCP server (opencode-dcp's `compress`). Explicit allowlist; a forwarded tool runs inside opencode with the calling agent's permissions. A name already held by a proxy def is dropped with a warning rather than taking it over. See [Forwarding opencode's own tools](#forwarding-opencode-s-own-tools). |
|
|
302
|
+
| `stripContextReminders` | boolean | `false` | Remove opencode-dcp's `<dcp-system-reminder>` blocks from message text when no `compress` tool is proxied, so an order the model cannot follow stops being re-sent with every message that carries it. Inert as soon as `compress` is reachable. See [Trimming unsatisfiable context reminders](#trimming-unsatisfiable-context-reminders). |
|
|
301
303
|
| `webSearch` | `"claude"` \| `"disabled"` \| `<tool>` | `"claude"` | Routing for Claude's built-in `WebSearch`. See [WebSearch routing](#websearch-routing). |
|
|
302
304
|
| `multiStepContinuation` | boolean | `true` | Append a system-prompt hint nudging Claude to chain tool calls within one turn instead of pausing between subtasks. Each opencode turn boundary requires the user to manually press "continue", so for multi-step tasks this reduces friction. Set `false` to disable. |
|
|
303
305
|
| `autoContinueIncompleteTurns` | boolean \| `"smart"` | `"smart"` | Smartly continue incomplete Claude CLI results inside the same opencode turn. Reduces manual "continue" presses when Claude ends after reasoning/tool activity without a useful final answer. Set `false` to disable. |
|
|
304
306
|
| `compactionModel` | string | `"claude-haiku-4-5"` | Model used when opencode invokes `/compact`. Override per-process via the `CLAUDE_CODE_COMPACTION_MODEL` env var (env wins over config). See [Compaction](#compaction). |
|
|
305
307
|
| `ignoreAnthropicApiKey` | boolean | `false` | Strip `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` from every spawned `claude` process so it authenticates with your logged-in subscription instead of pay-as-you-go API billing. The plugin warns once at startup whenever an API key is detected, regardless of this setting. See [Billing](#billing). |
|
|
306
|
-
| `idleProcessTimeoutMs` | number | – | Kill a retained headless Claude worker after this many idle milliseconds following a completed turn. The
|
|
307
|
-
| `bridgeOpencodeSkills` | boolean | `false` | Expose your opencode skills to Claude's native `Skill` tool. See [Skill bridge](#skill-bridge). Written by [@broskees](https://github.com/broskees). |
|
|
308
|
+
| `idleProcessTimeoutMs` | number | – | Kill a retained headless Claude worker after this many idle milliseconds following a completed turn. The timer starts when a turn finishes, a new turn cancels it, a worker that is mid-turn when it fires is left alone and re-timed, and the session id is preserved for `--resume`. Values above Node's maximum timer delay (`2147483647`) are ignored. Omit or set `0` to retain workers until LRU eviction (16 processes). Interactive transport is excluded. Contributed by [@bernardofortes](https://github.com/bernardofortes). |
|
|
309
|
+
| `bridgeOpencodeSkills` | boolean | `false` | Expose your opencode skills to Claude's native `Skill` tool. Off by default because every bridged skill is also in the system prompt opencode forwards, so a large set is paid for twice per turn; the bundled configuration skill is staged either way. See [Skill bridge](#skill-bridge). Written by [@broskees](https://github.com/broskees). |
|
|
308
310
|
| `logging` | object | all defaults | The plugin's own logger, four independent fields: `file` (boolean, default `false`), `dir` (string, default `~/.local/share/opencode-claude-code/`), `mode` (`"silent"` \| `"debug"`, default `"silent"`) and `level` (`"debug"` \| `"info"` \| `"notice"` \| `"warn"` \| `"error"`, default `"info"`). Goes under `provider.claude-code.options` like every other row here. See [Logging](#logging). |
|
|
309
311
|
| `turnStats` | boolean | `false` | Append a one-line cost / duration / cache footer to each finished turn. See [Per-turn stats](#per-turn-stats). |
|
|
310
312
|
| `interactive` | boolean | `false` | **Experimental.** Drive the interactive `claude` TUI (subscription billing) instead of headless `--print`. Requires opencode running under Bun with PTY support; silently falls back to headless otherwise. The tool proxy, `permissionMode` and `/btw` are all unavailable on it, so read [What it does not support](#what-it-does-not-support) before enabling. Env: `CLAUDE_CODE_INTERACTIVE_TRANSPORT=1`. |
|
|
@@ -378,6 +380,7 @@ Or per-process: `CLAUDE_CODE_INTERACTIVE_TRANSPORT=1`.
|
|
|
378
380
|
|
|
379
381
|
- The plugin's appended prompt (Claude CLI context, AGENTS.md guidance, continuation rules). The interactive transport intentionally does not forward opencode's own system prompt, because live testing showed that payload can trigger Claude Code's third-party-app usage gate on subscription accounts.
|
|
380
382
|
- The MCP bridge: bridged servers are passed via `--mcp-config` + `--strict-mcp-config`, and every bridged server is pre-allowed as `mcp__<server>__*`.
|
|
383
|
+
- The [skill bridge](#skill-bridge): the same `--plugin-dir` staging the headless spawn uses, so the TUI's native `Skill` tool can load your opencode skills too.
|
|
381
384
|
- Model selection, session reuse, and the whole streaming/usage pipeline.
|
|
382
385
|
|
|
383
386
|
Set `interactiveSystemPrompt: false` only for diagnostics. While disabled, the interactive session will not receive the plugin's CLI context, AGENTS.md guidance, or continuation hints.
|
|
@@ -427,7 +430,7 @@ By default, the plugin proxies `Bash`, `Edit`, `Write`, `WebFetch`, and `Task`.
|
|
|
427
430
|
- **Resume:** pass the child session ID back as `task_id` to continue that subagent session. Omit it to create a fresh child.
|
|
428
431
|
- **Nested tasks:** current opencode defaults `subagent_depth` to `1`, so a first-level child cannot launch another child. Increase top-level `subagent_depth` to permit deeper nesting, and explicitly grant `permission.task` on every subagent that should delegate; opencode otherwise adds a task deny to spawned subagent sessions.
|
|
429
432
|
- **Background:** `background: true` returns after starting the child and lets opencode notify the parent when it finishes. Current opencode requires `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true` in the environment of the opencode process. Foreground is the default.
|
|
430
|
-
- **Several at once:** `mcp__opencode_proxy__task_batch` takes a `tasks` array of ordinary task inputs and runs them concurrently. It exists because Claude Code sends MCP requests one at a time: when the model emits two `task` calls in one response, the second only leaves the CLI after the first has returned (measured live, 2026-09-06), so "launch two subagents" was always serial. The plugin turns one `task_batch` call into N opencode `task` calls inside a single tool boundary, which opencode executes in parallel, then hands the model every result together, labelled in task order. Same permissions, same
|
|
433
|
+
- **Several at once:** `mcp__opencode_proxy__task_batch` takes a `tasks` array of ordinary task inputs and runs them concurrently. It exists because Claude Code sends MCP requests one at a time: when the model emits two `task` calls in one response, the second only leaves the CLI after the first has returned (measured live, 2026-09-06), so "launch two subagents" was always serial. The plugin turns one `task_batch` call into N opencode `task` calls inside a single tool boundary, which opencode executes in parallel, then hands the model every result together, labelled in task order. Same permissions, same no-deadline default, same `subagent_type` list. Enabled whenever `Task` is proxied. Designed and first implemented by [@broskees](https://github.com/broskees) on his fork.
|
|
431
434
|
|
|
432
435
|
**Steering models to it.** Headless Claude Code CLIs expose no `Agent`/`Task`
|
|
433
436
|
dispatch tool of their own (verified on 2.1.211), while they *do* expose
|
|
@@ -489,7 +492,7 @@ It is the one proxy tool opencode never sees. The call is answered inside the pl
|
|
|
489
492
|
|
|
490
493
|
Without it, the appended system prompt tells the model that `compress` is unavailable and to ignore instructions that ask for it, which is the right answer when nothing implements it.
|
|
491
494
|
|
|
492
|
-
The
|
|
495
|
+
The round trip is verified live (Claude Code 2.1.263, opencode 1.18.31, haiku): the model called `mcp__opencode_proxy__compress` with a build identifier in its summary, the plugin logged `compress stored summary; session resets next turn`, the next turn logged `compress reset: dropped claude process and session id` and spawned a second `claude`, and that fresh process answered with the identifier it could only have read from the summary in its system prompt.
|
|
493
496
|
|
|
494
497
|
Only those seven values are actually proxied; anything else you put in `proxyTools` is ignored. Proxying `Edit` also disables `MultiEdit` — opencode has no batched-edit equivalent, so Claude is forced to fan out into single `Edit` calls that each flow through the permission UI. The `"Question"` proxy is version-gated on opencode's built-in `question` tool: on builds that lack the registry entry the def is silently dropped (a forwarded call would otherwise render as `⚙ invalid`), so add it only on opencode versions that ship the `question` tool.
|
|
495
498
|
|
|
@@ -499,6 +502,45 @@ Without `"Task"` in `proxyTools`, Claude's built-in `Agent` tool stays enabled a
|
|
|
499
502
|
"options": { "proxyTools": [] }
|
|
500
503
|
```
|
|
501
504
|
|
|
505
|
+
### Forwarding opencode's own tools
|
|
506
|
+
|
|
507
|
+
`proxyTools` names the tools this plugin ships defs for, and MCP-backed opencode tools are routed automatically ([`proxyOpencodeMcpTools`](#options-reference)). Neither covers a tool that **another opencode plugin declares directly**: it belongs to no MCP server, so the automatic match (`<server>` or `<server>_<tool>`) skips it and the model is never offered it. opencode-dcp's `compress` is the case that matters in practice, because DCP then injects "MAX CONTEXT LIMIT REACHED ... You MUST use the `compress` tool now" reminders that the model has no way to act on.
|
|
508
|
+
|
|
509
|
+
`proxyOpencodeTools` is the explicit allowlist. Empty by default:
|
|
510
|
+
|
|
511
|
+
```json
|
|
512
|
+
"options": {
|
|
513
|
+
"proxyTools": ["Bash", "Edit", "Write", "WebFetch", "Task"],
|
|
514
|
+
"proxyOpencodeTools": ["compress"]
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
Names are opencode's tool ids as `client.tool.list()` reports them, matched case-insensitively. An unknown name is skipped with a warning rather than failing the spawn. Forwarded tools use the same broker as every other proxy tool, so [how a proxied call ends](#how-a-proxied-call-ends) applies to them unchanged: abort, orphan sweep, session deletion and child exit all release them.
|
|
519
|
+
|
|
520
|
+
This is deliberately not automatic. A forwarded tool executes inside opencode with the calling agent's permissions, so which ones cross over is your decision, not the plugin's.
|
|
521
|
+
|
|
522
|
+
**The `compress` name collision.** Two different tools want it: DCP's, which rewrites opencode's transcript, and [this plugin's](#context-compression), which resets the Claude Code session. They compress different windows, and after a DCP compress the live `claude` process still holds its full context until something restarts it. If you enable both, the plugin's own tool keeps the name and the forwarded one is dropped with a warning in the log:
|
|
523
|
+
|
|
524
|
+
```
|
|
525
|
+
WARN: proxyOpencodeTools entry dropped: a proxy tool already holds that name, and it keeps it {"collided":["compress"]}
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
Pick one. The appended system prompt describes whichever is actually reachable, so the model is told the right semantics either way.
|
|
529
|
+
|
|
530
|
+
Verified live on Claude Code 2.1.263 and opencode 1.18.31 with DCP loaded: the plugin logged `forwarding opencode tools through the proxy {"tools":["compress"]}`, started the proxy with `tools: ["bash","compress"]`, received `proxy-mcp tool call received {"toolName":"compress"}`, queued it through the normal broker, and DCP really ran, returning `Compressed 3 messages into [Compressed conversation section]`. One wrinkle worth knowing: DCP's compress rewrites opencode's message history mid-turn, which makes opencode abort the provider stream at that tool boundary. The pending call is released normally and the result still reaches the model on the next step as text, so the turn completes, but you will see one `abort between proxy tool boundaries` line in the log each time.
|
|
531
|
+
|
|
532
|
+
### Trimming unsatisfiable context reminders
|
|
533
|
+
|
|
534
|
+
DCP anchors its nudges into message text as `<dcp-system-reminder>` blocks, so each one is re-sent with every message that carries it. If no `compress` tool is reachable they are an order the model cannot follow, and the plugin already tells it to ignore them. `stripContextReminders: true` stops paying for them too:
|
|
535
|
+
|
|
536
|
+
```json
|
|
537
|
+
"options": { "stripContextReminders": true }
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
Off by default. It removes those blocks from user and assistant text before the transcript reaches the CLI, including the fresh-session rebuild, where every anchored reminder would otherwise replay at once. It leaves opencode's own `<system-reminder>` blocks alone: those are opencode's instructions to the model, not an unsatisfiable order.
|
|
541
|
+
|
|
542
|
+
It switches itself off whenever `compress` is named in `proxyTools` or `proxyOpencodeTools`, since the reminder is then something the model can act on. The check is on configuration, so a name that is configured but missing from opencode's registry still counts as reachable and nothing is stripped, which errs toward keeping the reminder.
|
|
543
|
+
|
|
502
544
|
### Subagent todos
|
|
503
545
|
|
|
504
546
|
When Claude works through a multi-step task it emits `TaskCreate` / `TaskUpdate` calls. The plugin translates those into opencode's full-list `todowrite` so the todo panel populates. Inside a **subagent** that translation is blocked unless you say otherwise: opencode's task tool injects `todowrite: false` into the tools dict for any subagent without an explicit rule, so the plugin's synthetic emissions surface as `⚙ invalid todowrite` rows instead of todos. The built-in `general` subagent denies it by default.
|
|
@@ -552,18 +594,37 @@ sqlite3 ~/.local/share/opencode/opencode.db \
|
|
|
552
594
|
- A small per-call latency hop through `127.0.0.1:<random>/mcp`.
|
|
553
595
|
- Batched-edit ergonomics: with `Edit` proxied, Claude can no longer use `MultiEdit`, so a refactor that would have been one tool call becomes N single `Edit` calls.
|
|
554
596
|
|
|
597
|
+
### How a proxied call ends
|
|
598
|
+
|
|
599
|
+
A proxied call ends when something happens to it, not when a clock runs out. The plugin holds the CLI's request open and listens to the process, the stream and the protocol for the events that actually decide the call's fate; each one releases the call on the spot, and tells the CLI where there is still a CLI to tell:
|
|
600
|
+
|
|
601
|
+
| What happens | What the plugin does |
|
|
602
|
+
|---|---|
|
|
603
|
+
| opencode returns the tool's result | resolves the call; the CLI gets the result and carries on |
|
|
604
|
+
| you abort the turn (Esc / Ctrl+C) | sends the CLI an `interrupt`, which answers with its own result, and rejects every call the turn had pending, whether the abort lands before content, mid-turn, or while opencode is running the tool between two stream boundaries |
|
|
605
|
+
| you send the next message in that chat | rejects every call the previous turn left pending as orphaned, so the CLI gets an error result and the new turn starts clean |
|
|
606
|
+
| the `claude` process closes its output or exits, mid-turn or between turns | rejects its pending calls; a mid-turn death also ends the turn as a visible error |
|
|
607
|
+
| you delete the chat in opencode, or opencode exits | kills the worker and rejects its pending calls |
|
|
608
|
+
| the CLI hangs up on its own request | keeps the call so a late result can still be delivered as a plain-text continuation (see below) |
|
|
609
|
+
|
|
610
|
+
Because every ending is observed rather than inferred from elapsed time, a `task` can run until it is finished: **`task` and `task_batch` have no deadline by default**. Earlier flat ceilings fired mid-subagent, Claude believed its dispatch had failed, and the eventual result was dropped because the parent turn had already ended on the timeout error; a 60-minute one did the same to anything longer. What the default gives up is only that nothing fires on the clock alone, so a chat parked in a `task` holds its `claude` worker until one of the events above happens. That is the operator's decision to make, so no timer makes it for them.
|
|
611
|
+
|
|
612
|
+
So that a call with no deadline is never silent, the plugin says it is still waiting. Five minutes in, and every five minutes after, a call without a deadline logs a warning naming the tool, the call id, how long it has waited, and what will end it. It never ends the call, it only reports one, which is the whole point: the thing a deadline used to provide was visibility, not correctness, and visibility is what is kept. Calls that do have a deadline are not reported this way, because their deadline already does it. The line reaches your terminal (warnings always go to stderr), so a subagent that has genuinely wedged shows up on its own instead of waiting to be noticed. `/claude-code-doctor` lists the same calls on demand.
|
|
613
|
+
|
|
614
|
+
The same events are also what let a legitimately long call complete, which is the second half of the story: the CLI's own HTTP client used to give up on a silent reply at about five minutes whatever the tool deadline said. Every held call therefore keeps its connection visibly alive. A client that advertises SSE gets immediate headers and a keepalive comment every 15 seconds (since 0.15.0); a client that only accepts JSON gets its headers immediately as well, as a chunked body carrying keepalive whitespace on the same cadence, which is still one valid JSON-RPC response when the result lands, on success and on error. Keepalives are about the connection, not the tool: they never extend or replace a deadline. Claude's MCP client timeout for the proxy server, written into the generated `--mcp-config`, is set to the largest effective deadline, and to the largest value the CLI accepts (Node's timer maximum, about 24.8 days) while any tool has no deadline, because the CLI rejects a `timeout` of `0` outright.
|
|
615
|
+
|
|
555
616
|
### Per-tool proxy timeouts
|
|
556
617
|
|
|
557
|
-
|
|
618
|
+
Deadlines still exist, as an explicit backstop rather than the mechanism that decides when a call is over. If a tool with one has not been resolved within that many milliseconds, the call is rejected and Claude receives a timeout error. Resolved per tool, most-specific layer winning:
|
|
558
619
|
|
|
559
620
|
1. flat default — 10 min (matches Claude CLI's own Bash ceiling)
|
|
560
|
-
2. per-tool default
|
|
561
|
-
3. your `proxyToolTimeoutMs` override (case-insensitive key)
|
|
562
|
-
4. for `bash` only, the call's own `input.timeout
|
|
621
|
+
2. per-tool default: **`task` / `task_batch`: none**, **`question`: 30 min**, everything else: 10 min
|
|
622
|
+
3. your `proxyToolTimeoutMs` override (case-insensitive key; a positive value replaces the default, `0` removes the deadline, anything else is ignored)
|
|
623
|
+
4. for `bash` only, the call's own `input.timeout`: the proxy never undercuts a build the caller explicitly asked to run long (`max(resolved, input.timeout)`), and a positive `input.timeout` restores a deadline that `bash: 0` removed
|
|
563
624
|
|
|
564
|
-
|
|
625
|
+
`question` keeps 30 minutes because it blocks on a human reading a form, and a form nobody answers is not an event. A positive `task` override restores a wall-clock backstop for operators who want one; if it fires, the error tells Claude not to "schedule a wake-up": that is a Claude Code affordance which cannot fire in this headless/proxy context, so deferring silently loses the work.
|
|
565
626
|
|
|
566
|
-
|
|
627
|
+
Two watchdogs are a different thing again and are unchanged: the start watchdog (90 s of complete silence after a turn is written, respawn then error, see `CLAUDE_CODE_START_WATCHDOG_MS`) and the wire-inactivity watchdog (60 s of silence after content). Those exist because a process that is alive but wedged emits no event to listen to, and a proxy call is never what they are waiting on: a CLI parked inside a proxied tool is producing nothing on purpose, and both watchdogs know that.
|
|
567
628
|
|
|
568
629
|
If Claude nevertheless abandons the HTTP call, the plugin preserves narration emitted while opencode was running the tool, renders it on return, and delivers the late completion as a plain-text continuation naming the original call. It tells Claude not to run the tool again. A silent post-tool continuation gets one resumed-process retry, preserving the original model, account, effort, and proxy configuration; a second failure ends with an error rather than an indefinite hang. Buffered narration is capped at 500 lines and 2 MiB, with a warning if output was dropped.
|
|
569
630
|
|
|
@@ -667,7 +728,7 @@ Use the claude-code-plugin skill to configure a work account and idle worker cle
|
|
|
667
728
|
|
|
668
729
|
It covers accounts, models and agent effort, proxy tools, permissions, MCP/skill bridging, timeouts, logging, upgrades and troubleshooting. It directs the agent to preserve JSONC comments, change only requested settings, validate the result, protect credentials and ask before paid probes or broader permissions.
|
|
669
730
|
|
|
670
|
-
The plugin registers the bundled directory with opencode's `skills.paths`, making it available to other providers too on supporting opencode versions. For
|
|
731
|
+
The plugin registers the bundled directory with opencode's `skills.paths`, making it available to other providers too on supporting opencode versions. For Claude turns it also loads through Claude's native Skill tool as `opencode-skills:claude-code-plugin`, even when `bridgeOpencodeSkills` is `false`. This requires CLI `--plugin-dir` support and applies to the headless, interactive and direct `doGenerate` spawns; compaction never loads the native bridge.
|
|
671
732
|
|
|
672
733
|
No separate skill installation or copying is needed. It ships with each package version, so upgrading updates the reference. Fully restart opencode to load it. `test-configure-skill.ts` checks coverage of provider/logging options, model ids, proxy tools and environment variables; maintainers must update behavior and default guidance in the same change as the implementation.
|
|
673
734
|
|
|
@@ -675,7 +736,7 @@ No separate skill installation or copying is needed. It ships with each package
|
|
|
675
736
|
|
|
676
737
|
opencode and Claude Code use the same on-disk skill format, a `<name>/SKILL.md` whose frontmatter carries `name` and `description`, but they read from different directories. opencode looks in `.opencode/skills/` and `~/.config/opencode/skills/`; the Claude CLI looks in `~/.claude/skills/` and its own plugins. So opencode advertises your skills in the system prompt it forwards, the model calls `Skill("browser-automation")`, and Claude answers `Unknown skill`.
|
|
677
738
|
|
|
678
|
-
|
|
739
|
+
By default the plugin discovers your opencode skills, stages a throwaway Claude Code plugin directory that links them, and passes it as `claude --plugin-dir`. They register natively, prefixed with the plugin name:
|
|
679
740
|
|
|
680
741
|
```text
|
|
681
742
|
opencode-skills:browser-automation
|
|
@@ -686,7 +747,7 @@ Claude can invoke them with the Skill tool or as `/opencode-skills:<name>`. `--p
|
|
|
686
747
|
|
|
687
748
|
Discovery order, first match wins: `.opencode/skills/` walking up from the working directory, then `~/.opencode/skills/`, then `$OPENCODE_CONFIG_DIR/skills/`, then `~/.config/opencode/skills/`. A project skill shadows a global one of the same name. If the skill set is unchanged the staged directory is reused between spawns.
|
|
688
749
|
|
|
689
|
-
|
|
750
|
+
The bridge is **off by default**: every bridged skill's name and description is also in the system prompt opencode already forwards, so a large skill set is paid for twice on every turn. Set `bridgeOpencodeSkills: true` when the model tries `Skill("<name>")` for a skill opencode advertises and gets `Unknown skill`; the bundled configuration skill is staged either way. When on, the bridge applies to the headless, interactive and direct `doGenerate` spawns alike, never to compaction, and it is skipped on a Claude CLI without `--plugin-dir` (the plugin probes `claude --help` and logs a notice).
|
|
690
751
|
|
|
691
752
|
This bridge was written by [@broskees](https://github.com/broskees) (Joseph Roberts) on his fork and absorbed here with credit; see [Credits](#credits).
|
|
692
753
|
|
|
@@ -754,9 +815,11 @@ Each chat keeps a long-lived `claude` subprocess so the model retains its native
|
|
|
754
815
|
- **Same chat, multiple turns** → process reused, full Claude context retained.
|
|
755
816
|
- **New chat** → fresh process under the new session key.
|
|
756
817
|
- **Resumed chat after restart** → in-memory state is gone; a new process spawns and the conversation history is summarized and prepended.
|
|
757
|
-
- **Abort (Esc / Ctrl+C)** → the plugin sends the Claude CLI a stream-json `interrupt` control request, so the CLI actually stops generating and running tools instead of finishing the abandoned turn on your bill. The process stays alive for the next message in that chat. If a turn is somehow still running when the next one starts, it is interrupted first (5 s cap). Contributed by [@broskees](https://github.com/broskees).
|
|
758
|
-
- **Idle timeout** → when `idleProcessTimeoutMs` is
|
|
818
|
+
- **Abort (Esc / Ctrl+C)** → the plugin sends the Claude CLI a stream-json `interrupt` control request, so the CLI actually stops generating and running tools instead of finishing the abandoned turn on your bill. The process stays alive for the next message in that chat, and any proxied call the aborted turn left behind is released when that message arrives (see [How a proxied call ends](#how-a-proxied-call-ends)). If a turn is somehow still running when the next one starts, it is interrupted first (5 s cap). Contributed by [@broskees](https://github.com/broskees).
|
|
819
|
+
- **Idle timeout** → when `idleProcessTimeoutMs` is set, a completed headless turn arms an eviction timer (unset or `0` keeps workers until LRU eviction). Reuse cancels it, a worker found mid-turn when it fires is left alone and re-timed, and eviction preserves the session id, so the next message resumes the same conversation with `--resume`. An idle `claude --print` holds around 250 MB, which is the reason to set it if you keep many chats open.
|
|
759
820
|
- **Cap**: 16 active processes, LRU eviction. A process that is mid-turn is never the victim: eviction takes the oldest **idle** one, and when every process is busy it evicts nothing and warns instead, so a running answer is never truncated to make room.
|
|
821
|
+
- **Deleted chat** → deleting a session in opencode kills its `claude` workers at once and forgets their session ids and per-chat state; there is nothing left to resume. Other chats, and the shared fallback bucket used when no session id is known, are untouched.
|
|
822
|
+
- **opencode exits** → every retained worker is killed on the way out, so a hard shutdown does not leave `claude` processes reparented to init.
|
|
760
823
|
- **Crash** → if the CLI dies mid-turn (no terminal `result` line), the turn ends with a visible error naming the exit code or signal and the last stderr the CLI wrote, not a silent `stop` that reads as a short but finished answer. An abort you asked for is not reported this way.
|
|
761
824
|
|
|
762
825
|
---
|
|
@@ -1033,10 +1096,17 @@ Partial support since v0.5.1. DCP runs in a useful degraded mode: its automatic
|
|
|
1033
1096
|
| `experimental.chat.system.transform` (context-limit nudges, iteration reminders) | ✅ Works in headless | Headless spawns forward system-role content via `--append-system-prompt-file`. Interactive mode intentionally omits opencode's forwarded system prompt and keeps only this plugin's CLI/AGENTS/continuation prompt. |
|
|
1034
1097
|
| `/dcp compress`, `/dcp sweep`, `/dcp manual`, `/dcp context`, `/dcp stats` slash commands | ✅ Works | Handled by opencode's `command.execute.before` hook, not the model. |
|
|
1035
1098
|
| Automatic `deduplication` + `purgeErrors` strategies | ✅ Works | Message-transform only, no model tool calls. |
|
|
1036
|
-
| DCP's own autonomous `compress` / `distill` / `prune` tool calls |
|
|
1099
|
+
| DCP's own autonomous `compress` / `distill` / `prune` tool calls | ⚠️ Opt-in | DCP registers those as opencode-native tools rather than through an MCP server, so the automatic MCP routing never saw them. Name one in [`proxyOpencodeTools`](#forwarding-opencode-s-own-tools) and it is forwarded: `proxyOpencodeTools: ["compress"]` makes `mcp__opencode_proxy__compress` run DCP's real tool. |
|
|
1037
1100
|
| Model-driven compression through this plugin's `compress` proxy | ⚠️ Opt-in | Add `"Compress"` to `proxyTools` and the plugin exposes `mcp__opencode_proxy__compress`, which gives the model a working way to compress its own context. It is not DCP's tool and does not use DCP's strategies. See [Context compression](#context-compression). |
|
|
1101
|
+
| DCP's `<dcp-system-reminder>` context-limit nudges when no compress tool is reachable | ⚠️ Opt-in strip | Those reminders are anchored into messages, so each one is re-sent with every message that carries it. If you run without either compress route, `stripContextReminders: true` removes them. It turns itself off as soon as a `compress` tool is proxied. |
|
|
1102
|
+
|
|
1103
|
+
So autonomous compression is available, and DCP's own implementation is now one of the options. Three routes, all opt-in:
|
|
1104
|
+
|
|
1105
|
+
- `proxyOpencodeTools: ["compress"]` forwards **DCP's** tool, which compresses opencode's transcript using DCP's strategies.
|
|
1106
|
+
- `proxyTools: [..., "Compress"]` exposes **this plugin's** tool, which resets the Claude Code session and carries a summary into the fresh one.
|
|
1107
|
+
- Neither, and trigger DCP by hand with `/dcp compress`.
|
|
1038
1108
|
|
|
1039
|
-
|
|
1109
|
+
The two compress different windows, so pick deliberately rather than enabling both; [Forwarding opencode's own tools](#forwarding-opencode-s-own-tools) explains what happens if you do. With neither enabled, the plugin's appended system prompt tells Claude that no such tool exists and to ignore instructions asking for it, which is the correct answer in that case.
|
|
1040
1110
|
|
|
1041
1111
|
---
|
|
1042
1112
|
|
|
@@ -1045,7 +1115,7 @@ So autonomous compression is available, just not DCP's implementation of it. Two
|
|
|
1045
1115
|
- Tool inputs stream as they are constructed (Anthropic's `input_json_delta` is forwarded as `tool-input-delta`), but only for tool calls opencode actually sees. Calls the plugin deliberately does not forward, meaning proxy tools, CLI-internal `WebSearch`, `AskUserQuestion`, `ExitPlanMode`, the todo-ledger `Task*` family and Claude's other internal tools, have their deltas suppressed, because a delta for a tool opencode never saw start renders as a permanently pending `⚙ unknown` row.
|
|
1046
1116
|
- Raw chain-of-thought is not available. Claude 4 family models ship summarized thinking only. See [Extended thinking](#extended-thinking) for the full picture.
|
|
1047
1117
|
- Recommended Claude Code CLI: **2.1.142+**. Older CLIs work for everything else but skip the `--thinking-display` flag, so Claude Opus 4.7 turns may render empty Thinking rows. If something breaks after a Claude Code update, the CLI version is the first thing to check.
|
|
1048
|
-
- **Foreground Task calls have
|
|
1118
|
+
- **Foreground Task calls have no proxy deadline by default.** The plugin listens for the events that end a call instead of timing it (see [How a proxied call ends](#how-a-proxied-call-ends)), so a subagent runs to completion and a chat parked in one holds its `claude` worker until you abort, send another message, delete the chat, or the process goes away. Such a call warns that it is still waiting after five minutes and every five minutes after, so it is never silent. Add a wall-clock backstop via [`proxyToolTimeoutMs`](#per-tool-proxy-timeouts) if you want one. For independent work that should not block the turn at all, use `background: true` after enabling opencode's experimental background-subagent flag.
|
|
1049
1119
|
- **Subagent todos require explicit permission.** See [Subagent todos](#subagent-todos) for the rule and a working config.
|
|
1050
1120
|
|
|
1051
1121
|
---
|
|
@@ -1112,13 +1182,13 @@ This plugin absorbs work from its forks directly, cherry-picked with the origina
|
|
|
1112
1182
|
| [@galvani](https://github.com/galvani) (Jan Kozak) | Per-session working directory for `opencode serve`, so one server spawns each project's `claude` in the right place. Also found the stale `toolCallMap` re-emission three months before it was fixed here. | `9e02ce4`, `2238ed0` |
|
|
1113
1183
|
| [@HeikoAtGitHub](https://github.com/HeikoAtGitHub) | Stopped sending `AGENTS.md` to the model twice (opencode already forwards it). Independently diagnosed the 5-minute proxy wall. | `25260a4`, `42f426d` |
|
|
1114
1184
|
| [@bernardofortes](https://github.com/bernardofortes) (Bernardo Fortes) | `idleProcessTimeoutMs`, idle eviction of retained `claude` workers. | `a5f723a` |
|
|
1115
|
-
| [@broskees](https://github.com/broskees) (Joseph Roberts) | Task proxy default-on (PR #18), the abort `interrupt` so Esc really stops the CLI, the skill bridge, `task_batch` for concurrent subagents (and the measurement that the CLI serialises MCP calls),
|
|
1185
|
+
| [@broskees](https://github.com/broskees) (Joseph Roberts) | Task proxy default-on (PR #18), the abort `interrupt` so Esc really stops the CLI, the skill bridge, `task_batch` for concurrent subagents (and the measurement that the CLI serialises MCP calls), the undici 300 s diagnosis of the proxy wall, and the lifecycle release of proxied calls that made the `task` deadline unnecessary (PR #36). | PR #18, `68ed142`, PR #36 |
|
|
1116
1186
|
| [@jknlsn](https://github.com/jknlsn) (Jake Nelson) | Per-tool proxy timeouts, subagent dispatch steering, the question proxy, the start watchdog respawn. | `84f3db9`, `94980a6`, `47501d0`, `ffefc24` |
|
|
1117
1187
|
| [@CollieIsCute](https://github.com/CollieIsCute) (Collie Tsai) | The plan-mode approval bridge. | `8c5b583` |
|
|
1118
1188
|
| [@flupkede](https://github.com/flupkede) | The compress proxy tool design and the AI-SDK v4 image-part fix. | `4ac319f`, `60a6e9a` |
|
|
1119
1189
|
| [@CNQQC](https://github.com/CNQQC) | Cost units corrected to dollars per million tokens (PR #25). | PR #25 |
|
|
1120
1190
|
| [@willmcginnis](https://github.com/willmcginnis) | The proxy endpoint authentication (PR #28, GHSA-3mxm-w7gf-3c5x). | PR #28 |
|
|
1121
|
-
| [@nic-lan](https://github.com/nic-lan) | The issue #29 diagnosis of subagent output lost across the CLI resume boundary. | #29 |
|
|
1191
|
+
| [@nic-lan](https://github.com/nic-lan) | The issue #29 diagnosis of subagent output lost across the CLI resume boundary, and the fix for unattended output replaying as one text block per delta (PR #35). | #29, PR #35 |
|
|
1122
1192
|
| [@JWebCoder](https://github.com/JWebCoder) (joao moura) | Diagnosed that auto-continue never fires on current CLIs (PR #15). | PR #15 |
|
|
1123
1193
|
|
|
1124
1194
|
Commit hashes are on the contributors' forks where the work was cherry-picked; `git log --author` on this repo shows the preserved authorship.
|
package/dist/index.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ type OpenCodeConfig = {
|
|
|
87
87
|
* Bus events surface to plugins. Shape mirrors what opencode core publishes
|
|
88
88
|
* via `GlobalBus.emit("event", { directory, payload: { type, properties } })`
|
|
89
89
|
* but kept loose since opencode adds events over time and this plugin only
|
|
90
|
-
* reacts to a small subset (currently just `
|
|
90
|
+
* reacts to a small subset (currently just `session.deleted`).
|
|
91
91
|
*/
|
|
92
92
|
type OpenCodeEvent = {
|
|
93
93
|
type?: string;
|
|
@@ -181,6 +181,8 @@ interface ClaudeCodeConfig {
|
|
|
181
181
|
controlRequestToolBehaviors?: Record<string, ControlRequestBehavior>;
|
|
182
182
|
controlRequestDenyMessage?: string;
|
|
183
183
|
proxyTools?: string[];
|
|
184
|
+
proxyOpencodeTools?: string[];
|
|
185
|
+
stripContextReminders?: boolean;
|
|
184
186
|
extraDisallowedTools?: string[];
|
|
185
187
|
proxyToolTimeoutMs?: Record<string, number>;
|
|
186
188
|
/**
|
|
@@ -316,6 +318,45 @@ interface ClaudeCodeProviderSettings {
|
|
|
316
318
|
* entry, in which case the deny/markdown fallback applies.
|
|
317
319
|
*/
|
|
318
320
|
proxyTools?: string[];
|
|
321
|
+
/**
|
|
322
|
+
* opencode tools to forward through the proxy by name, on top of the
|
|
323
|
+
* built-in `proxyTools` defs. Empty by default.
|
|
324
|
+
*
|
|
325
|
+
* MCP-backed opencode tools are already routed automatically (see
|
|
326
|
+
* `proxyOpencodeMcpTools`), but that match is `<server>` or
|
|
327
|
+
* `<server>_<tool>`, so a tool another opencode plugin declares directly
|
|
328
|
+
* belongs to no server and is never offered to Claude. opencode-dcp's
|
|
329
|
+
* `compress` is the motivating case: dcp injects "MAX CONTEXT LIMIT
|
|
330
|
+
* REACHED ... You MUST use the `compress` tool now" reminders that the
|
|
331
|
+
* model could not act on, because the tool was never in its list.
|
|
332
|
+
*
|
|
333
|
+
* Names are opencode's tool ids as `client.tool.list()` reports them
|
|
334
|
+
* (matched case-insensitively): `["compress"]`. An unknown name is
|
|
335
|
+
* skipped with a warning. This is an explicit allowlist and never
|
|
336
|
+
* automatic: a forwarded tool executes inside opencode with the calling
|
|
337
|
+
* agent's permissions.
|
|
338
|
+
*
|
|
339
|
+
* A name already held by a proxy def is NOT taken over. Listing
|
|
340
|
+
* `"compress"` here while `proxyTools` also contains `"Compress"` leaves
|
|
341
|
+
* the plugin's own in-process compress in charge and drops the forwarded
|
|
342
|
+
* one with a warning, because the two do different things: the plugin's
|
|
343
|
+
* resets the Claude Code session, opencode's compresses opencode's
|
|
344
|
+
* transcript. Pick one.
|
|
345
|
+
*/
|
|
346
|
+
proxyOpencodeTools?: string[];
|
|
347
|
+
/**
|
|
348
|
+
* Remove `<dcp-system-reminder>` blocks from message text when no
|
|
349
|
+
* `compress` tool is being proxied. Off by default.
|
|
350
|
+
*
|
|
351
|
+
* opencode-dcp anchors those reminders into messages, so they are re-sent
|
|
352
|
+
* with every message that carries one. When compress is not reachable
|
|
353
|
+
* they are an instruction the model cannot follow, and the plugin already
|
|
354
|
+
* tells it to ignore them in the appended system prompt. Turning this on
|
|
355
|
+
* stops paying for them as well. It is inert whenever `compress` is
|
|
356
|
+
* proxied (via either `proxyTools` or `proxyOpencodeTools`), since the
|
|
357
|
+
* reminder is then something the model can actually act on.
|
|
358
|
+
*/
|
|
359
|
+
stripContextReminders?: boolean;
|
|
319
360
|
/**
|
|
320
361
|
* Extra Claude Code built-ins to switch off with `--disallowedTools`,
|
|
321
362
|
* on top of the ones implied by `proxyTools`.
|
|
@@ -338,13 +379,17 @@ interface ClaudeCodeProviderSettings {
|
|
|
338
379
|
* receives a timeout error.
|
|
339
380
|
*
|
|
340
381
|
* Defaults (used when a tool is absent here): `bash`/`edit`/`write`/
|
|
341
|
-
* `webfetch` → 10 min (matches Claude CLI's Bash ceiling); `task`
|
|
342
|
-
*
|
|
343
|
-
*
|
|
382
|
+
* `webfetch` → 10 min (matches Claude CLI's Bash ceiling); `task` and
|
|
383
|
+
* `task_batch` → no deadline (the call waits for the subagent; abandoned
|
|
384
|
+
* calls are released by aborts, the next user turn, and the process going
|
|
385
|
+
* away); `question` → 30 min (operator AFK). A positive value here replaces
|
|
386
|
+
* the default for that tool, `0` disables its deadline, and a negative or
|
|
387
|
+
* non-finite value is ignored.
|
|
344
388
|
*
|
|
345
389
|
* For `bash` specifically the call's own `input.timeout` is honoured on
|
|
346
390
|
* top: the effective deadline is `max(resolved, input.timeout)`, so a
|
|
347
|
-
* long build the caller explicitly asked to run is never undercut
|
|
391
|
+
* long build the caller explicitly asked to run is never undercut, and a
|
|
392
|
+
* positive `input.timeout` restores a deadline that `bash: 0` disabled.
|
|
348
393
|
*/
|
|
349
394
|
proxyToolTimeoutMs?: Record<string, number>;
|
|
350
395
|
/**
|
|
@@ -381,19 +426,24 @@ interface ClaudeCodeProviderSettings {
|
|
|
381
426
|
ignoreAnthropicApiKey?: boolean;
|
|
382
427
|
/**
|
|
383
428
|
* Kill a retained headless Claude worker after this many milliseconds of
|
|
384
|
-
* inactivity following a completed turn.
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
429
|
+
* inactivity following a completed turn. Off unless set. The timer
|
|
430
|
+
* starts when a turn completes (not at spawn), starting another turn cancels
|
|
431
|
+
* it, a worker found mid-turn when it fires is left alone and re-timed, and
|
|
432
|
+
* the Claude session id is retained for a transparent resume. Omit or set 0
|
|
433
|
+
* to keep workers until LRU eviction (16 processes). Interactive transport is
|
|
434
|
+
* excluded because it does not currently guarantee session-id resume.
|
|
388
435
|
*/
|
|
389
436
|
idleProcessTimeoutMs?: number;
|
|
390
437
|
/**
|
|
391
438
|
* Expose your opencode skills (`.opencode/skills`, `~/.config/opencode/skills`)
|
|
392
439
|
* to Claude Code's native Skill tool by staging them as a session-scoped
|
|
393
|
-
* `--plugin-dir
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
440
|
+
* `--plugin-dir`, so a `Skill("<name>")` call for a skill opencode advertises
|
|
441
|
+
* does not fail with `Unknown skill`. Off by default: every bridged skill
|
|
442
|
+
* is also listed in the system prompt opencode forwards, so a large skill
|
|
443
|
+
* set costs prompt tokens twice per turn. When on it applies to the
|
|
444
|
+
* headless, interactive and direct `doGenerate` spawns alike; compaction
|
|
445
|
+
* never loads it, and the bundled configuration skill is staged either way.
|
|
446
|
+
* No-op on CLIs without `--plugin-dir`.
|
|
397
447
|
*/
|
|
398
448
|
bridgeOpencodeSkills?: boolean;
|
|
399
449
|
/**
|
|
@@ -671,6 +721,12 @@ declare class ClaudeCodeLanguageModel implements LanguageModelV3 {
|
|
|
671
721
|
* answered": only the former is a real version-gate signal.
|
|
672
722
|
*/
|
|
673
723
|
private fetchLiveToolInfo;
|
|
724
|
+
/**
|
|
725
|
+
* Whether dcp-style context reminders should be stripped from this turn's
|
|
726
|
+
* messages. Config-only and synchronous, so it can be answered before the
|
|
727
|
+
* spawn block resolves anything: `userMsg` is built well ahead of it.
|
|
728
|
+
*/
|
|
729
|
+
private stripContextRemindersEnabled;
|
|
674
730
|
/** Share one lazy registry request within a turn without making it stale. */
|
|
675
731
|
private createLiveToolInfoLoader;
|
|
676
732
|
/**
|
|
@@ -846,9 +902,15 @@ declare function configModelsForProvider(providerModels: OpenCodeProvider["model
|
|
|
846
902
|
* diagnostics never report another provider's options.
|
|
847
903
|
*/
|
|
848
904
|
declare function claudeCodeProviders(providers: Record<string, DiagnosticsProviderEntry> | undefined): Record<string, DiagnosticsProviderEntry>;
|
|
905
|
+
/**
|
|
906
|
+
* The opencode session id a `session.deleted` bus event names, or undefined
|
|
907
|
+
* for any other event. opencode publishes `{ type, properties: { info } }`
|
|
908
|
+
* under `payload`, and the deleted session's own record is `properties.info`.
|
|
909
|
+
*/
|
|
910
|
+
declare function extractDeletedSessionId(event: OpenCodeEvent | undefined): string | undefined;
|
|
849
911
|
declare const _default: {
|
|
850
912
|
id: string;
|
|
851
913
|
server: OpenCodePlugin;
|
|
852
914
|
};
|
|
853
915
|
|
|
854
|
-
export { type AgentRecord, type ClaudeCodeConfig, ClaudeCodeLanguageModel, type ClaudeCodeProvider, type ClaudeCodeProviderSettings, type ClaudeStreamMessage, DEFAULT_PROXY_TOOL_NAMES, type OpenCodeHooks, type OpenCodeModel, type OpenCodePlugin, _resetPlanModeWarningForTests, bridgeOpencodeMcp, claudeCodeProviders, configModelsForProvider, createClaudeCode, _default as default, defaultModels, getAgentRegistry, getDefaultSubagentModel, registerDoctorCommand, registerSideQuestionCommand, resolveAgentModel, warnIfPlanModeCannotExit };
|
|
916
|
+
export { type AgentRecord, type ClaudeCodeConfig, ClaudeCodeLanguageModel, type ClaudeCodeProvider, type ClaudeCodeProviderSettings, type ClaudeStreamMessage, DEFAULT_PROXY_TOOL_NAMES, type OpenCodeHooks, type OpenCodeModel, type OpenCodePlugin, _resetPlanModeWarningForTests, bridgeOpencodeMcp, claudeCodeProviders, configModelsForProvider, createClaudeCode, _default as default, defaultModels, extractDeletedSessionId, getAgentRegistry, getDefaultSubagentModel, registerDoctorCommand, registerSideQuestionCommand, resolveAgentModel, warnIfPlanModeCannotExit };
|