@khalilgharbaoui/opencode-claude-code-plugin 0.27.2 → 0.28.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 +81 -2
- package/dist/index.d.ts +114 -2
- package/dist/index.js +401 -56
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/skills/claude-code-plugin/SKILL.md +30 -3
package/README.md
CHANGED
|
@@ -345,6 +345,7 @@ model: claude-code-work/claude-opus-5@work
|
|
|
345
345
|
| `cwd` | string | see description | Working directory for the spawned CLI. Resolved **lazily per request**, first match winning: this explicit value, 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()` when it is a real directory, then the project directory captured at plugin init (this rescues macOS GUI launches, where `process.cwd()` is `/`), and finally `process.cwd()` regardless. [Startup diagnostics](#startup-diagnostics) reports which tier won. Session tier contributed by [@galvani](https://github.com/galvani). |
|
|
346
346
|
| `skipPermissions` | boolean | `true` | Pass `--dangerously-skip-permissions` to `claude`. It is still passed when `proxyTools` is set: proxied calls go through opencode's permission system regardless, but unproxied CLI built-ins do not. The one case where the flag is dropped is `permissionMode: "plan"`, because the CLI lets the skip flag override plan mode outright. See [Plan mode](#plan-mode). |
|
|
347
347
|
| `permissionMode` | `acceptEdits` \| `auto` \| `bypassPermissions` \| `default` \| `dontAsk` \| `plan` | – | Forwarded to headless `claude --permission-mode`. `"plan"` also suppresses `--dangerously-skip-permissions` (see the row above). Not version-gated, so check that your installed CLI accepts the value. The [interactive transport](#interactive-transport-experimental) does not forward it. |
|
|
348
|
+
| `permissionPreset` | `"read-only"` | – | A named permission posture, so you set one option instead of combining five and getting one wrong. Opt-in: unset is exactly today's behaviour. `"read-only"` replaces `skipPermissions`, `permissionMode`, `controlRequestBehavior` and `controlRequestToolBehaviors`, and filters the write and command tools out of `proxyTools`. See [Read-only mode](#read-only-mode). |
|
|
348
349
|
| `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). |
|
|
349
350
|
| `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). |
|
|
350
351
|
| `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). |
|
|
@@ -362,7 +363,7 @@ model: claude-code-work/claude-opus-5@work
|
|
|
362
363
|
| `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). |
|
|
363
364
|
| `webSearch` | `"claude"` \| `"disabled"` \| `<tool>` | `"claude"` | Routing for Claude's built-in `WebSearch`. See [WebSearch routing](#websearch-routing). |
|
|
364
365
|
| `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. |
|
|
365
|
-
| `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. |
|
|
366
|
+
| `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. Also gates the `▌ **no reply:**` note on a turn that ends with no text and no tool call. Set `false` to disable both. |
|
|
366
367
|
| `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). |
|
|
367
368
|
| `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). |
|
|
368
369
|
| `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). |
|
|
@@ -391,7 +392,9 @@ Every variable the plugin itself reads, in one place. Config is read once at ope
|
|
|
391
392
|
| `OPENCODE_CLAUDE_CODE_LOG_DIR` | logger | Directory for the log file, overriding `logging.dir`. |
|
|
392
393
|
| `OPENCODE_CLAUDE_CODE_LOG_LEVEL` | logger | Minimum level to emit, overriding `logging.level`. An unrecognised value falls through to config. |
|
|
393
394
|
| `DEBUG` | logger | `DEBUG=opencode-claude-code` promotes the logger to `mode: "debug"`, echoing every emitted level to opencode's TUI. |
|
|
394
|
-
| `OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP` | startup cleanup | `1` skips the
|
|
395
|
+
| `OPENCODE_CLAUDE_CODE_PLUGIN_NO_CLEANUP` | startup cleanup | `1` skips the removal of a stale **unscoped** `opencode-claude-code-plugin` install from opencode's plugin cache. That old package is a different artifact that shadows this scoped one when both are present; set this if you are deliberately keeping it. |
|
|
396
|
+
| `OPENCODE_CLAUDE_CODE_PLUGIN_FORCE_CLEANUP` | startup cleanup | `1` runs that cleanup even when the marker at `$XDG_STATE_HOME/opencode-claude-code-plugin/cleanup-stale.json` (default `~/.local/state/...`) records that this plugin version already swept. Without it the cleanup walks opencode's plugin cache once per installed version rather than on every launch. |
|
|
397
|
+
| `OPENCODE_CLAUDE_CODE_NO_TMP_SWEEP` | scratch directory | `1` skips the sweep of `<tmpdir>/opencode-claude-code-<pid>` directories left behind by plugin processes that were killed. See [Scratch files on disk](#scratch-files-on-disk). |
|
|
395
398
|
| `OPENCODE_WORKTREE` | MCP bridge | Overrides worktree-root detection, which otherwise walks up from the working directory looking for a `.git` entry. |
|
|
396
399
|
| `OPENCODE_CONFIG` / `OPENCODE_CONFIG_DIR` | config discovery | Where the plugin looks for your opencode config when bridging MCP and skills. See [Discovery order](#discovery-order-highest-to-lowest-priority). |
|
|
397
400
|
| `OPENCODE_VERSION` | startup diagnostics | Reported as the opencode version when set, sparing the plugin a `--version` spawn. Diagnostics only. |
|
|
@@ -528,6 +531,23 @@ A patched process answers `401`. A `200` is a pre-0.13.2 process still running,
|
|
|
528
531
|
|
|
529
532
|
Nothing to configure. If proxied tools ever stop working after a Claude Code upgrade, check the plugin log for `proxy-mcp rejected a request`, which names which guard failed.
|
|
530
533
|
|
|
534
|
+
### Scratch files on disk
|
|
535
|
+
|
|
536
|
+
Everything the plugin writes for the Claude CLI to read goes into one per-process directory, `<tmpdir>/opencode-claude-code-<pid>`, created `0700`:
|
|
537
|
+
|
|
538
|
+
| File | Mode | Holds |
|
|
539
|
+
| --- | --- | --- |
|
|
540
|
+
| `mcp-<hash>.json` | `0600` | the bridged MCP config, including any `{env:VAR}` values substituted from your environment |
|
|
541
|
+
| `proxy-<hash>.json` | `0600` | the proxy endpoint's bearer token |
|
|
542
|
+
| `opencode-cc-sys-<uuid>.md` | `0600` | the full appended system prompt, forwarded opencode instructions and AGENTS.md included |
|
|
543
|
+
| `skills-<hash>/` | inherits | staged skill plugin dirs for the skill bridge; the `0700` parent is what keeps them private |
|
|
544
|
+
|
|
545
|
+
On a shared host the OS tmpdir is world-writable and the pid name is guessable, so the plugin refuses a path that already exists but is a symlink, is not a directory, or is not owned by you: it falls back to a fresh `mkdtemp` name and logs a warning naming both paths.
|
|
546
|
+
|
|
547
|
+
The directory is removed on normal exit. `SIGKILL` skips that, so on first use each run the plugin also sweeps `<tmpdir>/opencode-claude-code-<pid>` directories whose pid is no longer running and which you own. Anything else, another user's directory, a live process's, a symlink, a name that is not exactly that pattern, is left alone. Set `OPENCODE_CLAUDE_CODE_NO_TMP_SWEEP=1` to turn the sweep off.
|
|
548
|
+
|
|
549
|
+
**Windows is not hardened here.** Both spawn sites pass `shell: true` on `win32`, so the CLI argument list goes through `cmd.exe` unquoted. Treat Windows as unsupported until that is fixed; see the note in `docs/agents-history.md`.
|
|
550
|
+
|
|
531
551
|
### Closing a tool with no proxy
|
|
532
552
|
|
|
533
553
|
`proxyTools` only reaches built-ins the plugin can replace. A built-in with no opencode equivalent, `NotebookEdit` today and whatever Claude Code ships next, stays enabled and unmediated no matter what you put in that list. `extraDisallowedTools` names them directly:
|
|
@@ -782,6 +802,7 @@ Four Claude Code stream events used to reach nothing but a debug log:
|
|
|
782
802
|
- **A conversation Claude Code cleared.** Sending `/clear` as a message, or a plan-mode exit that clears context, makes Claude Code start a fresh conversation while opencode still shows the old messages. A `▌ **claude code reset:**` note says so. The plugin deliberately does not replay the earlier messages, since that would undo the clear. Start a new opencode session if you want the two to match.
|
|
783
803
|
- **A `result` whose subtype is not `success`** (`error_max_turns`, `error_during_execution`, …). The subtype is named in the transcript and the turn finishes as an error instead of an ordinary reply.
|
|
784
804
|
- **A CLI-executed tool that failed.** Its result is forwarded with the AI SDK's error flag, so opencode renders the row as failed rather than as a success whose output happens to be an error message.
|
|
805
|
+
- **A turn that finished cleanly without saying anything.** No text, no tool call, no error: opencode files it as an ordinary reply, so what you get is a blank message with nothing to distinguish it from a crash. A `▌ **no reply:**` note now says which of the two shapes it was, thinking-with-no-answer or nothing at all, and that nothing failed and nothing is pending. It is its own text part and is stripped from any transcript rebuilt for the CLI. Never on a compaction turn, a failed turn, an aborted one, or one that ended on a question, and suppressed entirely by `"autoContinueIncompleteTurns": false`. There is deliberately no automatic retry: measured across the whole retained plugin log, every finished turn carried between 940 and 5,080 characters of reply and none was silent.
|
|
785
806
|
|
|
786
807
|
At session start the plugin also warns once per process for each MCP server Claude Code could not connect (its tools are simply absent otherwise) and once when the CLI's own `apiKeySource` says an API key is in effect, which is the field that tells you pay-as-you-go billing is happening. See [`ignoreAnthropicApiKey`](#options-reference).
|
|
787
808
|
|
|
@@ -915,6 +936,64 @@ Each chat keeps a long-lived `claude` subprocess so the model retains its native
|
|
|
915
936
|
|
|
916
937
|
---
|
|
917
938
|
|
|
939
|
+
## Read-only mode
|
|
940
|
+
|
|
941
|
+
```json
|
|
942
|
+
"options": {
|
|
943
|
+
"permissionPreset": "read-only"
|
|
944
|
+
}
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
That is the whole configuration. The turn can read your code and search the
|
|
948
|
+
web, and it cannot write a file, run a command, or execute code.
|
|
949
|
+
|
|
950
|
+
Presets exist because read-only was previously a combination you had to get
|
|
951
|
+
exactly right. `permissionMode: "plan"` alone does not do it, and neither does
|
|
952
|
+
any single Claude Code flag, because this plugin puts a second execution path
|
|
953
|
+
next to the CLI's own tools: `proxyTools` defaults to `Bash`, `Edit`, `Write`,
|
|
954
|
+
`WebFetch` and `Task`, and each of those is an MCP tool the CLI calls and
|
|
955
|
+
**opencode** executes. No CLI flag reaches them. So the preset works at three
|
|
956
|
+
layers:
|
|
957
|
+
|
|
958
|
+
| Layer | What read-only does | Why it is needed |
|
|
959
|
+
| --- | --- | --- |
|
|
960
|
+
| Claude CLI tools | `--restricted` (CLI 2.1.258+) | Removes Bash, the REPL and the other code-running built-ins, removes WebFetch, confines the file tools to the working directories, and refuses bypass |
|
|
961
|
+
| Claude CLI tools, older CLIs | `--disallowedTools Bash Write Edit NotebookEdit REPL JavaScript WebFetch` | `--restricted` is version-gated; these names are not |
|
|
962
|
+
| The opencode proxy | `bash`, `write`, `edit`, `webfetch`, `task` and `task_batch` are dropped from `proxyTools` | These run in opencode, so the CLI flags above never see them |
|
|
963
|
+
| Everything else | `--permission-prompts none` (CLI 2.1.263+) and `controlRequestBehavior: "deny"` | A bridged MCP tool or a read outside the working directory is neither of the above |
|
|
964
|
+
|
|
965
|
+
`skipPermissions` is forced to `false`, and that is not a style choice:
|
|
966
|
+
`--restricted --dangerously-skip-permissions` is a startup error on CLI 2.1.280
|
|
967
|
+
(`Error: bypassPermissions not supported in restricted mode`), so a spawn
|
|
968
|
+
carrying both would not run at all.
|
|
969
|
+
|
|
970
|
+
**The preset replaces rather than merges.** Setting `skipPermissions`,
|
|
971
|
+
`permissionMode`, `controlRequestBehavior` or `controlRequestToolBehaviors`
|
|
972
|
+
next to it has no effect; each dropped value is logged at NOTICE at startup so
|
|
973
|
+
you can see it happen. `proxyTools` is the exception: it is filtered, so a list
|
|
974
|
+
naming `Question` keeps it. An unrecognised preset name applies **nothing** and
|
|
975
|
+
logs a WARN, rather than guessing at what you meant.
|
|
976
|
+
|
|
977
|
+
**What stops working.** Reads are fine (`Read`, `Grep`, `Glob`, `WebSearch`),
|
|
978
|
+
but anything that would raise a permission prompt is denied, and that includes
|
|
979
|
+
bridged MCP tools and the `question` proxy. Claude's own `AskUserQuestion`
|
|
980
|
+
still renders its stop-and-wait markdown, so the model can still ask you
|
|
981
|
+
things. If you need one specific tool allowed, do not use the preset: set the
|
|
982
|
+
underlying options yourself.
|
|
983
|
+
|
|
984
|
+
**On an older CLI** the preset still holds through `--disallowedTools` plus the
|
|
985
|
+
plugin's own denial of every permission request, and it warns naming what is
|
|
986
|
+
missing. Below 2.1.258 you lose the cwd confinement on reads; below 2.1.263 the
|
|
987
|
+
denial happens in the plugin rather than in the CLI, one layer instead of two.
|
|
988
|
+
|
|
989
|
+
Measured end to end on CLI 2.1.280 and `claude-haiku-4-5`: a turn under the
|
|
990
|
+
preset asked to write a file and run a command did neither, the file was never
|
|
991
|
+
created, and the CLI's own `permission_denials` recorded the single blocked
|
|
992
|
+
`Write` with no Bash attempt at all, because there was no Bash tool to attempt
|
|
993
|
+
with.
|
|
994
|
+
|
|
995
|
+
---
|
|
996
|
+
|
|
918
997
|
## Plan mode
|
|
919
998
|
|
|
920
999
|
Set `permissionMode: "plan"` to forward `--permission-mode plan` to Claude. The plugin handles `ExitPlanMode` specially — instead of forwarding it as a tool call, it converts it to a confirmation prompt that flows through opencode normally.
|
package/dist/index.d.ts
CHANGED
|
@@ -376,7 +376,15 @@ interface ClaudeCodeConfig {
|
|
|
376
376
|
accountFailover?: AccountFailoverMode;
|
|
377
377
|
providerID?: string;
|
|
378
378
|
skipPermissions?: boolean;
|
|
379
|
-
|
|
379
|
+
/**
|
|
380
|
+
* Widened past `PermissionMode` because a resolved `permissionPreset` puts
|
|
381
|
+
* its own internal token here (`READ_ONLY_PERMISSION_MODE`), which
|
|
382
|
+
* `buildCliArgs` translates to CLI flags. The operator-facing option on
|
|
383
|
+
* `ClaudeCodeProviderSettings` stays a plain `PermissionMode`.
|
|
384
|
+
*/
|
|
385
|
+
permissionMode?: EffectivePermissionMode;
|
|
386
|
+
/** The preset this config was resolved from, for diagnostics. */
|
|
387
|
+
permissionPreset?: PermissionPreset;
|
|
380
388
|
mcpConfig?: string | string[];
|
|
381
389
|
strictMcpConfig?: boolean;
|
|
382
390
|
bridgeOpencodeMcp?: boolean;
|
|
@@ -492,6 +500,23 @@ interface ClaudeCodeProviderSettings {
|
|
|
492
500
|
defaultSubagentModel?: string;
|
|
493
501
|
skipPermissions?: boolean;
|
|
494
502
|
permissionMode?: PermissionMode;
|
|
503
|
+
/**
|
|
504
|
+
* Apply a named permission preset instead of hand-combining
|
|
505
|
+
* `permissionMode`, `skipPermissions`, `proxyTools`,
|
|
506
|
+
* `extraDisallowedTools` and `controlRequestBehavior`.
|
|
507
|
+
*
|
|
508
|
+
* `"read-only"` makes the turn unable to change anything: no
|
|
509
|
+
* `--dangerously-skip-permissions` (the CLI refuses bypass under
|
|
510
|
+
* `--restricted` outright), `--restricted` so the CLI has no Bash, REPL or
|
|
511
|
+
* WebFetch at all, the mutating built-ins on `--disallowedTools` for CLIs
|
|
512
|
+
* too old for that flag, the write and command tools removed from the
|
|
513
|
+
* opencode proxy, and every remaining permission request denied.
|
|
514
|
+
*
|
|
515
|
+
* A preset overrides those five options rather than merging with them, so
|
|
516
|
+
* one setting decides the posture; the plugin warns about each value it
|
|
517
|
+
* drops. Unset (the default) changes nothing.
|
|
518
|
+
*/
|
|
519
|
+
permissionPreset?: PermissionPreset;
|
|
495
520
|
mcpConfig?: string | string[];
|
|
496
521
|
strictMcpConfig?: boolean;
|
|
497
522
|
/**
|
|
@@ -806,6 +831,25 @@ interface ClaudeCodeProviderSettings {
|
|
|
806
831
|
logging?: LoggingConfig;
|
|
807
832
|
}
|
|
808
833
|
type PermissionMode = "acceptEdits" | "auto" | "bypassPermissions" | "default" | "dontAsk" | "plan";
|
|
834
|
+
/**
|
|
835
|
+
* A named bundle of permission settings, so a safety posture is one option
|
|
836
|
+
* instead of a hand-rolled combination of `permissionMode`, `skipPermissions`,
|
|
837
|
+
* `proxyTools`, `extraDisallowedTools` and `controlRequestBehavior`. Opt-in:
|
|
838
|
+
* unset means today's behaviour, unchanged.
|
|
839
|
+
*
|
|
840
|
+
* `read-only` is the only preset so far. See `src/permission-presets.ts` for
|
|
841
|
+
* what it resolves to and why each part is needed.
|
|
842
|
+
*/
|
|
843
|
+
type PermissionPreset = "read-only";
|
|
844
|
+
/**
|
|
845
|
+
* The `permissionMode` a resolved preset puts on `ClaudeCodeConfig`.
|
|
846
|
+
* Plugin-internal, never a value the operator sets: `buildCliArgs` translates
|
|
847
|
+
* `"read-only"` into `--restricted` (plus `--permission-prompts none` where
|
|
848
|
+
* the CLI has it) rather than passing it to `--permission-mode`, which would
|
|
849
|
+
* reject it.
|
|
850
|
+
*/
|
|
851
|
+
declare const READ_ONLY_PERMISSION_MODE = "read-only";
|
|
852
|
+
type EffectivePermissionMode = PermissionMode | typeof READ_ONLY_PERMISSION_MODE;
|
|
809
853
|
type ControlRequestBehavior = "allow" | "deny";
|
|
810
854
|
/**
|
|
811
855
|
* Claude CLI stream-json message types.
|
|
@@ -937,6 +981,61 @@ interface ClaudeStreamMessage {
|
|
|
937
981
|
index?: number;
|
|
938
982
|
}
|
|
939
983
|
|
|
984
|
+
/**
|
|
985
|
+
* Named permission presets: one option that decides a safety posture, instead
|
|
986
|
+
* of the operator hand-combining `permissionMode`, `skipPermissions`,
|
|
987
|
+
* `proxyTools`, `extraDisallowedTools` and `controlRequestBehavior` and
|
|
988
|
+
* getting one of them wrong.
|
|
989
|
+
*
|
|
990
|
+
* Opt-in. No preset resolves to exactly today's behaviour, byte for byte.
|
|
991
|
+
*
|
|
992
|
+
* ## Why `read-only` is not just a CLI flag
|
|
993
|
+
*
|
|
994
|
+
* Claude Code 2.1.248 added `--restricted`, which removes the built-in tools
|
|
995
|
+
* that run commands or code plus WebFetch, confines the file tools to the
|
|
996
|
+
* working directories, and refuses bypassPermissions. That covers the CLI's
|
|
997
|
+
* own tools and nothing else, and this plugin's whole point is that it puts a
|
|
998
|
+
* second execution path next to them: `proxyTools` defaults to `Bash`, `Edit`,
|
|
999
|
+
* `Write`, `WebFetch` and `Task`, each an MCP tool the CLI calls and opencode
|
|
1000
|
+
* executes. `--restricted` never sees those. So the preset has to work at
|
|
1001
|
+
* three layers at once:
|
|
1002
|
+
*
|
|
1003
|
+
* 1. the CLI's own tools (`--restricted`, plus `--disallowedTools` for the
|
|
1004
|
+
* same names so a CLI too old for `--restricted` still refuses them),
|
|
1005
|
+
* 2. the opencode proxy (the mutating defs are dropped before the proxy
|
|
1006
|
+
* server is built, so they are never offered),
|
|
1007
|
+
* 3. everything left that would prompt (denied, because a bridged MCP
|
|
1008
|
+
* server or a file tool reaching outside the cwd is neither of the
|
|
1009
|
+
* above).
|
|
1010
|
+
*
|
|
1011
|
+
* ## Measured, on the CLI this was written against (2.1.280)
|
|
1012
|
+
*
|
|
1013
|
+
* `--restricted --dangerously-skip-permissions` is a hard startup error,
|
|
1014
|
+
* `Error: bypassPermissions not supported in restricted mode`, so dropping
|
|
1015
|
+
* the skip flag is a correctness requirement and not hygiene. In the binary,
|
|
1016
|
+
* `restrictedMode` is a `bypassImmune` circuit breaker, which is the same
|
|
1017
|
+
* fact from the other side. A `--restricted` run asked to write a file and
|
|
1018
|
+
* run a command reported one `permission_denials` entry (`Write`) and no Bash
|
|
1019
|
+
* attempt at all: the shell tool was not in the set to begin with.
|
|
1020
|
+
*/
|
|
1021
|
+
|
|
1022
|
+
/** The options a preset decides, resolved. */
|
|
1023
|
+
interface ResolvedPermissionPreset {
|
|
1024
|
+
preset: PermissionPreset;
|
|
1025
|
+
permissionMode: EffectivePermissionMode;
|
|
1026
|
+
skipPermissions: boolean;
|
|
1027
|
+
proxyTools: string[];
|
|
1028
|
+
extraDisallowedTools: string[];
|
|
1029
|
+
controlRequestBehavior: ControlRequestBehavior;
|
|
1030
|
+
/** Always undefined under a preset: see `overridden` below. */
|
|
1031
|
+
controlRequestToolBehaviors: undefined;
|
|
1032
|
+
/**
|
|
1033
|
+
* Operator-set values the preset replaced, as `option: reason` lines, so
|
|
1034
|
+
* the caller can warn once per option rather than silently winning.
|
|
1035
|
+
*/
|
|
1036
|
+
overridden: string[];
|
|
1037
|
+
}
|
|
1038
|
+
|
|
940
1039
|
interface DiagnosticsProviderEntry {
|
|
941
1040
|
name?: string;
|
|
942
1041
|
options?: Record<string, unknown>;
|
|
@@ -1139,6 +1238,19 @@ declare function registerSideQuestionCommand(config: OpenCodeConfig): boolean;
|
|
|
1139
1238
|
declare function registerDoctorCommand(config: OpenCodeConfig): boolean;
|
|
1140
1239
|
declare function _resetPlanModeWarningForTests(): void;
|
|
1141
1240
|
declare function warnIfPlanModeCannotExit(permissionMode: string | undefined): void;
|
|
1241
|
+
/**
|
|
1242
|
+
* Resolve `permissionPreset` for this provider, reporting what it replaced.
|
|
1243
|
+
*
|
|
1244
|
+
* The result is applied over the operator's settings by `createClaudeCode`,
|
|
1245
|
+
* which is the one funnel both opencode majors reach the language model
|
|
1246
|
+
* through, so a preset needs wiring in exactly one place.
|
|
1247
|
+
*
|
|
1248
|
+
* Every override is logged at NOTICE, and an unrecognised preset name is a
|
|
1249
|
+
* WARN plus no preset at all. A safety option must never be approximated: a
|
|
1250
|
+
* typo'd `"readonly"` silently running at full permissions is worse than one
|
|
1251
|
+
* that says so.
|
|
1252
|
+
*/
|
|
1253
|
+
declare function applyPermissionPreset(settings: ClaudeCodeProviderSettings, defaultProxyTools: readonly string[]): ResolvedPermissionPreset | null;
|
|
1142
1254
|
declare function createClaudeCode(settings?: ClaudeCodeProviderSettings): ClaudeCodeProvider;
|
|
1143
1255
|
/**
|
|
1144
1256
|
* Build models in OpenCode's config schema format (flat properties like
|
|
@@ -1178,4 +1290,4 @@ declare const _default: {
|
|
|
1178
1290
|
setup: (ctx: V2Context) => Promise<V2Cleanup>;
|
|
1179
1291
|
};
|
|
1180
1292
|
|
|
1181
|
-
export { type AgentRecord, type ClaudeCodeConfig, ClaudeCodeLanguageModel, type ClaudeCodeProvider, type ClaudeCodeProviderSettings, type ClaudeStreamMessage, DEFAULT_PROXY_TOOL_NAMES, type OpenCodeHooks, type OpenCodeModel, type OpenCodePlugin, _resetPlanModeWarningForTests, bridgeOpencodeMcp, buildAgentRegistry, claudeCodeProviders, configModelsForProvider, createClaudeCode, _default as default, defaultModels, extractDeletedSessionId, getAgentRegistry, getDefaultSubagentModel, registerDoctorCommand, registerSideQuestionCommand, resolveAgentModel, warnIfPlanModeCannotExit };
|
|
1293
|
+
export { type AgentRecord, type ClaudeCodeConfig, ClaudeCodeLanguageModel, type ClaudeCodeProvider, type ClaudeCodeProviderSettings, type ClaudeStreamMessage, DEFAULT_PROXY_TOOL_NAMES, type OpenCodeHooks, type OpenCodeModel, type OpenCodePlugin, _resetPlanModeWarningForTests, applyPermissionPreset, bridgeOpencodeMcp, buildAgentRegistry, claudeCodeProviders, configModelsForProvider, createClaudeCode, _default as default, defaultModels, extractDeletedSessionId, getAgentRegistry, getDefaultSubagentModel, registerDoctorCommand, registerSideQuestionCommand, resolveAgentModel, warnIfPlanModeCannotExit };
|