@ai-plugin-marketplace/core 0.1.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 (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/config.d.ts +47 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +38 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/core.d.ts +291 -0
  8. package/dist/index.d.ts +15 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +13 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/pipeline/build.d.ts +90 -0
  13. package/dist/pipeline/build.d.ts.map +1 -0
  14. package/dist/pipeline/build.js +224 -0
  15. package/dist/pipeline/build.js.map +1 -0
  16. package/dist/pipeline/discover.d.ts +37 -0
  17. package/dist/pipeline/discover.d.ts.map +1 -0
  18. package/dist/pipeline/discover.js +71 -0
  19. package/dist/pipeline/discover.js.map +1 -0
  20. package/dist/pipeline/init-template.d.ts +33 -0
  21. package/dist/pipeline/init-template.d.ts.map +1 -0
  22. package/dist/pipeline/init-template.js +142 -0
  23. package/dist/pipeline/init-template.js.map +1 -0
  24. package/dist/pipeline/init.d.ts +39 -0
  25. package/dist/pipeline/init.d.ts.map +1 -0
  26. package/dist/pipeline/init.js +84 -0
  27. package/dist/pipeline/init.js.map +1 -0
  28. package/dist/pipeline/load-config.d.ts +47 -0
  29. package/dist/pipeline/load-config.d.ts.map +1 -0
  30. package/dist/pipeline/load-config.js +106 -0
  31. package/dist/pipeline/load-config.js.map +1 -0
  32. package/dist/pipeline/operations.d.ts +70 -0
  33. package/dist/pipeline/operations.d.ts.map +1 -0
  34. package/dist/pipeline/operations.js +100 -0
  35. package/dist/pipeline/operations.js.map +1 -0
  36. package/dist/pipeline/scaffold.d.ts +105 -0
  37. package/dist/pipeline/scaffold.d.ts.map +1 -0
  38. package/dist/pipeline/scaffold.js +422 -0
  39. package/dist/pipeline/scaffold.js.map +1 -0
  40. package/dist/pipeline/sentinel.d.ts +127 -0
  41. package/dist/pipeline/sentinel.d.ts.map +1 -0
  42. package/dist/pipeline/sentinel.js +263 -0
  43. package/dist/pipeline/sentinel.js.map +1 -0
  44. package/dist/pipeline/types.d.ts +178 -0
  45. package/dist/pipeline/types.d.ts.map +1 -0
  46. package/dist/pipeline/types.js +26 -0
  47. package/dist/pipeline/types.js.map +1 -0
  48. package/dist/pipeline/validate.d.ts +90 -0
  49. package/dist/pipeline/validate.d.ts.map +1 -0
  50. package/dist/pipeline/validate.js +617 -0
  51. package/dist/pipeline/validate.js.map +1 -0
  52. package/dist/targets/claude/scaffold.d.ts +32 -0
  53. package/dist/targets/claude/scaffold.d.ts.map +1 -0
  54. package/dist/targets/claude/scaffold.js +48 -0
  55. package/dist/targets/claude/scaffold.js.map +1 -0
  56. package/dist/targets/claude/schemas.d.ts +119 -0
  57. package/dist/targets/claude/schemas.d.ts.map +1 -0
  58. package/dist/targets/claude/schemas.js +204 -0
  59. package/dist/targets/claude/schemas.js.map +1 -0
  60. package/dist/targets/claude/transform.d.ts +40 -0
  61. package/dist/targets/claude/transform.d.ts.map +1 -0
  62. package/dist/targets/claude/transform.js +48 -0
  63. package/dist/targets/claude/transform.js.map +1 -0
  64. package/dist/targets/claude/validate.d.ts +25 -0
  65. package/dist/targets/claude/validate.d.ts.map +1 -0
  66. package/dist/targets/claude/validate.js +263 -0
  67. package/dist/targets/claude/validate.js.map +1 -0
  68. package/dist/targets/cursor/scaffold.d.ts +29 -0
  69. package/dist/targets/cursor/scaffold.d.ts.map +1 -0
  70. package/dist/targets/cursor/scaffold.js +45 -0
  71. package/dist/targets/cursor/scaffold.js.map +1 -0
  72. package/dist/targets/cursor/schemas.d.ts +49 -0
  73. package/dist/targets/cursor/schemas.d.ts.map +1 -0
  74. package/dist/targets/cursor/schemas.js +125 -0
  75. package/dist/targets/cursor/schemas.js.map +1 -0
  76. package/dist/targets/cursor/validate.d.ts +28 -0
  77. package/dist/targets/cursor/validate.d.ts.map +1 -0
  78. package/dist/targets/cursor/validate.js +181 -0
  79. package/dist/targets/cursor/validate.js.map +1 -0
  80. package/dist/targets/gemini/bundle.d.ts +25 -0
  81. package/dist/targets/gemini/bundle.d.ts.map +1 -0
  82. package/dist/targets/gemini/bundle.js +149 -0
  83. package/dist/targets/gemini/bundle.js.map +1 -0
  84. package/dist/targets/gemini/scaffold.d.ts +28 -0
  85. package/dist/targets/gemini/scaffold.d.ts.map +1 -0
  86. package/dist/targets/gemini/scaffold.js +57 -0
  87. package/dist/targets/gemini/scaffold.js.map +1 -0
  88. package/dist/targets/gemini/schemas.d.ts +53 -0
  89. package/dist/targets/gemini/schemas.d.ts.map +1 -0
  90. package/dist/targets/gemini/schemas.js +72 -0
  91. package/dist/targets/gemini/schemas.js.map +1 -0
  92. package/dist/targets/gemini/transform.d.ts +106 -0
  93. package/dist/targets/gemini/transform.d.ts.map +1 -0
  94. package/dist/targets/gemini/transform.js +137 -0
  95. package/dist/targets/gemini/transform.js.map +1 -0
  96. package/dist/targets/gemini/validate.d.ts +26 -0
  97. package/dist/targets/gemini/validate.d.ts.map +1 -0
  98. package/dist/targets/gemini/validate.js +146 -0
  99. package/dist/targets/gemini/validate.js.map +1 -0
  100. package/dist/targets/kiro/bundle.d.ts +32 -0
  101. package/dist/targets/kiro/bundle.d.ts.map +1 -0
  102. package/dist/targets/kiro/bundle.js +106 -0
  103. package/dist/targets/kiro/bundle.js.map +1 -0
  104. package/dist/targets/kiro/scaffold.d.ts +28 -0
  105. package/dist/targets/kiro/scaffold.d.ts.map +1 -0
  106. package/dist/targets/kiro/scaffold.js +55 -0
  107. package/dist/targets/kiro/scaffold.js.map +1 -0
  108. package/dist/targets/kiro/schemas.d.ts +100 -0
  109. package/dist/targets/kiro/schemas.d.ts.map +1 -0
  110. package/dist/targets/kiro/schemas.js +147 -0
  111. package/dist/targets/kiro/schemas.js.map +1 -0
  112. package/dist/targets/kiro/transform.d.ts +53 -0
  113. package/dist/targets/kiro/transform.d.ts.map +1 -0
  114. package/dist/targets/kiro/transform.js +113 -0
  115. package/dist/targets/kiro/transform.js.map +1 -0
  116. package/dist/targets/kiro/validate.d.ts +36 -0
  117. package/dist/targets/kiro/validate.d.ts.map +1 -0
  118. package/dist/targets/kiro/validate.js +232 -0
  119. package/dist/targets/kiro/validate.js.map +1 -0
  120. package/dist/targets/scaffold-kit.d.ts +56 -0
  121. package/dist/targets/scaffold-kit.d.ts.map +1 -0
  122. package/dist/targets/scaffold-kit.js +33 -0
  123. package/dist/targets/scaffold-kit.js.map +1 -0
  124. package/dist/targets/vercel/scaffold.d.ts +34 -0
  125. package/dist/targets/vercel/scaffold.d.ts.map +1 -0
  126. package/dist/targets/vercel/scaffold.js +58 -0
  127. package/dist/targets/vercel/scaffold.js.map +1 -0
  128. package/dist/targets/vercel/schemas.d.ts +42 -0
  129. package/dist/targets/vercel/schemas.d.ts.map +1 -0
  130. package/dist/targets/vercel/schemas.js +69 -0
  131. package/dist/targets/vercel/schemas.js.map +1 -0
  132. package/dist/targets/vercel/validate.d.ts +28 -0
  133. package/dist/targets/vercel/validate.d.ts.map +1 -0
  134. package/dist/targets/vercel/validate.js +180 -0
  135. package/dist/targets/vercel/validate.js.map +1 -0
  136. package/package.json +50 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Per-target validator for the Cursor target.
3
+ *
4
+ * Responsibilities (v0.1.0):
5
+ * 1. Manifest file refs resolve — checks that paths in .cursor-plugin/plugin.json
6
+ * exist on disk with the correct type (directory for skills, .md for agents,
7
+ * either for commands). Hooks refs are intentionally excluded: the hooks field
8
+ * typically points at `hooks/claude.json`, which is a Claude-target generated
9
+ * artifact and is not guaranteed to exist in a Cursor-only build context.
10
+ * 2. Cursor rule frontmatter — validates YAML frontmatter in rules/*.mdc files
11
+ * against cursorRuleFrontmatterSchema. Files with no frontmatter block are
12
+ * silently skipped.
13
+ *
14
+ * Cross-target concerns (envelope adherence, name consistency, MCP key sync,
15
+ * marketplace registration, freshness) are NOT checked here.
16
+ *
17
+ * @see packages/core/docs/specs/architecture.md §10 (validation contract)
18
+ * @see packages/core/docs/specs/architecture.md §8.1 (Finding, FindingCode)
19
+ */
20
+ import * as fs from 'node:fs';
21
+ import * as path from 'node:path';
22
+ import { parse as parseYaml } from 'yaml';
23
+ import { cursorPluginManifestSchema, cursorRuleFrontmatterSchema } from './schemas.js';
24
+ // ---------------------------------------------------------------------------
25
+ // Helpers
26
+ // ---------------------------------------------------------------------------
27
+ function makeInvalid(plugin, message, hint) {
28
+ const finding = { severity: 'hard', code: 'schema-invalid', plugin, message };
29
+ if (hint !== undefined)
30
+ finding.hint = hint;
31
+ return finding;
32
+ }
33
+ /**
34
+ * Normalise a manifest field that may be a single string path, an array of
35
+ * string paths, or an inline object (which has no resolvable paths). Returns
36
+ * only the string path entries.
37
+ */
38
+ function normalisePathField(value) {
39
+ if (value === undefined)
40
+ return [];
41
+ if (typeof value === 'string')
42
+ return [value];
43
+ if (Array.isArray(value))
44
+ return value.filter((v) => typeof v === 'string');
45
+ // Inline object (record of commands, inline hooks object) — no paths to check.
46
+ return [];
47
+ }
48
+ // ---------------------------------------------------------------------------
49
+ // Manifest file-ref validation
50
+ // ---------------------------------------------------------------------------
51
+ function validateManifestFileRefs(pluginDir, pluginName) {
52
+ const manifestPath = path.join(pluginDir, '.cursor-plugin', 'plugin.json');
53
+ if (!fs.existsSync(manifestPath))
54
+ return [];
55
+ let raw;
56
+ try {
57
+ raw = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
58
+ }
59
+ catch {
60
+ return [
61
+ makeInvalid(pluginName, `.cursor-plugin/plugin.json is not valid JSON`, 'Ensure the file is well-formed JSON.'),
62
+ ];
63
+ }
64
+ const parsed = cursorPluginManifestSchema.safeParse(raw);
65
+ if (!parsed.success) {
66
+ const issues = parsed.error.issues.map((i) => i.message).join('; ');
67
+ return [
68
+ makeInvalid(pluginName, `.cursor-plugin/plugin.json failed schema validation: ${issues}`, 'Verify the manifest fields match the cursor plugin manifest schema.'),
69
+ ];
70
+ }
71
+ const manifest = parsed.data;
72
+ const findings = [];
73
+ // Ref groups: skills → directory, agents → .md file, commands → either.
74
+ // hooks is intentionally excluded — hooks/claude.json is a Claude-generated
75
+ // artifact and is not guaranteed present in a Cursor-only build context.
76
+ const refGroups = [
77
+ { field: 'skills', paths: normalisePathField(manifest.skills), mustBeDir: true },
78
+ { field: 'agents', paths: normalisePathField(manifest.agents), mustBeDir: false },
79
+ { field: 'commands', paths: normalisePathField(manifest.commands) },
80
+ ];
81
+ for (const { field, paths: refPaths, mustBeDir } of refGroups) {
82
+ for (const refPath of refPaths) {
83
+ // All manifest paths must start with "./"
84
+ if (!refPath.startsWith('./')) {
85
+ findings.push(makeInvalid(pluginName, `.cursor-plugin/plugin.json: ${field} path must start with "./": ${refPath}`, `Change the path to start with "./" (e.g. "./${refPath.replace(/^\/+/, '')}").`));
86
+ continue;
87
+ }
88
+ // Paths must not contain ".." segments (path traversal guard)
89
+ if (refPath.includes('..')) {
90
+ findings.push(makeInvalid(pluginName, `.cursor-plugin/plugin.json: ${field} path must not contain "..": ${refPath}`, 'Use a path relative to the plugin root without ".." traversal.'));
91
+ continue;
92
+ }
93
+ const resolved = path.join(pluginDir, refPath.slice(2));
94
+ if (!fs.existsSync(resolved)) {
95
+ findings.push(makeInvalid(pluginName, `.cursor-plugin/plugin.json: ${field} references non-existent path: ${refPath}`, `Create the missing ${field === 'skills' ? 'directory' : 'file'} at ${resolved}.`));
96
+ continue;
97
+ }
98
+ const stat = fs.statSync(resolved);
99
+ if (mustBeDir === true && !stat.isDirectory()) {
100
+ findings.push(makeInvalid(pluginName, `.cursor-plugin/plugin.json: ${field} path must be a directory, but a file was found: ${refPath}`, `The ${field} field expects a directory path, not a file path.`));
101
+ }
102
+ else if (mustBeDir === false && !stat.isFile()) {
103
+ findings.push(makeInvalid(pluginName, `.cursor-plugin/plugin.json: ${field} path must be a file, but a directory was found: ${refPath}`, `The ${field} field expects a file path, not a directory path.`));
104
+ }
105
+ }
106
+ }
107
+ return findings;
108
+ }
109
+ // ---------------------------------------------------------------------------
110
+ // Cursor rule frontmatter validation
111
+ // ---------------------------------------------------------------------------
112
+ /**
113
+ * Parse the YAML frontmatter block from a .mdc file.
114
+ *
115
+ * Returns `null` when no frontmatter block is present (plain content is valid).
116
+ * Returns the parsed object when a frontmatter block is found.
117
+ * Throws if the YAML inside the block is malformed.
118
+ */
119
+ function parseMdcFrontmatter(content) {
120
+ // Frontmatter is strictly between a leading `---\n` and the next `---`
121
+ if (!content.startsWith('---\n') && !content.startsWith('---\r\n'))
122
+ return null;
123
+ const end = content.indexOf('\n---', 4);
124
+ if (end === -1)
125
+ return null;
126
+ const yamlText = content.slice(4, end);
127
+ // yaml.parse returns `unknown`; we cast to a loose record type so Zod can
128
+ // validate the actual field types downstream.
129
+ const parsed = parseYaml(yamlText);
130
+ // An empty frontmatter block parses to null/undefined — treat as no frontmatter.
131
+ if (parsed === null || parsed === undefined)
132
+ return null;
133
+ return parsed;
134
+ }
135
+ function validateCursorRules(pluginDir, pluginName) {
136
+ const rulesDir = path.join(pluginDir, 'rules');
137
+ if (!fs.existsSync(rulesDir))
138
+ return [];
139
+ const findings = [];
140
+ const entries = fs.readdirSync(rulesDir, { withFileTypes: true });
141
+ for (const entry of entries) {
142
+ if (!entry.isFile() || !entry.name.endsWith('.mdc'))
143
+ continue;
144
+ const filePath = path.join(rulesDir, entry.name);
145
+ const content = fs.readFileSync(filePath, 'utf-8');
146
+ let frontmatter;
147
+ try {
148
+ frontmatter = parseMdcFrontmatter(content);
149
+ }
150
+ catch {
151
+ findings.push(makeInvalid(pluginName, `rules/${entry.name}: frontmatter YAML is malformed`, 'Ensure the YAML between the --- delimiters is valid.'));
152
+ continue;
153
+ }
154
+ // No frontmatter block → skip (plain .mdc content is valid)
155
+ if (frontmatter === null)
156
+ continue;
157
+ const result = cursorRuleFrontmatterSchema.safeParse(frontmatter);
158
+ if (!result.success) {
159
+ const issues = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');
160
+ findings.push(makeInvalid(pluginName, `rules/${entry.name}: frontmatter failed schema validation: ${issues}`, 'Check the alwaysApply (boolean), globs (string[]), and description (string) fields.'));
161
+ }
162
+ }
163
+ return findings;
164
+ }
165
+ // ---------------------------------------------------------------------------
166
+ // Public API
167
+ // ---------------------------------------------------------------------------
168
+ /**
169
+ * Run all Cursor-specific validators against a plugin directory.
170
+ *
171
+ * `pluginDir` is the absolute path to a `plugins/<name>/` directory.
172
+ * All findings use `plugin: path.basename(pluginDir)`.
173
+ */
174
+ export function validateCursorPlugin(pluginDir) {
175
+ const pluginName = path.basename(pluginDir);
176
+ return [
177
+ ...validateManifestFileRefs(pluginDir, pluginName),
178
+ ...validateCursorRules(pluginDir, pluginName),
179
+ ];
180
+ }
181
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/targets/cursor/validate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * I/O layer for the Gemini CLI target: copies a plugin's canonical files into a
3
+ * standalone export directory, rewriting agent tool names along the way.
4
+ *
5
+ * @see docs/specs/architecture.md §7 (mechanical transformations)
6
+ * @see docs/specs/architecture.md §12.4 (transform step + per-target folder layout)
7
+ */
8
+ /**
9
+ * Build the Gemini CLI standalone export for a single plugin. Copies the canonical
10
+ * set of files/dirs from `pluginDir` into `destDir`, rewriting agent `.md` files'
11
+ * tool names along the way. Matches the output of `buildGeminiStandalone` in the
12
+ * template's `build-standalone.ts`.
13
+ *
14
+ * Impure (I/O): reads from pluginDir, writes to destDir. Clears destDir first.
15
+ *
16
+ * @param pluginDir - Absolute path to the source plugin directory.
17
+ * @param destDir - Absolute path to the destination directory (cleared before writing).
18
+ * @returns `emitted`: paths relative to destDir for every file written.
19
+ * `droppedToolsByAgent`: map of agent filename → dropped Claude tool names.
20
+ */
21
+ export declare function bundleGeminiPlugin(pluginDir: string, destDir: string): {
22
+ emitted: string[];
23
+ droppedToolsByAgent: Record<string, string[]>;
24
+ };
25
+ //# sourceMappingURL=bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../../src/targets/gemini/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA+FH;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;CAAE,CAmDtE"}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * I/O layer for the Gemini CLI target: copies a plugin's canonical files into a
3
+ * standalone export directory, rewriting agent tool names along the way.
4
+ *
5
+ * @see docs/specs/architecture.md §7 (mechanical transformations)
6
+ * @see docs/specs/architecture.md §12.4 (transform step + per-target folder layout)
7
+ */
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import { convertClaudeHooksYamlToGeminiJson, rewriteAgentFrontmatterTools } from './transform.js';
11
+ // ---------------------------------------------------------------------------
12
+ // Internal file-system helpers (mirrors build-standalone.ts utilities)
13
+ // ---------------------------------------------------------------------------
14
+ function copyFile(src, dest) {
15
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
16
+ fs.copyFileSync(src, dest);
17
+ }
18
+ function copyDir(src, dest) {
19
+ if (!fs.existsSync(src))
20
+ return;
21
+ fs.mkdirSync(dest, { recursive: true });
22
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
23
+ const srcPath = path.join(src, entry.name);
24
+ const destPath = path.join(dest, entry.name);
25
+ if (entry.isDirectory()) {
26
+ copyDir(srcPath, destPath);
27
+ }
28
+ else {
29
+ copyFile(srcPath, destPath);
30
+ }
31
+ }
32
+ }
33
+ function copyIfExists(src, dest) {
34
+ if (!fs.existsSync(src))
35
+ return false;
36
+ if (fs.statSync(src).isDirectory()) {
37
+ copyDir(src, dest);
38
+ }
39
+ else {
40
+ copyFile(src, dest);
41
+ }
42
+ return true;
43
+ }
44
+ function cleanDir(dir) {
45
+ if (fs.existsSync(dir)) {
46
+ fs.rmSync(dir, { recursive: true });
47
+ }
48
+ }
49
+ /** Collect all file paths under `dir` relative to `dir`. */
50
+ function collectRelativePaths(dir) {
51
+ const results = [];
52
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
53
+ if (entry.isDirectory()) {
54
+ for (const sub of collectRelativePaths(path.join(dir, entry.name))) {
55
+ results.push(path.join(entry.name, sub));
56
+ }
57
+ }
58
+ else {
59
+ results.push(entry.name);
60
+ }
61
+ }
62
+ return results;
63
+ }
64
+ // ---------------------------------------------------------------------------
65
+ // Agent rewriting
66
+ // ---------------------------------------------------------------------------
67
+ /**
68
+ * Rewrite all `.md` files inside `agentsDir` in-place, translating Claude Code tool
69
+ * names to Gemini CLI equivalents. Returns a map of filename → dropped tools.
70
+ */
71
+ function rewriteAgentsDir(agentsDir) {
72
+ const droppedToolsByAgent = {};
73
+ if (!fs.existsSync(agentsDir))
74
+ return droppedToolsByAgent;
75
+ for (const file of fs.readdirSync(agentsDir)) {
76
+ if (!file.endsWith('.md'))
77
+ continue;
78
+ const filePath = path.join(agentsDir, file);
79
+ const original = fs.readFileSync(filePath, 'utf-8');
80
+ const { content, droppedTools } = rewriteAgentFrontmatterTools(original);
81
+ fs.writeFileSync(filePath, content, 'utf-8');
82
+ if (droppedTools.length > 0) {
83
+ droppedToolsByAgent[file] = droppedTools;
84
+ }
85
+ }
86
+ return droppedToolsByAgent;
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // Public API
90
+ // ---------------------------------------------------------------------------
91
+ /**
92
+ * Build the Gemini CLI standalone export for a single plugin. Copies the canonical
93
+ * set of files/dirs from `pluginDir` into `destDir`, rewriting agent `.md` files'
94
+ * tool names along the way. Matches the output of `buildGeminiStandalone` in the
95
+ * template's `build-standalone.ts`.
96
+ *
97
+ * Impure (I/O): reads from pluginDir, writes to destDir. Clears destDir first.
98
+ *
99
+ * @param pluginDir - Absolute path to the source plugin directory.
100
+ * @param destDir - Absolute path to the destination directory (cleared before writing).
101
+ * @returns `emitted`: paths relative to destDir for every file written.
102
+ * `droppedToolsByAgent`: map of agent filename → dropped Claude tool names.
103
+ */
104
+ export function bundleGeminiPlugin(pluginDir, destDir) {
105
+ cleanDir(destDir);
106
+ // ── Flat files (only if present) ──────────────────────────────────────────
107
+ const flatFiles = ['gemini-extension.json', 'GEMINI.md', 'README.md', 'LICENSE'];
108
+ for (const name of flatFiles) {
109
+ copyIfExists(path.join(pluginDir, name), path.join(destDir, name));
110
+ }
111
+ // ── Directories: skills/ and agents/ ─────────────────────────────────────
112
+ const plainDirs = ['skills', 'agents'];
113
+ for (const dir of plainDirs) {
114
+ copyIfExists(path.join(pluginDir, dir), path.join(destDir, dir));
115
+ }
116
+ // Rewrite agent tool names after copying
117
+ const droppedToolsByAgent = rewriteAgentsDir(path.join(destDir, 'agents'));
118
+ // ── commands/: .toml files only ───────────────────────────────────────────
119
+ const commandsSrc = path.join(pluginDir, 'commands');
120
+ const commandsDest = path.join(destDir, 'commands');
121
+ if (fs.existsSync(commandsSrc)) {
122
+ const tomlFiles = fs.readdirSync(commandsSrc).filter((f) => f.endsWith('.toml'));
123
+ if (tomlFiles.length > 0) {
124
+ fs.mkdirSync(commandsDest, { recursive: true });
125
+ for (const file of tomlFiles) {
126
+ copyFile(path.join(commandsSrc, file), path.join(commandsDest, file));
127
+ }
128
+ }
129
+ }
130
+ // ── hooks/hooks.json: translate Claude YAML → Gemini JSON ────────────────
131
+ // Gemini CLI looks for `hooks/hooks.json` regardless of the YAML source filename.
132
+ // Try claude.yaml first, then claude.yml, matching build-hooks.ts behaviour.
133
+ const hooksSrc = path.join(pluginDir, 'hooks');
134
+ const yamlCandidates = ['claude.yaml', 'claude.yml'];
135
+ for (const candidate of yamlCandidates) {
136
+ const yamlPath = path.join(hooksSrc, candidate);
137
+ if (fs.existsSync(yamlPath)) {
138
+ const yamlContent = fs.readFileSync(yamlPath, 'utf-8');
139
+ const jsonContent = convertClaudeHooksYamlToGeminiJson(yamlContent);
140
+ const hooksDestDir = path.join(destDir, 'hooks');
141
+ fs.mkdirSync(hooksDestDir, { recursive: true });
142
+ fs.writeFileSync(path.join(hooksDestDir, 'hooks.json'), jsonContent, 'utf-8');
143
+ break;
144
+ }
145
+ }
146
+ const emitted = collectRelativePaths(destDir);
147
+ return { emitted, droppedToolsByAgent };
148
+ }
149
+ //# sourceMappingURL=bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../../src/targets/gemini/bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Scaffold templates for the Gemini CLI target.
3
+ *
4
+ * `scaffoldGeminiFiles` is a pure function returning the skeleton files this target contributes
5
+ * to a new plugin: the `gemini-extension.json` manifest and its referenced `GEMINI.md` context
6
+ * file. Every manifest carries `schemaVersion: "0.1.0"` (§12.2). No generated-file sentinels —
7
+ * these are author-authored skeleton files (§4.3).
8
+ *
9
+ * This module must not import from any sibling targets/<other>/ folder (§3.4).
10
+ *
11
+ * @see docs/specs/architecture.md §4 (plugin source layout)
12
+ * @see docs/specs/architecture.md §6.4 (compatibility-assist)
13
+ * @see docs/specs/architecture.md §12.2 (schemaVersion on every manifest)
14
+ * @see docs/specs/architecture.md §12.5 (per-target scaffold.ts)
15
+ */
16
+ import { type ScaffoldedFile, type TargetScaffoldOptions } from '../scaffold-kit.js';
17
+ /**
18
+ * Produce the Gemini CLI skeleton files for a plugin.
19
+ *
20
+ * The minimum required artifact (`TARGET_MIN_REQUIRED.gemini`) is `gemini-extension.json`. The
21
+ * manifest declares `contextFileName: "GEMINI.md"`, so the companion `GEMINI.md` is emitted too.
22
+ *
23
+ * @param pluginName - Plugin identity; written verbatim as the manifest `name`.
24
+ * @param opts - Optional description and add-target placeholder behaviour.
25
+ * @returns Files contributed by this target, with paths relative to the plugin directory.
26
+ */
27
+ export declare function scaffoldGeminiFiles(pluginName: string, opts?: TargetScaffoldOptions): ScaffoldedFile[];
28
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/targets/gemini/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,oBAAoB,CAAC;AAK5B;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,qBAA0B,GAC/B,cAAc,EAAE,CA4BlB"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Scaffold templates for the Gemini CLI target.
3
+ *
4
+ * `scaffoldGeminiFiles` is a pure function returning the skeleton files this target contributes
5
+ * to a new plugin: the `gemini-extension.json` manifest and its referenced `GEMINI.md` context
6
+ * file. Every manifest carries `schemaVersion: "0.1.0"` (§12.2). No generated-file sentinels —
7
+ * these are author-authored skeleton files (§4.3).
8
+ *
9
+ * This module must not import from any sibling targets/<other>/ folder (§3.4).
10
+ *
11
+ * @see docs/specs/architecture.md §4 (plugin source layout)
12
+ * @see docs/specs/architecture.md §6.4 (compatibility-assist)
13
+ * @see docs/specs/architecture.md §12.2 (schemaVersion on every manifest)
14
+ * @see docs/specs/architecture.md §12.5 (per-target scaffold.ts)
15
+ */
16
+ import { resolveDescription, SCHEMA_VERSION, } from '../scaffold-kit.js';
17
+ /** Identity tag enabling editor highlighting of the embedded Markdown context file. */
18
+ const md = String.raw;
19
+ /**
20
+ * Produce the Gemini CLI skeleton files for a plugin.
21
+ *
22
+ * The minimum required artifact (`TARGET_MIN_REQUIRED.gemini`) is `gemini-extension.json`. The
23
+ * manifest declares `contextFileName: "GEMINI.md"`, so the companion `GEMINI.md` is emitted too.
24
+ *
25
+ * @param pluginName - Plugin identity; written verbatim as the manifest `name`.
26
+ * @param opts - Optional description and add-target placeholder behaviour.
27
+ * @returns Files contributed by this target, with paths relative to the plugin directory.
28
+ */
29
+ export function scaffoldGeminiFiles(pluginName, opts = {}) {
30
+ const description = resolveDescription(pluginName, opts);
31
+ const manifest = {
32
+ schemaVersion: SCHEMA_VERSION,
33
+ name: pluginName,
34
+ version: '0.0.1',
35
+ description,
36
+ contextFileName: 'GEMINI.md',
37
+ mcpServers: {},
38
+ };
39
+ return [
40
+ {
41
+ path: 'gemini-extension.json',
42
+ content: `${JSON.stringify(manifest, null, 2)}\n`,
43
+ },
44
+ {
45
+ path: 'GEMINI.md',
46
+ content: md `# ${pluginName}
47
+
48
+ ${description}
49
+
50
+ ## Overview
51
+
52
+ Describe what this plugin does for Gemini CLI users.
53
+ `,
54
+ },
55
+ ];
56
+ }
57
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../../src/targets/gemini/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,kBAAkB,EAClB,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAE5B,uFAAuF;AACvF,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC;AAEtB;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAkB,EAClB,OAA8B,EAAE;IAEhC,MAAM,WAAW,GAAG,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACzD,MAAM,QAAQ,GAA4B;QACxC,aAAa,EAAE,cAAc;QAC7B,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,OAAO;QAChB,WAAW;QACX,eAAe,EAAE,WAAW;QAC5B,UAAU,EAAE,EAAE;KACf,CAAC;IAEF,OAAO;QACL;YACE,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI;SAClD;QACD;YACE,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,EAAE,CAAA,KAAK,UAAU;;EAE9B,WAAW;;;;;CAKZ;SACI;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Zod schemas for the Gemini CLI target.
3
+ *
4
+ * These are faithful, non-breaking ports of the JSON Schema contracts that the template
5
+ * repository has used in practice. Per §13 Phase A of the architecture spec, no schema
6
+ * breaking changes are introduced here — this is a mechanical port only.
7
+ *
8
+ * @see https://ai.google.dev/gemini-api/docs/gemini-cli (Gemini CLI extension format)
9
+ * @see docs/specs/architecture.md §3.4, §7.2, §9.4, §12.2, §13 Phase A
10
+ */
11
+ import { z } from 'zod';
12
+ /**
13
+ * The canonical set of Gemini CLI tool names, derived from the CLAUDE_TO_GEMINI_TOOLS
14
+ * mapping in build-standalone.ts of the template repository.
15
+ *
16
+ * Stage 3's transform layer consumes this for tool-name validation. Exporting from the
17
+ * schema module keeps the data colocated with the authoritative type definitions.
18
+ */
19
+ export declare const GEMINI_TOOL_NAMES: readonly ["read_file", "replace", "search_file_content", "glob", "run_shell_command", "write_file", "activate_skill"];
20
+ /** Union type of all valid Gemini CLI tool names. */
21
+ export type GeminiToolName = (typeof GEMINI_TOOL_NAMES)[number];
22
+ /**
23
+ * Schema for `gemini-extension.json` — the Gemini CLI extension manifest.
24
+ *
25
+ * NOTE: This schema uses `.loose()` at the top level rather than `.strict()`. Gemini CLI
26
+ * may include additional top-level fields that the template does not yet model (e.g., display
27
+ * metadata, capability declarations). Using `.loose()` tolerates those unknown fields without
28
+ * breaking validation, which matches the original `GeminiExtensionSchema` in validate.ts.
29
+ * When Gemini's manifest format is formally documented and stabilised, tighten this to
30
+ * `.strict()` and enumerate every known field.
31
+ */
32
+ export declare const geminiExtensionManifestSchema: z.ZodObject<{
33
+ name: z.ZodString;
34
+ version: z.ZodOptional<z.ZodString>;
35
+ description: z.ZodOptional<z.ZodString>;
36
+ schemaVersion: z.ZodOptional<z.ZodString>;
37
+ }, z.core.$loose>;
38
+ /**
39
+ * Schema for the YAML frontmatter of `agents/*.md` files emitted for the Gemini CLI target.
40
+ *
41
+ * NOTE: This schema uses `.loose()` for the same reason as `geminiExtensionManifestSchema` —
42
+ * agent frontmatter may include additional fields that Gemini CLI accepts but that the template
43
+ * does not yet model. The `tools` field accepts `string[]` without constraining to
44
+ * `GEMINI_TOOL_NAMES` because tool-name validation belongs to Stage 3's transform layer, not
45
+ * the shape-only validator here.
46
+ */
47
+ export declare const geminiAgentFrontmatterSchema: z.ZodObject<{
48
+ name: z.ZodString;
49
+ description: z.ZodString;
50
+ tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
51
+ schemaVersion: z.ZodOptional<z.ZodString>;
52
+ }, z.core.$loose>;
53
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/targets/gemini/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,uHAQpB,CAAC;AAEX,qDAAqD;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAMhE;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B;;;;;iBAOhC,CAAC;AAMX;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B;;;;;iBAO/B,CAAC"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Zod schemas for the Gemini CLI target.
3
+ *
4
+ * These are faithful, non-breaking ports of the JSON Schema contracts that the template
5
+ * repository has used in practice. Per §13 Phase A of the architecture spec, no schema
6
+ * breaking changes are introduced here — this is a mechanical port only.
7
+ *
8
+ * @see https://ai.google.dev/gemini-api/docs/gemini-cli (Gemini CLI extension format)
9
+ * @see docs/specs/architecture.md §3.4, §7.2, §9.4, §12.2, §13 Phase A
10
+ */
11
+ import { z } from 'zod';
12
+ // ---------------------------------------------------------------------------
13
+ // Canonical Gemini CLI tool names
14
+ // ---------------------------------------------------------------------------
15
+ /**
16
+ * The canonical set of Gemini CLI tool names, derived from the CLAUDE_TO_GEMINI_TOOLS
17
+ * mapping in build-standalone.ts of the template repository.
18
+ *
19
+ * Stage 3's transform layer consumes this for tool-name validation. Exporting from the
20
+ * schema module keeps the data colocated with the authoritative type definitions.
21
+ */
22
+ export const GEMINI_TOOL_NAMES = [
23
+ 'read_file',
24
+ 'replace',
25
+ 'search_file_content',
26
+ 'glob',
27
+ 'run_shell_command',
28
+ 'write_file',
29
+ 'activate_skill',
30
+ ];
31
+ // ---------------------------------------------------------------------------
32
+ // gemini-extension.json
33
+ // ---------------------------------------------------------------------------
34
+ /**
35
+ * Schema for `gemini-extension.json` — the Gemini CLI extension manifest.
36
+ *
37
+ * NOTE: This schema uses `.loose()` at the top level rather than `.strict()`. Gemini CLI
38
+ * may include additional top-level fields that the template does not yet model (e.g., display
39
+ * metadata, capability declarations). Using `.loose()` tolerates those unknown fields without
40
+ * breaking validation, which matches the original `GeminiExtensionSchema` in validate.ts.
41
+ * When Gemini's manifest format is formally documented and stabilised, tighten this to
42
+ * `.strict()` and enumerate every known field.
43
+ */
44
+ export const geminiExtensionManifestSchema = z
45
+ .object({
46
+ name: z.string(),
47
+ version: z.string().optional(),
48
+ description: z.string().optional(),
49
+ schemaVersion: z.string().optional(),
50
+ })
51
+ .loose();
52
+ // ---------------------------------------------------------------------------
53
+ // agents/*.md YAML frontmatter (as emitted for Gemini)
54
+ // ---------------------------------------------------------------------------
55
+ /**
56
+ * Schema for the YAML frontmatter of `agents/*.md` files emitted for the Gemini CLI target.
57
+ *
58
+ * NOTE: This schema uses `.loose()` for the same reason as `geminiExtensionManifestSchema` —
59
+ * agent frontmatter may include additional fields that Gemini CLI accepts but that the template
60
+ * does not yet model. The `tools` field accepts `string[]` without constraining to
61
+ * `GEMINI_TOOL_NAMES` because tool-name validation belongs to Stage 3's transform layer, not
62
+ * the shape-only validator here.
63
+ */
64
+ export const geminiAgentFrontmatterSchema = z
65
+ .object({
66
+ name: z.string(),
67
+ description: z.string(),
68
+ tools: z.array(z.string()).optional(),
69
+ schemaVersion: z.string().optional(),
70
+ })
71
+ .loose();
72
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/targets/gemini/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8EAA8E;AAC9E,kCAAkC;AAClC,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,WAAW;IACX,SAAS;IACT,qBAAqB;IACrB,MAAM;IACN,mBAAmB;IACnB,YAAY;IACZ,gBAAgB;CACR,CAAC;AAKX,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAE9E;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC;KAC3C,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC;KACD,KAAK,EAAE,CAAC;AAEX,8EAA8E;AAC9E,uDAAuD;AACvD,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC;KAC1C,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACrC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC;KACD,KAAK,EAAE,CAAC"}