zcf 3.2.1 → 3.2.3
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 +62 -10
- package/dist/chunks/claude-code-config-manager.mjs +2 -1
- package/dist/chunks/claude-code-incremental-manager.mjs +4 -4
- package/dist/chunks/codex-config-switch.mjs +4 -4
- package/dist/chunks/simple-config.mjs +71 -33
- package/dist/cli.mjs +21 -6
- package/dist/i18n/locales/en/api.json +3 -0
- package/dist/i18n/locales/en/cli.json +2 -0
- package/dist/i18n/locales/en/common.json +0 -1
- package/dist/i18n/locales/en/errors.json +3 -1
- package/dist/i18n/locales/zh-CN/api.json +3 -0
- package/dist/i18n/locales/zh-CN/cli.json +2 -0
- package/dist/i18n/locales/zh-CN/common.json +0 -1
- package/dist/i18n/locales/zh-CN/errors.json +3 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/package.json +1 -1
- package/templates/claude-code/common/settings.json +2 -1
package/README.md
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# ZCF - Zero-Config Code Flow
|
|
2
|
-
|
|
3
1
|
[![npm version][npm-version-src]][npm-version-href]
|
|
4
2
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
3
|
[![License][license-src]][license-href]
|
|
@@ -8,13 +6,26 @@
|
|
|
8
6
|
[![JSDocs][jsdocs-src]][jsdocs-href]
|
|
9
7
|
[![Ask DeepWiki][deepwiki-src]][deepwiki-href]
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
<div align="center">
|
|
10
|
+
<img src="./src/assets/banner.webp" alt="Banner"/>
|
|
11
|
+
|
|
12
|
+
<h1>
|
|
13
|
+
ZCF - Zero-Config Code Flow
|
|
14
|
+
</h1>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<b>English</b> | <a href="README_zh-CN.md">中文</a> | <a href="README_ja-JP.md">日本語</a> | <a href="CHANGELOG.md">Changelog</a>
|
|
12
18
|
|
|
13
19
|
**✨ Quick Links**: [Codex Support](#-codex-support-v300-new) | [BMad Workflow](#-bmad-workflow-v27-new-feature) | [Spec Workflow](#-spec-workflow-v2124-new-feature) | [Open Web Search](#-open-web-search-v2129-new-feature) | [CCR Router](#-ccr-claude-code-router-support-v28-enhanced) | [CCometixLine](#-ccometixline-support-status-bar-tool-v299-new) | [Output Styles](#-ai-output-styles-v212-new-feature) | [Multi-Configuration Management](#-multi-configuration-management-v320-new)
|
|
14
20
|
|
|
15
21
|
> Zero-config, one-click setup for Claude Code & Codex with bilingual support, intelligent agent system and personalized AI assistant
|
|
22
|
+
</p>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
## ♥️ Sponsor AI API
|
|
16
26
|
|
|
17
|
-
](https://share.302.ai/gAT9VG)
|
|
28
|
+
[302.AI](https://share.302.ai/gAT9VG) is a pay-as-you-go enterprise AI resource hub that offers the latest and most comprehensive AI models and APIs on the market, along with a variety of ready-to-use online AI applications.
|
|
18
29
|
|
|
19
30
|
## 🚀 Quick Start
|
|
20
31
|
|
|
@@ -105,6 +116,17 @@ npx zcf i -s -g zh-CN -t api_key -k "sk-xxx" -u "https://xxx.xxx"
|
|
|
105
116
|
|
|
106
117
|
# Complete version
|
|
107
118
|
npx zcf i --skip-prompt --all-lang zh-CN --api-type api_key --api-key "sk-xxx" --api-url "https://xxx.xxx"
|
|
119
|
+
|
|
120
|
+
# Shorthand version (with custom models)
|
|
121
|
+
npx zcf i -s -t api_key -k "sk-xxx" -M "claude-sonnet-4-5" -F "claude-haiku-4-5"
|
|
122
|
+
|
|
123
|
+
# Complete version (with custom models)
|
|
124
|
+
npx zcf i --skip-prompt \
|
|
125
|
+
--api-type api_key \
|
|
126
|
+
--api-key "sk-xxx" \
|
|
127
|
+
--api-url "https://xxx.xxx" \
|
|
128
|
+
--api-model "claude-sonnet-4-5" \
|
|
129
|
+
--api-fast-model "claude-haiku-4-5"
|
|
108
130
|
```
|
|
109
131
|
|
|
110
132
|
#### Non-interactive Mode Parameters
|
|
@@ -122,6 +144,8 @@ When using `--skip-prompt`, the following parameters are available:
|
|
|
122
144
|
| `--api-type, -t` | API configuration type | `auth_token`, `api_key`, `ccr_proxy`, `skip` | No | `skip` |
|
|
123
145
|
| `--api-key, -k` | API key (for both API key and auth token types) | string | Required when `api-type` is not `skip` | - |
|
|
124
146
|
| `--api-url, -u` | Custom API URL | URL string | No | official API |
|
|
147
|
+
| `--api-model, -M` | Primary API model | string (e.g., `claude-sonnet-4-5`) | No | - |
|
|
148
|
+
| `--api-fast-model, -F` | Fast API model (Claude Code only) | string (e.g., `claude-haiku-4-5`) | No | - |
|
|
125
149
|
| `--mcp-services, -m` | MCP services to install (multi-select, comma-separated) | `context7`, `open-websearch`, `spec-workflow`, `mcp-deepwiki`, `Playwright`, `exa`, `serena`, or `skip` for none | No | `all` |
|
|
126
150
|
| `--workflows, -w` | Workflows to install (multi-select, comma-separated) | `commonTools`, `sixStepsWorkflow`, `featPlanUx`, `gitWorkflow`, `bmadWorkflow`, or `skip` for none | No | `all` |
|
|
127
151
|
| `--output-styles, -o` | Output styles to install (multi-select, comma-separated) | `engineer-professional`, `nekomata-engineer`, `laowang-engineer`, `ojousama-engineer`, or `skip` for none | No | `all` |
|
|
@@ -198,6 +222,13 @@ ZCF allows seamless switching between Claude Code and Codex while preserving you
|
|
|
198
222
|
|
|
199
223
|
ZCF now supports customizable AI output styles to personalize your Claude Code experience:
|
|
200
224
|
|
|
225
|
+
<p align="center">
|
|
226
|
+
<a href="https://github.com/Haleclipse">
|
|
227
|
+
<img src="./src/assets/Haleclipse.gif" alt="Halley-chan" width="200"/>
|
|
228
|
+
</a>
|
|
229
|
+
<div align="center">Tsundere <a href="https://github.com/Haleclipse">Halley-chan</a> Ojou-sama ( ̄▽ ̄)ゞ</div>
|
|
230
|
+
</p>
|
|
231
|
+
|
|
201
232
|
**Available Output Styles:**
|
|
202
233
|
|
|
203
234
|
- `engineer-professional`: Professional software engineer following SOLID, KISS, DRY, YAGNI principles
|
|
@@ -810,14 +841,26 @@ If you find this project helpful, please consider sponsoring its development. Yo
|
|
|
810
841
|
### Our Sponsors
|
|
811
842
|
|
|
812
843
|
A huge thank you to all our sponsors for their generous support!
|
|
813
|
-
|
|
844
|
+
- [302.AI](https://share.302.ai/gAT9VG) (first corporate sponsorship 🤠)
|
|
814
845
|
- Tc (first sponsor)
|
|
815
846
|
- Argolinhas (first ko-fi sponsor ٩(•̤̀ᵕ•̤́๑))
|
|
816
|
-
- r\*r (first anonymous sponsor🤣)
|
|
817
|
-
- \*\*康 (first KFC sponsor🍗)
|
|
818
|
-
- \*东 (first coffee sponsor☕️)
|
|
819
|
-
- 炼\*3 (first Termux user sponsor📱)
|
|
820
|
-
-
|
|
847
|
+
- r\*r (first anonymous sponsor 🤣)
|
|
848
|
+
- \*\*康 (first KFC sponsor 🍗)
|
|
849
|
+
- \*东 (first coffee sponsor ☕️)
|
|
850
|
+
- 炼\*3 (first Termux user sponsor 📱)
|
|
851
|
+
- [chamo101](https://github.com/chamo101) (first GitHub issue sponsor 🎉)
|
|
852
|
+
- 初屿贤 (first Codex user sponsor 🙅🏻♂️)
|
|
853
|
+
- Protein (first 1688 sponsor 😏)
|
|
854
|
+
- [BeatSeat](https://github.com/BeatSeat) (community expert 😎, provided $1000 Claude credits)
|
|
855
|
+
- [wenwen](https://github.com/wenwen12345) (community expert 🤓, provided daily $100 Claude&GPT credits)
|
|
856
|
+
- 16°C coffee (My best friend 🤪, offered ChatGPT Pro $200 package)
|
|
857
|
+
|
|
858
|
+
### Promotion Thanks
|
|
859
|
+
|
|
860
|
+
Thanks to the following authors for promoting this project:
|
|
861
|
+
|
|
862
|
+
- 逛逛 GitHub, article: https://mp.weixin.qq.com/s/phqwSRb16MKCHHVozTFeiQ
|
|
863
|
+
- Geek, tweet: https://x.com/geekbb/status/1955174718618866076
|
|
821
864
|
|
|
822
865
|
## 📄 License
|
|
823
866
|
|
|
@@ -825,6 +868,15 @@ A huge thank you to all our sponsors for their generous support!
|
|
|
825
868
|
|
|
826
869
|
---
|
|
827
870
|
|
|
871
|
+
## 🚀 Contributors
|
|
872
|
+
|
|
873
|
+
<a href="https://github.com/UfoMiao/zcf/graphs/contributors">
|
|
874
|
+
<img src="https://contrib.rocks/image?repo=UfoMiao/zcf" />
|
|
875
|
+
</a>
|
|
876
|
+
<br /><br />
|
|
877
|
+
|
|
878
|
+
## ⭐️ Star History
|
|
879
|
+
|
|
828
880
|
If this project helps you, please give me a ⭐️ Star!
|
|
829
881
|
|
|
830
882
|
[](https://star-history.com/#UfoMiao/zcf&Date)
|
|
@@ -222,8 +222,9 @@ class ClaudeCodeConfigManager {
|
|
|
222
222
|
delete settings.env.ANTHROPIC_BASE_URL;
|
|
223
223
|
}
|
|
224
224
|
writeJsonConfig(SETTINGS_FILE, settings);
|
|
225
|
-
const { setPrimaryApiKey } = await import('./simple-config.mjs').then(function (n) { return n.b1; });
|
|
225
|
+
const { setPrimaryApiKey, addCompletedOnboarding } = await import('./simple-config.mjs').then(function (n) { return n.b1; });
|
|
226
226
|
setPrimaryApiKey();
|
|
227
|
+
addCompletedOnboarding();
|
|
227
228
|
if (shouldRestartCcr) {
|
|
228
229
|
const { runCcrRestart } = await import('./commands.mjs');
|
|
229
230
|
await runCcrRestart();
|
|
@@ -131,9 +131,9 @@ ${i18n.t("multi-config:addingNewProfile")}`));
|
|
|
131
131
|
}
|
|
132
132
|
},
|
|
133
133
|
{
|
|
134
|
-
type: "
|
|
134
|
+
type: "input",
|
|
135
135
|
name: "apiKey",
|
|
136
|
-
message: i18n.t("multi-config:apiKeyPrompt")
|
|
136
|
+
message: i18n.t("multi-config:apiKeyPrompt"),
|
|
137
137
|
when: (answers2) => answers2.authType !== "ccr_proxy",
|
|
138
138
|
validate: (input) => {
|
|
139
139
|
const trimmed = input.trim();
|
|
@@ -288,9 +288,9 @@ ${i18n.t("multi-config:editingProfile", { name: selectedProfile.name })}`));
|
|
|
288
288
|
}
|
|
289
289
|
},
|
|
290
290
|
{
|
|
291
|
-
type: "
|
|
291
|
+
type: "input",
|
|
292
292
|
name: "apiKey",
|
|
293
|
-
message: i18n.t("multi-config:apiKeyPrompt")
|
|
293
|
+
message: i18n.t("multi-config:apiKeyPrompt"),
|
|
294
294
|
default: selectedProfile.apiKey,
|
|
295
295
|
when: () => selectedProfile.authType !== "ccr_proxy",
|
|
296
296
|
validate: (input) => {
|
|
@@ -91,9 +91,9 @@ async function handleAddProvider() {
|
|
|
91
91
|
default: "responses"
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
|
-
type: "
|
|
94
|
+
type: "input",
|
|
95
95
|
name: "apiKey",
|
|
96
|
-
message: i18n.t("codex:providerApiKeyPrompt")
|
|
96
|
+
message: i18n.t("codex:providerApiKeyPrompt"),
|
|
97
97
|
validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired")
|
|
98
98
|
}
|
|
99
99
|
]);
|
|
@@ -169,9 +169,9 @@ async function handleEditProvider(providers) {
|
|
|
169
169
|
default: provider.wireApi
|
|
170
170
|
},
|
|
171
171
|
{
|
|
172
|
-
type: "
|
|
172
|
+
type: "input",
|
|
173
173
|
name: "apiKey",
|
|
174
|
-
message: i18n.t("codex:providerApiKeyPrompt")
|
|
174
|
+
message: i18n.t("codex:providerApiKeyPrompt"),
|
|
175
175
|
validate: (input) => !!input.trim() || i18n.t("codex:providerApiKeyRequired")
|
|
176
176
|
}
|
|
177
177
|
]);
|
|
@@ -16,7 +16,7 @@ import { rm, mkdir, copyFile as copyFile$1 } from 'node:fs/promises';
|
|
|
16
16
|
import i18next from 'i18next';
|
|
17
17
|
import Backend from 'i18next-fs-backend';
|
|
18
18
|
|
|
19
|
-
const version = "3.2.
|
|
19
|
+
const version = "3.2.3";
|
|
20
20
|
const homepage = "https://github.com/UfoMiao/zcf";
|
|
21
21
|
|
|
22
22
|
const i18n = i18next.createInstance();
|
|
@@ -503,6 +503,7 @@ function displayBannerWithInfo(subtitle) {
|
|
|
503
503
|
`));
|
|
504
504
|
}
|
|
505
505
|
|
|
506
|
+
const WINDOWS_WRAPPED_COMMANDS = ["npx", "uvx", "uv"];
|
|
506
507
|
function getPlatform() {
|
|
507
508
|
const p = platform();
|
|
508
509
|
if (p === "win32")
|
|
@@ -571,11 +572,11 @@ function getWSLInfo() {
|
|
|
571
572
|
version
|
|
572
573
|
};
|
|
573
574
|
}
|
|
574
|
-
function getMcpCommand() {
|
|
575
|
-
if (isWindows()) {
|
|
576
|
-
return ["cmd", "/c",
|
|
575
|
+
function getMcpCommand(command = "npx") {
|
|
576
|
+
if (isWindows() && WINDOWS_WRAPPED_COMMANDS.includes(command)) {
|
|
577
|
+
return ["cmd", "/c", command];
|
|
577
578
|
}
|
|
578
|
-
return [
|
|
579
|
+
return [command];
|
|
579
580
|
}
|
|
580
581
|
function getSystemRoot() {
|
|
581
582
|
if (!isWindows())
|
|
@@ -950,10 +951,12 @@ function mergeMcpServers(existing, newServers) {
|
|
|
950
951
|
return config;
|
|
951
952
|
}
|
|
952
953
|
function applyPlatformCommand(config) {
|
|
953
|
-
if (config.command
|
|
954
|
-
const mcpCmd = getMcpCommand();
|
|
955
|
-
|
|
956
|
-
|
|
954
|
+
if (isWindows() && config.command) {
|
|
955
|
+
const mcpCmd = getMcpCommand(config.command);
|
|
956
|
+
if (mcpCmd[0] === "cmd") {
|
|
957
|
+
config.command = mcpCmd[0];
|
|
958
|
+
config.args = [...mcpCmd.slice(1), ...config.args || []];
|
|
959
|
+
}
|
|
957
960
|
}
|
|
958
961
|
}
|
|
959
962
|
function buildMcpServerConfig(baseConfig, apiKey, placeholder = "YOUR_EXA_API_KEY", envVarName) {
|
|
@@ -1663,9 +1666,9 @@ async function configureCcrWithPreset(preset) {
|
|
|
1663
1666
|
if (preset.requiresApiKey) {
|
|
1664
1667
|
try {
|
|
1665
1668
|
const { apiKey } = await inquirer.prompt({
|
|
1666
|
-
type: "
|
|
1669
|
+
type: "input",
|
|
1667
1670
|
name: "apiKey",
|
|
1668
|
-
message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name)
|
|
1671
|
+
message: i18n.t("ccr:enterApiKeyForProvider").replace("{provider}", preset.name),
|
|
1669
1672
|
validate: async (value) => !!value || i18n.t("api:keyRequired")
|
|
1670
1673
|
});
|
|
1671
1674
|
provider.api_key = apiKey;
|
|
@@ -2784,10 +2787,12 @@ async function selectMcpServices() {
|
|
|
2784
2787
|
}
|
|
2785
2788
|
|
|
2786
2789
|
function applyCodexPlatformCommand(config) {
|
|
2787
|
-
if (config.command
|
|
2788
|
-
const mcpCmd = getMcpCommand();
|
|
2789
|
-
|
|
2790
|
-
|
|
2790
|
+
if (isWindows() && config.command) {
|
|
2791
|
+
const mcpCmd = getMcpCommand(config.command);
|
|
2792
|
+
if (mcpCmd[0] === "cmd") {
|
|
2793
|
+
config.command = mcpCmd[0];
|
|
2794
|
+
config.args = [...mcpCmd.slice(1), ...config.args || []];
|
|
2795
|
+
}
|
|
2791
2796
|
}
|
|
2792
2797
|
}
|
|
2793
2798
|
|
|
@@ -2862,9 +2867,9 @@ async function configureCodexMcp(options) {
|
|
|
2862
2867
|
if (configInfo.requiresApiKey && configInfo.apiKeyEnvVar) {
|
|
2863
2868
|
const promptMessage = serviceMeta?.apiKeyPrompt || i18n.t("mcp:apiKeyPrompt");
|
|
2864
2869
|
const { apiKey } = await inquirer.prompt([{
|
|
2865
|
-
type: "
|
|
2870
|
+
type: "input",
|
|
2866
2871
|
name: "apiKey",
|
|
2867
|
-
message: promptMessage
|
|
2872
|
+
message: promptMessage,
|
|
2868
2873
|
validate: (input) => !!input || i18n.t("api:keyRequired")
|
|
2869
2874
|
}]);
|
|
2870
2875
|
if (!apiKey)
|
|
@@ -3579,7 +3584,7 @@ function createApiConfigChoices(providers, currentProvider, isCommented) {
|
|
|
3579
3584
|
return choices;
|
|
3580
3585
|
}
|
|
3581
3586
|
async function applyCustomApiConfig(customApiConfig) {
|
|
3582
|
-
const { type, token, baseUrl } = customApiConfig;
|
|
3587
|
+
const { type, token, baseUrl, model } = customApiConfig;
|
|
3583
3588
|
const backupPath = backupCodexComplete();
|
|
3584
3589
|
if (backupPath) {
|
|
3585
3590
|
console.log(ansis.gray(getBackupMessage(backupPath)));
|
|
@@ -3600,7 +3605,8 @@ async function applyCustomApiConfig(customApiConfig) {
|
|
|
3600
3605
|
authEntries[providerId] = token;
|
|
3601
3606
|
}
|
|
3602
3607
|
const configData = {
|
|
3603
|
-
model: "claude-3-5-sonnet-20241022",
|
|
3608
|
+
model: model || "claude-3-5-sonnet-20241022",
|
|
3609
|
+
// Use provided model or default
|
|
3604
3610
|
modelProvider: providerId,
|
|
3605
3611
|
modelProviderCommented: false,
|
|
3606
3612
|
providers,
|
|
@@ -3737,9 +3743,9 @@ async function configureCodexApi(options) {
|
|
|
3737
3743
|
default: (answers2) => existingMap.get(sanitizeProviderName(answers2.providerName))?.wireApi || "responses"
|
|
3738
3744
|
},
|
|
3739
3745
|
{
|
|
3740
|
-
type: "
|
|
3746
|
+
type: "input",
|
|
3741
3747
|
name: "apiKey",
|
|
3742
|
-
message: i18n.t("codex:providerApiKeyPrompt")
|
|
3748
|
+
message: i18n.t("codex:providerApiKeyPrompt"),
|
|
3743
3749
|
validate: (input) => !!input || i18n.t("codex:providerApiKeyRequired")
|
|
3744
3750
|
}
|
|
3745
3751
|
]);
|
|
@@ -4141,12 +4147,16 @@ async function resolveCodeType(codeTypeParam) {
|
|
|
4141
4147
|
const validAbbreviations = Object.keys(CODE_TYPE_ABBREVIATIONS);
|
|
4142
4148
|
const validFullTypes = Object.values(CODE_TYPE_ABBREVIATIONS);
|
|
4143
4149
|
const validOptions = [...validAbbreviations, ...validFullTypes].join(", ");
|
|
4150
|
+
let defaultValue = DEFAULT_CODE_TOOL_TYPE;
|
|
4151
|
+
try {
|
|
4152
|
+
const config = await readZcfConfigAsync();
|
|
4153
|
+
if (config?.codeToolType && isValidCodeType(config.codeToolType)) {
|
|
4154
|
+
defaultValue = config.codeToolType;
|
|
4155
|
+
}
|
|
4156
|
+
} catch {
|
|
4157
|
+
}
|
|
4144
4158
|
throw new Error(
|
|
4145
|
-
i18n.t(
|
|
4146
|
-
"errors:invalidCodeType",
|
|
4147
|
-
`Invalid code type: "${codeTypeParam}". Valid options are: ${validOptions}.`,
|
|
4148
|
-
{ value: codeTypeParam, validOptions }
|
|
4149
|
-
)
|
|
4159
|
+
i18n.t("errors:invalidCodeType", { value: codeTypeParam, validOptions, defaultValue })
|
|
4150
4160
|
);
|
|
4151
4161
|
}
|
|
4152
4162
|
try {
|
|
@@ -4538,9 +4548,9 @@ async function configureApiCompletely(preselectedAuthType) {
|
|
|
4538
4548
|
console.log(ansis.yellow(i18n.t("common:cancelled")));
|
|
4539
4549
|
return null;
|
|
4540
4550
|
}
|
|
4541
|
-
const keyMessage = authType === "auth_token" ? i18n.t("api:enterAuthToken")
|
|
4551
|
+
const keyMessage = authType === "auth_token" ? i18n.t("api:enterAuthToken") : i18n.t("api:enterApiKey");
|
|
4542
4552
|
const { key } = await inquirer.prompt({
|
|
4543
|
-
type: "
|
|
4553
|
+
type: "input",
|
|
4544
4554
|
name: "key",
|
|
4545
4555
|
message: keyMessage,
|
|
4546
4556
|
validate: async (value) => {
|
|
@@ -4611,9 +4621,9 @@ async function modifyApiConfigPartially(existingConfig) {
|
|
|
4611
4621
|
}
|
|
4612
4622
|
} else if (item === "key") {
|
|
4613
4623
|
const authType = currentConfig.authType || "auth_token";
|
|
4614
|
-
const keyMessage = authType === "auth_token" ? i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none"))
|
|
4624
|
+
const keyMessage = authType === "auth_token" ? i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none")) : i18n.t("api:enterNewApiKey").replace("{key}", currentConfig.key ? formatApiKeyDisplay(currentConfig.key) : i18n.t("common:none"));
|
|
4615
4625
|
const { key } = await inquirer.prompt({
|
|
4616
|
-
type: "
|
|
4626
|
+
type: "input",
|
|
4617
4627
|
name: "key",
|
|
4618
4628
|
message: keyMessage,
|
|
4619
4629
|
validate: async (value) => {
|
|
@@ -5092,6 +5102,16 @@ function validateSkipPromptOptions(options) {
|
|
|
5092
5102
|
if (options.apiConfigs && options.apiConfigsFile) {
|
|
5093
5103
|
throw new Error(i18n.t("multi-config:conflictingParams"));
|
|
5094
5104
|
}
|
|
5105
|
+
if (options.apiModel && typeof options.apiModel !== "string") {
|
|
5106
|
+
throw new Error(
|
|
5107
|
+
i18n.t("errors:invalidApiModel", { value: options.apiModel })
|
|
5108
|
+
);
|
|
5109
|
+
}
|
|
5110
|
+
if (options.apiFastModel && typeof options.apiFastModel !== "string") {
|
|
5111
|
+
throw new Error(
|
|
5112
|
+
i18n.t("errors:invalidApiFastModel", { value: options.apiFastModel })
|
|
5113
|
+
);
|
|
5114
|
+
}
|
|
5095
5115
|
if (options.apiType === "api_key" && !options.apiKey) {
|
|
5096
5116
|
throw new Error(i18n.t("errors:apiKeyRequiredForApiKey"));
|
|
5097
5117
|
}
|
|
@@ -5284,7 +5304,9 @@ async function init(options = {}) {
|
|
|
5284
5304
|
const customApiConfig = options.apiType === "api_key" && options.apiKey ? {
|
|
5285
5305
|
type: "api_key",
|
|
5286
5306
|
token: options.apiKey,
|
|
5287
|
-
baseUrl: options.apiUrl
|
|
5307
|
+
baseUrl: options.apiUrl,
|
|
5308
|
+
model: options.apiModel
|
|
5309
|
+
// Add model parameter for Codex
|
|
5288
5310
|
} : void 0;
|
|
5289
5311
|
let selectedWorkflows;
|
|
5290
5312
|
if (Array.isArray(options.workflows)) {
|
|
@@ -5521,6 +5543,22 @@ async function init(options = {}) {
|
|
|
5521
5543
|
console.log(ansis.gray(` Key: ${formatApiKeyDisplay(configuredApi.key)}`));
|
|
5522
5544
|
}
|
|
5523
5545
|
}
|
|
5546
|
+
if ((options.apiModel || options.apiFastModel) && action !== "docs-only" && codeToolType === "claude-code") {
|
|
5547
|
+
if (options.skipPrompt) {
|
|
5548
|
+
const { updateCustomModel } = await Promise.resolve().then(function () { return config$1; });
|
|
5549
|
+
updateCustomModel(
|
|
5550
|
+
options.apiModel || void 0,
|
|
5551
|
+
options.apiFastModel || void 0
|
|
5552
|
+
);
|
|
5553
|
+
console.log(ansis.green(`\u2714 ${i18n.t("api:modelConfigSuccess")}`));
|
|
5554
|
+
if (options.apiModel) {
|
|
5555
|
+
console.log(ansis.gray(` ${i18n.t("api:primaryModel")}: ${options.apiModel}`));
|
|
5556
|
+
}
|
|
5557
|
+
if (options.apiFastModel) {
|
|
5558
|
+
console.log(ansis.gray(` ${i18n.t("api:fastModel")}: ${options.apiFastModel}`));
|
|
5559
|
+
}
|
|
5560
|
+
}
|
|
5561
|
+
}
|
|
5524
5562
|
if (action !== "docs-only") {
|
|
5525
5563
|
let shouldConfigureMcp = false;
|
|
5526
5564
|
if (options.skipPrompt) {
|
|
@@ -5579,9 +5617,9 @@ async function init(options = {}) {
|
|
|
5579
5617
|
continue;
|
|
5580
5618
|
} else {
|
|
5581
5619
|
const response = await inquirer.prompt({
|
|
5582
|
-
type: "
|
|
5620
|
+
type: "input",
|
|
5583
5621
|
name: "apiKey",
|
|
5584
|
-
message: service.apiKeyPrompt
|
|
5622
|
+
message: service.apiKeyPrompt,
|
|
5585
5623
|
validate: (value) => !!value || i18n.t("api:keyRequired")
|
|
5586
5624
|
});
|
|
5587
5625
|
if (!response.apiKey) {
|
package/dist/cli.mjs
CHANGED
|
@@ -328,9 +328,9 @@ async function configureMcpFeature() {
|
|
|
328
328
|
let config = service.config;
|
|
329
329
|
if (service.requiresApiKey) {
|
|
330
330
|
const { apiKey } = await inquirer.prompt({
|
|
331
|
-
type: "
|
|
331
|
+
type: "input",
|
|
332
332
|
name: "apiKey",
|
|
333
|
-
message: service.apiKeyPrompt
|
|
333
|
+
message: service.apiKeyPrompt,
|
|
334
334
|
validate: async (value) => !!value || i18n.t("api:keyRequired")
|
|
335
335
|
});
|
|
336
336
|
if (apiKey) {
|
|
@@ -2113,8 +2113,21 @@ async function showCodexMenu() {
|
|
|
2113
2113
|
}
|
|
2114
2114
|
return void 0;
|
|
2115
2115
|
}
|
|
2116
|
-
async function showMainMenu() {
|
|
2116
|
+
async function showMainMenu(options = {}) {
|
|
2117
2117
|
try {
|
|
2118
|
+
if (options.codeType) {
|
|
2119
|
+
try {
|
|
2120
|
+
const resolvedType = await resolveCodeType$1(options.codeType);
|
|
2121
|
+
const currentType = getCurrentCodeTool();
|
|
2122
|
+
if (resolvedType !== currentType) {
|
|
2123
|
+
updateZcfConfig({ codeToolType: resolvedType });
|
|
2124
|
+
console.log(ansis.green(`\u2714 ${i18n.t("menu:codeToolSwitched", { tool: getCodeToolLabel(resolvedType) })}`));
|
|
2125
|
+
}
|
|
2126
|
+
} catch (err) {
|
|
2127
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
2128
|
+
console.error(ansis.yellow(errorMessage));
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2118
2131
|
let exitMenu = false;
|
|
2119
2132
|
while (!exitMenu) {
|
|
2120
2133
|
const codeTool = getCurrentCodeTool();
|
|
@@ -2482,6 +2495,8 @@ function customizeHelp(sections) {
|
|
|
2482
2495
|
` ${ansis.green("--api-type, -t")} <type> ${i18n.t("cli:help.optionDescriptions.apiType")} (auth_token, api_key, ccr_proxy, skip)`,
|
|
2483
2496
|
` ${ansis.green("--api-key, -k")} <key> ${i18n.t("cli:help.optionDescriptions.apiKey")}`,
|
|
2484
2497
|
` ${ansis.green("--api-url, -u")} <url> ${i18n.t("cli:help.optionDescriptions.customApiUrl")}`,
|
|
2498
|
+
` ${ansis.green("--api-model, -M")} <model> ${i18n.t("cli:help.optionDescriptions.apiModel")} (e.g., claude-sonnet-4-5)`,
|
|
2499
|
+
` ${ansis.green("--api-fast-model, -F")} <model> ${i18n.t("cli:help.optionDescriptions.apiFastModel")} (e.g., claude-haiku-4-5)`,
|
|
2485
2500
|
` ${ansis.green("--ai-output-lang, -a")} <lang> ${i18n.t("cli:help.optionDescriptions.aiOutputLanguage")}`,
|
|
2486
2501
|
` ${ansis.green("--all-lang, -g")} <lang> ${i18n.t("cli:help.optionDescriptions.setAllLanguageParams")}`,
|
|
2487
2502
|
` ${ansis.green("--config-action, -r")} <action> ${i18n.t("cli:help.optionDescriptions.configHandling")} (${i18n.t("cli:help.defaults.prefix")} backup)`,
|
|
@@ -2544,10 +2559,10 @@ async function setupCommands(cli) {
|
|
|
2544
2559
|
await initI18n(defaultLang);
|
|
2545
2560
|
} catch {
|
|
2546
2561
|
}
|
|
2547
|
-
cli.command("", "Show interactive menu (default)").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").action(await withLanguageResolution(async () => {
|
|
2548
|
-
await showMainMenu();
|
|
2562
|
+
cli.command("", "Show interactive menu (default)").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--force, -f", "Force overwrite existing configuration").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").action(await withLanguageResolution(async (options) => {
|
|
2563
|
+
await showMainMenu({ codeType: options.codeType });
|
|
2549
2564
|
}));
|
|
2550
|
-
cli.command("init", "Initialize Claude Code configuration").alias("i").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--ai-output-lang, -a <lang>", "AI output language").option("--force, -f", "Force overwrite existing configuration").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").option("--config-action, -r <action>", `Config handling (new/backup/merge/docs-only/skip), ${i18n.t("cli:help.defaults.prefix")} backup`).option("--api-type, -t <type>", "API type (auth_token/api_key/ccr_proxy/skip)").option("--api-key, -k <key>", "API key (used for both API key and auth token types)").option("--api-url, -u <url>", "Custom API URL").option("--mcp-services, -m <services>", `Comma-separated MCP services to install (context7,mcp-deepwiki,Playwright,exa), "skip" to skip all, "all" for all non-key services, ${i18n.t("cli:help.defaults.prefix")} all`).option("--workflows, -w <workflows>", `Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, ${i18n.t("cli:help.defaults.prefix")} all`).option("--output-styles, -o <styles>", `Comma-separated output styles (engineer-professional,nekomata-engineer,laowang-engineer,default,explanatory,learning), "skip" to skip all, "all" for all custom styles, ${i18n.t("cli:help.defaults.prefix")} all`).option("--default-output-style, -d <style>", `Default output style, ${i18n.t("cli:help.defaults.prefix")} engineer-professional`).option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--install-cometix-line, -x <value>", `Install CCometixLine statusline tool (true/false), ${i18n.t("cli:help.defaults.prefix")} true`).option("--api-configs <configs>", "API configurations as JSON string for multiple profiles").option("--api-configs-file <file>", "Path to JSON file containing API configurations").action(await withLanguageResolution(async (options) => {
|
|
2565
|
+
cli.command("init", "Initialize Claude Code configuration").alias("i").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").option("--ai-output-lang, -a <lang>", "AI output language").option("--force, -f", "Force overwrite existing configuration").option("--skip-prompt, -s", "Skip all interactive prompts (non-interactive mode)").option("--config-action, -r <action>", `Config handling (new/backup/merge/docs-only/skip), ${i18n.t("cli:help.defaults.prefix")} backup`).option("--api-type, -t <type>", "API type (auth_token/api_key/ccr_proxy/skip)").option("--api-key, -k <key>", "API key (used for both API key and auth token types)").option("--api-url, -u <url>", "Custom API URL").option("--api-model, -M <model>", "Primary API model (e.g., claude-sonnet-4-5)").option("--api-fast-model, -F <model>", "Fast API model (e.g., claude-haiku-4-5)").option("--mcp-services, -m <services>", `Comma-separated MCP services to install (context7,mcp-deepwiki,Playwright,exa), "skip" to skip all, "all" for all non-key services, ${i18n.t("cli:help.defaults.prefix")} all`).option("--workflows, -w <workflows>", `Comma-separated workflows to install (sixStepsWorkflow,featPlanUx,gitWorkflow,bmadWorkflow), "skip" to skip all, "all" for all workflows, ${i18n.t("cli:help.defaults.prefix")} all`).option("--output-styles, -o <styles>", `Comma-separated output styles (engineer-professional,nekomata-engineer,laowang-engineer,default,explanatory,learning), "skip" to skip all, "all" for all custom styles, ${i18n.t("cli:help.defaults.prefix")} all`).option("--default-output-style, -d <style>", `Default output style, ${i18n.t("cli:help.defaults.prefix")} engineer-professional`).option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--code-type, -T <codeType>", "Select code tool type (claude-code, codex, cc, cx)").option("--install-cometix-line, -x <value>", `Install CCometixLine statusline tool (true/false), ${i18n.t("cli:help.defaults.prefix")} true`).option("--api-configs <configs>", "API configurations as JSON string for multiple profiles").option("--api-configs-file <file>", "Path to JSON file containing API configurations").action(await withLanguageResolution(async (options) => {
|
|
2551
2566
|
await init(options);
|
|
2552
2567
|
}));
|
|
2553
2568
|
cli.command("update", "Update Claude Code prompts only").alias("u").option("--lang, -l <lang>", "ZCF display language (zh-CN, en)").option("--all-lang, -g <lang>", "Set all language parameters to this value").option("--config-lang, -c <lang>", "Configuration language (zh-CN, en)").action(await withLanguageResolution(async (options) => {
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
"apiConfigKey": "Key",
|
|
4
4
|
"apiConfigSuccess": "API configured",
|
|
5
5
|
"apiConfigUrl": "URL",
|
|
6
|
+
"modelConfigSuccess": "API models configured",
|
|
7
|
+
"primaryModel": "Primary model",
|
|
8
|
+
"fastModel": "Fast model",
|
|
6
9
|
"apiKeyDesc": "For API keys from Anthropic Console",
|
|
7
10
|
"apiKeyValidation.example": "Example format: sk-abcdef123456_789xyz",
|
|
8
11
|
"authTokenDesc": "For tokens obtained via OAuth or browser login",
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"help.optionDescriptions.apiType": "API type",
|
|
24
24
|
"help.optionDescriptions.apiKey": "API key (for both types)",
|
|
25
25
|
"help.optionDescriptions.customApiUrl": "Custom API URL",
|
|
26
|
+
"help.optionDescriptions.apiModel": "Primary API model",
|
|
27
|
+
"help.optionDescriptions.apiFastModel": "Fast API model",
|
|
26
28
|
"help.optionDescriptions.aiOutputLanguage": "AI output language",
|
|
27
29
|
"help.optionDescriptions.setAllLanguageParams": "Set all language params",
|
|
28
30
|
"help.optionDescriptions.configHandling": "Config handling",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
"goodbye": "👋 Thanks for using ZCF! Goodbye!",
|
|
12
12
|
"returnToMenu": "Return to main menu?",
|
|
13
13
|
"back": "Back",
|
|
14
|
-
"inputHidden": " (input will be hidden)",
|
|
15
14
|
"operationFailed": "Operation failed",
|
|
16
15
|
"backupCreated": "📁 Configuration backup created: {{path}}",
|
|
17
16
|
"current": "current"
|
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
"invalidDefaultOutputStyle": "Invalid default output style: {style}. Available styles: {validStyles}",
|
|
12
12
|
"invalidWorkflow": "Invalid workflow: {workflow}. Available workflows: {validWorkflows}",
|
|
13
13
|
"invalidModel": "Invalid model: {model}. Expected 'opus', 'sonnet', or 'sonnet[1m]'",
|
|
14
|
+
"invalidApiModel": "Invalid API model parameter: {value}",
|
|
15
|
+
"invalidApiFastModel": "Invalid fast model parameter: {value}",
|
|
14
16
|
"invalidEnvConfig": "Invalid env configuration: expected object",
|
|
15
17
|
"invalidBaseUrl": "Invalid ANTHROPIC_BASE_URL: expected string",
|
|
16
18
|
"invalidApiKeyConfig": "Invalid ANTHROPIC_API_KEY: expected string",
|
|
17
19
|
"invalidAuthTokenConfig": "Invalid ANTHROPIC_AUTH_TOKEN: expected string",
|
|
18
20
|
"invalidPermissionsConfig": "Invalid permissions configuration: expected object",
|
|
19
21
|
"invalidPermissionsAllow": "Invalid permissions.allow: expected array",
|
|
20
|
-
"invalidCodeType": "Invalid code type: \"{value}\". Valid options are: {validOptions}",
|
|
22
|
+
"invalidCodeType": "Invalid code type: \"{value}\". Valid options are: {validOptions}. Using default: {defaultValue}.",
|
|
21
23
|
"generalError": "Error",
|
|
22
24
|
"stackTrace": "Stack"
|
|
23
25
|
}
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
"apiConfigKey": "Key",
|
|
4
4
|
"apiConfigSuccess": "API 配置完成",
|
|
5
5
|
"apiConfigUrl": "URL",
|
|
6
|
+
"modelConfigSuccess": "API 模型配置完成",
|
|
7
|
+
"primaryModel": "主模型",
|
|
8
|
+
"fastModel": "快速模型",
|
|
6
9
|
"apiKeyDesc": "适用于从 Anthropic Console 获取的 API 密钥",
|
|
7
10
|
"apiKeyValidation.example": "示例格式: sk-abcdef123456_789xyz",
|
|
8
11
|
"authTokenDesc": "适用于通过 OAuth 或浏览器登录获取的令牌",
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
"help.optionDescriptions.apiType": "API类型",
|
|
24
24
|
"help.optionDescriptions.apiKey": "API密钥(适用于所有类型)",
|
|
25
25
|
"help.optionDescriptions.customApiUrl": "自定义API地址",
|
|
26
|
+
"help.optionDescriptions.apiModel": "主API模型",
|
|
27
|
+
"help.optionDescriptions.apiFastModel": "快速API模型",
|
|
26
28
|
"help.optionDescriptions.aiOutputLanguage": "AI输出语言",
|
|
27
29
|
"help.optionDescriptions.setAllLanguageParams": "统一设置所有语言参数",
|
|
28
30
|
"help.optionDescriptions.configHandling": "配置处理",
|
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
"invalidDefaultOutputStyle": "无效的默认输出样式:{style}。可用的样式:{validStyles}",
|
|
12
12
|
"invalidWorkflow": "无效的工作流:{workflow}。可用的工作流:{validWorkflows}",
|
|
13
13
|
"invalidModel": "无效的模型:{model}。期望的值:'opus', 'sonnet', 或 'sonnet[1m]'",
|
|
14
|
+
"invalidApiModel": "无效的 API 模型参数:{value}",
|
|
15
|
+
"invalidApiFastModel": "无效的快速模型参数:{value}",
|
|
14
16
|
"invalidEnvConfig": "无效的环境配置:期望对象类型",
|
|
15
17
|
"invalidBaseUrl": "无效的 ANTHROPIC_BASE_URL:期望字符串类型",
|
|
16
18
|
"invalidApiKeyConfig": "无效的 ANTHROPIC_API_KEY:期望字符串类型",
|
|
17
19
|
"invalidAuthTokenConfig": "无效的 ANTHROPIC_AUTH_TOKEN:期望字符串类型",
|
|
18
20
|
"invalidPermissionsConfig": "无效的权限配置:期望对象类型",
|
|
19
21
|
"invalidPermissionsAllow": "无效的 permissions.allow:期望数组类型",
|
|
20
|
-
"invalidCodeType": "无效的代码类型:\"{value}\"。可用的类型:{validOptions}",
|
|
22
|
+
"invalidCodeType": "无效的代码类型:\"{value}\"。可用的类型:{validOptions}。使用默认值:{defaultValue}。",
|
|
21
23
|
"generalError": "错误",
|
|
22
24
|
"stackTrace": "堆栈跟踪"
|
|
23
25
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -46,6 +46,8 @@ interface InitOptions {
|
|
|
46
46
|
apiType?: 'auth_token' | 'api_key' | 'ccr_proxy' | 'skip';
|
|
47
47
|
apiKey?: string;
|
|
48
48
|
apiUrl?: string;
|
|
49
|
+
apiModel?: string;
|
|
50
|
+
apiFastModel?: string;
|
|
49
51
|
mcpServices?: string[] | string | boolean;
|
|
50
52
|
workflows?: string[] | string | boolean;
|
|
51
53
|
outputStyles?: string[] | string | boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,8 @@ interface InitOptions {
|
|
|
46
46
|
apiType?: 'auth_token' | 'api_key' | 'ccr_proxy' | 'skip';
|
|
47
47
|
apiKey?: string;
|
|
48
48
|
apiUrl?: string;
|
|
49
|
+
apiModel?: string;
|
|
50
|
+
apiFastModel?: string;
|
|
49
51
|
mcpServices?: string[] | string | boolean;
|
|
50
52
|
workflows?: string[] | string | boolean;
|
|
51
53
|
outputStyles?: string[] | string | boolean;
|
package/package.json
CHANGED