Claude Code Router 如何从零创建并安装第一个 Wrapper 插件
【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router
如果你想在 Claude Code Router(下称 CCR)上跑一段自己的代码——比如暴露一个状态接口、启动一个本地后端、或者把代理模式捕获到的某个域名转发到自己的服务——就需要写一个 Wrapper plugin。本文按 CCR 官方文档给出一条完整路径:创建一个最小扩展目录(plugin.json+index.cjs),通过桌面 UI 安装,重启网关后用curl验证路由是否生效。适用于 CCR Desktop(桌面应用),配置通过Extensions页面管理;验证命令依赖本机的 Node 和 curl。
Wrapper plugin 能做什么
CCR 的扩展分两层,多数自定义扩展应从 Wrapper plugin 开始:
| 类型 | 配置位置 | 运行位置 | 适合做什么 |
|---|---|---|---|
| Wrapper plugin | plugins | CCR Desktop 的 Electron wrapper 进程 | 注册本地 HTTP 路由、启动本地后端、拦截代理流量、添加内置浏览器入口、连接供应商账号用量 |
| Core gateway plugin | providerPlugins或plugins[].coreGateway.providerPlugins | core gateway runtime | 扩展上游供应商、认证方式或 core gateway 内部能力 |
Wrapper plugin 的模块通过setup(ctx)拿到ctx,常用能力包括:ctx.pluginId、ctx.pluginConfig(配置里plugins[].config的内容)、ctx.logger(带[plugin:<id>]前缀的日志)、ctx.paths.pluginDataDir(扩展专属数据目录)、ctx.registerGatewayRoute(在 CCR 网关上注册本地 HTTP 路由)、ctx.registerHttpBackend(启动本地 HTTP 后端,返回{ url, host, port })、ctx.registerProxyRoute(把代理模式捕获的 host/path 转发到后端)等,完整字段见 扩展机制文档。
加载上有两条硬约束:
module必须解析到明确的本地 JavaScript 文件路径,可以是绝对路径、~/开头路径,或相对 CCR 配置目录的./...路径;- 任何通过
module加载 JavaScript 的扩展都必须显式声明trusted-code权限。该权限不是操作系统级沙箱,它用于限制 CCR 插件 API 并把“执行本地代码”的信任边界显式化。
创建扩展目录和 plugin.json
创建一个目录,例如~/ccr-extensions/hello-extension,结构如下:
hello-extension/ plugin.json index.cjsplugin.json用于让 CCR 的本地扩展选择器识别扩展 ID、名称和入口文件:
{ "id": "hello-extension", "name": "Hello Extension", "module": "index.cjs", "surfaces": ["apps", "gateway"], "permissions": ["trusted-code", "apps", "gateway-routes", "http-backends", "proxy-routes"], "apps": [ { "id": "hello-status", "name": "Hello Status", "url": "http://127.0.0.1:3456/plugins/hello" } ] }其中apps里的入口会让这个扩展出现在 CCR 内置浏览器应用列表中,url指向上面网关路由的默认地址(CCR 桌面应用网关默认监听http://127.0.0.1:3456)。
编写 index.cjs 模块
下面这个index.cjs注册一个状态路由、一个 echo 后端,以及一个代理转发规则:
"use strict"; module.exports = { async setup(ctx) { ctx.registerGatewayRoute({ auth: "none", id: "hello-status", method: "GET", path: "/plugins/hello", handler(_request, response, helpers) { helpers.sendJson(response, 200, { ok: true, plugin: ctx.pluginId, message: ctx.pluginConfig?.message || "hello from CCR" }); } }); const backend = await ctx.registerHttpBackend({ id: "hello-echo", async handler(request, response, helpers) { const body = request.method === "POST" ? (await helpers.readBody(request)).toString("utf8") : ""; helpers.sendJson(response, 200, { method: request.method, path: request.url, body }); } }); ctx.registerProxyRoute({ host: "api.example.local", id: "hello-example-api", paths: ["/v1"], preserveHost: true, upstream: backend.url }); ctx.logger.info(`hello backend listening at ${backend.url}`); } };这个扩展会暴露三样东西:
GET /plugins/hello:直接挂在 CCR 网关上,用来验证扩展是否加载。示例里显式设了auth: "none",因为它是状态页;如果你自己的路由要留在默认鉴权下,见后文验证部分。- 一个本地 echo 后端:由 CCR 自动分配端口,
backend.url会写进日志。 - 一个代理规则:当代理模式捕获到
api.example.local/v1...时转发到 echo 后端。api.example.local是文档给出的示例域名,真实流量要命中它需要请求方确实访问这个 host;代理规则匹配时host支持精确匹配、.example.com后缀和*.example.com通配,paths为空则匹配该 host 的所有路径,多个路径命中时取最长 path prefix。
模块也可以直接导出函数,或者返回注册对象(支持apps、gatewayRoutes、proxyRoutes、stop、onStop等字段),不必照抄上面的结构。
通过 Extensions 页面安装
CCR 的运行配置存储在 SQLite 中(桌面应用默认位于~/.claude-code-router/config.sqlite,Windows 为%APPDATA%\claude-code-router\config.sqlite),官方推荐通过 UI 添加扩展,旧版 JSON 配置文件仅用于参考。步骤:
- 打开Extensions页面。
- 点击添加扩展,选择本地扩展目录。
- 选择刚创建的
hello-extension目录。 - 保存配置。
- 打开Server页面,重启网关。保存扩展配置后必须重启网关才会生效。
保存后配置数据库中的条目结构大致如下,module是解析后的入口文件路径,config对应代码里的ctx.pluginConfig:
{ "plugins": [ { "id": "hello-extension", "enabled": true, "module": "/Users/you/ccr-extensions/hello-extension/index.cjs", "surfaces": { "apps": true, "gateway": true, "provider": false }, "permissions": ["trusted-code", "apps", "gateway-routes", "http-backends", "proxy-routes"], "config": { "message": "hello from my config" } } ] }上面的 JSON 是文档给出的条目结构示例,其中module的绝对路径要换成你机器上扩展目录的真实路径。
如果选择器没有识别到你的入口文件,本地目录选择器按顺序查找:plugin.json、ccr-plugin.json、.ccr-plugin/plugin.json、.codex-plugin/plugin.json、package.json里的main、ccr.module或ccrPlugin.module;都没有时,依次尝试目录里的index.cjs、index.mjs、index.js、plugin.cjs、plugin.mjs、plugin.js。
验证扩展是否加载
1. 先做语法检查
CommonJS 扩展可以先跑一遍语法检查,避免启动后才发现代码报错:
node --check ~/ccr-extensions/hello-extension/index.cjs如果扩展依赖 npm 包,先在扩展目录安装依赖,并确保入口文件能被 Node 解析。
2. 验证 Gateway route
重启网关后请求状态路由:
curl http://127.0.0.1:3456/plugins/hello按上面示例的 handler,响应是包含ok: true、插件 ID 和message字段的 JSON;配置了"config": { "message": "hello from my config" }时,message返回该值,否则回落到hello from CCR。
如果路由使用默认的auth: "gateway",并且 CCR 配置了 API Key(在API 密钥页面创建的客户端 Key),请求必须带凭据,把<CCR_API_KEY>替换为你的 Key:
curl -H "Authorization: Bearer <CCR_API_KEY>" http://127.0.0.1:3456/plugins/hello或者:
curl -H "x-api-key: <CCR_API_KEY>" http://127.0.0.1:3456/plugins/hello3. 验证 HTTP 后端和代理规则
registerHttpBackend返回的backend.url会写入日志(示例里的ctx.logger.info会打印出来)。先直接请求这个地址,确认后端工作正常;再开启代理模式,验证目标 host/path 是否被registerProxyRoute命中。
如果你是从源码运行 CCR 来调试,可以在 CCR 仓库根目录执行npm install和npm run dev(这会安装依赖并以开发模式启动桌面应用)。扩展里的ctx.logger.info/warn/error会出现在启动 CCR 的终端中,前缀类似[plugin:hello-extension]。
常见问题对照
| 现象 | 排查方向 |
|---|---|
| 扩展没有加载 | 检查plugins[].enabled、plugins[].module路径和终端里的[plugin:<id>]报错 |
GET /plugins/hello返回 404 | 确认网关已重启,路由path或pathPrefix是否以/开头 |
| 返回 401 | 路由默认需要 gateway API Key;调试路由可显式设置auth: "none" |
| 修改代码不生效 | Wrapper plugin 会在网关重启时重新加载;只有进程卡住时才需要重启 CCR |
| 端口被占用 | registerHttpBackend不传port会自动分配端口;固定端口冲突时改回自动分配 |
| 代理规则不命中 | 检查代理模式是否开启、证书是否安装、host 是否匹配真实请求的 hostname |
限制与安全边界
扩展代码运行在 CCR Desktop 的 Electron wrapper 进程里,且trusted-code只是 API 层面的信任声明,写扩展时按文档给出的安全建议约束自己:
- 只有状态页、健康检查或本机调试路由才使用
auth: "none",其余路由保留默认的auth: "gateway"; - 不要在日志里打印 API Key、OAuth token、Cookie 或完整请求头;
- 扩展写入文件时优先使用
ctx.paths.pluginDataDir; - 对
readJson得到的外部输入做类型校验; - 代理转发到外部 upstream 时,明确处理 header 白名单,避免把本地鉴权信息转发到不可信服务。
扩展停止时 CCR 会反向执行stop、onStop钩子,并关闭该扩展注册的 HTTP 后端和 SQLite store,所以长连接等资源可以在stop里释放。配置数据库位置、服务地址与端口的更多细节见 配置数据库位置 和 服务配置;完整的ctx字段、代理规则匹配语义和加载机制说明以 扩展机制 为准。
【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考