opencode 这个开源的终端 AI 编程智能体(Agent),我上篇讲的是入门:怎么装、怎么起一个 session、怎么用/init和/new把对话拉起来。这里先给没读过上篇的朋友一句话定位:它是跑在终端里的“AI 结对程序员”,不依赖特定 IDE,纯 TUI 交互,底层把大模型变成能读代码、改文件、跑命令的自动化角色。这篇下篇,咱们把四个容易被忽略、又决定上限的模块掰开:工具(Tools)、服务面(Providers/Servers)、外壳(Shell/UI)和实战集成。适合谁读?已经用上 opencode 想深度定制的、打算接入本地模型或私有 API 的、想把它嵌进团队工作流的——看完都能直接照着改配置。
1. 先从工具集说起:Agent 的“手”与“眼”
1.1 默认工具面:从读文件到跑命令
很多刚接触的人以为 Agent 只是“能打字聊天的模型”。这个理解在 opencode 的场景里是错的。决定一个任务能不能完成的,不是模型多聪明,而是它手上有没有恰当的工具、有没有权限调用。模型负责思考,工具负责动手。
opencode 默认提供给模型一组工具,常用的大致分这几类:
- 读类:
read读指定文件内容,grep关键词定位,glob按文件名模式找文件 - 写类:
write新建或覆盖文件,edit按行精准修改,patch应用差异补丁 - 执行类:
bash跑终端命令,比如测试、构建、查日志 - 外部获取:
webfetch抓取网页内容,task把子任务丢给新开的子 Agent 并行处理
我举个真实场景解释这套“眼手配合”。假设线上接口偶发 5xx,日志已经贴过来了。opencode 会先grep搜接口路由名,再read打开 controller 和 service 文件,定位到疑似空指针的位置,接着用edit补一个判空,最后bash跑一遍单测确认没改坏。整个过程我没碰过一次编辑器。工具面之所以重要,是因为模型本身没有验证能力,不接工具就只能凭训练数据猜;给了工具,它才能“验证自己的猜测”。所以工具面不是简单的“Do anything”开关,它决定了 Agent 能干多少活。
1.2 工具权限与安全护栏:别把 Agent 放养
工具越强,出事的可能性越大。opencode 的权限模型基本做到位了,它是“按工具分别授权 + 命令模式匹配”的组合,也是我最先研究的部分。一个典型配置长这样:
{ "permission": { "bash": { "deny": [ "rm -rf /", "git checkout .", "sudo" ], "ask": [ "git push", "docker compose *" ], "allow": [ "npm test", "go test ./...", "ls *" ] }, "edit": { "ask": ["src/services/*"] } } }我的默认策略是“宁严勿松”:只读类工具全开;写类工具对陌生路径 ask;bash只放白名单命令,高危命令一律 deny。真正需要全自动时才临时用opencode --dangerously-allow-all,而且只在一次性容器或临时分支里用,用完立刻关。
为什么强调这个?我见过有人把deny配成空数组,Agent 判断“这轮改的配置太多,干脆还原”,然后执行了git checkout .,把几百行未提交的代码全冲掉了。这种事故不是模型蠢,是权限配置给了它犯错的机会。记住一条:命令白名单写得越窄,Agent 闯祸的空间就越小。
1.3 自定义工具与技能(Skills)
开箱工具永远不够,真正好用的是“技能”(Skill)。在 opencode 社区里,Skill 本质上是一份“给 Agent 看的操作手册 + 可选脚本”,核心载体是 SKILL.md。我的习惯是在仓库里建.opencode/skills/目录,每个技能一个子目录:
--- name: commit-message description: 根据当前 git diff 生成符合规范的中文 commit message --- # 步骤 1. 执行 git status 和 git diff --stat 2. 读取最近的提交信息,确认提交风格(type: subject) 3. 如果涉及 breaking change,在 footer 写 BREAKING CHANGE要点是 description 必须写具体。“生成提交信息”这种写法太模糊,Agent 不知道什么时候该触发;写成“根据 git diff 生成符合XX规范的中文提交信息”,触发率会高很多。这跟搜索词一个道理,Agent 靠 description 判断是否触发。再提醒一句:不同版本对 Skill 目录的自动扫描策略不一样,如果你的版本不扫描,就在 AGENTS.md 里显式写一句“项目技能位于 .opencode/skills 目录”,效果一样。
2. 服务面:把模型通道配置明白
2.1 Provider 与多模型路由
先约定概念:opencode 里的“服务面”,就是回答“模型从哪个服务来”的接入层,也就是 provider/servers 体系。它跟工具面一样是可配置的。
默认情况下,opencode 能列出一大堆主流模型服务,多数通过opencode auth login填 API Key 就能启用。但真正到项目里,你更可能自定义 provider,接入公司内部部署的模型网关,或者接某个兼容 OpenAI 协议的服务。配置文件大概是这样的:
{ "$schema": "https://opencode.ai/config.json", "provider": { "custom": { "npm": "@ai-sdk/openai-compatible", "name": "Internal Gateway", "options": { "baseURL": "https://gateway.example.internal/v1" }, "models": { "internal-coder-32b": { "name": "Internal-Coder-32B" } } } } }一个 provider 就是“一套协议 + 一个 baseURL + 一组模型名”的集合。opencode 模型层基于 Vercel AI SDK 生态,所以自定义时用npm字段指定适配包,大多数 OpenAI 兼容服务直接用@ai-sdk/openai-compatible就行。不同版本的键名可能略有变化,拿不准就先opencode auth login看交互提示。
多模型方面,opencode 不是自动路由,而是手动切换。我在开发环境里会同时配三个:一个小而便宜的模型负责补全和简单重构,一个中档模型负责日常编码,一个强推理模型只在排查疑难 bug 时切过去。快捷键一般是Ctrl+K打开模型选择器,或直接输入/models。判断标准很简单:这个任务需要多强的推理能力。
2.2 本地模型接入:Ollama / LM Studio
私有化部署、省成本、批量小任务,这些都适合接本地模型。opencode 接本地模型很方便,因为 Ollama、LM Studio 都提供 OpenAI 兼容接口。以 Ollama 为例:
- 本机装好 Ollama,拉一个编码能力不错的模型,比如 qwen2.5-coder
- 配置里加一个 provider,
baseURL指向http://localhost:11434/v1 - 模型名对不上就先用服务商列表核对名称,再切过去用
{ "provider": { "ollama": { "npm": "@ai-sdk/openai-compatible", "name": "Local Ollama", "options": { "baseURL": "http://localhost:11434/v1" }, "models": { "qwen2.5-coder:32b": { "name": "Qwen Coder 32B" } } } } }实测下来,本地小模型在 opencode 里干“低级劳动”是划算的:整理 TODO、批量替换、写重复性测试桩,都能干。但让它独立排查跨模块的内存问题,经常会卡在推理链里出不来。我的方案是大小模型分工:本地模型负责跑量,远程强模型负责攻坚,成本和安全都兼顾。另外提醒,本地模型做全仓库任务会明显变慢,任务拆得越细越容易出成果;第一次用先跑一条最小任务确认 API 通,别上来就开大任务。
2.3 参数、额度与意外报错排查
服务面配好之后,高频问题集中在三块:参数没生效、额度和限流、报错看不懂。
参数方面,温度和输出上限能按模型单独设:
"models": { "internal-coder-32b": { "name": "Internal-Coder-32B", "options": { "temperature": 0.3, "maxOutputTokens": 8192 } } }写代码场景我把温度压在 0.1~0.4 之间,不然模型容易“发挥过头”,改出一堆脑洞代码。maxOutputTokens给足,长文件改写才不会半途截断。
额度是另一个高频问题,特别是“套餐是不是按模型分开算”这个疑问。如果你买的是 opencode go 这类第三方聚合套餐,最靠谱的确认方式只有两个:看套餐说明原文,或直接找客服确认。不同套餐的额度规则差异很大,有的是账户总额度共享,有的是每个模型独立计数,有的是按天数重置。只刷社区帖子容易被旧信息误导。
最后给一个典型案例。用 VS Code 扩展那段时间,我经常在面板里看到这条报错:
error from provider (console): opencode's free tier can only be used from within opencode这句话的意思是:当前 provider 用的是 opencode 官方免费额度,而这个额度只能在 opencode 自己的会话里使用,不允许被外部程序(编辑器扩展、自建脚本)当作通用接口调用。排查思路很简单:要么回到 opencode 主会话继续用免费额度,要么换成自己的 API Key,要么换本地模型。这不是故障,是免费额度的使用边界提示。
3. 外壳与界面:从终端 TUI 到 VSCode 协作
3.1 终端原生体验:快捷键、Vim 模式与 Zen 模式
opencode 的外壳,就是你日常操作它的那层界面,这层往往被低估。默认形态是终端 TUI,整个界面像给程序员定制的“半 IDE”:左边文件树或会话列表,中间对话区,下面输入框,支持多行粘贴和斜杠命令补全。
我的高频操作就这几个:/new开新会话、/compact压缩长上下文、Ctrl+K打开模型选择器、Ctrl+M做全屏或分屏切换。如果开了 Vim 模式,输入框里能用 HJKL 移动光标,对 Vim 党很友好。还有一个强烈建议试的——Zen 模式,也就是沉浸模式。它会把边栏、提示全部收起来,只留对话流和输出区,适合长时间专注改代码。壳层没有太多魔法,核心就是把快捷键和会话管理练成肌肉记忆,工作流才顺。
3.2 VSCode 扩展集成:编辑器与 Agent 协同
很多人问“opencode 是不是必须用终端”,答案不是。官方提供了 VS Code 扩展,装好之后可以把 opencode 会话拉进编辑器侧边栏,或直接用扩展唤起 Agent 会话。这样既有编辑器的智能感知(跳转、大纲、调试),又有 opencode 的执行和改动能力。
我的典型用法是:在 VS Code 里打开项目,用扩展新起一个会话定位问题;Agent 改完,我不离开编辑器,直接看 diff、跑测试。这比来回切终端舒服很多,尤其适合代码评审和小重构。有个坑要提醒:扩展的权限配置和终端会话不是共享的。终端里给了大权限,扩展面板里可能还是频繁询问;去扩展自己的配置里把 permission 对齐一遍。反过来也别图省事直接允许所有,扩展面板里的危险命令同样畅通。
3.3 终端之外的“外壳”扩展
工作流再高级一点,就把 opencode 嵌进熟悉的终端生态。比如 shell 别名alias oc="opencode",省得打长命令;再比如配合 tmux:一个 pane 开 opencode,另一个 pane 跑服务端日志,Agent 在左边干活,服务日志在右边滚,相当于给 Agent 配了“监控室”。还有cc-switch这类配置切换工具,可以把不同项目的模型和 API 配置分类管理,切项目时一键切换,不用手动改一堆 json。外壳的本质是“怎么让 Agent 顺手进入你的工作环境”,而不是让你迁就工具。
4. 实战集成:整套可落地的 Agent 工作流
4.1 项目初始化与 AGENTS.md 规范
光有工具和模型,Agent 能不能在真实项目里干好活,还取决于你有没有给它“项目说明书”。opencode 和很多现代 Agent 工具一样,会读取项目根目录的AGENTS.md(部分版本也支持.opencode/AGENTS.md),把它当项目级上下文加载。
AGENTS.md 里我一般放四类内容:技术栈和目录结构、常用命令、编码规范、操作忌讳。举一个真实模板片段:
# AGENTS.md ## 项目概况 这是一个 Go 写的 batch 任务系统,入口在 cmd/worker/main.go,核心逻辑在 internal/processors 下。 ## 常用命令 - 跑单元测试: go test ./internal/... - 跑 lint: make lint - 本地启动 worker: make run ## 规范 - 新增文件必须带单元测试 - 不要修改 vendor/ 和 generated/ 下的文件 - 错误统一用 errors.Errorf,不要裸 fmt.Errorf建议花半小时写一份,哪怕只是基础命令和目录信息,Agent 表现也会上一个台阶——它不用再试探性地到处翻文件了。
4.2 Skill 搭建实例
前面讲过 Skill 的原理,这里完整落一个实际案例。我拿真实项目里的“提交信息生成”技能做示范。
先建目录.opencode/skills/generate-commit/SKILL.md,写清楚触发条件和步骤。然后写代码前跟 Agent 说“用 generate-commit 处理提交”,或者靠它的自动触发机制。更完整的技能还可以把脚本挂进去,比如技能目录里放一个commit_helper.py,解析 git log 的风格模板,SKILL.md 里写“遇到 X 场景,执行 python commit_helper.py 生成信息”。
这里有一条核心经验:Skill 不要做得太泛。一个技能解决一个具体问题,description 写清楚适用和不适用场景,效果远好于一个“万能技能”。边界清晰的技能,Agent 才用得干脆。
4.3 与 Git 及自动化流程集成
最后把整套东西接上 Git 和自动化。日常开发里我是这样用的:主干分支先搭好 AGENTS.md 和基本目录结构,然后让 opencode 开一个独立分支,自动完成小规模功能开发;开发完,我人工 review diff、跑测试、再合并。因为 Agent 只改它自己分支的代码,就算出乱子也不影响主分支,这是我目前试下来最稳妥的落地方式。
自动化场景更直接,比如在 CI 里跑“自动修复 lint 报错”:
opencode run "修复 internal/ 下文件的所有 lint 错误,跑通 make lint,不要改动其他文件"非交互执行时,权限策略必须提前配好,因为没人会对着 CI 弹确认框。我通常会把这类任务限制在一个子目录,并 deny 掉git push、docker这类危险命令,避免 Agent 顺手把东西推到远程。自动化程度越高,护栏越要设计好。放权给 Agent 是为了提效,不是让它替你做决定。
5. 常见问题与排错实录
5.1 高频问题速查表
把群里和我自己踩过的高频问题整理成一张速查表,方便对照排错。
| 问题现象 | 原因 | 解决办法 |
|---|---|---|
| 安装失败或命令 not found | 环境变量或安装方式不匹配 | 看官方 README 安装说明;npm 安装确认包名;Ubuntu 用户先确认 Node 环境 |
| VSCode 扩展连不上 opencode | 扩展没找到本地会话、版本不匹配 | 确认命令行版本与扩展版本一致,重载窗口 |
提示opencode's free tier can only be used from within opencode | 官方免费额度被外部程序调用 | 回到 opencode 内使用,或换自有 API Key / 本地模型 |
| Agent 频繁询问权限 | 权限配置没覆盖当前操作 | 在 permission 里加 allow 或 ask 规则,注意命令模式匹配 |
| 本地模型运行很慢 | 模型规模与任务复杂度不匹配 | 拆小任务,或换更合适的模型 |
| 模型报 404 模型名不存在 | provider 模型名与服务端不一致 | 用服务商提供的模型列表核对名称 |
真遇到奇怪问题,第一件事是开opencode --log-level DEBUG看日志,比反复猜靠谱得多。
5.2 三个我踩过的坑
最后讲三个我实际掉进去、又被同事捞出来的坑,希望你配置时直接绕开。
第一个坑,权限配得太宽松。有次我把 bash 的 allow 配成了"*",Agent 清理临时文件时把另一个目录下未提交的产物删了。从那以后,高危命令默认 deny,偶尔需要就临时放行,绝不给全通配。
第二个坑,在超大项目里开最大上下文硬跑。几十个模块的代码库,Agent 把大量 token 浪费在翻无关文件上。后来我学会先/compact压缩历史,或者开场先用grep明确范围,让 Agent 从“全库搜索”变成“定点突破”。
第三个坑,改了配置不重启。opencode 有相当一部分配置是启动时加载的,改完opencode.json不重启,新配置根本不生效。有次我配了半天 provider,发现跑的还是旧模型,排查了十分钟才反应过来。现在我的习惯是改配置后顺手重开一个 session,或者用 opencode 自己的配置检查命令确认生效,不给自己留这种低级调试时间。
其实用 opencode 用久了,我的体会是:模型的能力大家都差不多,真正拉开差距的从来不是“谁的模型更聪明”,而是你愿不愿意把工具面权限、服务面配置、AGENTS.md 这些底座打磨好。工具定边界,服务面定能力,外壳定体验,三者刚好对上这篇文章的标题。如果你现在刚配好 opencode,我反而建议先别急着堆技能,花一个下午把 AGENTS.md 写清楚、把权限分层定明白,再挑一个高频场景把 Skill 固化下来。这种底子打得越早,后面 Agent 给你省的时间就越多。这是我踩了这么多坑之后最想说的一句话。