返回 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 v1 (Extensions)
260
261 A plugin can opt into the v1 manifest by declaring an `apiVersion`:
262
263 ```json
264 {
265 "apiVersion": "reasonix.io/plugin/v1",
266 "name": "example",
267 "version": "1.0.0",
268 "description": "Example extension",
269 "contributes": {
270 "skills": ["skills"],
271 "agents": ["agents"],
272 "commands": ["commands"],
273 "prompts": ["prompts"],
274 "hooks": {},
275 "mcpServers": {},
276 "themes": ["themes/*.reasonix-theme"]
277 },
278 "runtime": {
279 "command": "${REASONIX_PLUGIN_ROOT}/bin/example",
280 "args": [],
281 "env": {},
282 "required": true,
283 "priority": 0,
284 "intercepts": ["input.receive", "tool.before"],
285 "replaces": ["system_prompt"],
286 "capabilities": ["interceptors", "strategies", "providers", "ui"]
287 }
288 }
289 ```
290
291 Parsing rules:
292
293 - Manifests **without** `apiVersion` parse exactly as before (legacy format,
294 unknown fields ignored).
295 - v1 is strict: any unknown field — at the root or nested under
296 `contributes`/`runtime` — is an error naming the field path, so typos fail
297 loudly instead of silently disabling a capability.
298 - Unknown major versions (`reasonix.io/plugin/v2`, …) are rejected.
299 - v1 may mix legacy top-level fields (`skills`, `hooks`, `mcpServers`, …)
300 with `contributes`: identical paths are deduplicated; the same key with two
301 different definitions is a manifest error naming the key.
302 - All relative paths and globs must stay inside the plugin root: traversal,
303 absolute paths, escaping symlinks, and non-regular theme files are
304 rejected.
305
306 New resource types:
307
308 - `prompts` are prompt templates using the same semantics and argument
309 substitution as commands, invoked as `/<plugin>:<name>`. `commands` remains
310 a compatible alias.
311 - `themes` are `.reasonix-theme` files shown read-only in Desktop Settings as
312 plugin themes (IDs `plugin:<plugin>:<theme>`); they are never copied into
313 the user theme library. If the plugin is disabled or uninstalled while its
314 theme is active, the desktop falls back to the base style but keeps the
315 ID, so reinstalling the same plugin restores the theme.
316
317 The `runtime` block declares a code extension — a sidecar process Reasonix
318 launches and talks to over the Extension Protocol (JSON-RPC 2.0 over stdio;
319 see `docs/EXTENSION_PROTOCOL.generated.md` for the method index and
320 `sdk/go/README.md` for the Go SDK):
321
322 - `command`/`args`/`env` are **exec form only** — the command is the
323 executable (never shell-interpreted); `${REASONIX_PLUGIN_ROOT}` expands to
324 the installed plugin root.
325 - `intercepts` lists the events the extension wants to intercept (for example
326 `input.receive`, `tool.before`, `permission.decision`); `replaces` declares
327 the replacement slots it may own (`system_prompt`, `context`,
328 `provider_request`, `provider_response`, `compaction`, `session_policy`,
329 `permission`, `frontend_events`, `tool:<name>`, `provider:<ref>`). Each
330 slot has exactly one owner across all installed plugins; a collision fails
331 the build with both sources named.
332 - `capabilities` gates whole feature families: `interceptors`, `strategies`,
333 `providers`, `ui`. Anything the sidecar announces beyond the manifest is
334 rejected during the handshake.
335 - Provider models contributed by an extension appear as
336 `plugin/<plugin>/<provider>/<model>` in the model picker; the ref also
337 works as `default_model` (including on first boot) and in `/model`,
338 Desktop, and ACP model switches.
339
340 **Full trust.** A code extension runs outside the sandbox with the
341 unfiltered inherited environment. It can read the full session and
342 environment, bypass permissions, and operate the machine directly; a
343 `permission.decision` "allow" from an extension overrides a host deny.
344 Installing, updating, replacing, or `--link`ing a plugin with a `runtime`
345 block *is* the authorization — there is no second confirmation prompt, and
346 `--link` keeps trusting changed content automatically. The install preview,
347 `reasonix plugin show`, capability diagnostics, and the Desktop installer
348 therefore display a prominent `FULL TRUST` block with the runtime command,
349 interceptors, replacement slots, and provider/UI capabilities. Review that
350 block before installing, and only install runtimes you trust completely.
351 Only plugins installed through the plugin flow can start a runtime; project
352 configuration can never declare one.
353
354 ## Codex & Claude Compatibility
355
356 Reasonix also reads Codex plugin manifests at `.codex-plugin/plugin.json` and
357 Claude plugin manifests at `.claude-plugin/plugin.json`. The install preview
358 reports `full`, `partial`, or `none` compatibility, lists mapped capabilities,
359 and identifies every skipped entry. A non-native package with no mapped
360 capabilities is blocked instead of being recorded as an unusable installation.
361 `full` means every declared capability in the manifest parsed and mapped to a
362 Reasonix construct; it does not by itself guarantee every runtime decision an
363 imported hook can make is honored. `PreToolUse`/`PermissionRequest` "deny" and
364 `PermissionRequest` "allow" are implemented, but a hook's `updatedInput` or
365 `PreToolUse`'s `ask`/`defer` decisions are chosen by the script's stdout at
366 call time, not by anything in the manifest, so they can't be flagged during
367 install; see the hook bullet below for what's implemented.
368 GitHub-hosted multi-plugin marketplaces with a
369 `.claude-plugin/marketplace.json` can be installed from the repository root
370 when their plugin entries use relative string sources such as
371 `./plugins/example` or `plugins/example`; preview shows one action per plugin
372 before anything is written. Set the optional install name to a marketplace
373 plugin name to select only that entry. Object sources are accepted only for a
374 GitHub repository URL pinned to a full commit SHA. Unpinned external strings,
375 npm, `strict: false`, and other advanced marketplace protocols are skipped in
376 a bulk install and rejected when selected by name. For packages
377 such as Superpowers and Claude-style skill packs, Reasonix maps:
378
379 - `skills` to Reasonix skill roots. A Claude manifest that declares no
380 `skills` field falls back to the conventional `skills/` (or `.claude/skills/`)
381 directory, matching Claude's own auto-discovery. Plugin skills are displayed
382 and invoked canonically as `/<plugin>:<skill>`. An unambiguous `/<skill>` is
383 still accepted as a hidden compatibility alias; project and user skills keep
384 their short names, while same-name skills from multiple plugins remain
385 independently addressable only by their qualified names. This user-facing
386 namespace does not change the bare skill identifiers in the model skill index
387 or the `run_skill` tool.
388 - `commands/` (and `.claude/commands/`) to Reasonix custom slash commands: each
389 `<name>.md` prompt template is displayed and invoked canonically as
390 `/<plugin>:<name>`, with frontmatter `description` / `argument-hint` and
391 `$ARGUMENTS` / `$1..$N` substitution honored. An unambiguous `/<name>` remains
392 accepted as a hidden compatibility alias, but it is omitted from completion,
393 help, desktop menus, ACP command discovery, and the model-visible command
394 list. User- and project-authored commands own their short names, and no short
395 alias is created when multiple plugins export the same command name. An
396 explicit custom command can also occupy the qualified name; desktop plugin
397 details report that conflict. Native `reasonix-plugin.json` manifests can
398 declare the same thing explicitly with a `"commands"` path list.
399 - `agents/*.md` to manually invoked, plugin-owned subagent profiles. Claude
400 model aliases inherit the active Reasonix model; inline `tools` lists map to
401 Reasonix tool names, including wildcard MCP names such as `mcp__*__search`.
402 Agents use `/<plugin>:agent:<name>`, so an upstream agent and skill may share
403 the same name without shadowing one another.
404 - `hooks/session-start-codex` to the Reasonix `SessionStart` hook when present.
405 - A plugin-root `CLAUDE.md` file to a built-in `SessionStart` context hook. The
406 file is read directly by Reasonix, without spawning a shell command.
407 - `.claude/settings.json` and `hooks/hooks.json` command hooks to Reasonix hook
408 events when the event names match. `matcher`, `args`, `shell`, `async`,
409 `env`, and timeout are preserved. Claude's execution contract is retained:
410 an `args` field (even an empty array) selects exec form and preserves every
411 argument literally; omitting `args` selects shell form and passes the raw
412 command to the declared Bash or PowerShell interpreter. `matcher` and the
413 `tool_name` a hook script sees are
414 translated between Reasonix's own tool names and Claude's (`bash` ↔
415 `Bash`, `write_file` ↔ `Write`, ...), so a matcher like `"Bash"` fires
416 correctly; every Reasonix subagent-spawning tool (`task`, `read_only_task`,
417 `parallel_tasks`, and the dedicated `explore`/`research`/`review`/
418 `security_review` wrappers) maps to Claude's single `Agent` tool, and a
419 matcher can still use the legacy `Task` name. Every mapped `Agent` payload
420 includes Claude's required `prompt` and `description`; Reasonix supplies a
421 stable operation label when its tool call omitted the optional description.
422 `tool_input` keys that
423 Reasonix names differently from Claude are renamed too — `path` becomes
424 `file_path` for `Read`/`Write`/`Edit`/`MultiEdit` and `notebook_path` for
425 `NotebookEdit`, `name`/`arguments` become `skill`/`args` for `Skill`,
426 `job_id` becomes `task_id` for the current `TaskOutput`/`TaskStop`, the
427 dedicated subagent wrappers' `task` becomes `Agent`'s `prompt`, and
428 `parallel_tasks` synthesizes `Agent`'s `prompt` from its sub-task prompts
429 (keeping `tasks` alongside) — so a guard reading `.tool_input.file_path`
430 or `.tool_input.prompt` sees the target instead of failing open on an
431 empty value. Legacy `BashOutput`/`KillShell` matchers still fire while the
432 emitted names and fields use current Claude vocabulary. `bash_output`
433 supplies `TaskOutput`'s required non-blocking fields; `wait` also maps to
434 `TaskOutput`, including `task_id` when it waits for exactly one job, and
435 omits `TaskOutput`'s optional `timeout` for an unbounded wait rather than
436 claiming a `0`ms budget.
437 `AskUserQuestion` supplies omitted `multiSelect:false` and empty option
438 descriptions, while `TodoWrite` derives an omitted `activeForm` from the
439 task content. `NotebookEdit` also supplies `new_source` from Reasonix's
440 accepted aliases, or an empty string for delete/empty-cell operations.
441 Relative `file_path`/`notebook_path` values are resolved
442 absolute against the payload `cwd`, matching Claude's file-tool contract,
443 so prefix-matching guards inspect the path the tool actually accesses. A
444 `Bash` `tool_response` is delivered in Claude's `{stdout, stderr,
445 interrupted}` shape (Reasonix combines both streams into `stdout`; the
446 failure error text becomes `stderr`), which the official security-guidance
447 plugin's commit/push checks read; other tools' responses pass through as
448 the raw result. Imported hooks receive Claude-compatible snake_case stdin
449 payloads, including `hook_event_name`. Before process launch, the host
450 expands `${CLAUDE_PLUGIN_ROOT}` and `${REASONIX_PLUGIN_ROOT}` (plus their
451 unbraced `$NAME` and Windows `%NAME%` spellings), so plugin-relative paths
452 do not depend on the target shell's environment-variable syntax. On Windows,
453 shell-form hooks without an explicit shell use the same Git Bash-first,
454 PowerShell-fallback selection as Reasonix's shell tool. Explicit Bash hooks
455 and legacy bare `sh -c`/`bash -c` hooks are routed through a discovered Git
456 for Windows Bash even when it is not on `cmd.exe`'s `PATH`; an explicit
457 interpreter path remains untouched. If no usable Bash is installed, the hook
458 reports a clear prerequisite error instead of the localized `sh is not
459 recognized` output. A non-standard or portable Bash configured with
460 `[tools.shell] prefer = "bash"` and `path = ".../bash.exe"` is reused by
461 explicit Bash hooks. `reasonix plugin doctor <name>` and
462 `reasonix doctor capabilities` report a missing required shell before the
463 first hook invocation. Captured legacy-code-page output is normalized to
464 UTF-8 before it reaches the UI. A `PreToolUse` or
465 `UserPromptSubmit` hook can still deny via exit code 2 or its JSON deny
466 shape on exit 0 (`hookSpecificOutput.permissionDecision` for `PreToolUse`,
467 top-level `decision:"block"` for `UserPromptSubmit`); an imported
468 `PermissionRequest` hook additionally answers the permission dialog itself
469 (deny or auto-allow, rather than only notifying) via exit code 2 or
470 `hookSpecificOutput.decision.behavior`, matching Claude's own contract.
471 `updatedInput` is not yet applied to the tool call, and a hook's `if`
472 condition or `asyncRewake` field is not evaluated. A package reports partial
473 compatibility with a structured warning when it declares either field, a
474 `Stop`/`SubagentStop` hook (which cannot block the turn in Reasonix), or a
475 matcher that covers one of three inputs Reasonix cannot losslessly express:
476 `WebFetch.prompt`, `NotebookEdit.cell_id` for a Reasonix `cell_number` call,
477 or `TaskOutput.task_id` when Reasonix `wait` covers multiple/all jobs. Each
478 structural gap is reported once per hooks file, so a wildcard-matcher
479 plugin sees one warning per gap instead of one per hook.
480 - A plugin-root `.mcp.json` to installed MCP entries. Claude `local` maps to
481 stdio, non-ASCII display names receive stable internal IDs, and duplicate
482 declarations are deduplicated. Imported servers default to
483 `auto_start=false`; users connect them on demand so startup does not change
484 the provider-visible tool schema.
485
486 Unsupported Claude hook item types are skipped with a warning. Reasonix does not
487 run third-party install scripts.
488
489 Plugin hooks receive these environment variables:
490
491 - `REASONIX_PLUGIN_ROOT`
492 - `REASONIX_PLUGIN_NAME`
493 - `REASONIX_PLUGIN_VERSION`
494 - `REASONIX_HOME`
495 - `REASONIX_WORKSPACE_ROOT`
496 - `CLAUDE_PROJECT_DIR`
497 - `CLAUDE_PLUGIN_ROOT`
498
499 ## Desktop Backend Methods
500
501 Desktop exposes plugin package operations through Wails methods:
502
503 - `Plugins`
504 - `PlanPluginInstall`
505 - `InstallPlugin`
506 - `RemovePlugin`
507 - `SetPluginEnabled`
508 - `UpdatePlugin`
509 - `PluginDoctor`
510
510 lines MARKDOWN