@stablekernel/opencode-cursor 0.8.0 → 0.9.0-next.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/CHANGELOG.md CHANGED
@@ -4,6 +4,33 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.9.0-next.0] — 2026-08-26 (pre-release)
8
+
9
+ The Cursor agent can now use installed opencode plugins (#104), plus
10
+ consolidated opencode-ai dependency bumps (#107). Not yet on `latest`;
11
+ install with `npm install @stablekernel/opencode-cursor@next` to test.
12
+
13
+ - **Plugin tools bridge: other plugins' custom tools are now exposed to the
14
+ Cursor agent.** Custom tools from installed opencode plugins (e.g.
15
+ `opencode-pty`'s `pty_spawn`, `context-mode`'s `ctx_*`) are bridged to
16
+ Cursor via an `opencode-plugin-tools` MCP server (hand-rolled stdio
17
+ JSON-RPC, no MCP SDK dependency, running under Bun). Permission handling
18
+ mirrors opencode's `Permission.evaluate` — last matching rule wins per ask
19
+ pattern; a rule resolving to `ask` (which can't prompt from Cursor) or no
20
+ match fails closed. Controlled by `forwardPluginTools` and
21
+ `pluginTools.include/exclude`.
22
+ - **Plugin-bundled skills are mirrored into `.cursor/skills/` too.** New
23
+ lowest-priority scan roots in `discoverSkills`: the opencode plugin cache
24
+ (`~/.cache/opencode/packages/`) and `skills/`/`skill/` dirs alongside
25
+ file-based plugins, handling npm and git plugin specs. The per-turn re-sync
26
+ also merges opencode's live skills inventory at the same priority. No new
27
+ config surface — folds into `forwardSkills`; `skills.include/exclude` and
28
+ permission filtering apply unchanged. Project/global skills always win on
29
+ duplicate ids; user-owned skills are never overwritten.
30
+ - **Dependency bumps:** `@opencode-ai/plugin` ^1.18.4 → ^1.18.21 (deps),
31
+ `@opencode-ai/sdk` ^1.18.18 → ^1.18.21 (dev). Consolidates dependabot
32
+ PRs #105 and #106.
33
+
7
34
  ## [0.8.0] — 2026-08-21
8
35
 
9
36
  Live Cursor subagent activity: the `task` card behaves like a native opencode
package/README.md CHANGED
@@ -158,6 +158,7 @@ The plugin also registers two **delegation tools**:
158
158
  > `edit: deny`, `bash: ask`) do **not** apply to them.
159
159
  >
160
160
  > Options if you need a permission boundary:
161
+ >
161
162
  > - Set `sandbox: true` in `provider.cursor.options` to run Cursor's tools in Cursor's sandbox.
162
163
  > - Use `cursor_delegate` instead of the provider path — it is gated by opencode's `permission`
163
164
  > config.
@@ -302,17 +303,34 @@ The mirror includes:
302
303
  - **Global skills** from `~/.config/opencode/skills/` and `~/.config/opencode/skill/`,
303
304
  `~/.claude/skills/`, `~/.agents/skills/`, `~/.opencode/skills/` and `~/.opencode/skill/`.
304
305
  - **Configured paths** from `config.skills.paths` in your `opencode.json` — additional
305
- directories scanned at the lowest priority (project and standard global locations
306
+ directories scanned at low priority (project and standard global locations
306
307
  win on duplicate ids). `~/` prefixes are expanded to your home directory; relative
307
308
  paths are resolved against the project directory.
309
+ - **Plugin-bundled skills** — skills that ship inside installed opencode plugins,
310
+ scanned from the opencode plugin cache (`~/.cache/opencode/packages/` on
311
+ macOS/Linux; `%LocalAppData%\opencode\cache\packages\` on Windows) and from
312
+ `skills/`/`skill/` dirs alongside file-based plugins
313
+ (`~/.config/opencode/plugin/`, `~/.config/opencode/plugins/`, and the project's
314
+ `.opencode/plugin/`). Handles npm specs (`pkg@latest`, `@scope/pkg@latest`) and
315
+ git specs (`pkg@git+https:...`). Plugin-bundled skills are the **lowest**
316
+ priority: a project, global, or `skills.paths` skill with the same id always
317
+ wins, so you can shadow a plugin's skill by defining your own.
318
+ - **opencode's live skill inventory** — on every turn the mirror also consults
319
+ opencode's `app.skills` endpoint (when reachable) and merges any skill it
320
+ knows about that the filesystem scan missed, at the same lowest priority.
321
+ - **opencode's built-in skills** — skills opencode registers in code rather
322
+ than on disk (currently `customize-opencode`, its own config-authoring
323
+ guide). They only exist in the live inventory, so the mirror materialises
324
+ them from the endpoint's content into `.cursor/skills/` like any other
325
+ skill; the materialised copy updates whenever opencode's version changes.
308
326
  - **Supporting files** alongside each `SKILL.md` (preserving relative paths).
309
327
  - An `<available_skills>` catalogue appended to the generated system rule,
310
328
  listing each skill's id and description so the Cursor agent can load them on
311
329
  demand.
312
330
 
313
- > **Note:** `config.skills.urls` (HTTP skill catalogs) are not yet supported by
314
- > the mirror. If you rely on URL-sourced skills, they will not appear in
315
- > `.cursor/skills/`.
331
+ > **Note:** URL-sourced skills (`config.skills.urls`) that are also present in
332
+ > opencode's live inventory reach the mirror through that route; the mirror
333
+ > does not fetch `skills.urls` catalogs on its own.
316
334
 
317
335
  ### Permission filtering
318
336
 
@@ -346,13 +364,12 @@ user explicitly asked for them). `exclude` always drops the listed skills.
346
364
 
347
365
  ### Limitations
348
366
 
349
- - **Skills bundled inside opencode plugins are not mirrored.** Those ship under
350
- `<opencode-package-cache>/<pkg>/node_modules/<pkg>/skills/` (on macOS/Linux
351
- `~/.cache/opencode/packages/`; on Windows `%LocalAppData%\opencode\cache\packages\`),
352
- which is not a scanned location — `@opencode-ai/sdk` exposes no skills API, so
353
- the mirror resolves skills from the filesystem itself. Skills that reach
354
- opencode only through a plugin will be absent from `.cursor/skills/`. To
355
- mirror one, add its directory to `config.skills.paths`.
367
+ - Skills served via `skills.urls` that opencode itself hasn't loaded (the
368
+ endpoint is reachable but the catalog wasn't pulled this session) won't
369
+ appear until opencode sees them.
370
+ - Built-in skills require the live `app.skills` endpoint (i.e. a running
371
+ opencode server reachable by this plugin); the filesystem scan can't see
372
+ them on its own.
356
373
  - A user-owned `.cursor/skills/<id>/SKILL.md` (without the `generated:
357
374
  opencode-cursor` sentinel) is never overwritten or deleted.
358
375
  - Individual files larger than 1 MB are skipped (the rest of the skill is still
@@ -362,6 +379,88 @@ user explicitly asked for them). `exclude` always drops the listed skills.
362
379
  any pre-existing `.cursor/skills/` there still loads).
363
380
  - `cursor_cloud_agent` targets a remote repo and does not inherit skills.
364
381
 
382
+ ## Plugin tools
383
+
384
+ Other opencode plugins can register custom tools (e.g. `opencode-pty`'s
385
+ `pty_spawn`, `context-mode`'s `ctx_execute`). With `forwardPluginTools: true`
386
+ (default), this plugin **mirrors those tools to the Cursor agent** via a local
387
+ stdio MCP server (`opencode-plugin-tools`) that is added to the forwarded
388
+ `mcpServers`. When the Cursor agent calls one, the call runs through the
389
+ plugin's *real* implementation inside opencode's runtime — same code path
390
+ opencode itself uses.
391
+
392
+ How it works:
393
+
394
+ 1. At startup (and re-checked each turn) the plugin reads your `plugin: []`
395
+ list, re-imports each plugin from the opencode package cache, and reads its
396
+ `tool` map. Plugins that can't be imported are skipped and logged once.
397
+ 2. A loopback-only HTTP control channel (random port, per-session bearer
398
+ token) connects the MCP child process to the host plugin, which owns the
399
+ tool closures. Nothing is reachable from outside the machine.
400
+ 3. The Cursor agent sees the tools through its normal MCP surface and calls
401
+ them like any other MCP tool.
402
+
403
+ ### Permissions
404
+
405
+ Mirrored calls are evaluated against your opencode `permission` config,
406
+ keyed by the tool id — with the same semantics opencode itself uses:
407
+ permission keys are wildcard-matched, and every pattern a tool's `ask`
408
+ requests is matched against the rule's pattern; the **last** matching rule
409
+ wins. `~`/`$HOME` prefixes in patterns expand against your home directory.
410
+
411
+ - **`allow`** → runs without prompting (every requested pattern must allow).
412
+ - **`deny`** → rejected.
413
+ - **`ask`** (or no rule) → rejected with a clear message. The interactive
414
+ prompt is anchored to opencode's session/TUI and can't be surfaced to the
415
+ Cursor agent, so ask-permissioned tools are withheld rather than run
416
+ unattended. Set the tool to `allow` to use it from Cursor:
417
+
418
+ ```json
419
+ { "permission": { "pty_spawn": "allow", "ctx_*": "allow" } }
420
+ ```
421
+
422
+ Pattern-scoped rules work too — e.g. allow spawning ptys only under `/tmp`
423
+ (specific patterns must come **after** the wildcard they narrow):
424
+
425
+ ```json
426
+ { "permission": { "pty_spawn": { "*": "ask", "/tmp/*": "allow" } } }
427
+ ```
428
+
429
+ If a tool's execution calls `ask` internally and no gate is available, the
430
+ call fails closed.
431
+
432
+ ### Filtering
433
+
434
+ ```json
435
+ {
436
+ "provider": {
437
+ "cursor": {
438
+ "options": {
439
+ "forwardPluginTools": true,
440
+ "pluginTools": {
441
+ "include": ["pty_*"],
442
+ "exclude": ["ctx_execute"]
443
+ }
444
+ }
445
+ }
446
+ }
447
+ }
448
+ ```
449
+
450
+ `include` keeps only matching tool ids (wildcards supported); `exclude` always
451
+ drops. `forwardPluginTools: false` disables the bridge entirely.
452
+
453
+ ### Limitations
454
+
455
+ - Plugins that fail to re-import under the bridge (e.g. native modules that
456
+ only load under Bun, or plugins that throw when initialised twice) are
457
+ skipped and reported in the opencode log; their tools stay unavailable to
458
+ Cursor. Skills and MCP servers from those plugins are unaffected.
459
+ - Tool definitions are snapshotted at startup and re-checked per turn; a
460
+ plugin installed mid-session is picked up on the next turn.
461
+ - `cursor_cloud_agent` targets a remote repo and does not inherit plugin
462
+ tools.
463
+
365
464
  ## Delegation tools
366
465
 
367
466
  Both tools resolve the API key from your `opencode auth login` session (or `CURSOR_API_KEY`) and