Features: - 30+ Custom Skills (cognitive, development, UI/UX, autonomous agents) - RalphLoop autonomous agent integration - Multi-AI consultation (Qwen) - Agent management system with sync capabilities - Custom hooks for session management - MCP servers integration - Plugin marketplace setup - Comprehensive installation script Components: - Skills: always-use-superpowers, ralph, brainstorming, ui-ux-pro-max, etc. - Agents: 100+ agents across engineering, marketing, product, etc. - Hooks: session-start-superpowers, qwen-consult, ralph-auto-trigger - Commands: /brainstorm, /write-plan, /execute-plan - MCP Servers: zai-mcp-server, web-search-prime, web-reader, zread - Binaries: ralphloop wrapper Installation: ./supercharge.sh
386 lines
12 KiB
JavaScript
386 lines
12 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Claude Code Plugin CLI
|
|
*
|
|
* Command-line interface for managing Claude Code plugins
|
|
* Inspired by Conduit's CLI interface
|
|
*/
|
|
|
|
import { PluginManager } from './plugin-manager'
|
|
import { HookSystem } from './hook-system'
|
|
import { SecurityManager } from './security'
|
|
import { resolve } from 'path'
|
|
|
|
// ============================================================================
|
|
// CLI CLASS
|
|
// ============================================================================
|
|
|
|
class PluginCLI {
|
|
private pluginManager: PluginManager
|
|
private hookSystem: HookSystem
|
|
private security: SecurityManager
|
|
|
|
constructor() {
|
|
const claudeDir = process.env.CLAUDE_DIR || resolve(process.env.HOME || '', '.claude')
|
|
this.pluginManager = new PluginManager(claudeDir)
|
|
this.hookSystem = new HookSystem(claudeDir)
|
|
this.security = new SecurityManager()
|
|
}
|
|
|
|
async run(args: string[]): Promise<void> {
|
|
const [command, ...rest] = args
|
|
|
|
try {
|
|
await this.initialize()
|
|
|
|
switch (command) {
|
|
case 'discover':
|
|
case 'list':
|
|
await this.discover(rest[0])
|
|
break
|
|
|
|
case 'install':
|
|
await this.install(rest[0], rest[1])
|
|
break
|
|
|
|
case 'install-github':
|
|
await this.installFromGitHub(rest[0])
|
|
break
|
|
|
|
case 'uninstall':
|
|
await this.uninstall(rest[0], rest[1])
|
|
break
|
|
|
|
case 'enable':
|
|
await this.enable(rest[0], rest[1])
|
|
break
|
|
|
|
case 'disable':
|
|
await this.disable(rest[0], rest[1])
|
|
break
|
|
|
|
case 'update':
|
|
await this.update(rest[0], rest[1])
|
|
break
|
|
|
|
case 'info':
|
|
await this.info(rest[0])
|
|
break
|
|
|
|
case 'hooks':
|
|
await this.listHooks(rest[0])
|
|
break
|
|
|
|
case 'add-marketplace':
|
|
await this.addMarketplace(rest[0], rest[1])
|
|
break
|
|
|
|
case 'validate':
|
|
await this.validate(rest[0])
|
|
break
|
|
|
|
default:
|
|
this.showHelp()
|
|
}
|
|
} catch (error) {
|
|
console.error(`❌ Error: ${error instanceof Error ? error.message : String(error)}`)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
private async initialize(): Promise<void> {
|
|
await this.pluginManager.initialize()
|
|
await this.hookSystem.initialize()
|
|
}
|
|
|
|
// ============================================================================
|
|
// COMMANDS
|
|
// ============================================================================
|
|
|
|
private async discover(query?: string): Promise<void> {
|
|
console.log('🔍 Discovering plugins...\n')
|
|
|
|
const plugins = await this.pluginManager.discoverPlugins(query)
|
|
|
|
if (plugins.length === 0) {
|
|
console.log('No plugins found.')
|
|
return
|
|
}
|
|
|
|
console.log(`Found ${plugins.length} plugin(s):\n`)
|
|
|
|
for (const plugin of plugins) {
|
|
console.log(`📦 ${plugin.name}`)
|
|
console.log(` Description: ${plugin.description}`)
|
|
console.log(` Version: ${plugin.version}`)
|
|
console.log(` Author: ${plugin.author}`)
|
|
console.log(` Source: ${plugin.source}`)
|
|
console.log('')
|
|
}
|
|
}
|
|
|
|
private async install(marketplace: string, pluginName?: string): Promise<void> {
|
|
if (!marketplace) {
|
|
throw new Error('Usage: claude-plugin install <marketplace> [plugin-name]')
|
|
}
|
|
|
|
if (!pluginName) {
|
|
// Discover plugins in marketplace
|
|
const plugins = await this.pluginManager.discoverPlugins()
|
|
|
|
const marketplacePlugins = plugins.filter(p => p.source === marketplace)
|
|
|
|
if (marketplacePlugins.length === 0) {
|
|
console.log(`No plugins found in marketplace "${marketplace}"`)
|
|
return
|
|
}
|
|
|
|
console.log(`\n📦 Available plugins in "${marketplace}":\n`)
|
|
marketplacePlugins.forEach(p => {
|
|
console.log(` • ${p.name} - ${p.description}`)
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
console.log(`📦 Installing ${pluginName} from ${marketplace}...`)
|
|
|
|
const plugin = await this.pluginManager.installPlugin(marketplace, pluginName)
|
|
|
|
console.log(`\n✓ Successfully installed ${plugin.metadata.name} v${plugin.version}`)
|
|
console.log(` Location: ${plugin.installPath}`)
|
|
console.log(` Permissions: ${plugin.metadata.claude.permissions.join(', ')}`)
|
|
}
|
|
|
|
private async installFromGitHub(repo: string): Promise<void> {
|
|
if (!repo) {
|
|
throw new Error('Usage: claude-plugin install-github <user/repo>')
|
|
}
|
|
|
|
console.log(`📦 Installing plugin from GitHub: ${repo}...`)
|
|
|
|
const plugin = await this.pluginManager.installFromGitHub(repo)
|
|
|
|
console.log(`\n✓ Successfully installed ${plugin.metadata.name} v${plugin.version}`)
|
|
console.log(` Location: ${plugin.installPath}`)
|
|
console.log(` Permissions: ${plugin.metadata.claude.permissions.join(', ')}`)
|
|
}
|
|
|
|
private async uninstall(pluginName: string, marketplace?: string): Promise<void> {
|
|
if (!pluginName) {
|
|
throw new Error('Usage: claude-plugin uninstall <plugin-name> [marketplace]')
|
|
}
|
|
|
|
console.log(`🗑️ Uninstalling ${pluginName}...`)
|
|
|
|
await this.pluginManager.uninstallPlugin(pluginName, marketplace)
|
|
|
|
console.log(`✓ Successfully uninstalled ${pluginName}`)
|
|
}
|
|
|
|
private async enable(pluginName: string, marketplace?: string): Promise<void> {
|
|
if (!pluginName) {
|
|
throw new Error('Usage: claude-plugin enable <plugin-name> [marketplace]')
|
|
}
|
|
|
|
await this.pluginManager.enablePlugin(pluginName, marketplace)
|
|
console.log(`✓ Enabled ${pluginName}`)
|
|
}
|
|
|
|
private async disable(pluginName: string, marketplace?: string): Promise<void> {
|
|
if (!pluginName) {
|
|
throw new Error('Usage: claude-plugin disable <plugin-name> [marketplace]')
|
|
}
|
|
|
|
await this.pluginManager.disablePlugin(pluginName, marketplace)
|
|
console.log(`✓ Disabled ${pluginName}`)
|
|
}
|
|
|
|
private async update(pluginName: string, marketplace?: string): Promise<void> {
|
|
if (!pluginName) {
|
|
throw new Error('Usage: claude-plugin update <plugin-name> [marketplace]')
|
|
}
|
|
|
|
console.log(`🔄 Updating ${pluginName}...`)
|
|
|
|
await this.pluginManager.updatePlugin(pluginName, marketplace)
|
|
|
|
console.log(`✓ Updated ${pluginName}`)
|
|
}
|
|
|
|
private async info(pluginName: string): Promise<void> {
|
|
if (!pluginName) {
|
|
throw new Error('Usage: claude-plugin info <plugin-name>')
|
|
}
|
|
|
|
const installed = await this.pluginManager.loadInstalledPlugins()
|
|
|
|
for (const [key, plugins] of Object.entries(installed)) {
|
|
if (key.includes(pluginName)) {
|
|
const plugin = plugins[0]
|
|
|
|
console.log(`\n📦 ${plugin.metadata.name}`)
|
|
console.log(`Version: ${plugin.version}`)
|
|
console.log(`Description: ${plugin.metadata.description}`)
|
|
console.log(`Author: ${plugin.metadata.author}`)
|
|
console.log(`License: ${plugin.metadata.license || 'Not specified'}`)
|
|
console.log(`Repository: ${plugin.metadata.repository || 'Not specified'}`)
|
|
console.log(`\nInstalled:`)
|
|
console.log(` Path: ${plugin.installPath}`)
|
|
console.log(` Date: ${plugin.installedAt}`)
|
|
console.log(` Scope: ${plugin.scope}`)
|
|
console.log(` Enabled: ${plugin.enabled ? 'Yes' : 'No'}`)
|
|
console.log(`\nPermissions:`)
|
|
plugin.metadata.claude.permissions.forEach(perm => {
|
|
console.log(` • ${perm}`)
|
|
})
|
|
|
|
if (plugin.metadata.claude.commands?.length) {
|
|
console.log(`\nCommands (${plugin.metadata.claude.commands.length}):`)
|
|
plugin.metadata.claude.commands.forEach(cmd => {
|
|
console.log(` • ${cmd.name} - ${cmd.description}`)
|
|
})
|
|
}
|
|
|
|
if (plugin.metadata.claude.hooks?.length) {
|
|
console.log(`\nHooks (${plugin.metadata.claude.hooks.length}):`)
|
|
plugin.metadata.claude.hooks.forEach(hook => {
|
|
console.log(` • ${hook.event} - ${hook.handler}`)
|
|
})
|
|
}
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
console.log(`Plugin "${pluginName}" is not installed.`)
|
|
}
|
|
|
|
private async listHooks(event?: string): Promise<void> {
|
|
if (event) {
|
|
const hooks = await this.hookSystem.listHooksByEvent(event as any)
|
|
|
|
console.log(`\n🪝 Registered hooks for "${event}":\n`)
|
|
|
|
if (hooks.length === 0) {
|
|
console.log(' No hooks registered')
|
|
}
|
|
|
|
hooks.forEach((hook, i) => {
|
|
console.log(` ${i + 1}. ${hook.type}`)
|
|
if (hook.command) console.log(` Command: ${hook.command}`)
|
|
if (hook.module) console.log(` Module: ${hook.module}`)
|
|
if (hook.priority !== undefined) console.log(` Priority: ${hook.priority}`)
|
|
console.log(` Enabled: ${hook.enabled !== false}`)
|
|
})
|
|
} else {
|
|
const hooks = this.hookSystem.getRegisteredHooks()
|
|
|
|
console.log('\n🪝 All registered hooks:\n')
|
|
|
|
for (const [evt, hookList] of hooks.entries()) {
|
|
console.log(`${evt}: ${hookList.length} hook(s)`)
|
|
}
|
|
}
|
|
}
|
|
|
|
private async addMarketplace(name: string, url: string): Promise<void> {
|
|
if (!name || !url) {
|
|
throw new Error('Usage: claude-plugin add-marketplace <name> <github-url>')
|
|
}
|
|
|
|
// Parse GitHub URL
|
|
const match = url.match(/github\.com\/([^\/]+)\/([^\/]+)/)
|
|
|
|
if (!match) {
|
|
throw new Error('Invalid GitHub URL')
|
|
}
|
|
|
|
const [, owner, repo] = match
|
|
|
|
await this.pluginManager.addMarketplace(name, {
|
|
type: 'github',
|
|
repo: `${owner}/${repo}`,
|
|
})
|
|
|
|
console.log(`✓ Added marketplace "${name}"`)
|
|
}
|
|
|
|
private async validate(pluginPath: string): Promise<void> {
|
|
if (!pluginPath) {
|
|
throw new Error('Usage: claude-plugin validate <plugin-path>')
|
|
}
|
|
|
|
console.log(`🔍 Validating plugin at ${pluginPath}...`)
|
|
|
|
// Check for plugin.json
|
|
const pluginJsonPath = resolve(pluginPath, '.claude-plugin', 'plugin.json')
|
|
|
|
console.log(` ✓ Checking plugin.json...`)
|
|
|
|
// Validate structure
|
|
console.log(` ✓ Validating structure...`)
|
|
|
|
// Calculate integrity
|
|
const integrity = await this.security.calculateDirectoryIntegrity(pluginPath)
|
|
console.log(` ✓ Integrity: ${integrity.slice(0, 16)}...`)
|
|
|
|
console.log('\n✓ Plugin is valid!')
|
|
}
|
|
|
|
// ============================================================================
|
|
// HELP
|
|
// ============================================================================
|
|
|
|
private showHelp(): void {
|
|
console.log(`
|
|
Claude Code Plugin Manager
|
|
|
|
Commands:
|
|
discover [query] List available plugins (optional search query)
|
|
install <marketplace> Install a plugin from a marketplace
|
|
[plugin-name]
|
|
install-github <repo> Install a plugin directly from GitHub (user/repo)
|
|
uninstall <plugin-name> Uninstall a plugin
|
|
[marketplace]
|
|
enable <plugin-name> Enable a plugin
|
|
[marketplace]
|
|
disable <plugin-name> Disable a plugin
|
|
[marketplace]
|
|
update <plugin-name> Update a plugin to the latest version
|
|
[marketplace]
|
|
info <plugin-name> Show detailed information about a plugin
|
|
hooks [event] List registered hooks (optional: specific event)
|
|
add-marketplace <name> Add a new plugin marketplace
|
|
<github-url>
|
|
validate <path> Validate a plugin
|
|
|
|
Examples:
|
|
claude-plugin discover
|
|
claude-plugin discover git
|
|
claude-plugin install claude-plugins-official hookify
|
|
claude-plugin install-github username/my-plugin
|
|
claude-plugin uninstall hookify
|
|
claude-plugin info hookify
|
|
claude-plugin hooks PreFileEdit
|
|
|
|
For more information, visit: https://github.com/anthropics/claude-code
|
|
`)
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// MAIN
|
|
// ============================================================================
|
|
|
|
async function main() {
|
|
const cli = new PluginCLI()
|
|
await cli.run(process.argv.slice(2))
|
|
}
|
|
|
|
main().catch((error) => {
|
|
console.error('Fatal error:', error)
|
|
process.exit(1)
|
|
})
|