返回 DeepSeek-Reasonix
PLUGIN_PACKAGES.md
根目录 / docs / PLUGIN_PACKAGES.md
1 # Reasonix Plugin Packages
2
3 Reasonix plugin packages bundle skills, hooks, MCP servers, prompts, themes,
4 and code extensions behind one installable unit.
5
6 ## CLI Mode
7
8 Use `reasonix plugin` when installing or managing plugin packages from a
9 terminal. Plugin packages are installed globally under the Reasonix home
10 directory.
11
12 ### Install From CLI
13
14 `install` accepts one source:
15
16 - A GitHub repository, such as `git:github.com/obra/superpowers` or
17 `https://github.com/obra/superpowers`.
18 - A GitHub branch or subdirectory URL, such as
19 `https://github.com/owner/repo/tree/main/path/to/plugin`.
20 - A local directory that contains `reasonix-plugin.json`,
21 `.codex-plugin/plugin.json`, or `.claude-plugin/plugin.json`.
22
23 Preview the install plan without writing files:
24
25 ```bash
26 reasonix plugin install git:github.com/obra/superpowers --dry-run
27 ```
28
29 Install a plugin after reviewing the plan:
30
31 ```bash
32 reasonix plugin install git:github.com/obra/superpowers --yes
33 ```
34
35 Install with an explicit name or replace an installed plugin with the same name:
36
37 ```bash
38 reasonix plugin install git:github.com/obra/superpowers --name superpowers --replace --yes
39 ```
40
41 Use a local directory in developer mode:
42
43 ```bash
44 reasonix plugin install /path/to/plugin --link --replace --yes
45 ```
46
47 CLI install flags:
48
49 - `--dry-run` plans and validates the install without writing files.
50 - `--yes` is required for any install that writes files.
51 - `--replace` allows the source to replace an installed plugin with the same
52 name.
53 - `--name <name>` or `--name=<name>` overrides the name from the plugin
54 manifest for this install.
55 - `--link` links a local plugin directory instead of copying it into Reasonix's
56 plugin storage. Moving or deleting that directory breaks the linked plugin.
57
58 Running `reasonix plugin install <source>` without `--dry-run` or `--yes`
59 refuses to write files and prints a reminder to rerun with one of those flags.
60 Install and remove commands print the structured JSON response from the same
61 install-source backend used by the desktop UI.
62
63 Installed plugin state is stored in:
64
65 ```text
66 ~/.reasonix/plugin-packages.json
67 ~/.reasonix/plugins/<name>/
68 ```
69
70 ### Manage From CLI
71
72 List installed plugins:
73
74 ```bash
75 reasonix plugin list
76 ```
77
78 Show one plugin's metadata, root, source, and exported capability counts:
79
80 ```bash
81 reasonix plugin show superpowers
82 ```
83
84 `show` also prints the concrete capability inventory when available:
85
86 - **skills** include suggested `/<plugin>:<skill>` invocations and descriptions.
87 - **commands** include `/<plugin>:<command>` invocations, argument hints, and
88 descriptions.
89 - **hooks** list lifecycle events, matchers, and commands or context files.
90 - **mcpServers** list server names, transports, and launch targets.
91
92 Check that the manifest and skill roots are readable:
93
94 ```bash
95 reasonix plugin doctor superpowers
96 ```
97
98 For a workspace-wide capability report (skills, hooks, MCP merge, package roots), see
99 [Capability diagnostics](./CAPABILITY_DIAGNOSTICS.md):
100
101 ```bash
102 reasonix doctor capabilities --json
103 # Desktop: Settings → Diagnostics
104 # Agent: /reasonix-guide
105 ```
106
107 Enable or disable a plugin without uninstalling it:
108
109 ```bash
110 reasonix plugin disable superpowers
111 reasonix plugin enable superpowers
112 ```
113
114 Remove a plugin:
115
116 ```bash
117 reasonix plugin remove superpowers --yes
118 ```
119
120 `remove` also accepts `uninstall` as an alias. It requires `--yes` because it
121 writes state and removes copied plugin content. For linked local plugins, the
122 external source directory is left in place.
123
124 ### Use Installed Plugins From CLI
125
126 Installed plugins do not open a separate chat surface. When a plugin is enabled,
127 Reasonix loads its capabilities into normal interactive sessions:
128
129 - Run `/plugins` inside an interactive session to list installed plugin
130 packages. Run `/plugins show <name>` to inspect a plugin's exported skills,
131 hooks, MCP servers, and usage hints without leaving the chat.
132 - **Skills** appear in `/skills`. Invoke a plugin skill with
133 `/<plugin>:<skill> [args]`, or ask
134 naturally and let the agent choose a matching skill by description.
135 - **Hooks** run automatically at their configured lifecycle events, such as
136 `SessionStart`, `UserPromptSubmit`, `PreToolUse`, or `PostToolUse`.
137 - **MCP servers** join the normal MCP/tool flow. Ask for the task you want done;
138 Reasonix can call the plugin's tools when they are relevant.
139
140 After installing, enabling, disabling, or updating a plugin from a separate
141 terminal while a session is already running, start a new `reasonix` session or
142 reopen `/skills` to verify the current session sees the expected skills.
143
144 ## Desktop Settings
145
146 Open **Settings -> Plugins** to install and manage plugin packages without using
147 the CLI.
148
149 ### Install Plugins
150
151 The installer has two modes:
152
153 - **Local folder**: click **Choose plugin folder** and select a plugin directory
154 on disk. The selected path is shown next to the button.
155 - **Git repository**: enter a Git source such as
156 `git:github.com/obra/superpowers`. **Install name (optional)** can override
157 the plugin manifest name for this install or overwrite.
158
159 Use the action buttons after choosing the source and options:
160
161 - **Preview** validates the source and shows the planned install actions without
162 writing files.
163 - **Install plugin** installs the selected source using the current options.
164 - **Refresh plugins** reloads the installed-plugin list from disk and config.
165
166 Installer options:
167
168 - **Overwrite same-name plugin** allows the current source to replace an
169 installed plugin with the same name. Leave it off when duplicate-name installs
170 should fail instead of replacing existing content.
171 - **Developer mode: link source folder** appears for **Local folder** installs.
172 It links the selected directory instead of copying it into Reasonix's plugin
173 storage. Use it while developing or debugging a plugin. Moving or deleting the
174 selected directory will break the linked plugin.
175
176 Preview is the safest first step for a new Git source or local plugin directory.
177
178 ### Manage Installed Plugins
179
180 The installed-plugin list shows each plugin package and its exported skills,
181 hooks, and MCP servers. Use **Refresh plugins** after editing plugin files or
182 changing config outside the app.
183
184 Expand a plugin row to manage it:
185
186 - Enable or disable the plugin.
187 - Read **How to use** for the plugin's exported skills, hooks, and MCP servers.
188 - **Update** pulls or refreshes an installed plugin when an update source is
189 available.
190 - **Doctor** checks the plugin manifest and reports warnings or diagnostics.
191 - **Remove plugin** uninstalls the package after confirmation.
192
193 ### Use Installed Plugins From Desktop
194
195 The desktop settings page uses the same runtime model as the CLI:
196
197 - Expand an installed plugin to see its **How to use** section.
198 - In any desktop session, type `/plugins` to list installed plugins, or
199 `/plugins show <name>` to see the same usage details from the chat surface.
200 - Skills are shown with package-qualified direct commands such as
201 `/superpowers:writing-plans`; they are also discoverable from `/skills` in a
202 session.
203 - Plugin commands are shown and invoked with package-qualified names such as
204 `/superpowers:plan`.
205 - Hooks and MCP servers are listed for transparency. They do not need a manual
206 "run" button: enabled hooks trigger automatically, and MCP tools are available
207 through ordinary tool use.
208 - If a currently open session does not reflect a plugin change, refresh the
209 plugin list and open a new session.
210
211 ## Native Manifest
212
213 Reasonix plugins can declare `reasonix-plugin.json` at the plugin root:
214
215 ```json
216 {
217 "name": "example",
218 "version": "1.0.0",
219 "description": "Example plugin",
220 "skills": "skills",
221 "hooks": {
222 "SessionStart": [
223 {
224 "command": "hooks/session-start",
225 "args": [],
226 "description": "Load startup context"
227 },
228 {
229 "command": "printf 'ready' && ./hooks/audit",
230 "shell": "bash",
231 "description": "Run a compound shell script"
232 }
233 ]
234 },
235 "mcpServers": {
236 "helper": {
237 "command": "bin/helper"
238 }
239 }
240 }
241 ```
242
243 Relative paths are resolved inside the plugin root. Reasonix does not run
244 third-party install scripts during plugin installation.
245
246 Plugin hook execution is explicit:
247
248 - When `args` is present, including `"args": []`, the hook uses **exec form**.
249 `command` is the executable and every argument is passed literally, without
250 shell parsing or interpolation.
251 - When `args` is absent and `shell` is present, the hook uses **shell form**.
252 The complete `command` is handed unchanged to `bash`, `powershell`/`pwsh`,
253 `cmd` (Windows only), or `auto`. On Windows, `auto` prefers Git Bash and
254 falls back to PowerShell.
255 - Existing native hooks that declare neither field keep the historical
256 Reasonix shell-command behavior. `shellCommand: true` remains supported as
257 the legacy spelling of shell form.
258
259 ## Manifest v2 (Extensions)
260
261 Native Reasonix extensions use the exact v2 `apiVersion`:
262
263 ```json
264 {
265 "apiVersion": "reasonix.io/plugin/v2",
266 "name": "example",
267 "version": "1.0.0",
268 "description": "Example extension",
269 "requires": [],
270 "provides": [
271 {
272 "namespace": "plugin/example",
273 "kind": "interceptors",
274 "id": "default",
275 "version": "1.0.0"
276 }
277 ],
278 "contributes": {
279 "skills": ["skills"],
280 "agents": ["agents"],
281 "commands": ["commands"],
282 "prompts": ["prompts"],
283 "hooks": {},
284 "mcpServers": {},
285 "themes": ["themes/*.reasonix-theme"]
286 },
287 "runtime": {
288 "command": "${REASONIX_PLUGIN_ROOT}/bin/example",
289 "args": [],
290 "env": {},
291 "required": true,
292 "priority": 0,
293 "intercepts": ["input.receive", "tool.before"],
294 "replaces": [],
295 "capabilities": ["interceptors"]
296 }
297 }
298 ```
299
300 Parsing rules:
301
302 - Native `reasonix-plugin.json` manifests must declare the exact
303 `reasonix.io/plugin/v2` value. v1 and missing versions are rejected; there
304 is no v1 dual-read or automatic migration path.
305 - v2 is strict: any unknown field — at the root or nested under
306 `contributes`/`runtime` — is an error naming the field path, so typos fail
307 loudly instead of silently disabling a capability.
308 - v2 resource discovery is explicit. Reasonix loads only the skills, agents,
309 commands, prompts, hooks, MCP servers, themes, and runtime declared by the
310 native manifest. Host-specific sidecars such as a root `CLAUDE.md`,
311 `hooks/hooks.json`, `.claude/settings.json`, or `.mcp.json` are not imported
312 implicitly.
313 - Minor aliases (`reasonix.io/plugin/v2.0`, `v2.1`, …) and unknown major
314 versions are rejected.
315 - `requires` and `provides` declare dependency constraints and the capability
316 ceiling enforced against the Sidecar handshake.
317 - v2 may mix the supported top-level resource fields (`skills`, `hooks`,
318 `mcpServers`, …)
319 with `contributes`: identical paths are deduplicated; the same key with two
320 different definitions is a manifest error naming the key.
321 - All relative paths and globs must stay inside the plugin root: traversal,
322 absolute paths, escaping symlinks, and non-regular theme files are
323 rejected.
324
325 New resource types:
326
327 - `prompts` are prompt templates using the same semantics and argument
328 substitution as commands, invoked as `/<plugin>:<name>`. `commands` remains
329 a compatible alias.
330 - `themes` are `.reasonix-theme` files shown read-only in Desktop Settings as
331 plugin themes (IDs `plugin:<plugin>:<theme>`); they are never copied into
332 the user theme library. If the plugin is disabled or uninstalled while its
333 theme is active, the desktop falls back to the base style but keeps the
334 ID, so reinstalling the same plugin restores the theme.
335
336 The `runtime` block declares a code extension — a sidecar process Reasonix
337 launches and talks to over the Extension Protocol (JSON-RPC 2.0 over stdio;
338 see `docs/EXTENSION_PROTOCOL.generated.md` for the method index and
339 `sdk/go/README.md` for the Go SDK):
340
341 - `command`/`args`/`env` are **exec form only** — the command is the
342 executable (never shell-interpreted); `${REASONIX_PLUGIN_ROOT}` expands to
343 the installed plugin root.
344 - `intercepts` lists the events the extension wants to intercept (for example
345 `input.receive`, `tool.before`, `permission.decision`); `replaces` declares
346 the replacement slots it may own (`system_prompt`, `context`,
347 `provider_request`, `provider_response`, `compaction`, `session_policy`,
348 `permission`, `frontend_events`, `tool:<name>`, `provider:<ref>`). Each
349 slot has exactly one owner across all installed plugins; a collision fails
350 the build with both sources named.
351 - `capabilities` gates whole feature families: `interceptors`, `strategies`,
352 `providers`, `ui`. Anything the sidecar announces beyond the manifest is
353 rejected during the handshake.
354 - Provider models contributed by an extension appear as
355 `plugin/<plugin>/<provider>/<model>` in the model picker; the ref also
356 works as `default_model` (including on first boot) and in `/model`,
357 Desktop, and ACP model switches.
358
359 **Full trust.** A code extension runs outside the sandbox with the
360 unfiltered inherited environment. It can read the full session and
361 environment, bypass permissions, and operate the machine directly; a
362 `permission.decision` "allow" from an extension overrides a host deny.
363 Installing, updating, replacing, or `--link`ing a plugin with a `runtime`
364 block *is* the authorization — there is no second confirmation prompt, and
365 `--link` keeps trusting changed content automatically. The install preview,
366 `reasonix plugin show`, capability diagnostics, and the Desktop installer
367 therefore display a prominent `FULL TRUST` block with the runtime command,
368 interceptors, replacement slots, and provider/UI capabilities. Review that
369 block before installing, and only install runtimes you trust completely.
370 Only plugins installed through the plugin flow can start a runtime; project
371 configuration can never declare one.
372
373 ## Codex & Claude Compatibility
374
375 Reasonix also reads Codex plugin manifests at `.codex-plugin/plugin.json` and
376 Claude plugin manifests at `.claude-plugin/plugin.json`. The install preview
377 reports `full`, `partial`, or `none` compatibility, lists mapped capabilities,
378 and identifies every skipped entry. A non-native package with no mapped
379 capabilities is blocked instead of being recorded as an unusable installation.
380 `full` means every declared capability in the manifest parsed and mapped to a
381 Reasonix construct; it does not by itself guarantee every runtime decision an
382 imported hook can make is honored. `PreToolUse`/`PermissionRequest` "deny" and
383 `PermissionRequest` "allow" are implemented, but a hook's `updatedInput` or
384 `PreToolUse`'s `ask`/`defer` decisions are chosen by the script's stdout at
385 call time, not by anything in the manifest, so they can't be flagged during
386 install; see the hook bullet below for what's implemented.
387 GitHub-hosted multi-plugin marketplaces with a
388 `.claude-plugin/marketplace.json` can be installed from the repository root
389 when their plugin entries use relative string sources such as
390 `./plugins/example` or `plugins/example`; preview shows one action per plugin
391 before anything is written. Set the optional install name to a marketplace
392 plugin name to select only that entry. Object sources are accepted only for a
393 GitHub repository URL pinned to a full commit SHA. Unpinned external strings,
394 npm, `strict: false`, and other advanced marketplace protocols are skipped in
395 a bulk install and rejected when selected by name. For packages such as
396 Superpowers and Claude-style skill packs, Reasonix maps the following
397 compatibility conventions. Native v2 manifests use only their explicit
398 declarations and do not apply these fallbacks:
399
400 - `skills` to Reasonix skill roots. A Claude manifest that declares no
401 `skills` field falls back to the conventional `skills/` (or `.claude/skills/`)
402 directory, matching Claude's own auto-discovery. Plugin skills are displayed
403 and invoked canonically as `/<plugin>:<skill>`. An unambiguous `/<skill>` is
404 still accepted as a hidden compatibility alias; project and user skills keep
405 their short names, while same-name skills from multiple plugins remain
406 independently addressable only by their qualified names. This user-facing
407 namespace does not change the bare skill identifiers in the model skill index
408 or the `run_skill` tool.
409 - `commands/` (and `.claude/commands/`) to Reasonix custom slash commands: each
410 `<name>.md` prompt template is displayed and invoked canonically as
411 `/<plugin>:<name>`, with frontmatter `description` / `argument-hint` and
412 `$ARGUMENTS` / `$1..$N` substitution honored. An unambiguous `/<name>` remains
413 accepted as a hidden compatibility alias, but it is omitted from completion,
414 help, desktop menus, ACP command discovery, and the model-visible command
415 list. User- and project-authored commands own their short names, and no short
416 alias is created when multiple plugins export the same command name. An
417 explicit custom command can also occupy the qualified name; desktop plugin
418 details report that conflict. Native `reasonix-plugin.json` manifests can
419 declare the same thing explicitly with a `"commands"` path list.
420 - `agents/*.md` to manually invoked, plugin-owned subagent profiles. Claude
421 model aliases inherit the active Reasonix model; inline `tools` lists map to
422 Reasonix tool names, including wildcard MCP names such as `mcp__*__search`.
423 Agents use `/<plugin>:agent:<name>`, so an upstream agent and skill may share
424 the same name without shadowing one another.
425 - `hooks/session-start-codex` to the Reasonix `SessionStart` hook when present.
426 - For Codex compatibility packages, a plugin-root `CLAUDE.md` file to a built-in
427 `SessionStart` context hook. The file is read directly by Reasonix, without
428 spawning a shell command. Claude plugin manifests ignore this file, matching
429 Claude Code's plugin contract.
430 - `.claude/settings.json` and `hooks/hooks.json` command hooks to Reasonix hook
431 events when the event names match. `matcher`, `args`, `shell`, `async`,
432 `env`, and timeout are preserved. Claude's execution contract is retained:
433 an `args` field (even an empty array) selects exec form and preserves every
434 argument literally; omitting `args` selects shell form and passes the raw
435 command to the declared Bash or PowerShell interpreter. `matcher` and the
436 `tool_name` a hook script sees are
437 translated between Reasonix's own tool names and Claude's (`bash` ↔
438 `Bash`, `write_file` ↔ `Write`, ...), so a matcher like `"Bash"` fires
439 correctly; every Reasonix subagent-spawning tool (`task`, `read_only_task`,
440 `parallel_tasks`, and the dedicated `explore`/`research`/`review`/
441 `security_review` wrappers) maps to Claude's single `Agent` tool, and a
442 matcher can still use the legacy `Task` name. Every mapped `Agent` payload
443 includes Claude's required `prompt` and `description`; Reasonix supplies a
444 stable operation label when its tool call omitted the optional description.
445 `tool_input` keys that
446 Reasonix names differently from Claude are renamed too — `path` becomes
447 `file_path` for `Read`/`Write`/`Edit`/`MultiEdit` and `notebook_path` for
448 `NotebookEdit`, `name`/`arguments` become `skill`/`args` for `Skill`,
449 `job_id` becomes `task_id` for the current `TaskOutput`/`TaskStop`, the
450 dedicated subagent wrappers' `task` becomes `Agent`'s `prompt`, and
451 `parallel_tasks` synthesizes `Agent`'s `prompt` from its sub-task prompts
452 (keeping `tasks` alongside) — so a guard reading `.tool_input.file_path`
453 or `.tool_input.prompt` sees the target instead of failing open on an
454 empty value. Legacy `BashOutput`/`KillShell` matchers still fire while the
455 emitted names and fields use current Claude vocabulary. `bash_output`
456 supplies `TaskOutput`'s required non-blocking fields; `wait` also maps to
457 `TaskOutput`, including `task_id` when it waits for exactly one job, and
458 omits `TaskOutput`'s optional `timeout` for an unbounded wait rather than
459 claiming a `0`ms budget.
460 `AskUserQuestion` supplies omitted `multiSelect:false` and empty option
461 descriptions. `TodoWrite` accepts only flat `content` and `status` items; legacy `activeForm` is rejected by strict
462 validation. `NotebookEdit` also supplies `new_source` from Reasonix's
463 accepted aliases, or an empty string for delete/empty-cell operations.
464 Relative `file_path`/`notebook_path` values are resolved
465 absolute against the payload `cwd`, matching Claude's file-tool contract,
466 so prefix-matching guards inspect the path the tool actually accesses. A
467 `Bash` `tool_response` is delivered in Claude's `{stdout, stderr,
468 interrupted}` shape (Reasonix combines both streams into `stdout`; the
469 failure error text becomes `stderr`), which the official security-guidance
470 plugin's commit/push checks read; other tools' responses pass through as
471 the raw result. Imported hooks receive Claude-compatible snake_case stdin
472 payloads, including `hook_event_name`. Before process launch, the host
473 expands `${CLAUDE_PLUGIN_ROOT}` and `${REASONIX_PLUGIN_ROOT}` (plus their
474 unbraced `$NAME` and Windows `%NAME%` spellings), so plugin-relative paths
475 do not depend on the target shell's environment-variable syntax. On Windows,
476 shell-form hooks without an explicit shell use the same Git Bash-first,
477 PowerShell-fallback selection as Reasonix's shell tool; when a hook points to
478 a POSIX-shebang script file, the host also converts Windows paths to a Bash-
479 compatible form. Explicit Bash hooks
480 and legacy bare `sh -c`/`bash -c` hooks are routed through a discovered Git
481 for Windows Bash even when it is not on `cmd.exe`'s `PATH`; an explicit
482 interpreter path remains untouched. If no usable Bash is installed, the hook
483 reports a clear prerequisite error instead of the localized `sh is not
484 recognized` output. A non-standard or portable Bash configured with
485 `[tools.shell] prefer = "bash"` and `path = ".../bash.exe"` is reused by
486 explicit Bash hooks. `reasonix plugin doctor <name>` and
487 `reasonix doctor capabilities` report a missing required shell before the
488 first hook invocation. Captured legacy-code-page output is normalized to
489 UTF-8 before it reaches the UI. A `PreToolUse` or
490 `UserPromptSubmit` hook can still deny via exit code 2 or its JSON deny
491 shape on exit 0 (`hookSpecificOutput.permissionDecision` for `PreToolUse`,
492 top-level `decision:"block"` for `UserPromptSubmit`); an imported
493 `PermissionRequest` hook additionally answers the permission dialog itself
494 (deny or auto-allow, rather than only notifying) via exit code 2 or
495 `hookSpecificOutput.decision.behavior`, matching Claude's own contract.
496 `updatedInput` is not yet applied to the tool call, and a hook's `if`
497 condition or `asyncRewake` field is not evaluated. A package reports partial
498 compatibility with a structured warning when it declares either field, a
499 `Stop`/`SubagentStop` hook (which cannot block the turn in Reasonix), or a
500 matcher that covers one of three inputs Reasonix cannot losslessly express:
501 `WebFetch.prompt`, `NotebookEdit.cell_id` for a Reasonix `cell_number` call,
502 or `TaskOutput.task_id` when Reasonix `wait` covers multiple/all jobs. Each
503 structural gap is reported once per hooks file, so a wildcard-matcher
504 plugin sees one warning per gap instead of one per hook.
505 - A plugin-root `.mcp.json` to installed MCP entries. Claude `local` maps to
506 stdio, non-ASCII display names receive stable internal IDs, and duplicate
507 declarations are deduplicated. Imported servers default to
508 `auto_start=false`; users connect them on demand so startup does not change
509 the provider-visible tool schema.
510
511 Unsupported Claude hook item types are skipped with a warning. Reasonix does not
512 run third-party install scripts.
513
514 Plugin hooks receive these environment variables:
515
516 - `REASONIX_PLUGIN_ROOT`
517 - `REASONIX_PLUGIN_NAME`
518 - `REASONIX_PLUGIN_VERSION`
519 - `REASONIX_HOME`
520 - `REASONIX_WORKSPACE_ROOT`
521 - `CLAUDE_PROJECT_DIR`
522 - `CLAUDE_PLUGIN_ROOT`
523
524 ## Desktop Backend Methods
525
526 Desktop exposes plugin package operations through host commands:
527
528 - `Plugins`
529 - `PlanPluginInstall`
530 - `InstallPlugin`
531 - `RemovePlugin`
532 - `SetPluginEnabled`
533 - `UpdatePlugin`
534 - `PluginDoctor`
535
535 lines MARKDOWN