@leeovery/claude-manager 2.0.16 → 2.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,10 +30,10 @@
30
30
 
31
31
  ## About
32
32
 
33
- Claude Manager is an npm package that automatically manages [Claude Code](https://claude.ai/code) skills, commands, agents, and hooks across your projects.
33
+ Claude Manager is an npm package that automatically manages [Claude Code](https://claude.ai/code) skills, commands, agents, hooks, and scripts across your projects.
34
34
 
35
35
  **What it does:**
36
- - Automatically installs skills, commands, agents, and hooks from plugin packages into your project's `.claude/` directory
36
+ - Automatically installs skills, commands, agents, hooks, and scripts from plugin packages into your project's `.claude/` directory
37
37
  - Copies assets so they're committed to your repository and available immediately
38
38
  - Works with any project that has a `package.json` (Node.js, Laravel, Nuxt, etc.)
39
39
  - Provides CLI tools for listing and managing installed plugins
@@ -96,8 +96,10 @@ your-project/
96
96
  │ │ └── artisan-make.md
97
97
  │ ├── agents/
98
98
  │ │ └── code-reviewer.md
99
- └── hooks/
100
- └── pre-commit.sh
99
+ ├── hooks/
100
+ └── pre-commit.sh
101
+ │ └── scripts/
102
+ │ └── build-check.sh
101
103
  ├── node_modules/
102
104
  │ └── @your-org/
103
105
  │ └── claude-your-plugin/
@@ -123,7 +125,7 @@ Want to create your own skill or command packages?
123
125
 
124
126
  1. Have `@leeovery/claude-manager` as a dependency
125
127
  2. Add `postinstall` and `preuninstall` scripts (see example below)
126
- 3. Include asset directories (`skills/`, `commands/`, `agents/`, `hooks/`)
128
+ 3. Include asset directories (`skills/`, `commands/`, `agents/`, `hooks/`, `scripts/`)
127
129
 
128
130
  ### Example package.json
129
131
 
@@ -161,10 +163,12 @@ your-plugin/
161
163
  │ └── agent-one.md
162
164
  ├── hooks/
163
165
  │ └── pre-commit.sh
166
+ ├── scripts/
167
+ │ └── build-check.sh
164
168
  └── package.json
165
169
  ```
166
170
 
167
- The manager auto-discovers `skills/`, `commands/`, `agents/`, and `hooks/` directories—no additional configuration needed.
171
+ The manager auto-discovers `skills/`, `commands/`, `agents/`, `hooks/`, and `scripts/` directories—no additional configuration needed. All asset directories support nested subdirectories.
168
172
 
169
173
  ## Available Plugins
170
174
 
@@ -215,6 +219,7 @@ ls -la .claude/skills/
215
219
  ls -la .claude/commands/
216
220
  ls -la .claude/agents/
217
221
  ls -la .claude/hooks/
222
+ ls -la .claude/scripts/
218
223
  ```
219
224
 
220
225
  ### Plugin not detected
@@ -222,7 +227,7 @@ ls -la .claude/hooks/
222
227
  Verify the plugin's package.json has:
223
228
  - `@leeovery/claude-manager` as a dependency
224
229
  - `postinstall` and `preuninstall` scripts
225
- - A `skills/`, `commands/`, `agents/`, or `hooks/` directory with content
230
+ - A `skills/`, `commands/`, `agents/`, `hooks/`, or `scripts/` directory with content
226
231
 
227
232
  ## Requirements
228
233
 
package/dist/cli.js CHANGED
@@ -74,10 +74,10 @@ function cleanupManifestFiles(projectRoot) {
74
74
  }
75
75
 
76
76
  // src/lib/copier.ts
77
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync, readdirSync, statSync, readFileSync as readFileSync2 } from "fs";
77
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync, readdirSync, readFileSync as readFileSync2 } from "fs";
78
78
  import { createRequire } from "module";
79
79
  import { dirname as dirname2, join as join2, basename } from "path";
80
- var ASSET_DIRS = ["skills", "commands", "agents", "hooks"];
80
+ var ASSET_DIRS = ["skills", "commands", "agents", "hooks", "scripts"];
81
81
  function getPackageVersion(packagePath) {
82
82
  try {
83
83
  const pkgJson = JSON.parse(readFileSync2(join2(packagePath, "package.json"), "utf-8"));
@@ -86,23 +86,9 @@ function getPackageVersion(packagePath) {
86
86
  return "0.0.0";
87
87
  }
88
88
  }
89
- function copyDirectory(src, dest) {
90
- cpSync(src, dest, { recursive: true });
91
- }
92
- function copyFile(src, dest) {
93
- const destDir = join2(dest, "..");
94
- if (!existsSync2(destDir)) {
95
- mkdirSync2(destDir, { recursive: true });
96
- }
97
- cpSync(src, dest);
98
- }
99
- function isSkillDirectory(itemPath) {
100
- return statSync(itemPath).isDirectory();
101
- }
102
- function isAssetFile(itemPath) {
103
- const stat = statSync(itemPath);
89
+ function isValidAsset(itemPath) {
104
90
  const name = basename(itemPath);
105
- return stat.isFile() && name !== ".gitkeep";
91
+ return name !== ".gitkeep";
106
92
  }
107
93
  function copyPluginAssets(packagePath, projectRoot) {
108
94
  const claudeDir = join2(projectRoot, ".claude");
@@ -121,16 +107,9 @@ function copyPluginAssets(packagePath, projectRoot) {
121
107
  if (item === ".gitkeep") continue;
122
108
  const itemPath = join2(sourcePath, item);
123
109
  const targetPath = join2(targetDir, item);
124
- if (assetDir === "skills") {
125
- if (isSkillDirectory(itemPath)) {
126
- copyDirectory(itemPath, targetPath);
127
- copiedFiles.push(`${assetDir}/${item}`);
128
- }
129
- } else {
130
- if (isAssetFile(itemPath)) {
131
- copyFile(itemPath, targetPath);
132
- copiedFiles.push(`${assetDir}/${item}`);
133
- }
110
+ if (isValidAsset(itemPath)) {
111
+ cpSync(itemPath, targetPath, { recursive: true });
112
+ copiedFiles.push(`${assetDir}/${item}`);
134
113
  }
135
114
  }
136
115
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/lib/sync.ts","../src/lib/manifest.ts","../src/lib/copier.ts"],"sourcesContent":["import { program } from 'commander';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport {\n syncPlugins,\n addPluginToProject,\n listPlugins,\n removePluginFromProject,\n} from './lib/sync.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction getVersion(): string {\n try {\n const pkgPath = join(__dirname, '..', 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nfunction findProjectRoot(): string {\n // INIT_CWD is set by npm/pnpm to the directory where the command was run\n // This is critical during postinstall when process.cwd() points to the plugin's directory\n const initCwd = process.env.INIT_CWD;\n if (initCwd && existsSync(join(initCwd, 'package.json'))) {\n return initCwd;\n }\n\n // Fallback: walk up from current directory, skipping node_modules\n let dir = process.cwd();\n\n while (dir !== '/') {\n // Skip node_modules directories - we want the actual project root\n if (!dir.includes('node_modules') && existsSync(join(dir, 'package.json'))) {\n return dir;\n }\n dir = resolve(dir, '..');\n }\n\n return process.cwd();\n}\n\nprogram\n .name('claude-plugins')\n .description('Plugin manager for Claude Code skills and commands')\n .version(getVersion());\n\nprogram\n .command('install')\n .description('Sync all plugins from manifest to .claude directory')\n .option('-f, --force', 'Force sync even if versions match')\n .action((options: { force?: boolean }) => {\n const projectRoot = findProjectRoot();\n const result = syncPlugins(projectRoot, options);\n\n if (!result.synced) {\n console.log(result.reason || 'Nothing to sync.');\n return;\n }\n\n if (options.force) {\n console.log('Syncing Claude plugins (forced)...');\n }\n\n for (const plugin of result.installedPlugins) {\n console.log(` Installed ${plugin.name}@${plugin.version} (${plugin.fileCount} files)`);\n }\n\n if (result.removedPlugins.length > 0) {\n console.log(`\\nRemoved ${result.removedPlugins.length} uninstalled plugin(s) from manifest:`);\n for (const name of result.removedPlugins) {\n console.log(` - ${name}`);\n }\n }\n\n if (result.conflicts.length > 0) {\n console.log(`\\nWarning: ${result.conflicts.length} file conflict(s) detected (later plugin overwrote earlier):`);\n for (const conflict of result.conflicts) {\n console.log(` ${conflict}`);\n }\n }\n\n console.log(`\\nDone. ${result.totalFiles} files from ${result.pluginCount} plugin(s).`);\n });\n\nprogram\n .command('add')\n .description('Add and install a plugin (called from plugin postinstall)')\n .argument('[package]', 'Package name (auto-detected if run from postinstall)')\n .action((packageArg?: string) => {\n const projectRoot = findProjectRoot();\n const packageName = packageArg || process.env.npm_package_name;\n\n if (!packageName) {\n console.error('Error: Could not determine package name.');\n console.error('Please provide the package name as an argument: claude-plugins add <package>');\n process.exit(1);\n }\n\n const result = addPluginToProject(projectRoot, packageName);\n\n if (!result.success) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n if (result.files.length === 0) {\n console.log(`Package ${packageName} has no Claude assets to install.`);\n return;\n }\n\n console.log(`Installed ${packageName}@${result.version}:`);\n for (const file of result.files) {\n console.log(` .claude/${file}`);\n }\n });\n\nprogram\n .command('list')\n .description('List installed plugins and their assets')\n .action(() => {\n const projectRoot = findProjectRoot();\n const result = listPlugins(projectRoot);\n const pluginNames = Object.keys(result.plugins);\n\n if (pluginNames.length === 0) {\n console.log('No plugins installed.');\n return;\n }\n\n console.log('Installed Claude plugins:\\n');\n\n for (const [packageName, entry] of Object.entries(result.plugins)) {\n console.log(`${packageName}@${entry.version}`);\n for (const file of entry.files) {\n console.log(` .claude/${file}`);\n }\n console.log();\n }\n });\n\nprogram\n .command('remove')\n .description('Remove a plugin and its assets (called from plugin preuninstall)')\n .argument('[package]', 'Package name (auto-detected if run from preuninstall)')\n .action((packageArg?: string) => {\n const projectRoot = findProjectRoot();\n const packageName = packageArg || process.env.npm_package_name;\n\n if (!packageName) {\n console.error('Error: Could not determine package name.');\n console.error('Please provide the package name as an argument: claude-plugins remove <package>');\n process.exit(1);\n }\n\n const result = removePluginFromProject(projectRoot, packageName);\n\n if (!result.success) {\n console.error(result.error);\n process.exit(1);\n }\n\n for (const file of result.filesRemoved) {\n console.log(`Removed .claude/${file}`);\n }\n\n console.log(`Removed ${packageName}`);\n });\n\nprogram.parse();\n","import { existsSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport {\n readManifest,\n writeManifest,\n cleanupManifestFiles,\n addPlugin,\n removePlugin,\n type PluginEntry,\n} from './manifest.js';\nimport {\n copyPluginAssets,\n findPluginInNodeModules,\n hasAssets,\n getPackageVersion,\n} from './copier.js';\n\nexport interface SyncResult {\n success: boolean;\n synced: boolean;\n reason?: string;\n totalFiles: number;\n pluginCount: number;\n removedPlugins: string[];\n conflicts: string[];\n installedPlugins: Array<{ name: string; version: string; fileCount: number }>;\n}\n\nexport interface AddResult {\n success: boolean;\n alreadyExists: boolean;\n packageName: string;\n version?: string;\n files: string[];\n error?: string;\n}\n\nexport interface ListResult {\n plugins: Record<string, PluginEntry>;\n}\n\nexport interface RemoveResult {\n success: boolean;\n packageName: string;\n filesRemoved: string[];\n error?: string;\n}\n\nexport function syncPlugins(\n projectRoot: string,\n options: { force?: boolean } = {}\n): SyncResult {\n const manifest = readManifest(projectRoot);\n const pluginCount = Object.keys(manifest.plugins).length;\n\n if (pluginCount === 0) {\n return {\n success: true,\n synced: false,\n reason: 'No plugins to sync',\n totalFiles: 0,\n pluginCount: 0,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n\n // Check if any plugins have changed (unless --force)\n if (!options.force) {\n let needsSync = false;\n let reason = '';\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n needsSync = true;\n reason = `${packageName} was uninstalled`;\n break;\n }\n\n const currentVersion = getPackageVersion(packagePath);\n if (currentVersion !== entry.version) {\n needsSync = true;\n reason = `${packageName} changed (${entry.version} → ${currentVersion})`;\n break;\n }\n }\n\n if (!needsSync) {\n return {\n success: true,\n synced: false,\n reason: 'All plugins up to date',\n totalFiles: 0,\n pluginCount,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n }\n\n // Clean up existing files from manifest\n cleanupManifestFiles(projectRoot);\n\n // Re-copy all plugins from manifest\n const newManifest = { plugins: {} as Record<string, PluginEntry> };\n const fileOwnership = new Map<string, string>();\n const conflicts: string[] = [];\n const removedPlugins: string[] = [];\n const installedPlugins: Array<{ name: string; version: string; fileCount: number }> = [];\n let totalFiles = 0;\n\n for (const [packageName] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n removedPlugins.push(packageName);\n continue;\n }\n\n if (!hasAssets(packagePath)) {\n continue;\n }\n\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n // Check for conflicts\n for (const file of result.files) {\n const existingOwner = fileOwnership.get(file);\n if (existingOwner) {\n conflicts.push(`${file} (${existingOwner} vs ${packageName})`);\n }\n fileOwnership.set(file, packageName);\n }\n\n newManifest.plugins[packageName] = {\n version: result.version,\n files: result.files,\n };\n totalFiles += result.files.length;\n installedPlugins.push({\n name: packageName,\n version: result.version,\n fileCount: result.files.length,\n });\n }\n }\n\n writeManifest(projectRoot, newManifest);\n\n return {\n success: true,\n synced: true,\n totalFiles,\n pluginCount: Object.keys(newManifest.plugins).length,\n removedPlugins,\n conflicts,\n installedPlugins,\n };\n}\n\nexport function addPluginToProject(\n projectRoot: string,\n packageName: string\n): AddResult {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n return {\n success: false,\n alreadyExists: false,\n packageName,\n files: [],\n error: `Package ${packageName} not found in node_modules`,\n };\n }\n\n if (!hasAssets(packagePath)) {\n return {\n success: true,\n alreadyExists: false,\n packageName,\n files: [],\n };\n }\n\n // Clean up any existing files for this plugin\n const manifest = readManifest(projectRoot);\n const existing = manifest.plugins[packageName];\n\n if (existing) {\n const claudeDir = join(projectRoot, '.claude');\n for (const file of existing.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n }\n }\n }\n\n // Copy assets\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n addPlugin(projectRoot, packageName, result.version, result.files);\n }\n\n return {\n success: true,\n alreadyExists: !!existing,\n packageName,\n version: result.version,\n files: result.files,\n };\n}\n\nexport function listPlugins(projectRoot: string): ListResult {\n const manifest = readManifest(projectRoot);\n return { plugins: manifest.plugins };\n}\n\nexport function removePluginFromProject(\n projectRoot: string,\n packageName: string\n): RemoveResult {\n const manifest = readManifest(projectRoot);\n const entry = manifest.plugins[packageName];\n\n if (!entry) {\n return {\n success: false,\n packageName,\n filesRemoved: [],\n error: `Plugin ${packageName} is not installed`,\n };\n }\n\n const claudeDir = join(projectRoot, '.claude');\n const filesRemoved: string[] = [];\n\n // Remove files\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n filesRemoved.push(file);\n }\n }\n\n // Update manifest (will delete manifest file if no plugins left)\n removePlugin(projectRoot, packageName);\n\n return {\n success: true,\n packageName,\n filesRemoved,\n };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst MANIFEST_FILE = '.plugins-manifest.json';\n\nexport interface PluginEntry {\n version: string;\n files: string[];\n}\n\nexport interface Manifest {\n plugins: Record<string, PluginEntry>;\n}\n\nfunction getManifestPath(projectRoot: string): string {\n return join(projectRoot, '.claude', MANIFEST_FILE);\n}\n\nexport function readManifest(projectRoot: string): Manifest {\n const manifestPath = getManifestPath(projectRoot);\n\n if (!existsSync(manifestPath)) {\n return { plugins: {} };\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8');\n return JSON.parse(content) as Manifest;\n } catch {\n return { plugins: {} };\n }\n}\n\nexport function writeManifest(projectRoot: string, manifest: Manifest): void {\n const manifestPath = getManifestPath(projectRoot);\n const claudeDir = dirname(manifestPath);\n\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n}\n\nexport function addPlugin(\n projectRoot: string,\n packageName: string,\n version: string,\n files: string[]\n): void {\n const manifest = readManifest(projectRoot);\n\n manifest.plugins[packageName] = {\n version,\n files,\n };\n\n writeManifest(projectRoot, manifest);\n}\n\nexport function removePlugin(projectRoot: string, packageName: string): void {\n const manifest = readManifest(projectRoot);\n\n delete manifest.plugins[packageName];\n\n // Delete manifest if no plugins left, otherwise update it\n if (Object.keys(manifest.plugins).length === 0) {\n const manifestPath = join(projectRoot, '.claude', MANIFEST_FILE);\n if (existsSync(manifestPath)) {\n rmSync(manifestPath);\n }\n } else {\n writeManifest(projectRoot, manifest);\n }\n}\n\nexport function getPlugins(projectRoot: string): Record<string, PluginEntry> {\n return readManifest(projectRoot).plugins;\n}\n\nexport function cleanupManifestFiles(projectRoot: string): string[] {\n const manifest = readManifest(projectRoot);\n const claudeDir = join(projectRoot, '.claude');\n const removedFiles: string[] = [];\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n removedFiles.push(file);\n }\n }\n }\n\n return removedFiles;\n}\n","import { existsSync, mkdirSync, cpSync, readdirSync, statSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, basename } from 'node:path';\n\nconst ASSET_DIRS = ['skills', 'commands', 'agents', 'hooks'] as const;\ntype AssetDir = typeof ASSET_DIRS[number];\n\ninterface CopyResult {\n files: string[];\n version: string;\n}\n\nexport function getPackageVersion(packagePath: string): string {\n try {\n const pkgJson = JSON.parse(readFileSync(join(packagePath, 'package.json'), 'utf-8'));\n return pkgJson.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nfunction copyDirectory(src: string, dest: string): void {\n cpSync(src, dest, { recursive: true });\n}\n\nfunction copyFile(src: string, dest: string): void {\n const destDir = join(dest, '..');\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n cpSync(src, dest);\n}\n\nfunction isSkillDirectory(itemPath: string): boolean {\n return statSync(itemPath).isDirectory();\n}\n\nfunction isAssetFile(itemPath: string): boolean {\n const stat = statSync(itemPath);\n const name = basename(itemPath);\n return stat.isFile() && name !== '.gitkeep';\n}\n\nexport function copyPluginAssets(\n packagePath: string,\n projectRoot: string\n): CopyResult {\n const claudeDir = join(projectRoot, '.claude');\n const copiedFiles: string[] = [];\n\n for (const assetDir of ASSET_DIRS) {\n const sourcePath = join(packagePath, assetDir);\n\n if (!existsSync(sourcePath)) {\n continue;\n }\n\n const targetDir = join(claudeDir, assetDir);\n\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n }\n\n const items = readdirSync(sourcePath);\n\n for (const item of items) {\n if (item === '.gitkeep') continue;\n\n const itemPath = join(sourcePath, item);\n const targetPath = join(targetDir, item);\n\n if (assetDir === 'skills') {\n // Skills are directories\n if (isSkillDirectory(itemPath)) {\n copyDirectory(itemPath, targetPath);\n copiedFiles.push(`${assetDir}/${item}`);\n }\n } else {\n // Commands, agents, hooks are files\n if (isAssetFile(itemPath)) {\n copyFile(itemPath, targetPath);\n copiedFiles.push(`${assetDir}/${item}`);\n }\n }\n }\n }\n\n return {\n files: copiedFiles,\n version: getPackageVersion(packagePath),\n };\n}\n\nexport function findPluginInNodeModules(\n packageName: string,\n projectRoot: string\n): string | null {\n // Standard node_modules path (npm, pnpm, yarn classic, bun)\n const standardPath = join(projectRoot, 'node_modules', packageName);\n if (existsSync(standardPath)) {\n return standardPath;\n }\n\n // Fallback: use Node's require.resolve for yarn PnP and other setups\n try {\n const require = createRequire(join(projectRoot, 'package.json'));\n const resolved = require.resolve(`${packageName}/package.json`);\n return dirname(resolved);\n } catch {\n return null;\n }\n}\n\nexport function hasAssets(packagePath: string): boolean {\n for (const assetDir of ASSET_DIRS) {\n const dirPath = join(packagePath, assetDir);\n if (existsSync(dirPath)) {\n const items = readdirSync(dirPath).filter(f => f !== '.gitkeep');\n if (items.length > 0) {\n return true;\n }\n }\n }\n return false;\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,SAAS,cAAAA,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,WAAAC,UAAS,QAAAC,OAAM,eAAe;AACvC,SAAS,qBAAqB;;;ACH9B,SAAS,cAAAC,aAAY,UAAAC,eAAc;AACnC,SAAS,QAAAC,aAAY;;;ACDrB,SAAS,YAAY,WAAW,cAAc,eAAe,cAAc;AAC3E,SAAS,SAAS,YAAY;AAE9B,IAAM,gBAAgB;AAWtB,SAAS,gBAAgB,aAA6B;AACpD,SAAO,KAAK,aAAa,WAAW,aAAa;AACnD;AAEO,SAAS,aAAa,aAA+B;AAC1D,QAAM,eAAe,gBAAgB,WAAW;AAEhD,MAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,cAAc,OAAO;AAClD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACF;AAEO,SAAS,cAAc,aAAqB,UAA0B;AAC3E,QAAM,eAAe,gBAAgB,WAAW;AAChD,QAAM,YAAY,QAAQ,YAAY;AAEtC,MAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AAEA,gBAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACtE;AAEO,SAAS,UACd,aACA,aACA,SACA,OACM;AACN,QAAM,WAAW,aAAa,WAAW;AAEzC,WAAS,QAAQ,WAAW,IAAI;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,gBAAc,aAAa,QAAQ;AACrC;AAEO,SAAS,aAAa,aAAqB,aAA2B;AAC3E,QAAM,WAAW,aAAa,WAAW;AAEzC,SAAO,SAAS,QAAQ,WAAW;AAGnC,MAAI,OAAO,KAAK,SAAS,OAAO,EAAE,WAAW,GAAG;AAC9C,UAAM,eAAe,KAAK,aAAa,WAAW,aAAa;AAC/D,QAAI,WAAW,YAAY,GAAG;AAC5B,aAAO,YAAY;AAAA,IACrB;AAAA,EACF,OAAO;AACL,kBAAc,aAAa,QAAQ;AAAA,EACrC;AACF;AAMO,SAAS,qBAAqB,aAA+B;AAClE,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,YAAY,KAAK,aAAa,SAAS;AAC7C,QAAM,eAAyB,CAAC;AAEhC,aAAW,CAAC,aAAa,KAAK,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AACnE,eAAW,QAAQ,MAAM,OAAO;AAC9B,YAAM,WAAW,KAAK,WAAW,IAAI;AACrC,UAAI,WAAW,QAAQ,GAAG;AACxB,eAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjD,qBAAa,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AChGA,SAAS,cAAAC,aAAY,aAAAC,YAAW,QAAQ,aAAa,UAAU,gBAAAC,qBAAoB;AACnF,SAAS,qBAAqB;AAC9B,SAAS,WAAAC,UAAS,QAAAC,OAAM,gBAAgB;AAExC,IAAM,aAAa,CAAC,UAAU,YAAY,UAAU,OAAO;AAQpD,SAAS,kBAAkB,aAA6B;AAC7D,MAAI;AACF,UAAM,UAAU,KAAK,MAAMF,cAAaE,MAAK,aAAa,cAAc,GAAG,OAAO,CAAC;AACnF,WAAO,QAAQ,WAAW;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,KAAa,MAAoB;AACtD,SAAO,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC;AACvC;AAEA,SAAS,SAAS,KAAa,MAAoB;AACjD,QAAM,UAAUA,MAAK,MAAM,IAAI;AAC/B,MAAI,CAACJ,YAAW,OAAO,GAAG;AACxB,IAAAC,WAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,EACxC;AACA,SAAO,KAAK,IAAI;AAClB;AAEA,SAAS,iBAAiB,UAA2B;AACnD,SAAO,SAAS,QAAQ,EAAE,YAAY;AACxC;AAEA,SAAS,YAAY,UAA2B;AAC9C,QAAM,OAAO,SAAS,QAAQ;AAC9B,QAAM,OAAO,SAAS,QAAQ;AAC9B,SAAO,KAAK,OAAO,KAAK,SAAS;AACnC;AAEO,SAAS,iBACd,aACA,aACY;AACZ,QAAM,YAAYG,MAAK,aAAa,SAAS;AAC7C,QAAM,cAAwB,CAAC;AAE/B,aAAW,YAAY,YAAY;AACjC,UAAM,aAAaA,MAAK,aAAa,QAAQ;AAE7C,QAAI,CAACJ,YAAW,UAAU,GAAG;AAC3B;AAAA,IACF;AAEA,UAAM,YAAYI,MAAK,WAAW,QAAQ;AAE1C,QAAI,CAACJ,YAAW,SAAS,GAAG;AAC1B,MAAAC,WAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AAEA,UAAM,QAAQ,YAAY,UAAU;AAEpC,eAAW,QAAQ,OAAO;AACxB,UAAI,SAAS,WAAY;AAEzB,YAAM,WAAWG,MAAK,YAAY,IAAI;AACtC,YAAM,aAAaA,MAAK,WAAW,IAAI;AAEvC,UAAI,aAAa,UAAU;AAEzB,YAAI,iBAAiB,QAAQ,GAAG;AAC9B,wBAAc,UAAU,UAAU;AAClC,sBAAY,KAAK,GAAG,QAAQ,IAAI,IAAI,EAAE;AAAA,QACxC;AAAA,MACF,OAAO;AAEL,YAAI,YAAY,QAAQ,GAAG;AACzB,mBAAS,UAAU,UAAU;AAC7B,sBAAY,KAAK,GAAG,QAAQ,IAAI,IAAI,EAAE;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS,kBAAkB,WAAW;AAAA,EACxC;AACF;AAEO,SAAS,wBACd,aACA,aACe;AAEf,QAAM,eAAeA,MAAK,aAAa,gBAAgB,WAAW;AAClE,MAAIJ,YAAW,YAAY,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAMK,WAAU,cAAcD,MAAK,aAAa,cAAc,CAAC;AAC/D,UAAM,WAAWC,SAAQ,QAAQ,GAAG,WAAW,eAAe;AAC9D,WAAOF,SAAQ,QAAQ;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,UAAU,aAA8B;AACtD,aAAW,YAAY,YAAY;AACjC,UAAM,UAAUC,MAAK,aAAa,QAAQ;AAC1C,QAAIJ,YAAW,OAAO,GAAG;AACvB,YAAM,QAAQ,YAAY,OAAO,EAAE,OAAO,OAAK,MAAM,UAAU;AAC/D,UAAI,MAAM,SAAS,GAAG;AACpB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AF3EO,SAAS,YACd,aACA,UAA+B,CAAC,GACpB;AACZ,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,cAAc,OAAO,KAAK,SAAS,OAAO,EAAE;AAElD,MAAI,gBAAgB,GAAG;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,gBAAgB,CAAC;AAAA,MACjB,WAAW,CAAC;AAAA,MACZ,kBAAkB,CAAC;AAAA,IACrB;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,OAAO;AAClB,QAAI,YAAY;AAChB,QAAI,SAAS;AAEb,eAAW,CAAC,aAAa,KAAK,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AACnE,YAAM,cAAc,wBAAwB,aAAa,WAAW;AAEpE,UAAI,CAAC,aAAa;AAChB,oBAAY;AACZ,iBAAS,GAAG,WAAW;AACvB;AAAA,MACF;AAEA,YAAM,iBAAiB,kBAAkB,WAAW;AACpD,UAAI,mBAAmB,MAAM,SAAS;AACpC,oBAAY;AACZ,iBAAS,GAAG,WAAW,aAAa,MAAM,OAAO,WAAM,cAAc;AACrE;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC;AAAA,QACjB,WAAW,CAAC;AAAA,QACZ,kBAAkB,CAAC;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAGA,uBAAqB,WAAW;AAGhC,QAAM,cAAc,EAAE,SAAS,CAAC,EAAiC;AACjE,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,QAAM,YAAsB,CAAC;AAC7B,QAAM,iBAA2B,CAAC;AAClC,QAAM,mBAAgF,CAAC;AACvF,MAAI,aAAa;AAEjB,aAAW,CAAC,WAAW,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AAC5D,UAAM,cAAc,wBAAwB,aAAa,WAAW;AAEpE,QAAI,CAAC,aAAa;AAChB,qBAAe,KAAK,WAAW;AAC/B;AAAA,IACF;AAEA,QAAI,CAAC,UAAU,WAAW,GAAG;AAC3B;AAAA,IACF;AAEA,UAAM,SAAS,iBAAiB,aAAa,WAAW;AAExD,QAAI,OAAO,MAAM,SAAS,GAAG;AAE3B,iBAAW,QAAQ,OAAO,OAAO;AAC/B,cAAM,gBAAgB,cAAc,IAAI,IAAI;AAC5C,YAAI,eAAe;AACjB,oBAAU,KAAK,GAAG,IAAI,KAAK,aAAa,OAAO,WAAW,GAAG;AAAA,QAC/D;AACA,sBAAc,IAAI,MAAM,WAAW;AAAA,MACrC;AAEA,kBAAY,QAAQ,WAAW,IAAI;AAAA,QACjC,SAAS,OAAO;AAAA,QAChB,OAAO,OAAO;AAAA,MAChB;AACA,oBAAc,OAAO,MAAM;AAC3B,uBAAiB,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,OAAO;AAAA,QAChB,WAAW,OAAO,MAAM;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,gBAAc,aAAa,WAAW;AAEtC,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR;AAAA,IACA,aAAa,OAAO,KAAK,YAAY,OAAO,EAAE;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,mBACd,aACA,aACW;AACX,QAAM,cAAc,wBAAwB,aAAa,WAAW;AAEpE,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,MACA,OAAO,CAAC;AAAA,MACR,OAAO,WAAW,WAAW;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,CAAC,UAAU,WAAW,GAAG;AAC3B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAGA,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,WAAW,SAAS,QAAQ,WAAW;AAE7C,MAAI,UAAU;AACZ,UAAM,YAAYM,MAAK,aAAa,SAAS;AAC7C,eAAW,QAAQ,SAAS,OAAO;AACjC,YAAM,WAAWA,MAAK,WAAW,IAAI;AACrC,UAAIC,YAAW,QAAQ,GAAG;AACxB,QAAAC,QAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAS,iBAAiB,aAAa,WAAW;AAExD,MAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,cAAU,aAAa,aAAa,OAAO,SAAS,OAAO,KAAK;AAAA,EAClE;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe,CAAC,CAAC;AAAA,IACjB;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,OAAO,OAAO;AAAA,EAChB;AACF;AAEO,SAAS,YAAY,aAAiC;AAC3D,QAAM,WAAW,aAAa,WAAW;AACzC,SAAO,EAAE,SAAS,SAAS,QAAQ;AACrC;AAEO,SAAS,wBACd,aACA,aACc;AACd,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,QAAQ,SAAS,QAAQ,WAAW;AAE1C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,cAAc,CAAC;AAAA,MACf,OAAO,UAAU,WAAW;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,YAAYF,MAAK,aAAa,SAAS;AAC7C,QAAM,eAAyB,CAAC;AAGhC,aAAW,QAAQ,MAAM,OAAO;AAC9B,UAAM,WAAWA,MAAK,WAAW,IAAI;AACrC,QAAIC,YAAW,QAAQ,GAAG;AACxB,MAAAC,QAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjD,mBAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAGA,eAAa,aAAa,WAAW;AAErC,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;;;AD1PA,IAAM,YAAYC,SAAQ,cAAc,YAAY,GAAG,CAAC;AAExD,SAAS,aAAqB;AAC5B,MAAI;AACF,UAAM,UAAUC,MAAK,WAAW,MAAM,cAAc;AACpD,UAAM,MAAM,KAAK,MAAMC,cAAa,SAAS,OAAO,CAAC;AACrD,WAAO,IAAI,WAAW;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,kBAA0B;AAGjC,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAWC,YAAWF,MAAK,SAAS,cAAc,CAAC,GAAG;AACxD,WAAO;AAAA,EACT;AAGA,MAAI,MAAM,QAAQ,IAAI;AAEtB,SAAO,QAAQ,KAAK;AAElB,QAAI,CAAC,IAAI,SAAS,cAAc,KAAKE,YAAWF,MAAK,KAAK,cAAc,CAAC,GAAG;AAC1E,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,KAAK,IAAI;AAAA,EACzB;AAEA,SAAO,QAAQ,IAAI;AACrB;AAEA,QACG,KAAK,gBAAgB,EACrB,YAAY,oDAAoD,EAChE,QAAQ,WAAW,CAAC;AAEvB,QACG,QAAQ,SAAS,EACjB,YAAY,qDAAqD,EACjE,OAAO,eAAe,mCAAmC,EACzD,OAAO,CAAC,YAAiC;AACxC,QAAM,cAAc,gBAAgB;AACpC,QAAM,SAAS,YAAY,aAAa,OAAO;AAE/C,MAAI,CAAC,OAAO,QAAQ;AAClB,YAAQ,IAAI,OAAO,UAAU,kBAAkB;AAC/C;AAAA,EACF;AAEA,MAAI,QAAQ,OAAO;AACjB,YAAQ,IAAI,oCAAoC;AAAA,EAClD;AAEA,aAAW,UAAU,OAAO,kBAAkB;AAC5C,YAAQ,IAAI,eAAe,OAAO,IAAI,IAAI,OAAO,OAAO,KAAK,OAAO,SAAS,SAAS;AAAA,EACxF;AAEA,MAAI,OAAO,eAAe,SAAS,GAAG;AACpC,YAAQ,IAAI;AAAA,UAAa,OAAO,eAAe,MAAM,uCAAuC;AAC5F,eAAW,QAAQ,OAAO,gBAAgB;AACxC,cAAQ,IAAI,OAAO,IAAI,EAAE;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,OAAO,UAAU,SAAS,GAAG;AAC/B,YAAQ,IAAI;AAAA,WAAc,OAAO,UAAU,MAAM,8DAA8D;AAC/G,eAAW,YAAY,OAAO,WAAW;AACvC,cAAQ,IAAI,KAAK,QAAQ,EAAE;AAAA,IAC7B;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,QAAW,OAAO,UAAU,eAAe,OAAO,WAAW,aAAa;AACxF,CAAC;AAEH,QACG,QAAQ,KAAK,EACb,YAAY,2DAA2D,EACvE,SAAS,aAAa,sDAAsD,EAC5E,OAAO,CAAC,eAAwB;AAC/B,QAAM,cAAc,gBAAgB;AACpC,QAAM,cAAc,cAAc,QAAQ,IAAI;AAE9C,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,0CAA0C;AACxD,YAAQ,MAAM,8EAA8E;AAC5F,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,mBAAmB,aAAa,WAAW;AAE1D,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AACtC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,OAAO,MAAM,WAAW,GAAG;AAC7B,YAAQ,IAAI,WAAW,WAAW,mCAAmC;AACrE;AAAA,EACF;AAEA,UAAQ,IAAI,aAAa,WAAW,IAAI,OAAO,OAAO,GAAG;AACzD,aAAW,QAAQ,OAAO,OAAO;AAC/B,YAAQ,IAAI,aAAa,IAAI,EAAE;AAAA,EACjC;AACF,CAAC;AAEH,QACG,QAAQ,MAAM,EACd,YAAY,yCAAyC,EACrD,OAAO,MAAM;AACZ,QAAM,cAAc,gBAAgB;AACpC,QAAM,SAAS,YAAY,WAAW;AACtC,QAAM,cAAc,OAAO,KAAK,OAAO,OAAO;AAE9C,MAAI,YAAY,WAAW,GAAG;AAC5B,YAAQ,IAAI,uBAAuB;AACnC;AAAA,EACF;AAEA,UAAQ,IAAI,6BAA6B;AAEzC,aAAW,CAAC,aAAa,KAAK,KAAK,OAAO,QAAQ,OAAO,OAAO,GAAG;AACjE,YAAQ,IAAI,GAAG,WAAW,IAAI,MAAM,OAAO,EAAE;AAC7C,eAAW,QAAQ,MAAM,OAAO;AAC9B,cAAQ,IAAI,aAAa,IAAI,EAAE;AAAA,IACjC;AACA,YAAQ,IAAI;AAAA,EACd;AACF,CAAC;AAEH,QACG,QAAQ,QAAQ,EAChB,YAAY,kEAAkE,EAC9E,SAAS,aAAa,uDAAuD,EAC7E,OAAO,CAAC,eAAwB;AAC/B,QAAM,cAAc,gBAAgB;AACpC,QAAM,cAAc,cAAc,QAAQ,IAAI;AAE9C,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,0CAA0C;AACxD,YAAQ,MAAM,iFAAiF;AAC/F,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,SAAS,wBAAwB,aAAa,WAAW;AAE/D,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,MAAM,OAAO,KAAK;AAC1B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,aAAW,QAAQ,OAAO,cAAc;AACtC,YAAQ,IAAI,mBAAmB,IAAI,EAAE;AAAA,EACvC;AAEA,UAAQ,IAAI,WAAW,WAAW,EAAE;AACtC,CAAC;AAEH,QAAQ,MAAM;","names":["existsSync","readFileSync","dirname","join","existsSync","rmSync","join","existsSync","mkdirSync","readFileSync","dirname","join","require","join","existsSync","rmSync","dirname","join","readFileSync","existsSync"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/lib/sync.ts","../src/lib/manifest.ts","../src/lib/copier.ts"],"sourcesContent":["import { program } from 'commander';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport {\n syncPlugins,\n addPluginToProject,\n listPlugins,\n removePluginFromProject,\n} from './lib/sync.js';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction getVersion(): string {\n try {\n const pkgPath = join(__dirname, '..', 'package.json');\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nfunction findProjectRoot(): string {\n // INIT_CWD is set by npm/pnpm to the directory where the command was run\n // This is critical during postinstall when process.cwd() points to the plugin's directory\n const initCwd = process.env.INIT_CWD;\n if (initCwd && existsSync(join(initCwd, 'package.json'))) {\n return initCwd;\n }\n\n // Fallback: walk up from current directory, skipping node_modules\n let dir = process.cwd();\n\n while (dir !== '/') {\n // Skip node_modules directories - we want the actual project root\n if (!dir.includes('node_modules') && existsSync(join(dir, 'package.json'))) {\n return dir;\n }\n dir = resolve(dir, '..');\n }\n\n return process.cwd();\n}\n\nprogram\n .name('claude-plugins')\n .description('Plugin manager for Claude Code skills and commands')\n .version(getVersion());\n\nprogram\n .command('install')\n .description('Sync all plugins from manifest to .claude directory')\n .option('-f, --force', 'Force sync even if versions match')\n .action((options: { force?: boolean }) => {\n const projectRoot = findProjectRoot();\n const result = syncPlugins(projectRoot, options);\n\n if (!result.synced) {\n console.log(result.reason || 'Nothing to sync.');\n return;\n }\n\n if (options.force) {\n console.log('Syncing Claude plugins (forced)...');\n }\n\n for (const plugin of result.installedPlugins) {\n console.log(` Installed ${plugin.name}@${plugin.version} (${plugin.fileCount} files)`);\n }\n\n if (result.removedPlugins.length > 0) {\n console.log(`\\nRemoved ${result.removedPlugins.length} uninstalled plugin(s) from manifest:`);\n for (const name of result.removedPlugins) {\n console.log(` - ${name}`);\n }\n }\n\n if (result.conflicts.length > 0) {\n console.log(`\\nWarning: ${result.conflicts.length} file conflict(s) detected (later plugin overwrote earlier):`);\n for (const conflict of result.conflicts) {\n console.log(` ${conflict}`);\n }\n }\n\n console.log(`\\nDone. ${result.totalFiles} files from ${result.pluginCount} plugin(s).`);\n });\n\nprogram\n .command('add')\n .description('Add and install a plugin (called from plugin postinstall)')\n .argument('[package]', 'Package name (auto-detected if run from postinstall)')\n .action((packageArg?: string) => {\n const projectRoot = findProjectRoot();\n const packageName = packageArg || process.env.npm_package_name;\n\n if (!packageName) {\n console.error('Error: Could not determine package name.');\n console.error('Please provide the package name as an argument: claude-plugins add <package>');\n process.exit(1);\n }\n\n const result = addPluginToProject(projectRoot, packageName);\n\n if (!result.success) {\n console.error(`Error: ${result.error}`);\n process.exit(1);\n }\n\n if (result.files.length === 0) {\n console.log(`Package ${packageName} has no Claude assets to install.`);\n return;\n }\n\n console.log(`Installed ${packageName}@${result.version}:`);\n for (const file of result.files) {\n console.log(` .claude/${file}`);\n }\n });\n\nprogram\n .command('list')\n .description('List installed plugins and their assets')\n .action(() => {\n const projectRoot = findProjectRoot();\n const result = listPlugins(projectRoot);\n const pluginNames = Object.keys(result.plugins);\n\n if (pluginNames.length === 0) {\n console.log('No plugins installed.');\n return;\n }\n\n console.log('Installed Claude plugins:\\n');\n\n for (const [packageName, entry] of Object.entries(result.plugins)) {\n console.log(`${packageName}@${entry.version}`);\n for (const file of entry.files) {\n console.log(` .claude/${file}`);\n }\n console.log();\n }\n });\n\nprogram\n .command('remove')\n .description('Remove a plugin and its assets (called from plugin preuninstall)')\n .argument('[package]', 'Package name (auto-detected if run from preuninstall)')\n .action((packageArg?: string) => {\n const projectRoot = findProjectRoot();\n const packageName = packageArg || process.env.npm_package_name;\n\n if (!packageName) {\n console.error('Error: Could not determine package name.');\n console.error('Please provide the package name as an argument: claude-plugins remove <package>');\n process.exit(1);\n }\n\n const result = removePluginFromProject(projectRoot, packageName);\n\n if (!result.success) {\n console.error(result.error);\n process.exit(1);\n }\n\n for (const file of result.filesRemoved) {\n console.log(`Removed .claude/${file}`);\n }\n\n console.log(`Removed ${packageName}`);\n });\n\nprogram.parse();\n","import { existsSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport {\n readManifest,\n writeManifest,\n cleanupManifestFiles,\n addPlugin,\n removePlugin,\n type PluginEntry,\n} from './manifest.js';\nimport {\n copyPluginAssets,\n findPluginInNodeModules,\n hasAssets,\n getPackageVersion,\n} from './copier.js';\n\nexport interface SyncResult {\n success: boolean;\n synced: boolean;\n reason?: string;\n totalFiles: number;\n pluginCount: number;\n removedPlugins: string[];\n conflicts: string[];\n installedPlugins: Array<{ name: string; version: string; fileCount: number }>;\n}\n\nexport interface AddResult {\n success: boolean;\n alreadyExists: boolean;\n packageName: string;\n version?: string;\n files: string[];\n error?: string;\n}\n\nexport interface ListResult {\n plugins: Record<string, PluginEntry>;\n}\n\nexport interface RemoveResult {\n success: boolean;\n packageName: string;\n filesRemoved: string[];\n error?: string;\n}\n\nexport function syncPlugins(\n projectRoot: string,\n options: { force?: boolean } = {}\n): SyncResult {\n const manifest = readManifest(projectRoot);\n const pluginCount = Object.keys(manifest.plugins).length;\n\n if (pluginCount === 0) {\n return {\n success: true,\n synced: false,\n reason: 'No plugins to sync',\n totalFiles: 0,\n pluginCount: 0,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n\n // Check if any plugins have changed (unless --force)\n if (!options.force) {\n let needsSync = false;\n let reason = '';\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n needsSync = true;\n reason = `${packageName} was uninstalled`;\n break;\n }\n\n const currentVersion = getPackageVersion(packagePath);\n if (currentVersion !== entry.version) {\n needsSync = true;\n reason = `${packageName} changed (${entry.version} → ${currentVersion})`;\n break;\n }\n }\n\n if (!needsSync) {\n return {\n success: true,\n synced: false,\n reason: 'All plugins up to date',\n totalFiles: 0,\n pluginCount,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n }\n\n // Clean up existing files from manifest\n cleanupManifestFiles(projectRoot);\n\n // Re-copy all plugins from manifest\n const newManifest = { plugins: {} as Record<string, PluginEntry> };\n const fileOwnership = new Map<string, string>();\n const conflicts: string[] = [];\n const removedPlugins: string[] = [];\n const installedPlugins: Array<{ name: string; version: string; fileCount: number }> = [];\n let totalFiles = 0;\n\n for (const [packageName] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n removedPlugins.push(packageName);\n continue;\n }\n\n if (!hasAssets(packagePath)) {\n continue;\n }\n\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n // Check for conflicts\n for (const file of result.files) {\n const existingOwner = fileOwnership.get(file);\n if (existingOwner) {\n conflicts.push(`${file} (${existingOwner} vs ${packageName})`);\n }\n fileOwnership.set(file, packageName);\n }\n\n newManifest.plugins[packageName] = {\n version: result.version,\n files: result.files,\n };\n totalFiles += result.files.length;\n installedPlugins.push({\n name: packageName,\n version: result.version,\n fileCount: result.files.length,\n });\n }\n }\n\n writeManifest(projectRoot, newManifest);\n\n return {\n success: true,\n synced: true,\n totalFiles,\n pluginCount: Object.keys(newManifest.plugins).length,\n removedPlugins,\n conflicts,\n installedPlugins,\n };\n}\n\nexport function addPluginToProject(\n projectRoot: string,\n packageName: string\n): AddResult {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n return {\n success: false,\n alreadyExists: false,\n packageName,\n files: [],\n error: `Package ${packageName} not found in node_modules`,\n };\n }\n\n if (!hasAssets(packagePath)) {\n return {\n success: true,\n alreadyExists: false,\n packageName,\n files: [],\n };\n }\n\n // Clean up any existing files for this plugin\n const manifest = readManifest(projectRoot);\n const existing = manifest.plugins[packageName];\n\n if (existing) {\n const claudeDir = join(projectRoot, '.claude');\n for (const file of existing.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n }\n }\n }\n\n // Copy assets\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n addPlugin(projectRoot, packageName, result.version, result.files);\n }\n\n return {\n success: true,\n alreadyExists: !!existing,\n packageName,\n version: result.version,\n files: result.files,\n };\n}\n\nexport function listPlugins(projectRoot: string): ListResult {\n const manifest = readManifest(projectRoot);\n return { plugins: manifest.plugins };\n}\n\nexport function removePluginFromProject(\n projectRoot: string,\n packageName: string\n): RemoveResult {\n const manifest = readManifest(projectRoot);\n const entry = manifest.plugins[packageName];\n\n if (!entry) {\n return {\n success: false,\n packageName,\n filesRemoved: [],\n error: `Plugin ${packageName} is not installed`,\n };\n }\n\n const claudeDir = join(projectRoot, '.claude');\n const filesRemoved: string[] = [];\n\n // Remove files\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n filesRemoved.push(file);\n }\n }\n\n // Update manifest (will delete manifest file if no plugins left)\n removePlugin(projectRoot, packageName);\n\n return {\n success: true,\n packageName,\n filesRemoved,\n };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst MANIFEST_FILE = '.plugins-manifest.json';\n\nexport interface PluginEntry {\n version: string;\n files: string[];\n}\n\nexport interface Manifest {\n plugins: Record<string, PluginEntry>;\n}\n\nfunction getManifestPath(projectRoot: string): string {\n return join(projectRoot, '.claude', MANIFEST_FILE);\n}\n\nexport function readManifest(projectRoot: string): Manifest {\n const manifestPath = getManifestPath(projectRoot);\n\n if (!existsSync(manifestPath)) {\n return { plugins: {} };\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8');\n return JSON.parse(content) as Manifest;\n } catch {\n return { plugins: {} };\n }\n}\n\nexport function writeManifest(projectRoot: string, manifest: Manifest): void {\n const manifestPath = getManifestPath(projectRoot);\n const claudeDir = dirname(manifestPath);\n\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n}\n\nexport function addPlugin(\n projectRoot: string,\n packageName: string,\n version: string,\n files: string[]\n): void {\n const manifest = readManifest(projectRoot);\n\n manifest.plugins[packageName] = {\n version,\n files,\n };\n\n writeManifest(projectRoot, manifest);\n}\n\nexport function removePlugin(projectRoot: string, packageName: string): void {\n const manifest = readManifest(projectRoot);\n\n delete manifest.plugins[packageName];\n\n // Delete manifest if no plugins left, otherwise update it\n if (Object.keys(manifest.plugins).length === 0) {\n const manifestPath = join(projectRoot, '.claude', MANIFEST_FILE);\n if (existsSync(manifestPath)) {\n rmSync(manifestPath);\n }\n } else {\n writeManifest(projectRoot, manifest);\n }\n}\n\nexport function getPlugins(projectRoot: string): Record<string, PluginEntry> {\n return readManifest(projectRoot).plugins;\n}\n\nexport function cleanupManifestFiles(projectRoot: string): string[] {\n const manifest = readManifest(projectRoot);\n const claudeDir = join(projectRoot, '.claude');\n const removedFiles: string[] = [];\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n removedFiles.push(file);\n }\n }\n }\n\n return removedFiles;\n}\n","import { existsSync, mkdirSync, cpSync, readdirSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, basename } from 'node:path';\n\nconst ASSET_DIRS = ['skills', 'commands', 'agents', 'hooks', 'scripts'] as const;\ntype AssetDir = typeof ASSET_DIRS[number];\n\ninterface CopyResult {\n files: string[];\n version: string;\n}\n\nexport function getPackageVersion(packagePath: string): string {\n try {\n const pkgJson = JSON.parse(readFileSync(join(packagePath, 'package.json'), 'utf-8'));\n return pkgJson.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nfunction isValidAsset(itemPath: string): boolean {\n const name = basename(itemPath);\n return name !== '.gitkeep';\n}\n\nexport function copyPluginAssets(\n packagePath: string,\n projectRoot: string\n): CopyResult {\n const claudeDir = join(projectRoot, '.claude');\n const copiedFiles: string[] = [];\n\n for (const assetDir of ASSET_DIRS) {\n const sourcePath = join(packagePath, assetDir);\n\n if (!existsSync(sourcePath)) {\n continue;\n }\n\n const targetDir = join(claudeDir, assetDir);\n\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n }\n\n const items = readdirSync(sourcePath);\n\n for (const item of items) {\n if (item === '.gitkeep') continue;\n\n const itemPath = join(sourcePath, item);\n const targetPath = join(targetDir, item);\n\n if (isValidAsset(itemPath)) {\n // Copy files or directories recursively\n cpSync(itemPath, targetPath, { recursive: true });\n copiedFiles.push(`${assetDir}/${item}`);\n }\n }\n }\n\n return {\n files: copiedFiles,\n version: getPackageVersion(packagePath),\n };\n}\n\nexport function findPluginInNodeModules(\n packageName: string,\n projectRoot: string\n): string | null {\n // Standard node_modules path (npm, pnpm, yarn classic, bun)\n const standardPath = join(projectRoot, 'node_modules', packageName);\n if (existsSync(standardPath)) {\n return standardPath;\n }\n\n // Fallback: use Node's require.resolve for yarn PnP and other setups\n try {\n const require = createRequire(join(projectRoot, 'package.json'));\n const resolved = require.resolve(`${packageName}/package.json`);\n return dirname(resolved);\n } catch {\n return null;\n }\n}\n\nexport function hasAssets(packagePath: string): boolean {\n for (const assetDir of ASSET_DIRS) {\n const dirPath = join(packagePath, assetDir);\n if (existsSync(dirPath)) {\n const items = readdirSync(dirPath).filter(f => f !== '.gitkeep');\n if (items.length > 0) {\n return true;\n }\n }\n }\n return false;\n}\n"],"mappings":"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","names":["existsSync","readFileSync","dirname","join","existsSync","rmSync","join","existsSync","mkdirSync","readFileSync","dirname","join","require","join","existsSync","rmSync","dirname","join","readFileSync","existsSync"]}
package/dist/index.js CHANGED
@@ -73,10 +73,10 @@ function cleanupManifestFiles(projectRoot) {
73
73
  }
74
74
 
75
75
  // src/lib/copier.ts
76
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync, readdirSync, statSync, readFileSync as readFileSync2 } from "fs";
76
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync, readdirSync, readFileSync as readFileSync2 } from "fs";
77
77
  import { createRequire } from "module";
78
78
  import { dirname as dirname2, join as join2, basename } from "path";
79
- var ASSET_DIRS = ["skills", "commands", "agents", "hooks"];
79
+ var ASSET_DIRS = ["skills", "commands", "agents", "hooks", "scripts"];
80
80
  function getPackageVersion(packagePath) {
81
81
  try {
82
82
  const pkgJson = JSON.parse(readFileSync2(join2(packagePath, "package.json"), "utf-8"));
@@ -85,23 +85,9 @@ function getPackageVersion(packagePath) {
85
85
  return "0.0.0";
86
86
  }
87
87
  }
88
- function copyDirectory(src, dest) {
89
- cpSync(src, dest, { recursive: true });
90
- }
91
- function copyFile(src, dest) {
92
- const destDir = join2(dest, "..");
93
- if (!existsSync2(destDir)) {
94
- mkdirSync2(destDir, { recursive: true });
95
- }
96
- cpSync(src, dest);
97
- }
98
- function isSkillDirectory(itemPath) {
99
- return statSync(itemPath).isDirectory();
100
- }
101
- function isAssetFile(itemPath) {
102
- const stat = statSync(itemPath);
88
+ function isValidAsset(itemPath) {
103
89
  const name = basename(itemPath);
104
- return stat.isFile() && name !== ".gitkeep";
90
+ return name !== ".gitkeep";
105
91
  }
106
92
  function copyPluginAssets(packagePath, projectRoot) {
107
93
  const claudeDir = join2(projectRoot, ".claude");
@@ -120,16 +106,9 @@ function copyPluginAssets(packagePath, projectRoot) {
120
106
  if (item === ".gitkeep") continue;
121
107
  const itemPath = join2(sourcePath, item);
122
108
  const targetPath = join2(targetDir, item);
123
- if (assetDir === "skills") {
124
- if (isSkillDirectory(itemPath)) {
125
- copyDirectory(itemPath, targetPath);
126
- copiedFiles.push(`${assetDir}/${item}`);
127
- }
128
- } else {
129
- if (isAssetFile(itemPath)) {
130
- copyFile(itemPath, targetPath);
131
- copiedFiles.push(`${assetDir}/${item}`);
132
- }
109
+ if (isValidAsset(itemPath)) {
110
+ cpSync(itemPath, targetPath, { recursive: true });
111
+ copiedFiles.push(`${assetDir}/${item}`);
133
112
  }
134
113
  }
135
114
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/sync.ts","../src/lib/manifest.ts","../src/lib/copier.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { addPluginToProject, removePluginFromProject } from './lib/sync.js';\n\n/**\n * Get package name from env var or package.json in cwd\n */\nfunction getPackageName(): string | null {\n // Try env var first (set by npm, sometimes by pnpm)\n if (process.env.npm_package_name) {\n return process.env.npm_package_name;\n }\n\n // Fall back to reading package.json in cwd (where postinstall runs)\n const pkgPath = join(process.cwd(), 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.name || null;\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\n// Main exports for programmatic usage\nexport {\n readManifest,\n writeManifest,\n addPlugin,\n removePlugin,\n getPlugins,\n cleanupManifestFiles,\n type Manifest,\n type PluginEntry,\n} from './lib/manifest.js';\n\nexport {\n copyPluginAssets,\n findPluginInNodeModules,\n hasAssets,\n getPackageVersion,\n} from './lib/copier.js';\n\nexport {\n syncPlugins,\n addPluginToProject,\n listPlugins,\n removePluginFromProject,\n type SyncResult,\n type AddResult,\n type ListResult,\n type RemoveResult,\n} from './lib/sync.js';\n\n/**\n * Find project root by walking up from INIT_CWD or cwd\n */\nfunction findProjectRoot(): string {\n // INIT_CWD is set by npm/pnpm to the directory where the command was run\n const initCwd = process.env.INIT_CWD;\n if (initCwd && existsSync(join(initCwd, 'package.json'))) {\n return initCwd;\n }\n\n let dir = process.cwd();\n while (dir !== '/') {\n if (!dir.includes('node_modules') && existsSync(join(dir, 'package.json'))) {\n return dir;\n }\n dir = resolve(dir, '..');\n }\n return process.cwd();\n}\n\n/**\n * Add the current plugin to the project.\n * Called from plugin's postinstall: node -e \"require('@leeovery/claude-manager').add()\"\n */\nexport function add(): void {\n const packageName = getPackageName();\n if (!packageName) {\n console.error('[claude-manager] Could not determine package name');\n process.exit(1);\n }\n\n const projectRoot = findProjectRoot();\n const result = addPluginToProject(projectRoot, packageName);\n\n if (!result.success) {\n console.error(`[claude-manager] Error: ${result.error}`);\n process.exit(1);\n }\n\n if (result.files.length === 0) {\n return; // No assets to install, stay silent\n }\n\n console.log(`[claude-manager] Installed ${packageName}@${result.version}:`);\n for (const file of result.files) {\n console.log(` .claude/${file}`);\n }\n}\n\n/**\n * Remove the current plugin from the project.\n * Called from plugin's preuninstall: node -e \"require('@leeovery/claude-manager').remove()\"\n */\nexport function remove(): void {\n const packageName = getPackageName();\n if (!packageName) {\n console.error('[claude-manager] Could not determine package name');\n process.exit(1);\n }\n\n const projectRoot = findProjectRoot();\n const result = removePluginFromProject(projectRoot, packageName);\n\n if (!result.success) {\n // Silently ignore if plugin not in manifest (might already be removed)\n return;\n }\n\n if (result.filesRemoved.length > 0) {\n console.log(`[claude-manager] Removed ${packageName}:`);\n for (const file of result.filesRemoved) {\n console.log(` .claude/${file}`);\n }\n }\n}\n","import { existsSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport {\n readManifest,\n writeManifest,\n cleanupManifestFiles,\n addPlugin,\n removePlugin,\n type PluginEntry,\n} from './manifest.js';\nimport {\n copyPluginAssets,\n findPluginInNodeModules,\n hasAssets,\n getPackageVersion,\n} from './copier.js';\n\nexport interface SyncResult {\n success: boolean;\n synced: boolean;\n reason?: string;\n totalFiles: number;\n pluginCount: number;\n removedPlugins: string[];\n conflicts: string[];\n installedPlugins: Array<{ name: string; version: string; fileCount: number }>;\n}\n\nexport interface AddResult {\n success: boolean;\n alreadyExists: boolean;\n packageName: string;\n version?: string;\n files: string[];\n error?: string;\n}\n\nexport interface ListResult {\n plugins: Record<string, PluginEntry>;\n}\n\nexport interface RemoveResult {\n success: boolean;\n packageName: string;\n filesRemoved: string[];\n error?: string;\n}\n\nexport function syncPlugins(\n projectRoot: string,\n options: { force?: boolean } = {}\n): SyncResult {\n const manifest = readManifest(projectRoot);\n const pluginCount = Object.keys(manifest.plugins).length;\n\n if (pluginCount === 0) {\n return {\n success: true,\n synced: false,\n reason: 'No plugins to sync',\n totalFiles: 0,\n pluginCount: 0,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n\n // Check if any plugins have changed (unless --force)\n if (!options.force) {\n let needsSync = false;\n let reason = '';\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n needsSync = true;\n reason = `${packageName} was uninstalled`;\n break;\n }\n\n const currentVersion = getPackageVersion(packagePath);\n if (currentVersion !== entry.version) {\n needsSync = true;\n reason = `${packageName} changed (${entry.version} → ${currentVersion})`;\n break;\n }\n }\n\n if (!needsSync) {\n return {\n success: true,\n synced: false,\n reason: 'All plugins up to date',\n totalFiles: 0,\n pluginCount,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n }\n\n // Clean up existing files from manifest\n cleanupManifestFiles(projectRoot);\n\n // Re-copy all plugins from manifest\n const newManifest = { plugins: {} as Record<string, PluginEntry> };\n const fileOwnership = new Map<string, string>();\n const conflicts: string[] = [];\n const removedPlugins: string[] = [];\n const installedPlugins: Array<{ name: string; version: string; fileCount: number }> = [];\n let totalFiles = 0;\n\n for (const [packageName] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n removedPlugins.push(packageName);\n continue;\n }\n\n if (!hasAssets(packagePath)) {\n continue;\n }\n\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n // Check for conflicts\n for (const file of result.files) {\n const existingOwner = fileOwnership.get(file);\n if (existingOwner) {\n conflicts.push(`${file} (${existingOwner} vs ${packageName})`);\n }\n fileOwnership.set(file, packageName);\n }\n\n newManifest.plugins[packageName] = {\n version: result.version,\n files: result.files,\n };\n totalFiles += result.files.length;\n installedPlugins.push({\n name: packageName,\n version: result.version,\n fileCount: result.files.length,\n });\n }\n }\n\n writeManifest(projectRoot, newManifest);\n\n return {\n success: true,\n synced: true,\n totalFiles,\n pluginCount: Object.keys(newManifest.plugins).length,\n removedPlugins,\n conflicts,\n installedPlugins,\n };\n}\n\nexport function addPluginToProject(\n projectRoot: string,\n packageName: string\n): AddResult {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n return {\n success: false,\n alreadyExists: false,\n packageName,\n files: [],\n error: `Package ${packageName} not found in node_modules`,\n };\n }\n\n if (!hasAssets(packagePath)) {\n return {\n success: true,\n alreadyExists: false,\n packageName,\n files: [],\n };\n }\n\n // Clean up any existing files for this plugin\n const manifest = readManifest(projectRoot);\n const existing = manifest.plugins[packageName];\n\n if (existing) {\n const claudeDir = join(projectRoot, '.claude');\n for (const file of existing.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n }\n }\n }\n\n // Copy assets\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n addPlugin(projectRoot, packageName, result.version, result.files);\n }\n\n return {\n success: true,\n alreadyExists: !!existing,\n packageName,\n version: result.version,\n files: result.files,\n };\n}\n\nexport function listPlugins(projectRoot: string): ListResult {\n const manifest = readManifest(projectRoot);\n return { plugins: manifest.plugins };\n}\n\nexport function removePluginFromProject(\n projectRoot: string,\n packageName: string\n): RemoveResult {\n const manifest = readManifest(projectRoot);\n const entry = manifest.plugins[packageName];\n\n if (!entry) {\n return {\n success: false,\n packageName,\n filesRemoved: [],\n error: `Plugin ${packageName} is not installed`,\n };\n }\n\n const claudeDir = join(projectRoot, '.claude');\n const filesRemoved: string[] = [];\n\n // Remove files\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n filesRemoved.push(file);\n }\n }\n\n // Update manifest (will delete manifest file if no plugins left)\n removePlugin(projectRoot, packageName);\n\n return {\n success: true,\n packageName,\n filesRemoved,\n };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst MANIFEST_FILE = '.plugins-manifest.json';\n\nexport interface PluginEntry {\n version: string;\n files: string[];\n}\n\nexport interface Manifest {\n plugins: Record<string, PluginEntry>;\n}\n\nfunction getManifestPath(projectRoot: string): string {\n return join(projectRoot, '.claude', MANIFEST_FILE);\n}\n\nexport function readManifest(projectRoot: string): Manifest {\n const manifestPath = getManifestPath(projectRoot);\n\n if (!existsSync(manifestPath)) {\n return { plugins: {} };\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8');\n return JSON.parse(content) as Manifest;\n } catch {\n return { plugins: {} };\n }\n}\n\nexport function writeManifest(projectRoot: string, manifest: Manifest): void {\n const manifestPath = getManifestPath(projectRoot);\n const claudeDir = dirname(manifestPath);\n\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n}\n\nexport function addPlugin(\n projectRoot: string,\n packageName: string,\n version: string,\n files: string[]\n): void {\n const manifest = readManifest(projectRoot);\n\n manifest.plugins[packageName] = {\n version,\n files,\n };\n\n writeManifest(projectRoot, manifest);\n}\n\nexport function removePlugin(projectRoot: string, packageName: string): void {\n const manifest = readManifest(projectRoot);\n\n delete manifest.plugins[packageName];\n\n // Delete manifest if no plugins left, otherwise update it\n if (Object.keys(manifest.plugins).length === 0) {\n const manifestPath = join(projectRoot, '.claude', MANIFEST_FILE);\n if (existsSync(manifestPath)) {\n rmSync(manifestPath);\n }\n } else {\n writeManifest(projectRoot, manifest);\n }\n}\n\nexport function getPlugins(projectRoot: string): Record<string, PluginEntry> {\n return readManifest(projectRoot).plugins;\n}\n\nexport function cleanupManifestFiles(projectRoot: string): string[] {\n const manifest = readManifest(projectRoot);\n const claudeDir = join(projectRoot, '.claude');\n const removedFiles: string[] = [];\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n removedFiles.push(file);\n }\n }\n }\n\n return removedFiles;\n}\n","import { existsSync, mkdirSync, cpSync, readdirSync, statSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, basename } from 'node:path';\n\nconst ASSET_DIRS = ['skills', 'commands', 'agents', 'hooks'] as const;\ntype AssetDir = typeof ASSET_DIRS[number];\n\ninterface CopyResult {\n files: string[];\n version: string;\n}\n\nexport function getPackageVersion(packagePath: string): string {\n try {\n const pkgJson = JSON.parse(readFileSync(join(packagePath, 'package.json'), 'utf-8'));\n return pkgJson.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nfunction copyDirectory(src: string, dest: string): void {\n cpSync(src, dest, { recursive: true });\n}\n\nfunction copyFile(src: string, dest: string): void {\n const destDir = join(dest, '..');\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n cpSync(src, dest);\n}\n\nfunction isSkillDirectory(itemPath: string): boolean {\n return statSync(itemPath).isDirectory();\n}\n\nfunction isAssetFile(itemPath: string): boolean {\n const stat = statSync(itemPath);\n const name = basename(itemPath);\n return stat.isFile() && name !== '.gitkeep';\n}\n\nexport function copyPluginAssets(\n packagePath: string,\n projectRoot: string\n): CopyResult {\n const claudeDir = join(projectRoot, '.claude');\n const copiedFiles: string[] = [];\n\n for (const assetDir of ASSET_DIRS) {\n const sourcePath = join(packagePath, assetDir);\n\n if (!existsSync(sourcePath)) {\n continue;\n }\n\n const targetDir = join(claudeDir, assetDir);\n\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n }\n\n const items = readdirSync(sourcePath);\n\n for (const item of items) {\n if (item === '.gitkeep') continue;\n\n const itemPath = join(sourcePath, item);\n const targetPath = join(targetDir, item);\n\n if (assetDir === 'skills') {\n // Skills are directories\n if (isSkillDirectory(itemPath)) {\n copyDirectory(itemPath, targetPath);\n copiedFiles.push(`${assetDir}/${item}`);\n }\n } else {\n // Commands, agents, hooks are files\n if (isAssetFile(itemPath)) {\n copyFile(itemPath, targetPath);\n copiedFiles.push(`${assetDir}/${item}`);\n }\n }\n }\n }\n\n return {\n files: copiedFiles,\n version: getPackageVersion(packagePath),\n };\n}\n\nexport function findPluginInNodeModules(\n packageName: string,\n projectRoot: string\n): string | null {\n // Standard node_modules path (npm, pnpm, yarn classic, bun)\n const standardPath = join(projectRoot, 'node_modules', packageName);\n if (existsSync(standardPath)) {\n return standardPath;\n }\n\n // Fallback: use Node's require.resolve for yarn PnP and other setups\n try {\n const require = createRequire(join(projectRoot, 'package.json'));\n const resolved = require.resolve(`${packageName}/package.json`);\n return dirname(resolved);\n } catch {\n return null;\n }\n}\n\nexport function hasAssets(packagePath: string): boolean {\n for (const assetDir of ASSET_DIRS) {\n const dirPath = join(packagePath, assetDir);\n if (existsSync(dirPath)) {\n const items = readdirSync(dirPath).filter(f => f !== '.gitkeep');\n if (items.length > 0) {\n return true;\n }\n }\n }\n return false;\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","existsSync","rmSync","join","existsSync","mkdirSync","readFileSync","dirname","join","require","join","existsSync","rmSync","join","existsSync","readFileSync"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/sync.ts","../src/lib/manifest.ts","../src/lib/copier.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { addPluginToProject, removePluginFromProject } from './lib/sync.js';\n\n/**\n * Get package name from env var or package.json in cwd\n */\nfunction getPackageName(): string | null {\n // Try env var first (set by npm, sometimes by pnpm)\n if (process.env.npm_package_name) {\n return process.env.npm_package_name;\n }\n\n // Fall back to reading package.json in cwd (where postinstall runs)\n const pkgPath = join(process.cwd(), 'package.json');\n if (existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n return pkg.name || null;\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\n// Main exports for programmatic usage\nexport {\n readManifest,\n writeManifest,\n addPlugin,\n removePlugin,\n getPlugins,\n cleanupManifestFiles,\n type Manifest,\n type PluginEntry,\n} from './lib/manifest.js';\n\nexport {\n copyPluginAssets,\n findPluginInNodeModules,\n hasAssets,\n getPackageVersion,\n} from './lib/copier.js';\n\nexport {\n syncPlugins,\n addPluginToProject,\n listPlugins,\n removePluginFromProject,\n type SyncResult,\n type AddResult,\n type ListResult,\n type RemoveResult,\n} from './lib/sync.js';\n\n/**\n * Find project root by walking up from INIT_CWD or cwd\n */\nfunction findProjectRoot(): string {\n // INIT_CWD is set by npm/pnpm to the directory where the command was run\n const initCwd = process.env.INIT_CWD;\n if (initCwd && existsSync(join(initCwd, 'package.json'))) {\n return initCwd;\n }\n\n let dir = process.cwd();\n while (dir !== '/') {\n if (!dir.includes('node_modules') && existsSync(join(dir, 'package.json'))) {\n return dir;\n }\n dir = resolve(dir, '..');\n }\n return process.cwd();\n}\n\n/**\n * Add the current plugin to the project.\n * Called from plugin's postinstall: node -e \"require('@leeovery/claude-manager').add()\"\n */\nexport function add(): void {\n const packageName = getPackageName();\n if (!packageName) {\n console.error('[claude-manager] Could not determine package name');\n process.exit(1);\n }\n\n const projectRoot = findProjectRoot();\n const result = addPluginToProject(projectRoot, packageName);\n\n if (!result.success) {\n console.error(`[claude-manager] Error: ${result.error}`);\n process.exit(1);\n }\n\n if (result.files.length === 0) {\n return; // No assets to install, stay silent\n }\n\n console.log(`[claude-manager] Installed ${packageName}@${result.version}:`);\n for (const file of result.files) {\n console.log(` .claude/${file}`);\n }\n}\n\n/**\n * Remove the current plugin from the project.\n * Called from plugin's preuninstall: node -e \"require('@leeovery/claude-manager').remove()\"\n */\nexport function remove(): void {\n const packageName = getPackageName();\n if (!packageName) {\n console.error('[claude-manager] Could not determine package name');\n process.exit(1);\n }\n\n const projectRoot = findProjectRoot();\n const result = removePluginFromProject(projectRoot, packageName);\n\n if (!result.success) {\n // Silently ignore if plugin not in manifest (might already be removed)\n return;\n }\n\n if (result.filesRemoved.length > 0) {\n console.log(`[claude-manager] Removed ${packageName}:`);\n for (const file of result.filesRemoved) {\n console.log(` .claude/${file}`);\n }\n }\n}\n","import { existsSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport {\n readManifest,\n writeManifest,\n cleanupManifestFiles,\n addPlugin,\n removePlugin,\n type PluginEntry,\n} from './manifest.js';\nimport {\n copyPluginAssets,\n findPluginInNodeModules,\n hasAssets,\n getPackageVersion,\n} from './copier.js';\n\nexport interface SyncResult {\n success: boolean;\n synced: boolean;\n reason?: string;\n totalFiles: number;\n pluginCount: number;\n removedPlugins: string[];\n conflicts: string[];\n installedPlugins: Array<{ name: string; version: string; fileCount: number }>;\n}\n\nexport interface AddResult {\n success: boolean;\n alreadyExists: boolean;\n packageName: string;\n version?: string;\n files: string[];\n error?: string;\n}\n\nexport interface ListResult {\n plugins: Record<string, PluginEntry>;\n}\n\nexport interface RemoveResult {\n success: boolean;\n packageName: string;\n filesRemoved: string[];\n error?: string;\n}\n\nexport function syncPlugins(\n projectRoot: string,\n options: { force?: boolean } = {}\n): SyncResult {\n const manifest = readManifest(projectRoot);\n const pluginCount = Object.keys(manifest.plugins).length;\n\n if (pluginCount === 0) {\n return {\n success: true,\n synced: false,\n reason: 'No plugins to sync',\n totalFiles: 0,\n pluginCount: 0,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n\n // Check if any plugins have changed (unless --force)\n if (!options.force) {\n let needsSync = false;\n let reason = '';\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n needsSync = true;\n reason = `${packageName} was uninstalled`;\n break;\n }\n\n const currentVersion = getPackageVersion(packagePath);\n if (currentVersion !== entry.version) {\n needsSync = true;\n reason = `${packageName} changed (${entry.version} → ${currentVersion})`;\n break;\n }\n }\n\n if (!needsSync) {\n return {\n success: true,\n synced: false,\n reason: 'All plugins up to date',\n totalFiles: 0,\n pluginCount,\n removedPlugins: [],\n conflicts: [],\n installedPlugins: [],\n };\n }\n }\n\n // Clean up existing files from manifest\n cleanupManifestFiles(projectRoot);\n\n // Re-copy all plugins from manifest\n const newManifest = { plugins: {} as Record<string, PluginEntry> };\n const fileOwnership = new Map<string, string>();\n const conflicts: string[] = [];\n const removedPlugins: string[] = [];\n const installedPlugins: Array<{ name: string; version: string; fileCount: number }> = [];\n let totalFiles = 0;\n\n for (const [packageName] of Object.entries(manifest.plugins)) {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n removedPlugins.push(packageName);\n continue;\n }\n\n if (!hasAssets(packagePath)) {\n continue;\n }\n\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n // Check for conflicts\n for (const file of result.files) {\n const existingOwner = fileOwnership.get(file);\n if (existingOwner) {\n conflicts.push(`${file} (${existingOwner} vs ${packageName})`);\n }\n fileOwnership.set(file, packageName);\n }\n\n newManifest.plugins[packageName] = {\n version: result.version,\n files: result.files,\n };\n totalFiles += result.files.length;\n installedPlugins.push({\n name: packageName,\n version: result.version,\n fileCount: result.files.length,\n });\n }\n }\n\n writeManifest(projectRoot, newManifest);\n\n return {\n success: true,\n synced: true,\n totalFiles,\n pluginCount: Object.keys(newManifest.plugins).length,\n removedPlugins,\n conflicts,\n installedPlugins,\n };\n}\n\nexport function addPluginToProject(\n projectRoot: string,\n packageName: string\n): AddResult {\n const packagePath = findPluginInNodeModules(packageName, projectRoot);\n\n if (!packagePath) {\n return {\n success: false,\n alreadyExists: false,\n packageName,\n files: [],\n error: `Package ${packageName} not found in node_modules`,\n };\n }\n\n if (!hasAssets(packagePath)) {\n return {\n success: true,\n alreadyExists: false,\n packageName,\n files: [],\n };\n }\n\n // Clean up any existing files for this plugin\n const manifest = readManifest(projectRoot);\n const existing = manifest.plugins[packageName];\n\n if (existing) {\n const claudeDir = join(projectRoot, '.claude');\n for (const file of existing.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n }\n }\n }\n\n // Copy assets\n const result = copyPluginAssets(packagePath, projectRoot);\n\n if (result.files.length > 0) {\n addPlugin(projectRoot, packageName, result.version, result.files);\n }\n\n return {\n success: true,\n alreadyExists: !!existing,\n packageName,\n version: result.version,\n files: result.files,\n };\n}\n\nexport function listPlugins(projectRoot: string): ListResult {\n const manifest = readManifest(projectRoot);\n return { plugins: manifest.plugins };\n}\n\nexport function removePluginFromProject(\n projectRoot: string,\n packageName: string\n): RemoveResult {\n const manifest = readManifest(projectRoot);\n const entry = manifest.plugins[packageName];\n\n if (!entry) {\n return {\n success: false,\n packageName,\n filesRemoved: [],\n error: `Plugin ${packageName} is not installed`,\n };\n }\n\n const claudeDir = join(projectRoot, '.claude');\n const filesRemoved: string[] = [];\n\n // Remove files\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n filesRemoved.push(file);\n }\n }\n\n // Update manifest (will delete manifest file if no plugins left)\n removePlugin(projectRoot, packageName);\n\n return {\n success: true,\n packageName,\n filesRemoved,\n };\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\n\nconst MANIFEST_FILE = '.plugins-manifest.json';\n\nexport interface PluginEntry {\n version: string;\n files: string[];\n}\n\nexport interface Manifest {\n plugins: Record<string, PluginEntry>;\n}\n\nfunction getManifestPath(projectRoot: string): string {\n return join(projectRoot, '.claude', MANIFEST_FILE);\n}\n\nexport function readManifest(projectRoot: string): Manifest {\n const manifestPath = getManifestPath(projectRoot);\n\n if (!existsSync(manifestPath)) {\n return { plugins: {} };\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8');\n return JSON.parse(content) as Manifest;\n } catch {\n return { plugins: {} };\n }\n}\n\nexport function writeManifest(projectRoot: string, manifest: Manifest): void {\n const manifestPath = getManifestPath(projectRoot);\n const claudeDir = dirname(manifestPath);\n\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n}\n\nexport function addPlugin(\n projectRoot: string,\n packageName: string,\n version: string,\n files: string[]\n): void {\n const manifest = readManifest(projectRoot);\n\n manifest.plugins[packageName] = {\n version,\n files,\n };\n\n writeManifest(projectRoot, manifest);\n}\n\nexport function removePlugin(projectRoot: string, packageName: string): void {\n const manifest = readManifest(projectRoot);\n\n delete manifest.plugins[packageName];\n\n // Delete manifest if no plugins left, otherwise update it\n if (Object.keys(manifest.plugins).length === 0) {\n const manifestPath = join(projectRoot, '.claude', MANIFEST_FILE);\n if (existsSync(manifestPath)) {\n rmSync(manifestPath);\n }\n } else {\n writeManifest(projectRoot, manifest);\n }\n}\n\nexport function getPlugins(projectRoot: string): Record<string, PluginEntry> {\n return readManifest(projectRoot).plugins;\n}\n\nexport function cleanupManifestFiles(projectRoot: string): string[] {\n const manifest = readManifest(projectRoot);\n const claudeDir = join(projectRoot, '.claude');\n const removedFiles: string[] = [];\n\n for (const [packageName, entry] of Object.entries(manifest.plugins)) {\n for (const file of entry.files) {\n const fullPath = join(claudeDir, file);\n if (existsSync(fullPath)) {\n rmSync(fullPath, { recursive: true, force: true });\n removedFiles.push(file);\n }\n }\n }\n\n return removedFiles;\n}\n","import { existsSync, mkdirSync, cpSync, readdirSync, readFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { dirname, join, basename } from 'node:path';\n\nconst ASSET_DIRS = ['skills', 'commands', 'agents', 'hooks', 'scripts'] as const;\ntype AssetDir = typeof ASSET_DIRS[number];\n\ninterface CopyResult {\n files: string[];\n version: string;\n}\n\nexport function getPackageVersion(packagePath: string): string {\n try {\n const pkgJson = JSON.parse(readFileSync(join(packagePath, 'package.json'), 'utf-8'));\n return pkgJson.version || '0.0.0';\n } catch {\n return '0.0.0';\n }\n}\n\nfunction isValidAsset(itemPath: string): boolean {\n const name = basename(itemPath);\n return name !== '.gitkeep';\n}\n\nexport function copyPluginAssets(\n packagePath: string,\n projectRoot: string\n): CopyResult {\n const claudeDir = join(projectRoot, '.claude');\n const copiedFiles: string[] = [];\n\n for (const assetDir of ASSET_DIRS) {\n const sourcePath = join(packagePath, assetDir);\n\n if (!existsSync(sourcePath)) {\n continue;\n }\n\n const targetDir = join(claudeDir, assetDir);\n\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true });\n }\n\n const items = readdirSync(sourcePath);\n\n for (const item of items) {\n if (item === '.gitkeep') continue;\n\n const itemPath = join(sourcePath, item);\n const targetPath = join(targetDir, item);\n\n if (isValidAsset(itemPath)) {\n // Copy files or directories recursively\n cpSync(itemPath, targetPath, { recursive: true });\n copiedFiles.push(`${assetDir}/${item}`);\n }\n }\n }\n\n return {\n files: copiedFiles,\n version: getPackageVersion(packagePath),\n };\n}\n\nexport function findPluginInNodeModules(\n packageName: string,\n projectRoot: string\n): string | null {\n // Standard node_modules path (npm, pnpm, yarn classic, bun)\n const standardPath = join(projectRoot, 'node_modules', packageName);\n if (existsSync(standardPath)) {\n return standardPath;\n }\n\n // Fallback: use Node's require.resolve for yarn PnP and other setups\n try {\n const require = createRequire(join(projectRoot, 'package.json'));\n const resolved = require.resolve(`${packageName}/package.json`);\n return dirname(resolved);\n } catch {\n return null;\n }\n}\n\nexport function hasAssets(packagePath: string): boolean {\n for (const assetDir of ASSET_DIRS) {\n const dirPath = join(packagePath, assetDir);\n if (existsSync(dirPath)) {\n const items = readdirSync(dirPath).filter(f => f !== '.gitkeep');\n if (items.length > 0) {\n return true;\n }\n }\n }\n return false;\n}\n"],"mappings":";AAAA,SAAS,cAAAA,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,QAAAC,OAAM,eAAe;;;ACD9B,SAAS,cAAAC,aAAY,UAAAC,eAAc;AACnC,SAAS,QAAAC,aAAY;;;ACDrB,SAAS,YAAY,WAAW,cAAc,eAAe,cAAc;AAC3E,SAAS,SAAS,YAAY;AAE9B,IAAM,gBAAgB;AAWtB,SAAS,gBAAgB,aAA6B;AACpD,SAAO,KAAK,aAAa,WAAW,aAAa;AACnD;AAEO,SAAS,aAAa,aAA+B;AAC1D,QAAM,eAAe,gBAAgB,WAAW;AAEhD,MAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,cAAc,OAAO;AAClD,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,EAAE,SAAS,CAAC,EAAE;AAAA,EACvB;AACF;AAEO,SAAS,cAAc,aAAqB,UAA0B;AAC3E,QAAM,eAAe,gBAAgB,WAAW;AAChD,QAAM,YAAY,QAAQ,YAAY;AAEtC,MAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AAEA,gBAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACtE;AAEO,SAAS,UACd,aACA,aACA,SACA,OACM;AACN,QAAM,WAAW,aAAa,WAAW;AAEzC,WAAS,QAAQ,WAAW,IAAI;AAAA,IAC9B;AAAA,IACA;AAAA,EACF;AAEA,gBAAc,aAAa,QAAQ;AACrC;AAEO,SAAS,aAAa,aAAqB,aAA2B;AAC3E,QAAM,WAAW,aAAa,WAAW;AAEzC,SAAO,SAAS,QAAQ,WAAW;AAGnC,MAAI,OAAO,KAAK,SAAS,OAAO,EAAE,WAAW,GAAG;AAC9C,UAAM,eAAe,KAAK,aAAa,WAAW,aAAa;AAC/D,QAAI,WAAW,YAAY,GAAG;AAC5B,aAAO,YAAY;AAAA,IACrB;AAAA,EACF,OAAO;AACL,kBAAc,aAAa,QAAQ;AAAA,EACrC;AACF;AAEO,SAAS,WAAW,aAAkD;AAC3E,SAAO,aAAa,WAAW,EAAE;AACnC;AAEO,SAAS,qBAAqB,aAA+B;AAClE,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,YAAY,KAAK,aAAa,SAAS;AAC7C,QAAM,eAAyB,CAAC;AAEhC,aAAW,CAAC,aAAa,KAAK,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AACnE,eAAW,QAAQ,MAAM,OAAO;AAC9B,YAAM,WAAW,KAAK,WAAW,IAAI;AACrC,UAAI,WAAW,QAAQ,GAAG;AACxB,eAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjD,qBAAa,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AChGA,SAAS,cAAAC,aAAY,aAAAC,YAAW,QAAQ,aAAa,gBAAAC,qBAAoB;AACzE,SAAS,qBAAqB;AAC9B,SAAS,WAAAC,UAAS,QAAAC,OAAM,gBAAgB;AAExC,IAAM,aAAa,CAAC,UAAU,YAAY,UAAU,SAAS,SAAS;AAQ/D,SAAS,kBAAkB,aAA6B;AAC7D,MAAI;AACF,UAAM,UAAU,KAAK,MAAMF,cAAaE,MAAK,aAAa,cAAc,GAAG,OAAO,CAAC;AACnF,WAAO,QAAQ,WAAW;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,UAA2B;AAC/C,QAAM,OAAO,SAAS,QAAQ;AAC9B,SAAO,SAAS;AAClB;AAEO,SAAS,iBACd,aACA,aACY;AACZ,QAAM,YAAYA,MAAK,aAAa,SAAS;AAC7C,QAAM,cAAwB,CAAC;AAE/B,aAAW,YAAY,YAAY;AACjC,UAAM,aAAaA,MAAK,aAAa,QAAQ;AAE7C,QAAI,CAACJ,YAAW,UAAU,GAAG;AAC3B;AAAA,IACF;AAEA,UAAM,YAAYI,MAAK,WAAW,QAAQ;AAE1C,QAAI,CAACJ,YAAW,SAAS,GAAG;AAC1B,MAAAC,WAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AAEA,UAAM,QAAQ,YAAY,UAAU;AAEpC,eAAW,QAAQ,OAAO;AACxB,UAAI,SAAS,WAAY;AAEzB,YAAM,WAAWG,MAAK,YAAY,IAAI;AACtC,YAAM,aAAaA,MAAK,WAAW,IAAI;AAEvC,UAAI,aAAa,QAAQ,GAAG;AAE1B,eAAO,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAChD,oBAAY,KAAK,GAAG,QAAQ,IAAI,IAAI,EAAE;AAAA,MACxC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,SAAS,kBAAkB,WAAW;AAAA,EACxC;AACF;AAEO,SAAS,wBACd,aACA,aACe;AAEf,QAAM,eAAeA,MAAK,aAAa,gBAAgB,WAAW;AAClE,MAAIJ,YAAW,YAAY,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAMK,WAAU,cAAcD,MAAK,aAAa,cAAc,CAAC;AAC/D,UAAM,WAAWC,SAAQ,QAAQ,GAAG,WAAW,eAAe;AAC9D,WAAOF,SAAQ,QAAQ;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,UAAU,aAA8B;AACtD,aAAW,YAAY,YAAY;AACjC,UAAM,UAAUC,MAAK,aAAa,QAAQ;AAC1C,QAAIJ,YAAW,OAAO,GAAG;AACvB,YAAM,QAAQ,YAAY,OAAO,EAAE,OAAO,OAAK,MAAM,UAAU;AAC/D,UAAI,MAAM,SAAS,GAAG;AACpB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;AFlDO,SAAS,YACd,aACA,UAA+B,CAAC,GACpB;AACZ,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,cAAc,OAAO,KAAK,SAAS,OAAO,EAAE;AAElD,MAAI,gBAAgB,GAAG;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,gBAAgB,CAAC;AAAA,MACjB,WAAW,CAAC;AAAA,MACZ,kBAAkB,CAAC;AAAA,IACrB;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,OAAO;AAClB,QAAI,YAAY;AAChB,QAAI,SAAS;AAEb,eAAW,CAAC,aAAa,KAAK,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AACnE,YAAM,cAAc,wBAAwB,aAAa,WAAW;AAEpE,UAAI,CAAC,aAAa;AAChB,oBAAY;AACZ,iBAAS,GAAG,WAAW;AACvB;AAAA,MACF;AAEA,YAAM,iBAAiB,kBAAkB,WAAW;AACpD,UAAI,mBAAmB,MAAM,SAAS;AACpC,oBAAY;AACZ,iBAAS,GAAG,WAAW,aAAa,MAAM,OAAO,WAAM,cAAc;AACrE;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC;AAAA,QACjB,WAAW,CAAC;AAAA,QACZ,kBAAkB,CAAC;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAGA,uBAAqB,WAAW;AAGhC,QAAM,cAAc,EAAE,SAAS,CAAC,EAAiC;AACjE,QAAM,gBAAgB,oBAAI,IAAoB;AAC9C,QAAM,YAAsB,CAAC;AAC7B,QAAM,iBAA2B,CAAC;AAClC,QAAM,mBAAgF,CAAC;AACvF,MAAI,aAAa;AAEjB,aAAW,CAAC,WAAW,KAAK,OAAO,QAAQ,SAAS,OAAO,GAAG;AAC5D,UAAM,cAAc,wBAAwB,aAAa,WAAW;AAEpE,QAAI,CAAC,aAAa;AAChB,qBAAe,KAAK,WAAW;AAC/B;AAAA,IACF;AAEA,QAAI,CAAC,UAAU,WAAW,GAAG;AAC3B;AAAA,IACF;AAEA,UAAM,SAAS,iBAAiB,aAAa,WAAW;AAExD,QAAI,OAAO,MAAM,SAAS,GAAG;AAE3B,iBAAW,QAAQ,OAAO,OAAO;AAC/B,cAAM,gBAAgB,cAAc,IAAI,IAAI;AAC5C,YAAI,eAAe;AACjB,oBAAU,KAAK,GAAG,IAAI,KAAK,aAAa,OAAO,WAAW,GAAG;AAAA,QAC/D;AACA,sBAAc,IAAI,MAAM,WAAW;AAAA,MACrC;AAEA,kBAAY,QAAQ,WAAW,IAAI;AAAA,QACjC,SAAS,OAAO;AAAA,QAChB,OAAO,OAAO;AAAA,MAChB;AACA,oBAAc,OAAO,MAAM;AAC3B,uBAAiB,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,SAAS,OAAO;AAAA,QAChB,WAAW,OAAO,MAAM;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,gBAAc,aAAa,WAAW;AAEtC,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR;AAAA,IACA,aAAa,OAAO,KAAK,YAAY,OAAO,EAAE;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,mBACd,aACA,aACW;AACX,QAAM,cAAc,wBAAwB,aAAa,WAAW;AAEpE,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,MACA,OAAO,CAAC;AAAA,MACR,OAAO,WAAW,WAAW;AAAA,IAC/B;AAAA,EACF;AAEA,MAAI,CAAC,UAAU,WAAW,GAAG;AAC3B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAGA,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,WAAW,SAAS,QAAQ,WAAW;AAE7C,MAAI,UAAU;AACZ,UAAM,YAAYM,MAAK,aAAa,SAAS;AAC7C,eAAW,QAAQ,SAAS,OAAO;AACjC,YAAM,WAAWA,MAAK,WAAW,IAAI;AACrC,UAAIC,YAAW,QAAQ,GAAG;AACxB,QAAAC,QAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAS,iBAAiB,aAAa,WAAW;AAExD,MAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,cAAU,aAAa,aAAa,OAAO,SAAS,OAAO,KAAK;AAAA,EAClE;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe,CAAC,CAAC;AAAA,IACjB;AAAA,IACA,SAAS,OAAO;AAAA,IAChB,OAAO,OAAO;AAAA,EAChB;AACF;AAEO,SAAS,YAAY,aAAiC;AAC3D,QAAM,WAAW,aAAa,WAAW;AACzC,SAAO,EAAE,SAAS,SAAS,QAAQ;AACrC;AAEO,SAAS,wBACd,aACA,aACc;AACd,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,QAAQ,SAAS,QAAQ,WAAW;AAE1C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,cAAc,CAAC;AAAA,MACf,OAAO,UAAU,WAAW;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,YAAYF,MAAK,aAAa,SAAS;AAC7C,QAAM,eAAyB,CAAC;AAGhC,aAAW,QAAQ,MAAM,OAAO;AAC9B,UAAM,WAAWA,MAAK,WAAW,IAAI;AACrC,QAAIC,YAAW,QAAQ,GAAG;AACxB,MAAAC,QAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjD,mBAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAGA,eAAa,aAAa,WAAW;AAErC,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,EACF;AACF;;;AD/PA,SAAS,iBAAgC;AAEvC,MAAI,QAAQ,IAAI,kBAAkB;AAChC,WAAO,QAAQ,IAAI;AAAA,EACrB;AAGA,QAAM,UAAUC,MAAK,QAAQ,IAAI,GAAG,cAAc;AAClD,MAAIC,YAAW,OAAO,GAAG;AACvB,QAAI;AACF,YAAM,MAAM,KAAK,MAAMC,cAAa,SAAS,OAAO,CAAC;AACrD,aAAO,IAAI,QAAQ;AAAA,IACrB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAmCA,SAAS,kBAA0B;AAEjC,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,WAAWD,YAAWD,MAAK,SAAS,cAAc,CAAC,GAAG;AACxD,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,IAAI;AACtB,SAAO,QAAQ,KAAK;AAClB,QAAI,CAAC,IAAI,SAAS,cAAc,KAAKC,YAAWD,MAAK,KAAK,cAAc,CAAC,GAAG;AAC1E,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,KAAK,IAAI;AAAA,EACzB;AACA,SAAO,QAAQ,IAAI;AACrB;AAMO,SAAS,MAAY;AAC1B,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,mDAAmD;AACjE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,cAAc,gBAAgB;AACpC,QAAM,SAAS,mBAAmB,aAAa,WAAW;AAE1D,MAAI,CAAC,OAAO,SAAS;AACnB,YAAQ,MAAM,2BAA2B,OAAO,KAAK,EAAE;AACvD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,OAAO,MAAM,WAAW,GAAG;AAC7B;AAAA,EACF;AAEA,UAAQ,IAAI,8BAA8B,WAAW,IAAI,OAAO,OAAO,GAAG;AAC1E,aAAW,QAAQ,OAAO,OAAO;AAC/B,YAAQ,IAAI,aAAa,IAAI,EAAE;AAAA,EACjC;AACF;AAMO,SAAS,SAAe;AAC7B,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,mDAAmD;AACjE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,cAAc,gBAAgB;AACpC,QAAM,SAAS,wBAAwB,aAAa,WAAW;AAE/D,MAAI,CAAC,OAAO,SAAS;AAEnB;AAAA,EACF;AAEA,MAAI,OAAO,aAAa,SAAS,GAAG;AAClC,YAAQ,IAAI,4BAA4B,WAAW,GAAG;AACtD,eAAW,QAAQ,OAAO,cAAc;AACtC,cAAQ,IAAI,aAAa,IAAI,EAAE;AAAA,IACjC;AAAA,EACF;AACF;","names":["existsSync","readFileSync","join","existsSync","rmSync","join","existsSync","mkdirSync","readFileSync","dirname","join","require","join","existsSync","rmSync","join","existsSync","readFileSync"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leeovery/claude-manager",
3
- "version": "2.0.16",
3
+ "version": "2.0.18",
4
4
  "description": "Plugin manager for Claude Code skills and commands",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",