@vibe-agent-toolkit/cli 0.1.33 → 0.1.34-rc.2

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 (27) hide show
  1. package/dist/commands/audit/hierarchical-output.js +2 -2
  2. package/dist/commands/audit/hierarchical-output.js.map +1 -1
  3. package/dist/commands/audit.d.ts.map +1 -1
  4. package/dist/commands/audit.js +79 -2
  5. package/dist/commands/audit.js.map +1 -1
  6. package/dist/commands/claude/plugin/build.d.ts +4 -3
  7. package/dist/commands/claude/plugin/build.d.ts.map +1 -1
  8. package/dist/commands/claude/plugin/build.js +178 -71
  9. package/dist/commands/claude/plugin/build.js.map +1 -1
  10. package/dist/commands/claude/plugin/plugin-files.d.ts +19 -0
  11. package/dist/commands/claude/plugin/plugin-files.d.ts.map +1 -0
  12. package/dist/commands/claude/plugin/plugin-files.js +53 -0
  13. package/dist/commands/claude/plugin/plugin-files.js.map +1 -0
  14. package/dist/commands/claude/plugin/plugin-json-merge.d.ts +29 -0
  15. package/dist/commands/claude/plugin/plugin-json-merge.d.ts.map +1 -0
  16. package/dist/commands/claude/plugin/plugin-json-merge.js +76 -0
  17. package/dist/commands/claude/plugin/plugin-json-merge.js.map +1 -0
  18. package/dist/commands/claude/plugin/plugin-validators.d.ts +13 -0
  19. package/dist/commands/claude/plugin/plugin-validators.d.ts.map +1 -0
  20. package/dist/commands/claude/plugin/plugin-validators.js +59 -0
  21. package/dist/commands/claude/plugin/plugin-validators.js.map +1 -0
  22. package/dist/commands/claude/plugin/tree-copy.d.ts +23 -0
  23. package/dist/commands/claude/plugin/tree-copy.d.ts.map +1 -0
  24. package/dist/commands/claude/plugin/tree-copy.js +68 -0
  25. package/dist/commands/claude/plugin/tree-copy.js.map +1 -0
  26. package/docs/audit.md +6 -0
  27. package/package.json +11 -11
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Build-time validators for plugin declarations.
3
+ *
4
+ * - verifyPluginDirCaseMatch: guards against macOS/Windows case-insensitive FS drift
5
+ * (plugin: "foo-bar" -> plugins/Foo-Bar/ locally would break on Linux CI).
6
+ * - verifyNoCaseCollidingPluginNames: rejects pairs whose toLowerCase() collides.
7
+ * - parsePluginJsonFiles: parse-only JSON validation of hooks.json + .mcp.json
8
+ * (deep schema validation is Claude runtime's job).
9
+ */
10
+ import { existsSync } from 'node:fs';
11
+ import { readFile, readdir } from 'node:fs/promises';
12
+ import { safePath } from '@vibe-agent-toolkit/utils';
13
+ export async function verifyPluginDirCaseMatch(projectRoot, pluginName) {
14
+ const pluginsBase = safePath.join(projectRoot, 'plugins');
15
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- controlled path
16
+ if (!existsSync(pluginsBase))
17
+ return;
18
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- controlled path
19
+ const entries = await readdir(pluginsBase, { withFileTypes: true });
20
+ const matchInsensitive = entries.find((e) => e.isDirectory() && e.name.toLowerCase() === pluginName.toLowerCase());
21
+ if (matchInsensitive && matchInsensitive.name !== pluginName) {
22
+ throw new Error(`Plugin "${pluginName}" declared in config, but on-disk directory is "plugins/${matchInsensitive.name}/". ` +
23
+ `Names must match exactly (case-sensitive). This check catches macOS/Windows case-insensitive FS drift ` +
24
+ `that would break on Linux CI. Rename the directory or the config entry to match.`);
25
+ }
26
+ }
27
+ export function verifyNoCaseCollidingPluginNames(names) {
28
+ const seen = new Map();
29
+ for (const name of names) {
30
+ const key = name.toLowerCase();
31
+ const prior = seen.get(key);
32
+ if (prior === name) {
33
+ throw new Error(`Plugin name "${name}" is declared more than once across marketplaces. ` +
34
+ `Plugin names must be globally unique within a repo; rename one.`);
35
+ }
36
+ if (prior && prior !== name) {
37
+ throw new Error(`Plugin names "${prior}" and "${name}" differ only in case. ` +
38
+ `They would collide on case-insensitive filesystems; rename one.`);
39
+ }
40
+ seen.set(key, name);
41
+ }
42
+ }
43
+ async function parseJsonFileIfPresent(path, label) {
44
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved path
45
+ if (!existsSync(path))
46
+ return;
47
+ try {
48
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved path
49
+ JSON.parse(await readFile(path, 'utf-8'));
50
+ }
51
+ catch (e) {
52
+ throw new Error(`${label} is not valid JSON: ${e.message}`);
53
+ }
54
+ }
55
+ export async function parsePluginJsonFiles(pluginSourceDir) {
56
+ await parseJsonFileIfPresent(safePath.join(pluginSourceDir, 'hooks', 'hooks.json'), 'hooks/hooks.json');
57
+ await parseJsonFileIfPresent(safePath.join(pluginSourceDir, '.mcp.json'), '.mcp.json');
58
+ }
59
+ //# sourceMappingURL=plugin-validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-validators.js","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/plugin-validators.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAmB,EACnB,UAAkB;IAElB,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAC1D,sFAAsF;IACtF,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO;IAErC,sFAAsF;IACtF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,UAAU,CAAC,WAAW,EAAE,CAC5E,CAAC;IACF,IAAI,gBAAgB,IAAI,gBAAgB,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CACb,WAAW,UAAU,2DAA2D,gBAAgB,CAAC,IAAI,MAAM;YACzG,wGAAwG;YACxG,kFAAkF,CACrF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,KAAwB;IACvE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,oDAAoD;gBACtE,iEAAiE,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,iBAAiB,KAAK,UAAU,IAAI,yBAAyB;gBAC3D,iEAAiE,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,IAAY,EAAE,KAAa;IAC/D,oFAAoF;IACpF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO;IAC9B,IAAI,CAAC;QACH,oFAAoF;QACpF,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,uBAAwB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,eAAuB;IAChE,MAAM,sBAAsB,CAC1B,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,YAAY,CAAC,EACrD,kBAAkB,CACnB,CAAC;IACF,MAAM,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;AACzF,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Tree-copy stream for plugin build.
3
+ *
4
+ * Copies everything under <sourceDir> to <destDir>, except:
5
+ * - .claude-plugin/ (owned by plugin.json merge-write)
6
+ *
7
+ * Respects .gitignore via crawlDirectory (respectGitignore: true, the default).
8
+ * Returns counts keyed to the spec's YAML summary extension.
9
+ */
10
+ export interface TreeCopyOptions {
11
+ sourceDir: string;
12
+ destDir: string;
13
+ warn?: (message: string) => void;
14
+ }
15
+ export interface TreeCopyResult {
16
+ commandsCopied: number;
17
+ hooksCopied: number;
18
+ agentsCopied: number;
19
+ mcpCopied: number;
20
+ filesCopied: number;
21
+ }
22
+ export declare function treeCopyPlugin(options: TreeCopyOptions): Promise<TreeCopyResult>;
23
+ //# sourceMappingURL=tree-copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-copy.d.ts","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/tree-copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAYD,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAiDtF"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Tree-copy stream for plugin build.
3
+ *
4
+ * Copies everything under <sourceDir> to <destDir>, except:
5
+ * - .claude-plugin/ (owned by plugin.json merge-write)
6
+ *
7
+ * Respects .gitignore via crawlDirectory (respectGitignore: true, the default).
8
+ * Returns counts keyed to the spec's YAML summary extension.
9
+ */
10
+ import { existsSync } from 'node:fs';
11
+ import { copyFile, mkdir } from 'node:fs/promises';
12
+ import { dirname } from 'node:path';
13
+ import { crawlDirectory, safePath, toForwardSlash } from '@vibe-agent-toolkit/utils';
14
+ const EXCLUDE_PATTERNS = ['.claude-plugin/**'];
15
+ function classifyRelative(rel) {
16
+ if (rel.startsWith('commands/'))
17
+ return 'commandsCopied';
18
+ if (rel.startsWith('hooks/'))
19
+ return 'hooksCopied';
20
+ if (rel.startsWith('agents/'))
21
+ return 'agentsCopied';
22
+ if (rel === '.mcp.json')
23
+ return 'mcpCopied';
24
+ return undefined;
25
+ }
26
+ export async function treeCopyPlugin(options) {
27
+ const { sourceDir, destDir, warn } = options;
28
+ const result = {
29
+ commandsCopied: 0,
30
+ hooksCopied: 0,
31
+ agentsCopied: 0,
32
+ mcpCopied: 0,
33
+ filesCopied: 0,
34
+ };
35
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- sourceDir resolved from config
36
+ if (!existsSync(sourceDir)) {
37
+ return result;
38
+ }
39
+ const authorMarketplaceJson = safePath.join(sourceDir, '.claude-plugin', 'marketplace.json');
40
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- controlled path
41
+ if (existsSync(authorMarketplaceJson) && warn) {
42
+ warn(`Ignoring ${toForwardSlash(authorMarketplaceJson)}: marketplace.json is VAT-generated ` +
43
+ `at the marketplace level and cannot be supplied per-plugin.`);
44
+ }
45
+ const files = await crawlDirectory({
46
+ baseDir: sourceDir,
47
+ include: ['**/*'],
48
+ exclude: EXCLUDE_PATTERNS,
49
+ absolute: true,
50
+ filesOnly: true,
51
+ respectGitignore: true,
52
+ dot: true,
53
+ });
54
+ for (const absPath of files) {
55
+ const rel = toForwardSlash(safePath.relative(sourceDir, absPath));
56
+ const target = safePath.join(destDir, rel);
57
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- dest resolved from sourceDir+relative
58
+ await mkdir(dirname(target), { recursive: true });
59
+ await copyFile(absPath, target);
60
+ result.filesCopied += 1;
61
+ const bucket = classifyRelative(rel);
62
+ if (bucket) {
63
+ result[bucket] += 1;
64
+ }
65
+ }
66
+ return result;
67
+ }
68
+ //# sourceMappingURL=tree-copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-copy.js","sourceRoot":"","sources":["../../../../src/commands/claude/plugin/tree-copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAgBrF,MAAM,gBAAgB,GAAG,CAAC,mBAAmB,CAAC,CAAC;AAE/C,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,gBAAgB,CAAC;IACzD,IAAI,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,aAAa,CAAC;IACnD,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,cAAc,CAAC;IACrD,IAAI,GAAG,KAAK,WAAW;QAAE,OAAO,WAAW,CAAC;IAC5C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAwB;IAC3D,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAC7C,MAAM,MAAM,GAAmB;QAC7B,cAAc,EAAE,CAAC;QACjB,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,CAAC;QACf,SAAS,EAAE,CAAC;QACZ,WAAW,EAAE,CAAC;KACf,CAAC;IAEF,qGAAqG;IACrG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,qBAAqB,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;IAC7F,sFAAsF;IACtF,IAAI,UAAU,CAAC,qBAAqB,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9C,IAAI,CACF,YAAY,cAAc,CAAC,qBAAqB,CAAC,sCAAsC;YACrF,6DAA6D,CAChE,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC;QACjC,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,OAAO,EAAE,gBAAgB;QACzB,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI;QACf,gBAAgB,EAAE,IAAI;QACtB,GAAG,EAAE,IAAI;KACV,CAAC,CAAC;IAEH,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3C,4GAA4G;QAC5G,MAAM,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAChC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;QAExB,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/docs/audit.md CHANGED
@@ -61,6 +61,11 @@ Plugin directories contain a `.claude-plugin/plugin.json` manifest:
61
61
  my-plugin/
62
62
  ├── .claude-plugin/
63
63
  │ └── plugin.json # Plugin manifest
64
+ ├── commands/ # slash commands (optional)
65
+ ├── agents/ # subagents (optional)
66
+ ├── hooks/
67
+ │ └── hooks.json # hook registry (optional)
68
+ ├── .mcp.json # MCP server config (optional)
64
69
  └── skills/
65
70
  └── skill1.md
66
71
  ```
@@ -69,6 +74,7 @@ my-plugin/
69
74
  - `plugin.json` exists and is valid JSON
70
75
  - Schema validation against plugin manifest schema
71
76
  - Referenced skills exist
77
+ - `hooks/hooks.json` and `.mcp.json` parse as valid JSON when present (emits `PLUGIN_INVALID_JSON`)
72
78
 
73
79
  ### 2. Marketplace Directories
74
80
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-agent-toolkit/cli",
3
- "version": "0.1.33",
3
+ "version": "0.1.34-rc.2",
4
4
  "description": "Command-line interface for vibe-agent-toolkit",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,16 +41,16 @@
41
41
  "//dependencies-note": "DO NOT add example agent packages or adopter packages here. Adopter packages (like vat-development-agents) depend on the CLI binary at build time — declaring them as deps creates a circular build dependency. They are built in a second turbo pass via package#task overrides in turbo.json.",
42
42
  "dependencies": {
43
43
  "@anthropic-ai/sdk": "^0.71.2",
44
- "@vibe-agent-toolkit/agent-config": "0.1.33",
45
- "@vibe-agent-toolkit/agent-schema": "0.1.33",
46
- "@vibe-agent-toolkit/agent-skills": "0.1.33",
47
- "@vibe-agent-toolkit/claude-marketplace": "0.1.33",
48
- "@vibe-agent-toolkit/discovery": "0.1.33",
49
- "@vibe-agent-toolkit/gateway-mcp": "0.1.33",
50
- "@vibe-agent-toolkit/rag": "0.1.33",
51
- "@vibe-agent-toolkit/rag-lancedb": "0.1.33",
52
- "@vibe-agent-toolkit/resources": "0.1.33",
53
- "@vibe-agent-toolkit/utils": "0.1.33",
44
+ "@vibe-agent-toolkit/agent-config": "0.1.34-rc.2",
45
+ "@vibe-agent-toolkit/agent-schema": "0.1.34-rc.2",
46
+ "@vibe-agent-toolkit/agent-skills": "0.1.34-rc.2",
47
+ "@vibe-agent-toolkit/claude-marketplace": "0.1.34-rc.2",
48
+ "@vibe-agent-toolkit/discovery": "0.1.34-rc.2",
49
+ "@vibe-agent-toolkit/gateway-mcp": "0.1.34-rc.2",
50
+ "@vibe-agent-toolkit/rag": "0.1.34-rc.2",
51
+ "@vibe-agent-toolkit/rag-lancedb": "0.1.34-rc.2",
52
+ "@vibe-agent-toolkit/resources": "0.1.34-rc.2",
53
+ "@vibe-agent-toolkit/utils": "0.1.34-rc.2",
54
54
  "adm-zip": "^0.5.16",
55
55
  "commander": "^12.1.0",
56
56
  "js-yaml": "^4.1.0",