@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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/components.ts","../src/fs.ts","../src/schema.ts","../src/source.ts","../src/build.ts","../src/managed.ts","../src/targets.ts","../src/render.ts","../src/cleanup.ts","../src/diff.ts","../src/validate.ts"],"sourcesContent":["import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { createJiti } from \"jiti\";\nimport { z } from \"zod\";\nimport { componentDirs } from \"./components.js\";\nimport { exists } from \"./fs.js\";\nimport { configSchema, sourcePluginManifestSchema } from \"./schema.js\";\nimport { createFilesystemSourceProvider } from \"./source.js\";\nimport type {\n ResolvedProject,\n PluginpackConfig,\n ResolvedProjectConfig,\n SourcePlugin,\n SourcePluginManifest,\n} from \"./types.js\";\n\nexport function defineConfig(config: PluginpackConfig): PluginpackConfig {\n return config;\n}\n\nexport async function loadConfig(\n cwd = process.cwd(),\n configPath?: string,\n): Promise<ResolvedProject> {\n const projectConfig = await loadProjectConfig(cwd, configPath);\n const { config, rootDir } = projectConfig;\n const sourceRoot = path.resolve(rootDir, config.source?.plugins ?? \"plugins\");\n const plugins = await discoverSourcePlugins(sourceRoot);\n await addRootSkillsPlugin(rootDir, config, plugins);\n return {\n ...projectConfig,\n sourceRoot,\n plugins,\n source: createFilesystemSourceProvider(plugins),\n };\n}\n\nexport async function loadProjectConfig(\n cwd = process.cwd(),\n configPath?: string,\n): Promise<ResolvedProjectConfig> {\n const resolvedConfigPath = configPath\n ? path.resolve(cwd, configPath)\n : await findConfig(cwd);\n const jiti = createJiti(pathToFileURL(resolvedConfigPath).href, {\n interopDefault: true,\n });\n const loaded = await jiti.import(resolvedConfigPath, { default: true });\n const config = parseWithContext(\n configSchema,\n loaded,\n resolvedConfigPath,\n ) as PluginpackConfig;\n const rootDir = path.dirname(resolvedConfigPath);\n return {\n rootDir,\n configPath: resolvedConfigPath,\n config,\n };\n}\n\nasync function addRootSkillsPlugin(\n rootDir: string,\n config: PluginpackConfig,\n plugins: Map<string, SourcePlugin>,\n): Promise<void> {\n if (!config.source?.skills) {\n return;\n }\n const id = config.source.rootPlugin?.id ?? \"core\";\n if (plugins.has(id)) {\n throw new Error(\n `Root skills source plugin \"${id}\" conflicts with an existing source plugin.`,\n );\n }\n const skillsDir = path.resolve(rootDir, config.source.skills);\n if (!(await exists(skillsDir))) {\n throw new Error(`Root skills source directory is missing: ${skillsDir}`);\n }\n const manifest = { ...(config.source.rootPlugin ?? {}) };\n delete manifest.id;\n plugins.set(id, {\n id,\n dir: rootDir,\n manifest,\n componentRoots: {\n skills: skillsDir,\n },\n includeStaticFiles: false,\n });\n}\n\nasync function findConfig(cwd: string): Promise<string> {\n const names = [\n \"pluginpack.config.ts\",\n \"pluginpack.config.mts\",\n \"pluginpack.config.mjs\",\n \"pluginpack.config.js\",\n ];\n for (const name of names) {\n const candidate = path.resolve(cwd, name);\n if (await exists(candidate)) {\n return candidate;\n }\n }\n throw new Error(\n `No pluginpack config found in ${cwd}. Expected ${names.join(\", \")}.`,\n );\n}\n\nasync function discoverSourcePlugins(\n sourceRoot: string,\n): Promise<Map<string, SourcePlugin>> {\n const plugins = new Map<string, SourcePlugin>();\n if (!(await exists(sourceRoot))) {\n return plugins;\n }\n const entries = await fs.readdir(sourceRoot, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) {\n continue;\n }\n const dir = path.join(sourceRoot, entry.name);\n if (!(await isSourcePluginDir(dir))) {\n continue;\n }\n const manifestPath = path.join(dir, \"plugin.pluginpack.json\");\n const manifest = await readSourceManifest(manifestPath);\n plugins.set(entry.name, {\n id: entry.name,\n dir,\n manifest,\n });\n }\n return plugins;\n}\n\n// A source plugin dir declares a manifest or has at least one component dir.\n// This keeps generated target output (e.g. plugins/cursor/ in a single-repo\n// layout) from being misread as source on rebuild.\nasync function isSourcePluginDir(dir: string): Promise<boolean> {\n if (await exists(path.join(dir, \"plugin.pluginpack.json\"))) {\n return true;\n }\n for (const component of componentDirs) {\n if (await exists(path.join(dir, component))) {\n return true;\n }\n }\n return false;\n}\n\nasync function readSourceManifest(\n filePath: string,\n): Promise<SourcePluginManifest> {\n if (!(await exists(filePath))) {\n return {};\n }\n const raw = await fs.readFile(filePath, \"utf8\");\n try {\n return parseWithContext(\n sourcePluginManifestSchema,\n JSON.parse(raw),\n filePath,\n ) as SourcePluginManifest;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid JSON in ${filePath}: ${error.message}`);\n }\n throw error;\n }\n}\n\nfunction parseWithContext(\n schema: z.ZodType,\n value: unknown,\n context: string,\n): unknown {\n const parsed = schema.safeParse(value);\n if (parsed.success) {\n return parsed.data;\n }\n const details = parsed.error.issues\n .map((issue) => `${issue.path.join(\".\") || \"(root)\"}: ${issue.message}`)\n .join(\"; \");\n throw new Error(`Invalid pluginpack config in ${context}: ${details}`);\n}\n","import type { TargetName } from \"./types.js\";\n\nexport const componentDirs = [\n \"skills\",\n \"agents\",\n \"commands\",\n \"rules\",\n \"hooks\",\n \"scripts\",\n \"assets\",\n \"policies\",\n \"themes\",\n];\n\nexport const staticFiles = [\"README.md\", \"CHANGELOG.md\", \"LICENSE\"];\n\nexport const targetDefaultComponents: Record<TargetName, readonly string[]> = {\n claude: [\"skills\", \"agents\", \"hooks\", \"scripts\", \"assets\"],\n copilot: [\"skills\", \"agents\", \"hooks\", \"scripts\", \"assets\"],\n cursor: [\"skills\", \"agents\", \"rules\", \"hooks\", \"scripts\", \"assets\"],\n antigravity: [\"skills\", \"agents\", \"rules\", \"hooks\", \"scripts\", \"assets\"],\n};\n\nexport function resolveTargetComponents(\n target: TargetName,\n pluginConfig: { components?: string[] },\n): Set<string> {\n return new Set(pluginConfig.components ?? targetDefaultComponents[target]);\n}\n\nexport function isComponentPath(relativePath: string): boolean {\n return componentDirs.includes(relativePath.split(\"/\")[0]);\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport fastGlob from \"fast-glob\";\nimport type { FileValue } from \"./types.js\";\n\nexport function toPosix(value: string): string {\n return value.split(path.sep).join(\"/\");\n}\n\nexport async function walkFiles(dir: string): Promise<string[]> {\n const entries = await fastGlob(\"**/*\", {\n cwd: dir,\n absolute: true,\n onlyFiles: true,\n dot: true,\n });\n return entries.sort();\n}\n\nexport async function writeArtifact(\n outDir: string,\n files: Map<string, FileValue>,\n): Promise<void> {\n for (const [relativePath, value] of files) {\n const destination = path.join(outDir, relativePath);\n await fs.mkdir(path.dirname(destination), { recursive: true });\n await fs.writeFile(destination, value);\n }\n}\n\nexport function json(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nexport function isSafeRelativePath(value: string): boolean {\n if (!value) {\n return false;\n }\n if (value.startsWith(\"http://\") || value.startsWith(\"https://\")) {\n return true;\n }\n if (path.isAbsolute(value)) {\n return false;\n }\n const normalized = path.posix.normalize(value.replace(/\\\\/g, \"/\"));\n return normalized !== \"..\" && !normalized.startsWith(\"../\");\n}\n\nexport async function exists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","import { z } from \"zod\";\n\nconst authorSchema = z.object({\n name: z.string().min(1),\n email: z.string().optional(),\n url: z.string().optional(),\n});\n\nconst metadataSchema = z.object({\n displayName: z.string().optional(),\n description: z.string().optional(),\n author: authorSchema.optional(),\n owner: authorSchema.optional(),\n homepage: z.string().optional(),\n repository: z.string().optional(),\n license: z.string().optional(),\n logo: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n category: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n\nconst rootPluginSchema = metadataSchema.extend({\n id: z.string().min(1).optional(),\n name: z.string().optional(),\n description: z.string().optional(),\n});\n\nconst sourceSchema = z.object({\n plugins: z.string().optional(),\n skills: z.string().optional(),\n rootPlugin: rootPluginSchema.optional(),\n});\n\nconst emittedPluginSchema = z.object({\n from: z.array(z.string().min(1)).min(1),\n path: z.string().optional(),\n version: z.string().optional(),\n description: z.string().optional(),\n displayName: z.string().optional(),\n manifest: z.record(z.string(), z.unknown()).optional(),\n components: z.array(z.string()).optional(),\n});\n\nconst targetSchema = z.object({\n outDir: z.string().min(1),\n marketplaceDir: z.string().optional(),\n pluginRoot: z.string().optional(),\n version: z.string().optional(),\n plugins: z.record(z.string(), emittedPluginSchema),\n manifest: z.record(z.string(), z.unknown()).optional(),\n ignoredDiffPaths: z.array(z.string()).optional(),\n});\n\nconst configSchema = z.object({\n name: z.string().min(1),\n version: z.string().min(1),\n source: sourceSchema.optional(),\n metadata: metadataSchema.optional(),\n targets: z.object({\n claude: targetSchema.optional(),\n copilot: targetSchema.optional(),\n cursor: targetSchema.optional(),\n antigravity: targetSchema.optional(),\n }),\n});\n\nconst sourcePluginManifestSchema = metadataSchema.extend({\n name: z.string().optional(),\n description: z.string().optional(),\n mcpServers: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport { configSchema, sourcePluginManifestSchema };\n\nexport type Author = z.infer<typeof authorSchema>;\nexport type Metadata = z.infer<typeof metadataSchema>;\nexport type SourceConfig = z.infer<typeof sourceSchema>;\nexport type EmittedPluginConfig = z.infer<typeof emittedPluginSchema>;\nexport type TargetConfig = z.infer<typeof targetSchema>;\nexport type PluginpackConfig = z.infer<typeof configSchema>;\nexport type SourcePluginManifest = z.infer<typeof sourcePluginManifestSchema>;\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { componentDirs, staticFiles } from \"./components.js\";\nimport { exists, toPosix, walkFiles } from \"./fs.js\";\nimport type {\n FileValue,\n SourcePlugin,\n SourceProvider,\n TargetName,\n} from \"./types.js\";\n\n// Filesystem-backed source: reads a discovered plugin's component and static\n// files (with target overrides) and its MCP servers from disk. The discovered\n// plugins map is passed in; an API-backed provider would implement the same\n// SourceProvider interface against the Skills API instead.\nexport function createFilesystemSourceProvider(\n plugins: Map<string, SourcePlugin>,\n): SourceProvider {\n return {\n listPlugins: () => Promise.resolve(plugins),\n readPluginFiles: (pluginId, target) =>\n readPluginFiles(pluginOrThrow(plugins, pluginId), target),\n readMcpServers: (pluginId) =>\n readMcpServers(pluginOrThrow(plugins, pluginId)),\n };\n}\n\nfunction pluginOrThrow(\n plugins: Map<string, SourcePlugin>,\n pluginId: string,\n): SourcePlugin {\n const plugin = plugins.get(pluginId);\n if (!plugin) {\n throw new Error(`Unknown source plugin \"${pluginId}\".`);\n }\n return plugin;\n}\n\nasync function readPluginFiles(\n plugin: SourcePlugin,\n target: TargetName,\n): Promise<Map<string, FileValue>> {\n const files = new Map<string, FileValue>();\n for (const dirName of componentDirs) {\n const dir =\n plugin.componentRoots?.[dirName] ?? path.join(plugin.dir, dirName);\n if (!(await exists(dir))) {\n continue;\n }\n for (const file of await walkFiles(dir)) {\n if (isTargetOverrideFile(file)) {\n continue;\n }\n const relativeToPlugin = toPosix(\n plugin.componentRoots?.[dirName]\n ? path.join(dirName, path.relative(dir, file))\n : path.relative(plugin.dir, file),\n );\n const resolved = await resolveTargetOverride(plugin.dir, file, target);\n files.set(relativeToPlugin, await fs.readFile(resolved));\n }\n }\n\n if (plugin.includeStaticFiles !== false) {\n for (const fileName of staticFiles) {\n const file = path.join(plugin.dir, fileName);\n if (!(await exists(file))) {\n continue;\n }\n const resolved = await resolveTargetOverride(plugin.dir, file, target);\n files.set(fileName, await fs.readFile(resolved));\n }\n }\n return files;\n}\n\nfunction isTargetOverrideFile(filePath: string): boolean {\n return filePath.split(path.sep).includes(\"targets\");\n}\n\nasync function resolveTargetOverride(\n pluginDir: string,\n file: string,\n target: TargetName,\n): Promise<string> {\n const basenameOverride = path.join(\n path.dirname(file),\n \"targets\",\n target,\n path.basename(file),\n );\n if (await exists(basenameOverride)) {\n return basenameOverride;\n }\n const relative = path.relative(pluginDir, file);\n const rootOverride = path.join(pluginDir, \"targets\", target, relative);\n if (await exists(rootOverride)) {\n return rootOverride;\n }\n return file;\n}\n\n// A source plugin declares MCP servers via a .mcp.json file (standard\n// { mcpServers: {...} } shape) or an mcpServers key in plugin.pluginpack.json.\n// The file takes precedence when both are present.\nasync function readMcpServers(\n plugin: SourcePlugin,\n): Promise<Record<string, unknown> | undefined> {\n const filePath = path.join(plugin.dir, \".mcp.json\");\n if (await exists(filePath)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(await fs.readFile(filePath, \"utf8\"));\n } catch (error) {\n throw new Error(\n `Invalid JSON in ${filePath}: ${(error as Error).message}`,\n );\n }\n const servers = (parsed as { mcpServers?: unknown }).mcpServers;\n return isObject(servers) ? servers : undefined;\n }\n return isObject(plugin.manifest.mcpServers)\n ? plugin.manifest.mcpServers\n : undefined;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import path from \"node:path\";\nimport { loadConfig } from \"./config.js\";\nimport { writeArtifact } from \"./fs.js\";\nimport {\n buildDeleteGuard,\n pruneManagedFiles,\n writeManagedManifest,\n} from \"./managed.js\";\nimport { emitTarget } from \"./targets.js\";\nimport type { Artifact, BuildOptions, TargetName } from \"./types.js\";\n\nconst allTargets: TargetName[] = [\"cursor\", \"claude\", \"antigravity\", \"copilot\"];\n\nexport async function build(options: BuildOptions = {}): Promise<Artifact[]> {\n const project = await loadConfig(options.cwd, options.configPath);\n const targets = options.target\n ? [options.target]\n : allTargets.filter((target) => project.config.targets[target]);\n const guard = buildDeleteGuard(\n project.rootDir,\n project.config,\n project.configPath,\n );\n const artifacts: Artifact[] = [];\n for (const target of targets) {\n artifacts.push(await emitTarget(project, target, options.outDir));\n }\n assertNoCrossTargetCollisions(artifacts);\n if (!options.dryRun) {\n for (const artifact of artifacts) {\n await pruneManagedFiles(artifact, { guard });\n await writeArtifact(artifact.outDir, artifact.files);\n await writeManagedManifest(artifact);\n }\n }\n return artifacts;\n}\n\n// Two targets pointed at overlapping output paths would silently overwrite each\n// other (and one target's prune could delete the other's files). Catch it.\nfunction assertNoCrossTargetCollisions(artifacts: Artifact[]): void {\n const owner = new Map<string, TargetName>();\n const collisions: string[] = [];\n for (const artifact of artifacts) {\n for (const managedPath of artifact.managedPaths) {\n const absolute = path.resolve(artifact.outDir, managedPath);\n const previous = owner.get(absolute);\n if (previous && previous !== artifact.target) {\n collisions.push(` ${previous} and ${artifact.target}: ${absolute}`);\n } else {\n owner.set(absolute, artifact.target);\n }\n }\n }\n if (collisions.length > 0) {\n throw new Error(\n `Targets write overlapping output paths; give them distinct outDirs:\\n${collisions.join(\"\\n\")}`,\n );\n }\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { json, toPosix } from \"./fs.js\";\nimport type {\n Artifact,\n CleanupEntry,\n CleanupResult,\n DeleteGuard,\n PluginpackConfig,\n TargetName,\n} from \"./types.js\";\n\ntype ManagedManifest = {\n version: 1;\n target: TargetName;\n files: string[];\n};\n\nexport function managedManifestPath(target: TargetName): string {\n return toPosix(path.join(\".pluginpack\", `${target}.json`));\n}\n\nexport async function writeManagedManifest(artifact: Artifact): Promise<void> {\n const manifest: ManagedManifest = {\n version: 1,\n target: artifact.target,\n files: artifact.managedPaths,\n };\n const destination = path.join(\n artifact.outDir,\n managedManifestPath(artifact.target),\n );\n await fs.mkdir(path.dirname(destination), { recursive: true });\n await fs.writeFile(destination, json(manifest));\n}\n\nexport async function readManagedManifest(\n outDir: string,\n target: TargetName,\n): Promise<ManagedManifest | null> {\n const manifestPath = path.join(outDir, managedManifestPath(target));\n let raw: string;\n try {\n raw = await fs.readFile(manifestPath, \"utf8\");\n } catch (error) {\n if (isNotFound(error)) {\n return null;\n }\n throw error;\n }\n const parsed = JSON.parse(raw) as Partial<ManagedManifest>;\n if (\n parsed.version !== 1 ||\n parsed.target !== target ||\n !Array.isArray(parsed.files) ||\n !parsed.files.every((file) => typeof file === \"string\")\n ) {\n throw new Error(`Invalid managed manifest: ${manifestPath}`);\n }\n return parsed as ManagedManifest;\n}\n\nexport async function pruneManagedFiles(\n artifact: Artifact,\n options: { dryRun?: boolean; guard?: DeleteGuard } = {},\n): Promise<CleanupResult> {\n const previous = await readManagedManifest(artifact.outDir, artifact.target);\n const current = new Set(artifact.managedPaths.map(normalizeManagedPath));\n const stale = (previous?.files ?? [])\n .map(normalizeManagedPath)\n .filter((file) => !current.has(file));\n if (!options.dryRun) {\n assertNoProtectedDeletions(artifact.outDir, stale, options.guard, \"prune\");\n }\n const entries: CleanupEntry[] = [];\n for (const normalized of stale) {\n entries.push({\n type: \"stale\",\n target: artifact.target,\n path: normalized,\n });\n if (!options.dryRun) {\n await removeManagedPath(artifact.outDir, normalized);\n }\n }\n return {\n target: artifact.target,\n outDir: artifact.outDir,\n entries,\n };\n}\n\nexport async function cleanManagedFiles(\n outDir: string,\n target: TargetName,\n options: { dryRun?: boolean; guard?: DeleteGuard } = {},\n): Promise<CleanupResult> {\n const previous = await readManagedManifest(outDir, target);\n const entries: CleanupEntry[] = [];\n if (!previous) {\n return { target, outDir, entries };\n }\n const files = (previous.files ?? []).map(normalizeManagedPath);\n if (!options.dryRun) {\n assertNoProtectedDeletions(outDir, files, options.guard, \"clean\");\n }\n for (const normalized of files) {\n entries.push({ type: \"deleted\", target, path: normalized });\n if (!options.dryRun) {\n await removeManagedPath(outDir, normalized);\n }\n }\n const manifestPath = managedManifestPath(target);\n entries.push({ type: \"deleted\", target, path: manifestPath });\n if (!options.dryRun) {\n await removeManagedPath(outDir, manifestPath);\n }\n return { target, outDir, entries };\n}\n\nexport function buildDeleteGuard(\n rootDir: string,\n config: PluginpackConfig,\n configPath: string,\n force?: boolean,\n): DeleteGuard {\n const protectedRoots: string[] = [];\n if (config.source?.skills) {\n protectedRoots.push(path.resolve(rootDir, config.source.skills));\n }\n if (config.source?.plugins) {\n protectedRoots.push(path.resolve(rootDir, config.source.plugins));\n }\n return { protectedRoots, configPath: path.resolve(configPath), force };\n}\n\nfunction assertNoProtectedDeletions(\n outDir: string,\n paths: string[],\n guard: DeleteGuard | undefined,\n command: string,\n): void {\n if (!guard || guard.force) {\n return;\n }\n const blocked = paths.filter((file) =>\n isProtectedDeletion(outDir, file, guard),\n );\n if (blocked.length === 0) {\n return;\n }\n throw new Error(\n `Refusing to ${command} ${blocked.length} path(s) that resolve inside your source tree or config:\\n` +\n `${blocked.map((file) => ` ${file}`).join(\"\\n\")}\\n` +\n `This usually means a target outDir overlaps source.skills/source.plugins. ` +\n `Fix the config, or re-run with --force to delete anyway.`,\n );\n}\n\nfunction isProtectedDeletion(\n outDir: string,\n relativePath: string,\n guard: DeleteGuard,\n): boolean {\n const absolute = path.resolve(outDir, normalizeManagedPath(relativePath));\n if (guard.configPath && absolute === guard.configPath) {\n return true;\n }\n return guard.protectedRoots.some(\n (root) => absolute === root || absolute.startsWith(`${root}${path.sep}`),\n );\n}\n\nexport function normalizeManagedPath(value: string): string {\n const normalized = path.posix.normalize(value.replace(/\\\\/g, \"/\"));\n if (\n !value ||\n path.posix.isAbsolute(normalized) ||\n normalized === \"..\" ||\n normalized.startsWith(\"../\")\n ) {\n throw new Error(`Unsafe managed path: ${value}`);\n }\n return normalized.startsWith(\"./\") ? normalized.slice(2) : normalized;\n}\n\nasync function removeManagedPath(\n outDir: string,\n relativePath: string,\n): Promise<void> {\n const root = path.resolve(outDir);\n const normalized = normalizeManagedPath(relativePath);\n const destination = path.resolve(root, normalized);\n if (destination !== root && !destination.startsWith(`${root}${path.sep}`)) {\n throw new Error(`Managed path escapes output directory: ${relativePath}`);\n }\n await fs.rm(destination, { force: true });\n await removeEmptyParents(path.dirname(destination), root);\n}\n\nasync function removeEmptyParents(dir: string, root: string): Promise<void> {\n let current = dir;\n while (current !== root && current.startsWith(`${root}${path.sep}`)) {\n try {\n await fs.rmdir(current);\n } catch (error) {\n if (isNotFound(error) || isDirectoryNotEmpty(error)) {\n return;\n }\n throw error;\n }\n current = path.dirname(current);\n }\n}\n\nfunction isNotFound(error: unknown): boolean {\n return (\n error instanceof Error &&\n \"code\" in error &&\n (error as NodeJS.ErrnoException).code === \"ENOENT\"\n );\n}\n\nfunction isDirectoryNotEmpty(error: unknown): boolean {\n return (\n error instanceof Error &&\n \"code\" in error &&\n ((error as NodeJS.ErrnoException).code === \"ENOTEMPTY\" ||\n (error as NodeJS.ErrnoException).code === \"EEXIST\")\n );\n}\n","import path from \"node:path\";\nimport { collectPluginFiles, resolveMcpServers } from \"./render.js\";\nimport { json, toPosix } from \"./fs.js\";\nimport { resolveTargetComponents } from \"./components.js\";\nimport type {\n Artifact,\n EmittedPluginConfig,\n Metadata,\n ResolvedProject,\n TargetConfig,\n TargetName,\n} from \"./types.js\";\n\ntype TargetEmitter = (\n project: ResolvedProject,\n target: TargetName,\n targetConfig: TargetConfig,\n outDir: string,\n) => Promise<Artifact>;\n\nconst emitters: Record<TargetName, TargetEmitter> = {\n claude: emitClaude,\n copilot: emitCopilot,\n cursor: emitCursor,\n antigravity: emitAntigravity,\n};\n\nexport async function emitTarget(\n project: ResolvedProject,\n target: TargetName,\n outDir?: string,\n): Promise<Artifact> {\n const targetConfig = project.config.targets[target];\n if (!targetConfig) {\n throw new Error(`Target \"${target}\" is not configured.`);\n }\n const emitter = emitters[target];\n const resolvedOutDir = path.resolve(\n project.rootDir,\n outDir ?? targetConfig.outDir,\n );\n return emitter(project, target, targetConfig, resolvedOutDir);\n}\n\ntype MarketplaceEntry = {\n name: string;\n source: string;\n description?: string;\n};\n\ntype EmitPluginsOptions = {\n resolvePluginPath: (\n pluginName: string,\n pluginConfig: EmittedPluginConfig,\n ) => string;\n pluginManifestPath: (pluginPath: string) => string;\n buildManifest: (\n metadata: Metadata | undefined,\n pluginName: string,\n pluginConfig: EmittedPluginConfig,\n componentDirs: Set<string>,\n mcpServers: Record<string, unknown> | undefined,\n ) => Record<string, unknown>;\n entrySource?: (pluginPath: string) => string;\n mcp?: \"file\" | \"antigravity\";\n};\n\nasync function emitPlugins(\n project: ResolvedProject,\n target: TargetName,\n targetConfig: TargetConfig,\n files: Map<string, string | Buffer>,\n options: EmitPluginsOptions,\n): Promise<MarketplaceEntry[]> {\n const entries: MarketplaceEntry[] = [];\n for (const [pluginName, pluginConfig] of Object.entries(\n targetConfig.plugins,\n )) {\n const pluginPath = options.resolvePluginPath(pluginName, pluginConfig);\n const pluginFiles = await collectPluginFiles(\n project,\n target,\n pluginConfig.from,\n resolveTargetComponents(target, pluginConfig),\n );\n const componentDirs = new Set(\n [...pluginFiles.keys()].map((file) => file.split(\"/\")[0]),\n );\n for (const [relativePath, value] of pluginFiles) {\n files.set(toPosix(path.join(pluginPath, relativePath)), value);\n }\n\n const mcpServers = await resolveMcpServers(project, pluginConfig.from);\n if (mcpServers && options.mcp === \"file\") {\n files.set(\n toPosix(path.join(pluginPath, \".mcp.json\")),\n json({ mcpServers }),\n );\n } else if (mcpServers && options.mcp === \"antigravity\") {\n files.set(\n toPosix(path.join(pluginPath, \"mcp_config.json\")),\n json({ mcpServers }),\n );\n }\n\n const metadata = emittedPluginMetadata(project, pluginConfig);\n const manifest = options.buildManifest(\n metadata,\n pluginName,\n pluginConfig,\n componentDirs,\n mcpServers,\n );\n files.set(toPosix(options.pluginManifestPath(pluginPath)), json(manifest));\n\n if (options.entrySource) {\n entries.push({\n name: pluginName,\n source: options.entrySource(pluginPath),\n description:\n pluginConfig.description ??\n (manifest.description as string | undefined),\n });\n }\n }\n return entries;\n}\n\nasync function emitCursor(\n project: ResolvedProject,\n target: TargetName,\n targetConfig: TargetConfig,\n outDir: string,\n): Promise<Artifact> {\n const marketplaceDir = targetConfig.marketplaceDir ?? \".cursor-plugin\";\n const version = targetConfig.version ?? project.config.version;\n const files = new Map<string, string | Buffer>();\n\n const plugins = await emitPlugins(project, target, targetConfig, files, {\n resolvePluginPath: (pluginName, pluginConfig) =>\n pluginConfig.path ?? pluginName,\n pluginManifestPath: (pluginPath) =>\n path.join(pluginPath, marketplaceDir, \"plugin.json\"),\n buildManifest: (\n metadata,\n pluginName,\n pluginConfig,\n componentDirs,\n mcpServers,\n ) =>\n cursorPluginManifest(\n metadata,\n pluginConfig.version ?? version,\n pluginName,\n pluginConfig,\n componentDirs,\n mcpServers,\n ),\n entrySource: (pluginPath) => pluginPath,\n mcp: \"file\",\n });\n\n const marketplace = stripUndefined(\n deepMerge(\n {\n name: project.config.name,\n owner:\n project.config.metadata?.owner ?? project.config.metadata?.author,\n metadata: {\n description: project.config.metadata?.description,\n keywords: project.config.metadata?.keywords,\n },\n plugins,\n version,\n },\n targetConfig.manifest ?? {},\n ),\n );\n files.set(\n toPosix(path.join(marketplaceDir, \"marketplace.json\")),\n json(marketplace),\n );\n\n return artifact(target, outDir, files);\n}\n\nasync function emitClaude(\n project: ResolvedProject,\n target: TargetName,\n targetConfig: TargetConfig,\n outDir: string,\n): Promise<Artifact> {\n const marketplaceDir = targetConfig.marketplaceDir ?? \".claude-plugin\";\n const pluginRoot = targetConfig.pluginRoot ?? \"plugins\";\n const version = targetConfig.version ?? project.config.version;\n const files = new Map<string, string | Buffer>();\n\n const plugins = await emitPlugins(project, target, targetConfig, files, {\n resolvePluginPath: (pluginName, pluginConfig) =>\n pluginConfig.path ?? toPosix(path.join(pluginRoot, pluginName)),\n pluginManifestPath: (pluginPath) =>\n path.join(pluginPath, marketplaceDir, \"plugin.json\"),\n buildManifest: (metadata, pluginName, pluginConfig) =>\n claudePluginManifest(\n metadata,\n pluginConfig.version ?? version,\n pluginName,\n pluginConfig,\n ),\n entrySource: (pluginPath) => `./${pluginPath}`,\n mcp: \"file\",\n });\n\n const marketplace = stripUndefined(\n deepMerge(\n {\n $schema: \"https://anthropic.com/claude-code/marketplace.schema.json\",\n name: project.config.name,\n version,\n description: project.config.metadata?.description,\n owner:\n project.config.metadata?.owner ?? project.config.metadata?.author,\n plugins,\n },\n targetConfig.manifest ?? {},\n ),\n );\n files.set(\n toPosix(path.join(marketplaceDir, \"marketplace.json\")),\n json(marketplace),\n );\n\n return artifact(target, outDir, files);\n}\n\nasync function emitAntigravity(\n project: ResolvedProject,\n target: TargetName,\n targetConfig: TargetConfig,\n outDir: string,\n): Promise<Artifact> {\n const version = targetConfig.version ?? project.config.version;\n const files = new Map<string, string | Buffer>();\n\n await emitPlugins(project, target, targetConfig, files, {\n resolvePluginPath: (pluginName, pluginConfig) =>\n pluginConfig.path ?? pluginName,\n pluginManifestPath: (pluginPath) => path.join(pluginPath, \"plugin.json\"),\n buildManifest: (metadata, pluginName, pluginConfig) =>\n antigravityPluginManifest(\n metadata,\n pluginConfig.version ?? version,\n pluginName,\n pluginConfig,\n ),\n mcp: \"antigravity\",\n });\n\n return artifact(target, outDir, files);\n}\n\nasync function emitCopilot(\n project: ResolvedProject,\n target: TargetName,\n targetConfig: TargetConfig,\n outDir: string,\n): Promise<Artifact> {\n const version = targetConfig.version ?? project.config.version;\n const pluginRoot = targetConfig.pluginRoot ?? \"plugins\";\n const files = new Map<string, string | Buffer>();\n const plugins: Record<string, unknown>[] = [];\n\n for (const [pluginName, pluginConfig] of Object.entries(\n targetConfig.plugins,\n )) {\n const pluginPath =\n pluginConfig.path ?? toPosix(path.join(pluginRoot, pluginName));\n const pluginFiles = await collectPluginFiles(\n project,\n target,\n pluginConfig.from,\n resolveTargetComponents(target, pluginConfig),\n );\n for (const [relativePath, value] of pluginFiles) {\n files.set(toPosix(path.join(pluginPath, relativePath)), value);\n }\n\n const mcpServers = await resolveMcpServers(project, pluginConfig.from);\n if (mcpServers) {\n files.set(\n toPosix(path.join(pluginPath, \".mcp.json\")),\n json({ mcpServers }),\n );\n }\n\n const skills = [\n ...new Set(\n [...pluginFiles.keys()]\n .filter((file) => file.startsWith(\"skills/\"))\n .map((file) => `./skills/${file.split(\"/\")[1]}`),\n ),\n ].sort();\n const metadata = emittedPluginMetadata(project, pluginConfig);\n plugins.push(\n stripUndefined({\n name: pluginName,\n source: `./${pluginPath}`,\n description: pluginConfig.description ?? metadata?.description,\n version: pluginConfig.version ?? version,\n skills,\n mcpServers: mcpServers ? \".mcp.json\" : undefined,\n }),\n );\n }\n\n const marketplace = stripUndefined(\n deepMerge(\n {\n name: project.config.name,\n metadata: stripUndefined({\n description: project.config.metadata?.description,\n version,\n keywords: project.config.metadata?.keywords,\n }),\n owner:\n project.config.metadata?.owner ?? project.config.metadata?.author,\n plugins,\n },\n targetConfig.manifest ?? {},\n ),\n );\n // Copilot reuses the Claude marketplace schema and reads it from both the\n // repo-root .claude-plugin/ and .github/plugin/ (see github/copilot-plugins).\n const marketplaceJson = json(marketplace);\n files.set(\n toPosix(path.join(\".claude-plugin\", \"marketplace.json\")),\n marketplaceJson,\n );\n files.set(\n toPosix(path.join(\".github\", \"plugin\", \"marketplace.json\")),\n marketplaceJson,\n );\n\n return artifact(target, outDir, files);\n}\n\nfunction emittedPluginMetadata(\n project: ResolvedProject,\n pluginConfig: EmittedPluginConfig,\n): Metadata | undefined {\n const sourceMetadata =\n pluginConfig.from.length === 1\n ? project.plugins.get(pluginConfig.from[0])?.manifest\n : undefined;\n return stripUndefined({\n ...project.config.metadata,\n ...sourceMetadata,\n });\n}\n\nfunction cursorPluginManifest(\n metadata: Metadata | undefined,\n version: string,\n pluginName: string,\n pluginConfig: EmittedPluginConfig,\n componentDirs: Set<string>,\n mcpServers: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {\n name: pluginName,\n displayName:\n pluginConfig.displayName ??\n metadata?.displayName ??\n titleCase(pluginName),\n version,\n description: pluginConfig.description ?? metadata?.description,\n author: metadata?.author,\n homepage: metadata?.homepage,\n repository: metadata?.repository,\n license: metadata?.license,\n logo: metadata?.logo,\n keywords: metadata?.keywords,\n category: metadata?.category,\n tags: metadata?.tags,\n };\n const components = pluginConfig.components ?? [\n \"skills\",\n \"agents\",\n \"commands\",\n \"rules\",\n \"hooks\",\n ];\n for (const component of components) {\n if (componentDirs.has(component)) {\n manifest[component] = `./${component}/`;\n }\n }\n if (mcpServers) {\n manifest.mcpServers = \"./.mcp.json\";\n }\n return stripUndefined(deepMerge(manifest, pluginConfig.manifest ?? {}));\n}\n\nfunction claudePluginManifest(\n metadata: Metadata | undefined,\n version: string,\n pluginName: string,\n pluginConfig: EmittedPluginConfig,\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {\n name: pluginName,\n version,\n description: pluginConfig.description ?? metadata?.description,\n author: metadata?.author,\n homepage: metadata?.homepage,\n repository: metadata?.repository,\n license: metadata?.license,\n keywords: metadata?.keywords,\n };\n return stripUndefined(deepMerge(manifest, pluginConfig.manifest ?? {}));\n}\n\nfunction antigravityPluginManifest(\n metadata: Metadata | undefined,\n version: string,\n pluginName: string,\n pluginConfig: EmittedPluginConfig,\n): Record<string, unknown> {\n const manifest: Record<string, unknown> = {\n name: pluginName,\n version,\n description: pluginConfig.description ?? metadata?.description,\n };\n return stripUndefined(deepMerge(manifest, pluginConfig.manifest ?? {}));\n}\n\nfunction artifact(\n target: TargetName,\n outDir: string,\n files: Map<string, string | Buffer>,\n): Artifact {\n const managedPaths = [...files.keys()].sort();\n return {\n target,\n outDir,\n files: new Map([...files.entries()].sort(([a], [b]) => a.localeCompare(b))),\n managedPaths,\n };\n}\n\nfunction stripUndefined<T extends Record<string, unknown>>(value: T): T {\n for (const key of Object.keys(value)) {\n if (value[key] === undefined) {\n delete value[key];\n }\n }\n return value;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n// Deep-merge an override onto a generated manifest. Nested objects merge so a\n// sibling key isn't lost; arrays and scalars from the override replace (not\n// concatenate, so keywords/tags don't double up). This is the general escape\n// hatch — any field, at any depth, can be overridden via a target/plugin\n// `manifest`.\nfunction deepMerge(\n base: Record<string, unknown>,\n override: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = { ...base };\n for (const [key, value] of Object.entries(override)) {\n const existing = result[key];\n result[key] =\n isPlainObject(existing) && isPlainObject(value)\n ? deepMerge(existing, value)\n : value;\n }\n return result;\n}\n\nfunction titleCase(value: string): string {\n return value\n .split(/[-_.]/)\n .filter(Boolean)\n .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)\n .join(\" \");\n}\n","import { isComponentPath } from \"./components.js\";\nimport type { FileValue, ResolvedProject, TargetName } from \"./types.js\";\n\n// Merge the files of one or more source plugins into a single emitted-plugin\n// file map. File acquisition is delegated to project.source; the merge +\n// duplicate-path guard is pluginpack logic that holds regardless of source.\nexport async function collectPluginFiles(\n project: ResolvedProject,\n target: TargetName,\n sourceIds: string[],\n components?: Set<string>,\n): Promise<Map<string, FileValue>> {\n const files = new Map<string, FileValue>();\n for (const sourceId of sourceIds) {\n if (!project.plugins.has(sourceId)) {\n throw new Error(\n `Target \"${target}\" references unknown source plugin \"${sourceId}\".`,\n );\n }\n const pluginFiles = await project.source.readPluginFiles(sourceId, target);\n for (const [relativePath, value] of pluginFiles) {\n if (!shouldEmitFile(relativePath, components)) {\n continue;\n }\n setFile(files, relativePath, value, sourceId);\n }\n }\n return files;\n}\n\n// Merge the MCP servers of one or more source plugins; a server name present in\n// two merged plugins is an error.\nexport async function resolveMcpServers(\n project: ResolvedProject,\n sourceIds: string[],\n): Promise<Record<string, unknown> | undefined> {\n const merged: Record<string, unknown> = {};\n let found = false;\n for (const sourceId of sourceIds) {\n if (!project.plugins.has(sourceId)) {\n continue;\n }\n const servers = await project.source.readMcpServers(sourceId);\n if (!servers) {\n continue;\n }\n found = true;\n for (const [name, config] of Object.entries(servers)) {\n if (name in merged) {\n throw new Error(\n `Duplicate MCP server \"${name}\" while merging source plugin \"${sourceId}\".`,\n );\n }\n merged[name] = config;\n }\n }\n return found ? merged : undefined;\n}\n\nfunction shouldEmitFile(\n relativePath: string,\n components: Set<string> | undefined,\n): boolean {\n if (!components || !isComponentPath(relativePath)) {\n return true;\n }\n return components.has(relativePath.split(\"/\")[0]);\n}\n\nfunction setFile(\n files: Map<string, FileValue>,\n relativePath: string,\n value: FileValue,\n sourceId: string,\n): void {\n if (files.has(relativePath)) {\n throw new Error(\n `Duplicate emitted file \"${relativePath}\" while merging source plugin \"${sourceId}\". Add a target override or change the target plugin mapping.`,\n );\n }\n files.set(relativePath, value);\n}\n","import path from \"node:path\";\nimport { build } from \"./build.js\";\nimport { loadProjectConfig } from \"./config.js\";\nimport {\n buildDeleteGuard,\n cleanManagedFiles,\n pruneManagedFiles,\n} from \"./managed.js\";\nimport type { CleanupResult, TargetName } from \"./types.js\";\n\nexport async function prune(\n options: {\n cwd?: string;\n configPath?: string;\n target?: TargetName;\n dryRun?: boolean;\n force?: boolean;\n } = {},\n): Promise<CleanupResult[]> {\n const project = await loadProjectConfig(options.cwd, options.configPath);\n const guard = buildDeleteGuard(\n project.rootDir,\n project.config,\n project.configPath,\n options.force,\n );\n const artifacts = await build({\n cwd: options.cwd,\n configPath: options.configPath,\n target: options.target,\n dryRun: true,\n });\n const results: CleanupResult[] = [];\n for (const artifact of artifacts) {\n results.push(\n await pruneManagedFiles(artifact, { dryRun: options.dryRun, guard }),\n );\n }\n return results;\n}\n\nexport async function clean(\n options: {\n cwd?: string;\n configPath?: string;\n target?: TargetName;\n dryRun?: boolean;\n force?: boolean;\n } = {},\n): Promise<CleanupResult[]> {\n const project = await loadProjectConfig(options.cwd, options.configPath);\n const guard = buildDeleteGuard(\n project.rootDir,\n project.config,\n project.configPath,\n options.force,\n );\n const targets = options.target\n ? [options.target]\n : (Object.keys(project.config.targets) as TargetName[]);\n const results: CleanupResult[] = [];\n for (const target of targets) {\n const targetConfig = project.config.targets[target];\n if (!targetConfig) {\n throw new Error(`Target \"${target}\" is not configured.`);\n }\n const outDir = path.resolve(project.rootDir, targetConfig.outDir);\n results.push(\n await cleanManagedFiles(outDir, target, {\n dryRun: options.dryRun,\n guard,\n }),\n );\n }\n return results;\n}\n","import { promises as fs } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { build } from \"./build.js\";\nimport { loadConfig } from \"./config.js\";\nimport { exists } from \"./fs.js\";\nimport { normalizeManagedPath, readManagedManifest } from \"./managed.js\";\nimport type { DiffEntry, DiffResult, TargetName } from \"./types.js\";\n\nexport async function diffTarget(options: {\n cwd?: string;\n configPath?: string;\n target: TargetName;\n against: string;\n}): Promise<DiffResult> {\n const tempDir = await fs.mkdtemp(path.join(tmpdir(), \"pluginpack-diff-\"));\n try {\n const project = await loadConfig(options.cwd, options.configPath);\n const ignoredDiffPaths =\n project.config.targets[options.target]?.ignoredDiffPaths ?? [];\n const [artifact] = await build({\n cwd: options.cwd,\n configPath: options.configPath,\n target: options.target,\n outDir: tempDir,\n });\n const againstRoot = path.resolve(\n options.cwd ?? process.cwd(),\n options.against,\n );\n const entries: DiffEntry[] = [];\n const currentManagedPaths = new Set(\n artifact.managedPaths.map(normalizeManagedPath),\n );\n for (const relativePath of artifact.managedPaths) {\n if (isIgnoredDiffPath(relativePath, ignoredDiffPaths)) {\n continue;\n }\n const generatedPath = path.join(tempDir, relativePath);\n const againstPath = path.join(againstRoot, relativePath);\n if (!(await exists(againstPath))) {\n entries.push({ type: \"added\", path: relativePath });\n continue;\n }\n const [generated, existing] = await Promise.all([\n fs.readFile(generatedPath),\n fs.readFile(againstPath),\n ]);\n if (!generated.equals(existing)) {\n entries.push({ type: \"changed\", path: relativePath });\n }\n }\n const previous = await readManagedManifest(againstRoot, options.target);\n for (const previousPath of previous?.files ?? []) {\n const normalized = normalizeManagedPath(previousPath);\n if (\n currentManagedPaths.has(normalized) ||\n isIgnoredDiffPath(normalized, ignoredDiffPaths)\n ) {\n continue;\n }\n if (await exists(path.join(againstRoot, normalized))) {\n entries.push({ type: \"removed\", path: normalized });\n }\n }\n return {\n ok: entries.length === 0,\n entries,\n };\n } finally {\n await fs.rm(tempDir, { force: true, recursive: true });\n }\n}\n\nfunction isIgnoredDiffPath(\n relativePath: string,\n ignoredPaths: string[],\n): boolean {\n const normalized = normalizeDiffPath(relativePath);\n return ignoredPaths.some((ignoredPath) => {\n const ignored = normalizeDiffPath(ignoredPath);\n return normalized === ignored || normalized.startsWith(`${ignored}/`);\n });\n}\n\nfunction normalizeDiffPath(value: string): string {\n const normalized = path.posix.normalize(value.replace(/\\\\/g, \"/\"));\n return normalized.startsWith(\"./\") ? normalized.slice(2) : normalized;\n}\n","import { promises as fs, statSync } from \"node:fs\";\nimport path from \"node:path\";\nimport matter from \"gray-matter\";\nimport { exists, isSafeRelativePath, toPosix, walkFiles } from \"./fs.js\";\nimport type { TargetName, ValidationIssue, ValidationResult } from \"./types.js\";\n\nconst pluginNamePattern = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;\nconst marketplaceNamePattern = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;\n\nexport async function validateOutput(\n target: TargetName,\n dir: string,\n): Promise<ValidationResult> {\n const root = path.resolve(dir);\n const issues: ValidationIssue[] = [];\n if (target === \"cursor\") {\n await validateCursor(root, issues);\n } else if (target === \"claude\") {\n await validateClaude(root, issues);\n } else if (target === \"antigravity\") {\n await validateAntigravity(root, issues);\n } else {\n await validateCopilot(root, issues);\n }\n return {\n ok: issues.every((issue) => issue.level !== \"error\"),\n issues,\n };\n}\n\nasync function validateAntigravity(\n root: string,\n issues: ValidationIssue[],\n): Promise<void> {\n const entries = await fs.readdir(root, { withFileTypes: true });\n const pluginDirs = entries\n .filter((entry) => entry.isDirectory() && !entry.name.startsWith(\".\"))\n .map((entry) => path.join(root, entry.name));\n if (pluginDirs.length === 0) {\n error(\n issues,\n \"Antigravity output must contain at least one plugin directory.\",\n );\n return;\n }\n for (const pluginDir of pluginDirs) {\n const manifest = await readJson(\n path.join(pluginDir, \"plugin.json\"),\n \"Antigravity plugin manifest\",\n issues,\n );\n if (!manifest) {\n continue;\n }\n const pluginName = path.basename(pluginDir);\n if (\n typeof manifest.name !== \"string\" ||\n !pluginNamePattern.test(manifest.name)\n ) {\n error(\n issues,\n `${pluginName}: plugin.json must have a lowercase kebab-case \"name\".`,\n );\n }\n if (manifest.name && manifest.name !== pluginName) {\n error(\n issues,\n `${pluginName}: manifest name must match plugin directory name.`,\n );\n }\n for (const field of [\"version\", \"description\"]) {\n if (typeof manifest[field] !== \"string\" || !manifest[field]) {\n error(\n issues,\n `${pluginName}: plugin.json is missing required field \"${field}\".`,\n );\n }\n }\n const mcpConfigPath = path.join(pluginDir, \"mcp_config.json\");\n if (await exists(mcpConfigPath)) {\n await readJson(mcpConfigPath, `${pluginName} MCP config`, issues);\n }\n await validateFrontmatter(pluginDir, pluginName, \"antigravity\", issues);\n await validateHooks(pluginDir, pluginName, issues);\n }\n}\n\nasync function validateCopilot(\n root: string,\n issues: ValidationIssue[],\n): Promise<void> {\n const marketplacePath = path.join(root, \".claude-plugin\", \"marketplace.json\");\n const marketplace = await readJson(\n marketplacePath,\n \"Marketplace manifest\",\n issues,\n );\n if (!marketplace) {\n return;\n }\n validateMarketplaceBasics(marketplace, issues);\n if (\n !(await exists(path.join(root, \".github\", \"plugin\", \"marketplace.json\")))\n ) {\n error(\n issues,\n \"Copilot output must mirror the marketplace at .github/plugin/marketplace.json.\",\n );\n }\n const plugins = Array.isArray(marketplace.plugins) ? marketplace.plugins : [];\n if (plugins.length === 0) {\n error(issues, 'Marketplace \"plugins\" must be a non-empty array.');\n return;\n }\n for (const [index, entry] of plugins.entries()) {\n const pluginName = validatePluginEntry(entry, index, root, issues);\n if (!pluginName) {\n continue;\n }\n await validateFrontmatter(\n path.join(root, entry.source),\n pluginName,\n \"copilot\",\n issues,\n );\n }\n}\n\nasync function validateCursor(\n root: string,\n issues: ValidationIssue[],\n): Promise<void> {\n const marketplacePath = path.join(root, \".cursor-plugin\", \"marketplace.json\");\n const marketplace = await readJson(\n marketplacePath,\n \"Marketplace manifest\",\n issues,\n );\n if (!marketplace) {\n return;\n }\n validateMarketplaceBasics(marketplace, issues);\n const plugins = Array.isArray(marketplace.plugins) ? marketplace.plugins : [];\n if (plugins.length === 0) {\n error(issues, 'Marketplace \"plugins\" must be a non-empty array.');\n return;\n }\n for (const [index, entry] of plugins.entries()) {\n const pluginName = validatePluginEntry(entry, index, root, issues);\n if (!pluginName) {\n continue;\n }\n const pluginDir = path.join(root, entry.source);\n const manifest = await readJson(\n path.join(pluginDir, \".cursor-plugin\", \"plugin.json\"),\n `${pluginName} plugin manifest`,\n issues,\n );\n if (!manifest) {\n continue;\n }\n if (manifest.name !== pluginName) {\n error(\n issues,\n `${pluginName}: marketplace entry name does not match plugin.json name (\"${manifest.name}\").`,\n );\n }\n await validateReferencedManifestPaths(\n pluginDir,\n pluginName,\n manifest,\n [\"logo\", \"commands\", \"agents\", \"skills\", \"rules\", \"hooks\", \"mcpServers\"],\n issues,\n );\n await validateFrontmatter(pluginDir, pluginName, \"cursor\", issues);\n }\n}\n\nasync function validateClaude(\n root: string,\n issues: ValidationIssue[],\n): Promise<void> {\n const marketplacePath = path.join(root, \".claude-plugin\", \"marketplace.json\");\n const marketplace = await readJson(\n marketplacePath,\n \"Marketplace manifest\",\n issues,\n );\n if (!marketplace) {\n return;\n }\n validateMarketplaceBasics(marketplace, issues);\n const plugins = Array.isArray(marketplace.plugins) ? marketplace.plugins : [];\n if (plugins.length === 0) {\n error(issues, 'Marketplace \"plugins\" must be a non-empty array.');\n return;\n }\n for (const [index, entry] of plugins.entries()) {\n const pluginName = validatePluginEntry(entry, index, root, issues);\n if (!pluginName) {\n continue;\n }\n const pluginDir = path.join(root, entry.source);\n const manifest = await readJson(\n path.join(pluginDir, \".claude-plugin\", \"plugin.json\"),\n `${pluginName} plugin manifest`,\n issues,\n );\n if (!manifest) {\n continue;\n }\n if (manifest.name !== pluginName) {\n error(\n issues,\n `${pluginName}: marketplace entry name does not match plugin.json name (\"${manifest.name}\").`,\n );\n }\n for (const field of [\"name\", \"version\", \"description\"]) {\n if (typeof manifest[field] !== \"string\" || !manifest[field]) {\n error(\n issues,\n `${pluginName}: plugin.json is missing required field \"${field}\".`,\n );\n }\n }\n if (\n !manifest.author ||\n typeof manifest.author.name !== \"string\" ||\n !manifest.author.name\n ) {\n error(issues, `${pluginName}: plugin.json is missing \"author.name\".`);\n }\n await validateFrontmatter(pluginDir, pluginName, \"claude\", issues);\n await validateHooks(pluginDir, pluginName, issues);\n }\n}\n\nfunction validateMarketplaceBasics(\n marketplace: Record<string, unknown>,\n issues: ValidationIssue[],\n): void {\n if (\n typeof marketplace.name !== \"string\" ||\n !marketplaceNamePattern.test(marketplace.name)\n ) {\n error(\n issues,\n 'Marketplace \"name\" must be lowercase kebab-case and start/end with an alphanumeric character.',\n );\n }\n const owner = marketplace.owner as Record<string, unknown> | undefined;\n if (owner && (typeof owner.name !== \"string\" || !owner.name)) {\n error(\n issues,\n 'Marketplace \"owner.name\" must be a non-empty string when owner is present.',\n );\n }\n}\n\nfunction validatePluginEntry(\n entry: Record<string, string>,\n index: number,\n root: string,\n issues: ValidationIssue[],\n): string | null {\n if (!entry || typeof entry !== \"object\") {\n error(issues, `plugins[${index}] must be an object.`);\n return null;\n }\n if (typeof entry.name !== \"string\" || !pluginNamePattern.test(entry.name)) {\n error(\n issues,\n `plugins[${index}].name must be lowercase and use only alphanumerics, hyphens, and periods.`,\n );\n return null;\n }\n if (typeof entry.source !== \"string\" || !isSafeRelativePath(entry.source)) {\n error(issues, `plugins[${index}].source must be a safe relative path.`);\n return null;\n }\n const pluginDir = path.join(root, entry.source);\n if (!entry.source.startsWith(\"http\") && !pathExistsSync(pluginDir)) {\n error(\n issues,\n `plugins[${index}].source directory is missing: ${entry.source}`,\n );\n return null;\n }\n return entry.name;\n}\n\nasync function validateReferencedManifestPaths(\n pluginDir: string,\n pluginName: string,\n manifest: Record<string, unknown>,\n fields: string[],\n issues: ValidationIssue[],\n): Promise<void> {\n for (const field of fields) {\n for (const value of extractPathValues(manifest[field])) {\n if (value.startsWith(\"http://\") || value.startsWith(\"https://\")) {\n continue;\n }\n if (!isSafeRelativePath(value)) {\n error(\n issues,\n `${pluginName}: field \"${field}\" has unsafe path \"${value}\".`,\n );\n continue;\n }\n if (!(await exists(path.join(pluginDir, value)))) {\n error(\n issues,\n `${pluginName}: field \"${field}\" references missing path \"${value}\".`,\n );\n }\n }\n }\n}\n\nfunction extractPathValues(value: unknown): string[] {\n if (typeof value === \"string\") {\n return [value];\n }\n if (Array.isArray(value)) {\n return value.flatMap(extractPathValues);\n }\n if (value && typeof value === \"object\") {\n const object = value as Record<string, unknown>;\n return [object.path, object.file].filter(\n (entry): entry is string => typeof entry === \"string\",\n );\n }\n return [];\n}\n\nasync function validateFrontmatter(\n pluginDir: string,\n pluginName: string,\n target: TargetName,\n issues: ValidationIssue[],\n): Promise<void> {\n const files = await walkFiles(pluginDir);\n for (const file of files) {\n const kind = detectFrontmatterKind(file);\n if (!kind) {\n continue;\n }\n const relative = toPosix(path.relative(pluginDir, file));\n const parsed = parseFrontmatter(await fs.readFile(file, \"utf8\"));\n if (!parsed.ok) {\n error(\n issues,\n `${pluginName}: ${kind} frontmatter error in ${relative}: ${parsed.error}`,\n );\n continue;\n }\n if (kind === \"agent\") {\n requireFrontmatter(\n pluginName,\n kind,\n relative,\n parsed.value,\n [\"name\", \"description\"],\n issues,\n );\n } else if (kind === \"command\") {\n requireFrontmatter(\n pluginName,\n kind,\n relative,\n parsed.value,\n [\"description\"],\n issues,\n );\n if (\n target === \"cursor\" ||\n target === \"antigravity\" ||\n target === \"copilot\"\n ) {\n requireFrontmatter(\n pluginName,\n kind,\n relative,\n parsed.value,\n [\"name\"],\n issues,\n );\n }\n } else if (kind === \"skill\") {\n if (target === \"cursor\") {\n requireFrontmatter(\n pluginName,\n kind,\n relative,\n parsed.value,\n [\"name\", \"description\"],\n issues,\n );\n } else if (!parsed.value.description && !parsed.value.when_to_use) {\n error(\n issues,\n `${pluginName}: ${kind} frontmatter error in ${relative}: Missing required \"description\" field.`,\n );\n }\n } else if (kind === \"rule\") {\n requireFrontmatter(\n pluginName,\n kind,\n relative,\n parsed.value,\n [\"description\"],\n issues,\n );\n }\n }\n}\n\nfunction detectFrontmatterKind(\n filePath: string,\n): \"agent\" | \"skill\" | \"command\" | \"rule\" | null {\n const normalized = toPosix(filePath);\n const inSkillContent =\n /\\/skills\\/[^/]+\\//.test(normalized) && !normalized.endsWith(\"/SKILL.md\");\n if (\n normalized.includes(\"/agents/\") &&\n /\\.(md|mdc|markdown)$/.test(normalized) &&\n !inSkillContent\n ) {\n return \"agent\";\n }\n if (normalized.includes(\"/skills/\") && normalized.endsWith(\"/SKILL.md\")) {\n return \"skill\";\n }\n if (\n normalized.includes(\"/commands/\") &&\n /\\.(md|mdc|markdown|txt)$/.test(normalized) &&\n !inSkillContent\n ) {\n return \"command\";\n }\n if (\n normalized.includes(\"/rules/\") &&\n /\\.(md|mdc|markdown)$/.test(normalized) &&\n !inSkillContent\n ) {\n return \"rule\";\n }\n return null;\n}\n\nfunction parseFrontmatter(\n content: string,\n): { ok: true; value: Record<string, unknown> } | { ok: false; error: string } {\n try {\n const parsed = matter(content);\n if (Object.keys(parsed.data).length === 0) {\n return { ok: false, error: \"No frontmatter found\" };\n }\n return { ok: true, value: parsed.data };\n } catch (err) {\n return { ok: false, error: `YAML parse failed: ${(err as Error).message}` };\n }\n}\n\nfunction requireFrontmatter(\n pluginName: string,\n kind: string,\n relative: string,\n frontmatter: Record<string, unknown>,\n fields: string[],\n issues: ValidationIssue[],\n): void {\n for (const field of fields) {\n if (typeof frontmatter[field] !== \"string\" || !frontmatter[field]) {\n error(\n issues,\n `${pluginName}: ${kind} frontmatter error in ${relative}: Missing required \"${field}\" field.`,\n );\n }\n }\n}\n\nasync function validateHooks(\n pluginDir: string,\n pluginName: string,\n issues: ValidationIssue[],\n): Promise<void> {\n const hooksPath = path.join(pluginDir, \"hooks\", \"hooks.json\");\n if (!(await exists(hooksPath))) {\n return;\n }\n const hooks = await readJson(\n hooksPath,\n `${pluginName} hooks/hooks.json`,\n issues,\n );\n if (hooks && (!hooks.hooks || typeof hooks.hooks !== \"object\")) {\n error(\n issues,\n `${pluginName}: hooks/hooks.json must have a \"hooks\" object.`,\n );\n }\n}\n\nasync function readJson(\n filePath: string,\n context: string,\n issues: ValidationIssue[],\n): Promise<Record<string, any> | null> {\n try {\n return JSON.parse(await fs.readFile(filePath, \"utf8\")) as Record<\n string,\n any\n >;\n } catch (err) {\n error(\n issues,\n `${context} is missing or invalid (${filePath}): ${(err as Error).message}`,\n );\n return null;\n }\n}\n\nfunction pathExistsSync(filePath: string): boolean {\n try {\n statSync(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction error(issues: ValidationIssue[], message: string): void {\n issues.push({ level: \"error\", message });\n}\n"],"mappings":"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","names":["fs","path","fs","path","path","fs","error","path","fs","error","path","fs","path","path","artifact","fs","error","path","path","componentDirs","artifact","path","path","artifact","path","fs","path","fs","path","artifact","fs","path","path","fs"]}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/cli.js ADDED
@@ -0,0 +1,414 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ build,
4
+ clean,
5
+ diffTarget,
6
+ loadConfig,
7
+ prune,
8
+ validateOutput
9
+ } from "./chunk-HR2ZVYJA.js";
10
+
11
+ // src/cli.ts
12
+ import { promises as fs, readFileSync } from "fs";
13
+ import path from "path";
14
+ import { Command, Option } from "commander";
15
+ var targets = ["cursor", "claude", "antigravity", "copilot"];
16
+ async function main() {
17
+ const program = createProgram();
18
+ await program.parseAsync(process.argv);
19
+ }
20
+ function createProgram() {
21
+ const program = new Command();
22
+ const pkg = readPackageJson();
23
+ program.name("pluginpack").description(pkg.description).version(pkg.version);
24
+ program.command("init").description(
25
+ "Create a starter pluginpack.config.ts and source plugin layout."
26
+ ).action(init);
27
+ program.command("build").description(
28
+ "Compile configured source plugins into target-native plugin payloads."
29
+ ).usage(
30
+ "[--target cursor|claude|antigravity|copilot] [--out-dir <path>] [--dry-run]"
31
+ ).addOption(
32
+ new Option(
33
+ "--target <target>",
34
+ "Build only one configured target."
35
+ ).choices([...targets])
36
+ ).option(
37
+ "--out-dir <path>",
38
+ "Override the configured output directory for the selected target."
39
+ ).option(
40
+ "--dry-run",
41
+ "Resolve and print planned managed output paths without writing files."
42
+ ).action(
43
+ async (options) => {
44
+ const artifacts = await build({
45
+ target: options.target,
46
+ outDir: options.outDir,
47
+ dryRun: options.dryRun
48
+ });
49
+ for (const artifact of artifacts) {
50
+ console.log(
51
+ `${options.dryRun ? "Would write" : "Wrote"} ${artifact.managedPaths.length} managed files for ${artifact.target} -> ${artifact.outDir}`
52
+ );
53
+ if (options.dryRun) {
54
+ for (const managedPath of artifact.managedPaths) {
55
+ console.log(` ${managedPath}`);
56
+ }
57
+ }
58
+ }
59
+ }
60
+ );
61
+ program.command("validate").description(
62
+ "Validate an existing target output directory for native manifest, path, and frontmatter requirements."
63
+ ).usage("--target cursor|claude|antigravity|copilot [--dir <path>]").requiredOption(
64
+ "--target <target>",
65
+ "Required target validator.",
66
+ parseTarget
67
+ ).option(
68
+ "--dir <path>",
69
+ "Directory to validate. Defaults to the configured target outDir."
70
+ ).action(async (options) => {
71
+ let dir = options.dir;
72
+ if (!dir) {
73
+ const project = await loadConfig();
74
+ const targetConfig = project.config.targets[options.target];
75
+ if (!targetConfig) {
76
+ throw new Error(`Target "${options.target}" is not configured.`);
77
+ }
78
+ dir = targetConfig.outDir;
79
+ }
80
+ const result = await validateOutput(options.target, dir);
81
+ for (const issue of result.issues) {
82
+ const stream = issue.level === "error" ? console.error : console.warn;
83
+ stream(`${issue.level}: ${issue.message}`);
84
+ }
85
+ if (!result.ok) {
86
+ process.exitCode = 1;
87
+ return;
88
+ }
89
+ console.log("Validation passed.");
90
+ });
91
+ program.command("diff").description(
92
+ "Build into a temporary directory and compare generated managed files with an existing target repo."
93
+ ).usage("--target cursor|claude|antigravity|copilot --against <path>").requiredOption(
94
+ "--target <target>",
95
+ "Required target to build and compare.",
96
+ parseTarget
97
+ ).requiredOption(
98
+ "--against <path>",
99
+ "Existing target repo or output directory to compare against."
100
+ ).action(async (options) => {
101
+ const result = await diffTarget({
102
+ target: options.target,
103
+ against: options.against
104
+ });
105
+ if (result.ok) {
106
+ console.log("Managed files match.");
107
+ return;
108
+ }
109
+ console.log("Managed files differ:");
110
+ for (const entry of result.entries) {
111
+ console.log(` ${entry.type.padEnd(7)} ${entry.path}`);
112
+ }
113
+ process.exitCode = 1;
114
+ });
115
+ program.command("prune").description(
116
+ "Remove stale managed files that are no longer emitted by the current config."
117
+ ).usage("[--target cursor|claude|antigravity|copilot] [--dry-run]").addOption(
118
+ new Option(
119
+ "--target <target>",
120
+ "Prune only one configured target."
121
+ ).choices([...targets])
122
+ ).option("--dry-run", "Print stale managed files without deleting them.").option(
123
+ "--force",
124
+ "Delete even paths that resolve inside the source tree or config."
125
+ ).action(
126
+ async (options) => {
127
+ const results = await prune(options);
128
+ printCleanupResults(results, options.dryRun ? "Would prune" : "Pruned");
129
+ }
130
+ );
131
+ program.command("clean").description("Remove all managed files for configured target outputs.").usage("[--target cursor|claude|antigravity|copilot] [--dry-run]").addOption(
132
+ new Option(
133
+ "--target <target>",
134
+ "Clean only one configured target."
135
+ ).choices([...targets])
136
+ ).option("--dry-run", "Print managed files without deleting them.").option(
137
+ "--force",
138
+ "Delete even paths that resolve inside the source tree or config."
139
+ ).action(
140
+ async (options) => {
141
+ const results = await clean(options);
142
+ printCleanupResults(
143
+ results,
144
+ options.dryRun ? "Would clean" : "Cleaned"
145
+ );
146
+ }
147
+ );
148
+ program.command("docs").description(
149
+ "Generate the README CLI reference section from command metadata."
150
+ ).option("--check", "Fail if README.md is not up to date.").action(async (options) => {
151
+ const readmePath = path.resolve("README.md");
152
+ const current = await fs.readFile(readmePath, "utf8");
153
+ const next = replaceGeneratedSection(
154
+ current,
155
+ renderCliReference(program)
156
+ );
157
+ if (options.check) {
158
+ if (next !== current) {
159
+ console.error(
160
+ "README.md CLI reference is out of date. Run pluginpack docs."
161
+ );
162
+ process.exitCode = 1;
163
+ } else {
164
+ console.log("README.md CLI reference is up to date.");
165
+ }
166
+ return;
167
+ }
168
+ await fs.writeFile(readmePath, next);
169
+ console.log("Updated README.md CLI reference.");
170
+ });
171
+ return program;
172
+ }
173
+ function printCleanupResults(results, verb) {
174
+ for (const result of results) {
175
+ console.log(
176
+ `${verb} ${result.entries.length} managed files for ${result.target} -> ${result.outDir}`
177
+ );
178
+ for (const entry of result.entries) {
179
+ console.log(` ${entry.path}`);
180
+ }
181
+ }
182
+ }
183
+ async function init() {
184
+ const configPath = path.resolve("pluginpack.config.ts");
185
+ if (await exists(configPath)) {
186
+ throw new Error("pluginpack.config.ts already exists.");
187
+ }
188
+ await fs.mkdir(path.resolve("plugins", "example", "skills", "example"), {
189
+ recursive: true
190
+ });
191
+ await fs.writeFile(configPath, starterConfig());
192
+ await fs.writeFile(
193
+ path.resolve("plugins", "example", "plugin.pluginpack.json"),
194
+ `${JSON.stringify(
195
+ {
196
+ description: "Example plugin generated by pluginpack init"
197
+ },
198
+ null,
199
+ 2
200
+ )}
201
+ `
202
+ );
203
+ await fs.writeFile(
204
+ path.resolve("plugins", "example", "skills", "example", "SKILL.md"),
205
+ starterSkill()
206
+ );
207
+ console.log("Created pluginpack.config.ts and plugins/example.");
208
+ }
209
+ function parseTarget(value) {
210
+ if (value !== "cursor" && value !== "claude" && value !== "antigravity" && value !== "copilot") {
211
+ throw new Error("Expected cursor, claude, antigravity, or copilot.");
212
+ }
213
+ return value;
214
+ }
215
+ function replaceGeneratedSection(readme, content) {
216
+ const start = "<!-- pluginpack-cli:start -->";
217
+ const end = "<!-- pluginpack-cli:end -->";
218
+ const startIndex = readme.indexOf(start);
219
+ const endIndex = readme.indexOf(end);
220
+ if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
221
+ throw new Error("README.md is missing pluginpack CLI marker comments.");
222
+ }
223
+ return `${readme.slice(0, startIndex + start.length)}
224
+
225
+ ${content}
226
+ ${readme.slice(endIndex)}`;
227
+ }
228
+ function readPackageJson() {
229
+ const packageJson = JSON.parse(
230
+ readFileSync(new URL("../package.json", import.meta.url), "utf8")
231
+ );
232
+ if (typeof packageJson.version !== "string") {
233
+ throw new Error("package.json is missing a string version.");
234
+ }
235
+ if (typeof packageJson.description !== "string") {
236
+ throw new Error("package.json is missing a string description.");
237
+ }
238
+ return { version: packageJson.version, description: packageJson.description };
239
+ }
240
+ function renderCliReference(program) {
241
+ const lines = ["## CLI Reference", ""];
242
+ for (const command of program.commands) {
243
+ if (command.name() === "help") {
244
+ continue;
245
+ }
246
+ lines.push(
247
+ `### \`${command.name()}\``,
248
+ "",
249
+ command.description(),
250
+ "",
251
+ "```bash",
252
+ commandUsage(command),
253
+ "```",
254
+ ""
255
+ );
256
+ const visibleOptions = command.options.filter(
257
+ (option) => option.flags !== "-h, --help"
258
+ );
259
+ if (visibleOptions.length > 0) {
260
+ lines.push("Options:", "");
261
+ for (const option of visibleOptions) {
262
+ lines.push(`- \`${option.flags}\`: ${option.description}`);
263
+ }
264
+ lines.push("");
265
+ }
266
+ const examples = commandExamples(command.name());
267
+ if (examples.length > 0) {
268
+ lines.push("Examples:", "");
269
+ for (const example of examples) {
270
+ lines.push(`- \`${example}\``);
271
+ }
272
+ lines.push("");
273
+ }
274
+ const exitCodes = commandExitCodes(command.name());
275
+ if (exitCodes.length > 0) {
276
+ lines.push("Exit codes:", "");
277
+ for (const exitCode of exitCodes) {
278
+ lines.push(`- ${exitCode}`);
279
+ }
280
+ lines.push("");
281
+ }
282
+ }
283
+ return lines.join("\n").trimEnd();
284
+ }
285
+ function commandUsage(command) {
286
+ const usage = command.usage();
287
+ return usage ? `pluginpack ${command.name()} ${usage}` : `pluginpack ${command.name()}`;
288
+ }
289
+ function commandExamples(commandName) {
290
+ switch (commandName) {
291
+ case "init":
292
+ return ["pluginpack init"];
293
+ case "build":
294
+ return [
295
+ "pluginpack build",
296
+ "pluginpack build --target cursor",
297
+ "pluginpack build --target claude --dry-run"
298
+ ];
299
+ case "validate":
300
+ return ["pluginpack validate --target cursor --dir ../cursor-plugins"];
301
+ case "diff":
302
+ return ["pluginpack diff --target cursor --against ../cursor-plugins"];
303
+ case "prune":
304
+ return ["pluginpack prune", "pluginpack prune --target claude --dry-run"];
305
+ case "clean":
306
+ return ["pluginpack clean", "pluginpack clean --target cursor --dry-run"];
307
+ case "docs":
308
+ return ["pluginpack docs", "pluginpack docs --check"];
309
+ default:
310
+ return [];
311
+ }
312
+ }
313
+ function commandExitCodes(commandName) {
314
+ switch (commandName) {
315
+ case "init":
316
+ return [
317
+ "0 when files are created",
318
+ "1 when files already exist or cannot be written"
319
+ ];
320
+ case "build":
321
+ return [
322
+ "0 when all selected targets build",
323
+ "1 when config, source resolution, or file output fails"
324
+ ];
325
+ case "validate":
326
+ return ["0 when validation passes", "1 when validation finds errors"];
327
+ case "diff":
328
+ return [
329
+ "0 when managed files match",
330
+ "1 when managed files differ or the command fails"
331
+ ];
332
+ case "prune":
333
+ return [
334
+ "0 when stale managed files are removed or listed",
335
+ "1 when config, source resolution, or cleanup fails"
336
+ ];
337
+ case "clean":
338
+ return [
339
+ "0 when managed files are removed or listed",
340
+ "1 when config, manifest loading, or cleanup fails"
341
+ ];
342
+ case "docs":
343
+ return [
344
+ "0 when docs are current or updated",
345
+ "1 when --check finds stale docs"
346
+ ];
347
+ default:
348
+ return [];
349
+ }
350
+ }
351
+ async function exists(filePath) {
352
+ try {
353
+ await fs.access(filePath);
354
+ return true;
355
+ } catch {
356
+ return false;
357
+ }
358
+ }
359
+ function starterConfig() {
360
+ return `import { defineConfig } from "@gleanwork/pluginpack";
361
+
362
+ export default defineConfig({
363
+ name: "example-plugins",
364
+ version: "0.1.0",
365
+ metadata: {
366
+ description: "Example pluginpack plugin marketplace",
367
+ author: { name: "Example" },
368
+ license: "MIT"
369
+ },
370
+ targets: {
371
+ cursor: {
372
+ outDir: "dist/cursor",
373
+ plugins: {
374
+ example: { from: ["example"] }
375
+ }
376
+ },
377
+ claude: {
378
+ outDir: "dist/claude",
379
+ plugins: {
380
+ example: { from: ["example"] }
381
+ }
382
+ },
383
+ antigravity: {
384
+ outDir: "dist/antigravity",
385
+ plugins: {
386
+ example: { from: ["example"] }
387
+ }
388
+ },
389
+ copilot: {
390
+ outDir: "dist/copilot",
391
+ plugins: {
392
+ example: { from: ["example"] }
393
+ }
394
+ }
395
+ }
396
+ });
397
+ `;
398
+ }
399
+ function starterSkill() {
400
+ return `---
401
+ name: example
402
+ description: Example skill generated by pluginpack init.
403
+ ---
404
+
405
+ # Example
406
+
407
+ Use this skill as a starting point.
408
+ `;
409
+ }
410
+ main().catch((error) => {
411
+ console.error(error.message);
412
+ process.exit(1);
413
+ });
414
+ //# sourceMappingURL=cli.js.map