universal-plugin 0.17.0 → 0.18.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 (37) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/.cursor-plugin/plugin.json +1 -1
  4. package/CHANGELOG.md +28 -0
  5. package/agents/agentskills-specialist.md +6 -11
  6. package/com.github.copilot/agents/agentskills-specialist.agent.md +6 -11
  7. package/dist/cli.mjs +164 -12
  8. package/package.json +1 -1
  9. package/plugin.json +1 -1
  10. package/readme.md +1 -1
  11. package/references/plugin-design.md +19 -33
  12. package/references/slash-invocation.md +2 -2
  13. package/skills/adopt-upx/scripts/rewrite-upx.mjs +1 -1
  14. package/skills/build-plugin/SKILL.md +2 -3
  15. package/skills/build-plugin/scripts/build.mjs +1 -1
  16. package/skills/doctor-universal-plugin/README.md +1 -1
  17. package/skills/doctor-universal-plugin/SKILL.md +18 -6
  18. package/skills/doctor-universal-plugin/scripts/doctor.mjs +225 -2
  19. package/skills/init-universal-plugin/README.md +1 -1
  20. package/skills/init-universal-plugin/SKILL.md +62 -3
  21. package/skills/init-universal-plugin/references/create.md +10 -7
  22. package/skills/init-universal-plugin/references/detection.md +1 -1
  23. package/skills/init-universal-plugin/references/frontmatter.md +1 -1
  24. package/skills/init-universal-plugin/references/release-tools.md +272 -0
  25. package/skills/init-universal-plugin/references/standard.md +3 -3
  26. package/skills/init-universal-plugin/references/vendors/copilot-cli.md +3 -0
  27. package/skills/init-universal-plugin/scripts/init.mjs +1 -1
  28. package/skills/marketplace/scripts/add.mjs +1 -1
  29. package/skills/marketplace/scripts/install-docs.mjs +1 -1
  30. package/skills/marketplace/scripts/marketplace.mjs +1 -1
  31. package/skills/marketplace/scripts/update.mjs +1 -1
  32. package/skills/marketplace/scripts/validate.mjs +1 -1
  33. package/skills/migrate-plugin/SKILL.md +1 -2
  34. package/skills/publish-plugin/SKILL.md +7 -6
  35. package/skills/version/README.md +7 -3
  36. package/skills/version/SKILL.md +129 -10
  37. package/skills/version/scripts/version.mjs +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: version
3
- description: Use this skill to move a universal agent plugin's version — bump it, set an explicit one, cut a release number, or reconcile a version that drifted between the canonical plugin.json and its npm package.json. Handles every release model: a plain repository, where the author picks the number, and a release tool (changesets, release-please, semantic-release) that decides it and hands it to plugin version to stamp everywhere. Trigger on "bump the plugin version", "release a new version of this plugin", "set the plugin version to 1.0.0", "cut a patch release", or "the manifest and package.json versions disagree".
3
+ description: Use this skill to move a universal agent plugin's version — bump it, set an explicit one, cut a release number, or reconcile a version that drifted between the canonical plugin.json and its npm package.json. Handles every release model: a plain repository, where the author picks the number, and a release tool (changesets, release-please, semantic-release, release-it) that decides it and hands it to plugin version to stamp everywhere. Trigger on "bump the plugin version", "release a new version of this plugin", "set the plugin version to 1.0.0", "cut a patch release", or "the manifest and package.json versions disagree".
4
4
  ---
5
5
 
6
6
  # Move a plugin's version
@@ -34,11 +34,13 @@ Ask who decides the number. There are three sources, and the release model picks
34
34
  | Source | Call | Used by |
35
35
  |---|---|---|
36
36
  | Author bump | `plugin version minor` | Plain repositories, with no `packagePath` |
37
- | Explicit number | `plugin version 1.4.0` | semantic-release |
38
- | The package's `package.json` | `plugin version --from-package` | changesets, release-please |
37
+ | Explicit number | `plugin version 1.4.0` | semantic-release, release-it |
38
+ | The package's `package.json` | `plugin version --from-package` | changesets, release-please with an npm package |
39
+ | The canonical `plugin.json` | `plugin version --from-manifest` | release-please with no `package.json` (`extra-files`) |
39
40
 
40
41
  ```bash
41
42
  test -d .changeset && echo "changesets"
43
+ ls .release-it.* 2>/dev/null; grep -q '"release-it"' package.json 2>/dev/null && echo "release-it"
42
44
  cat .agents/universal-plugin.json # is packagePath declared?
43
45
  ```
44
46
 
@@ -51,10 +53,14 @@ Wire a release tool once; after that the release runs the stamp for you:
51
53
 
52
54
  - **changesets.** Root `version` script: `changeset version && universal-plugin plugin version --from-package --root <plugin>`.
53
55
  `init-universal-plugin --npm` writes it.
54
- - **release-please.** Run `universal-plugin plugin version --from-package` after the release PR
55
- bumps the package.
56
+ - **release-please, npm package.** Run `universal-plugin plugin version --from-package` after the
57
+ release PR bumps the package.
58
+ - **release-please, no `package.json`.** `extra-files` bumps `plugin.json`, and a workflow step on the
59
+ release PR runs `universal-plugin plugin version --from-manifest`. See the section below.
56
60
  - **semantic-release.** Add `@semantic-release/exec` with
57
61
  `prepareCmd: "universal-plugin plugin version ${nextRelease.version}"`.
62
+ - **release-it.** Run the stamp in the `after:bump` hook. For a plugin that ships to no npm package,
63
+ set `"npm": false` so release-it ignores `package.json`; see below.
58
64
 
59
65
  In a changesets repository, add a changeset and let the release run. Do not run `plugin version minor`
60
66
  there: it would decide a number changesets is about to decide again.
@@ -64,17 +70,128 @@ there: it would decide a number changesets is about to decide again.
64
70
  The stamped files exist only in the npm package unless `@semantic-release/git` commits them back.
65
71
  Git-sourced installs (Copilot CLI, GitHub-hosted marketplaces) read `plugin.json` from the repository,
66
72
  so for those channels the commit-back is required. Without it they are unsupported. Set `assets` to
67
- `plugin.json`, the vendor manifests, `skills/**`, `.plugin/pins.json`, and the mcp file.
73
+ `plugin.json`, the vendor manifests, the repository catalogs (`.claude-plugin/marketplace.json`,
74
+ `.cursor-plugin/marketplace.json`, `.agents/plugins/marketplace.json`,
75
+ `.github/plugin/marketplace.json`), `skills/**`, `.plugin/pins.json`, and the mcp file. The stamp
76
+ re-derives the catalogs too, so leaving them out leaves them a release behind.
77
+
78
+ `doctor` reports `semantic-release-no-stamp` when no `prepareCmd` runs `plugin version`, and
79
+ `semantic-release-npm-unshipped` when a plugin that ships to no npm package still runs
80
+ `@semantic-release/npm`.
81
+
82
+ ### release-please with no `package.json`
83
+
84
+ release-please releases a plugin with no `package.json`. `release-type: simple` keeps the number in
85
+ `.release-please-manifest.json` (`{ ".": "1.2.3" }`) and updates only `CHANGELOG.md` and a
86
+ `version.txt` it skips when absent. `extra-files` bumps `plugin.json`:
87
+
88
+ ```json
89
+ {
90
+ "packages": {
91
+ ".": {
92
+ "release-type": "simple",
93
+ "extra-files": [{ "type": "json", "path": "plugin.json", "jsonpath": "$.version" }]
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ release-please runs no command before its release commit, so the vendor manifests, catalogs, skill
100
+ pins and compiled scripts stay on the old number. Restamp the release PR in the same workflow, right
101
+ after the action. `--from-manifest` takes the number `plugin.json` already holds.
102
+
103
+ Both pushes need a token that starts workflow runs. A push made with the default `GITHUB_TOKEN`
104
+ starts none, so the release PR's checks would never run on its head commit, and a required check
105
+ would block the merge. Mint a GitHub App token for the run and give it to release-please and to
106
+ `actions/checkout`, which pushes the restamp with it:
107
+
108
+ ```yaml
109
+ on:
110
+ push:
111
+ branches: [main]
112
+ permissions:
113
+ contents: read
114
+ jobs:
115
+ release-please:
116
+ runs-on: ubuntu-latest
117
+ steps:
118
+ - id: app-token
119
+ uses: actions/create-github-app-token@v3
120
+ with:
121
+ client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
122
+ private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
123
+ - id: release
124
+ uses: googleapis/release-please-action@v4
125
+ with:
126
+ token: ${{ steps.app-token.outputs.token }}
127
+ - if: ${{ steps.release.outputs.prs_created == 'true' }}
128
+ uses: actions/checkout@v4
129
+ with:
130
+ ref: ${{ fromJSON(steps.release.outputs.pr).headBranchName }}
131
+ token: ${{ steps.app-token.outputs.token }}
132
+ - if: ${{ steps.release.outputs.prs_created == 'true' }}
133
+ run: |
134
+ npx -y universal-plugin@0.18.0 plugin version --from-manifest
135
+ git config user.name "github-actions[bot]"
136
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
137
+ git add -A
138
+ git diff --cached --quiet || { git commit -m "chore: restamp the plugin version"; git push; }
139
+ ```
140
+
141
+ Set the App up once:
142
+
143
+ 1. Create a GitHub App with the repository permissions Contents, Pull requests and Issues set to
144
+ read and write. release-please labels its PR through the Issues API.
145
+ 2. Install it on the repository.
146
+ 3. Store its client ID as the variable `RELEASE_APP_CLIENT_ID` and a private key as the secret
147
+ `RELEASE_APP_PRIVATE_KEY`.
148
+
149
+ The workflow's own `GITHUB_TOKEN` then needs only `contents: read`, because every write goes through
150
+ the App token.
151
+
152
+ - release-please force-pushes its branch each time it updates the PR, which drops the restamp commit.
153
+ The action reports an updated PR in `prs_created` as well, so the step runs again and restamps it.
154
+ - The App token is minted for this run, expires within an hour, and is revoked when the job ends.
155
+ The private key is the one standing secret, and it reaches only the repositories the App is
156
+ installed on. A personal access token works too, but it is long-lived and acts as a person.
157
+ - Do not re-run CI with `workflow_dispatch` (`gh workflow run`) instead. Checks from a
158
+ `workflow_dispatch` run do not count toward a required check.
159
+ - Do not list the stamped files in `extra-files` instead. The skill pins and the compiled script
160
+ headers are not a `$.version` field, and the vendor manifests and catalogs belong to `plugin build`.
161
+ - With `packagePath` declared, bump the package and run `--from-package` instead. `--from-manifest` is
162
+ refused there.
163
+
164
+ `doctor` reports `release-please-no-restamp` when `extra-files` bumps `plugin.json` and no workflow runs
165
+ `plugin version`, and `release-please-restamp-no-ci` when the restamp is pushed with the default
166
+ `GITHUB_TOKEN`.
167
+
168
+ ### release-it reads the version from the git tag
169
+
170
+ With `"npm": false`, release-it needs no `package.json`. Its `after:bump` hook runs before the release
171
+ commit and tag, and the commit includes every tracked file the hook changed, so the stamp ships in the
172
+ tagged commit. In `.release-it.json`:
173
+
174
+ ```json
175
+ {
176
+ "npm": false,
177
+ "hooks": { "after:bump": "universal-plugin plugin version ${version}" }
178
+ }
179
+ ```
180
+
181
+ Before the first release, tag the commit that carries the current version (`git tag v1.2.0`).
182
+ release-it reads the tag, not `plugin.json`: without one it starts from `0.0.0`, and
183
+ `plugin version` refuses a number that does not advance.
68
184
 
69
185
  ## Step 2 — Run it
70
186
 
71
187
  ```bash
72
188
  node scripts/version.mjs <bump-or-number>
73
189
  node scripts/version.mjs --from-package
190
+ node scripts/version.mjs --from-manifest
74
191
  ```
75
192
 
76
193
  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.17.0` pinned to this skill's version.
194
+ (`pnpm exec universal-plugin`), else `npx universal-plugin@0.18.0` pinned to this skill's version.
78
195
  `universal-plugin plugin version` on the `PATH` is the fallback. The command never prompts, so it is safe to run unattended once the
79
196
  source is decided.
80
197
 
@@ -89,6 +206,7 @@ source is decided.
89
206
  | Flag | Effect |
90
207
  |---|---|
91
208
  | `--from-package` | Take the version the package's `package.json` already holds |
209
+ | `--from-manifest` | Restamp at the version `plugin.json` already holds; refused under `packagePath` |
92
210
  | `--preid <id>` | Prerelease identifier for the `pre*` release types |
93
211
  | `--dry-run` | Print the plan, write nothing. Run this first when unsure |
94
212
  | `--force` | Allow a target that does not advance on the current version |
@@ -129,6 +247,7 @@ Every guard resolves before the first write, so a failed run leaves the tree unt
129
247
  | 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 |
130
248
  | a release type under `packagePath` | the package owns the number | bump the package with the release tool, then `plugin version --from-package` |
131
249
  | `0.0.0-development` from `--from-package` | semantic-release's placeholder, not a release | pass the explicit number instead |
250
+ | `--from-manifest` under `packagePath` | the package owns the number | run `--from-package` instead |
132
251
  | a missing `package.json` at `packagePath` | `.agents/universal-plugin.json` names a package directory that does not exist | fix `packagePath`, or create the package |
133
252
 
134
253
  ## Do not
@@ -138,8 +257,8 @@ Every guard resolves before the first write, so a failed run leaves the tree unt
138
257
  `plugin build`; the bump already re-derived them.
139
258
  - **Run `npm version`.** It knows only `package.json` and leaves the canonical manifest and the
140
259
  skill pins stale.
141
- - **Use the deprecated commands.** `plugin bundle` and `publish sync-version` print a warning and are
142
- removed in the next minor release. `sync-version` now runs `plugin version --from-package`.
260
+ - **Use the deprecated commands.** `plugin bundle` and `publish sync-version` print a deprecation
261
+ warning; use `plugin version` instead. `sync-version` now runs `plugin version --from-package`.
143
262
 
144
263
  ## Related skills
145
264
 
@@ -148,7 +267,7 @@ Every guard resolves before the first write, so a failed run leaves the tree unt
148
267
  | Create, adopt, or change what the plugin declares | `init-universal-plugin` |
149
268
  | Re-derive the vendor manifests by hand | `build-plugin` |
150
269
  | Check whether every place agrees (`unstamped`, `version-drift`) | `doctor-universal-plugin` |
151
- | Add a changeset for the change being released | `add-changeset` |
270
+ | Add a changeset for the change being released | `buddy-changesets:changesets` |
152
271
  | Refresh the repository's own marketplace catalogs after a bump | `marketplace` |
153
272
  | List the released plugin in the shared marketplace | `publish-plugin` |
154
273
 
@@ -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.17.0","entry":"skills/version/scripts/version.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace update":"skills/marketplace/scripts/update.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"}};
3
+ globalThis.__SKILL_SCRIPT__ = {"package":"universal-plugin","bin":"universal-plugin","version":"0.18.0","entry":"skills/version/scripts/version.mjs","commands":{"marketplace add":"skills/marketplace/scripts/add.mjs","marketplace init":"skills/marketplace/scripts/marketplace.mjs","marketplace update":"skills/marketplace/scripts/update.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