尧图精选

Claude Code 环境管理器(开源):用 Go + Wails 打造多环境切换面板

🕒 发布时间:2026/9/26 22:57:53 📁 来源:尧图网络
1. 为什么我又写了一个 Claude Code 环境切换工具如果你同时维护两三个项目每个项目用的 Claude Code 后端配置都不一样那你大概率经历过这种场景早上到公司先改一遍ANTHROPIC_BASE_URL中午切到另一个仓库再改回来晚上回家跑个人项目又得重新设一遍 token。改环境变量本身不复杂烦的是它散落在 shell 配置、.env、系统环境变量三四个地方改完还得重启终端才生效。Claude Code 环境管理器就是冲着这个痛点来的。它是一个用 Go Wails 写的开源桌面应用核心能力只有一件事把多套 Anthropic API 配置存成 JSON点一下就把对应的一组环境变量写进系统再点一下切到另一套。适合需要在多套 API 配置间频繁切换的开发者尤其是同时用官方通道和统一网关通道的人。我试过纯手写 shell 函数来切换能用但配置一多就乱而且团队里其他人拿到你的脚本还得改路径。桌面面板的好处是配置可视化、状态实时可见、切换动作有明确反馈。下面我把项目骨架、配置文件结构、以及通过 TaoToken 统一 Key 接入的完整配置和验证步骤都拆开讲你可以直接照着搭一套自己的。2. TaoToken 前置先把统一通道和 Key 准备好这个工具管理的是环境变量而环境变量最终指向哪个 API 通道取决于你填什么。我建议把 TaoToken 作为统一入口来配原因是它一个 Key 就能覆盖 Claude 系列模型切换模型时不用换 Key只需要改ANTHROPIC_MODEL这对环境管理器来说正好——配置项少一个变量切换逻辑就简单一分。先到官网注册并进入控制台在 API Keys 页面创建一个 Key。创建时注意两点一是给它起个能区分用途的名字比如claude-code-dev二是创建后立刻复制页面刷新后就看不到完整值了。拿到 Key 之后你需要记住两个地址官网入口https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 基址https://taotoken.net/api注意 API 基址后面不要手动加/v1Claude Code 客户端会自己拼接路径。这一点我在排障章节还会再强调因为它是最高频的 404 来源。如果你后面要跑长期编码任务或者 Agent 流程可以顺带看一下 Coding Plan 页面它和按量调用是两套计费逻辑选错了会多花钱Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content模型对话体验https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentKey 和地址都齐了接下来进入代码部分。3. Go Wails 项目骨架与配置文件结构3.1 环境准备与初始化Wails 的前置要求是 Go 1.21 和 Wails CLI v2。Windows 上还需要 WebView2 运行时Win11 一般自带Win10 可能需要手动装。go install github.com/wailsapp/wails/v2/cmd/wailslatest wails doctorwails doctor会告诉你缺什么依赖按提示补就行。然后初始化项目wails init -n claude-env-switcher -t vanilla cd claude-env-switcher go mod tidy模板选 vanilla 就够了这个工具不需要前端框架原生 HTML CSS 反而更轻。3.2 目录结构我习惯把环境变量读写逻辑单独抽一层方便以后加测试claude-env-switcher/ ├── app.go # Wails 绑定层暴露给前端的方法 ├── main.go # 入口注册窗口和资源 ├── envstore/ │ ├── store.go # config.json 读写 │ └── apply.go # 环境变量写入系统 ├── frontend/ │ ├── index.html │ ├── style.css │ └── main.js └── config.json # 运行时生成3.3 配置文件结构配置文件是整个工具的核心结构设计得越清晰后面切换越省事。我用的是「当前激活环境 环境数组」的结构{ current_env: taotoken-dev, environments: [ { name: taotoken-dev, description: TaoToken 统一通道 - 开发用, variables: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-5-20250929 } }, { name: taotoken-prod, description: TaoToken 统一通道 - 生产用, variables: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: sk-另一个Key, ANTHROPIC_MODEL: claude-opus-4-1-20250805 } } ] }这里有个设计取舍值得说我把ANTHROPIC_API_KEY留空了。原因是 Claude Code 在同时存在ANTHROPIC_AUTH_TOKEN和ANTHROPIC_API_KEY时行为可能不符合预期容易互相覆盖。统一用ANTHROPIC_AUTH_TOKEN一个字段排障时变量更少。3.4 读写逻辑envstore/store.go里最关键的是加载和保存两个函数注意用os.UserConfigDir()而不是当前目录否则打包后配置文件会散落在奇怪的地方package envstore import ( encoding/json os path/filepath ) type Environment struct { Name string json:name Description string json:description Variables map[string]string json:variables } type Config struct { CurrentEnv string json:current_env Environments []Environment json:environments } func configPath() (string, error) { dir, err : os.UserConfigDir() if err ! nil { return , err } full : filepath.Join(dir, claude-env-switcher) os.MkdirAll(full, 0o755) return filepath.Join(full, config.json), nil } func Load() (*Config, error) { p, err : configPath() if err ! nil { return nil, err } data, err : os.ReadFile(p) if os.IsNotExist(err) { return Config{Environments: []Environment{}}, nil } if err ! nil { return nil, err } var c Config if err : json.Unmarshal(data, c); err ! nil { return nil, err } return c, nil } func Save(c *Config) error { p, err : configPath() if err ! nil { return err } data, err : json.MarshalIndent(c, , ) if err ! nil { return err } return os.WriteFile(p, data, 0o600) }0o600这个权限别省配置文件里有 Key同机器其他用户不该读到。3.5 写入系统环境变量apply.go负责把选中的配置写进系统。跨平台写法不同Windows 走setx类 Unix 走 shell profile 追加package envstore import ( os os/exec runtime ) func Apply(env Environment) error { for k, v : range env.Variables { if v { continue } if err : setVar(k, v); err ! nil { return err } } return nil } func setVar(key, value string) error { if runtime.GOOS windows { return exec.Command(setx, key, value).Run() } os.Setenv(key, value) return nil }Windows 的setx是持久化的写注册表类 Unix 这里只设了当前进程要持久化得往~/.zshrc或~/.bashrc追加你可以按需扩展。3.6 Wails 绑定app.go里把方法暴露给前端前端按钮直接调package main import ( context claude-env-switcher/envstore ) type App struct { ctx context.Context } func NewApp() *App { return App{} } func (a *App) Startup(ctx context.Context) { a.ctx ctx } func (a *App) ListEnvs() ([]envstore.Environment, error) { c, err : envstore.Load() if err ! nil { return nil, err } return c.Environments, nil } func (a *App) ApplyEnv(name string) error { c, err : envstore.Load() if err ! nil { return err } for _, e : range c.Environments { if e.Name name { if err : envstore.Apply(e); err ! nil { return err } c.CurrentEnv name return envstore.Save(c) } } return nil }跑wails dev就能看到窗口改前端代码热重载改 Go 代码自动重编译。4. 可复制配置settings.json 与切换验证4.1 Claude Code 侧的 settings.json环境管理器写的是系统环境变量但 Claude Code 自己还有一份settings.json。两者关系是系统环境变量提供默认值settings.json可以覆盖。我建议把通道信息统一放在环境变量里settings.json只留权限和工具相关配置避免两处都写 Key 导致排查困难。如果你确实想在settings.json里固定通道可以这样写{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: sk-你的Key, ANTHROPIC_MODEL: claude-sonnet-4-5-20250929 }, permissions: { allow: [Read, Edit, Bash(git:*)], deny: [] } }这个文件放在项目根目录的.claude/settings.json或者用户级的~/.claude/settings.json。项目级优先级更高适合团队统一配置。4.2 切换后的验证步骤切完配置别急着写代码先验证通道通不通。最直接的方式是用 curl 打一次模型列表或对话接口curl -s https://taotoken.net/api/v1/messages \ -H x-api-key: $ANTHROPIC_AUTH_TOKEN \ -H anthropic-version: 2023-06-01 \ -H content-type: application/json \ -d { model: claude-sonnet-4-5-20250929, max_tokens: 64, messages: [{role: user, content: ping}] }返回里带content字段就说明通道正常。如果返回 401检查 Key返回 404检查 base URL 是不是多写了/v1。然后在 Claude Code 里跑一次真实请求claude -p 用一句话说明当前工作目录的作用能正常返回说明环境变量已经被 Claude Code 读到。注意已经打开的终端不会自动刷新环境变量切换后要新开一个终端窗口。4.3 环境变量状态检查在终端里直接打印确认值写进去了echo $ANTHROPIC_BASE_URL echo $ANTHROPIC_MODELWindows PowerShell 用$env:ANTHROPIC_BASE_URL $env:ANTHROPIC_MODEL如果打印为空说明setx写的是用户级变量但当前会话没继承重开终端即可。5. 本篇常见错排查5.1 切换后 Claude Code 仍走旧配置最常见的原因是终端会话缓存。环境变量在进程启动时读取已经开着的终端不会感知新值。解决办法就是关掉重开。另一个可能是settings.json里的env字段覆盖了系统变量检查项目级和用户级两个文件。5.2 404 Not Found九成是 base URL 写错。正确写法是https://taotoken.net/api不要写成https://taotoken.net/api/v1也不要漏掉/api。Claude Code 会在 base URL 后面自己拼/v1/messages你多写一层就变成/api/v1/v1/messages。5.3 401 UnauthorizedKey 无效或没被读到。先确认ANTHROPIC_AUTH_TOKEN的值没有多余空格再确认 Key 没有过期或被删除。如果同时设了ANTHROPIC_API_KEY把它清掉只留ANTHROPIC_AUTH_TOKEN。5.4 Windows 上 wails build 报 WebView2 缺失去微软官网下载 WebView2 Runtime 安装即可这是 Wails 在 Windows 上的硬依赖不是项目问题。5.5 配置文件丢失如果你把config.json放在项目目录wails build后运行的是build/bin下的可执行文件工作目录变了配置就找不到了。用os.UserConfigDir()就是为了避免这个问题配置固定在用户目录下跟可执行文件位置无关。5.6 模型名写错导致 400ANTHROPIC_MODEL必须是完整模型 ID比如claude-sonnet-4-5-20250929不能简写成sonnet。不同通道支持的模型 ID 可能略有差异拿不准时先用模型对话页面确认一下可用模型模型对话https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content6. 把切换这件事收进一个面板搭完这套东西你手里就有了一个能存多套配置、一键切换、状态可见的桌面面板。它的价值不在于技术多复杂而在于把「改环境变量」这个动作从三四个文件里收拢到一个按钮上。团队协作时把config.json的模板发出去每个人填自己的 Key配置结构统一排障时沟通成本直接降一半。如果你还没建 Key先去控制台创建一个API Keyshttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content接入过程中遇到报错对照接入文档查参数接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content长期跑编码任务的话Coding Plan 比按量调用更划算Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content最后提醒一句config.json里有明文 Key别提交到 Git.gitignore里加一行或者干脆用os.UserConfigDir()把它放到仓库外面。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →