@tkpdx01/ccc 1.2.2
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/.github/workflows/npm-publish.yml +30 -0
- package/Claude Code settings.txt +777 -0
- package/README.md +62 -0
- package/index.js +76 -0
- package/package.json +39 -0
- package/postinstall.js +18 -0
- package/src/commands/delete.js +66 -0
- package/src/commands/edit.js +106 -0
- package/src/commands/help.js +52 -0
- package/src/commands/import.js +365 -0
- package/src/commands/index.js +10 -0
- package/src/commands/list.js +53 -0
- package/src/commands/new.js +143 -0
- package/src/commands/show.js +68 -0
- package/src/commands/sync.js +168 -0
- package/src/commands/use.js +19 -0
- package/src/config.js +9 -0
- package/src/launch.js +69 -0
- package/src/parsers.js +154 -0
- package/src/profiles.js +123 -0
- package/src/utils.js +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# claude-code-launcher (ccc)
|
|
2
|
+
|
|
3
|
+
Claude Code Settings Launcher - Launch Claude Code with different settings profiles. Run multiple Claude instances with different API configurations simultaneously.
|
|
4
|
+
|
|
5
|
+
Claude Code 设置启动器 - 使用不同的 settings profile 文件启动 Claude Code,可同时运行多个使用不同 API 配置的 Claude 实例。
|
|
6
|
+
|
|
7
|
+
## Compatibility / 兼容性
|
|
8
|
+
|
|
9
|
+
Tested export file versions / 已测试的导出文件版本:
|
|
10
|
+
|
|
11
|
+
| Tool | Version | Export Format |
|
|
12
|
+
|------|---------|---------------|
|
|
13
|
+
| [cc-switch](https://github.com/farion1231/cc-switch) | 3.8.2 | SQL |
|
|
14
|
+
| [All API Hub](https://github.com/qixing-jk/all-api-hub) | v2.26.1 | JSON |
|
|
15
|
+
|
|
16
|
+
## Installation / 安装
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install -g @tkpdx01/ccc
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage / 使用
|
|
23
|
+
|
|
24
|
+
### Launch / 启动
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
ccc # Default profile or select / 使用默认或交互选择
|
|
28
|
+
ccc <profile> # Specific profile / 指定配置
|
|
29
|
+
ccc -d # With --dangerously-skip-permissions
|
|
30
|
+
ccc <profile> -d # Combine both / 组合使用
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Manage Profiles / 管理配置
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
ccc list # List profiles / 列出配置
|
|
37
|
+
ccc list -v # List with URLs / 显示 API URLs
|
|
38
|
+
ccc show [profile] # Show config / 显示完整配置
|
|
39
|
+
ccc use <profile> # Set default / 设置默认
|
|
40
|
+
ccc new [name] # Create from template / 从模板创建
|
|
41
|
+
ccc import # Import from cc-switch SQL or All API Hub JSON / 导入 cc-switch SQL 或 All API Hub JSON
|
|
42
|
+
ccc sync [profile] # Sync from template / 从模板同步
|
|
43
|
+
ccc sync -a # Sync all / 同步所有
|
|
44
|
+
ccc edit [profile] # Edit profile / 编辑配置
|
|
45
|
+
ccc delete [profile] # Delete profile / 删除配置
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Features / 功能
|
|
49
|
+
|
|
50
|
+
- **Multiple Profiles / 多配置**: Manage different API configurations
|
|
51
|
+
- **Template Support / 模板**: Based on `~/.claude/settings.json`
|
|
52
|
+
- **Smart Import / 智能导入**: Auto-detect API URL and token
|
|
53
|
+
- **Sync Settings / 同步**: Update from template, preserve credentials
|
|
54
|
+
|
|
55
|
+
## Storage / 存储
|
|
56
|
+
|
|
57
|
+
- Profiles: `~/.ccc/profiles/*.json`
|
|
58
|
+
- Template: `~/.claude/settings.json`
|
|
59
|
+
|
|
60
|
+
## License / 许可证
|
|
61
|
+
|
|
62
|
+
MIT
|
package/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import {
|
|
6
|
+
getDefaultProfile,
|
|
7
|
+
profileExists,
|
|
8
|
+
resolveProfile
|
|
9
|
+
} from './src/profiles.js';
|
|
10
|
+
import { launchClaude, selectProfile } from './src/launch.js';
|
|
11
|
+
import {
|
|
12
|
+
listCommand,
|
|
13
|
+
useCommand,
|
|
14
|
+
showCommand,
|
|
15
|
+
importCommand,
|
|
16
|
+
newCommand,
|
|
17
|
+
syncCommand,
|
|
18
|
+
editCommand,
|
|
19
|
+
deleteCommand,
|
|
20
|
+
helpCommand
|
|
21
|
+
} from './src/commands/index.js';
|
|
22
|
+
|
|
23
|
+
const program = new Command();
|
|
24
|
+
|
|
25
|
+
// 主程序
|
|
26
|
+
program
|
|
27
|
+
.name('ccc')
|
|
28
|
+
.description('Claude Code Settings Launcher - 管理多个 Claude Code 配置文件')
|
|
29
|
+
.version('0.2.0');
|
|
30
|
+
|
|
31
|
+
// 注册所有命令
|
|
32
|
+
listCommand(program);
|
|
33
|
+
useCommand(program);
|
|
34
|
+
showCommand(program);
|
|
35
|
+
importCommand(program);
|
|
36
|
+
newCommand(program);
|
|
37
|
+
syncCommand(program);
|
|
38
|
+
editCommand(program);
|
|
39
|
+
deleteCommand(program);
|
|
40
|
+
helpCommand(program);
|
|
41
|
+
|
|
42
|
+
// ccc <profile> 或 ccc (无参数)
|
|
43
|
+
// 使用 -d 或 --ddd 启用 dangerously-skip-permissions
|
|
44
|
+
program
|
|
45
|
+
.argument('[profile]', '要使用的 profile 名称或序号')
|
|
46
|
+
.option('-d, --ddd', '启用 --dangerously-skip-permissions 参数')
|
|
47
|
+
.action(async (profile, options) => {
|
|
48
|
+
const dangerouslySkipPermissions = options.ddd || false;
|
|
49
|
+
|
|
50
|
+
if (profile) {
|
|
51
|
+
// 检查是否是子命令
|
|
52
|
+
if (['list', 'ls', 'use', 'show', 'import', 'if', 'new', 'sync', 'edit', 'delete', 'rm', 'help'].includes(profile)) {
|
|
53
|
+
return; // 让子命令处理
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 解析序号或名称
|
|
57
|
+
const resolvedProfile = resolveProfile(profile);
|
|
58
|
+
if (resolvedProfile) {
|
|
59
|
+
launchClaude(resolvedProfile, dangerouslySkipPermissions);
|
|
60
|
+
} else {
|
|
61
|
+
console.log(chalk.red(`Profile "${profile}" 不存在`));
|
|
62
|
+
console.log(chalk.yellow(`使用 "ccc list" 查看可用的 profiles`));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
// 无参数,检查默认或交互选择
|
|
67
|
+
const defaultProfile = getDefaultProfile();
|
|
68
|
+
if (defaultProfile && profileExists(defaultProfile)) {
|
|
69
|
+
launchClaude(defaultProfile, dangerouslySkipPermissions);
|
|
70
|
+
} else {
|
|
71
|
+
await selectProfile(dangerouslySkipPermissions);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
program.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tkpdx01/ccc",
|
|
3
|
+
"version": "1.2.2",
|
|
4
|
+
"description": "Claude Code Settings Launcher - Manage multiple Claude Code profiles",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"ccc": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "node index.js --help",
|
|
12
|
+
"postinstall": "node postinstall.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"claude",
|
|
16
|
+
"claude-code",
|
|
17
|
+
"cli",
|
|
18
|
+
"settings",
|
|
19
|
+
"launcher",
|
|
20
|
+
"profile",
|
|
21
|
+
"anthropic"
|
|
22
|
+
],
|
|
23
|
+
"author": "tkpdx01",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/tkpdx01/claude-code-launcher.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/tkpdx01/claude-code-launcher/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/tkpdx01/claude-code-launcher#readme",
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"chalk": "^5.3.0",
|
|
35
|
+
"cli-table3": "^0.6.5",
|
|
36
|
+
"commander": "^12.0.0",
|
|
37
|
+
"inquirer": "^9.2.0"
|
|
38
|
+
}
|
|
39
|
+
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const message = `
|
|
4
|
+
╔════════════════════════════════════════════════════════════╗
|
|
5
|
+
║ ║
|
|
6
|
+
║ claude-code-launcher installed successfully! ║
|
|
7
|
+
║ ║
|
|
8
|
+
║ Command: ccc ║
|
|
9
|
+
║ ║
|
|
10
|
+
║ Quick start: ║
|
|
11
|
+
║ ccc help - Show all commands ║
|
|
12
|
+
║ ccc new - Create a new profile ║
|
|
13
|
+
║ ccc import - Import from pasted text ║
|
|
14
|
+
║ ║
|
|
15
|
+
╚════════════════════════════════════════════════════════════╝
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
console.log(message);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import {
|
|
4
|
+
getProfiles,
|
|
5
|
+
getDefaultProfile,
|
|
6
|
+
profileExists,
|
|
7
|
+
deleteProfile,
|
|
8
|
+
clearDefaultProfile
|
|
9
|
+
} from '../profiles.js';
|
|
10
|
+
|
|
11
|
+
export function deleteCommand(program) {
|
|
12
|
+
program
|
|
13
|
+
.command('delete [profile]')
|
|
14
|
+
.alias('rm')
|
|
15
|
+
.description('删除 profile')
|
|
16
|
+
.action(async (profile) => {
|
|
17
|
+
const profiles = getProfiles();
|
|
18
|
+
|
|
19
|
+
if (profiles.length === 0) {
|
|
20
|
+
console.log(chalk.yellow('没有可用的 profiles'));
|
|
21
|
+
process.exit(0);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// 如果没有指定 profile,交互选择
|
|
25
|
+
if (!profile) {
|
|
26
|
+
const { selectedProfile } = await inquirer.prompt([
|
|
27
|
+
{
|
|
28
|
+
type: 'list',
|
|
29
|
+
name: 'selectedProfile',
|
|
30
|
+
message: '选择要删除的配置:',
|
|
31
|
+
choices: profiles
|
|
32
|
+
}
|
|
33
|
+
]);
|
|
34
|
+
profile = selectedProfile;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!profileExists(profile)) {
|
|
38
|
+
console.log(chalk.red(`Profile "${profile}" 不存在`));
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const { confirm } = await inquirer.prompt([
|
|
43
|
+
{
|
|
44
|
+
type: 'confirm',
|
|
45
|
+
name: 'confirm',
|
|
46
|
+
message: `确定要删除 "${profile}" 吗?`,
|
|
47
|
+
default: false
|
|
48
|
+
}
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
if (!confirm) {
|
|
52
|
+
console.log(chalk.yellow('已取消'));
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
deleteProfile(profile);
|
|
57
|
+
|
|
58
|
+
// 如果删除的是默认 profile,清除默认设置
|
|
59
|
+
if (getDefaultProfile() === profile) {
|
|
60
|
+
clearDefaultProfile();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
console.log(chalk.green(`✓ Profile "${profile}" 已删除`));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import {
|
|
5
|
+
getProfiles,
|
|
6
|
+
getDefaultProfile,
|
|
7
|
+
profileExists,
|
|
8
|
+
getProfilePath,
|
|
9
|
+
readProfile,
|
|
10
|
+
saveProfile,
|
|
11
|
+
setDefaultProfile,
|
|
12
|
+
deleteProfile,
|
|
13
|
+
resolveProfile
|
|
14
|
+
} from '../profiles.js';
|
|
15
|
+
|
|
16
|
+
export function editCommand(program) {
|
|
17
|
+
program
|
|
18
|
+
.command('edit [profile]')
|
|
19
|
+
.description('编辑 profile 配置')
|
|
20
|
+
.action(async (profile) => {
|
|
21
|
+
const profiles = getProfiles();
|
|
22
|
+
|
|
23
|
+
if (profiles.length === 0) {
|
|
24
|
+
console.log(chalk.yellow('没有可用的 profiles'));
|
|
25
|
+
console.log(chalk.gray('使用 "ccc import" 导入配置'));
|
|
26
|
+
process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 如果没有指定 profile,交互选择
|
|
30
|
+
if (!profile) {
|
|
31
|
+
const { selectedProfile } = await inquirer.prompt([
|
|
32
|
+
{
|
|
33
|
+
type: 'list',
|
|
34
|
+
name: 'selectedProfile',
|
|
35
|
+
message: '选择要编辑的配置:',
|
|
36
|
+
choices: profiles
|
|
37
|
+
}
|
|
38
|
+
]);
|
|
39
|
+
profile = selectedProfile;
|
|
40
|
+
} else {
|
|
41
|
+
// 支持序号或名称
|
|
42
|
+
const resolved = resolveProfile(profile);
|
|
43
|
+
if (!resolved) {
|
|
44
|
+
console.log(chalk.red(`Profile "${profile}" 不存在`));
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
profile = resolved;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const currentSettings = readProfile(profile);
|
|
51
|
+
|
|
52
|
+
console.log(chalk.cyan(`\n当前配置 (${profile}):`));
|
|
53
|
+
console.log(chalk.gray(` API URL: ${currentSettings.apiUrl || '未设置'}`));
|
|
54
|
+
console.log(chalk.gray(` API Key: ${currentSettings.apiKey ? currentSettings.apiKey.substring(0, 10) + '...' : '未设置'}`));
|
|
55
|
+
console.log();
|
|
56
|
+
|
|
57
|
+
const { apiUrl, apiKey, newName } = await inquirer.prompt([
|
|
58
|
+
{
|
|
59
|
+
type: 'input',
|
|
60
|
+
name: 'apiUrl',
|
|
61
|
+
message: 'API URL:',
|
|
62
|
+
default: currentSettings.apiUrl || ''
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: 'input',
|
|
66
|
+
name: 'apiKey',
|
|
67
|
+
message: 'API Key:',
|
|
68
|
+
default: currentSettings.apiKey || ''
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
type: 'input',
|
|
72
|
+
name: 'newName',
|
|
73
|
+
message: 'Profile 名称:',
|
|
74
|
+
default: profile
|
|
75
|
+
}
|
|
76
|
+
]);
|
|
77
|
+
|
|
78
|
+
const newSettings = {
|
|
79
|
+
...currentSettings,
|
|
80
|
+
apiUrl,
|
|
81
|
+
apiKey
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// 如果重命名
|
|
85
|
+
if (newName && newName !== profile) {
|
|
86
|
+
const newPath = getProfilePath(newName);
|
|
87
|
+
if (fs.existsSync(newPath)) {
|
|
88
|
+
console.log(chalk.red(`Profile "${newName}" 已存在`));
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
saveProfile(newName, newSettings);
|
|
92
|
+
deleteProfile(profile);
|
|
93
|
+
|
|
94
|
+
// 更新默认 profile
|
|
95
|
+
if (getDefaultProfile() === profile) {
|
|
96
|
+
setDefaultProfile(newName);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(chalk.green(`\n✓ Profile 已重命名为 "${newName}" 并保存`));
|
|
100
|
+
} else {
|
|
101
|
+
saveProfile(profile, newSettings);
|
|
102
|
+
console.log(chalk.green(`\n✓ Profile "${profile}" 已更新`));
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
|
|
3
|
+
export function showHelp() {
|
|
4
|
+
console.log(chalk.cyan.bold('\n CCC - Claude Code Settings Launcher\n'));
|
|
5
|
+
console.log(chalk.white(' 管理多个 Claude Code 配置文件,快速切换不同的 API 设置\n'));
|
|
6
|
+
|
|
7
|
+
console.log(chalk.yellow(' 启动命令:'));
|
|
8
|
+
console.log(chalk.gray(' ccc ') + '使用默认配置启动,无默认则交互选择');
|
|
9
|
+
console.log(chalk.gray(' ccc <profile> ') + '使用指定配置启动(支持名称或序号)');
|
|
10
|
+
console.log(chalk.gray(' ccc <序号> ') + '使用序号启动(如 ccc 1)');
|
|
11
|
+
console.log(chalk.gray(' ccc -d, --ddd ') + '启动时添加 --dangerously-skip-permissions');
|
|
12
|
+
console.log();
|
|
13
|
+
|
|
14
|
+
console.log(chalk.yellow(' 管理命令:'));
|
|
15
|
+
console.log(chalk.gray(' ccc list, ls ') + '列出所有配置(带序号,按 a-z 排序)');
|
|
16
|
+
console.log(chalk.gray(' ccc show [profile] ') + '显示完整配置');
|
|
17
|
+
console.log(chalk.gray(' ccc use <profile> ') + '设置默认配置');
|
|
18
|
+
console.log(chalk.gray(' ccc new [name] ') + '基于模板创建新配置');
|
|
19
|
+
console.log(chalk.gray(' ccc import <file> ') + '从文件导入(自动识别格式)');
|
|
20
|
+
console.log(chalk.gray(' ccc sync [profile] ') + '同步模板设置(保留 API 配置)');
|
|
21
|
+
console.log(chalk.gray(' ccc sync -a, --all ') + '同步所有配置');
|
|
22
|
+
console.log(chalk.gray(' ccc edit [profile] ') + '编辑配置');
|
|
23
|
+
console.log(chalk.gray(' ccc delete, rm [name] ') + '删除配置');
|
|
24
|
+
console.log(chalk.gray(' ccc help ') + '显示此帮助信息');
|
|
25
|
+
console.log();
|
|
26
|
+
|
|
27
|
+
console.log(chalk.yellow(' 配置存储:'));
|
|
28
|
+
console.log(chalk.gray(' ~/.ccc/profiles/ ') + '配置文件目录');
|
|
29
|
+
console.log(chalk.gray(' ~/.claude/settings.json') + '模板来源(用于 ccc new)');
|
|
30
|
+
console.log();
|
|
31
|
+
|
|
32
|
+
console.log(chalk.yellow(' 支持的导入格式:'));
|
|
33
|
+
console.log(chalk.gray(' CC-Switch SQL ') + '自动识别 INSERT INTO providers 语句');
|
|
34
|
+
console.log(chalk.gray(' All API Hub JSON ') + '自动识别 accounts.accounts 结构');
|
|
35
|
+
console.log();
|
|
36
|
+
|
|
37
|
+
console.log(chalk.yellow(' 示例:'));
|
|
38
|
+
console.log(chalk.gray(' ccc ls ') + '查看配置列表和序号');
|
|
39
|
+
console.log(chalk.gray(' ccc 3 ') + '启动第 3 个配置');
|
|
40
|
+
console.log(chalk.gray(' ccc 3 -d ') + '启动第 3 个配置 + 跳过权限');
|
|
41
|
+
console.log(chalk.gray(' ccc kfc ') + '使用名称启动');
|
|
42
|
+
console.log(chalk.gray(' ccc import export.sql ') + '从文件导入配置');
|
|
43
|
+
console.log();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function helpCommand(program) {
|
|
47
|
+
program
|
|
48
|
+
.command('help')
|
|
49
|
+
.description('显示帮助信息')
|
|
50
|
+
.action(showHelp);
|
|
51
|
+
}
|
|
52
|
+
|