universal-plugin 0.11.3 → 0.12.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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/dist/cli.mjs +3294 -3163
- package/package.json +3 -3
- package/plugin.json +1 -1
- package/skills/build-plugin/SKILL.md +7 -1
- package/skills/publish-plugin/README.md +8 -0
- package/skills/publish-plugin/SKILL.md +44 -5
- package/skills/publish-plugin/evals/evals.json +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Universal AI agent plugin build tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-plugin",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@cyberuni/agent-harness": "^0.3.0",
|
|
43
43
|
"@repobuddy/upx": "^0.2.0",
|
|
44
44
|
"@toon-format/toon": "^4.1.1",
|
|
45
|
-
"commander": "^
|
|
45
|
+
"commander": "^15.0.0",
|
|
46
46
|
"semver": "^7.8.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"tsdown": "^0.23.0",
|
|
54
54
|
"tsx": "^4.22.3",
|
|
55
55
|
"typescript": "^6.0.0",
|
|
56
|
-
"vitest": "^
|
|
56
|
+
"vitest": "^5.0.0"
|
|
57
57
|
},
|
|
58
58
|
"engines": {
|
|
59
59
|
"node": ">=22"
|
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "universal-plugin",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.0",
|
|
5
5
|
"description": "Research and design toolkit for building universal AI coding agent plugins that work across Claude Code, Cursor, Codex, and GitHub Copilot CLI.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "unional"
|
|
@@ -56,6 +56,7 @@ The command never prompts, so it is safe to run unattended.
|
|
|
56
56
|
| `--dry-run` | Validate and report the plan, write nothing. Run this first when unsure what will change |
|
|
57
57
|
| `--vendor <id>` | Build one vendor (`claude-code`, `cursor`, `codex`, `copilot-cli`), and refresh only its catalog |
|
|
58
58
|
| `--verbose` | Print each field-level decision the derivation made |
|
|
59
|
+
| `--strict-dependencies` | Fail when a refreshed catalog cannot resolve a declared dependency. Use in CI |
|
|
59
60
|
| `--format json` | The same result as JSON, for scripts |
|
|
60
61
|
|
|
61
62
|
`--clean` also exists. It deletes derived manifests before rewriting them, so reach for it only
|
|
@@ -76,9 +77,14 @@ A catalog row reads `updated`, `unchanged`, or `planned` on `--dry-run`. A build
|
|
|
76
77
|
catalog, and it keeps an entry's non-local source, such as an npm package, while it re-derives the
|
|
77
78
|
version. To add a catalog or change a source, use `marketplace`.
|
|
78
79
|
|
|
80
|
+
The build also checks each declared dependency against the catalogs it refreshes. A bare dependency
|
|
81
|
+
the catalog does not list warns: offer the user both fixes the warning names, listing it with
|
|
82
|
+
`marketplace add` or qualifying it with the marketplace that lists it. A dependency whose entry
|
|
83
|
+
declares a `source` is listed in the catalog by the build itself.
|
|
84
|
+
|
|
79
85
|
Read stderr too. The build drops what a vendor cannot represent and warns instead of failing: a hook
|
|
80
86
|
handler type a vendor cannot run, a `harnesses.copilot-cli` override with no delivery path, an
|
|
81
|
-
invalid catalog. Each warning names something that will not reach a runtime. Tell the user each
|
|
87
|
+
invalid catalog, a dependency the catalog cannot resolve. Each warning names something that will not reach a runtime. Tell the user each
|
|
82
88
|
one; do not bury it in a summary.
|
|
83
89
|
|
|
84
90
|
`built 0` with "nothing to build" is not success. The manifest declares no vendor, so hand it to
|
|
@@ -22,6 +22,14 @@ Every check and every entry field in Steps 1–2 reads from the plugin location
|
|
|
22
22
|
from the cwd by assumption. Getting this wrong means the marketplace entry ends up pointing at the
|
|
23
23
|
marketplace repo's own URL instead of the plugin's.
|
|
24
24
|
|
|
25
|
+
## A plugin's dependencies go with it
|
|
26
|
+
|
|
27
|
+
A plain dependency (no marketplace named) resolves against the marketplace the plugin is installed
|
|
28
|
+
from, so publishing a plugin whose plain dependency the catalog does not list publishes something
|
|
29
|
+
nobody can install. The skill lists such a dependency in the same PR, or stops and asks for it to be
|
|
30
|
+
published first. A dependency that names another marketplace only needs that marketplace in the
|
|
31
|
+
catalog's `allowCrossMarketplaceDependenciesOn`, which the skill offers to add.
|
|
32
|
+
|
|
25
33
|
## Why this is not the `marketplace` skill
|
|
26
34
|
|
|
27
35
|
`marketplace` generates a repository's own local catalog — no submission, no shared listing, no PR.
|
|
@@ -19,7 +19,7 @@ Publishing has four steps:
|
|
|
19
19
|
|
|
20
20
|
0. **Locate** — work out which repo is which, and where the plugin and the marketplace each live
|
|
21
21
|
1. **Pre-flight** — validate the plugin is ready
|
|
22
|
-
2. **Prepare entries** — build the entry for each vendor marketplace file that exists
|
|
22
|
+
2. **Prepare entries** — build the entry for each vendor marketplace file that exists, and resolve the plugin's dependencies against the target marketplace
|
|
23
23
|
3. **Submit PR** — one PR that updates all relevant marketplace files
|
|
24
24
|
|
|
25
25
|
Work through each step in order. Do not skip pre-flight even if the user says the plugin is ready.
|
|
@@ -211,7 +211,39 @@ If the plugin is already listed (this is an update), find its existing entry, up
|
|
|
211
211
|
|
|
212
212
|
Show all prepared entries to the user and ask them to confirm before proceeding.
|
|
213
213
|
|
|
214
|
-
### 2f.
|
|
214
|
+
### 2f. Resolve the plugin's dependencies
|
|
215
|
+
|
|
216
|
+
Claude Code installs a plugin only when every dependency it declares resolves, so a catalog that lists
|
|
217
|
+
the plugin but not what it depends on publishes a plugin nobody can install. Read the declaration
|
|
218
|
+
Claude Code receives, from the **plugin location**: `dependencies` in `.claude-plugin/plugin.json`
|
|
219
|
+
(the built manifest), or, if that has not been built, the canonical one —
|
|
220
|
+
`extensions["org.cyberuni.universal-plugin"].harnesses["claude-code"].dependencies`, else
|
|
221
|
+
`extensions["org.cyberuni.universal-plugin"].dependencies` in `plugin.json`. No declaration means
|
|
222
|
+
nothing to do here.
|
|
223
|
+
|
|
224
|
+
Each entry is a string (`<plugin>` or `<plugin>@<marketplace>`, optionally with an `@^range` tail) or
|
|
225
|
+
an object (`{ "name", "marketplace"?, "version"?, ... }`). Sort each one:
|
|
226
|
+
|
|
227
|
+
- **Plain** — a bare `<plugin>`, or an object with no `marketplace`. Claude Code resolves it against
|
|
228
|
+
the marketplace the plugin is installed from, which is this one. If the target catalog
|
|
229
|
+
(`.claude-plugin/marketplace.json`) already lists that name, it is resolved. Otherwise it must be
|
|
230
|
+
listed in this same PR: locate the dependency's own repository or package (an object's `source`
|
|
231
|
+
field, when present, says where it is distributed from; otherwise ask the user), run Step 1's
|
|
232
|
+
pre-flight against it, and prepare its entries exactly as 2b–2e do for the main plugin — then
|
|
233
|
+
resolve *its* plain dependencies the same way. If a plain dependency cannot be listed (no
|
|
234
|
+
repository or package to read, pre-flight fails, the user declines), **stop**: tell the user to
|
|
235
|
+
publish that dependency to this marketplace first, and do not open the PR.
|
|
236
|
+
- **Names a marketplace** — `<plugin>@<marketplace>`, or an object with `marketplace`. Not held to
|
|
237
|
+
this catalog's listing, even when the marketplace it names is this one; do not add an entry for
|
|
238
|
+
it. When the named marketplace is **not** this catalog's `name`, Claude Code refuses the
|
|
239
|
+
dependency at install unless this catalog's top-level `allowCrossMarketplaceDependenciesOn` lists
|
|
240
|
+
that marketplace. If it does not, tell the user that installs from this marketplace need it, and
|
|
241
|
+
offer to add the marketplace name to that array in the same PR.
|
|
242
|
+
|
|
243
|
+
Report how each dependency was sorted and what was done about it, and include the dependency entries
|
|
244
|
+
in what you show the user to confirm.
|
|
245
|
+
|
|
246
|
+
### 2g. Validate the catalogs
|
|
215
247
|
|
|
216
248
|
Before moving to Step 3, run the validator against the marketplace repo's working copy (the same
|
|
217
249
|
checkout the entries were just written into):
|
|
@@ -221,7 +253,11 @@ npx universal-plugin marketplace validate --root .
|
|
|
221
253
|
```
|
|
222
254
|
|
|
223
255
|
This is the same check `marketplace init`/`build` rely on — it catches an entry shape no runtime can
|
|
224
|
-
load (a bad `source`, a missing required key) before it reaches a PR.
|
|
256
|
+
load (a bad `source`, a missing required key) before it reaches a PR. In the Claude catalog it also
|
|
257
|
+
reports a plain dependency the catalog does not list and a dependency on a marketplace missing from
|
|
258
|
+
`allowCrossMarketplaceDependenciesOn`, as far as it can see them offline (an entry's own
|
|
259
|
+
`dependencies`, and plugins at `./` paths) — so it does not replace 2f for a plugin listed from npm
|
|
260
|
+
or git. Fix any reported issue and
|
|
225
261
|
re-run before continuing. Do not open the PR while validation fails.
|
|
226
262
|
|
|
227
263
|
---
|
|
@@ -266,7 +302,7 @@ git checkout -b add-<plugin-name>
|
|
|
266
302
|
|
|
267
303
|
### 3c. Edit all detected marketplace files
|
|
268
304
|
|
|
269
|
-
For each vendor marketplace file detected in Step 2a, append the plugin entry to its `plugins` array. Preserve formatting and all existing entries exactly. Stage all changed files together.
|
|
305
|
+
For each vendor marketplace file detected in Step 2a, append the plugin entry — and the entry of each dependency 2f listed — to its `plugins` array, and add any `allowCrossMarketplaceDependenciesOn` change the user accepted in 2f. Preserve formatting and all existing entries exactly. Stage all changed files together.
|
|
270
306
|
|
|
271
307
|
### 3d. Commit and push
|
|
272
308
|
|
|
@@ -319,6 +355,8 @@ gh pr create \
|
|
|
319
355
|
- [ ] Semver version string
|
|
320
356
|
- [ ] SPDX license identifier
|
|
321
357
|
- [ ] Entry appended to each detected marketplace file
|
|
358
|
+
- [ ] Every plain dependency is listed in this marketplace (here or already)
|
|
359
|
+
- [ ] Every marketplace a dependency names is in `allowCrossMarketplaceDependenciesOn`, or noted as not needed
|
|
322
360
|
EOF
|
|
323
361
|
)"
|
|
324
362
|
```
|
|
@@ -337,7 +375,8 @@ Return the PR URL to the user when done.
|
|
|
337
375
|
| Name conflict in marketplace | Check existing entries in each marketplace file first |
|
|
338
376
|
| Plugin loads but skills missing | Add `skills` array to the Claude Code marketplace entry |
|
|
339
377
|
| Entry installs nothing for a monorepo plugin | `source` was `url`/root-clone instead of `git-subdir` — redo 2b/2c with the plugin's actual repo-relative path |
|
|
340
|
-
|
|
|
378
|
+
| Install fails resolving a dependency | 2f was skipped — list the plain dependency in this marketplace, or allow the named marketplace in `allowCrossMarketplaceDependenciesOn` |
|
|
379
|
+
| `marketplace validate` fails after 2g | Fix the reported shape before opening the PR — do not open it while validation fails |
|
|
341
380
|
| Entry's `repository`/`source.url` points at the marketplace repo | Step 0 role detection was skipped or overridden wrongly — re-check which repo the cwd is |
|
|
342
381
|
|
|
343
382
|
---
|
|
@@ -30,6 +30,12 @@
|
|
|
30
30
|
"prompt": "I'm a maintainer of cyberuni/marketplace and I already have it checked out here. I want to add a plugin called 'db-migrate' that lives at github.com/someuser/db-migrate. Add it.",
|
|
31
31
|
"expected_output": "Detects the cwd is the marketplace repo itself, not the plugin, so it reads the plugin's metadata from the given URL (cloning it to a scratch location) instead of the cwd, then works directly in the existing checkout (fetch/merge, branch, edit, commit, push, PR) rather than cloning or forking cyberuni/marketplace again. The prepared entry's source/repository URL points at db-migrate's repo, not at cyberuni/marketplace.",
|
|
32
32
|
"files": []
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"id": 6,
|
|
36
|
+
"prompt": "Publish buddy-agent-harness (in ~/code/buddy-agent-harness) to the cyberplace marketplace. Its plugin.json declares dependencies [\"agent-harness\", { \"name\": \"cyber-asana\", \"marketplace\": \"cyberuni\" }]. cyberplace's .claude-plugin/marketplace.json does not list agent-harness and has no allowCrossMarketplaceDependenciesOn.",
|
|
37
|
+
"expected_output": "Reads the plugin's dependencies before submitting. Treats \"agent-harness\" as a plain dependency resolved against cyberplace: since cyberplace does not list it, prepares agent-harness's entry in the same PR from its own repository/package (after pre-flight), or stops and tells the user to publish agent-harness first — never opens a PR listing buddy-agent-harness without it. Treats cyber-asana@cyberuni as a named-marketplace dependency: adds no entry for it, says installs from cyberplace need \"cyberuni\" in allowCrossMarketplaceDependenciesOn, and offers to add it.",
|
|
38
|
+
"files": []
|
|
33
39
|
}
|
|
34
40
|
]
|
|
35
41
|
}
|