@khalilgharbaoui/opencode-claude-code-plugin 0.45.0 → 0.46.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/dist/index.d.ts +27 -0
- package/dist/index.js +640 -225
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/claude-code-plugin/SKILL.md +28 -5
package/package.json
CHANGED
|
@@ -146,6 +146,7 @@ Defaults below describe normal headless opencode use when the key is absent.
|
|
|
146
146
|
| `turnStats` | boolean | `false` | Append one `▌ **stats:**` line to each finished turn: cost, wall duration, CLI turn count, input/output/cache-read/cache-write tokens, and a permission-denial count when the turn had any, taken from the CLI's own `result`. Never on a compaction turn or a turn that ended in error. Its own text part, stripped from transcripts rebuilt for the CLI, so the model never sees it. The same numbers are logged at INFO regardless, and `modelUsage` plus `permission_denials` always reach `providerMetadata`. Reported cost is the CLI's figure, not a billing guarantee. |
|
|
147
147
|
| `forkSessions` | boolean | `false` | When a new opencode session turns out to be a fork of one this provider already served, branch the parent's Claude conversation with `claude --resume <parent> --fork-session` instead of re-rendering the whole thread as text into the first message. Measured on CLI 2.1.280 with haiku 4.5 over a ~13k-token thread: 814 cache tokens written and 39,710 read, against 22,355 written and 17,385 read for the replay, so $0.0058 against $0.0467 for that turn; the parent's transcript is byte-identical afterwards. Neither opencode major tells a provider that a session is a fork, so the parent is found by matching this prompt's history against what each sibling session key was last asked to continue. Off by default because a resumed Claude conversation reuses the system prompt recorded on its FIRST request (`--system-prompt-snapshot`, default `on`), so a forked session answers under the parent's appended system prompt rather than this turn's; measured directly, a parent seeded with codename ZEBRA and forked while passing QUAIL answered ZEBRA. Falls back to the replay, unchanged, for: another account, an unknown or released parent session id, a busy parent (live process, proxied call in flight, unanswered plan-mode question), a fork cut mid-conversation, a fork taken mid tool round trip, a different cwd / model / agent / effort / prompt-cache TTL, compaction, an account-failover switch, and a `claude` whose `--help` does not advertise `--fork-session`. Recording costs nothing while the option is off. |
|
|
148
148
|
| `resumeAfterRestart` | boolean | `true` | After an opencode restart, resume the conversation's Claude session (`--resume`) instead of replaying the thread as text. Persists session id + conversation digest per session key in `$XDG_STATE_HOME/opencode-claude-code-plugin/claude-sessions.json` (0600, 256 entries, 30 days) after each successful turn. Resumes only on the same session key and binary, with the transcript on disk and the history equal to the recorded conversation plus Claude's reply; anything else (edit, revert, compaction, account switch, open tool round trip) replays. Not on compaction. Log: `resuming the claude session from before the restart` (NOTICE) or `not resuming ...` with a reason (INFO). `false` disables reading and writing. |
|
|
149
|
+
| `resumeAcrossModelChanges` | boolean | `true` | When the operator changes a conversation's model or reasoning effort mid-conversation, continue the same Claude session (`--resume <id> --model <new>`) instead of replaying the thread as text. Both are in the session key, so changing either used to start a fresh Claude conversation (issue #91); neither needs one, because `--model` and `CLAUDE_CODE_EFFORT_LEVEL` are spawn-time and the CLI applies either to a resumed transcript (measured on 2.1.288). The session is MOVED off the old key, so one Claude conversation has exactly one owner. Refused on every term `resumeAfterRestart` is refused on (another account, a transcript that is gone, a conversation that changed) plus two more: a sibling whose transcript may still be written to, and anything that is not the same cwd, request scope, opencode session, agent and prompt-cache TTL. Not on compaction, not on an account-failover switch. It reads the record `resumeAfterRestart` writes, so `resumeAfterRestart: false` turns it off too. Log: `continuing this conversation's claude session under the new model or effort` (NOTICE). |
|
|
149
150
|
| `bridgeOpencodeSkills` | boolean | `false` | Stage the user's opencode skills for Claude's native Skill tool as `opencode-skills:<name>`, on the headless and interactive spawns (never compaction). Covers every root opencode reads: project `.opencode/`, `.claude/`, `.agents/` walking up, the opencode config dirs (`skill/` and `skills/`), and global `~/.claude/skills` and `~/.agents/skills` under opencode's own `OPENCODE_DISABLE_EXTERNAL_SKILLS` / `OPENCODE_DISABLE_CLAUDE_CODE_SKILLS` switches. Requires the CLI's `--help` to advertise `--plugin-dir`; otherwise no-op. Bridged skills are also listed in opencode's forwarded system prompt, so a large skill set costs prompt tokens twice, which is why it is off by default; `true` opts the user's skills in. Bundled skill staging ignores this option, but still requires flag support and successful discovery/staging. |
|
|
150
151
|
| `bridgeSkipNativeSkills` | boolean | `true` | Leave a skill unbridged when the Claude session already loads it: from `<CLAUDE_CONFIG_DIR>/skills`, the project's `.claude/skills`, or an installed plugin's `skills/`. Matched by resolved directory, by byte-identical SKILL.md, or (user/project scope only, since plugin skills are namespaced `<plugin>:<name>`) by name. A name match means `Skill("<name>")` answers from Claude's copy, not opencode's, so it is logged at WARN with both paths. The plugin scan reads `installed_plugins.json` and does not check whether the plugin is enabled. `false` bridges everything and reinstates the duplicates. |
|
|
151
152
|
| `transport` | `"auto"` / `"headless"` / `"interactive"` | unset (headless) | Explicit choice wins over `interactive` and its env var. `auto` prefers headless and probes required headless flags with free help/argument parsing and no prompt. Only definitive unsupported flags select the PTY; timeout, auth failure, missing binary and unknown output stay headless. Never retries a submitted request. Explicit or automatic PTY selection requires `Bun.Terminal`, otherwise errors. Title stubs do not probe. `/compact` follows the selected transport. On the PTY, `read-only` is `--restricted` plus `dontAsk` (CLI 2.1.263+, refused below rather than weakened) and plan mode parks `ExitPlanMode`'s dialog for the operator. `/claude-code-doctor usage` reports the free headless check unavailable when those flags are absent; it does not run a PTY inference prompt. |
|
|
@@ -320,7 +321,9 @@ through the TUI's own input queue, as on headless. A turn ends on its stop reaso
|
|
|
320
321
|
`turn_duration`, or, as a safeguard for a CLI that writes neither, after 20 s of total
|
|
321
322
|
silence once it has its reply (reported as ended without a stop reason). It reads
|
|
322
323
|
completed transcript blocks, not token
|
|
323
|
-
deltas.
|
|
324
|
+
deltas. A poll reads only the bytes appended since the last one, so a poll that finds
|
|
325
|
+
nothing new costs one `stat` and no read at all, however long the conversation is.
|
|
326
|
+
Normal interactive turns
|
|
324
327
|
do not forward opencode's system prompt (on the TUI, Claude Code bills a request
|
|
325
328
|
carrying it as a third-party app's from extra usage; headless does not). The
|
|
326
329
|
account-switch form, the fallback chain, `forkSessions`, the usage-limit and
|
|
@@ -381,10 +384,30 @@ resend your message, or wait for the window to reset.
|
|
|
381
384
|
and the `▌ **rate limit:**` paragraph the plugin used to write is log-only now, so a
|
|
382
385
|
limited turn carries exactly one block.
|
|
383
386
|
- Written on a child session too (a subagent that died on a limit is what the parent's
|
|
384
|
-
`task` result should say), but never on a compaction turn,
|
|
385
|
-
|
|
386
|
-
-
|
|
387
|
-
|
|
387
|
+
`task` result should say), but never on a compaction turn, which fails outright
|
|
388
|
+
instead (see "A failed compaction turn" below).
|
|
389
|
+
- The turn **finishes as an error** (`finishReason` `{unified:"error", raw:"usage_limit"}`),
|
|
390
|
+
the way the account-block note's turn always has: nothing was served, so filing it as
|
|
391
|
+
a reply hid the failure from opencode. There is no `error` stream part outside
|
|
392
|
+
compaction, so the note stays the single account of what happened.
|
|
393
|
+
- `permission_denials` and `turnStats` are untouched; `turnStats` was already suppressed
|
|
394
|
+
on a failed turn, so a limited turn never carried a stats line anyway.
|
|
395
|
+
|
|
396
|
+
### A failed compaction turn
|
|
397
|
+
|
|
398
|
+
A compaction turn's text is what opencode stores as the summary, so a compaction whose
|
|
399
|
+
`result` is `is_error: true` (or carries a failing subtype) writes **no text at all**:
|
|
400
|
+
no note, no CLI prose, nothing. It ends on an `error` stream part naming the cause and
|
|
401
|
+
the CLI's own sentence, plus a finish of `{unified:"error", raw:<cause>}` where the
|
|
402
|
+
cause is `usage_limit`, an account-block kind such as `authentication_failed`, or the
|
|
403
|
+
failing subtype. opencode then marks the compaction failed and keeps the conversation
|
|
404
|
+
it already had.
|
|
405
|
+
|
|
406
|
+
Before this, a usage-limited compaction returned the CLI's sentence as a normal answer
|
|
407
|
+
and opencode stored it as the summary, so every later session that could not resume its
|
|
408
|
+
Claude transcript began from that sentence with the earlier messages gone (issue #90).
|
|
409
|
+
There is no option for this and nothing to turn off; the operator retries the
|
|
410
|
+
compaction once the account can serve.
|
|
388
411
|
|
|
389
412
|
When a user says the limit message is unhelpful, check the plugin version before
|
|
390
413
|
anything else: this note is recent and a long-lived opencode window may predate it.
|