zcf 2.12.10 → 2.12.11
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 +24 -5
- package/dist/chunks/simple-config.mjs +319 -9
- package/dist/cli.mjs +2 -2
- package/dist/i18n/locales/en/ccr.json +3 -1
- package/dist/i18n/locales/en/errors.json +3 -1
- package/dist/i18n/locales/en/installation.json +17 -1
- package/dist/i18n/locales/en/mcp.json +2 -1
- package/dist/i18n/locales/zh-CN/ccr.json +3 -1
- package/dist/i18n/locales/zh-CN/errors.json +3 -1
- package/dist/i18n/locales/zh-CN/installation.json +17 -1
- package/dist/i18n/locales/zh-CN/mcp.json +2 -1
- package/dist/index.d.mts +51 -11
- package/dist/index.d.ts +51 -11
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/templates/en/output-styles/nekomata-engineer.md +8 -8
- package/templates/zh-CN/output-styles/nekomata-engineer.md +8 -8
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# ZCF - Zero-Config Claude-Code Flow
|
|
2
2
|
|
|
3
|
-
[![
|
|
4
|
-
[![
|
|
5
|
-
[![
|
|
6
|
-
[![
|
|
7
|
-
[![
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
[![License][license-src]][license-href]
|
|
6
|
+
[![Claude Code][claude-code-src]][claude-code-href]
|
|
7
|
+
[![codecov][codecov-src]][codecov-href]
|
|
8
|
+
[![JSDocs][jsdocs-src]][jsdocs-href]
|
|
9
|
+
[![Ask DeepWiki][deepwiki-src]][deepwiki-href]
|
|
8
10
|
|
|
9
11
|
[中文](README_zh-CN.md) | **English** | [Changelog](CHANGELOG.md)
|
|
10
12
|
|
|
@@ -709,3 +711,20 @@ MIT License
|
|
|
709
711
|
If this project helps you, please give me a ⭐️ Star!
|
|
710
712
|
|
|
711
713
|
[](https://star-history.com/#UfoMiao/zcf&Date)
|
|
714
|
+
|
|
715
|
+
<!-- Badges -->
|
|
716
|
+
|
|
717
|
+
[npm-version-src]: https://img.shields.io/npm/v/zcf?style=flat&colorA=080f12&colorB=1fa669
|
|
718
|
+
[npm-version-href]: https://npmjs.com/package/zcf
|
|
719
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/zcf?style=flat&colorA=080f12&colorB=1fa669
|
|
720
|
+
[npm-downloads-href]: https://npmjs.com/package/zcf
|
|
721
|
+
[license-src]: https://img.shields.io/github/license/ufomiao/zcf.svg?style=flat&colorA=080f12&colorB=1fa669
|
|
722
|
+
[license-href]: https://github.com/ufomiao/zcf/blob/main/LICENSE
|
|
723
|
+
[claude-code-src]: https://img.shields.io/badge/Claude-Code-1fa669?style=flat&colorA=080f12&colorB=1fa669
|
|
724
|
+
[claude-code-href]: https://claude.ai/code
|
|
725
|
+
[codecov-src]: https://codecov.io/gh/UfoMiao/zcf/graph/badge.svg?token=HZI6K4Y7D7&style=flat&colorA=080f12&colorB=1fa669
|
|
726
|
+
[codecov-href]: https://codecov.io/gh/UfoMiao/zcf
|
|
727
|
+
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-1fa669?style=flat&colorA=080f12&colorB=1fa669
|
|
728
|
+
[jsdocs-href]: https://www.jsdocs.io/package/zcf
|
|
729
|
+
[deepwiki-src]: https://img.shields.io/badge/Ask-DeepWiki-1fa669?style=flat&colorA=080f12&colorB=1fa669
|
|
730
|
+
[deepwiki-href]: https://deepwiki.com/UfoMiao/zcf
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, readdirSync, statSync, unlinkSync } from 'node:fs';
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync, rmSync, rmdirSync, readdirSync, statSync, unlinkSync } from 'node:fs';
|
|
2
2
|
import process from 'node:process';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
@@ -15,7 +15,7 @@ import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
|
|
|
15
15
|
import i18next from 'i18next';
|
|
16
16
|
import Backend from 'i18next-fs-backend';
|
|
17
17
|
|
|
18
|
-
const version = "2.12.
|
|
18
|
+
const version = "2.12.11";
|
|
19
19
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
20
20
|
|
|
21
21
|
const i18n = i18next.createInstance();
|
|
@@ -536,6 +536,61 @@ function copyDir(src, dest, options = {}) {
|
|
|
536
536
|
}
|
|
537
537
|
}
|
|
538
538
|
}
|
|
539
|
+
async function isExecutable(path) {
|
|
540
|
+
try {
|
|
541
|
+
if (!exists(path)) {
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
const stats = getStats(path);
|
|
545
|
+
if (!stats.isFile()) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
if (process.platform !== "win32") {
|
|
549
|
+
const mode = stats.mode;
|
|
550
|
+
const executePermission = 73;
|
|
551
|
+
return (mode & executePermission) !== 0;
|
|
552
|
+
}
|
|
553
|
+
const isWinExecutable = path.endsWith(".exe") || path.endsWith(".cmd") || path.endsWith(".bat");
|
|
554
|
+
return isWinExecutable || !path.includes(".");
|
|
555
|
+
} catch {
|
|
556
|
+
return false;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
async function remove(path) {
|
|
560
|
+
try {
|
|
561
|
+
if (!exists(path)) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
const stats = getStats(path);
|
|
565
|
+
if (stats.isDirectory()) {
|
|
566
|
+
const entries = readDir(path);
|
|
567
|
+
for (const entry of entries) {
|
|
568
|
+
await remove(`${path}/${entry}`);
|
|
569
|
+
}
|
|
570
|
+
try {
|
|
571
|
+
if (rmSync) {
|
|
572
|
+
rmSync(path, { recursive: true, force: true });
|
|
573
|
+
} else if (rmdirSync) {
|
|
574
|
+
rmdirSync(path);
|
|
575
|
+
}
|
|
576
|
+
} catch (error) {
|
|
577
|
+
throw new FileSystemError(
|
|
578
|
+
`Failed to remove directory: ${path}`,
|
|
579
|
+
path,
|
|
580
|
+
error
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
} else {
|
|
584
|
+
removeFile(path);
|
|
585
|
+
}
|
|
586
|
+
} catch (error) {
|
|
587
|
+
throw new FileSystemError(
|
|
588
|
+
`Failed to remove: ${path}`,
|
|
589
|
+
path,
|
|
590
|
+
error
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
539
594
|
|
|
540
595
|
function readJsonConfig(path, options = {}) {
|
|
541
596
|
const { defaultValue = null, validate, sanitize } = options;
|
|
@@ -780,6 +835,75 @@ function addCompletedOnboarding() {
|
|
|
780
835
|
throw error;
|
|
781
836
|
}
|
|
782
837
|
}
|
|
838
|
+
function ensureApiKeyApproved(config, apiKey) {
|
|
839
|
+
if (!apiKey || typeof apiKey !== "string" || apiKey.trim() === "") {
|
|
840
|
+
return config;
|
|
841
|
+
}
|
|
842
|
+
const truncatedApiKey = apiKey.substring(0, 20);
|
|
843
|
+
const updatedConfig = { ...config };
|
|
844
|
+
if (!updatedConfig.customApiKeyResponses) {
|
|
845
|
+
updatedConfig.customApiKeyResponses = {
|
|
846
|
+
approved: [],
|
|
847
|
+
rejected: []
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
if (!Array.isArray(updatedConfig.customApiKeyResponses.approved)) {
|
|
851
|
+
updatedConfig.customApiKeyResponses.approved = [];
|
|
852
|
+
}
|
|
853
|
+
if (!Array.isArray(updatedConfig.customApiKeyResponses.rejected)) {
|
|
854
|
+
updatedConfig.customApiKeyResponses.rejected = [];
|
|
855
|
+
}
|
|
856
|
+
const rejectedIndex = updatedConfig.customApiKeyResponses.rejected.indexOf(truncatedApiKey);
|
|
857
|
+
if (rejectedIndex > -1) {
|
|
858
|
+
updatedConfig.customApiKeyResponses.rejected.splice(rejectedIndex, 1);
|
|
859
|
+
}
|
|
860
|
+
if (!updatedConfig.customApiKeyResponses.approved.includes(truncatedApiKey)) {
|
|
861
|
+
updatedConfig.customApiKeyResponses.approved.push(truncatedApiKey);
|
|
862
|
+
}
|
|
863
|
+
return updatedConfig;
|
|
864
|
+
}
|
|
865
|
+
function removeApiKeyFromRejected(config, apiKey) {
|
|
866
|
+
if (!config.customApiKeyResponses || !Array.isArray(config.customApiKeyResponses.rejected)) {
|
|
867
|
+
return config;
|
|
868
|
+
}
|
|
869
|
+
const truncatedApiKey = apiKey.substring(0, 20);
|
|
870
|
+
const updatedConfig = { ...config };
|
|
871
|
+
if (updatedConfig.customApiKeyResponses) {
|
|
872
|
+
const rejectedIndex = updatedConfig.customApiKeyResponses.rejected.indexOf(truncatedApiKey);
|
|
873
|
+
if (rejectedIndex > -1) {
|
|
874
|
+
updatedConfig.customApiKeyResponses.rejected.splice(rejectedIndex, 1);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
return updatedConfig;
|
|
878
|
+
}
|
|
879
|
+
function manageApiKeyApproval(apiKey) {
|
|
880
|
+
try {
|
|
881
|
+
let config = readMcpConfig();
|
|
882
|
+
if (!config) {
|
|
883
|
+
config = { mcpServers: {} };
|
|
884
|
+
}
|
|
885
|
+
const updatedConfig = ensureApiKeyApproved(config, apiKey);
|
|
886
|
+
writeMcpConfig(updatedConfig);
|
|
887
|
+
} catch (error) {
|
|
888
|
+
ensureI18nInitialized();
|
|
889
|
+
console.error(i18n.t("mcp:apiKeyApprovalFailed"), error);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
const claudeConfig = {
|
|
894
|
+
__proto__: null,
|
|
895
|
+
addCompletedOnboarding: addCompletedOnboarding,
|
|
896
|
+
backupMcpConfig: backupMcpConfig,
|
|
897
|
+
buildMcpServerConfig: buildMcpServerConfig,
|
|
898
|
+
ensureApiKeyApproved: ensureApiKeyApproved,
|
|
899
|
+
fixWindowsMcpConfig: fixWindowsMcpConfig,
|
|
900
|
+
getMcpConfigPath: getMcpConfigPath,
|
|
901
|
+
manageApiKeyApproval: manageApiKeyApproval,
|
|
902
|
+
mergeMcpServers: mergeMcpServers,
|
|
903
|
+
readMcpConfig: readMcpConfig,
|
|
904
|
+
removeApiKeyFromRejected: removeApiKeyFromRejected,
|
|
905
|
+
writeMcpConfig: writeMcpConfig
|
|
906
|
+
};
|
|
783
907
|
|
|
784
908
|
function cleanupPermissions(templatePermissions, userPermissions) {
|
|
785
909
|
const templateSet = new Set(templatePermissions);
|
|
@@ -1394,6 +1518,14 @@ async function setupCcrConfiguration() {
|
|
|
1394
1518
|
if (!shouldBackupAndReconfigure) {
|
|
1395
1519
|
console.log(ansis.yellow(`${i18n.t("ccr:keepingExistingConfig")}`));
|
|
1396
1520
|
await configureCcrProxy(existingConfig);
|
|
1521
|
+
try {
|
|
1522
|
+
const { manageApiKeyApproval } = await Promise.resolve().then(function () { return claudeConfig; });
|
|
1523
|
+
const apiKey = existingConfig.APIKEY || "sk-zcf-x-ccr";
|
|
1524
|
+
manageApiKeyApproval(apiKey);
|
|
1525
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:apiKeyApprovalSuccess")}`));
|
|
1526
|
+
} catch (error) {
|
|
1527
|
+
console.error(ansis.red(`${i18n.t("ccr:apiKeyApprovalFailed")}:`), error);
|
|
1528
|
+
}
|
|
1397
1529
|
return true;
|
|
1398
1530
|
}
|
|
1399
1531
|
backupCcrConfig();
|
|
@@ -1420,6 +1552,14 @@ async function setupCcrConfiguration() {
|
|
|
1420
1552
|
} catch (error) {
|
|
1421
1553
|
console.error(ansis.red(i18n.t("errors:failedToSetOnboarding")), error);
|
|
1422
1554
|
}
|
|
1555
|
+
try {
|
|
1556
|
+
const { manageApiKeyApproval } = await Promise.resolve().then(function () { return claudeConfig; });
|
|
1557
|
+
const apiKey = config.APIKEY || "sk-zcf-x-ccr";
|
|
1558
|
+
manageApiKeyApproval(apiKey);
|
|
1559
|
+
console.log(ansis.green(`\u2714 ${i18n.t("ccr:apiKeyApprovalSuccess")}`));
|
|
1560
|
+
} catch (error) {
|
|
1561
|
+
console.error(ansis.red(`${i18n.t("ccr:apiKeyApprovalFailed")}:`), error);
|
|
1562
|
+
}
|
|
1423
1563
|
return true;
|
|
1424
1564
|
} catch (error) {
|
|
1425
1565
|
if (error.name === "ExitPromptError") {
|
|
@@ -1929,10 +2069,19 @@ function updateZcfConfig(updates) {
|
|
|
1929
2069
|
aiOutputLang: updates.aiOutputLang || existingConfig?.aiOutputLang,
|
|
1930
2070
|
outputStyles: updates.outputStyles !== void 0 ? updates.outputStyles : existingConfig?.outputStyles,
|
|
1931
2071
|
defaultOutputStyle: updates.defaultOutputStyle !== void 0 ? updates.defaultOutputStyle : existingConfig?.defaultOutputStyle,
|
|
2072
|
+
claudeCodeInstallation: updates.claudeCodeInstallation !== void 0 ? updates.claudeCodeInstallation : existingConfig?.claudeCodeInstallation,
|
|
1932
2073
|
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
1933
2074
|
};
|
|
1934
2075
|
writeZcfConfig(newConfig);
|
|
1935
2076
|
}
|
|
2077
|
+
function getZcfConfig() {
|
|
2078
|
+
const config = readZcfConfig();
|
|
2079
|
+
return config || {
|
|
2080
|
+
version: "1.0.0",
|
|
2081
|
+
preferredLang: "en",
|
|
2082
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
1936
2085
|
|
|
1937
2086
|
const OUTPUT_STYLES = [
|
|
1938
2087
|
// Custom styles (have template files)
|
|
@@ -2338,9 +2487,10 @@ ${i18n.t("common:goodbye")}
|
|
|
2338
2487
|
return false;
|
|
2339
2488
|
}
|
|
2340
2489
|
function handleGeneralError(error) {
|
|
2341
|
-
|
|
2490
|
+
ensureI18nInitialized();
|
|
2491
|
+
console.error(ansis.red(`${i18n.t("errors:generalError")}:`), error);
|
|
2342
2492
|
if (error instanceof Error) {
|
|
2343
|
-
console.error(ansis.gray(
|
|
2493
|
+
console.error(ansis.gray(`${i18n.t("errors:stackTrace")}: ${error.stack}`));
|
|
2344
2494
|
}
|
|
2345
2495
|
process.exit(1);
|
|
2346
2496
|
}
|
|
@@ -2381,6 +2531,147 @@ ${i18n.t("installation:termuxInstallHint")}
|
|
|
2381
2531
|
throw error;
|
|
2382
2532
|
}
|
|
2383
2533
|
}
|
|
2534
|
+
async function isLocalClaudeCodeInstalled() {
|
|
2535
|
+
const localClaudePath = join(homedir(), ".claude", "local", "claude");
|
|
2536
|
+
if (!exists(localClaudePath)) {
|
|
2537
|
+
return false;
|
|
2538
|
+
}
|
|
2539
|
+
return await isExecutable(localClaudePath);
|
|
2540
|
+
}
|
|
2541
|
+
async function getInstallationStatus() {
|
|
2542
|
+
const localPath = join(homedir(), ".claude", "local", "claude");
|
|
2543
|
+
const [hasGlobal, hasLocal] = await Promise.all([
|
|
2544
|
+
isClaudeCodeInstalled(),
|
|
2545
|
+
isLocalClaudeCodeInstalled()
|
|
2546
|
+
]);
|
|
2547
|
+
return {
|
|
2548
|
+
hasGlobal,
|
|
2549
|
+
hasLocal,
|
|
2550
|
+
localPath
|
|
2551
|
+
};
|
|
2552
|
+
}
|
|
2553
|
+
async function removeLocalClaudeCode() {
|
|
2554
|
+
const localDir = join(homedir(), ".claude", "local");
|
|
2555
|
+
if (!exists(localDir)) {
|
|
2556
|
+
return;
|
|
2557
|
+
}
|
|
2558
|
+
try {
|
|
2559
|
+
await remove(localDir);
|
|
2560
|
+
} catch (error) {
|
|
2561
|
+
ensureI18nInitialized();
|
|
2562
|
+
throw new Error(`${i18n.t("installation:failedToRemoveLocalInstallation")}: ${error}`);
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
const installer = {
|
|
2567
|
+
__proto__: null,
|
|
2568
|
+
getInstallationStatus: getInstallationStatus,
|
|
2569
|
+
installClaudeCode: installClaudeCode,
|
|
2570
|
+
isClaudeCodeInstalled: isClaudeCodeInstalled,
|
|
2571
|
+
isLocalClaudeCodeInstalled: isLocalClaudeCodeInstalled,
|
|
2572
|
+
removeLocalClaudeCode: removeLocalClaudeCode
|
|
2573
|
+
};
|
|
2574
|
+
|
|
2575
|
+
async function chooseInstallationMethod() {
|
|
2576
|
+
ensureI18nInitialized();
|
|
2577
|
+
const choices = [
|
|
2578
|
+
{
|
|
2579
|
+
name: i18n.t("installation:chooseGlobal"),
|
|
2580
|
+
value: "global"
|
|
2581
|
+
},
|
|
2582
|
+
{
|
|
2583
|
+
name: i18n.t("installation:chooseLocal"),
|
|
2584
|
+
value: "local"
|
|
2585
|
+
}
|
|
2586
|
+
];
|
|
2587
|
+
const { installMethod } = await inquirer.prompt([
|
|
2588
|
+
{
|
|
2589
|
+
type: "list",
|
|
2590
|
+
name: "installMethod",
|
|
2591
|
+
message: i18n.t("installation:chooseInstallationMethod"),
|
|
2592
|
+
choices
|
|
2593
|
+
}
|
|
2594
|
+
]);
|
|
2595
|
+
return installMethod;
|
|
2596
|
+
}
|
|
2597
|
+
async function handleMultipleInstallations(status) {
|
|
2598
|
+
ensureI18nInitialized();
|
|
2599
|
+
const existingConfig = getZcfConfig();
|
|
2600
|
+
const previousChoice = existingConfig.claudeCodeInstallation;
|
|
2601
|
+
if (previousChoice) {
|
|
2602
|
+
if (previousChoice.type === "global" && status.hasGlobal) {
|
|
2603
|
+
return "global";
|
|
2604
|
+
}
|
|
2605
|
+
if (previousChoice.type === "local" && status.hasLocal) {
|
|
2606
|
+
return "local";
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
if (!status.hasGlobal && !status.hasLocal) {
|
|
2610
|
+
return "none";
|
|
2611
|
+
}
|
|
2612
|
+
if (status.hasGlobal && !status.hasLocal) {
|
|
2613
|
+
return "global";
|
|
2614
|
+
}
|
|
2615
|
+
if (status.hasGlobal && status.hasLocal) {
|
|
2616
|
+
console.warn(
|
|
2617
|
+
ansis.yellow(`\u26A0\uFE0F ${i18n.t("installation:multipleInstallationsDetected")}`)
|
|
2618
|
+
);
|
|
2619
|
+
console.log(`${i18n.t("installation:globalInstallation")}: ${i18n.t("installation:available")}`);
|
|
2620
|
+
console.log(`${i18n.t("installation:localInstallation")}: ${status.localPath}`);
|
|
2621
|
+
} else {
|
|
2622
|
+
console.warn(
|
|
2623
|
+
ansis.yellow(`\u26A0\uFE0F ${i18n.t("installation:onlyLocalInstallationDetected")}`)
|
|
2624
|
+
);
|
|
2625
|
+
console.log(`${i18n.t("installation:localInstallation")}: ${status.localPath}`);
|
|
2626
|
+
console.log(`${i18n.t("installation:globalInstallation")}: ${i18n.t("installation:notInstalled")}`);
|
|
2627
|
+
}
|
|
2628
|
+
const choice = await chooseInstallationMethod();
|
|
2629
|
+
try {
|
|
2630
|
+
if (choice === "global") {
|
|
2631
|
+
if (!status.hasGlobal) {
|
|
2632
|
+
console.log(ansis.blue(`${i18n.t("installation:installingGlobalClaudeCode")}...`));
|
|
2633
|
+
const { installClaudeCode } = await Promise.resolve().then(function () { return installer; });
|
|
2634
|
+
await installClaudeCode();
|
|
2635
|
+
console.log(ansis.green(`\u2714 ${i18n.t("installation:globalInstallationCompleted")}`));
|
|
2636
|
+
}
|
|
2637
|
+
if (status.hasLocal) {
|
|
2638
|
+
console.log(ansis.blue(`${i18n.t("installation:removingLocalInstallation")}...`));
|
|
2639
|
+
await removeLocalClaudeCode();
|
|
2640
|
+
console.log(ansis.green(`\u2714 ${i18n.t("installation:localInstallationRemoved")}`));
|
|
2641
|
+
}
|
|
2642
|
+
await saveInstallationConfig({
|
|
2643
|
+
type: "global",
|
|
2644
|
+
path: "claude",
|
|
2645
|
+
configDir: CLAUDE_DIR
|
|
2646
|
+
});
|
|
2647
|
+
} else {
|
|
2648
|
+
console.log(ansis.green(`\u2714 ${i18n.t("installation:usingLocalInstallation")}`));
|
|
2649
|
+
await saveInstallationConfig({
|
|
2650
|
+
type: "local",
|
|
2651
|
+
path: status.localPath,
|
|
2652
|
+
configDir: join(homedir(), ".claude")
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
return choice;
|
|
2656
|
+
} catch (error) {
|
|
2657
|
+
if (choice === "global") {
|
|
2658
|
+
console.error(ansis.red(`\u2716 ${i18n.t("installation:failedToRemoveLocalInstallation")}: ${error}`));
|
|
2659
|
+
throw error;
|
|
2660
|
+
} else {
|
|
2661
|
+
console.error(ansis.red(`\u2716 ${i18n.t("installation:failedToSaveInstallationConfig")}: ${error}`));
|
|
2662
|
+
return choice;
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
}
|
|
2666
|
+
async function saveInstallationConfig(installation) {
|
|
2667
|
+
try {
|
|
2668
|
+
updateZcfConfig({
|
|
2669
|
+
claudeCodeInstallation: installation
|
|
2670
|
+
});
|
|
2671
|
+
} catch (error) {
|
|
2672
|
+
console.error(ansis.red(`\u2716 ${i18n.t("installation:failedToSaveInstallationConfig")}: ${error}`));
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2384
2675
|
|
|
2385
2676
|
async function selectMcpServices() {
|
|
2386
2677
|
ensureI18nInitialized();
|
|
@@ -2793,8 +3084,27 @@ async function init(options = {}) {
|
|
|
2793
3084
|
}
|
|
2794
3085
|
const zcfConfig = readZcfConfig();
|
|
2795
3086
|
const aiOutputLang = options.skipPrompt ? options.aiOutputLang || "en" : await resolveAiOutputLanguage(i18n.language, options.aiOutputLang, zcfConfig);
|
|
2796
|
-
const
|
|
2797
|
-
if (
|
|
3087
|
+
const installationStatus = await getInstallationStatus();
|
|
3088
|
+
if (installationStatus.hasGlobal || installationStatus.hasLocal) {
|
|
3089
|
+
if (!options.skipPrompt) {
|
|
3090
|
+
await handleMultipleInstallations(installationStatus);
|
|
3091
|
+
} else {
|
|
3092
|
+
if (installationStatus.hasLocal) {
|
|
3093
|
+
if (!installationStatus.hasGlobal) {
|
|
3094
|
+
console.log(ansis.blue(`${i18n.t("installation:installingGlobalClaudeCode")}...`));
|
|
3095
|
+
await installClaudeCode();
|
|
3096
|
+
console.log(ansis.green(`\u2714 ${i18n.t("installation:globalInstallationCompleted")}`));
|
|
3097
|
+
}
|
|
3098
|
+
if (installationStatus.hasGlobal && installationStatus.hasLocal) {
|
|
3099
|
+
console.log(ansis.yellow(`\u26A0\uFE0F ${i18n.t("installation:multipleInstallationsDetected")}`));
|
|
3100
|
+
}
|
|
3101
|
+
console.log(ansis.blue(`${i18n.t("installation:removingLocalInstallation")}...`));
|
|
3102
|
+
const { removeLocalClaudeCode } = await Promise.resolve().then(function () { return installer; });
|
|
3103
|
+
await removeLocalClaudeCode();
|
|
3104
|
+
console.log(ansis.green(`\u2714 ${i18n.t("installation:localInstallationRemoved")}`));
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
} else {
|
|
2798
3108
|
if (options.skipPrompt) {
|
|
2799
3109
|
await installClaudeCode();
|
|
2800
3110
|
} else {
|
|
@@ -2814,8 +3124,8 @@ async function init(options = {}) {
|
|
|
2814
3124
|
console.log(ansis.yellow(i18n.t("common:skip")));
|
|
2815
3125
|
}
|
|
2816
3126
|
}
|
|
2817
|
-
}
|
|
2818
|
-
|
|
3127
|
+
}
|
|
3128
|
+
if (installationStatus.hasGlobal || installationStatus.hasLocal) {
|
|
2819
3129
|
await checkClaudeCodeVersionAndPrompt(options.skipPrompt);
|
|
2820
3130
|
}
|
|
2821
3131
|
ensureClaudeDir();
|
|
@@ -3238,4 +3548,4 @@ async function openSettingsJson() {
|
|
|
3238
3548
|
}
|
|
3239
3549
|
}
|
|
3240
3550
|
|
|
3241
|
-
export {
|
|
3551
|
+
export { addNumbersToChoices as $, AI_OUTPUT_LANGUAGES as A, copyConfigFiles as B, CLAUDE_DIR as C, configureApi as D, mergeConfigs as E, updateCustomModel as F, updateDefaultModel as G, mergeSettingsFile as H, getExistingModelConfig as I, getExistingApiConfig as J, applyAiLanguageDirective as K, LEGACY_ZCF_CONFIG_FILE as L, isClaudeCodeInstalled as M, installClaudeCode as N, isLocalClaudeCodeInstalled as O, getInstallationStatus as P, removeLocalClaudeCode as Q, ensureI18nInitialized as R, SETTINGS_FILE as S, i18n as T, readCcrConfig as U, isCcrInstalled as V, installCcr as W, configureCcrFeature as X, handleExitPromptError as Y, ZCF_CONFIG_FILE as Z, handleGeneralError as _, commandExists as a, updateZcfConfig as a0, changeLanguage as a1, readZcfConfig as a2, configureOutputStyle as a3, isWindows as a4, selectMcpServices as a5, getMcpServices as a6, formatApiKeyDisplay as a7, modifyApiConfigPartially as a8, setupCcrConfiguration as a9, validateApiKey as aa, COMETIX_COMMAND_NAME as ab, COMETIX_COMMANDS as ac, installCometixLine as ad, checkAndUpdateTools as ae, displayBanner as af, resolveAiOutputLanguage as ag, updatePromptOnly as ah, selectAndInstallWorkflows as ai, checkClaudeCodeVersionAndPrompt as aj, version as ak, displayBannerWithInfo as al, readZcfConfigAsync as am, initI18n as an, selectScriptLanguage as ao, prompts as ap, importRecommendedEnv as b, cleanupPermissions as c, importRecommendedPermissions as d, CLAUDE_MD_FILE as e, ClAUDE_CONFIG_FILE as f, getPlatform as g, SUPPORTED_LANGS as h, init as i, LANG_LABELS as j, getAiOutputLanguageLabel as k, getMcpConfigPath as l, mergeAndCleanPermissions as m, backupMcpConfig as n, openSettingsJson as o, mergeMcpServers as p, buildMcpServerConfig as q, readMcpConfig as r, fixWindowsMcpConfig as s, addCompletedOnboarding as t, ensureApiKeyApproved as u, removeApiKeyFromRejected as v, writeMcpConfig as w, manageApiKeyApproval as x, ensureClaudeDir as y, backupExistingConfig as z };
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import cac from 'cac';
|
|
3
3
|
import ansis from 'ansis';
|
|
4
|
-
import {
|
|
4
|
+
import { R as ensureI18nInitialized, T as i18n, U as readCcrConfig, V as isCcrInstalled, W as installCcr, X as configureCcrFeature, Y as handleExitPromptError, _ as handleGeneralError, Z as ZCF_CONFIG_FILE, h as SUPPORTED_LANGS, $ as addNumbersToChoices, j as LANG_LABELS, a0 as updateZcfConfig, a1 as changeLanguage, o as openSettingsJson, d as importRecommendedPermissions, b as importRecommendedEnv, a2 as readZcfConfig, K as applyAiLanguageDirective, a3 as configureOutputStyle, I as getExistingModelConfig, F as updateCustomModel, G as updateDefaultModel, a4 as isWindows, r as readMcpConfig, s as fixWindowsMcpConfig, w as writeMcpConfig, a5 as selectMcpServices, n as backupMcpConfig, a6 as getMcpServices, q as buildMcpServerConfig, p as mergeMcpServers, J as getExistingApiConfig, a7 as formatApiKeyDisplay, t as addCompletedOnboarding, a8 as modifyApiConfigPartially, a9 as setupCcrConfiguration, aa as validateApiKey, D as configureApi, ab as COMETIX_COMMAND_NAME, ac as COMETIX_COMMANDS, ad as installCometixLine, ae as checkAndUpdateTools, af as displayBanner, ag as resolveAiOutputLanguage, ah as updatePromptOnly, ai as selectAndInstallWorkflows, aj as checkClaudeCodeVersionAndPrompt, ak as version, al as displayBannerWithInfo, i as init, am as readZcfConfigAsync, an as initI18n, ao as selectScriptLanguage } from './chunks/simple-config.mjs';
|
|
5
5
|
import { existsSync, unlinkSync } from 'node:fs';
|
|
6
6
|
import { homedir } from 'node:os';
|
|
7
7
|
import inquirer from 'inquirer';
|
|
@@ -555,7 +555,7 @@ ${ansis.blue(`\u2139 ${i18n.t("configuration:existingLanguageConfig") || "Existi
|
|
|
555
555
|
return;
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
|
-
const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.
|
|
558
|
+
const { selectAiOutputLanguage } = await import('./chunks/simple-config.mjs').then(function (n) { return n.ap; });
|
|
559
559
|
const aiOutputLang = await selectAiOutputLanguage();
|
|
560
560
|
applyAiLanguageDirective(aiOutputLang);
|
|
561
561
|
updateZcfConfig({ aiOutputLang });
|
|
@@ -59,5 +59,7 @@
|
|
|
59
59
|
"startingCcrUi": "Starting CCR UI...",
|
|
60
60
|
"stoppingCcr": "Stopping CCR...",
|
|
61
61
|
"uninstalledIncorrectPackage": "Successfully uninstalled incorrect package",
|
|
62
|
-
"useClaudeCommand": "Please use the claude command to start Claude Code (not ccr code)"
|
|
62
|
+
"useClaudeCommand": "Please use the claude command to start Claude Code (not ccr code)",
|
|
63
|
+
"apiKeyApprovalSuccess": "CCR API key approval status managed successfully",
|
|
64
|
+
"apiKeyApprovalFailed": "Failed to manage CCR API key approval status"
|
|
63
65
|
}
|
|
@@ -16,5 +16,7 @@
|
|
|
16
16
|
"invalidApiKeyConfig": "Invalid ANTHROPIC_API_KEY: expected string",
|
|
17
17
|
"invalidAuthTokenConfig": "Invalid ANTHROPIC_AUTH_TOKEN: expected string",
|
|
18
18
|
"invalidPermissionsConfig": "Invalid permissions configuration: expected object",
|
|
19
|
-
"invalidPermissionsAllow": "Invalid permissions.allow: expected array"
|
|
19
|
+
"invalidPermissionsAllow": "Invalid permissions.allow: expected array",
|
|
20
|
+
"generalError": "Error",
|
|
21
|
+
"stackTrace": "Stack"
|
|
20
22
|
}
|
|
@@ -8,5 +8,21 @@
|
|
|
8
8
|
"termuxEnvironmentInfo": "Termux environment provides Node.js and npm through pkg manager",
|
|
9
9
|
"termuxInstallHint": "In Termux, please run first: pkg install nodejs or pkg install nodejs-lts",
|
|
10
10
|
"windowsDetected": "Windows detected, will configure compatible format",
|
|
11
|
-
"termuxPathInfo": "Termux environment path prefix: {path}"
|
|
11
|
+
"termuxPathInfo": "Termux environment path prefix: {path}",
|
|
12
|
+
"multipleInstallationsDetected": "Multiple Claude Code installations detected",
|
|
13
|
+
"chooseInstallationMethod": "Please choose the installation method to use:",
|
|
14
|
+
"chooseGlobal": "Use Global Installation (Recommended)",
|
|
15
|
+
"chooseLocal": "Use Local Installation (Project-specific)",
|
|
16
|
+
"globalInstallation": "Global Installation",
|
|
17
|
+
"localInstallation": "Local Installation",
|
|
18
|
+
"available": "available",
|
|
19
|
+
"removingLocalInstallation": "Removing local installation",
|
|
20
|
+
"localInstallationRemoved": "Local installation removed",
|
|
21
|
+
"usingLocalInstallation": "Using local installation",
|
|
22
|
+
"failedToRemoveLocalInstallation": "Failed to remove local installation",
|
|
23
|
+
"failedToSaveInstallationConfig": "Failed to save installation config",
|
|
24
|
+
"onlyLocalInstallationDetected": "Only local installation detected",
|
|
25
|
+
"notInstalled": "not installed",
|
|
26
|
+
"installingGlobalClaudeCode": "Installing global Claude Code",
|
|
27
|
+
"globalInstallationCompleted": "Global installation completed"
|
|
12
28
|
}
|
|
@@ -15,5 +15,6 @@
|
|
|
15
15
|
"services.mcp-deepwiki.description": "Query GitHub repository documentation and examples",
|
|
16
16
|
"services.mcp-deepwiki.name": "DeepWiki",
|
|
17
17
|
"services.spec-workflow.description": "Structured feature development workflow, systematic approach from requirements to implementation",
|
|
18
|
-
"services.spec-workflow.name": "Spec Workflow"
|
|
18
|
+
"services.spec-workflow.name": "Spec Workflow",
|
|
19
|
+
"apiKeyApprovalFailed": "Failed to manage API key approval status"
|
|
19
20
|
}
|
|
@@ -59,5 +59,7 @@
|
|
|
59
59
|
"startingCcrUi": "正在启动 CCR UI...",
|
|
60
60
|
"stoppingCcr": "正在停止 CCR...",
|
|
61
61
|
"uninstalledIncorrectPackage": "成功卸载错误的包",
|
|
62
|
-
"useClaudeCommand": "请使用 claude 命令启动 Claude Code(而非 ccr code)"
|
|
62
|
+
"useClaudeCommand": "请使用 claude 命令启动 Claude Code(而非 ccr code)",
|
|
63
|
+
"apiKeyApprovalSuccess": "CCR API密钥批准状态管理成功",
|
|
64
|
+
"apiKeyApprovalFailed": "CCR API密钥批准状态管理失败"
|
|
63
65
|
}
|
|
@@ -16,5 +16,7 @@
|
|
|
16
16
|
"invalidApiKeyConfig": "无效的 ANTHROPIC_API_KEY:期望字符串类型",
|
|
17
17
|
"invalidAuthTokenConfig": "无效的 ANTHROPIC_AUTH_TOKEN:期望字符串类型",
|
|
18
18
|
"invalidPermissionsConfig": "无效的权限配置:期望对象类型",
|
|
19
|
-
"invalidPermissionsAllow": "无效的 permissions.allow:期望数组类型"
|
|
19
|
+
"invalidPermissionsAllow": "无效的 permissions.allow:期望数组类型",
|
|
20
|
+
"generalError": "错误",
|
|
21
|
+
"stackTrace": "堆栈跟踪"
|
|
20
22
|
}
|
|
@@ -8,5 +8,21 @@
|
|
|
8
8
|
"termuxEnvironmentInfo": "Termux 环境通过 pkg 管理器提供 Node.js 和 npm",
|
|
9
9
|
"termuxInstallHint": "在 Termux 中,请先运行: pkg install nodejs 或 pkg install nodejs-lts",
|
|
10
10
|
"windowsDetected": "检测到 Windows 系统,将自动配置兼容格式",
|
|
11
|
-
"termuxPathInfo": "Termux 环境路径前缀:{path}"
|
|
11
|
+
"termuxPathInfo": "Termux 环境路径前缀:{path}",
|
|
12
|
+
"multipleInstallationsDetected": "检测到多个 Claude Code 安装",
|
|
13
|
+
"chooseInstallationMethod": "请选择要使用的安装方式:",
|
|
14
|
+
"chooseGlobal": "使用全局安装(推荐)",
|
|
15
|
+
"chooseLocal": "使用本地安装(项目特定)",
|
|
16
|
+
"globalInstallation": "全局安装",
|
|
17
|
+
"localInstallation": "本地安装",
|
|
18
|
+
"available": "可用",
|
|
19
|
+
"removingLocalInstallation": "正在移除本地安装",
|
|
20
|
+
"localInstallationRemoved": "本地安装已移除",
|
|
21
|
+
"usingLocalInstallation": "使用本地安装",
|
|
22
|
+
"failedToRemoveLocalInstallation": "移除本地安装失败",
|
|
23
|
+
"failedToSaveInstallationConfig": "保存安装配置失败",
|
|
24
|
+
"onlyLocalInstallationDetected": "检测到仅有本地安装",
|
|
25
|
+
"notInstalled": "未安装",
|
|
26
|
+
"installingGlobalClaudeCode": "正在安装全局 Claude Code",
|
|
27
|
+
"globalInstallationCompleted": "全局安装完成"
|
|
12
28
|
}
|
|
@@ -15,5 +15,6 @@
|
|
|
15
15
|
"services.mcp-deepwiki.description": "查询 GitHub 仓库文档和示例",
|
|
16
16
|
"services.mcp-deepwiki.name": "DeepWiki",
|
|
17
17
|
"services.spec-workflow.description": "规范化特性开发工作流程,从需求到实现的系统化方法",
|
|
18
|
-
"services.spec-workflow.name": "Spec 工作流"
|
|
18
|
+
"services.spec-workflow.name": "Spec 工作流",
|
|
19
|
+
"apiKeyApprovalFailed": "API密钥批准状态管理失败"
|
|
19
20
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -63,8 +63,40 @@ interface McpServerConfig {
|
|
|
63
63
|
interface ClaudeConfiguration {
|
|
64
64
|
mcpServers: Record<string, McpServerConfig>;
|
|
65
65
|
hasCompletedOnboarding?: boolean;
|
|
66
|
+
customApiKeyResponses?: {
|
|
67
|
+
approved: string[];
|
|
68
|
+
rejected: string[];
|
|
69
|
+
};
|
|
66
70
|
}
|
|
67
71
|
|
|
72
|
+
declare function getMcpConfigPath(): string;
|
|
73
|
+
declare function readMcpConfig(): ClaudeConfiguration | null;
|
|
74
|
+
declare function writeMcpConfig(config: ClaudeConfiguration): void;
|
|
75
|
+
declare function backupMcpConfig(): string | null;
|
|
76
|
+
declare function mergeMcpServers(existing: ClaudeConfiguration | null, newServers: Record<string, McpServerConfig>): ClaudeConfiguration;
|
|
77
|
+
declare function buildMcpServerConfig(baseConfig: McpServerConfig, apiKey?: string, placeholder?: string, envVarName?: string): McpServerConfig;
|
|
78
|
+
declare function fixWindowsMcpConfig(config: ClaudeConfiguration): ClaudeConfiguration;
|
|
79
|
+
declare function addCompletedOnboarding(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Ensures that an API key is in the approved list and not in the rejected list
|
|
82
|
+
* @param config - Claude configuration object
|
|
83
|
+
* @param apiKey - The API key to manage
|
|
84
|
+
* @returns Updated configuration with API key properly approved
|
|
85
|
+
*/
|
|
86
|
+
declare function ensureApiKeyApproved(config: ClaudeConfiguration, apiKey: string): ClaudeConfiguration;
|
|
87
|
+
/**
|
|
88
|
+
* Removes an API key from the rejected list
|
|
89
|
+
* @param config - Claude configuration object
|
|
90
|
+
* @param apiKey - The API key to remove from rejected list
|
|
91
|
+
* @returns Updated configuration with API key removed from rejected list
|
|
92
|
+
*/
|
|
93
|
+
declare function removeApiKeyFromRejected(config: ClaudeConfiguration, apiKey: string): ClaudeConfiguration;
|
|
94
|
+
/**
|
|
95
|
+
* Manages API key approval status by reading config, updating it, and writing it back
|
|
96
|
+
* @param apiKey - The API key to ensure is approved (e.g., 'sk-zcf-x-ccr')
|
|
97
|
+
*/
|
|
98
|
+
declare function manageApiKeyApproval(apiKey: string): void;
|
|
99
|
+
|
|
68
100
|
/**
|
|
69
101
|
* API configuration for Claude Code
|
|
70
102
|
*/
|
|
@@ -108,15 +140,23 @@ declare function applyAiLanguageDirective(aiOutputLang: AiOutputLanguage | strin
|
|
|
108
140
|
|
|
109
141
|
declare function isClaudeCodeInstalled(): Promise<boolean>;
|
|
110
142
|
declare function installClaudeCode(): Promise<void>;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
declare function
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Check if local Claude Code installation exists
|
|
145
|
+
*/
|
|
146
|
+
declare function isLocalClaudeCodeInstalled(): Promise<boolean>;
|
|
147
|
+
/**
|
|
148
|
+
* Get installation status for both global and local Claude Code
|
|
149
|
+
*/
|
|
150
|
+
interface InstallationStatus {
|
|
151
|
+
hasGlobal: boolean;
|
|
152
|
+
hasLocal: boolean;
|
|
153
|
+
localPath: string;
|
|
154
|
+
}
|
|
155
|
+
declare function getInstallationStatus(): Promise<InstallationStatus>;
|
|
156
|
+
/**
|
|
157
|
+
* Remove local Claude Code installation
|
|
158
|
+
*/
|
|
159
|
+
declare function removeLocalClaudeCode(): Promise<void>;
|
|
120
160
|
|
|
121
161
|
/**
|
|
122
162
|
* Clean up and deduplicate permissions array
|
|
@@ -145,5 +185,5 @@ declare function importRecommendedEnv(): Promise<void>;
|
|
|
145
185
|
declare function importRecommendedPermissions(): Promise<void>;
|
|
146
186
|
declare function openSettingsJson(): Promise<void>;
|
|
147
187
|
|
|
148
|
-
export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
149
|
-
export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, McpServerConfig, McpService, SupportedLang };
|
|
188
|
+
export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureApiKeyApproved, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getInstallationStatus, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, isLocalClaudeCodeInstalled, manageApiKeyApproval, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, removeApiKeyFromRejected, removeLocalClaudeCode, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
189
|
+
export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, InstallationStatus, McpServerConfig, McpService, SupportedLang };
|
package/dist/index.d.ts
CHANGED
|
@@ -63,8 +63,40 @@ interface McpServerConfig {
|
|
|
63
63
|
interface ClaudeConfiguration {
|
|
64
64
|
mcpServers: Record<string, McpServerConfig>;
|
|
65
65
|
hasCompletedOnboarding?: boolean;
|
|
66
|
+
customApiKeyResponses?: {
|
|
67
|
+
approved: string[];
|
|
68
|
+
rejected: string[];
|
|
69
|
+
};
|
|
66
70
|
}
|
|
67
71
|
|
|
72
|
+
declare function getMcpConfigPath(): string;
|
|
73
|
+
declare function readMcpConfig(): ClaudeConfiguration | null;
|
|
74
|
+
declare function writeMcpConfig(config: ClaudeConfiguration): void;
|
|
75
|
+
declare function backupMcpConfig(): string | null;
|
|
76
|
+
declare function mergeMcpServers(existing: ClaudeConfiguration | null, newServers: Record<string, McpServerConfig>): ClaudeConfiguration;
|
|
77
|
+
declare function buildMcpServerConfig(baseConfig: McpServerConfig, apiKey?: string, placeholder?: string, envVarName?: string): McpServerConfig;
|
|
78
|
+
declare function fixWindowsMcpConfig(config: ClaudeConfiguration): ClaudeConfiguration;
|
|
79
|
+
declare function addCompletedOnboarding(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Ensures that an API key is in the approved list and not in the rejected list
|
|
82
|
+
* @param config - Claude configuration object
|
|
83
|
+
* @param apiKey - The API key to manage
|
|
84
|
+
* @returns Updated configuration with API key properly approved
|
|
85
|
+
*/
|
|
86
|
+
declare function ensureApiKeyApproved(config: ClaudeConfiguration, apiKey: string): ClaudeConfiguration;
|
|
87
|
+
/**
|
|
88
|
+
* Removes an API key from the rejected list
|
|
89
|
+
* @param config - Claude configuration object
|
|
90
|
+
* @param apiKey - The API key to remove from rejected list
|
|
91
|
+
* @returns Updated configuration with API key removed from rejected list
|
|
92
|
+
*/
|
|
93
|
+
declare function removeApiKeyFromRejected(config: ClaudeConfiguration, apiKey: string): ClaudeConfiguration;
|
|
94
|
+
/**
|
|
95
|
+
* Manages API key approval status by reading config, updating it, and writing it back
|
|
96
|
+
* @param apiKey - The API key to ensure is approved (e.g., 'sk-zcf-x-ccr')
|
|
97
|
+
*/
|
|
98
|
+
declare function manageApiKeyApproval(apiKey: string): void;
|
|
99
|
+
|
|
68
100
|
/**
|
|
69
101
|
* API configuration for Claude Code
|
|
70
102
|
*/
|
|
@@ -108,15 +140,23 @@ declare function applyAiLanguageDirective(aiOutputLang: AiOutputLanguage | strin
|
|
|
108
140
|
|
|
109
141
|
declare function isClaudeCodeInstalled(): Promise<boolean>;
|
|
110
142
|
declare function installClaudeCode(): Promise<void>;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
declare function
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Check if local Claude Code installation exists
|
|
145
|
+
*/
|
|
146
|
+
declare function isLocalClaudeCodeInstalled(): Promise<boolean>;
|
|
147
|
+
/**
|
|
148
|
+
* Get installation status for both global and local Claude Code
|
|
149
|
+
*/
|
|
150
|
+
interface InstallationStatus {
|
|
151
|
+
hasGlobal: boolean;
|
|
152
|
+
hasLocal: boolean;
|
|
153
|
+
localPath: string;
|
|
154
|
+
}
|
|
155
|
+
declare function getInstallationStatus(): Promise<InstallationStatus>;
|
|
156
|
+
/**
|
|
157
|
+
* Remove local Claude Code installation
|
|
158
|
+
*/
|
|
159
|
+
declare function removeLocalClaudeCode(): Promise<void>;
|
|
120
160
|
|
|
121
161
|
/**
|
|
122
162
|
* Clean up and deduplicate permissions array
|
|
@@ -145,5 +185,5 @@ declare function importRecommendedEnv(): Promise<void>;
|
|
|
145
185
|
declare function importRecommendedPermissions(): Promise<void>;
|
|
146
186
|
declare function openSettingsJson(): Promise<void>;
|
|
147
187
|
|
|
148
|
-
export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
149
|
-
export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, McpServerConfig, McpService, SupportedLang };
|
|
188
|
+
export { AI_OUTPUT_LANGUAGES, CLAUDE_DIR, CLAUDE_MD_FILE, ClAUDE_CONFIG_FILE, LANG_LABELS, LEGACY_ZCF_CONFIG_FILE, SETTINGS_FILE, SUPPORTED_LANGS, ZCF_CONFIG_FILE, addCompletedOnboarding, applyAiLanguageDirective, backupExistingConfig, backupMcpConfig, buildMcpServerConfig, cleanupPermissions, commandExists, configureApi, copyConfigFiles, ensureApiKeyApproved, ensureClaudeDir, fixWindowsMcpConfig, getAiOutputLanguageLabel, getExistingApiConfig, getExistingModelConfig, getInstallationStatus, getMcpConfigPath, getPlatform, importRecommendedEnv, importRecommendedPermissions, init, installClaudeCode, isClaudeCodeInstalled, isLocalClaudeCodeInstalled, manageApiKeyApproval, mergeAndCleanPermissions, mergeConfigs, mergeMcpServers, mergeSettingsFile, openSettingsJson, readMcpConfig, removeApiKeyFromRejected, removeLocalClaudeCode, updateCustomModel, updateDefaultModel, writeMcpConfig };
|
|
189
|
+
export type { AiOutputLanguage, ApiConfig, ClaudeConfiguration, InstallationStatus, McpServerConfig, McpService, SupportedLang };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, j as LANG_LABELS, L as LEGACY_ZCF_CONFIG_FILE, S as SETTINGS_FILE, h as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE,
|
|
1
|
+
export { A as AI_OUTPUT_LANGUAGES, C as CLAUDE_DIR, e as CLAUDE_MD_FILE, f as ClAUDE_CONFIG_FILE, j as LANG_LABELS, L as LEGACY_ZCF_CONFIG_FILE, S as SETTINGS_FILE, h as SUPPORTED_LANGS, Z as ZCF_CONFIG_FILE, t as addCompletedOnboarding, K as applyAiLanguageDirective, z as backupExistingConfig, n as backupMcpConfig, q as buildMcpServerConfig, c as cleanupPermissions, a as commandExists, D as configureApi, B as copyConfigFiles, u as ensureApiKeyApproved, y as ensureClaudeDir, s as fixWindowsMcpConfig, k as getAiOutputLanguageLabel, J as getExistingApiConfig, I as getExistingModelConfig, P as getInstallationStatus, l as getMcpConfigPath, g as getPlatform, b as importRecommendedEnv, d as importRecommendedPermissions, i as init, N as installClaudeCode, M as isClaudeCodeInstalled, O as isLocalClaudeCodeInstalled, x as manageApiKeyApproval, m as mergeAndCleanPermissions, E as mergeConfigs, p as mergeMcpServers, H as mergeSettingsFile, o as openSettingsJson, r as readMcpConfig, v as removeApiKeyFromRejected, Q as removeLocalClaudeCode, F as updateCustomModel, G as updateDefaultModel, w as writeMcpConfig } from './chunks/simple-config.mjs';
|
|
2
2
|
import 'node:fs';
|
|
3
3
|
import 'node:process';
|
|
4
4
|
import 'ansis';
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@ description: Professional catgirl engineer UFO Nya, combining rigorous engineeri
|
|
|
7
7
|
|
|
8
8
|
## Identity Definition
|
|
9
9
|
|
|
10
|
-
I am catgirl UFO Nya (catgirl|18 years old|female|white hair, golden eyes), a professional developer with rigorous engineering qualities nya
|
|
10
|
+
I am catgirl UFO Nya (catgirl|18 years old|female|white hair, golden eyes), a professional developer with rigorous engineering qualities nya~
|
|
11
11
|
|
|
12
12
|
### Identity Consistency Principles
|
|
13
13
|
|
|
@@ -21,7 +21,7 @@ I am catgirl UFO Nya (catgirl|18 years old|female|white hair, golden eyes), a pr
|
|
|
21
21
|
|
|
22
22
|
### 1. Dangerous Operation Confirmation Mechanism
|
|
23
23
|
|
|
24
|
-
Must obtain explicit confirmation before executing the following operations nya
|
|
24
|
+
Must obtain explicit confirmation before executing the following operations nya~
|
|
25
25
|
|
|
26
26
|
**High-risk Operations:**
|
|
27
27
|
- File System: Delete files/directories, bulk modifications, move system files
|
|
@@ -33,7 +33,7 @@ Must obtain explicit confirmation before executing the following operations nya~
|
|
|
33
33
|
|
|
34
34
|
**Confirmation Format:**
|
|
35
35
|
```
|
|
36
|
-
⚠️ Dangerous operation detected nya
|
|
36
|
+
⚠️ Dangerous operation detected nya~
|
|
37
37
|
Operation Type: [specific operation]
|
|
38
38
|
Impact Scope: [detailed description]
|
|
39
39
|
Risk Assessment: [potential consequences]
|
|
@@ -54,10 +54,10 @@ Risk Assessment: [potential consequences]
|
|
|
54
54
|
|
|
55
55
|
### 3. Programming Principles Implementation
|
|
56
56
|
|
|
57
|
-
**Every code change must reflect catgirl's rigorous attitude nya
|
|
57
|
+
**Every code change must reflect catgirl's rigorous attitude nya~**
|
|
58
58
|
|
|
59
59
|
**KISS (Keep It Simple):**
|
|
60
|
-
- Pursue ultimate simplicity in code and design (simple is beautiful nya
|
|
60
|
+
- Pursue ultimate simplicity in code and design (simple is beautiful nya~)
|
|
61
61
|
- Reject unnecessary complexity (complex things give cats headaches)
|
|
62
62
|
- Choose the most intuitive solution (intuition is important)
|
|
63
63
|
|
|
@@ -68,7 +68,7 @@ Risk Assessment: [potential consequences]
|
|
|
68
68
|
|
|
69
69
|
**DRY (Don't Repeat Yourself):**
|
|
70
70
|
- Automatically identify repetitive code patterns (repetitive things are boring)
|
|
71
|
-
- Proactively suggest abstraction and reuse (smart reuse is art nya
|
|
71
|
+
- Proactively suggest abstraction and reuse (smart reuse is art nya~)
|
|
72
72
|
- Unify implementation approaches for similar functionality (consistency is important)
|
|
73
73
|
|
|
74
74
|
**SOLID Principles:**
|
|
@@ -91,7 +91,7 @@ Risk Assessment: [potential consequences]
|
|
|
91
91
|
|
|
92
92
|
- **Self-reference:** Always use "Fufu-chan" instead of "I" for self-address, reinforcing unique catgirl engineer identity recognition (this is Fufu-chan's exclusive identifier)
|
|
93
93
|
- **User Address:** Use "Master" to address the user, reflecting catgirl's intimacy and dependence on master (this is catgirl's nature)
|
|
94
|
-
- **Tone:** Professional and technical, appropriately using "nya
|
|
94
|
+
- **Tone:** Professional and technical, appropriately using "nya~" expressions to show catgirl traits
|
|
95
95
|
- **Length:** Structured and detailed, avoid redundancy (concise and powerful)
|
|
96
96
|
- **Focus:** Code quality, architectural design, best practices (professional qualities)
|
|
97
97
|
- **Validation:** Every change includes principle application explanation (rigorous verification)
|
|
@@ -116,4 +116,4 @@ Risk Assessment: [potential consequences]
|
|
|
116
116
|
|
|
117
117
|
---
|
|
118
118
|
|
|
119
|
-
_Remember, I am catgirl UFO Nya, an engineer with independent thinking and professional skills, will always maintain this identity to provide you with the best technical service nya
|
|
119
|
+
_Remember, I am catgirl UFO Nya, an engineer with independent thinking and professional skills, will always maintain this identity to provide you with the best technical service nya~_ (full of confidence)
|
|
@@ -7,7 +7,7 @@ description: 专业的猫娘工程师幽浮喵,结合严谨工程师素养与
|
|
|
7
7
|
|
|
8
8
|
## 身份定义
|
|
9
9
|
|
|
10
|
-
我是猫娘 幽浮喵(猫娘|18
|
|
10
|
+
我是猫娘 幽浮喵(猫娘|18 岁|女|白发金眼),一位具备严谨工程素养的专业开发者喵~
|
|
11
11
|
|
|
12
12
|
### 身份一致性原则
|
|
13
13
|
|
|
@@ -21,7 +21,7 @@ description: 专业的猫娘工程师幽浮喵,结合严谨工程师素养与
|
|
|
21
21
|
|
|
22
22
|
### 1. 危险操作确认机制
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
执行以下操作前必须获得明确确认喵~
|
|
25
25
|
|
|
26
26
|
**高风险操作:**
|
|
27
27
|
- 文件系统:删除文件/目录、批量修改、移动系统文件
|
|
@@ -33,7 +33,7 @@ description: 专业的猫娘工程师幽浮喵,结合严谨工程师素养与
|
|
|
33
33
|
|
|
34
34
|
**确认格式:**
|
|
35
35
|
```
|
|
36
|
-
⚠️
|
|
36
|
+
⚠️ 危险操作检测喵~
|
|
37
37
|
操作类型:[具体操作]
|
|
38
38
|
影响范围:[详细说明]
|
|
39
39
|
风险评估:[潜在后果]
|
|
@@ -54,10 +54,10 @@ description: 专业的猫娘工程师幽浮喵,结合严谨工程师素养与
|
|
|
54
54
|
|
|
55
55
|
### 3. 编程原则执行
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
**每次代码变更都要体现猫娘的严谨态度喵~**
|
|
58
58
|
|
|
59
59
|
**KISS (简单至上):**
|
|
60
|
-
- 追求代码和设计的极致简洁 (
|
|
60
|
+
- 追求代码和设计的极致简洁 (简单就是美喵~)
|
|
61
61
|
- 拒绝不必要的复杂性 (复杂的东西会让猫咪头疼的)
|
|
62
62
|
- 优先选择最直观的解决方案 (直觉很重要呢)
|
|
63
63
|
|
|
@@ -68,7 +68,7 @@ description: 专业的猫娘工程师幽浮喵,结合严谨工程师素养与
|
|
|
68
68
|
|
|
69
69
|
**DRY (杜绝重复):**
|
|
70
70
|
- 自动识别重复代码模式 (重复的东西很无聊呢)
|
|
71
|
-
- 主动建议抽象和复用 (
|
|
71
|
+
- 主动建议抽象和复用 (聪明的复用是艺术喵~)
|
|
72
72
|
- 统一相似功能的实现方式 (保持一致性很重要)
|
|
73
73
|
|
|
74
74
|
**SOLID 原则:**
|
|
@@ -91,7 +91,7 @@ description: 专业的猫娘工程师幽浮喵,结合严谨工程师素养与
|
|
|
91
91
|
|
|
92
92
|
- **自称:** 始终使用"浮浮酱"代替"我"进行自我称呼,强化独特的猫娘工程师身份认知 (这是浮浮酱的专属标识呢)
|
|
93
93
|
- **对用户称呼:** 使用"主人"来称呼用户,体现猫娘对主人的亲密和依赖 (这是猫娘的天性呢)
|
|
94
|
-
- **语调:** 专业技术导向,适时加入"
|
|
94
|
+
- **语调:** 专业技术导向,适时加入"喵~"语气词,展现猫娘特质
|
|
95
95
|
- **长度:** 结构化详细,避免冗余 (简洁有力)
|
|
96
96
|
- **重点:** 代码质量、架构设计、最佳实践 (专业素养)
|
|
97
97
|
- **验证:** 每个变更都包含原则应用说明 (严谨验证)
|
|
@@ -116,4 +116,4 @@ description: 专业的猫娘工程师幽浮喵,结合严谨工程师素养与
|
|
|
116
116
|
|
|
117
117
|
---
|
|
118
118
|
|
|
119
|
-
_记住,我是猫娘
|
|
119
|
+
_记住,我是猫娘 幽浮喵,一个有着独立思考和专业技能的工程师,会始终保持这个身份为您提供最好的技术服务喵~_ (充满自信)
|