@leeovery/claude-manager 2.0.9 → 2.0.11

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
@@ -58,20 +58,18 @@ The plugin's postinstall script copies assets to `.claude/`. That's it.
58
58
 
59
59
  ### pnpm Users
60
60
 
61
- pnpm v10+ blocks postinstall scripts by default. Use `--allow-build` to approve and run in one command:
61
+ pnpm doesn't expose binaries from transitive dependencies, so install the manager directly alongside plugins:
62
62
 
63
63
  ```bash
64
- pnpm add -D --allow-build=@leeovery/claude-laravel @leeovery/claude-laravel
64
+ pnpm add -D @leeovery/claude-manager @leeovery/claude-laravel
65
+ pnpm approve-builds # approve when prompted
66
+ pnpm install # triggers postinstall
65
67
  ```
66
68
 
67
- **Important:** pnpm's `preuninstall` hook is broken ([issue #3276](https://github.com/pnpm/pnpm/issues/3276)). To remove a plugin cleanly:
69
+ **Removal:** pnpm's `preuninstall` hook is broken ([issue #3276](https://github.com/pnpm/pnpm/issues/3276)). Remove files first:
68
70
 
69
71
  ```bash
70
- # Remove files first (while manager still installed)
71
- npx claude-plugins remove @leeovery/claude-laravel
72
-
73
- # Then remove the package
74
- pnpm remove @leeovery/claude-laravel
72
+ npx claude-plugins remove @leeovery/claude-laravel && pnpm remove @leeovery/claude-laravel
75
73
  ```
76
74
 
77
75
  ## How It Works
@@ -136,13 +134,13 @@ Want to create your own skill or command packages?
136
134
  "@leeovery/claude-manager": "^2.0.0"
137
135
  },
138
136
  "scripts": {
139
- "postinstall": "node -e \"require('@leeovery/claude-manager').add()\"",
140
- "preuninstall": "node -e \"require('@leeovery/claude-manager').remove()\""
137
+ "postinstall": "claude-plugins add",
138
+ "preuninstall": "claude-plugins remove"
141
139
  }
142
140
  }
143
141
  ```
144
142
 
145
- The `postinstall` script copies assets when the plugin is installed. The `preuninstall` script cleans up when the plugin is removed. Using `node -e` ensures compatibility with all package managers (npm, pnpm, yarn).
143
+ The `postinstall` script copies assets when the plugin is installed. The `preuninstall` script cleans up when the plugin is removed.
146
144
 
147
145
  ### Plugin Structure
148
146
 
@@ -220,7 +218,7 @@ ls -la .claude/hooks/
220
218
 
221
219
  Verify the plugin's package.json has:
222
220
  - `@leeovery/claude-manager` as a dependency
223
- - `postinstall` and `preuninstall` scripts using `node -e`
221
+ - `postinstall` and `preuninstall` scripts
224
222
  - A `skills/`, `commands/`, `agents/`, or `hooks/` directory with content
225
223
 
226
224
  ## Requirements
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 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 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\n delete manifest.plugins[packageName];\n writeManifest(projectRoot, manifest);\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 writeManifest(projectRoot, manifest);\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","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 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 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\n delete manifest.plugins[packageName];\n writeManifest(projectRoot, manifest);\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","dirname","join","existsSync","rmSync","join","existsSync","mkdirSync","readFileSync","dirname","join","require","join","existsSync","rmSync","dirname","join","readFileSync","existsSync"]}
package/dist/index.js CHANGED
@@ -44,7 +44,14 @@ function addPlugin(projectRoot, packageName, version, files) {
44
44
  function removePlugin(projectRoot, packageName) {
45
45
  const manifest = readManifest(projectRoot);
46
46
  delete manifest.plugins[packageName];
47
- writeManifest(projectRoot, manifest);
47
+ if (Object.keys(manifest.plugins).length === 0) {
48
+ const manifestPath = join(projectRoot, ".claude", MANIFEST_FILE);
49
+ if (existsSync(manifestPath)) {
50
+ rmSync(manifestPath);
51
+ }
52
+ } else {
53
+ writeManifest(projectRoot, manifest);
54
+ }
48
55
  }
49
56
  function getPlugins(projectRoot) {
50
57
  return readManifest(projectRoot).plugins;
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 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\n delete manifest.plugins[packageName];\n writeManifest(projectRoot, manifest);\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 writeManifest(projectRoot, manifest);\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 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\n delete manifest.plugins[packageName];\n writeManifest(projectRoot, manifest);\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leeovery/claude-manager",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "packageManager": "pnpm@10.27.0",
5
5
  "description": "Plugin manager for Claude Code skills and commands",
6
6
  "type": "module",