@gleanwork/pluginpack 0.5.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/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ - Initial prerelease.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Glean
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,482 @@
1
+ # pluginpack
2
+
3
+ [![Experimental](https://img.shields.io/badge/-Experimental-D8FD49?style=flat-square&logo=data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0yNC4zMDA2IDIuOTU0MjdMMjAuNzY1NiAwLjE5OTk1MUwxNy45MDI4IDMuOTk1MjdDMTMuNTY1MyAxLjkzNDk1IDguMjMwMTkgMy4wODQzOSA1LjE5Mzk0IDcuMDA5ODNDMS42NTg4OCAxMS41NjQyIDIuNDgzIDE4LjExMzggNy4wMzczOCAyMS42NDg5QzguNzcyMzggMjIuOTkzNSAxMC43ODkzIDIzLjcwOTIgMTIuODI3OSAyMy44MTc3QzE2LjE0NjEgMjQuMDEyOCAxOS41MDc3IDIyLjYyNDggMjEuNjc2NSAxOS44MDU1QzI0LjczNDQgMTUuODggMjQuNTE3NSAxMC40MTQ4IDIxLjQ1OTYgNi43Mjc4OUwyNC4zMDA2IDIuOTU0MjdaTTE4LjExOTcgMTcuMDUxMkMxNi4xMDI4IDE5LjYzMiAxMi4zNzI1IDIwLjEwOTEgOS43NzAwMSAxOC4wOTIyQzcuMTg5MTkgMTYuMDc1MiA2LjcxMjA3IDEyLjMyMzMgOC43MjkwMSA5Ljc0MjQ2QzkuNzA0OTQgOC40ODQ1OCAxMS4xMTQ2IDcuNjgyMTQgMTIuNjc2MSA3LjQ4Njk2QzEzLjA0NDggNy40NDM1OCAxMy40MTM1IDcuNDIxOSAxMy43ODIyIDcuNDQzNThDMTQuOTc1IDcuNTA4NjUgMTYuMTI0NCA3Ljk0MjM5IDE3LjA3ODcgOC42Nzk3N0MxOS42NTk1IDEwLjcxODQgMjAuMTM2NiAxNC40NzAzIDE4LjExOTcgMTcuMDUxMloiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0yNC41MTc2IDIxLjY5MjJDMjMuOTMyIDIyLjQ1MTMgMjMuMjgxNCAyMy4xMjM2IDIyLjU2NTcgMjMuNzUyNUMyMS44NzE3IDI0LjMzODEgMjEuMTEyNyAyNC44ODAzIDIwLjMxMDIgMjUuMzM1N0MxOS41Mjk1IDI1Ljc2OTUgMTguNjgzNyAyNi4xMzgyIDE3LjgzNzggMjYuNDIwMUMxNi45OTIgMjYuNzAyIDE2LjEwMjggMjYuODk3MiAxNS4yMTM3IDI3LjAwNTdDMTQuMzI0NSAyNy4xMTQxIDEzLjQzNTMgMjcuMTU3NSAxMi41MjQ0IDI3LjA5MjRDMTEuNjEzNSAyNy4wMjczIDEwLjcyNDMgMjYuODc1NSA5Ljg1Njg0IDI2LjY1ODdMOS42NjE2NSAyNy4zNzQzTDguNzcyNDYgMzAuOTk2MkM5LjkwMDIxIDMxLjI5OTggMTEuMDQ5NyAzMS40NzMzIDEyLjIyMDggMzEuNTZDMTIuMjY0MiAzMS41NiAxMi4zMjkyIDMxLjU2IDEyLjM3MjYgMzEuNTZDMTMuNTAwMyAzMS42MjUxIDE0LjY0OTggMzEuNTgxNyAxNS43NTU4IDMxLjQ1MTZDMTYuOTI3IDMxLjI5OTggMTguMDk4MSAzMS4wMzk1IDE5LjIyNTggMzAuNjcwOEMyMC4zNTM2IDMwLjMwMjIgMjEuNDU5NyAyOS44MjUgMjIuNTAwNyAyOS4yMzk1QzIzLjU2MzQgMjguNjUzOSAyNC41NjEgMjcuOTM4MiAyNS40OTM1IDI3LjE1NzVDMjYuNDQ3OCAyNi4zNTUgMjcuMzE1MyAyNS40NDQyIDI4LjA3NDQgMjQuNDQ2NUMyOC4xODI4IDI0LjMxNjQgMjguMjY5NSAyNC4xNjQ2IDI4LjM3OCAyNC4wMTI4TDI0Ljc3NzkgMjEuMzQ1MkMyNC42Njk0IDIxLjQ1MzcgMjQuNjA0NCAyMS41ODM4IDI0LjUxNzYgMjEuNjkyMloiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPg==&labelColor=343CED)](https://github.com/gleanwork/.github/blob/main/docs/repository-stability.md#experimental)
4
+ [![npm version](https://img.shields.io/npm/v/@gleanwork/pluginpack.svg)](https://www.npmjs.com/package/@gleanwork/pluginpack)
5
+ [![CI](https://github.com/gleanwork/pluginpack/actions/workflows/ci.yml/badge.svg)](https://github.com/gleanwork/pluginpack/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ One source of truth for agent plugins across AI app ecosystems.
9
+
10
+ `pluginpack` is a build tool for compiling portable skills, commands, agents, rules, hooks, assets, and metadata into the native plugin layouts expected by each AI app. It copies files, writes target manifests, and validates generated output; it is not a package manager or publisher.
11
+
12
+ <p align="center">
13
+ <img src="assets/pluginpack-flow.svg" alt="pluginpack packages source components into Claude, Cursor, Antigravity, and Copilot plugin targets">
14
+ </p>
15
+
16
+ ## Quick Start
17
+
18
+ Start with portable plugin components, declare the native targets you want, then run `pluginpack build`.
19
+
20
+ ```bash snippet=readme/snippet-01.bash
21
+ npm install -D @gleanwork/pluginpack
22
+ ```
23
+
24
+ Create repo-level component directories:
25
+
26
+ ```tree
27
+ skills/
28
+ release-notes/
29
+ SKILL.md
30
+ agents/
31
+ search-assistant.md
32
+ commands/
33
+ summarize.md
34
+ rules/
35
+ style.mdc
36
+ hooks/
37
+ before-run.sh
38
+ assets/
39
+ icon.png
40
+ pluginpack.config.ts
41
+ ```
42
+
43
+ Add a config that maps that portable source into native plugin outputs. `source.skills` gives the repo a simple portable install surface; sibling component directories are included when the selected target supports them or when you opt into them with `components`.
44
+
45
+ ```ts snippet=readme/snippet-02.ts
46
+ import { defineConfig } from "@gleanwork/pluginpack";
47
+
48
+ export default defineConfig({
49
+ name: "acme-plugins",
50
+ version: "0.1.0",
51
+ source: {
52
+ skills: "skills",
53
+ rootPlugin: {
54
+ id: "core",
55
+ description: "Acme portable skills.",
56
+ },
57
+ },
58
+ metadata: {
59
+ description: "Acme agent plugins.",
60
+ author: { name: "Acme" },
61
+ license: "MIT",
62
+ },
63
+ targets: {
64
+ cursor: {
65
+ outDir: ".",
66
+ plugins: {
67
+ acme: {
68
+ from: ["core"],
69
+ path: "plugins/cursor/acme",
70
+ },
71
+ },
72
+ },
73
+ claude: {
74
+ outDir: ".",
75
+ pluginRoot: "plugins/claude",
76
+ plugins: {
77
+ acme: { from: ["core"] },
78
+ },
79
+ },
80
+ antigravity: {
81
+ outDir: "plugins/antigravity",
82
+ plugins: {
83
+ acme: { from: ["core"] },
84
+ },
85
+ },
86
+ copilot: {
87
+ outDir: "plugins/copilot",
88
+ plugins: {
89
+ acme: { from: ["core"] },
90
+ },
91
+ },
92
+ },
93
+ });
94
+ ```
95
+
96
+ Build and validate the generated outputs:
97
+
98
+ ```bash
99
+ npx pluginpack build
100
+ npx pluginpack validate --target cursor
101
+ ```
102
+
103
+ Users who only want portable skills install from the `skills/` subpath, for example `npx skills add owner/repo/skills --skill '*'`. Claude, Cursor, Antigravity, and Copilot users install from the generated native layout that can include skills, agents, rules, hooks, assets, MCP config, and target-specific manifests.
104
+
105
+ ## Mental Model
106
+
107
+ Agent apps increasingly support similar ideas: skills, commands, agents, rules, hooks, MCP configuration, and plugin marketplaces. The packaging formats are different enough that maintaining one repo per app quickly drifts.
108
+
109
+ `pluginpack` does four things:
110
+
111
+ - reads a portable source plugin from your repo
112
+ - copies selected component directories into each target
113
+ - writes the manifests each target expects
114
+ - validates, diffs, prunes, and cleans generated output
115
+
116
+ It does not try to make every app behave the same. Target adapters own target-specific layout, manifests, and validation.
117
+
118
+ ## Recommended Shape
119
+
120
+ The preferred path is one public plugin repository with top-level component directories. `skills/` remains the portable `skills` CLI install surface, while the other component directories feed native plugin outputs.
121
+
122
+ ```tree
123
+ skills/
124
+ release-notes/
125
+ SKILL.md
126
+ agents/
127
+ search-assistant.md
128
+ commands/
129
+ summarize.md
130
+ rules/
131
+ style.mdc
132
+ hooks/
133
+ before-run.sh
134
+ assets/
135
+ icon.png
136
+ pluginpack.config.ts
137
+
138
+ .cursor-plugin/
139
+ marketplace.json
140
+ plugins/
141
+ cursor/
142
+ acme/
143
+ .cursor-plugin/plugin.json
144
+ agents/
145
+ rules/
146
+ hooks/
147
+ skills/
148
+ claude/
149
+ acme/
150
+ .claude-plugin/plugin.json
151
+ agents/
152
+ hooks/
153
+ skills/
154
+ antigravity/
155
+ .pluginpack/
156
+ antigravity.json
157
+ acme/
158
+ mcp_config.json
159
+ plugin.json
160
+ agents/
161
+ rules/
162
+ hooks/
163
+ skills/
164
+ copilot/
165
+ .claude-plugin/
166
+ marketplace.json
167
+ .github/
168
+ plugin/
169
+ marketplace.json
170
+ .pluginpack/
171
+ copilot.json
172
+ plugins/
173
+ acme/
174
+ agents/
175
+ hooks/
176
+ skills/
177
+ .claude-plugin/
178
+ marketplace.json
179
+ .pluginpack/
180
+ cursor.json
181
+ claude.json
182
+ ```
183
+
184
+ `source.skills` points at the repo-level skills directory and creates a root source plugin from the sibling component directories. `source.rootPlugin.id` creates the source plugin name used by each target's `from` array. The repo root is intentionally also home to generated native plugin outputs, so the `skills/` subpath keeps `skills` CLI discovery focused on the canonical portable skills.
185
+
186
+ `pluginpack` writes a `.pluginpack/<target>.json` managed-file manifest for each built target. That manifest lets builds and cleanup commands remove stale generated files without touching source files or unmanaged repo content.
187
+
188
+ ## Components
189
+
190
+ In `pluginpack`, a component is a top-level plugin capability directory. Components are the portable pieces of a source plugin that may or may not exist in every target ecosystem.
191
+
192
+ Supported component directories are:
193
+
194
+ ```txt
195
+ skills/
196
+ agents/
197
+ commands/
198
+ rules/
199
+ hooks/
200
+ scripts/
201
+ assets/
202
+ policies/
203
+ themes/
204
+ ```
205
+
206
+ Target adapters translate those component directories into each app's native layout and manifest fields. Each target has a smart default component list. By default, `claude`, `cursor`, `antigravity`, and `copilot` emit skills and other native plugin support files but omit `commands`, since those ecosystems increasingly expose skills as slash commands.
207
+
208
+ Use `components` only when a plugin needs an exact target-specific component set:
209
+
210
+ ```ts snippet=readme/snippet-03.ts
211
+ import { defineConfig } from "@gleanwork/pluginpack";
212
+
213
+ export default defineConfig({
214
+ name: "acme-plugins",
215
+ version: "0.1.0",
216
+ source: {
217
+ skills: "skills",
218
+ rootPlugin: {
219
+ id: "core",
220
+ description: "Acme portable skills.",
221
+ },
222
+ },
223
+ metadata: {
224
+ description: "Acme agent plugins.",
225
+ author: { name: "Acme" },
226
+ license: "MIT",
227
+ },
228
+ targets: {
229
+ antigravity: {
230
+ outDir: "plugins/antigravity",
231
+ plugins: {
232
+ acme: { from: ["core"], components: ["skills", "commands"] },
233
+ },
234
+ },
235
+ claude: {
236
+ outDir: "plugins/claude",
237
+ plugins: {
238
+ acme: { from: ["core"], components: ["skills"] },
239
+ },
240
+ },
241
+ },
242
+ });
243
+ ```
244
+
245
+ ## Targets
246
+
247
+ The first adapters are:
248
+
249
+ - `cursor`
250
+ - `claude`
251
+ - `antigravity`
252
+ - `copilot`
253
+
254
+ `cursor` emits Cursor plugin and marketplace manifests. `claude` emits Claude plugin and marketplace manifests. `antigravity` emits Antigravity CLI plugins with a `plugin.json` manifest and optional `mcp_config.json`. `copilot` emits the GitHub Copilot plugins format (per [`github/copilot-plugins`](https://github.com/github/copilot-plugins)): a `.claude-plugin/marketplace.json` mirrored to `.github/plugin/marketplace.json`, each plugin under `plugins/<name>/` with a `skills` array per marketplace entry.
255
+
256
+ Because Copilot reuses the Claude marketplace layout, the `claude` and `copilot` targets both write `.claude-plugin/marketplace.json` and therefore need separate output roots (distinct `outDir`s or separate repos).
257
+
258
+ More targets should be added from official docs or real plugin examples, not guessed abstractions.
259
+
260
+ ## Source Plugins
261
+
262
+ The quick-start shape treats repo-level component directories as one source plugin. For more complex source content, keep source plugins under `plugins/` and emit them into one or more target outputs:
263
+
264
+ ```tree
265
+ plugins/
266
+ core/
267
+ plugin.pluginpack.json
268
+ .mcp.json
269
+ skills/
270
+ release-notes/
271
+ SKILL.md
272
+ agents/
273
+ commands/
274
+ rules/
275
+ hooks/
276
+ assets/
277
+ ```
278
+
279
+ A target can emit a source plugin directly, rename it, or merge multiple source plugins into one emitted plugin.
280
+
281
+ ## MCP Servers
282
+
283
+ A source plugin declares MCP servers with a standard `.mcp.json` file at its root (`{ "mcpServers": { "name": { ... } } }`), or with an `mcpServers` key in `plugin.pluginpack.json`. The file wins if both are present, and merging plugins with the same server name is an error.
284
+
285
+ Each target wires MCP into its native shape: `claude` ships `.mcp.json` at the plugin root (auto-discovered), `cursor` references it from `plugin.json` (`"mcpServers": "./.mcp.json"`), `copilot` references it from the marketplace entry, and `antigravity` writes `mcp_config.json` beside `plugin.json`.
286
+
287
+ ## Target Overrides
288
+
289
+ Skill files are not always perfectly portable. When one app needs different frontmatter or content, add a target override next to the base file:
290
+
291
+ ```txt
292
+ skills/release-notes/SKILL.md
293
+ skills/release-notes/targets/cursor/SKILL.md
294
+ skills/release-notes/targets/claude/SKILL.md
295
+ ```
296
+
297
+ Resolution order is target override first, then the base file.
298
+
299
+ ## Other Shapes
300
+
301
+ There are two reasonable alternatives when the single-repo shape is not enough:
302
+
303
+ - Single source repo, multiple output repos: best when each target ecosystem expects its own repo root shape.
304
+ - Single source repo, release artifacts: best when users install zipped plugin payloads or release assets instead of browsing generated files in Git.
305
+
306
+ ## Why Not Just Copy Files?
307
+
308
+ For one target, copying files by hand may be enough. `pluginpack` starts to earn its keep when you need deterministic manifests, target-specific overrides, validation, and CI checks across multiple target repos.
309
+
310
+ ## CI Change Detection
311
+
312
+ `pluginpack diff` is designed for automation. It builds into a temporary directory, compares generated managed files against an existing plugin repo, and exits non-zero when the plugin repo is stale:
313
+
314
+ ```bash snippet=readme/snippet-04.bash
315
+ pluginpack diff --target cursor --against ../cursor-plugins
316
+ pluginpack diff --target claude --against ../claude-plugins
317
+ ```
318
+
319
+ Use that in CI to fail clearly or to trigger an action that opens a PR against the generated plugin repo.
320
+
321
+ When a generated target repo intentionally owns a path, add `ignoredDiffPaths` to that target config. Entries are target-output-relative paths; a directory entry ignores everything below it.
322
+
323
+ <!-- pluginpack-cli:start -->
324
+
325
+ ## CLI Reference
326
+
327
+ ### `init`
328
+
329
+ Create a starter pluginpack.config.ts and source plugin layout.
330
+
331
+ ```bash
332
+ pluginpack init [options]
333
+ ```
334
+
335
+ Examples:
336
+
337
+ - `pluginpack init`
338
+
339
+ Exit codes:
340
+
341
+ - 0 when files are created
342
+ - 1 when files already exist or cannot be written
343
+
344
+ ### `build`
345
+
346
+ Compile configured source plugins into target-native plugin payloads.
347
+
348
+ ```bash
349
+ pluginpack build [--target cursor|claude|antigravity|copilot] [--out-dir <path>] [--dry-run]
350
+ ```
351
+
352
+ Options:
353
+
354
+ - `--target <target>`: Build only one configured target.
355
+ - `--out-dir <path>`: Override the configured output directory for the selected target.
356
+ - `--dry-run`: Resolve and print planned managed output paths without writing files.
357
+
358
+ Examples:
359
+
360
+ - `pluginpack build`
361
+ - `pluginpack build --target cursor`
362
+ - `pluginpack build --target claude --dry-run`
363
+
364
+ Exit codes:
365
+
366
+ - 0 when all selected targets build
367
+ - 1 when config, source resolution, or file output fails
368
+
369
+ ### `validate`
370
+
371
+ Validate an existing target output directory for native manifest, path, and frontmatter requirements.
372
+
373
+ ```bash
374
+ pluginpack validate --target cursor|claude|antigravity|copilot [--dir <path>]
375
+ ```
376
+
377
+ Options:
378
+
379
+ - `--target <target>`: Required target validator.
380
+ - `--dir <path>`: Directory to validate. Defaults to the configured target outDir.
381
+
382
+ Examples:
383
+
384
+ - `pluginpack validate --target cursor --dir ../cursor-plugins`
385
+
386
+ Exit codes:
387
+
388
+ - 0 when validation passes
389
+ - 1 when validation finds errors
390
+
391
+ ### `diff`
392
+
393
+ Build into a temporary directory and compare generated managed files with an existing target repo.
394
+
395
+ ```bash
396
+ pluginpack diff --target cursor|claude|antigravity|copilot --against <path>
397
+ ```
398
+
399
+ Options:
400
+
401
+ - `--target <target>`: Required target to build and compare.
402
+ - `--against <path>`: Existing target repo or output directory to compare against.
403
+
404
+ Examples:
405
+
406
+ - `pluginpack diff --target cursor --against ../cursor-plugins`
407
+
408
+ Exit codes:
409
+
410
+ - 0 when managed files match
411
+ - 1 when managed files differ or the command fails
412
+
413
+ ### `prune`
414
+
415
+ Remove stale managed files that are no longer emitted by the current config.
416
+
417
+ ```bash
418
+ pluginpack prune [--target cursor|claude|antigravity|copilot] [--dry-run]
419
+ ```
420
+
421
+ Options:
422
+
423
+ - `--target <target>`: Prune only one configured target.
424
+ - `--dry-run`: Print stale managed files without deleting them.
425
+ - `--force`: Delete even paths that resolve inside the source tree or config.
426
+
427
+ Examples:
428
+
429
+ - `pluginpack prune`
430
+ - `pluginpack prune --target claude --dry-run`
431
+
432
+ Exit codes:
433
+
434
+ - 0 when stale managed files are removed or listed
435
+ - 1 when config, source resolution, or cleanup fails
436
+
437
+ ### `clean`
438
+
439
+ Remove all managed files for configured target outputs.
440
+
441
+ ```bash
442
+ pluginpack clean [--target cursor|claude|antigravity|copilot] [--dry-run]
443
+ ```
444
+
445
+ Options:
446
+
447
+ - `--target <target>`: Clean only one configured target.
448
+ - `--dry-run`: Print managed files without deleting them.
449
+ - `--force`: Delete even paths that resolve inside the source tree or config.
450
+
451
+ Examples:
452
+
453
+ - `pluginpack clean`
454
+ - `pluginpack clean --target cursor --dry-run`
455
+
456
+ Exit codes:
457
+
458
+ - 0 when managed files are removed or listed
459
+ - 1 when config, manifest loading, or cleanup fails
460
+
461
+ ### `docs`
462
+
463
+ Generate the README CLI reference section from command metadata.
464
+
465
+ ```bash
466
+ pluginpack docs [options]
467
+ ```
468
+
469
+ Options:
470
+
471
+ - `--check`: Fail if README.md is not up to date.
472
+
473
+ Examples:
474
+
475
+ - `pluginpack docs`
476
+ - `pluginpack docs --check`
477
+
478
+ Exit codes:
479
+
480
+ - 0 when docs are current or updated
481
+ - 1 when --check finds stale docs
482
+ <!-- pluginpack-cli:end -->