1. 为什么你的 opencode Skills 换个项目就“失灵”
很多人第一次接触 opencode 的 Agent Skills,都会经历一个很爽的阶段:在 A 项目里写了一个SKILL.md,Agent 生成代码时自动遵守命名规范、自动带上类型注解、自动按三层结构建目录,感觉像给 AI 装了个“团队规范插件”。然后你换到 B 项目,把.opencode/skills/整个目录复制过去,结果 Agent 要么完全不加载,要么加载了却按另一套模型端点去请求,生成质量忽高忽低。
问题通常不在 Skill 本身,而在两个地方:一是 Skill 的发现路径和命名规则没对齐,二是 Skill 里隐含调用的模型通道没有统一。opencode 的 Skills 机制本质是「SKILL.md定义文件 +skill工具按需加载」,Agent 先看到一份可用 Skills 清单,需要时才把完整内容读进上下文。这意味着 Skill 是跨项目复用的天然载体,但前提是它调用的模型端点得是一个稳定、统一、可迁移的通道。
这篇就聚焦一件事:把SKILL.md里涉及的模型调用统一改到 TaoToken 通道,让同一份 Skill 在任意项目里复用都走同一个 Key 和 Base URL。TaoToken 是一个面向开发者的模型 API 聚合通道,官网在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,它提供统一的 API 入口,你只需要维护一套 Key,就能在 opencode、Cline、Claude Code 这类工具里复用同一套模型配置。适合谁?适合已经在用 opencode 写代码、手里攒了好几个 Skill、又不想每个项目重新配一遍模型通道的人。
我试过把团队里 6 个 Skill 从“每个项目各自配端点”改成“统一走 TaoToken”,最大的感受是排障成本骤降——以前报 401 要翻三个项目的配置文件,现在只看一个 Base URL 和一把 Key。下面从SKILL.md结构讲起,一步步改到统一通道,最后给你一个可复制的验证动作。
2. opencode Skills 复用机制与 SKILL.md 结构拆解
先把复用机制讲透,不然后面改配置容易改错地方。opencode 加载 Skills 的搜索路径有好几层,项目级和全局级并存:
| 路径 | 说明 |
|---|---|
.opencode/skills/<name>/SKILL.md | 项目级配置 |
~/.config/opencode/skills/<name>/SKILL.md | 全局配置 |
.claude/skills/<name>/SKILL.md | Claude 兼容路径(项目级) |
~/.claude/skills/<name>/SKILL.md | Claude 兼容路径(全局) |
.agents/skills/<name>/SKILL.md | Agent 兼容路径(项目级) |
~/.agents/skills/<name>/SKILL.md | Agent 兼容路径(全局) |
项目级路径有个细节:opencode 会从当前工作目录向上遍历直到 git worktree 根目录,沿途所有匹配的 Skills 都会被加载。这就是为什么你把 Skill 放在仓库根目录的.opencode/skills/下,在子目录里跑 opencode 也能发现它。跨项目复用的关键就在这——把通用 Skill 放到全局路径~/.config/opencode/skills/,所有项目共享;把项目专属 Skill 放项目级路径,跟着 Git 走。
SKILL.md的结构分两块:YAML frontmatter 和 Markdown 指令正文。frontmatter 里name和description是必填,name必须满足^[a-z0-9]+(-[a-z0-9]+)*$,也就是小写字母数字加单个连字符,不能以连字符开头结尾,不能有连续--,而且必须和包含SKILL.md的目录名一致。description长度 1 到 1024 字符,写得越具体,Agent 越容易在正确场景选中它。
一个典型的 Skill 目录长这样:
.opencode/skills/ ├── git-release/ │ └── SKILL.md ├── python-class/ │ └── SKILL.md ├── pytest-suite/ │ └── SKILL.md └── fastapi-crud/ └── SKILL.mdAgent 在skill工具描述里看到的是一份清单,类似:
<available_skills> <skill> <name>git-release</name> <description>Create consistent releases and changelogs</description> </skill> <skill> <name>python-class</name> <description>Generate Python classes following PEP8 and modern standards</description> </skill> </available_skills>需要时 Agent 调用skill({ name: "git-release" })把完整内容加载进上下文。这里要划重点:Skill 本身不直接发模型请求,它是一段被注入上下文的指令。真正发请求的是 opencode 背后的模型通道。所以“把 Skill 改到 TaoToken 统一通道”,改的不是SKILL.md里的某行 URL,而是让 opencode 这个运行环境统一走 TaoToken 的 Base URL 和 Key,这样所有 Skill 在任意项目里加载后,背后的模型请求都落到同一个通道。
理解这一层,你就明白为什么单纯复制SKILL.md不够——Skill 是“规范”,通道是“水管”,规范可以复制,水管得统一接。下面进入配置环节。
3. 把 opencode 模型通道统一改到 TaoToken 的可复制配置
opencode 的模型配置走opencode.json,通常放在项目根目录或全局配置目录。我们要做的是把 provider 的 Base URL 指向 TaoToken 的 API 入口,Key 用 TaoToken 的 Key,Model ID 填你要用的模型。TaoToken 的 API 地址是 https://taotoken.net/api ,注意这个地址不带 UTM 参数,配置里就用它。
先看一份可复制的opencode.json片段,把 provider 配成 OpenAI 兼容格式:
{ "$schema": "https://opencode.ai/config.json", "provider": { "taotoken": { "npm": "@ai-sdk/openai-compatible", "name": "TaoToken", "options": { "baseURL": "https://taotoken.net/api", "apiKey": "{env:TAOTOKEN_API_KEY}" }, "models": { "claude-sonnet-4-5": { "name": "Claude Sonnet 4.5" }, "gpt-4.1": { "name": "GPT-4.1" } } } }, "model": "taotoken/claude-sonnet-4-5" }这里三件套要写全:Base URL 是https://taotoken.net/api,Key 通过环境变量TAOTOKEN_API_KEY注入,Model ID 是taotoken/claude-sonnet-4-5这种provider/model格式。为什么用环境变量而不是把 Key 写死在 JSON 里?因为opencode.json通常要提交到 Git 做团队共享,Key 写死会泄露。环境变量在本地和 CI 里各自设置,配置文件保持干净。
设置环境变量的方式,Linux/macOS:
export TAOTOKEN_API_KEY="你的TaoToken Key"Windows PowerShell:
$env:TAOTOKEN_API_KEY="你的TaoToken Key"想持久化就写进~/.zshrc或~/.bashrc。Key 在 TaoToken 控制台的 API Keys 页面创建,地址是 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,创建后复制一次,之后不再显示,记得存好。
如果你想让全局所有项目都用这套通道,把opencode.json放到全局配置目录,而不是每个项目一份。opencode 的全局配置路径通常在~/.config/opencode/opencode.json。项目级配置会覆盖全局,所以项目里想用别的模型时,只在项目级opencode.json里覆盖model字段即可,provider 定义可以继承全局。
接下来是 Skill 侧。SKILL.md本身不需要写 URL,但为了让 Skill 在描述里明确“我走的是统一通道”,可以在 frontmatter 的metadata里加一条标记,方便团队识别:
--- name: fastapi-crud description: Generate FastAPI CRUD endpoints with SQLAlchemy models and Pydantic schemas license: MIT compatibility: opencode metadata: channel: taotoken audience: backend workflow: api --- ## What I do - Create SQLAlchemy models with common fields (id, created_at, updated_at) - Generate Pydantic Create/Response schemas - Implement 5 standard endpoints (list, get, create, update, delete) - Use async/await throughout - Add proper error handling and HTTP status codes ## When to use me Use this when creating new CRUD endpoints for a FastAPI application. ## Code structure app/ ├── models/{model}.py ├── schemas/{model}.py └── routers/{model}.pymetadata是字符串到字符串的映射,未知字段会被忽略,所以加channel: taotoken不会影响加载,但能让团队一眼看出这个 Skill 走的是统一通道。这一步不是必须,但对跨项目复用很有帮助——当你有几十个 Skill 时,靠 metadata 就能筛出哪些还没迁移。
权限配置也顺手统一一下。在opencode.json里控制哪些 Skill 可用:
{ "permission": { "skill": { "*": "allow", "internal-*": "deny", "experimental-*": "ask" } } }allow立即加载,deny对 Agent 隐藏,ask加载前提示批准。通配符internal-*能匹配internal-docs、internal-tools。跨项目复用时,把团队通用 Skill 设为allow,把实验性的设为ask,避免 Agent 在正式项目里误用未验证的 Skill。
配置改完,通道就统一了。下面验证一次。
4. 验证请求:一次 Skill 复用与成功结果确认
配置对不对,跑一次就知道。验证分两步:先确认 opencode 能连上 TaoToken 通道,再确认 Skill 能被正确加载并复用。
第一步,在项目根目录启动 opencode,发一个最小请求,看模型是否响应。你可以直接问一句:
用一句话说明当前使用的模型通道。如果配置正确,Agent 会正常回复,不会报 401 或连接错误。这一步验证的是通道连通性。
第二步,验证 Skill 复用。在项目里放一个python-classSkill,目录结构:
.opencode/skills/python-class/SKILL.md内容:
--- name: python-class description: Generate Python classes following PEP8 and modern standards metadata: channel: taotoken --- ## What I do - Generate Python classes with type annotations (PEP 484) - Include Google-style docstrings - Use `@dataclass` when appropriate - Implement `__repr__` methods - Follow PEP 8 naming conventions ## When to use me Use this when creating new Python classes or refactoring existing ones. ## Code structure - Class names: PascalCase - Methods/variables: snake_case - Constants: UPPER_SNAKE_CASE - Private methods: leading underscore `_method`然后在 opencode 会话里明确引用这个 Skill:
使用 python-class skill 创建一个 DataProcessor 类,负责读取 CSV 并做字段清洗。预期结果是 Agent 生成的类带类型注解、有 Google 风格 docstring、命名符合 PEP 8、私有方法带下划线。如果生成结果符合这些规范,说明 Skill 被正确加载,且背后的模型请求走的是 TaoToken 通道。
再验证一次跨项目复用:把.opencode/skills/python-class/整个目录复制到另一个项目,或者把它放到全局路径~/.config/opencode/skills/python-class/,在新项目里重复上面的请求。如果结果一致,说明 Skill 复用成功,通道也统一了。
成功结果的判断标准有三条:一是 Agent 在<available_skills>清单里能看到python-class;二是生成代码符合 Skill 里定义的规范;三是没有出现 401、连接超时、模型不存在这类错误。三条都满足,这次迁移就算完成。
如果你用的是 Claude Code 或 Cline 这类工具,验证逻辑类似,只是配置文件位置不同。Claude Code 的配置在~/.claude/settings.json或项目级.claude/settings.json,Cline 在 VS Code 设置里。核心三件套不变:Base URL 填https://taotoken.net/api,Key 填 TaoToken Key,Model ID 填对应模型。想快速试模型效果,也可以直接用模型对话页面 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 发一条消息,确认 Key 和模型都可用,再回到 opencode 里配。
5. 本篇常见错排查:401、local proxy failed 与 Skill 不加载
配置过程中最容易撞上的几类报错,逐个拆。
401 Unauthorized。这是 Key 没生效。先确认环境变量真的被读到了,在终端里echo $TAOTOKEN_API_KEY(Windows 用echo $env:TAOTOKEN_API_KEY),如果为空,说明 export 没生效或写错了 shell 配置文件。再确认opencode.json里写的是{env:TAOTOKEN_API_KEY}而不是别的变量名。还有一种情况是 Key 复制时带了空格或换行,重新从控制台复制一次。Key 在 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 创建。
local proxy failed / connection refused。这类报错通常是 Base URL 写错或网络层拦截。确认baseURL是https://taotoken.net/api,不要多加/v1或漏掉/api。有些 OpenAI 兼容客户端会自动拼/v1/chat/completions,如果你的客户端这么干,Base URL 可能只需要到域名层,具体以接入文档为准,文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。另外检查本地是否有其他进程占用端口,或者公司网络策略拦截了外部 API 请求。
reading choices 报错 / 返回结构解析失败。这通常是模型返回格式和客户端预期不一致。opencode 用@ai-sdk/openai-compatible时,要确保 provider 的npm字段写对,模型 ID 用provider/model格式。如果返回体里没有choices字段,说明请求可能打到了非兼容端点,检查 Base URL 是否指向了正确的 API 路径。
OAuth 相关报错。如果你之前用 OAuth 方式登录过某个 provider,opencode 可能还在用旧的认证方式。检查opencode.json里有没有残留的 OAuth 配置,清掉后改用 API Key 方式。Claude Code 用户如果遇到 OAuth 报错,检查~/.claude/settings.json里的认证字段,确保走的是 API Key 而不是订阅登录。
Skill 不加载 / 不在 available_skills 清单里。按顺序排查:文件名必须是全大写SKILL.md;frontmatter 必须含name和description;name必须和目录名一致且符合^[a-z0-9]+(-[a-z0-9]+)*$;检查权限配置里有没有被deny;确认文件在正确的搜索路径下。项目级路径会从当前目录向上遍历到 git worktree 根目录,如果你在子目录里跑 opencode,Skill 放在仓库根目录也能被发现,但放在仓库外就不行。
Agent 没遵循 Skill 规范。这不是报错,但很常见。原因通常是description写得太泛,Agent 没选中这个 Skill;或者 Skill 内容太抽象,没有具体规范。解决办法是把description写具体,在正文里给出代码结构和命名约定,必要时在对话里明确说“使用 xxx skill”。
排障时有个通用技巧:先用最简单的请求测试通道连通性,再逐步加 Skill、加复杂度。这样能快速定位是通道问题还是 Skill 问题。如果通道本身不通,先解决 401 和连接问题;通道通了但 Skill 不生效,再查 Skill 加载。
6. 长期复用:把 Skills 和统一通道沉淀成团队资产
单次迁移做完,接下来要考虑的是怎么让这套东西长期可维护。跨项目复用 Skills 的落地方法,核心是三层结构:全局 Skill 放通用规范,项目 Skill 放业务专属,统一通道放模型配置。
全局 Skill 放~/.config/opencode/skills/,比如python-class、pytest-suite、naming-convention这类跟具体业务无关的规范。项目 Skill 放项目根目录.opencode/skills/,比如company-auth、company-fastapi-crud这类带公司业务逻辑的。统一通道配置放全局opencode.json,项目级只覆盖model字段。这样新项目初始化时,只需要克隆项目、设置一次环境变量,所有通用 Skill 和通道配置自动生效。
团队共享靠 Git。建一个team-opencode-config仓库,结构:
team-opencode-config/ ├── README.md ├── opencode.json └── skills/ ├── company-fastapi-crud/ │ └── SKILL.md ├── company-auth/ │ └── SKILL.md └── company-naming-convention/ └── SKILL.md新成员克隆后,把skills/复制或软链到全局路径,把opencode.json合并到全局配置,设置TAOTOKEN_API_KEY环境变量,就能在所有项目里复用同一套 Skill 和通道。软链方式:
ln -s /path/to/team-opencode-config/skills/* ~/.config/opencode/skills/Skill 的版本管理走 Git,每次更新提交一次,git log -- .opencode/skills/fastapi-crud/能看变更历史,需要回退就git checkout <commit> -- .opencode/skills/fastapi-crud/。这样 Skill 的演进有迹可循,团队里谁改了什么一目了然。
如果你还在用 Claude Code 做编码,TaoToken 也支持 Claude Code 接入,配置方式类似,Base URL 和 Key 一致,具体可以参考接入文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。长期跑编码任务或 Agent 工作流的话,Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 有更细的说明,适合需要稳定通道和额度管理的场景。
最后给一个实用技巧:给每个 Skill 的metadata加channel: taotoken和version字段,迁移进度和版本一眼可见。定期检查 Skill 内容是否还适用当前技术栈,示例代码有没有过时,团队反馈有没有需要补充的。Skill 不是写完就完事,它跟代码一样需要维护。把通道统一到 TaoToken 之后,你至少不用再为每个项目的模型端点操心,剩下的精力可以全放在 Skill 内容本身的打磨上。