UNPKG

claude-keys-manager

Version:

Claude Code API Key manager with template and repository management tools

444 lines (395 loc) 14.5 kB
#!/usr/bin/env node const { program } = require('commander'); const inquirer = require('inquirer'); const chalk = require('chalk'); const ClaudeCodeManager = require('../index'); const KeyManager = require('../lib/keyManager'); const package = require('../package.json'); program .name('claude-get') .description('Claude Code Manager - 轻量级代码模板和项目管理工具') .version(package.version); program .argument('[repository]', 'GitHub仓库URL或简化格式 (owner/repo)') .option('-d, --dir <directory>', '目标目录') .option('-i, --interactive', '交互式模式') .description('下载GitHub仓库') .action(async (repository, options) => { try { const manager = new ClaudeCodeManager(); // 交互式模式 if (options.interactive || !repository) { const answers = await inquirer.prompt([ { type: 'input', name: 'repository', message: '请输入GitHub仓库URL或简化格式 (owner/repo):', when: !repository, validate: (input) => { if (!input.trim()) { return '仓库URL不能为空'; } return true; } }, { type: 'input', name: 'targetDir', message: '目标目录 (留空使用默认):', when: !options.dir } ]); repository = repository || answers.repository; options.dir = options.dir || answers.targetDir; } // 执行主要功能 await manager.run(repository, { targetDir: options.dir }); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }); program .command('template') .description('模板管理') .addCommand( program.createCommand('create') .argument('<name>', '模板名称') .argument('<source>', '源目录路径') .description('创建代码模板') .action(async (name, source) => { try { const manager = new ClaudeCodeManager(); await manager.createTemplate(name, source); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ) .addCommand( program.createCommand('use') .argument('<name>', '模板名称') .option('-d, --dir <directory>', '目标目录') .description('使用代码模板') .action(async (name, options) => { try { const manager = new ClaudeCodeManager(); await manager.useTemplate(name, options.dir); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ) .addCommand( program.createCommand('list') .description('列出所有模板') .action(async () => { try { const manager = new ClaudeCodeManager(); const templates = await manager.listTemplates(); if (templates.length === 0) { console.log(chalk.yellow('📝 暂无可用模板')); console.log(chalk.gray('使用 claude-get template create <name> <source> 创建模板')); return; } console.log(chalk.blue.bold('📝 可用模板:')); templates.forEach(template => { console.log(chalk.green(` • ${template.name}`)); console.log(chalk.gray(` 创建时间: ${new Date(template.created).toLocaleString()}`)); }); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ); program .command('quick') .description('快速下载常用项目模板') .action(async () => { try { const { template } = await inquirer.prompt([ { type: 'list', name: 'template', message: '选择项目模板:', choices: [ { name: 'React App (Create React App)', value: 'facebook/create-react-app' }, { name: 'Vue.js 3 (Vue CLI)', value: 'vuejs/vue-cli' }, { name: 'Next.js Starter', value: 'vercel/next.js' }, { name: 'Express.js Starter', value: 'expressjs/express' }, { name: 'Node.js TypeScript Starter', value: 'microsoft/TypeScript-Node-Starter' }, { name: 'Python Flask Starter', value: 'pallets/flask' }, { name: 'Django Starter', value: 'django/django' }, { name: '自定义输入', value: 'custom' } ] } ]); let repoUrl = template; if (template === 'custom') { const { customRepo } = await inquirer.prompt([ { type: 'input', name: 'customRepo', message: '请输入GitHub仓库URL或简化格式:', validate: (input) => input.trim() ? true : '仓库URL不能为空' } ]); repoUrl = customRepo; } const manager = new ClaudeCodeManager(); await manager.run(repoUrl); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }); program .command('key') .description('Claude Code API Key管理') .addCommand( program.createCommand('add') .description('添加新的API Key') .action(async () => { try { const keyManager = new KeyManager(); await keyManager.init(); const answers = await inquirer.prompt([ { type: 'input', name: 'name', message: '请输入Key名称:', validate: (input) => input.trim() ? true : 'Key名称不能为空' }, { type: 'password', name: 'key', message: '请输入API Key:', validate: (input) => input.trim() ? true : 'API Key不能为空' }, { type: 'input', name: 'description', message: '描述 (可选):', } ]); await keyManager.addKey(answers); console.log(chalk.green(`✅ Key "${answers.name}" 添加成功`)); // 询问是否立即验证 const { validate } = await inquirer.prompt([ { type: 'confirm', name: 'validate', message: '是否立即验证此Key?', default: true } ]); if (validate) { const keys = keyManager.listKeys(); const newKey = keys.find(k => k.name === answers.name); await keyManager.validateKey(newKey.id); } } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ) .addCommand( program.createCommand('list') .description('列出所有API Keys') .action(async () => { try { const keyManager = new KeyManager(); await keyManager.init(); const keys = keyManager.listKeys(); const stats = keyManager.getKeyStats(); console.log(chalk.blue.bold('\n🔑 API Keys 管理')); console.log(chalk.gray(`总计: ${stats.total} | 有效: ${stats.valid} | 无效: ${stats.invalid} | 未测试: ${stats.untested}`)); console.log(chalk.yellow(`当前使用: ${stats.currentKey}`)); console.log(chalk.gray(`总使用次数: ${stats.totalUsage}\n`)); if (keys.length === 0) { console.log(chalk.yellow('📝 暂无API Keys')); console.log(chalk.gray('使用 claude-get key add 添加新的Key')); return; } keys.forEach(key => { const status = key.isValid === true ? chalk.green('✅') : key.isValid === false ? chalk.red('❌') : chalk.gray('❓'); const current = key.isCurrent ? chalk.yellow(' (当前)') : ''; console.log(`${status} ${chalk.cyan(key.name)}${current}`); console.log(chalk.gray(` Key: ${key.key}`)); console.log(chalk.gray(` 描述: ${key.description || '无'}`)); console.log(chalk.gray(` 使用次数: ${key.usageCount} | 最后使用: ${key.lastUsed ? new Date(key.lastUsed).toLocaleString() : '从未使用'}`)); console.log(''); }); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ) .addCommand( program.createCommand('switch') .description('切换当前使用的API Key') .action(async () => { try { const keyManager = new KeyManager(); await keyManager.init(); const keys = keyManager.listKeys(); if (keys.length === 0) { console.log(chalk.yellow('暂无可用的API Keys')); return; } const { keyId } = await inquirer.prompt([ { type: 'list', name: 'keyId', message: '选择要使用的API Key:', choices: keys.map(key => ({ name: `${key.name} ${key.isCurrent ? '(当前)' : ''}`, value: key.id })) } ]); const switchedKey = await keyManager.switchKey(keyId); console.log(chalk.green(`✅ 已切换到Key: ${switchedKey.name}`)); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ) .addCommand( program.createCommand('test') .description('测试API Key功能') .option('-k, --key <keyId>', '指定要测试的Key ID') .option('-p, --prompt <prompt>', '自定义测试提示', 'Hello, Claude!') .action(async (options) => { try { const keyManager = new KeyManager(); await keyManager.init(); let keyId = options.key; if (!keyId) { const keys = keyManager.listKeys(); if (keys.length === 0) { console.log(chalk.yellow('暂无可用的API Keys')); return; } const { selectedKeyId } = await inquirer.prompt([ { type: 'list', name: 'selectedKeyId', message: '选择要测试的API Key:', choices: keys.map(key => ({ name: `${key.name} ${key.isCurrent ? '(当前)' : ''}`, value: key.id })) } ]); keyId = selectedKeyId; } console.log(chalk.blue(`🧪 测试提示: "${options.prompt}"`)); const result = await keyManager.testKey(keyId, options.prompt); console.log(chalk.green('\n✅ 测试结果:')); console.log(chalk.cyan(`响应: ${result.response}`)); console.log(chalk.gray(`Token使用: ${result.usage.total_tokens} (输入: ${result.usage.prompt_tokens}, 输出: ${result.usage.completion_tokens})`)); console.log(chalk.gray(`时间: ${new Date(result.timestamp).toLocaleString()}`)); } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ) .addCommand( program.createCommand('validate') .description('验证API Key有效性') .option('-a, --all', '验证所有Keys') .action(async (options) => { try { const keyManager = new KeyManager(); await keyManager.init(); const keys = keyManager.listKeys(); if (keys.length === 0) { console.log(chalk.yellow('暂无可用的API Keys')); return; } if (options.all) { console.log(chalk.blue('🔍 验证所有API Keys...')); for (const key of keys) { await keyManager.validateKey(key.id); } } else { const { keyId } = await inquirer.prompt([ { type: 'list', name: 'keyId', message: '选择要验证的API Key:', choices: keys.map(key => ({ name: `${key.name} ${key.isCurrent ? '(当前)' : ''}`, value: key.id })) } ]); await keyManager.validateKey(keyId); } } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ) .addCommand( program.createCommand('remove') .description('删除API Key') .action(async () => { try { const keyManager = new KeyManager(); await keyManager.init(); const keys = keyManager.listKeys(); if (keys.length === 0) { console.log(chalk.yellow('暂无可用的API Keys')); return; } const { keyId } = await inquirer.prompt([ { type: 'list', name: 'keyId', message: '选择要删除的API Key:', choices: keys.map(key => ({ name: `${key.name} ${key.isCurrent ? '(当前)' : ''}`, value: key.id })) } ]); const keyToRemove = keys.find(k => k.id === keyId); const { confirm } = await inquirer.prompt([ { type: 'confirm', name: 'confirm', message: `确认删除Key "${keyToRemove.name}"?`, default: false } ]); if (confirm) { await keyManager.removeKey(keyId); console.log(chalk.green(`✅ Key "${keyToRemove.name}" 已删除`)); } else { console.log(chalk.gray('操作已取消')); } } catch (error) { console.error(chalk.red.bold(`❌ 错误: ${error.message}`)); process.exit(1); } }) ); // 解析命令行参数 program.parse(); // 如果没有提供命令,显示帮助 if (!process.argv.slice(2).length) { program.outputHelp(); }