@vibeapi/cli 0.0.38 → 0.0.40

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @vibeapi/api-helper
2
2
 
3
- > 一条命令,在 Claude Code / Codex / OpenClaw / Hermes / AtomCode 之间统一配置 API Key 与模型。
3
+ > 一条命令,在 Claude Code / Codex / OpenClaw / Hermes / AtomCode / Grok Build 之间统一配置 API Key 与模型。
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@vibeapi/api-helper.svg)](https://www.npmjs.com/package/@vibeapi/api-helper)
6
6
  [![Node](https://img.shields.io/node/v/@vibeapi/api-helper.svg)](https://nodejs.org)
@@ -47,6 +47,7 @@ Codex 同时开启 1M 上下文时,末尾加最短参数 `--1m`;已经配置
47
47
  ```bash
48
48
  vibecli setup --codexkey sk-xxx --1m
49
49
  vibecli setup --1m
50
+ vibecli setup --no-1m
50
51
  ```
51
52
 
52
53
  配完直接运行 `claude` / `codex` 即可。
@@ -75,9 +76,9 @@ vibecli config claude-code clear-model # 模型选择被钉住时,交还给
75
76
 
76
77
  ## 能做什么
77
78
 
78
- - **多工具一键配置**:把当前 API Key / 模型注入 Claude Code、Codex、OpenClaw、Hermes、AtomCode(OpenCode 暂时下架,`vibecli config opencode` 仍可用)。
79
+ - **多工具一键配置**:把当前 API Key / 模型注入 Claude Code、Codex、OpenClaw、Hermes、AtomCode、Grok Build(OpenCode 暂时下架,`vibecli config opencode` 仍可用)。
79
80
  - **按工具选模型**:使用默认 / 实时从 API 拉取 / 内置预设 / 手动输入;每个工具可用不同模型。
80
- - Claude Code 用默认模型时不写 `ANTHROPIC_*_MODEL` 环境变量,顶层 `model` 由 `settings-template.json` 提供(当前为 `opus[1m]`);显式选择其它模型时会覆盖该模板值。Codex 默认 `gpt-5.6-sol`,其余工具默认 `gpt-5.5`。
81
+ - Claude Code 用默认模型时不写 `ANTHROPIC_*_MODEL` 环境变量,顶层 `model` 由 `settings-template.json` 提供(当前为 `opus[1m]`);显式选择其它模型时会覆盖该模板值。Codex 默认 `gpt-6-astra`,其余工具默认 `gpt-5.5`。
81
82
  - Codex 默认启用 1M 上下文窗口(自动压缩阈值 900K);交互配置 Codex 时可取消。
82
83
  - **不动你的其它配置**:只改本工具的 provider 字段,你的 hooks、MCP、插件、权限设置原样保留。
83
84
  - **改前自动备份 + 一键还原**:覆盖配置前先快照(每文件留 10 份),`vibecli config <tool> restore` 随时回退;还原本身也可再撤销。
@@ -90,7 +91,7 @@ vibecli config claude-code clear-model # 模型选择被钉住时,交还给
90
91
  vibecli config <tool> # 配置某工具(选模型 → 应用 / 移除 / 还原)
91
92
  vibecli config <tool> restore # 还原该工具到上次更改前
92
93
  vibecli config <tool> clear-model # 清掉钉死的模型设置,回到工具自带默认(保留 API Key)
93
- vibecli config tool-model set codex gpt-5.6-sol # 单独给某工具指定模型
94
+ vibecli config tool-model set codex gpt-6-astra # 单独给某工具指定模型
94
95
  vibecli config profile use work # 切换 profile
95
96
  vibecli doctor # 健康巡检
96
97
  ```
@@ -12,6 +12,9 @@
12
12
  * vibecli setup --1m
13
13
  * 复用当前 profile 已保存的 Codex Key,开启 1M 上下文并重新应用配置。
14
14
  *
15
+ * vibecli setup --no-1m
16
+ * 复用当前 profile 已保存的 Codex Key,关闭 1M 上下文且不改写凭据。
17
+ *
15
18
  * 重复执行即换令牌(幂等)。模型一律用默认组合,之后可在向导 / tool-model 里改。
16
19
  */
17
20
  export interface SetupCommandOptions {
@@ -1 +1 @@
1
- import e from"chalk";import{i18n as o}from"../lib/i18n.js";import{configManager as t}from"../lib/config.js";import{toolManager as a,SUPPORTED_TOOLS as s}from"../lib/tool-manager.js";import{validateApiKey as l,fetchModels as i}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as n,setCodexOneMillionContext as d}from"../lib/tools/codex.js";async function r(e){const o=await i(e);if(!o.ok)return{hasClaude:!0,hasGpt:!0,probed:!1};const t=o.models.map(e=>e.toLowerCase());return{hasClaude:t.some(e=>e.includes("claude")),hasGpt:t.some(e=>e.startsWith("gpt")||e.includes("gpt-")||/^o\d/.test(e)),probed:!0}}function p(o){console.log(e.green(o))}function c(o){console.log(e.yellow(o))}function u(o){console.error(e.red(o))}async function m(t,a){console.log(e.gray(o.t("setup.validating",{label:t})));const s=await l(a);return!!s.valid||(u(o.t("setup.invalid_key",{label:t,reason:s.message||s.error||"invalid"})),!1)}function f(l,i,d=!1){const r=s[l];try{"codex"===l&&d&&t.setToolSetting("codex",n,!0),a.loadPrivateConfig(l,i,t.getModelsForTool(l))}catch(e){return u(o.t("setup.apply_failed",{tool:r.displayName,reason:e instanceof Error?e.message:String(e)})),!1}return p(o.t("setup.configured",{tool:r.displayName,command:r.command})),"codex"===l&&d&&p(o.t("setup.codex_1m_enabled")),a.isToolInstalled(l)||console.log(e.gray(o.t("setup.install_hint",{tool:r.displayName,install:r.installCommand}))),!0}export async function setupCommand(e){const a=e.key?.trim(),l=e.claudekey?.trim(),i=e.codexkey?.trim(),y=!0===e.oneMillion;if(!a&&!l&&!i&&y){if(!t.getApiKeyForTool("codex"))return u(o.t("setup.codex_1m_missing_key")),void(process.exitCode=1);try{t.setToolSetting("codex",n,!0),d(!0),p(o.t("setup.codex_1m_enabled"))}catch(e){u(o.t("setup.apply_failed",{tool:s.codex.displayName,reason:e instanceof Error?e.message:String(e)})),process.exitCode=1}return}if(!a&&!l&&!i)return u(o.t("setup.usage")),void(process.exitCode=1);let g=0,b=0;const _=new Set,x=[];l&&x.push({tool:"claude-code",label:"--claudekey",apiKey:l,need:"claude"}),i&&x.push({tool:"codex",label:"--codexkey",apiKey:i,need:"gpt"});for(const e of x){if(!await m(e.label,e.apiKey)){b+=1;continue}const a=await r(e.apiKey),s="claude"===e.need?a.hasClaude:a.hasGpt;!a.probed||s?(a.probed||c(o.t("setup.probe_failed",{label:e.label})),t.setToolApiKey(e.tool,e.apiKey),f(e.tool,e.apiKey,y)?(g+=1,_.add(e.tool)):b+=1):(u(o.t("claude"===e.need?"setup.key_no_claude":"setup.key_no_gpt",{label:e.label})),b+=1)}if(a){if(!await m("--key",a))return void(process.exitCode=1);t.setApiKey(a);const e=await r(a);if(e.probed||c(o.t("setup.probe_failed",{label:"--key"})),e.probed&&!e.hasClaude&&!e.hasGpt)return u(o.t("setup.key_no_family")),void(process.exitCode=1);const s=[{tool:"claude-code",capable:e.hasClaude,skipMsg:o.t("setup.skip_no_claude")},{tool:"codex",capable:e.hasGpt,skipMsg:o.t("setup.skip_no_gpt")}];for(const e of s)_.has(e.tool)||(e.capable?f(e.tool,a,y)?(g+=1,_.add(e.tool)):b+=1:c(e.skipMsg))}if(g>0){const e=[..._].map(e=>s[e]?.command).filter(Boolean).join(" / ");p("\n"+o.t("setup.done",{count:String(g),commands:e}))}(b>0||0===g)&&(process.exitCode=1)}
1
+ import e from"chalk";import{i18n as o}from"../lib/i18n.js";import{configManager as t}from"../lib/config.js";import{toolManager as a,SUPPORTED_TOOLS as l}from"../lib/tool-manager.js";import{validateApiKey as s,fetchModels as i}from"../lib/api-validator.js";import{CODEX_ONE_MILLION_CONTEXT_SETTING as n,setCodexOneMillionContext as d}from"../lib/tools/codex.js";async function r(e){const o=await i(e);if(!o.ok)return{hasClaude:!0,hasGpt:!0,probed:!1};const t=o.models.map(e=>e.toLowerCase());return{hasClaude:t.some(e=>e.includes("claude")),hasGpt:t.some(e=>e.startsWith("gpt")||e.includes("gpt-")||/^o\d/.test(e)),probed:!0}}function c(o){console.log(e.green(o))}function p(o){console.log(e.yellow(o))}function u(o){console.error(e.red(o))}async function m(t,a){console.log(e.gray(o.t("setup.validating",{label:t})));const l=await s(a);return!!l.valid||(u(o.t("setup.invalid_key",{label:t,reason:l.message||l.error||"invalid"})),!1)}function f(s,i,d){const r=l[s];try{"codex"===s&&void 0!==d&&t.setToolSetting("codex",n,d),a.loadPrivateConfig(s,i,t.getModelsForTool(s))}catch(e){return u(o.t("setup.apply_failed",{tool:r.displayName,reason:e instanceof Error?e.message:String(e)})),!1}return c(o.t("setup.configured",{tool:r.displayName,command:r.command})),"codex"===s&&void 0!==d&&c(o.t(d?"setup.codex_1m_enabled":"setup.codex_1m_disabled")),a.isToolInstalled(s)||console.log(e.gray(o.t("setup.install_hint",{tool:r.displayName,install:r.installCommand}))),!0}export async function setupCommand(e){const a=e.key?.trim(),s=e.claudekey?.trim(),i=e.codexkey?.trim(),y=void 0!==e.oneMillion;if(!a&&!s&&!i&&y){if(!t.getApiKeyForTool("codex"))return u(o.t("setup.codex_1m_missing_key")),void(process.exitCode=1);try{const a=!0===e.oneMillion;t.setToolSetting("codex",n,a),d(a),c(o.t(a?"setup.codex_1m_enabled":"setup.codex_1m_disabled"))}catch(e){u(o.t("setup.apply_failed",{tool:l.codex.displayName,reason:e instanceof Error?e.message:String(e)})),process.exitCode=1}return}if(!a&&!s&&!i)return u(o.t("setup.usage")),void(process.exitCode=1);let g=0,b=0;const _=new Set,x=[];s&&x.push({tool:"claude-code",label:"--claudekey",apiKey:s,need:"claude"}),i&&x.push({tool:"codex",label:"--codexkey",apiKey:i,need:"gpt"});for(const a of x){if(!await m(a.label,a.apiKey)){b+=1;continue}const l=await r(a.apiKey),s="claude"===a.need?l.hasClaude:l.hasGpt;!l.probed||s?(l.probed||p(o.t("setup.probe_failed",{label:a.label})),t.setToolApiKey(a.tool,a.apiKey),f(a.tool,a.apiKey,e.oneMillion)?(g+=1,_.add(a.tool)):b+=1):(u(o.t("claude"===a.need?"setup.key_no_claude":"setup.key_no_gpt",{label:a.label})),b+=1)}if(a){if(!await m("--key",a))return void(process.exitCode=1);t.setApiKey(a);const l=await r(a);if(l.probed||p(o.t("setup.probe_failed",{label:"--key"})),l.probed&&!l.hasClaude&&!l.hasGpt)return u(o.t("setup.key_no_family")),void(process.exitCode=1);const s=[{tool:"claude-code",capable:l.hasClaude,skipMsg:o.t("setup.skip_no_claude")},{tool:"codex",capable:l.hasGpt,skipMsg:o.t("setup.skip_no_gpt")}];for(const o of s)_.has(o.tool)||(o.capable?f(o.tool,a,e.oneMillion)?(g+=1,_.add(o.tool)):b+=1:p(o.skipMsg))}if(g>0){const e=[..._].map(e=>l[e]?.command).filter(Boolean).join(" / ");c("\n"+o.t("setup.done",{count:String(g),commands:e}))}(b>0||0===g)&&(process.exitCode=1)}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Brand identity used when this CLI writes provider entries into third-party
3
- * tool config files (Codex, OpenClaw, Hermes, AtomCode, ...).
3
+ * tool config files (Codex, OpenClaw, Hermes, AtomCode, Grok Build, ...).
4
4
  *
5
5
  * Keeping these in one place makes a rebrand (or a white-label fork) a single-file
6
6
  * change instead of a grep-and-replace across every tool adapter.
@@ -1 +1 @@
1
- import{Command as e}from"commander";import{i18n as a,detectSystemLang as o}from"./i18n.js";import{configManager as t}from"./config.js";import{wizard as n}from"./wizard.js";import{langCommand as i,authCommand as s,doctorCommand as r,configCommand as c,statusCommand as m}from"../commands/index.js";import{logsCommand as p}from"../commands/logs.js";import{completionCommand as l}from"../commands/completion.js";import{benchCommand as d}from"../commands/bench.js";import{updateCommand as g}from"../commands/update.js";import{setupCommand as u}from"../commands/setup.js";import h from"chalk";import{readFileSync as y}from"fs";import{join as f,dirname as b}from"path";import{fileURLToPath as k}from"url";import{setRuntimeOptions as v,detectColorPreferenceFromEnv as w,isColorEnabled as $,isJsonMode as j}from"./runtime-options.js";import{cleanupAnthropicEnvVars as x}from"./env-cleanup.js";import{runStartupUpdate as C}from"./auto-update.js";export class Command{program;constructor(){const n=t.isFirstRun()?o():t.getLang();a.loadFromConfig(n),this.program=new e,this.setupProgram()}getVersion(){try{const e=k(import.meta.url),a=b(e),o=f(a,"../../package.json");return JSON.parse(y(o,"utf-8")).version}catch{return"1.0.0"}}setupProgram(){this.program.name("vibecli").description(a.t("cli.title")).version(this.getVersion(),"-v, --version",a.t("commands.version")).helpOption("-h, --help",a.t("commands.help")).option("--base <url>","Custom API base URL").option("--non-interactive","Disable interactive prompts (CI mode)").option("--json","Emit machine-readable JSON output where applicable").option("--yes, -y","Auto-confirm prompts that have a default action").option("--dry-run","Show planned changes without writing anywhere").option("--no-color","Disable colored output"),this.program.command("setup").description(a.t("commands.setup")).option("--key <key>","API key for all capable tools (capability auto-detected)").option("--claudekey <key>","Dedicated API key for Claude Code").option("--codexkey <key>","Dedicated API key for Codex").option("--1m","Enable the 1M context window for Codex").option("--all","Configure every tool the key can serve (default behavior)").action(async e=>{await u({key:e.key,claudekey:e.claudekey,codexkey:e.codexkey,all:e.all,oneMillion:e["1m"]})}),this.program.command("init").description(a.t("commands.init")).action(async()=>{await this.handleInitCommand()});const e=this.program.command("lang").description(a.t("commands.lang"));e.command("show").description(a.t("lang.show_usage")).action(async()=>{await i(["show"])}),e.command("set <locale>").description(a.t("lang.set_usage")).action(async e=>{await i(["set",e])});const o=this.program.command("auth").description(a.t("commands.auth"));o.argument("[token]","API token").action(async e=>{const a=[];e&&a.push(e),await s(a)}),o.command("revoke").description("Revoke saved API key").action(async()=>{await s(["revoke"])}),o.command("reload <tool>").description("Reload plan configuration to the specified tool (e.g., claude)").action(async e=>{await s(["reload",e])}),this.program.command("doctor").description(a.t("commands.doctor")).action(async()=>{await r()}),this.program.command("status").description(a.t("commands.status")).action(async()=>{await m()}),this.program.command("logs").description("Inspect vibecli log files").argument("[action]","list|tail|path").argument("[file]","specific log file when using tail").action(async(e,a)=>{const o=[];e&&o.push(e),a&&o.push(a),await p(o)}),this.program.command("completion <shell>").description("Print shell completion script (bash|zsh|fish)").action(async e=>{await l([e])}),this.program.command("update").description("Check for a newer version across CNB and npm mirrors").action(async()=>{await g()}),this.program.command("bench").description("Benchmark the configured API endpoint").option("--samples <n>","number of samples to send","5").action(async e=>{const a=[];e.samples&&a.push("--samples",e.samples),await d(a)}),this.program.command("config").description("Manage profiles, presets, backups, and per-tool config").argument("[args...]","Subcommand and arguments").allowUnknownOption(!0).action(async e=>{await c(e||[])}),this.program.command("enter [option]").description(a.t("commands.enter")).action(async e=>{if(e)switch(e){case"lang":case"language":await n.configLanguage();break;case"apikey":case"api-key":await n.configApiKey();break;case"models":await n.configModels();break;default:{const a=[e];await c(a);break}}else await n.run()}),this.program.action(async()=>{await n.run()}),this.program.configureHelp({sortSubcommands:!0,subcommandTerm:e=>e.name()+" "+e.usage()}),this.program.addHelpText("after",`\n${h.bold(a.t("cli.examples"))}:\n ${h.gray("$ vibecli # Interactive main menu")}\n ${h.gray("$ vibecli init # Run first-time setup wizard")}\n ${h.gray("$ vibecli setup --key sk-xxx # One-shot setup (auto-detect capable tools)")}\n ${h.gray("$ vibecli setup --claudekey sk-a --codexkey sk-b")}\n ${h.gray("$ vibecli status --json # Machine-readable status")}\n ${h.gray("$ vibecli config profile list")}\n ${h.gray("$ vibecli config profile create work")}\n ${h.gray("$ vibecli config profile use work")}\n ${h.gray("$ vibecli config preset save fast")}\n ${h.gray("$ vibecli config backup create snapshot")}\n ${h.gray("$ vibecli auth <token> --non-interactive")}\n ${h.gray("$ vibecli auth revoke --yes")}\n ${h.gray("$ vibecli logs path")}\n ${h.gray("$ vibecli completion bash")}\n ${h.gray("$ vibecli bench --samples 3")}\n ${h.gray("$ vibecli update")}\n ${h.gray('$ vibecli --base "https://custom.api.com" init # Custom base URL')}\n`)}async handleInitCommand(){await n.runFirstTimeSetup()}cleanupLeakedEnvVars(){const e=x();if(0===e.length||j())return;const o=a.t("messages.env_vars_cleared",{vars:e.join(", ")});console.log($()?h.yellow(o):o)}preflightArgs(e){const a=a=>e.includes(a),o=!a("--no-color")&&w();let n;v({nonInteractive:a("--non-interactive"),json:a("--json"),yes:a("--yes")||a("-y"),dryRun:a("--dry-run"),color:o}),o||(h.level=0);for(let a=0;a<e.length;a+=1){const o=e[a];if("--base"===o&&e[a+1]){n=e[a+1];break}if(o.startsWith("--base=")){n=o.slice(7);break}}n&&t.setBaseUrl(n)}async execute(e){try{if(this.preflightArgs(e),this.cleanupLeakedEnvVars(),(await C(e)).handled)return;await this.program.parseAsync(e,{from:"user"})}catch(e){if(e instanceof Error){const o=$()?h.red:e=>e;console.error(o(a.t("cli.error_general")),e.message)}process.exit(1)}}getProgram(){return this.program}}
1
+ import{Command as e}from"commander";import{i18n as o,detectSystemLang as a}from"./i18n.js";import{configManager as t}from"./config.js";import{wizard as n}from"./wizard.js";import{langCommand as i,authCommand as s,doctorCommand as r,configCommand as c,statusCommand as m}from"../commands/index.js";import{logsCommand as p}from"../commands/logs.js";import{completionCommand as l}from"../commands/completion.js";import{benchCommand as d}from"../commands/bench.js";import{updateCommand as g}from"../commands/update.js";import{setupCommand as u}from"../commands/setup.js";import h from"chalk";import{readFileSync as y}from"fs";import{join as f,dirname as b}from"path";import{fileURLToPath as k}from"url";import{setRuntimeOptions as v,detectColorPreferenceFromEnv as w,isColorEnabled as $,isJsonMode as j}from"./runtime-options.js";import{cleanupAnthropicEnvVars as x}from"./env-cleanup.js";import{runStartupUpdate as C}from"./auto-update.js";export class Command{program;constructor(){const n=t.isFirstRun()?a():t.getLang();o.loadFromConfig(n),this.program=new e,this.setupProgram()}getVersion(){try{const e=k(import.meta.url),o=b(e),a=f(o,"../../package.json");return JSON.parse(y(a,"utf-8")).version}catch{return"1.0.0"}}setupProgram(){this.program.name("vibecli").description(o.t("cli.title")).version(this.getVersion(),"-v, --version",o.t("commands.version")).helpOption("-h, --help",o.t("commands.help")).option("--base <url>","Custom API base URL").option("--non-interactive","Disable interactive prompts (CI mode)").option("--json","Emit machine-readable JSON output where applicable").option("--yes, -y","Auto-confirm prompts that have a default action").option("--dry-run","Show planned changes without writing anywhere").option("--no-color","Disable colored output"),this.program.command("setup").description(o.t("commands.setup")).option("--key <key>","API key for all capable tools (capability auto-detected)").option("--claudekey <key>","Dedicated API key for Claude Code").option("--codexkey <key>","Dedicated API key for Codex").option("--1m","Enable the 1M context window for Codex").option("--no-1m","Disable the 1M context window for Codex").option("--all","Configure every tool the key can serve (default behavior)").action(async e=>{await u({key:e.key,claudekey:e.claudekey,codexkey:e.codexkey,all:e.all,oneMillion:e["1m"]})}),this.program.command("init").description(o.t("commands.init")).action(async()=>{await this.handleInitCommand()});const e=this.program.command("lang").description(o.t("commands.lang"));e.command("show").description(o.t("lang.show_usage")).action(async()=>{await i(["show"])}),e.command("set <locale>").description(o.t("lang.set_usage")).action(async e=>{await i(["set",e])});const a=this.program.command("auth").description(o.t("commands.auth"));a.argument("[token]","API token").action(async e=>{const o=[];e&&o.push(e),await s(o)}),a.command("revoke").description("Revoke saved API key").action(async()=>{await s(["revoke"])}),a.command("reload <tool>").description("Reload plan configuration to the specified tool (e.g., claude)").action(async e=>{await s(["reload",e])}),this.program.command("doctor").description(o.t("commands.doctor")).action(async()=>{await r()}),this.program.command("status").description(o.t("commands.status")).action(async()=>{await m()}),this.program.command("logs").description("Inspect vibecli log files").argument("[action]","list|tail|path").argument("[file]","specific log file when using tail").action(async(e,o)=>{const a=[];e&&a.push(e),o&&a.push(o),await p(a)}),this.program.command("completion <shell>").description("Print shell completion script (bash|zsh|fish)").action(async e=>{await l([e])}),this.program.command("update").description("Check for a newer version across CNB and npm mirrors").action(async()=>{await g()}),this.program.command("bench").description("Benchmark the configured API endpoint").option("--samples <n>","number of samples to send","5").action(async e=>{const o=[];e.samples&&o.push("--samples",e.samples),await d(o)}),this.program.command("config").description("Manage profiles, presets, backups, and per-tool config").argument("[args...]","Subcommand and arguments").allowUnknownOption(!0).action(async e=>{await c(e||[])}),this.program.command("enter [option]").description(o.t("commands.enter")).action(async e=>{if(e)switch(e){case"lang":case"language":await n.configLanguage();break;case"apikey":case"api-key":await n.configApiKey();break;case"models":await n.configModels();break;default:{const o=[e];await c(o);break}}else await n.run()}),this.program.action(async()=>{await n.run()}),this.program.configureHelp({sortSubcommands:!0,subcommandTerm:e=>e.name()+" "+e.usage()}),this.program.addHelpText("after",`\n${h.bold(o.t("cli.examples"))}:\n ${h.gray("$ vibecli # Interactive main menu")}\n ${h.gray("$ vibecli init # Run first-time setup wizard")}\n ${h.gray("$ vibecli setup --key sk-xxx # One-shot setup (auto-detect capable tools)")}\n ${h.gray("$ vibecli setup --claudekey sk-a --codexkey sk-b")}\n ${h.gray("$ vibecli status --json # Machine-readable status")}\n ${h.gray("$ vibecli config profile list")}\n ${h.gray("$ vibecli config profile create work")}\n ${h.gray("$ vibecli config profile use work")}\n ${h.gray("$ vibecli config preset save fast")}\n ${h.gray("$ vibecli config backup create snapshot")}\n ${h.gray("$ vibecli auth <token> --non-interactive")}\n ${h.gray("$ vibecli auth revoke --yes")}\n ${h.gray("$ vibecli logs path")}\n ${h.gray("$ vibecli completion bash")}\n ${h.gray("$ vibecli bench --samples 3")}\n ${h.gray("$ vibecli update")}\n ${h.gray('$ vibecli --base "https://custom.api.com" init # Custom base URL')}\n`)}async handleInitCommand(){await n.runFirstTimeSetup()}cleanupLeakedEnvVars(){const e=x();if(0===e.length||j())return;const a=o.t("messages.env_vars_cleared",{vars:e.join(", ")});console.log($()?h.yellow(a):a)}preflightArgs(e){const o=o=>e.includes(o),a=!o("--no-color")&&w();let n;v({nonInteractive:o("--non-interactive"),json:o("--json"),yes:o("--yes")||o("-y"),dryRun:o("--dry-run"),color:a}),a||(h.level=0);for(let o=0;o<e.length;o+=1){const a=e[o];if("--base"===a&&e[o+1]){n=e[o+1];break}if(a.startsWith("--base=")){n=a.slice(7);break}}n&&t.setBaseUrl(n)}async execute(e){try{if(this.preflightArgs(e),this.cleanupLeakedEnvVars(),(await C(e)).handled)return;await this.program.parseAsync(e,{from:"user"})}catch(e){if(e instanceof Error){const a=$()?h.red:e=>e;console.error(a(o.t("cli.error_general")),e.message)}process.exit(1)}}getProgram(){return this.program}}
@@ -14,7 +14,7 @@ export interface ModelPreset {
14
14
  }
15
15
  export interface ModelRegistryData {
16
16
  defaultModels: Models;
17
- /** Default model for non-Claude tools (Codex/OpenCode/OpenClaw/Hermes/AtomCode). */
17
+ /** Default model for non-Claude tools (Codex/OpenCode/OpenClaw/Hermes/AtomCode/Grok). */
18
18
  defaultToolModel?: string;
19
19
  /** Per-tool default model. Empty string (e.g. claude-code) means "use the tool's built-in default". */
20
20
  toolDefaults?: Record<string, string>;
@@ -0,0 +1,2 @@
1
+ import { type ToolAdapter } from './types.js';
2
+ export declare const grokAdapter: ToolAdapter;
@@ -0,0 +1 @@
1
+ import{existsSync as e,readFileSync as t}from"fs";import{join as r}from"path";import*as o from"@iarna/toml";import{logger as n}from"../../utils/logger.js";import{BRAND_NAME as i,PROVIDER_KEY as l}from"../brand.js";import{backupBeforeWrite as s,atomicWriteFile as a}from"./backup.js";import{pickModel as m,toolHome as d,withV1 as f}from"./types.js";import{getToolDefaultModel as c}from"../model-registry.js";const p=()=>r(r(d(),".grok"),"config.toml"),g=l,u="win32"===process.platform?'powershell -c "irm https://x.ai/cli/install.ps1 | iex"':"curl -fsSL https://x.ai/cli/install.sh | bash";function y(e){return!!e&&"object"==typeof e&&!Array.isArray(e)}function h(e,t){return y(e[t])||(e[t]={}),e[t]}function k(){if(!e(p()))return{};const r=t(p(),"utf-8");if(!r.trim())return{};try{const e=o.parse(r);if(!y(e))throw new Error("config.toml root must be a TOML table");return e}catch(e){throw new Error(`Existing ~/.grok/config.toml cannot be parsed, back it up and fix it first: ${e instanceof Error?e.message:String(e)}`)}}export const grokAdapter={name:"grok",displayName:"Grok Build",command:"grok",installCommand:u,configPath:p(),loadPrivateConfig(e){const t=k();h(t,"endpoints").models_base_url=f(e.baseUrl),h(t,"models").default=g;const r=h(t,"model"),n=y(r[g])?{...r[g]}:{};r[g]={...n,name:i,model:m(e.models,c("grok")),api_key:e.apiKey,context_window:256e3},s(p()),a(p(),o.stringify(t))},unloadPrivateConfig(){if(!e(p()))return;let t;try{t=k()}catch(e){return void n.logError("grokAdapter.unloadPrivateConfig",e)}y(t.model)&&(delete t.model[g],0===Object.keys(t.model).length&&delete t.model),y(t.models)&&t.models.default===g&&(delete t.models.default,0===Object.keys(t.models).length&&delete t.models),y(t.endpoints)&&(delete t.endpoints.models_base_url,0===Object.keys(t.endpoints).length&&delete t.endpoints),s(p()),a(p(),o.stringify(t))},detectCurrentConfig(){try{const e=k(),t=y(e.model)?e.model:{},r=y(t[g])?t[g]:null,o=r?r.api_key:null;return{apiKey:"string"==typeof o&&o.trim()?o:null}}catch{return{apiKey:null}}},getConfig(){try{return k()}catch(e){return n.logError("grokAdapter.getConfig",e),null}}};
@@ -1 +1 @@
1
- import{claudeCodeAdapter as o}from"./claude-code.js";import{opencodeAdapter as r}from"./opencode.js";import{codexAdapter as t}from"./codex.js";import{openclawAdapter as e}from"./openclaw.js";import{hermesAdapter as m}from"./hermes.js";import{atomcodeAdapter as p}from"./atomcode.js";const n=[o,r,t,e,m,p];export const TOOL_ADAPTERS=Object.fromEntries(n.map(o=>[o.name,o]));export function getAdapter(o){return TOOL_ADAPTERS[o]}export function listAdapters(){return[...n]}
1
+ import{claudeCodeAdapter as o}from"./claude-code.js";import{opencodeAdapter as r}from"./opencode.js";import{codexAdapter as t}from"./codex.js";import{openclawAdapter as e}from"./openclaw.js";import{hermesAdapter as m}from"./hermes.js";import{atomcodeAdapter as p}from"./atomcode.js";import{grokAdapter as s}from"./grok.js";const n=[o,r,t,e,m,p,s];export const TOOL_ADAPTERS=Object.fromEntries(n.map(o=>[o.name,o]));export function getAdapter(o){return TOOL_ADAPTERS[o]}export function listAdapters(){return[...n]}
@@ -313,8 +313,9 @@
313
313
  "non_interactive_aborted": "Aborted - missing required input"
314
314
  },
315
315
  "setup": {
316
- "usage": "Usage: vibecli setup --key sk-xxx or vibecli setup --claudekey sk-a --codexkey sk-b or vibecli setup --1m",
316
+ "usage": "Usage: vibecli setup --key sk-xxx or vibecli setup --claudekey sk-a --codexkey sk-b or vibecli setup --1m|--no-1m",
317
317
  "codex_1m_enabled": "Codex 1M context is enabled",
318
+ "codex_1m_disabled": "Codex 1M context is disabled",
318
319
  "codex_1m_missing_key": "No saved Codex API key was found; configure one with --key or --codexkey first",
319
320
  "validating": "Validating API key for {{label}}...",
320
321
  "invalid_key": "API key for {{label}} is invalid: {{reason}}",
@@ -313,8 +313,9 @@
313
313
  "non_interactive_aborted": "已中止 - 缺少必要输入"
314
314
  },
315
315
  "setup": {
316
- "usage": "用法: vibecli setup --key sk-xxx 或 vibecli setup --claudekey sk-a --codexkey sk-b 或 vibecli setup --1m",
316
+ "usage": "用法: vibecli setup --key sk-xxx 或 vibecli setup --claudekey sk-a --codexkey sk-b 或 vibecli setup --1m|--no-1m",
317
317
  "codex_1m_enabled": "Codex 1M 上下文已开启",
318
+ "codex_1m_disabled": "Codex 1M 上下文已关闭",
318
319
  "codex_1m_missing_key": "未找到已保存的 Codex API Key;请先用 --key 或 --codexkey 完成配置",
319
320
  "validating": "正在验证 {{label}} 的 API Key...",
320
321
  "invalid_key": "{{label}} 的 API Key 无效: {{reason}}",
package/dist/models.json CHANGED
@@ -9,10 +9,11 @@
9
9
  "toolDefaults": {
10
10
  "claude-code": "",
11
11
  "opencode": "gpt-5.5",
12
- "codex": "gpt-5.6-sol",
12
+ "codex": "gpt-6-astra",
13
13
  "openclaw": "gpt-5.5",
14
14
  "hermes": "gpt-5.5",
15
- "atomcode": "gpt-5.5"
15
+ "atomcode": "gpt-5.5",
16
+ "grok": "gpt-5.5"
16
17
  },
17
18
  "presets": [
18
19
  { "name": "GPT-5.5", "model": "gpt-5.5" },
package/models.json CHANGED
@@ -9,10 +9,11 @@
9
9
  "toolDefaults": {
10
10
  "claude-code": "",
11
11
  "opencode": "gpt-5.5",
12
- "codex": "gpt-5.6-sol",
12
+ "codex": "gpt-6-astra",
13
13
  "openclaw": "gpt-5.5",
14
14
  "hermes": "gpt-5.5",
15
- "atomcode": "gpt-5.5"
15
+ "atomcode": "gpt-5.5",
16
+ "grok": "gpt-5.5"
16
17
  },
17
18
  "presets": [
18
19
  { "name": "GPT-5.5", "model": "gpt-5.5" },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vibeapi/cli",
3
- "version": "0.0.38",
4
- "description": "CLI tool for managing AI coding assistants (Claude Code, Codex, OpenClaw, Hermes, AtomCode) with one unified config",
3
+ "version": "0.0.40",
4
+ "description": "CLI tool for managing AI coding assistants (Claude Code, Codex, OpenClaw, Hermes, AtomCode, Grok Build) with one unified config",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "homepage": "https://www.vibeapi.cn/",