@tkpdx01/ccc 1.2.5 → 1.2.7
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/.claude/settings.local.json +34 -0
- package/Claude Code settings.txt +776 -776
- package/index.js +4 -4
- package/nul +1 -0
- package/package.json +39 -39
- package/settings-sample.json +4 -0
- package/src/commands/delete.js +66 -66
- package/src/commands/edit.js +120 -106
- package/src/commands/help.js +50 -52
- package/src/commands/import.js +356 -365
- package/src/commands/index.js +10 -10
- package/src/commands/list.js +46 -58
- package/src/commands/new.js +109 -143
- package/src/commands/show.js +68 -68
- package/src/commands/sync.js +93 -168
- package/src/commands/use.js +19 -19
- package/src/config.js +9 -9
- package/src/launch.js +69 -69
- package/src/parsers.js +154 -154
- package/src/profiles.js +182 -123
- package/src/utils.js +67 -82
package/src/commands/sync.js
CHANGED
|
@@ -1,168 +1,93 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import {
|
|
4
|
-
getProfiles,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.
|
|
15
|
-
.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
console.log(chalk.
|
|
29
|
-
process.exit(0);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
choices: [...profiles, new inquirer.Separator(), { name: '同步全部', value: '__all__' }]
|
|
95
|
-
}
|
|
96
|
-
]);
|
|
97
|
-
|
|
98
|
-
if (selectedProfile === '__all__') {
|
|
99
|
-
// 递归调用同步全部
|
|
100
|
-
const { confirm } = await inquirer.prompt([
|
|
101
|
-
{
|
|
102
|
-
type: 'confirm',
|
|
103
|
-
name: 'confirm',
|
|
104
|
-
message: `确定要同步所有 ${profiles.length} 个配置吗?`,
|
|
105
|
-
default: false
|
|
106
|
-
}
|
|
107
|
-
]);
|
|
108
|
-
|
|
109
|
-
if (!confirm) {
|
|
110
|
-
console.log(chalk.yellow('已取消'));
|
|
111
|
-
process.exit(0);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
profiles.forEach(name => {
|
|
115
|
-
const result = syncProfile(name);
|
|
116
|
-
console.log(chalk.green(`✓ ${name}`) + chalk.gray(` (保留: ${Object.keys(result.preserved).join(', ')})`));
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
console.log(chalk.green(`\n✓ 已同步 ${profiles.length} 个配置`));
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
profile = selectedProfile;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (!profileExists(profile)) {
|
|
127
|
-
console.log(chalk.red(`配置 "${profile}" 不存在`));
|
|
128
|
-
process.exit(1);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// 显示将要进行的更改
|
|
132
|
-
const currentSettings = readProfile(profile);
|
|
133
|
-
|
|
134
|
-
console.log(chalk.cyan(`\n同步配置: ${profile}`));
|
|
135
|
-
console.log(chalk.gray('将保留以下字段:'));
|
|
136
|
-
preserveKeys.forEach(key => {
|
|
137
|
-
const value = currentSettings[key];
|
|
138
|
-
if (value !== undefined) {
|
|
139
|
-
const display = key === 'apiKey' ? value.substring(0, 10) + '...' : value;
|
|
140
|
-
console.log(chalk.gray(` ${key}: ${display}`));
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
const templateKeys = Object.keys(template).filter(k => !preserveKeys.includes(k));
|
|
145
|
-
console.log(chalk.gray('\n将从模板同步:'));
|
|
146
|
-
console.log(chalk.gray(` ${templateKeys.join(', ') || '(无)'}`));
|
|
147
|
-
console.log();
|
|
148
|
-
|
|
149
|
-
const { confirm } = await inquirer.prompt([
|
|
150
|
-
{
|
|
151
|
-
type: 'confirm',
|
|
152
|
-
name: 'confirm',
|
|
153
|
-
message: '确认同步?',
|
|
154
|
-
default: true
|
|
155
|
-
}
|
|
156
|
-
]);
|
|
157
|
-
|
|
158
|
-
if (!confirm) {
|
|
159
|
-
console.log(chalk.yellow('已取消'));
|
|
160
|
-
process.exit(0);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
syncProfile(profile);
|
|
164
|
-
console.log(chalk.green(`\n✓ 配置 "${profile}" 已同步`));
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import {
|
|
4
|
+
getProfiles,
|
|
5
|
+
syncProfileWithTemplate,
|
|
6
|
+
getClaudeSettingsTemplate,
|
|
7
|
+
resolveProfile
|
|
8
|
+
} from '../profiles.js';
|
|
9
|
+
|
|
10
|
+
export function syncCommand(program) {
|
|
11
|
+
program
|
|
12
|
+
.command('sync [profile]')
|
|
13
|
+
.description('同步 ~/.claude/settings.json 到 profile(保留 API 凭证)')
|
|
14
|
+
.option('-a, --all', '同步所有 profiles')
|
|
15
|
+
.action(async (profile, options) => {
|
|
16
|
+
// 检查主配置是否存在
|
|
17
|
+
const template = getClaudeSettingsTemplate();
|
|
18
|
+
if (!template) {
|
|
19
|
+
console.log(chalk.red('未找到 ~/.claude/settings.json'));
|
|
20
|
+
console.log(chalk.gray('请确保 Claude Code 已正确安装'));
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const profiles = getProfiles();
|
|
25
|
+
|
|
26
|
+
if (profiles.length === 0) {
|
|
27
|
+
console.log(chalk.yellow('没有可用的 profiles'));
|
|
28
|
+
console.log(chalk.gray('使用 "ccc new" 创建配置'));
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 同步所有 profiles
|
|
33
|
+
if (options.all) {
|
|
34
|
+
const { confirm } = await inquirer.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: 'confirm',
|
|
37
|
+
name: 'confirm',
|
|
38
|
+
message: `确定要同步所有 ${profiles.length} 个 profiles 吗?`,
|
|
39
|
+
default: false
|
|
40
|
+
}
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
if (!confirm) {
|
|
44
|
+
console.log(chalk.yellow('已取消'));
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
console.log(chalk.cyan('\n开始同步所有 profiles...\n'));
|
|
49
|
+
|
|
50
|
+
let successCount = 0;
|
|
51
|
+
for (const p of profiles) {
|
|
52
|
+
const result = syncProfileWithTemplate(p);
|
|
53
|
+
if (result) {
|
|
54
|
+
console.log(chalk.green(` ✓ ${p}`));
|
|
55
|
+
successCount++;
|
|
56
|
+
} else {
|
|
57
|
+
console.log(chalk.red(` ✗ ${p} (同步失败)`));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(chalk.green(`\n✓ 已同步 ${successCount}/${profiles.length} 个 profiles`));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 同步单个 profile
|
|
66
|
+
if (!profile) {
|
|
67
|
+
const { selectedProfile } = await inquirer.prompt([
|
|
68
|
+
{
|
|
69
|
+
type: 'list',
|
|
70
|
+
name: 'selectedProfile',
|
|
71
|
+
message: '选择要同步的配置:',
|
|
72
|
+
choices: profiles
|
|
73
|
+
}
|
|
74
|
+
]);
|
|
75
|
+
profile = selectedProfile;
|
|
76
|
+
} else {
|
|
77
|
+
const resolved = resolveProfile(profile);
|
|
78
|
+
if (!resolved) {
|
|
79
|
+
console.log(chalk.red(`Profile "${profile}" 不存在`));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
profile = resolved;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const result = syncProfileWithTemplate(profile);
|
|
86
|
+
if (result) {
|
|
87
|
+
console.log(chalk.green(`\n✓ Profile "${profile}" 已同步(保留了 API 凭证)`));
|
|
88
|
+
} else {
|
|
89
|
+
console.log(chalk.red(`\n✗ 同步失败`));
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
package/src/commands/use.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { profileExists, setDefaultProfile } from '../profiles.js';
|
|
3
|
-
|
|
4
|
-
export function useCommand(program) {
|
|
5
|
-
program
|
|
6
|
-
.command('use <profile>')
|
|
7
|
-
.description('设置默认 profile')
|
|
8
|
-
.action((profile) => {
|
|
9
|
-
if (!profileExists(profile)) {
|
|
10
|
-
console.log(chalk.red(`Profile "${profile}" 不存在`));
|
|
11
|
-
console.log(chalk.yellow(`使用 "ccc list" 查看可用的 profiles`));
|
|
12
|
-
process.exit(1);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
setDefaultProfile(profile);
|
|
16
|
-
console.log(chalk.green(`✓ 默认 profile 已设置为 "${profile}"`));
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { profileExists, setDefaultProfile } from '../profiles.js';
|
|
3
|
+
|
|
4
|
+
export function useCommand(program) {
|
|
5
|
+
program
|
|
6
|
+
.command('use <profile>')
|
|
7
|
+
.description('设置默认 profile')
|
|
8
|
+
.action((profile) => {
|
|
9
|
+
if (!profileExists(profile)) {
|
|
10
|
+
console.log(chalk.red(`Profile "${profile}" 不存在`));
|
|
11
|
+
console.log(chalk.yellow(`使用 "ccc list" 查看可用的 profiles`));
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
setDefaultProfile(profile);
|
|
16
|
+
console.log(chalk.green(`✓ 默认 profile 已设置为 "${profile}"`));
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
package/src/config.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import os from 'os';
|
|
3
|
-
|
|
4
|
-
// 配置文件存储目录
|
|
5
|
-
export const CONFIG_DIR = path.join(os.homedir(), '.ccc');
|
|
6
|
-
export const PROFILES_DIR = path.join(CONFIG_DIR, 'profiles');
|
|
7
|
-
export const DEFAULT_FILE = path.join(CONFIG_DIR, 'default');
|
|
8
|
-
export const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), '.claude', 'settings.json');
|
|
9
|
-
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
|
|
4
|
+
// 配置文件存储目录
|
|
5
|
+
export const CONFIG_DIR = path.join(os.homedir(), '.ccc');
|
|
6
|
+
export const PROFILES_DIR = path.join(CONFIG_DIR, 'profiles');
|
|
7
|
+
export const DEFAULT_FILE = path.join(CONFIG_DIR, 'default');
|
|
8
|
+
export const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), '.claude', 'settings.json');
|
|
9
|
+
|
package/src/launch.js
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import inquirer from 'inquirer';
|
|
3
|
-
import { spawn } from 'child_process';
|
|
4
|
-
import {
|
|
5
|
-
getProfiles,
|
|
6
|
-
getDefaultProfile,
|
|
7
|
-
profileExists,
|
|
8
|
-
getProfilePath
|
|
9
|
-
} from './profiles.js';
|
|
10
|
-
|
|
11
|
-
// 启动 claude
|
|
12
|
-
export function launchClaude(profileName, dangerouslySkipPermissions = false) {
|
|
13
|
-
const profilePath = getProfilePath(profileName);
|
|
14
|
-
|
|
15
|
-
if (!profileExists(profileName)) {
|
|
16
|
-
console.log(chalk.red(`Profile "${profileName}" 不存在`));
|
|
17
|
-
console.log(chalk.yellow(`使用 "ccc list" 查看可用的 profiles`));
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const args = ['--settings', profilePath];
|
|
22
|
-
if (dangerouslySkipPermissions) {
|
|
23
|
-
args.push('--dangerously-skip-permissions');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
console.log(chalk.green(`启动 Claude Code,使用配置: ${profileName}`));
|
|
27
|
-
console.log(chalk.gray(`命令: claude ${args.join(' ')}`));
|
|
28
|
-
|
|
29
|
-
const child = spawn('claude', args, {
|
|
30
|
-
stdio: 'inherit',
|
|
31
|
-
shell: true
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
child.on('error', (err) => {
|
|
35
|
-
console.log(chalk.red(`启动失败: ${err.message}`));
|
|
36
|
-
process.exit(1);
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// 交互式选择 profile
|
|
41
|
-
export async function selectProfile(dangerouslySkipPermissions = false) {
|
|
42
|
-
const profiles = getProfiles();
|
|
43
|
-
|
|
44
|
-
if (profiles.length === 0) {
|
|
45
|
-
console.log(chalk.yellow('没有可用的 profiles'));
|
|
46
|
-
console.log(chalk.gray('使用 "ccc import" 导入配置'));
|
|
47
|
-
process.exit(0);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const defaultProfile = getDefaultProfile();
|
|
51
|
-
|
|
52
|
-
const choices = profiles.map((p, index) => ({
|
|
53
|
-
name: p === defaultProfile ? `${index + 1}. ${p} ${chalk.green('(默认)')}` : `${index + 1}. ${p}`,
|
|
54
|
-
value: p
|
|
55
|
-
}));
|
|
56
|
-
|
|
57
|
-
const { profile } = await inquirer.prompt([
|
|
58
|
-
{
|
|
59
|
-
type: 'list',
|
|
60
|
-
name: 'profile',
|
|
61
|
-
message: '选择要使用的配置:',
|
|
62
|
-
choices,
|
|
63
|
-
default: defaultProfile
|
|
64
|
-
}
|
|
65
|
-
]);
|
|
66
|
-
|
|
67
|
-
launchClaude(profile, dangerouslySkipPermissions);
|
|
68
|
-
}
|
|
69
|
-
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import inquirer from 'inquirer';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import {
|
|
5
|
+
getProfiles,
|
|
6
|
+
getDefaultProfile,
|
|
7
|
+
profileExists,
|
|
8
|
+
getProfilePath
|
|
9
|
+
} from './profiles.js';
|
|
10
|
+
|
|
11
|
+
// 启动 claude
|
|
12
|
+
export function launchClaude(profileName, dangerouslySkipPermissions = false) {
|
|
13
|
+
const profilePath = getProfilePath(profileName);
|
|
14
|
+
|
|
15
|
+
if (!profileExists(profileName)) {
|
|
16
|
+
console.log(chalk.red(`Profile "${profileName}" 不存在`));
|
|
17
|
+
console.log(chalk.yellow(`使用 "ccc list" 查看可用的 profiles`));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const args = ['--settings', profilePath];
|
|
22
|
+
if (dangerouslySkipPermissions) {
|
|
23
|
+
args.push('--dangerously-skip-permissions');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log(chalk.green(`启动 Claude Code,使用配置: ${profileName}`));
|
|
27
|
+
console.log(chalk.gray(`命令: claude ${args.join(' ')}`));
|
|
28
|
+
|
|
29
|
+
const child = spawn('claude', args, {
|
|
30
|
+
stdio: 'inherit',
|
|
31
|
+
shell: true
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
child.on('error', (err) => {
|
|
35
|
+
console.log(chalk.red(`启动失败: ${err.message}`));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 交互式选择 profile
|
|
41
|
+
export async function selectProfile(dangerouslySkipPermissions = false) {
|
|
42
|
+
const profiles = getProfiles();
|
|
43
|
+
|
|
44
|
+
if (profiles.length === 0) {
|
|
45
|
+
console.log(chalk.yellow('没有可用的 profiles'));
|
|
46
|
+
console.log(chalk.gray('使用 "ccc import" 导入配置'));
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const defaultProfile = getDefaultProfile();
|
|
51
|
+
|
|
52
|
+
const choices = profiles.map((p, index) => ({
|
|
53
|
+
name: p === defaultProfile ? `${index + 1}. ${p} ${chalk.green('(默认)')}` : `${index + 1}. ${p}`,
|
|
54
|
+
value: p
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
const { profile } = await inquirer.prompt([
|
|
58
|
+
{
|
|
59
|
+
type: 'list',
|
|
60
|
+
name: 'profile',
|
|
61
|
+
message: '选择要使用的配置:',
|
|
62
|
+
choices,
|
|
63
|
+
default: defaultProfile
|
|
64
|
+
}
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
launchClaude(profile, dangerouslySkipPermissions);
|
|
68
|
+
}
|
|
69
|
+
|