@khalilgharbaoui/opencode-claude-code-plugin 0.15.3 → 0.16.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 CHANGED
@@ -249,7 +249,8 @@ model: claude-code-appical/claude-opus-5@appical
249
249
  "skipPermissions": true,
250
250
  "permissionMode": "default",
251
251
  "bridgeOpencodeMcp": true,
252
- "strictMcpConfig": false
252
+ "strictMcpConfig": false,
253
+ "idleProcessTimeoutMs": 900000
253
254
  }
254
255
  }
255
256
  }
@@ -260,7 +261,7 @@ model: claude-code-appical/claude-opus-5@appical
260
261
  |---|---|---|---|
261
262
  | `cliPath` | string | `process.env.CLAUDE_CLI_PATH ?? "claude"` | Path to the `claude` binary. |
262
263
  | `accounts` | string[] | – | Optional account list. `default` is implicit. Expands into `Claude Code (Default)`, `Claude Code (Personal)`, etc. |
263
- | `cwd` | string | `process.cwd()` | Working directory for the spawned CLI. Resolved **lazily per request**, so opencode's project switching works. |
264
+ | `cwd` | string | session directory, then `process.cwd()` | Working directory for the spawned CLI. Resolved **lazily per request**: an explicit value wins, then the opencode session's own `directory` (so `opencode serve` and the web UI spawn in the right project even though one server handles many), then `process.cwd()`. Contributed by [@galvani](https://github.com/galvani). |
264
265
  | `skipPermissions` | boolean | `true` | Pass `--dangerously-skip-permissions` to `claude`. Ignored when `proxyTools` is set — the proxy handles permissions through opencode instead. |
265
266
  | `permissionMode` | `acceptEdits` \| `auto` \| `bypassPermissions` \| `default` \| `dontAsk` \| `plan` | – | Forwarded to `claude --permission-mode`. |
266
267
  | `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). |
@@ -278,6 +279,8 @@ model: claude-code-appical/claude-opus-5@appical
278
279
  | `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. |
279
280
  | `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). |
280
281
  | `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-change-june-15-2026-agent-sdk-credit). |
282
+ | `idleProcessTimeoutMs` | number | – | Kill a retained headless Claude worker after this many idle milliseconds following a completed turn. The session id is preserved for `--resume`; a new turn cancels the timer. Values above Node's maximum timer delay (`2147483647`) are ignored. Omit or set to `0` to retain workers until LRU eviction. Interactive transport is excluded. Contributed by [@bernardofortes](https://github.com/bernardofortes). |
283
+ | `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). |
281
284
  | `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. Env: `CLAUDE_CODE_INTERACTIVE_TRANSPORT=1`. See [Interactive transport](#interactive-transport-experimental). |
282
285
  | `interactiveBypass` | boolean | `false` | Deprecated/no-op with `interactive`: Claude Code's TUI shows a manual safety confirmation for `bypassPermissions`, so the plugin intentionally does not pass it. |
283
286
  | `interactiveAllowTools` | string[] | `["Bash", "Edit", "Write", "Read", "WebFetch"]` | With `interactive`: built-in tools pre-allowed without prompting (replaces the default list). MCP server wildcards (`mcp__<server>__*`) are always added from the bridged config. |
@@ -549,6 +552,25 @@ Notes:
549
552
 
550
553
  Fully restart opencode after upgrading to load the command and runtime changes. Other providers do not gain Claude's native side-question behavior from this command.
551
554
 
555
+ ## Skill bridge
556
+
557
+ 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`.
558
+
559
+ With `bridgeOpencodeSkills: true` 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:
560
+
561
+ ```text
562
+ opencode-skills:browser-automation
563
+ opencode-skills:rtk
564
+ ```
565
+
566
+ Claude can invoke them with the Skill tool or as `/opencode-skills:<name>`. `--plugin-dir` is scoped to the spawned session, so nothing is written into your `~/.claude`.
567
+
568
+ 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.
569
+
570
+ It is **off by default** here, unlike on the fork it came from: every bridged skill is also listed in the system prompt opencode already forwards, so a large skill set is paid for twice on every turn. Turn it on when you see `Unknown skill`. It no-ops on the compaction path and on a Claude CLI without `--plugin-dir` (the plugin probes `claude --help` and logs a notice).
571
+
572
+ This bridge was written by [@broskees](https://github.com/broskees) (Joseph Roberts) on his fork and absorbed here with credit; see [Credits](#credits).
573
+
552
574
  ## WebSearch routing
553
575
 
554
576
  Claude Code ships a built-in `WebSearch` tool. The `webSearch` option controls who actually executes those calls:
@@ -613,7 +635,8 @@ Each chat keeps a long-lived `claude` subprocess so the model retains its native
613
635
  - **Same chat, multiple turns** → process reused, full Claude context retained.
614
636
  - **New chat** → fresh process under the new session key.
615
637
  - **Resumed chat after restart** → in-memory state is gone; a new process spawns and the conversation history is summarized and prepended.
616
- - **Abort (Ctrl+C)** → stream closes, process stays alive for the next message in that chat.
638
+ - **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).
639
+ - **Idle timeout** → when `idleProcessTimeoutMs` is configured, a completed headless turn arms an eviction timer; reuse cancels it, and eviction preserves the session id for `--resume`.
617
640
  - **Cap**: 16 active processes, LRU eviction.
618
641
 
619
642
  ---
@@ -933,6 +956,26 @@ The GitHub Actions workflow at `.github/workflows/publish.yml` runs `npm publish
933
956
  </picture>
934
957
  </a>
935
958
 
959
+ ## Credits
960
+
961
+ This plugin absorbs work from its forks directly, cherry-picked with the original authorship preserved or reimplemented with the author named in the commit, rather than waiting on pull requests. The people behind the features you are using:
962
+
963
+ | Who | What | Where |
964
+ |---|---|---|
965
+ | [@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` |
966
+ | [@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` |
967
+ | [@bernardofortes](https://github.com/bernardofortes) (Bernardo Fortes) | `idleProcessTimeoutMs`, idle eviction of retained `claude` workers. | `a5f723a` |
968
+ | [@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, and the undici 300 s diagnosis of the proxy wall. | PR #18, `68ed142` |
969
+ | [@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` |
970
+ | [@CollieIsCute](https://github.com/CollieIsCute) (Collie Tsai) | The plan-mode approval bridge. | `8c5b583` |
971
+ | [@flupkede](https://github.com/flupkede) | The compress proxy tool design and the AI-SDK v4 image-part fix. | `4ac319f`, `60a6e9a` |
972
+ | [@CNQQC](https://github.com/CNQQC) | Cost units corrected to dollars per million tokens (PR #25). | PR #25 |
973
+ | [@willmcginnis](https://github.com/willmcginnis) | The proxy endpoint authentication (PR #28, GHSA-3mxm-w7gf-3c5x). | PR #28 |
974
+ | [@nic-lan](https://github.com/nic-lan) | The issue #29 diagnosis of subagent output lost across the CLI resume boundary. | #29 |
975
+ | [@JWebCoder](https://github.com/JWebCoder) (joao moura) | Diagnosed that auto-continue never fires on current CLIs (PR #15). | PR #15 |
976
+
977
+ Commit hashes are on the contributors' forks where the work was cherry-picked; `git log --author` on this repo shows the preserved authorship.
978
+
936
979
  ## License
937
980
 
938
981
  MIT. See [LICENSE](./LICENSE).
package/dist/index.d.ts CHANGED
@@ -194,6 +194,10 @@ interface ClaudeCodeConfig {
194
194
  autoContinueIncompleteTurns?: boolean | "smart";
195
195
  compactionModel?: string;
196
196
  ignoreAnthropicApiKey?: boolean;
197
+ /** Kill an idle headless Claude worker after this many milliseconds. */
198
+ idleProcessTimeoutMs?: number;
199
+ /** Stage opencode skills as a `--plugin-dir` so Claude's Skill tool can run them. */
200
+ bridgeOpencodeSkills?: boolean;
197
201
  logging?: LoggingConfig;
198
202
  }
199
203
  interface LoggingConfig {
@@ -365,6 +369,23 @@ interface ClaudeCodeProviderSettings {
365
369
  * plugin logs a one-time warning at startup when an API key is detected.
366
370
  */
367
371
  ignoreAnthropicApiKey?: boolean;
372
+ /**
373
+ * Kill a retained headless Claude worker after this many milliseconds of
374
+ * inactivity following a completed turn. Starting another turn cancels the
375
+ * timer, and the Claude session id is retained for a transparent resume.
376
+ * Omit or set to 0 to keep workers until LRU eviction. Interactive transport
377
+ * is excluded because it does not currently guarantee session-id resume.
378
+ */
379
+ idleProcessTimeoutMs?: number;
380
+ /**
381
+ * Expose your opencode skills (`.opencode/skills`, `~/.config/opencode/skills`)
382
+ * to Claude Code's native Skill tool by staging them as a session-scoped
383
+ * `--plugin-dir`. Off by default: every bridged skill is also listed in the
384
+ * system prompt opencode already forwards, so a large skill set is paid for
385
+ * twice per turn. Turn it on when the model tries `Skill("<name>")` and gets
386
+ * `Unknown skill`. No-op on CLIs without `--plugin-dir`.
387
+ */
388
+ bridgeOpencodeSkills?: boolean;
368
389
  /**
369
390
  * Routing for Claude's built-in `WebSearch` tool.
370
391
  *
@@ -382,7 +403,7 @@ interface ClaudeCodeProviderSettings {
382
403
  * underlying claude process so newly enabled / disabled MCPs become
383
404
  * visible to the model without restarting opencode or starting a new
384
405
  * chat. Eviction happens at the start of the next user turn (never mid
385
- * tool-call) and `--session-id` is preserved so the conversation
406
+ * tool-call) and the session id is preserved for `--resume` so the conversation
386
407
  * continues seamlessly. Defaults to `true`.
387
408
  *
388
409
  * Set to `false` to keep the previous behavior (cached subprocess