universal-plugin 0.2.1 → 0.3.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.
Files changed (38) hide show
  1. package/.claude-plugin/plugin.json +15 -0
  2. package/.codex-plugin/plugin.json +14 -0
  3. package/.cursor-plugin/plugin.json +14 -0
  4. package/agents/agentskills-specialist.md +132 -0
  5. package/bin/upx.mjs +6 -0
  6. package/dist/cli.mjs +1330 -255
  7. package/dist/run.mjs +271 -0
  8. package/governances/plugin-design.md +22 -17
  9. package/governances/slash-invocation.md +30 -0
  10. package/package.json +14 -5
  11. package/plugin.json +18 -0
  12. package/readme.md +37 -3
  13. package/skills/adopt-upx/README.md +38 -0
  14. package/skills/adopt-upx/SKILL.md +120 -0
  15. package/skills/adopt-upx/scripts/rewrite-upx.mjs +168 -0
  16. package/skills/migrate-plugin/SKILL.md +106 -0
  17. package/skills/migrate-plugin/evals/evals.json +11 -0
  18. package/skills/migrate-plugin/evals/trigger-queries.json +35 -0
  19. package/skills/plugin/README.md +37 -0
  20. package/skills/plugin/SKILL.md +105 -0
  21. package/skills/plugin/assets/templates/agent.md +7 -0
  22. package/skills/plugin/assets/templates/command.md +9 -0
  23. package/skills/plugin/assets/templates/hooks.json +9 -0
  24. package/skills/plugin/assets/templates/plugin.json +19 -0
  25. package/skills/plugin/assets/templates/setup-command.md +15 -0
  26. package/skills/plugin/assets/templates/skill.md +15 -0
  27. package/skills/plugin/references/adopt.md +114 -0
  28. package/skills/plugin/references/create.md +163 -0
  29. package/skills/plugin/references/delete.md +23 -0
  30. package/skills/plugin/references/inspect.md +21 -0
  31. package/skills/plugin/references/update.md +26 -0
  32. package/skills/plugin/references/version.md +97 -0
  33. package/skills/publish-plugin/SKILL.md +246 -0
  34. package/skills/publish-plugin/evals/evals.json +23 -0
  35. package/skills/publish-plugin/references/vendor-requirements.md +38 -0
  36. package/skills/upgrade-plugin/README.md +23 -0
  37. package/skills/upgrade-plugin/SKILL.md +86 -0
  38. package/LICENSE +0 -21
@@ -0,0 +1,114 @@
1
+ # Adopt the open standard
2
+
3
+ Convert something that is *already* a plugin — or already ships skills — onto the canonical
4
+ Agent Plugins Specification manifest, without changing what it does.
5
+
6
+ Two starting shapes land here:
7
+
8
+ - **A vendor-specific plugin** — it has one or more hand-written vendor manifests
9
+ (`.claude-plugin/plugin.json`, `.cursor-plugin/plugin.json`, …) and no canonical root
10
+ `plugin.json`.
11
+ - **Bare public skills** — it ships `skills/<name>/SKILL.md` to users but has no plugin manifest of
12
+ any kind.
13
+
14
+ Adoption is **lossless by contract**: every vendor that worked before must still work after. Step 6
15
+ is the check that proves it — do not skip it.
16
+
17
+ ## Step 0 — Confirm the user wants this
18
+
19
+ Adoption rewrites the project's manifest layout and turns hand-written vendor manifests into
20
+ generated artifacts. Say that plainly and get agreement before touching files. If the user declines,
21
+ route back to whatever they originally asked for.
22
+
23
+ Also confirm the working tree is clean (`git status`). The Step 6 diff is worthless if uncommitted
24
+ changes are mixed in.
25
+
26
+ ## Step 1 — Inventory what exists
27
+
28
+ ```bash
29
+ ls -d .claude-plugin .cursor-plugin .codex-plugin .github/plugin .plugin 2>/dev/null
30
+ test -f plugin.json && cat plugin.json
31
+ find . -name SKILL.md -not -path '*/node_modules/*' -not -path './.git/*'
32
+ ls .mcp.json .lsp.json hooks/ commands/ agents/ rules/ output-styles/ 2>/dev/null
33
+ ```
34
+
35
+ Record, for each vendor manifest found: its path, and every field it sets. You are about to
36
+ reproduce all of it.
37
+
38
+ **If a root `plugin.json` already exists**, read it before assuming anything. It is either the
39
+ canonical manifest (has `$schema` pointing at `agent-plugins.org` and an `extensions` object — in
40
+ which case there is nothing to adopt; route to `update.md` or `inspect.md` instead), or a legacy
41
+ Copilot CLI manifest that now collides with the canonical path and must be folded in.
42
+
43
+ ## Step 2 — Sort every field into shared vs vendor-specific
44
+
45
+ Build two buckets from the manifests you inventoried:
46
+
47
+ - **Shared metadata** — `name`, `version`, `description`, `author`, `homepage`, `repository`,
48
+ `license`, `keywords`, and the component paths. These go at the canonical top level.
49
+ - **Vendor-specific** — anything only one runtime understands (Cursor's `publisher`/`category`/
50
+ `tags`, Codex's `interface`, Copilot's `category`/`tags`). These go under
51
+ `extensions["org.cyberuni.universal-plugin"].harnesses.<vendor>`.
52
+
53
+ Where two vendor manifests disagree on a shared field, **ask the user** which value is canonical
54
+ rather than picking one. A silent choice here is a silent behavior change for one of their runtimes.
55
+
56
+ ## Step 3 — Write the canonical manifest
57
+
58
+ Scaffold it, naming exactly the vendors you found in Step 1:
59
+
60
+ ```bash
61
+ npx universal-plugin plugin init --name <name> --vendor claude-code --vendor cursor
62
+ ```
63
+
64
+ > `plugin init` writes a **minimal** manifest — `$schema`, `name`, and the `vendors` list. It does
65
+ > not read your existing vendor manifests. Carry the Step 2 buckets in by hand afterwards.
66
+
67
+ Then fill in the shared metadata and `harnesses` as laid out in
68
+ [`create.md`](./create.md) Step 5. Point the component paths at the directories that already exist —
69
+ adoption must not move files.
70
+
71
+ For the bare-public-skills case there is no metadata to carry over; supply `name`, `description`,
72
+ and `version`, set `"skills": "./skills/"`, and choose vendors with the user (see
73
+ [`create.md`](./create.md) Step 2).
74
+
75
+ ## Step 4 — Decide what happens to the old manifests
76
+
77
+ The vendor manifests are now **build outputs**. They stay at the same paths, but they are
78
+ regenerated rather than edited.
79
+
80
+ - Commit them as-is first, so Step 6 has a baseline to diff against.
81
+ - Tell the user they are generated from here on, and that hand-edits will be overwritten by
82
+ `plugin build`.
83
+ - If the project has a legacy root `plugin.json` for Copilot CLI, that path is now the canonical
84
+ manifest — its derived Copilot output moves elsewhere. Check the vendor output table in
85
+ [`create.md`](./create.md) Step 2 for the current path.
86
+
87
+ ## Step 5 — Build
88
+
89
+ ```bash
90
+ npx universal-plugin plugin build
91
+ ```
92
+
93
+ ## Step 6 — Prove it was lossless
94
+
95
+ This is the point of the whole procedure.
96
+
97
+ ```bash
98
+ git diff -- .claude-plugin .cursor-plugin .codex-plugin .github/plugin
99
+ ```
100
+
101
+ Read every line of that diff. Expect only formatting and key-order churn.
102
+
103
+ **Any field that disappeared is a regression**, not a cleanup. Trace it back: either it belongs in
104
+ the shared metadata, or it belongs in that vendor's `harnesses` entry, or it is a field the build
105
+ does not yet support — in which case stop and tell the user rather than shipping a quiet
106
+ capability loss.
107
+
108
+ Then confirm the plugin still loads. See [`create.md`](./create.md) Step 8 for local install.
109
+
110
+ ## Step 7 — Hand off
111
+
112
+ - Audit the skills: [`create.md`](./create.md) Step 6.
113
+ - Shipping it on npm? → `migrate-plugin`.
114
+ - Listing it in the marketplace? → `publish-plugin`.
@@ -0,0 +1,163 @@
1
+ # Create a universal plugin
2
+
3
+ Scaffold a new plugin from a single canonical `plugin.json` and build one manifest per chosen
4
+ vendor.
5
+
6
+ ## Step 1 — Gather plugin identity
7
+
8
+ Ask if not provided. All fields map to the canonical root `plugin.json`.
9
+
10
+ | Field | Required | Notes |
11
+ |-------|----------|-------|
12
+ | `name` | Yes | kebab-case, 1–64 chars, `a-z 0-9 - .` only |
13
+ | `description` | Recommended | one sentence; Codex requires this |
14
+ | `version` | If publishing | semver; Codex requires this |
15
+ | `author.name` | Recommended | person or org name |
16
+ | `homepage` | Optional | docs or landing page URL |
17
+ | `repository` | Optional | source repo URL |
18
+ | `license` | Optional | SPDX identifier e.g. `MIT` |
19
+ | `keywords` | Optional | discovery tags; array of strings |
20
+
21
+ ## Step 2 — Choose vendor targets
22
+
23
+ Ask the user which runtimes to support. Each chosen vendor becomes a key in
24
+ `extensions["org.cyberuni.universal-plugin"].harnesses` — that is what drives the `build` output.
25
+ Add the vendor's id to `extensions["org.cyberuni.universal-plugin"].vendors` too, so `build` knows
26
+ to generate its manifest.
27
+
28
+ | Vendor ID | Manifest read from | Hook event case | Required fields beyond `name` |
29
+ |-----------|--------------------|-----------------|-------------------------------|
30
+ | `claude-code` | `.claude-plugin/plugin.json` *(derived)* | PascalCase | none |
31
+ | `cursor` | `.cursor-plugin/plugin.json` *(derived)* | camelCase | none |
32
+ | `codex` | `.codex-plugin/plugin.json` *(derived)* | PascalCase | `version`, `description` |
33
+ | `copilot-cli` | root `plugin.json` — **the canonical manifest itself** | camelCase | none |
34
+
35
+ **Copilot CLI derives nothing.** It searches `.plugin/plugin.json` → `plugin.json` →
36
+ `.github/plugin/plugin.json` → `.claude-plugin/plugin.json` and takes the *first* match, so root
37
+ always wins; and it has read Open Plugin Spec v1 manifests since v1.0.74. `plugin build` reports it
38
+ with status `canonical` and writes no file. A `harnesses["copilot-cli"]` override cannot be
39
+ delivered — the canonical schema is closed to vendor-only fields — and the build warns if you set
40
+ one.
41
+
42
+ Universal minimum (no vendor manifest needed): `skills/<name>/SKILL.md` + `.mcp.json`.
43
+
44
+ Default to all four if the user is unsure.
45
+
46
+ ## Step 3 — Choose components
47
+
48
+ Infer from context; ask only if ambiguous. Apply rules from the `plugin-design` governance loaded
49
+ in the gateway's Prerequisites.
50
+
51
+ | Component | Field | Directory | Cross-vendor? |
52
+ |-----------|-------|-----------|--------------|
53
+ | Skills | `skills` | `skills/<name>/SKILL.md` | Yes — all |
54
+ | Commands | `commands` | `commands/<name>.md` | Claude Code, Cursor, Copilot CLI |
55
+ | Agents | `agents` | `agents/<name>.md` | Claude Code, Cursor, Copilot CLI |
56
+ | MCP servers | `mcpServers` | `.mcp.json` | Yes — all |
57
+ | Hooks | `hooks` | `hooks/hooks.json` | Partial — event names translated on build |
58
+ | Rules | `rules` | `rules/<name>.mdc` | Cursor-only |
59
+ | LSP servers | `lspServers` | `.lsp.json` | Claude Code, Cursor |
60
+ | Output styles | `outputStyles` | `output-styles/` | Claude Code only |
61
+
62
+ ## Step 4 — Scaffold files
63
+
64
+ Read the templates from `../assets/templates/` and fill in the placeholders:
65
+
66
+ | File to create | Template |
67
+ |----------------|----------|
68
+ | `plugin.json` | `assets/templates/plugin.json` |
69
+ | `skills/<name>/SKILL.md` | `assets/templates/skill.md` |
70
+ | `commands/<name>.md` | `assets/templates/command.md` |
71
+ | `agents/<name>.md` | `assets/templates/agent.md` |
72
+ | `hooks/hooks.json` | `assets/templates/hooks.json` |
73
+ | `commands/setup.md` (when `rules/` included) | `assets/templates/setup-command.md` |
74
+
75
+ Directory layout:
76
+
77
+ ```
78
+ <plugin-name>/
79
+ ├── plugin.json ← canonical definition (source of truth)
80
+ ├── skills/<name>/SKILL.md
81
+ ├── commands/
82
+ ├── agents/
83
+ ├── rules/ (only if always-on Cursor guidance requested)
84
+ ├── hooks/hooks.json
85
+ ├── .mcp.json
86
+ └── README.md
87
+ ```
88
+
89
+ ## Step 5 — Populate extensions["org.cyberuni.universal-plugin"]
90
+
91
+ In root `plugin.json`, under `extensions["org.cyberuni.universal-plugin"]`, add the chosen vendors
92
+ to `vendors` and add a `harnesses` object with one entry per chosen vendor. An empty `{}` opts into
93
+ that vendor's output with no vendor-specific fields.
94
+
95
+ ```json
96
+ {
97
+ "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
98
+ "name": "<plugin-name>",
99
+ "version": "1.0.0",
100
+ "description": "<description>",
101
+ "author": { "name": "<author>" },
102
+ "extensions": {
103
+ "org.cyberuni.universal-plugin": {
104
+ "vendors": ["claude-code", "cursor", "codex", "copilot-cli"],
105
+ "skills": "./skills/",
106
+ "harnesses": {
107
+ "claude-code": {},
108
+ "cursor": {
109
+ "publisher": "<org>",
110
+ "category": "<category>",
111
+ "tags": ["<tag>"]
112
+ },
113
+ "codex": {
114
+ "interface": {
115
+ "displayName": "<Human Name>",
116
+ "category": "<category>"
117
+ }
118
+ },
119
+ "copilot-cli": {
120
+ "category": "<category>",
121
+ "tags": ["<tag>"]
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ ```
128
+
129
+ See spec §3.3 for the full list of vendor-specific fields:
130
+ https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/spec.md
131
+
132
+ ## Step 6 — Audit skills
133
+
134
+ Audit each skill via the aced **improve-skill** skill's mechanical `validate.mts` engine:
135
+
136
+ ```bash
137
+ node "<path to aced improve-skill>/scripts/validate.mts" --path skills/<skill-name>
138
+ ```
139
+
140
+ Fix any CRITICAL findings. Then invoke the **audit-skill** skill for full review.
141
+
142
+ ## Step 7 — Build vendor manifests
143
+
144
+ > **Note:** The `build` CLI is not yet available. Use the manual steps below.
145
+
146
+ For each vendor in `extensions["org.cyberuni.universal-plugin"].vendors`:
147
+
148
+ 1. Copy canonical fields from root `plugin.json`
149
+ 2. Merge vendor-specific fields from `extensions["org.cyberuni.universal-plugin"].harnesses.<vendor>`
150
+ 3. Drop fields not supported by that vendor (see spec §6.1)
151
+ 4. Translate hook event names (see spec §4.2)
152
+ 5. Translate `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` env vars (see spec §5)
153
+ 6. Write to the vendor output path (see the Step 2 table)
154
+
155
+ See spec §7 for full build rules:
156
+ https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/spec.md
157
+
158
+ ## Step 8 — Install locally for testing
159
+
160
+ ```bash
161
+ ln -sf "$(pwd)" ~/.claude/plugins/local/<plugin-name> # Claude Code
162
+ ln -sf "$(pwd)" ~/.cursor/plugins/local/<plugin-name> # Cursor → Developer: Reload Window
163
+ ```
@@ -0,0 +1,23 @@
1
+ # Delete a universal plugin
2
+
3
+ ## Remove generated manifests only (keep source)
4
+
5
+ Delete each vendor's output file. Generated manifests are build artifacts — safe to delete and
6
+ regenerate via [`create.md`](./create.md) Step 7.
7
+
8
+ ```bash
9
+ rm -f .claude-plugin/plugin.json
10
+ rm -f .cursor-plugin/plugin.json
11
+ rm -f .codex-plugin/plugin.json
12
+ ```
13
+
14
+ > **Never delete root `plugin.json`.** It is the canonical source of truth, not a build artifact —
15
+ > and it is also what Copilot CLI reads, so removing it takes out both the source and the Copilot
16
+ > target. `copilot-cli` has no generated manifest to clean.
17
+
18
+ If the project has a stale `.github/plugin/plugin.json` from an older build, it is safe to delete —
19
+ that path is shadowed by root and is no longer generated.
20
+
21
+ ## Remove the whole plugin
22
+
23
+ Delete the plugin root directory. Confirm with the user before proceeding — this is irreversible.
@@ -0,0 +1,21 @@
1
+ # Inspect a universal plugin
2
+
3
+ Show the current state of a plugin.
4
+
5
+ 1. Read root `plugin.json` — show `name`, `version`, declared vendors
6
+ (`extensions["org.cyberuni.universal-plugin"].vendors`).
7
+ 2. For each vendor, check whether the generated manifest exists at its output path.
8
+ 3. Report status: which vendors are built, which are missing or stale.
9
+
10
+ Example output:
11
+
12
+ ```
13
+ Plugin: my-plugin v1.0.0
14
+ Vendors declared: claude-code, cursor, codex, copilot-cli
15
+ claude-code .claude-plugin/plugin.json ✓ present
16
+ cursor .cursor-plugin/plugin.json ✓ present
17
+ codex .codex-plugin/plugin.json ✗ missing — run build
18
+ copilot-cli plugin.json ✗ missing — run build
19
+ ```
20
+
21
+ Vendor output paths are listed in [`create.md`](./create.md) Step 2.
@@ -0,0 +1,26 @@
1
+ # Update a universal plugin
2
+
3
+ Change which vendors or components an existing plugin declares. Every path ends with a rebuild —
4
+ see [`create.md`](./create.md) Step 7.
5
+
6
+ ## Add a vendor
7
+
8
+ 1. Add the vendor id to `extensions["org.cyberuni.universal-plugin"].vendors` in root
9
+ `plugin.json`, and add its key to `extensions["org.cyberuni.universal-plugin"].harnesses`.
10
+ 2. Populate vendor-specific fields (see spec §3.3).
11
+ 3. If the vendor requires extra fields (`codex`: `version`, `description`), ensure they are in the
12
+ canonical section.
13
+ 4. Rebuild for the new vendor.
14
+
15
+ ## Remove a vendor
16
+
17
+ 1. Remove the vendor id from `extensions["org.cyberuni.universal-plugin"].vendors` and its key from
18
+ `harnesses`.
19
+ 2. Delete the generated manifest at its output path.
20
+
21
+ ## Add or remove a component
22
+
23
+ 1. Add/remove the component field under `extensions["org.cyberuni.universal-plugin"]` in root
24
+ `plugin.json` (e.g. `"commands": "./commands/"`).
25
+ 2. Scaffold or delete the corresponding files.
26
+ 3. Rebuild to regenerate all vendor manifests.
@@ -0,0 +1,97 @@
1
+ # Move a universal plugin's version
2
+
3
+ Bump or set the version a plugin releases under, keeping every file that carries one in sync.
4
+
5
+ A plugin's version lives in up to five places, but only **two are authored** — the canonical root
6
+ `plugin.json` and, when the project declares a `packagePath`, that `package.json`. The per-vendor
7
+ manifests, the local marketplace catalogs, and the `npx`/`upx` pins inside `skills/**/SKILL.md` are
8
+ all **derived**. So never hand-edit a version: editing one file leaves the other authored file and
9
+ every derived artifact stale, and a consumer's plugin cache is keyed by version, so a content change
10
+ without a matching bump is invisible to them.
11
+
12
+ ## Step 0 — Does this repo use changesets?
13
+
14
+ ```bash
15
+ test -d .changeset && echo "changesets"
16
+ ```
17
+
18
+ **If it does**, the version number is decided by changesets, not by you. Add a changeset and let the
19
+ release run — the repo's `version` script should already call `publish sync-version`, which carries
20
+ the released number from `package.json` into the canonical manifest:
21
+
22
+ ```bash
23
+ npx universal-plugin publish sync-version
24
+ ```
25
+
26
+ Do **not** run `plugin version` in a changesets repo — it would decide a number changesets is about
27
+ to decide again.
28
+
29
+ **If it does not**, `plugin version` is the whole release-number step. Continue below.
30
+
31
+ ## Step 1 — Move the version
32
+
33
+ ```bash
34
+ npx universal-plugin plugin version <bump>
35
+ ```
36
+
37
+ `<bump>` is either a semver release type or an explicit version:
38
+
39
+ | `<bump>` | From `1.2.3` you get |
40
+ |---|---|
41
+ | `patch` | `1.2.4` |
42
+ | `minor` | `1.3.0` |
43
+ | `major` | `2.0.0` |
44
+ | `prerelease --preid beta` | `1.2.4-beta.0` |
45
+ | `2.0.0-rc.1` (explicit) | `2.0.0-rc.1` |
46
+
47
+ Useful flags:
48
+
49
+ | Flag | Effect |
50
+ |---|---|
51
+ | `--preid <id>` | Prerelease identifier for the `pre*` release types |
52
+ | `--dry-run` | Print the plan, write nothing — run this first when unsure |
53
+ | `--force` | Allow a target that does not advance on the current version |
54
+ | `--no-build` | Skip re-deriving the vendor manifests (you will run `plugin build` yourself) |
55
+ | `--format json` | Machine-readable result: `from`, `to`, `written` |
56
+
57
+ **Which release type?** That is the user's call, not the command's and not yours to guess — a
58
+ version is a promise to consumers about what broke. If the user has not said, ask, and offer the
59
+ semver reading of the change: breaking → `major`, new behavior → `minor`, fix only → `patch` (on a
60
+ `0.x` plugin, breaking → `minor` and everything else → `patch`).
61
+
62
+ ## Step 2 — Confirm what moved
63
+
64
+ The command reports every file it wrote and every manifest it re-derived. Expect the canonical
65
+ manifest, the `packagePath` `package.json` if one is declared, and one derived manifest per declared
66
+ harness:
67
+
68
+ ```bash
69
+ npx universal-plugin plugin version patch --format json
70
+ ```
71
+
72
+ If the plugin declares no harnesses, only the authored files are written — that is correct, not a
73
+ failure.
74
+
75
+ ## Guards
76
+
77
+ Every guard resolves before the first write, so a failed run leaves the tree untouched.
78
+
79
+ | Message names | What it means | Do this |
80
+ |---|---|---|
81
+ | a missing `plugin.json` | not at a plugin root, or the plugin was never scaffolded | `cd` to the plugin root, or see [`create.md`](./create.md) |
82
+ | no version to bump from | the manifest has never carried a `version` | pass an explicit version (`plugin version 0.1.0`) to set the first one |
83
+ | an unknown version or release type | the argument is neither a release type nor valid semver | use one of the values in the table above |
84
+ | a target that does not advance | the requested version is not greater than the current one | pick a higher version, or pass `--force` if the user genuinely wants to move backward |
85
+ | a missing `package.json` at `packagePath` | `.agents/universal-plugin.json` names a package directory that does not exist | fix `packagePath`, or create the package |
86
+
87
+ ## Do not
88
+
89
+ - **Hand-edit a `version` field.** Two authored files and every derived artifact fall out of sync.
90
+ - **Write a derived manifest.** `.claude-plugin/plugin.json` and its siblings belong to
91
+ `plugin build`; the bump already re-derived them.
92
+ - **Run `npm version`.** It knows only `package.json` and leaves the canonical manifest — the actual
93
+ source of truth — stale.
94
+
95
+ ## References
96
+
97
+ - Spec: https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/plugin/version/README.md