最近在用 oh-my-openagent + opencode 写代码,这两个组合是真香——但每当我想换个供应商(比如从 NewAPI 切到自家部署的 OneAPI,或者从 kimi 切到 deepseek)的时候,我都要做以下动作:
- 打开
~/.config/opencode/opencode.jsonc,把provider.omos整段替换 - 打开
~/.config/oh-my-openagent/oh-my-openagent.json,把所有agents.*.model和categories.*.model全部改一遍 - 祈祷自己没改漏
- 启动 opencode,发现
sisyphus还在用上家的模型,回去看 JSON,果然漏了一个 - 重复步骤 3-4
步骤 4 通常要发生两到三次。直到某天我连续把同一份配置改了 4 次,决定:这事必须工具化。
于是就有了 oh-my-openagent-switch——一个 Tauri 桌面应用,核心功能就一句话:点一下配置名,所有相关 JSON 全部改好。
它能做什么
| 功能 | 说明 |
|---|---|
| 配置管理 | 增删改查、复制、深拷贝 payload |
| 一键应用 | 同时修改 opencode.jsonc 的 provider.omos,整体替换 oh-my-openagent.json |
| 自动备份 | 每次应用前自动备份到 backups/<file>-<timestamp>.jsonc,写入失败保留原文件 |
| 导入 / 导出 | 从当前 opencode 自动导入;从外部 JSON 文件导入 / 导出到任意路径 |
| 激活状态检测 | 实时识别当前激活配置、配置漂移、孤立配置 |
| 跨平台 | macOS / Windows / Linux 桌面应用 |

上面就是工具的主界面,左边是所有配置项,中间那个绿色”已激活”徽章的就是当前在用的供应商。点一行 → 右边出现应用/编辑/复制/删除按钮 —— 点”应用”,就完成了一次”切换供应商”。
最后一行是重点——我写代码主力 mac,但偶尔用 Windows 笔记本出门,跨平台是硬需求。
选型:为什么是 Tauri 不是 Electron
我调研了一圈,最后选了 Tauri 2。原因如下:
- 包体积 — Tauri 编译出来的
.dmg大约 8MB,Electron 同类应用动辄 80-150MB。我不需要 Electron 那个 Chromium 给我”打开本地 HTML”用。 - 启动速度 — Tauri 冷启动约 200ms,Electron 普遍 1s+。开工具卡 1 秒,跟人对着干,我会想砸电脑。
- Rust 后端 — 我一直想认真学 Rust,这次正好有动力。
jsonc-parser、serde_json、sha2写起来非常顺,处理 JSONC(带注释的 JSON)比 JS 那边的JSON.parse干净得多——JSON.parse不支持注释和尾逗号,jsonc-parser支持,这就赢了。 - 跨平台打包 — Tauri 的
tauri build+ GitHub Actions,tag 触发三平台构建,产物直接发 Release。很省心。
代价是 Tauri 的生态比 Electron 小很多,有些库得自己造(比如配置存储的目录解析)。但考虑到我这个项目主要在干”读写文件 + 显示表单”,复杂度可控。
技术栈
- 前端 — React 18 + TypeScript + Vite + Tailwind v4 + daisyUI + Zustand + React Router
- 后端 — Tauri 2 (Rust) +
jsonc-parser+serde_json+sha2 - 存储 —
~/.config/oh-my-openagent-switch/下的 JSON 文件configs/<id>.json— 配置正文backups/<file>-<timestamp>.jsonc— 备份文件active.json— 当前激活配置 + 指纹
几个有意思的实现细节
1. JSONC 解析不能丢注释
opencode 的配置文件是 JSONC(带注释、尾逗号)。我用 jsonc-parser 解析,但写回时必须保留原注释。不然下次用户打开看,注释全没了,会骂我。
做法:解析时拿到 ObjectProperty 节点的 range,写回时只在值的位置做字符串替换,不动其他字节。等价于 “surgical edit”。
2. 配置漂移检测
active.json 里存了配置指纹(sha2 算的配置正文 hash)。每次启动工具时,把磁盘上的 opencode.jsonc 的 provider.omos 算个 hash,跟 active.json 里的对比——不一致就提示”配置漂移”,可能用户在工具外手动改过。
这功能原本是为了”防止工具外误改”,结果我自己用它抓出了两次 oh-my-openagent 自动更新后悄悄改回默认值的 bug。
3. 深合并 provider.omos,不是替换
应用配置时,opencode.jsonc 的 provider.omos 要深合并:用户新增的 models.* 字段要保留,被本工具覆盖的字段要更新。比 JSON.parse + JSON.stringify 简单粗暴替换要友好得多。
// 伪代码
function applyProvider(omos: ProviderConfig) {
const current = readOpencodeConfig();
const merged = deepMerge(current.provider.omos, omos);
writeProviderField("provider.omos", merged);
}
4. 写入失败保留原文件
写 opencode.jsonc 时,先用临时文件 + rename 原子写入。失败的话原文件不动,只在 UI 上提示。没有”写到一半崩了,配置文件整个没了”这种噩梦场景。
跨平台打包的真相
macOS 首次打开会弹”无法验证开发者”,要去「系统设置 › 隐私与安全」点”仍要打开”。我没有做 Apple 代码签名(开发者账号要 99 刀/年,我先不花)。
GitHub Actions 上配了三个 workflow,v* tag 触发三平台构建,产物发到 Release。实际跑下来,Linux 的 .AppImage 最好用,Windows 的 .msi 偶尔被 Defender 误杀,macOS 的 .dmg 每次都要点”仍要打开”。
已知限制(MVP)
老实说,没做完的功能:
- ❌ 不含代码签名 / 公证(macOS 那个弹窗就是代价)
- ❌ 不含自动更新(updater 插件暂未启用)
- ❌ 不支持自定义 opencode 路径,只认
~/.config/opencode/(macOS / Linux)或%APPDATA%\opencode\(Windows) - ❌ 不支持配置分组 / 标签 / 搜索(路线图规划中)
路线图
- 配置分组 + 标签
- 全局搜索
- 一键备份清理(保留最近 N 份)
- 代码签名 + 公证 + 自动更新
- 多语言(英 / 中)
仓库
代码全部开源 MIT:
名字里那个 “swtich” 是我手抖打错的(本来想打 switch)。仓库已经创建,改名的代价是丢 star 链接,所以就这么着了。如果以后看这个 typo 觉得碍眼,欢迎 PR 帮我改库名,我会欣然接受。
写在最后
这就是我前面说的”瞎搞”。10 年下来什么技术都摸一点,什么技术都不精——但偶尔能造出一个让自己爽的工具。这就够了。
如果这个工具对你也有用,欢迎提 issue / PR / star。