@tkpdx01/ccc 1.3.4 → 1.3.5
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 +1 -1
- package/package.json +1 -1
- package/src/commands/edit.js +3 -1
- package/src/commands/new.js +43 -3
- package/src/profiles.js +62 -0
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ ccc webdav status # View sync status / 查看同步状态
|
|
|
60
60
|
- **Template Support / 模板**: Based on `~/.claude/settings.json`
|
|
61
61
|
- **Smart Import / 智能导入**: Auto-detect API URL and token
|
|
62
62
|
- **Sync Settings / 同步**: Update from template, preserve credentials
|
|
63
|
-
- **Claude Env Defaults / Claude 环境变量默认值**: Auto-ensure `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`, `CLAUDE_CODE_ATTRIBUTION_HEADER=0`,
|
|
63
|
+
- **Claude Env Defaults / Claude 环境变量默认值**: Auto-ensure these values in the `env` section of both `~/.claude/settings.json` and each profile: `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`, `CLAUDE_CODE_ATTRIBUTION_HEADER=0`, `DISABLE_INSTALLATION_CHECKS=1`
|
|
64
64
|
- **WebDAV Cloud Sync / 云同步**: Encrypted sync across devices
|
|
65
65
|
|
|
66
66
|
## Sync Command / 同步命令
|
package/package.json
CHANGED
package/src/commands/edit.js
CHANGED
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
resolveProfile,
|
|
14
14
|
getProfileCredentials,
|
|
15
15
|
getClaudeSettingsTemplate,
|
|
16
|
-
ensureRequiredClaudeEnvSettings
|
|
16
|
+
ensureRequiredClaudeEnvSettings,
|
|
17
|
+
ensureClaudeSettingsExtras
|
|
17
18
|
} from '../profiles.js';
|
|
18
19
|
|
|
19
20
|
export function editCommand(program) {
|
|
@@ -98,6 +99,7 @@ export function editCommand(program) {
|
|
|
98
99
|
|
|
99
100
|
// 确保主配置(~/.claude/settings.json)与 profile 都包含必要 env 设置
|
|
100
101
|
ensureRequiredClaudeEnvSettings();
|
|
102
|
+
ensureClaudeSettingsExtras();
|
|
101
103
|
currentProfile.env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = '1';
|
|
102
104
|
currentProfile.env.CLAUDE_CODE_ATTRIBUTION_HEADER = '0';
|
|
103
105
|
currentProfile.env.DISABLE_INSTALLATION_CHECKS = '1';
|
package/src/commands/new.js
CHANGED
|
@@ -5,10 +5,42 @@ import {
|
|
|
5
5
|
getProfiles,
|
|
6
6
|
profileExists,
|
|
7
7
|
createProfileFromTemplate,
|
|
8
|
-
setDefaultProfile
|
|
8
|
+
setDefaultProfile,
|
|
9
|
+
ensureClaudeSettingsExtras
|
|
9
10
|
} from '../profiles.js';
|
|
10
11
|
import { launchClaude } from '../launch.js';
|
|
11
12
|
|
|
13
|
+
const RESERVED_PROFILE_NAMES = [
|
|
14
|
+
'list',
|
|
15
|
+
'ls',
|
|
16
|
+
'use',
|
|
17
|
+
'show',
|
|
18
|
+
'import',
|
|
19
|
+
'if',
|
|
20
|
+
'new',
|
|
21
|
+
'edit',
|
|
22
|
+
'delete',
|
|
23
|
+
'rm',
|
|
24
|
+
'sync',
|
|
25
|
+
'webdav',
|
|
26
|
+
'help'
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
function isReservedProfileName(name) {
|
|
30
|
+
return RESERVED_PROFILE_NAMES.includes(name);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function validateProfileName(input) {
|
|
34
|
+
const trimmed = input.trim();
|
|
35
|
+
if (!trimmed) {
|
|
36
|
+
return '请输入配置名称';
|
|
37
|
+
}
|
|
38
|
+
if (isReservedProfileName(trimmed)) {
|
|
39
|
+
return '配置名称不能使用命令关键词';
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
12
44
|
export function newCommand(program) {
|
|
13
45
|
program
|
|
14
46
|
.command('new [name]')
|
|
@@ -21,10 +53,16 @@ export function newCommand(program) {
|
|
|
21
53
|
type: 'input',
|
|
22
54
|
name: 'profileName',
|
|
23
55
|
message: '配置名称:',
|
|
24
|
-
validate:
|
|
56
|
+
validate: validateProfileName
|
|
25
57
|
}
|
|
26
58
|
]);
|
|
27
59
|
name = profileName;
|
|
60
|
+
} else {
|
|
61
|
+
const validationResult = validateProfileName(name);
|
|
62
|
+
if (validationResult !== true) {
|
|
63
|
+
console.log(chalk.red(validationResult));
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
28
66
|
}
|
|
29
67
|
|
|
30
68
|
// 检查是否已存在
|
|
@@ -60,7 +98,8 @@ export function newCommand(program) {
|
|
|
60
98
|
type: 'input',
|
|
61
99
|
name: 'finalName',
|
|
62
100
|
message: 'Profile 名称:',
|
|
63
|
-
default: name
|
|
101
|
+
default: name,
|
|
102
|
+
validate: validateProfileName
|
|
64
103
|
}
|
|
65
104
|
]);
|
|
66
105
|
|
|
@@ -81,6 +120,7 @@ export function newCommand(program) {
|
|
|
81
120
|
}
|
|
82
121
|
|
|
83
122
|
ensureDirs();
|
|
123
|
+
ensureClaudeSettingsExtras();
|
|
84
124
|
createProfileFromTemplate(finalName, apiUrl, apiKey);
|
|
85
125
|
console.log(chalk.green(`\n✓ 配置 "${finalName}" 已创建(基于 ~/.claude/settings.json)`));
|
|
86
126
|
|
package/src/profiles.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
3
4
|
import { CONFIG_DIR, PROFILES_DIR, DEFAULT_FILE, CLAUDE_SETTINGS_PATH } from './config.js';
|
|
4
5
|
|
|
5
6
|
function stringifyClaudeSettings(settings) {
|
|
@@ -138,6 +139,67 @@ export function ensureRequiredClaudeEnvSettings() {
|
|
|
138
139
|
});
|
|
139
140
|
}
|
|
140
141
|
|
|
142
|
+
// 获取 statusLine 的 ccline 路径(适配不同操作系统)
|
|
143
|
+
function getCclineCommand() {
|
|
144
|
+
const platform = os.platform();
|
|
145
|
+
if (platform === 'win32') {
|
|
146
|
+
return '%USERPROFILE%\\.claude\\ccline\\ccline.exe';
|
|
147
|
+
} else {
|
|
148
|
+
// Linux 和 macOS
|
|
149
|
+
return '~/.claude/ccline/ccline';
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 确保主配置包含 attribution/includeCoAuthoredBy 和 statusLine 设置
|
|
154
|
+
export function ensureClaudeSettingsExtras() {
|
|
155
|
+
const template = getClaudeSettingsTemplate();
|
|
156
|
+
if (!template) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
let changed = false;
|
|
161
|
+
|
|
162
|
+
// 确保 attribution 禁用(commit/pr 为空字符串)
|
|
163
|
+
if (!template.attribution || typeof template.attribution !== 'object' || Array.isArray(template.attribution)) {
|
|
164
|
+
template.attribution = { commit: '', pr: '' };
|
|
165
|
+
changed = true;
|
|
166
|
+
} else {
|
|
167
|
+
if (template.attribution.commit !== '' || template.attribution.pr !== '') {
|
|
168
|
+
template.attribution.commit = '';
|
|
169
|
+
template.attribution.pr = '';
|
|
170
|
+
changed = true;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 兼容旧版本:确保 includeCoAuthoredBy: false
|
|
175
|
+
if (template.includeCoAuthoredBy !== false) {
|
|
176
|
+
template.includeCoAuthoredBy = false;
|
|
177
|
+
changed = true;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// 确保 statusLine 配置
|
|
181
|
+
const expectedCommand = getCclineCommand();
|
|
182
|
+
const expectedStatusLine = {
|
|
183
|
+
type: 'command',
|
|
184
|
+
command: expectedCommand,
|
|
185
|
+
padding: 0
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
if (!template.statusLine ||
|
|
189
|
+
template.statusLine.type !== 'command' ||
|
|
190
|
+
template.statusLine.command !== expectedCommand ||
|
|
191
|
+
template.statusLine.padding !== 0) {
|
|
192
|
+
template.statusLine = expectedStatusLine;
|
|
193
|
+
changed = true;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (changed) {
|
|
197
|
+
fs.writeFileSync(CLAUDE_SETTINGS_PATH, stringifyClaudeSettings(template));
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return template;
|
|
201
|
+
}
|
|
202
|
+
|
|
141
203
|
// 读取 profile 配置
|
|
142
204
|
export function readProfile(name) {
|
|
143
205
|
const profilePath = getProfilePath(name);
|