先说实话:我一开始对 opencode 是带偏见的。团队里有人提议把新项目的 agent 从 claude code 换到它时,我的第一反应是“又一个套壳 CLI,换个 UI 而已”。结果用了一周后,我把话说收回来了——opencode 对多文件上下文、项目级配置、Skills 这套机制的处理方式,确实和我用过的其他 agent 不一样。这篇文章就把我从安装、配模型、写 Skills、接 LSP 到拿 Playwright 跑前端 bug 复现的完整过程写下来,给正在观望或者已经装上但不知道从哪下手的人一个参考。
1. 先把定位搞清楚:opencode 不是“又一个 claude code 套壳”
1.1 值得先搞清楚的一件事:它是一套独立实现的 agent 架构
很多人第一次看到 opencode 的 TUI 界面,会觉得它长得像 claude code,就默认它是“换个皮肤的 Claude Code”。这个判断不准确。
opencode 的核心不是某个模型,而是一套完整的 agent 运行框架:它自己实现了工具调用循环、会话管理、多 provider 路由、权限系统和 Skills 机制。模型是通过 provider 抽象层接进来的,你可以接 Anthropic、OpenAI、DeepSeek、本地 Ollama,甚至接各种聚合服务。换句话说,opencode 跟 claude code 的关系不是“模仿品”,而是“同赛道竞争对手”,只是它把重心放在了可配置和可扩展上。
我真正意识到这点,是在处理一个跨多个服务的项目时。项目里既有 TypeScript 后端,又有 React 前端,还牵扯到几个 JSON 配置文件。claude code 在会话里改到第三个文件时上下文就会明显“飘”,要么忘记前面定的命名规范,要么把已经确认不该动的文件又改了。opencode 的会话管理方式不一样:它把文件状态、工具调用结果、用户确认过的决定都拆得更细,agent 在长会话中更不容易丢失前文信息。
当然这不是说 claude code 不行,而是两者设计取向不同。opencode 更强调“把控制权拿回来”:模型可以换,工具可以加,行为可以用 Skills 调。对喜欢折腾、经常在不同项目间切换的人来说,这种自由度是很值钱的。
1.2 和 codex、claude code、pi 放在一起,它到底赢在哪里
我把它们放在同一个维度上做了一次横向对比,不看宣传,只看我用下来的实际体感:
| 对比项 | opencode | claude code | codex CLI | pi |
|---|---|---|---|---|
| 模型接入方式 | 多 provider,自由切换 | 以 Claude 为主 | OpenAI 系为主 | 较封闭 |
| 会话管理 | 文件状态拆分细,长会话稳定 | 会话机制成熟,但长上下文有衰减 | 单线程感强 | 一般 |
| Skills/规则注入 | 内置 Skills 机制 | 需要借助 CLAUDE.md 等手段 | 插件机制较新 | 有限 |
| 编辑器生态 | VSCode + JetBrains 插件,有桌面版 | 官方 IDE 集成逐步完善 | 偏 CLI | CLI 为主 |
| 开源/可扩展 | MIT 开源,配置驱动 | 未开源 | 未开源 | 闭源 |
| 上手成本 | 中低,配置一次后续省事 | 低,开箱即用 | 低 | 中 |
这个表格里我最看重的是“模型接入方式”。opencode 允许多 provider 并存,意味着同一个会话里你可以先用一个便宜模型做初稿,再切到更强模型做 review。这种“按需换模型”的用法,在项目预算敏感或者某个模型临时抽风时,特别实用。
1.3 出处与社区:不是大厂出品,但是背景很有意思
公开信息显示,opencode 是开源项目,核心发起和维护方是 Anomaly Innovations——就是做 SST 框架的那个团队。SST 在开发者社区里口碑不错,这保证了 opencode 在架构设计上是经过考量的,不是随便做来玩的东西。项目采用 MIT 协议,意味着你不仅能用,还能基于它做二次开发,比如搭团队内部定制的 agent。
oc 到了 2.0 版本,配置格式、插件架构都有明显调整。网上搜教程时要注意版本差异,很多旧教程里写的配置项在 2.0 里已经不适用了。我后面讲配置时也会特意说明这一点。
2. 安装到能跑通:这条路上有三个坑位
2.1 根据自己习惯选安装方式
opencode 的安装方式不止一种,我建议根据你平时用命令行的习惯来选。
如果你已经装了 Node.js,npm 全局安装是最直接的。官方 README 现在推荐的方式绝大多数是 npm,包名以仓库说明为准,一般类似 opencode-ai。装完直接在终端敲opencode就能进入 TUI。
如果你不想把 Node 环境牵扯进来,官方也提供了 curl 脚本安装的方式,适合 Linux/macOS 环境,脚本会把这套工具放到你的用户目录下,不需要 root 权限。macOS 用户还有 Homebrew 路线可以选。
我个人推荐:主力开发机用 npm,因为后续升级只需要npm update -g一条命令;在服务器或者临时环境用 curl 脚本,装完就走,不污染环境。
注意:opencode 是个更新很勤快的项目,建议每两周左右关注一次版本更新。版本滞后太久,配置文件格式可能已经变了,那种“昨天还好好的,今天起不来了”的问题,一半是服务商故障,另一半就是版本不匹配。
2.2 Windows 上“无法将 opencode 识别为 cmdlet”的完整排查
这条错误可以说是我见过最多人吐槽的:opencode : 无法将“opencode”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。网上一搜一大片,但很多人只给结论不给排查路径,我踩过一次后把完整思路整理出来了。
这个报错的本质是:你在 PowerShell 里输入 opencode,但 Windows 系统不知道这个命令放在哪。可能性无非三个:npm 全局安装目录不在 PATH 里、安装没完成、装错了包名。
第一步,先在终端里执行npm config get prefix,拿到 npm 全局安装根目录。如果这个路径是C:\Users\<你的用户名>\AppData\Roaming\npm,Windows 默认会在用户级 PATH 里自动加这个目录,理论上装完就能用。如果 npm 的 prefix 被改到了别处,比如 Program Files,那大概率没权限写,安装会失败一半,命令自然也不存在。
第二步,执行where opencode或者Get-Command opencode看看系统能否找到这个命令。如果提示找不到,去看npm ls -g里是否有这个包。
第三步,确认包名没错。opencode 在 npm 上的命名历史上有点小复杂,如果你用的是旧教程里搜到的某个重名包,装完大概率命令不叫 opencode。最稳的办法是直接去 GitHub 仓库主页看 README 里的安装命令,不要凭记忆敲包名。
提示:修改 PATH 后要重开终端窗口才能生效。很多人改完立刻再敲
opencode,发现还报错,就以为没改对——其实是当前窗口的环境变量还没刷新。
2.3 装完先做模型检查,而不是急着写第一句话
安装完成后,很多人第一反应是直接开个目录就opencode .,然后发现 agent 回一句 error,就以为装坏了。其实不是装坏了,是模型配置还没建立。
opencode 首次启动时会引导你完成 provider 登录或配置。如果你平时用某个模型服务商,可以在 TUI 里用/models命令查看当前配置下能用的模型列表;如果只有error或者列表为空,说明 key 没填对或者 model id 写错了。
我建议的工作流是:先启动一次opencode,把登录流程走完;然后退出,把项目目录打开再进入;最后在 TUI 里敲/models确认模型列表正确。这三步走完,才算是真正“跑通”了。
3. 模型接入才是大头:provider、订阅与配置文件
3.1 配置文件的层级、位置和 2.0 之后的格式变化
opencode 的配置是分层的。全局配置放在用户主目录下的.config/opencode/opencode.json(Linux/macOS,Windows 在类似路径),这部分存的是通用信息,比如默认模型、全局 key、代理规则等。项目级配置则放在项目根目录的opencode.json,这部分存的是项目专属的设置,比如项目用哪个 LSP、启用了哪些 Skills、要不要开启权限审批。
互不干扰的设计,你要记住一个原则:凡是“换台机器也要生效”的放全局,凡是“进了这个项目才需要”的放项目级。
到了 2.0 版本,配置文件统一为 JSON 格式。网上一些旧教程会让你写 YAML 或者 TOML,那些配置在旧版本可能能跑,新版本直接不识别。判断方法很简单:打开配置文件,如果第一行不是{开头,先想想是不是版本没跟上。
配置里最核心的几项:
provider:模型服务商,比如 openai、anthropic、deepseek,有时是第三方聚合服务。model:默认使用的模型 id,比如某个开源模型的具体型号。apiKey:密钥,通常放在环境变量里,配置里填引用即可,不要把明文 key 写进仓库。baseUrl:API 服务地址,用第三方兼容接口时必须填对。experimental:一些实验性功能开关。permission:控制自动执行、询问、拒绝的规则。
3.2 多 provider 混用的实操配置
多 provider 混用是我最推荐大家尝试的用法。常规做法不是把所有 key 都塞进一个文件,而是在配置里声明 provider 列表,再通过环境变量管理各自的 key。
我在一个写博客生成工具的项目里是这样配的:
{ "provider": { "main": { "npm": "@ai-sdk/openai-compatible", "name": "MainProvider", "options": { "baseURL": "https://api.example.com/v1", "apiKey": "{env:MAIN_API_KEY}" }, "models": { "fast-model": { "name": "Fast Model" }, "strong-model": { "name": "Strong Model" } } }, "local": { "npm": "@ai-sdk/openai-compatible", "name": "Ollama", "options": { "baseURL": "http://localhost:11434/v1" }, "models": { "qwen2.5-coder:7b": { "name": "Qwen Coder 7B" } } } }, "model": "fast-model", "permission": { "edit": "ask", "bash": "ask" } }这样配置之后,在 TUI 里就能通过/models随时切换:简单任务用 fast-model,复杂重构切换到 strong-model,离线或者不想烧 token 时切到本地 Ollama。日常开发里这种“用便宜模型跑量、贵模型做 review”的组合,一个月能省下不少预算。
3.3 社区为什么普遍配合 ccswitch 这类工具
你搜 opencode 相关讨论时,会频繁看到 ccswitch。简单理解,它就是一套“API 服务商配置切换器”,本质上是在多个 provider 的 baseURL、apiKey、model 映射之间做集中管理和一键切换。
为什么要它?因为很多人手里的 key 不止一个:官方直连的、开源模型聚合服务的、公司内部 HTTP 网关的。如果没有一个统一的地方管理 baseURL 和 key,每次切换都要去改环境变量或者改 JSON,非常容易出错。ccswitch 这类工具把“服务商 A 的 key + 模型映射”当成一套完整配置管理起来,切换时一次性替换,opencode 读取到的就是一套完整、自洽的配置。
我自己在团队里推广 opencode 时,要求每个成员必须把自己的服务商配置通过 ccswitch 管理,原因很简单:它减少了“我这明明配好了,怎么到你那就报错”这类问题。大家统一用一套配置模板,出问题对根因都快很多。
提示:社区里常说的 go 套餐/订阅聚合服务,本质上是把多个模型放在一个 API 地址后面,用同一个 key 访问。对 opencode 来说它就是一个普通 provider,配置上不外乎 baseURL、apiKey、model 三样,选模型时注意套餐里实际包含哪些模型。
3.4 Java/Maven 项目下的 mvn 配置
如果你用 opencode 处理 Java/Maven 项目,会遇到一个别处很少被提到的问题:agent 在终端里执行mvn compile时,经常报找不到mvn命令,但你自己在同一个终端敲是好的。
原因多半是 opencode 的启动环境和你 shell 的登录环境不一致,加载不到 Maven 相关的 PATH 配置。排查思路是:先在你的 shell 里执行which mvn拿到绝对路径,然后在 opencode 配置里把环境变量显式声明出来:
{ "env": { "PATH": "/usr/local/bin:/opt/homebrew/bin:/Users/username/.sdkman/candidates/maven/current/bin:/usr/bin:/bin" } }这里最关键的是把 Maven 所在的目录追加到 PATH 前面。Java 开发者如果还用了 sdkman 管理 JDK 版本,也要把 sdkman 的 candidate 路径一并加进去,否则 agent 拿到的 Java 版本可能和你的项目要求不一致。
另外,Maven 项目里经常有本机构件库配置(settings.xml),如果 agent 执行 mvn 时连私有仓库都拉不到,检查一下是不是没有把配置文件路径通过MAVEN_OPTS或-s参数传给子进程。这类问题很隐蔽,光看报错很容易误判成网络问题。
4. 让 agent 真正“像人一样干活”的几项功能
4.1 Skills:把项目规范写成 agent 能读的说明书
很多人用 agent 工具,把期望放在“模型足够聪明,什么都会”。但实际玩下来你会发现,模型再强,不了解你项目的潜规则,也会干出一些让你血压升高的事。比如明明项目约定组件文件用 PascalCase,它给你建了一堆 kebab-case;明明 commit 规范要求带 typescript 前缀,它给你写“update some files”。
opencode 解决这个问题的机制是 Skills。简单说,Skills 是一组 Markdown 文档,放在项目的.opencode/skills目录里(也能放全局目录,对所有项目生效),告诉 agent 在这种场景下应该怎么做。
我写了一个简单的示例供参考:
--- name: frontend-bug-fix description: 修复前端页面 bug 时遵循的流程 --- 1. 先找到对应页面组件,理清状态流转。 2. 如果是接口返回问题,先查看 network mock 数据和类型定义。 3. 修改后必须检查同文件其他调用点,防止连带影响。 4. 单测用 vitest 跑对应文件,不要跑全量。这个机制大家不陌生——用 claude code 的人会想起 CLAUDE.md,用其他 agent 的会想起 rules 文件。但 Skills 和它们的区别是:Skills 是按需加载的,agent 看到相关任务时才去读对应文档,而不是一股脑全塞进上下文。所以你可以塞几十个 Skills 而不担心把上下文撑爆。
社区里很火的 superpowers 就是利用了这一点:它是一个现成的 Skills 包,装到全局目录后,agent 就获得了规划、调试、代码审查等一系列经过验证的行为模板。我装了之后明显感觉 agent 在复杂任务里更“有条理”,而不是拿到需求就开始乱改。安装方式也不复杂,clone 到全局 skills 目录即可。
这里给一个实际感受:没有 Skills 时,agent 就像刚入职、只知道技术栈但不懂团队规矩的新人;加了 Skills 后,相当于给新人发了一份带详细批注的开发手册。你不能指望它完全像老手,但至少不会踩低级规矩的坑了。
4.2 Memory:该记什么、不该记什么
opencode 的 Memory 机制,解决的是跨会话的“记忆”问题。人的记忆会丢,agent 的上下文也会丢,但有些信息你希望它每次都知道。比如这个项目的技术决策、你偏好什么样的提交信息、哪些目录不能随便动。
但 Memory 不是越大越好。我见过有人把整个技术方案塞进 memory,结果 agent 每次响应都背一遍方案,token 烧得飞快,对实际帮助却不大。我的建议只有一条:记结论,不记流水账。
值得记的:
- 项目架构决策,比如“业务层与数据层分离,禁止在组件中直接请求接口”。
- 全局偏好,比如“提交信息统一使用英文,遵循 conventional commits”。
- 痛点清单,比如“不要修改 generated 目录下的文件,改动会丢失”。
不值得记的:
- 某次 bug 的完整排查日志。
- 特定某天你让它做的事。
- 任何会频繁变化的信息,比如当前分支名、当前版本号。
4.3 接 LSP:让 agent 看到编译器级错误
opencode 的一个容易被忽略但很有价值的能力,是接入 LSP(Language Server Protocol)。LSP 就是编辑器里做代码补全、跳转定义、报类型错误的那套技术,比如 TypeScript 的 typescript-language-server、Python 的 pyright、Go 的 gopls。opencode 接上 LSP 之后,agent 在分析代码和修改代码时能拿到编译器和类型系统的诊断信息,而不只是靠“读文本”来猜。
这么说吧:不接 LSP 的 agent 修改代码,就像一个人拿着记事本改代码,只能靠肉眼找问题;接了 LSP,等于给了它一个编译器随时在旁边提示“这行类型不匹配”“这个函数参数错了”。改起来准确率会高不少。
配置方式上,opencode 的配置里有 LSP 相关的声明项,指定要加载的 language server 即可。我在一个 TypeScript + React 项目里做了一次对比测试:不接 LSP,让 agent 改一个涉及类型推导的公共函数,它改完运行时才报错;接上 LSP 后,同样的任务,agent 在生成代码时就会收到类型错误反馈,并当场修正。
需要提醒的是:LSP 不是开得越多越好。如果你的项目混了七八种语言,把所有 language server 全部启动,TUI 会有明显卡顿。按需加载就好,哪个目录是 TypeScript 就加载 TS server,哪个模块是 Python 再加 pyright。
4.4 用 Playwright 验证前端 bug 的实测复现
前端项目里让 agent 修 bug,最大的问题是它“看不见”页面。纯代码层面的问题,它可以分析;但布局错乱、交互点击无反应、控制台报错这类问题,只靠静态代码分析很难定位准确。opencode 有一个很实用的组合方案:结合 Playwright,让 agent 自己打开浏览器去复现 bug。
我在一个后台管理系统里遇到过一个搜索页偶发白屏的问题。传统排查方式是自己开 dev server、打开页面、手动操作复现、看网络和 console,很耗时间。用 opencode + Playwright 的方式,我给它写了一个明确的任务描述:
“用 Playwright 打开这个搜索页面,填入关键词 phone,点击搜索,等待列表渲染完成,截图保存,并抓取浏览器 console 里所有 error 日志。”
opencode 会调用 Playwright 工具完成整套操作,然后把截图路径和 console 日志带回来,结合源代码分析。那次实测中,它从 console 里抓到了一个资源加载失败的报错,顺藤摸瓜找到了 CDN 域名配置问题,整个定位过程不到 10 分钟。
这里要强调一个技巧:让 agent 用 Playwright 跑前端时,不要只让它“打开页面看看”,而是要给出非常具体的操作步骤、等待条件和需要收集的信息。agent 不是测试工程师,它不会自主设计测试用例,但你给它明确指令后,它的执行能力是靠谱的。
5. 从终端走向编辑器:VSCode、IDEA 与桌面版
5.1 VSCode 插件的核心价值是 diff 审阅
终端 TUI 虽好,但很多人的日常工作主战场还是编辑器。opencode 官方提供了 VSCode 插件,装上之后,你可以在编辑器侧边栏打开 opencode 面板,直接基于当前打开的文件向 agent 提问、要求修改代码。
这个插件最值钱的地方不是“在编辑器里开个终端”,而是 diff 审阅体验。agent 修改完代码后,插件会以 diff 形式展示每一次改动,你可以逐行确认是否接受。相比之下,纯终端场景下 agent 改完文件,你只能靠 git diff 自己查,交互效率差很远。我第一次用插件执行一个跨 5 个文件的改动时,每个文件都能在编辑器里直观看到变化、决定要不要保留——这种“可控感”对生产项目很重要。
插件依赖本地的 opencode CLI 和登录配置,也就是说你在终端里配好的 provider、key、Skills,在插件里直接就能用,不用重复配。
5.2 JetBrains IDEA 插件的适配情况
用 Java/Kotlin 栈的同事可能会担心 IDEA 适配问题。opencode 官方在 JetBrains 插件市场里也上了插件。功能界面整体思路和 VSCode 版类似,但成熟度略逊一筹,主要体现在某些面板操作的流畅度和报错提示的友好程度上。
我用 IDEA 插件跑过一个 Maven 项目的模块拆分任务。agent 能读取项目结构、执行 mvn 命令、修改代码,整个过程的对话记录都在 IDEA 侧边栏里,体验是完整的。如果你是纯 Java 开发者,平时不碰终端,那在 IDEA 里直接用 opencode 体验会好很多;如果你两边都装了,建议优先用 VSCode 版本,功能相对更完整一些。
5.3 桌面版的意义:降低使用门槛
opencode 桌面版是我意料之外的一个产品。它本质上是一个 GUI 封装,不需要在终端里操作,适合那些不想碰命令行、但想借助 AI agent 写代码的同事。装好后可以打开一个项目目录,在界面上选模型、开对话、查看文件改动。
桌面版还解决了一个场景:跨项目切换。终端里你每次都要cd到对应目录再启动,桌面版可以直接在界面上管理多个项目的会话记录,对同时维护多个仓库的人来说确实更顺手。目前它还在快速迭代阶段,和 CLI 相比功能上仍有差距,但作为一个“低门槛入口”,价值是实打实的。
6. 高频报错定位思路:这几条路大多数人都会走一遍
6.1 error: unexpected server error 的排查链路
用过 opencode 的人,几乎都会遇到error: unexpected server error. check server logs这类报错。问题在于:报错信息太笼统,没说到底是谁的错误。我的排查链路基本是固定三步:
第一步,确认 provider 服务端是否正常。直接看服务商的状态页,很多聚合服务或大规模模型的 API 会有不定期波动。如果状态页有异常,不用继续查,等恢复就行。
第二步,开 opencode 的调试日志重新跑一次。opencode 支持调试模式,会输出更详细的请求和响应信息。重点看三个时间点:请求发出前、请求接收后、响应解析时。大多数情况下错误出现在响应解析阶段,原因往往是服务端返回的内容格式和配置里声明的模型不兼容。
第三步,用换模型来缩小范围。把配置切到同一个 provider 下的另一个常见模型,如果正常,说明是某个特定模型接口的问题;如果还报错,说明是配置或者网络层面的共性问题。这个“二分法”虽然笨,但定位速度最快。
提示:不要一报错就怀疑是 opencode 本身的问题。它在终端里只是个客户端,真正的计算和响应都发生在服务端。90% 以上的 unexpected server error,本质是上游服务返回了异常内容。
6.2 “model not available” 的合规处理思路
另一个高频报错是this model is not available in your country。遇到这个提示,第一反应不要是去网上搜“怎么绕过限制”,那些教程很多是拿你的 key 去跑不明脚本,风险极高。
正确的处理顺序是:
先确认 model id 是否拼写正确。有些模型的完整名称带区域后缀,比如带
fr之类的标识,你只写了前半截,服务端可能就把它当成一个不可用模型。查服务商官方文档里对该模型的区域支持说明。如果你的账号所在区域确实不支持这个模型,那就是硬限制。
换用服务商在该区域正常开放的模型。绝大多数服务商都有替代模型,只是能力档位不同。
如果你需要完全本地化、不依赖外部服务,可以配置本地模型(比如通过 Ollama 跑开源模型),把 provider 指向 localhost 即可。这样既没有区域限制问题,也不涉及数据传输。
我见过有人为了用某个被限制的模型,把配置文件里的地区参数改来改去,结果 key 被服务商风控直接封禁。为省一点麻烦去冒账号风险,完全不值得。
最后再说两句实在的
opencode 用到现在,我最深的体会是:它值得花时间去配置,而不是装完当 claude code 用就完事。配置好 provider、Skills、LSP,它才真正变成一个“懂你项目”的 agent,而不只是一个会聊天的代码生成器。
在团队里推广的话,建议先让一个人把配置文件、Skills 模板、Maven/Node 这类环境的坑摸清楚,沉淀成一份内部文档,其他人照着抄一遍就行。opencode 的配置都是文本文件,天然适合版本化管理和团队共享。这也是它能在一个团队里从“个别折腾”发展到“全员使用”的关键。