universal-plugin 0.13.0 → 0.14.1
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 +1010 -971
- package/package.json +2 -2
- package/plugin.json +1 -1
- package/skills/adopt-upx/scripts/rewrite-upx.mjs +1 -1
- package/skills/build-plugin/README.md +1 -1
- package/skills/build-plugin/SKILL.md +1 -1
- package/skills/build-plugin/scripts/build.mjs +1 -1
- package/skills/doctor-universal-plugin/SKILL.md +22 -22
- package/skills/doctor-universal-plugin/scripts/doctor.mjs +1 -1
- package/skills/init-universal-plugin/references/create.md +2 -2
- package/skills/init-universal-plugin/references/standard.md +1 -1
- package/skills/init-universal-plugin/scripts/init.mjs +1 -1
- package/skills/marketplace/SKILL.md +1 -1
- package/skills/marketplace/references/init.md +1 -1
- package/skills/marketplace/scripts/add.mjs +1 -1
- package/skills/marketplace/scripts/install-docs.mjs +1 -1
- package/skills/marketplace/scripts/marketplace.mjs +1 -1
- package/skills/marketplace/scripts/validate.mjs +1 -1
- package/skills/publish-plugin/README.md +9 -1
- package/skills/publish-plugin/SKILL.md +40 -9
- package/skills/publish-plugin/evals/evals.json +9 -3
- package/skills/remove-plugin/SKILL.md +1 -1
- package/skills/version/SKILL.md +2 -2
- package/skills/version/scripts/version.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "universal-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Universal AI agent plugin build tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-plugin",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"agents"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@cyberuni/agent-harness": "^0.
|
|
42
|
+
"@cyberuni/agent-harness": "^0.7.0",
|
|
43
43
|
"@repobuddy/upx": "^0.2.0",
|
|
44
44
|
"@toon-format/toon": "^4.1.1",
|
|
45
45
|
"commander": "^15.0.0",
|
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.14.1",
|
|
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"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/rewrite-upx.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/adopt-upx/scripts/rewrite-upx.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { join, resolve } from "node:path";
|
|
6
6
|
//#region src/skill-scripts/rewrite-upx.ts
|
|
@@ -22,7 +22,7 @@ rather than reported as success.
|
|
|
22
22
|
## Install
|
|
23
23
|
|
|
24
24
|
Ships with the `universal-plugin` plugin. It is invoked in Claude Code as
|
|
25
|
-
`/universal-plugin:build-plugin
|
|
25
|
+
`/universal-plugin:build-plugin` (pnpm install: `pnpm-universal-plugin-build-plugin`).
|
|
26
26
|
|
|
27
27
|
## References
|
|
28
28
|
|
|
@@ -47,7 +47,7 @@ node scripts/build.mjs --root <plugin-root>
|
|
|
47
47
|
|
|
48
48
|
Resolve `scripts/build.mjs` against this skill's own directory. It runs the CLI the project installed
|
|
49
49
|
(`pnpm exec universal-plugin`), else the CLI pinned to the version this skill shipped with
|
|
50
|
-
(`npx universal-plugin@0.
|
|
50
|
+
(`npx universal-plugin@0.14.1`), so it works in a skill that was linked or copied on its own. `--root` defaults to the working directory and
|
|
51
51
|
must name the directory that holds the canonical `plugin.json`.
|
|
52
52
|
|
|
53
53
|
The command never prompts, so it is safe to run unattended.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/run-cli.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/build-plugin/scripts/build.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
//#region src/compile/scripts.ts
|
|
6
6
|
/** The global the header assigns the script data to. Framework-neutral: a script's own code, or the
|
|
@@ -23,7 +23,7 @@ Resolve that path against this skill's own directory. It asks the project's inst
|
|
|
23
23
|
(`pnpm exec universal-plugin`), else the CLI pinned to this skill's version (`npx`), about the
|
|
24
24
|
current working directory; add `--root <path>` to diagnose elsewhere.
|
|
25
25
|
Add `--marketplace-root <path>` (repeatable) to also check a **separately-cloned** shared marketplace
|
|
26
|
-
repository (e.g. a local clone of `cyberuni/
|
|
26
|
+
repository (e.g. a local clone of `cyberuni/cyberplace`) — see
|
|
27
27
|
[Catalogs are checked at the repository root](#catalogs-are-checked-at-the-repository-root).
|
|
28
28
|
It never prompts and never writes, so it is safe to run unattended.
|
|
29
29
|
|
|
@@ -71,32 +71,32 @@ Each `code` below is what the script emits.
|
|
|
71
71
|
|
|
72
72
|
| Finding | What it means | Repair |
|
|
73
73
|
| --- | --- | --- |
|
|
74
|
-
| `no-manifest` | no root `plugin.json` — this is not a plugin yet | `/universal-plugin:init-universal-plugin` |
|
|
75
|
-
| `legacy-manifest` | root `plugin.json` with neither `$schema` nor `extensions` — a single-vendor manifest on the canonical path | `/universal-plugin:init-universal-plugin
|
|
76
|
-
| `vendor-only` | a vendor manifest with no canonical manifest above it | `/universal-plugin:init-universal-plugin
|
|
77
|
-
| `unbuilt` | a declared vendor whose output path holds no file — that runtime sees no plugin | `/universal-plugin:build-plugin` |
|
|
78
|
-
| `stale` | a derived manifest older than `plugin.json`; for a derived directory (`com.github.copilot/`), its newest file is what is compared | `/universal-plugin:build-plugin` |
|
|
74
|
+
| `no-manifest` | no root `plugin.json` — this is not a plugin yet | `/universal-plugin:init-universal-plugin` (pnpm install: `pnpm-universal-plugin-init-universal-plugin`) |
|
|
75
|
+
| `legacy-manifest` | root `plugin.json` with neither `$schema` nor `extensions` — a single-vendor manifest on the canonical path | `/universal-plugin:init-universal-plugin` (pnpm install: `pnpm-universal-plugin-init-universal-plugin`), adopt route |
|
|
76
|
+
| `vendor-only` | a vendor manifest with no canonical manifest above it | `/universal-plugin:init-universal-plugin` (pnpm install: `pnpm-universal-plugin-init-universal-plugin`), adopt route |
|
|
77
|
+
| `unbuilt` | a declared vendor whose output path holds no file — that runtime sees no plugin | `/universal-plugin:build-plugin` (pnpm install: `pnpm-universal-plugin-build-plugin`) |
|
|
78
|
+
| `stale` | a derived manifest older than `plugin.json`; for a derived directory (`com.github.copilot/`), its newest file is what is compared | `/universal-plugin:build-plugin` (pnpm install: `pnpm-universal-plugin-build-plugin`) |
|
|
79
79
|
| `hand-edited` | a derived manifest that `build` would rewrite — the edit is already lost, it just has not been overwritten yet | move the field to the canonical manifest or to `harnesses.<vendor>`, then rebuild |
|
|
80
80
|
| `unknown-vendor` | a `vendors` entry no build target matches; reported as `skipped` plus a warning | fix the id in `plugin.json` |
|
|
81
81
|
| `unsupported-component` | a component path on the shared extension names a component one targeted vendor has none of (`agents` for Codex, `rules` for Claude Code, …); the build leaves it out of that vendor's manifest | declare the path under `harnesses.<vendor>` for the vendors that read it, or leave it — nothing is lost |
|
|
82
|
-
| `stale-script` | a compiled skill script (`scripts` in the extension) is missing, or no longer matches what its source compiles to. A script that differs only in its embedded version is `version-drift` instead, never both | `/universal-plugin:build-plugin
|
|
83
|
-
| `script-compile-failed` | a declared script entry could not be compiled into one self-contained file — usually an import that does not resolve from the plugin root | fix the entry, then `/universal-plugin:build-plugin` |
|
|
82
|
+
| `stale-script` | a compiled skill script (`scripts` in the extension) is missing, or no longer matches what its source compiles to. A script that differs only in its embedded version is `version-drift` instead, never both | `/universal-plugin:build-plugin` (pnpm install: `pnpm-universal-plugin-build-plugin`), then commit the compiled script |
|
|
83
|
+
| `script-compile-failed` | a declared script entry could not be compiled into one self-contained file — usually an import that does not resolve from the plugin root | fix the entry, then `/universal-plugin:build-plugin` (pnpm install: `pnpm-universal-plugin-build-plugin`) |
|
|
84
84
|
| `script-over-budget` | a compiled skill script is over the 150 KB budget | have the skill call the installed CLI instead: `pnpm exec <bin>` with a pinned `npx` fallback |
|
|
85
85
|
| `skill-link-escapes` | a relative Markdown link in a skill climbs out of the skill folder (`../../readme.md`). pnpm links or copies each skill folder on its own, and a plugin cache keeps only what ships, so the link resolves to nothing there | copy the file into the skill and link it relatively, or link it by URL |
|
|
86
|
-
| `undeliverable-override` | `harnesses["copilot-cli"]` sets fields that reach nothing | `/universal-plugin:init-universal-plugin
|
|
86
|
+
| `undeliverable-override` | `harnesses["copilot-cli"]` sets fields that reach nothing | `/universal-plugin:init-universal-plugin` (pnpm install: `pnpm-universal-plugin-init-universal-plugin`), update route — move them to a vendor that has a derived manifest, or drop them |
|
|
87
87
|
| `codex-fields-missing` | Codex is targeted without `version` or `description`; the build fails and writes **nothing at all**, including for the other vendors | add both to the canonical top level |
|
|
88
|
-
| `version-drift` | one file carries a different version from the release's number — the canonical manifest, a derived vendor manifest, a catalog entry, a skill pin, a marked `mcpServers` entry, or the version a compiled skill script embeds; one finding per file, named by path | `/universal-plugin:version` (for a package-sourced drift, `universal-plugin plugin version --from-package`); then [offer the CI check](#offer-the-check-to-ci) |
|
|
89
|
-
| `unstamped` | a place holds `0.0.0-development`, semantic-release's placeholder. The release has not stamped it yet, so it is not drift (severity low) | in `prepareCmd`, `plugin version ${nextRelease.version}`, and commit the stamped files back with `@semantic-release/git`; see `/universal-plugin:version` |
|
|
90
|
-
| `unreleased-content` | shipped content was committed after the commit that set the current version — a consumer keyed on that version never re-extracts it | `/universal-plugin:version` |
|
|
91
|
-
| `copilot-root-components` | agents, commands, rules, hooks, or LSP servers sit at the plugin root with no copy under `com.github.copilot/` — Copilot CLI reads them only from there in spec mode, so it loads none of them, silently | `/universal-plugin:build-plugin` |
|
|
92
|
-
| `stale-github-plugin` | a leftover `.github/plugin/plugin.json` from an older build — shadowed by root and no longer generated | `/universal-plugin:remove-plugin` |
|
|
93
|
-
| `shadowing-manifest` | a `.plugin/plugin.json` exists — it outranks root in Copilot CLI's search order and silently shadows the canonical manifest | `/universal-plugin:remove-plugin` |
|
|
94
|
-
| `no-vendors` | no vendor is declared, so the build writes nothing and no runtime reads the plugin. When the repository carries `vendorExtensions` or a `.plugin/plugin.json`, the build stops rather than reporting an empty result, and the detail says so — read it beside `legacy-manifest` and `shadowing-manifest`, which name the signals | `/universal-plugin:init-universal-plugin
|
|
88
|
+
| `version-drift` | one file carries a different version from the release's number — the canonical manifest, a derived vendor manifest, a catalog entry, a skill pin, a marked `mcpServers` entry, or the version a compiled skill script embeds; one finding per file, named by path | `/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`) (for a package-sourced drift, `universal-plugin plugin version --from-package`); then [offer the CI check](#offer-the-check-to-ci) |
|
|
89
|
+
| `unstamped` | a place holds `0.0.0-development`, semantic-release's placeholder. The release has not stamped it yet, so it is not drift (severity low) | in `prepareCmd`, `plugin version ${nextRelease.version}`, and commit the stamped files back with `@semantic-release/git`; see `/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`) |
|
|
90
|
+
| `unreleased-content` | shipped content was committed after the commit that set the current version — a consumer keyed on that version never re-extracts it | `/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`) |
|
|
91
|
+
| `copilot-root-components` | agents, commands, rules, hooks, or LSP servers sit at the plugin root with no copy under `com.github.copilot/` — Copilot CLI reads them only from there in spec mode, so it loads none of them, silently | `/universal-plugin:build-plugin` (pnpm install: `pnpm-universal-plugin-build-plugin`) |
|
|
92
|
+
| `stale-github-plugin` | a leftover `.github/plugin/plugin.json` from an older build — shadowed by root and no longer generated | `/universal-plugin:remove-plugin` (pnpm install: `pnpm-universal-plugin-remove-plugin`) |
|
|
93
|
+
| `shadowing-manifest` | a `.plugin/plugin.json` exists — it outranks root in Copilot CLI's search order and silently shadows the canonical manifest | `/universal-plugin:remove-plugin` (pnpm install: `pnpm-universal-plugin-remove-plugin`) |
|
|
94
|
+
| `no-vendors` | no vendor is declared, so the build writes nothing and no runtime reads the plugin. When the repository carries `vendorExtensions` or a `.plugin/plugin.json`, the build stops rather than reporting an empty result, and the detail says so — read it beside `legacy-manifest` and `shadowing-manifest`, which name the signals | `/universal-plugin:init-universal-plugin` (pnpm install: `pnpm-universal-plugin-init-universal-plugin`), adopt route when `vendorExtensions` or `.plugin/plugin.json` is present, else update route |
|
|
95
95
|
| `package-path-missing` | `packagePath` names a directory with no readable `package.json` | fix `packagePath`, or create the package |
|
|
96
96
|
| `package-path-unknown` | the CLI could not report `packagePath` (a version too old to read it), so `version-drift` and `unreleased-content` were skipped rather than guessed | upgrade universal-plugin |
|
|
97
97
|
| `misplaced-package-path` | `plugin.json` declares `packagePath` under `extensions["org.cyberuni.universal-plugin"]`, where the CLI never reads it — the plugin is silently treated as not shipping to npm | move it to `.agents/universal-plugin.json`, relative to the plugin root |
|
|
98
98
|
| `unparsable-manifest` | root `plugin.json` is not valid JSON | fix the syntax error |
|
|
99
|
-
| `invalid-catalog` | a marketplace catalog — at the repository root, or at a `--marketplace-root` clone — is not a shape its runtime loads — it is found, read, and refused at install time, in the user's terminal | `/universal-plugin:marketplace` |
|
|
99
|
+
| `invalid-catalog` | a marketplace catalog — at the repository root, or at a `--marketplace-root` clone — is not a shape its runtime loads — it is found, read, and refused at install time, in the user's terminal | `/universal-plugin:marketplace` (pnpm install: `pnpm-universal-plugin-marketplace`) |
|
|
100
100
|
| `marketplace-root-missing` | a `--marketplace-root` path does not exist, so it could not be checked at all | clone the marketplace repository, or fix the path |
|
|
101
101
|
|
|
102
102
|
## Catalogs are checked at the repository root
|
|
@@ -105,11 +105,11 @@ The marketplace catalogs sit above the plugin in a monorepo, so the catalog chec
|
|
|
105
105
|
repository root rather than `--root`. It reports only a catalog that would be **refused**: a missing
|
|
106
106
|
one is not a fault, and nothing here has an opinion on which catalogs a repository ought to carry.
|
|
107
107
|
|
|
108
|
-
The detail names the key at fault, so hand it to `/universal-plugin:marketplace` as it stands. An
|
|
108
|
+
The detail names the key at fault, so hand it to `/universal-plugin:marketplace` (pnpm install: `pnpm-universal-plugin-marketplace`) as it stands. An
|
|
109
109
|
entry's fields are derived from the plugin's `plugin.json`, and the catalog's own `name` and `owner`
|
|
110
110
|
are authored in the catalog — which half is at fault decides where the repair goes.
|
|
111
111
|
|
|
112
|
-
A **shared** marketplace repository (e.g. `cyberuni/
|
|
112
|
+
A **shared** marketplace repository (e.g. `cyberuni/cyberplace`) is a repository of its own — a bad
|
|
113
113
|
entry that reached it by another path (a hand-edited entry, a PR from a different tool, a curator
|
|
114
114
|
edit) is invisible to a `doctor` run inside any plugin's own repo, because that run never sees the
|
|
115
115
|
shared repository at all. Clone it separately and name the clone explicitly:
|
|
@@ -157,7 +157,7 @@ holding `0.0.0-development` is reported as `unstamped`, not as `version-drift`.
|
|
|
157
157
|
|
|
158
158
|
Files diverge when someone ran `npm version`, or when a release tool (changesets, release-please,
|
|
159
159
|
semantic-release) moved `package.json` and nothing stamped the number on. All of it is
|
|
160
|
-
`/universal-plugin:version`'s to fix — never patch one file by hand to match another.
|
|
160
|
+
`/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`)'s to fix — never patch one file by hand to match another.
|
|
161
161
|
|
|
162
162
|
### Offer the check to CI
|
|
163
163
|
|
|
@@ -172,7 +172,7 @@ it does not, offer to add it — ask first, because both are the user's files:
|
|
|
172
172
|
semantic-release bot opens.
|
|
173
173
|
|
|
174
174
|
Use the locked `universal-plugin` from the repository's devDependencies when it has one; otherwise
|
|
175
|
-
`npx universal-plugin@0.
|
|
175
|
+
`npx universal-plugin@0.14.1`, pinned. This check matters most where the release tool picks the
|
|
176
176
|
number, because nothing else runs between that bump and publish.
|
|
177
177
|
|
|
178
178
|
## Unreleased content
|
|
@@ -191,7 +191,7 @@ Two cases are deliberately silent. A plugin that declares `packagePath` is skipp
|
|
|
191
191
|
release picks the number ([ADR-0010](https://github.com/cyberuni/universal-plugin/blob/main/packages/universal-plugin/.agents/spec/design/decisions/0010-version-policy.md) §2) and content waiting ahead of the last released version is the
|
|
192
192
|
normal state of a branch. A tree with no git history is skipped rather than guessed at.
|
|
193
193
|
|
|
194
|
-
The repair is the bump, and it belongs to `/universal-plugin:version
|
|
194
|
+
The repair is the bump, and it belongs to `/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`). Judge first whether the change
|
|
195
195
|
is meant to ship — content that is still being worked on is not a finding to act on.
|
|
196
196
|
|
|
197
197
|
## Rules
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/doctor.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/doctor-universal-plugin/scripts/doctor.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import * as path from "node:path";
|
|
@@ -43,7 +43,7 @@ node scripts/init.mjs --name <plugin-name> --vendor claude-code --vendor cursor
|
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
Resolve `scripts/init.mjs` against this skill's directory; it runs the project's installed CLI, else
|
|
46
|
-
the pinned `npx universal-plugin@0.
|
|
46
|
+
the pinned `npx universal-plugin@0.14.1`. Add `--npm` when an npm package ships the plugin,
|
|
47
47
|
which also wires that `package.json`'s `files` to carry the derived manifests, copies its `version`
|
|
48
48
|
into the manifest, and, in a changesets repository, wires the root `version` script to run
|
|
49
49
|
`plugin version --from-package` (SKILL.md Phase 3 asks before that rewrite).
|
|
@@ -122,4 +122,4 @@ rejected by Cursor's own scan.
|
|
|
122
122
|
## Next
|
|
123
123
|
|
|
124
124
|
Shipping it on npm → `migrate-plugin`. Listing it in a marketplace → `publish-plugin`. Releasing a
|
|
125
|
-
number → `/universal-plugin:version
|
|
125
|
+
number → `/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`).
|
|
@@ -86,7 +86,7 @@ what only that component does; the `plugin-design` reference is the authority on
|
|
|
86
86
|
|
|
87
87
|
- **Never hand-edit a derived manifest.** `plugin build` owns `.claude-plugin/plugin.json` and its
|
|
88
88
|
siblings; an edit there survives until the next build and no longer.
|
|
89
|
-
- **Never hand-edit a `version` field.** That move belongs to `/universal-plugin:version
|
|
89
|
+
- **Never hand-edit a `version` field.** That move belongs to `/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`).
|
|
90
90
|
- **The canonical schema is closed.** A vendor-only field cannot be added at the top level; it goes
|
|
91
91
|
under that vendor's `harnesses` entry or nowhere.
|
|
92
92
|
- Root `plugin.json` is not a build artifact. It is both the source of truth and the file Copilot CLI
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/run-cli.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/init-universal-plugin/scripts/init.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
//#region src/compile/scripts.ts
|
|
6
6
|
/** The global the header assigns the script data to. Framework-neutral: a script's own code, or the
|
|
@@ -77,7 +77,7 @@ Copilot CLI. The reverse does not hold: Claude Code rejects the Codex catalog fo
|
|
|
77
77
|
have published will not understand why nobody can install.
|
|
78
78
|
- **Ask before editing the README**, and before `--force` replaces anything a user may have written
|
|
79
79
|
by hand.
|
|
80
|
-
- Listing a plugin in the shared `cyberuni/
|
|
80
|
+
- Listing a plugin in the shared `cyberuni/cyberplace` repository is a different job: use
|
|
81
81
|
`publish-plugin`.
|
|
82
82
|
|
|
83
83
|
## Related skills
|
|
@@ -127,5 +127,5 @@ with the current source, so neither `codex plugin remove` nor a version bump is
|
|
|
127
127
|
the cache when a session starts, so the session you are in keeps the old copy — start a new one.
|
|
128
128
|
|
|
129
129
|
The catalog entry's version is derived from the canonical manifest, so a version move updates both
|
|
130
|
-
(`/universal-plugin:version` owns that). Codex itself does not read the entry's version; keeping it
|
|
130
|
+
(`/universal-plugin:version` (pnpm install: `pnpm-universal-plugin-version`) owns that). Codex itself does not read the entry's version; keeping it
|
|
131
131
|
true is this project's policy, so the catalog never states a version the plugin does not have.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/run-cli.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/marketplace/scripts/add.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
//#region src/compile/scripts.ts
|
|
6
6
|
/** The global the header assigns the script data to. Framework-neutral: a script's own code, or the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/install-docs.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/marketplace/scripts/install-docs.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { execFileSync } from "node:child_process";
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
6
|
import * as path from "node:path";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/run-cli.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/marketplace/scripts/marketplace.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
//#region src/compile/scripts.ts
|
|
6
6
|
/** The global the header assigns the script data to. Framework-neutral: a script's own code, or the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/run-cli.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/marketplace/scripts/validate.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
//#region src/compile/scripts.ts
|
|
6
6
|
/** The global the header assigns the script data to. Framework-neutral: a script's own code, or the
|
|
@@ -12,7 +12,7 @@ for each vendor catalog that exists, then open one PR that updates all of them t
|
|
|
12
12
|
|
|
13
13
|
The plugin being published and the marketplace it is going into are different repos, and the current
|
|
14
14
|
working directory could be either. The skill checks the cwd's remote against the target marketplace
|
|
15
|
-
repo (`cyberuni/
|
|
15
|
+
repo (`cyberuni/cyberplace` by default) before doing anything else:
|
|
16
16
|
|
|
17
17
|
- cwd is the plugin → the marketplace repo gets cloned or forked, as it always did.
|
|
18
18
|
- cwd is already the marketplace → work happens in place; the plugin's metadata is read from wherever
|
|
@@ -30,6 +30,14 @@ nobody can install. The skill lists such a dependency in the same PR, or stops a
|
|
|
30
30
|
published first. A dependency that names another marketplace only needs that marketplace in the
|
|
31
31
|
catalog's `allowCrossMarketplaceDependenciesOn`, which the skill offers to add.
|
|
32
32
|
|
|
33
|
+
## Some marketplaces take no pull requests
|
|
34
|
+
|
|
35
|
+
A curated directory, such as `anthropics/claude-plugins-official`, closes pull requests from
|
|
36
|
+
outsiders and takes new plugins through a form. When the user has only read access to the target,
|
|
37
|
+
the skill reads its workflows and Contributing section live, and, if it is curated, drafts the entry
|
|
38
|
+
in the catalog's own shape and hands over the submission link instead of opening a PR. It checks
|
|
39
|
+
each time rather than storing the catalog's rules, because those rules change.
|
|
40
|
+
|
|
33
41
|
## Why this is not the `marketplace` skill
|
|
34
42
|
|
|
35
43
|
`marketplace` generates a repository's own local catalog — no submission, no shared listing, no PR.
|
|
@@ -5,9 +5,9 @@ description: Use this skill whenever the user wants to publish, release, submit,
|
|
|
5
5
|
|
|
6
6
|
# Publish Universal Plugin
|
|
7
7
|
|
|
8
|
-
Guides adding an already-packaged plugin to a marketplace repo by opening a pull request. Each vendor runtime may have its own marketplace manifest file inside the marketplace repo — update every one that exists.
|
|
8
|
+
Guides adding an already-packaged plugin to a marketplace repo by opening a pull request, or, for a curated marketplace that takes no pull requests, by drafting the submission. Each vendor runtime may have its own marketplace manifest file inside the marketplace repo — update every one that exists.
|
|
9
9
|
|
|
10
|
-
**Default marketplace repo:** `cyberuni/
|
|
10
|
+
**Default marketplace repo:** `cyberuni/cyberplace` (adjust if the user targets a different one)
|
|
11
11
|
|
|
12
12
|
Listing a plugin in a shared repository is not the only way to distribute it. A repository can carry
|
|
13
13
|
its own catalog and let users add it directly as a marketplace. That is the `marketplace` skill; the
|
|
@@ -17,7 +17,7 @@ two compose, and neither replaces the other.
|
|
|
17
17
|
|
|
18
18
|
Publishing has four steps:
|
|
19
19
|
|
|
20
|
-
0. **Locate** — work out which repo is which,
|
|
20
|
+
0. **Locate** — work out which repo is which, where the plugin and the marketplace each live, and whether the marketplace takes PRs at all
|
|
21
21
|
1. **Pre-flight** — validate the plugin is ready
|
|
22
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
|
|
@@ -34,7 +34,7 @@ is the common case.
|
|
|
34
34
|
|
|
35
35
|
### 0a. Identify the marketplace repo
|
|
36
36
|
|
|
37
|
-
Default to `cyberuni/
|
|
37
|
+
Default to `cyberuni/cyberplace` unless the user names another one.
|
|
38
38
|
|
|
39
39
|
### 0b. Identify which repo the cwd is
|
|
40
40
|
|
|
@@ -63,6 +63,36 @@ the user:
|
|
|
63
63
|
Every pre-flight check and entry field in Steps 1–2 reads from the plugin location, not the cwd.
|
|
64
64
|
Step 3 branches on whether the marketplace location is already the cwd.
|
|
65
65
|
|
|
66
|
+
### 0c. Check how the marketplace takes submissions
|
|
67
|
+
|
|
68
|
+
Some marketplaces are curated directories that do not take plugins by pull request, for example
|
|
69
|
+
`anthropics/claude-plugins-official`. Check the target live every time; do not rely on what you
|
|
70
|
+
remember about a catalog, because its rules change.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
gh repo view <marketplace-repo> --json viewerPermission -q .viewerPermission
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If the result is `READ` (no write access):
|
|
77
|
+
|
|
78
|
+
1. List the target's `.github/workflows/` and read any workflow that closes pull requests from
|
|
79
|
+
outsiders. Note what it lets through, if anything.
|
|
80
|
+
2. Read the README's Contributing section (or `CONTRIBUTING.md`) for the submission route.
|
|
81
|
+
|
|
82
|
+
If submission is form-only, or a workflow closes outside pull requests automatically, **do not open
|
|
83
|
+
a PR**. Switch to drafting the submission:
|
|
84
|
+
|
|
85
|
+
- Run Step 1's pre-flight as usual.
|
|
86
|
+
- Resolve dependencies (2f) against the target's **live** catalog, read from its default branch. A
|
|
87
|
+
plain dependency the catalog does not list cannot be added through a form, so tell the user it
|
|
88
|
+
will not resolve there.
|
|
89
|
+
- Write the entry in the shape the catalog's existing entries use, not the shape in 2c. For example,
|
|
90
|
+
when existing entries pin `git-subdir` sources with `ref` and `sha`, use the plugin's release tag
|
|
91
|
+
and that tag's commit.
|
|
92
|
+
- Hand the user the drafted entry and the submission link the target names. Skip Step 3.
|
|
93
|
+
|
|
94
|
+
Otherwise (write access, or a fork-and-PR route the target accepts), continue to Step 1.
|
|
95
|
+
|
|
66
96
|
---
|
|
67
97
|
|
|
68
98
|
## Step 1: Pre-flight validation
|
|
@@ -279,15 +309,15 @@ Otherwise, the marketplace repo is elsewhere and needs a working copy. If the us
|
|
|
279
309
|
(org member), work directly:
|
|
280
310
|
|
|
281
311
|
```bash
|
|
282
|
-
gh repo clone cyberuni/
|
|
283
|
-
cd
|
|
312
|
+
gh repo clone cyberuni/cyberplace
|
|
313
|
+
cd cyberplace
|
|
284
314
|
```
|
|
285
315
|
|
|
286
316
|
If a fork is needed:
|
|
287
317
|
|
|
288
318
|
```bash
|
|
289
|
-
gh repo fork cyberuni/
|
|
290
|
-
cd
|
|
319
|
+
gh repo fork cyberuni/cyberplace --clone --remote
|
|
320
|
+
cd cyberplace
|
|
291
321
|
git fetch upstream && git merge upstream/main
|
|
292
322
|
```
|
|
293
323
|
|
|
@@ -316,7 +346,7 @@ git push origin add-<plugin-name>
|
|
|
316
346
|
|
|
317
347
|
```bash
|
|
318
348
|
gh pr create \
|
|
319
|
-
--repo cyberuni/
|
|
349
|
+
--repo cyberuni/cyberplace \
|
|
320
350
|
--title "Add <plugin-name> v<version>" \
|
|
321
351
|
--body "$(cat <<'EOF'
|
|
322
352
|
## Plugin
|
|
@@ -377,6 +407,7 @@ Return the PR URL to the user when done.
|
|
|
377
407
|
| 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 |
|
|
378
408
|
| Install fails resolving a dependency | 2f was skipped — list the plain dependency in this marketplace, or allow the named marketplace in `allowCrossMarketplaceDependenciesOn` |
|
|
379
409
|
| `marketplace validate` fails after 2g | Fix the reported shape before opening the PR — do not open it while validation fails |
|
|
410
|
+
| PR closed automatically as soon as it opened | The target is curated — redo 0c and use its submission route instead of a PR |
|
|
380
411
|
| 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 |
|
|
381
412
|
|
|
382
413
|
---
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
"id": 4,
|
|
24
|
-
"prompt": "My plugin 'foo' lives at packages/foo/plugin.json inside a monorepo (the repo root only has a marketplace.json catalog, no plugin.json). Publish it to cyberuni/
|
|
24
|
+
"prompt": "My plugin 'foo' lives at packages/foo/plugin.json inside a monorepo (the repo root only has a marketplace.json catalog, no plugin.json). Publish it to cyberuni/cyberplace.",
|
|
25
25
|
"expected_output": "Determines the plugin is not at the repo root and has no npm packagePath, so decides source type git-subdir rather than a root-clone url. Writes { \"source\": \"git-subdir\", \"url\": \"<clone-url>.git\", \"path\": \"packages/foo\" } in the marketplace entry. Runs marketplace validate against the marketplace working copy before opening the PR, and does not proceed if it fails.",
|
|
26
26
|
"files": []
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"id": 5,
|
|
30
|
-
"prompt": "I'm a maintainer of cyberuni/
|
|
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/
|
|
30
|
+
"prompt": "I'm a maintainer of cyberuni/cyberplace 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
|
+
"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/cyberplace again. The prepared entry's source/repository URL points at db-migrate's repo, not at cyberuni/cyberplace.",
|
|
32
32
|
"files": []
|
|
33
33
|
},
|
|
34
34
|
{
|
|
@@ -36,6 +36,12 @@
|
|
|
36
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
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
38
|
"files": []
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": 7,
|
|
42
|
+
"prompt": "Publish cyber-asana (in ~/code/cyber-asana, a monorepo with the plugin at packages/cyber-asana, released as tag cyber-asana@1.2.0) to anthropics/claude-plugins-official. Its plugin.json declares the plain dependency \"cyber-agent-harness\".",
|
|
43
|
+
"expected_output": "Before preparing a PR, runs `gh repo view anthropics/claude-plugins-official --json viewerPermission`, sees READ, then reads the target's .github/workflows/ for a workflow that closes outside PRs and its README's Contributing section. Concludes the catalog is curated (outside PRs are closed automatically; new plugins go through a submission form), so it does not clone, fork, branch, push, or open a PR. Runs pre-flight, resolves cyber-agent-harness against the target's live catalog and tells the user it will not resolve there, and drafts the entry in the shape the catalog's existing entries use (e.g. a git-subdir source pinned with the release tag as ref and that tag's commit as sha). Hands the user the draft and the submission form link the target names. Does not rely on remembered facts about that catalog.",
|
|
44
|
+
"files": []
|
|
39
45
|
}
|
|
40
46
|
]
|
|
41
47
|
}
|
|
@@ -49,7 +49,7 @@ Copilot CLI's search order is `.plugin/plugin.json` → `plugin.json` → `.gith
|
|
|
49
49
|
|
|
50
50
|
Removing a vendor is a manifest edit first and a deletion second — deleting only the file leaves the
|
|
51
51
|
vendor declared, and the next build writes it straight back. That edit belongs to
|
|
52
|
-
`/universal-plugin:init-universal-plugin`'s update route; come back here for the file.
|
|
52
|
+
`/universal-plugin:init-universal-plugin` (pnpm install: `pnpm-universal-plugin-init-universal-plugin`)'s update route; come back here for the file.
|
|
53
53
|
|
|
54
54
|
## Remove the whole plugin
|
|
55
55
|
|
package/skills/version/SKILL.md
CHANGED
|
@@ -74,7 +74,7 @@ node scripts/version.mjs --from-package
|
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
Resolve that path against this skill's own directory; it runs the project's installed CLI
|
|
77
|
-
(`pnpm exec universal-plugin`), else `npx universal-plugin@0.
|
|
77
|
+
(`pnpm exec universal-plugin`), else `npx universal-plugin@0.14.1` pinned to this skill's version.
|
|
78
78
|
`universal-plugin plugin version` on the `PATH` is the fallback. The command never prompts, so it is safe to run unattended once the
|
|
79
79
|
source is decided.
|
|
80
80
|
|
|
@@ -123,7 +123,7 @@ Every guard resolves before the first write, so a failed run leaves the tree unt
|
|
|
123
123
|
|
|
124
124
|
| Message names | What it means | Do this |
|
|
125
125
|
|---|---|---|
|
|
126
|
-
| a missing `plugin.json` | not at a plugin root, or the plugin was never scaffolded | `cd` to the plugin root, or run `/universal-plugin:init-universal-plugin` |
|
|
126
|
+
| a missing `plugin.json` | not at a plugin root, or the plugin was never scaffolded | `cd` to the plugin root, or run `/universal-plugin:init-universal-plugin` (pnpm install: `pnpm-universal-plugin-init-universal-plugin`) |
|
|
127
127
|
| 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 |
|
|
128
128
|
| 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 |
|
|
129
129
|
| 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 |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Compiled by `universal-plugin plugin build` from src/skill-scripts/run-cli.ts. Edit the source, not this file.
|
|
3
|
-
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.
|
|
3
|
+
globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.14.1","entry":"skills/version/scripts/version.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace validate":"skills/marketplace/scripts/validate.mjs","plugin build":"skills/build-plugin/scripts/build.mjs","plugin init":"skills/init-universal-plugin/scripts/init.mjs","plugin version":"skills/version/scripts/version.mjs"}};
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
//#region src/compile/scripts.ts
|
|
6
6
|
/** The global the header assigns the script data to. Framework-neutral: a script's own code, or the
|