
技能库首页:封面/视频预览、来源、安装位置,以及「需要更新 5」和「检查更新」
先说结论
我同时用 Claude Code 和 Codex,也经历过只用其中一个的阶段。两种情况下,真正麻烦的都不是模型能力,而是同一份资产散落在不同目录、格式不同、更新不可见。
同时用两个 Agent 时,一个 MCP server 要在 Claude Code 的 .mcp.json 和 Codex 的 config.toml 里各写一次;一个技能要放进 .claude/skills、.agents/skills 或对应 Agent 的技能目录;一条提示词在 Claude Code 里是 command,在 Codex 里可能是指令文件里的一段。改了一个,忘了另一个,是常态。
只用一种 Agent 时,问题不是同步,而是另外两个:你的技能、提示词、插件散在几个目录里,很多时候你只记得名字,不记得它长什么样、能做什么;上游更新了没有,也没有一个地方能看见。
Context Hub 就是为这两类问题做的:一个本地资产库,能预览截图、视频和 GIF,能按 Agent 投递,也能检查上游更新。插件包和环境变量也在里面,但主线是资产库、预览和更新。
这篇文章不讲功能清单,讲三个问题:
- 跨 Agent 的配置维护为什么没有想象中简单;
- JSONC/TOML 无损编辑、幂等投递、更新追踪怎么做;
- 为什么只用一种 Agent,它也值得用。
一、先看一个具体场景
前段时间我给项目加一个 GitHub MCP server。
以前的操作是:
- 打开 Claude Code 的
.mcp.json,加一段mcpServers.github; - 打开 Codex 的
config.toml,用 TOML 再写一遍同样的命令、参数和环境变量; - 发现
GITHUB_TOKEN的变量名写错了,两边各改一次; - 过两周,其中一个文件被格式化工具重排,注释没了,diff 里全是噪声。
这不是"多写几行"的问题,而是三件事叠在一起:
- 格式不同:一个是 JSONC,一个是 TOML;
- 位置不同:工作区一份、全局一份,作用域不同;
- 语义相同:它们描述的是同一个 MCP server,应该只有一份事实来源。
我试过几种偷懒办法,都不太成立。
软链接。 技能目录可以软链接,但 MCP 配置不行:两个客户端的文件格式不一样,不能共享同一个文件。Windows 上创建软链接还需要开发者模式或管理员权限,团队里没法要求每个人都开。
复制脚本。 写个脚本把一份配置复制到两边,能解决大部分场景。但复制是整文件覆盖,会吃掉对方文件里的注释、键顺序和尾逗号;而且没法判断"这份文件我手改过,要不要覆盖"。
dotfiles 管理器。 适合管理 shell 配置和编辑器配置,但它不理解 Agent 语义:不知道什么叫"这个技能装到工作区还是全局",也不知道"这个 MCP server 在某个客户端被禁用了"。
云同步。 对个人用户来说,没必要把 Agent 配置和 token 放到云端;本地文件本来就应该留在本地。
所以我想要的是一个本地库 + 按 Agent 投递的模型:资产只在库里维护一份,每个 Agent 通过一个适配器声明"我能接收什么、写到哪里、用什么格式"。
二、难点一:不要重新格式化用户的配置
这是整个项目里最容易被低估的部分。
很多工具处理 JSON 的方式是 JSON.parse 再 JSON.stringify。对普通配置没问题,但 Agent 的配置文件里经常有注释:
jsonc
{
// 团队共享的 GitHub MCP
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
}
}
}
一旦 parse + stringify,这行注释就没了,键顺序也可能变,原本手写的紧凑排版会被重排成两空格缩进。用户打开 diff,看到的是整文件重写,而不是"加了一个 server"。
TOML 更麻烦。重新序列化会改写引号风格、丢掉注释、把内联表展开成多行表。
我的做法是不做整体序列化,只改目标节点所在的文本区间:
- 先解析,确认目标节点在语法树里的位置;
- 在原始文本里找到这个节点对应的行区间;
- 只替换或插入这一段;
- 写回之前重新解析一遍,确认"改完的结果"和"我想改的结果"一致;
- 不一致就拒绝写入,而不是写一个半坏的文件。
这套做法不优雅,但它能同时满足"改对"和"不破坏用户文件"。代价是要为 JSONC 和 TOML 各写一套逐节点编辑器,测试里要覆盖注释、尾逗号、内联表、嵌套表这些边界。
三、难点二:投递必须幂等
技能和 MCP 的投递相对简单:一个目录、一段配置,装一次和装两次结果一样。
提示词不一样。它经常要写进一个已经存在 的指令文件,比如 CLAUDE.md 或 AGENTS.md。如果每次安装都追加一段,装三次就会有三段重复内容;如果删除时直接删文件,又会把用户自己写的内容一起删掉。
我的做法是给每一节加一对不会在渲染时显示的注释标记:
md
<!-- context-hub:code-review -->
## Code review
- 先看 diff,再看测试
- 不要只根据文件名猜行为
<!-- /context-hub:code-review -->
规则只有三条:
- 安装时,如果同名标记已经存在,替换这一节,而不是追加;
- 删除时,只删两个标记之间的内容,标记外的字节原样保留;
- 如果删完文件变空,才删文件;否则保留空行和用户的其他内容。
这样同一个提示词装十次也只有一节,卸载时也不会误伤别人的内容。
四、难点三:更新时不要覆盖手改
"从上游更新"是另一个容易想当然的地方。
假设你从某个仓库装了一个技能,过了一周上游更新了。直接覆盖当然简单,但用户可能已经在本地改过这个技能;直接覆盖等于把人的修改扔掉。
所以要区分两个问题:
- 上游是否前进:记录的版本/哈希和上游当前值是否不同;
- 本地是否被改:当前目录的哈希和安装时记录的哈希是否不同。
只有"上游前进了,且本地没改"才自动更新:
ts
const canUpdate = outdated(record, latest) && !modified(record, currentHash);
技能这边,skills CLI 会在安装目录旁写一个 skills-lock.json,里面已经有上游哈希。我复刻了它的目录哈希算法(相对路径 + 字节 + 按路径序喂进一个 SHA-256),只补它答不上的那一问:安装之后文件有没有被改过。插件包同理,用记录的 revision 判断上游,用目录哈希判断本地。
这个策略不追求"永远最新",追求的是不静默覆盖人的修改。手改过的资产会一直显示"有更新",但不会自动动它。
五、难点四:每个 Agent 的差异,不应该写进核心
如果核心代码里写满 if (agent === "claude-code"),每加一个 Agent 就是一次核心改动,测试面会越来越大。
所以我把 Agent 差异收进扩展:
- 一个 Agent 扩展声明自己有哪些位置(工作区/全局)、每种位置能接收什么形式(command、rule、指令文件分节、agent 文件)、每个形式的落点在哪里;
- 页面只画这个位置声明过的形式,核心不认识任何具体 Agent;
- 新增一个 Agent 是加一个扩展,不是改页面代码。
这和"插件市场"是同一套机制:语言包、搜索源、Agent 集成都是扩展。代价是扩展 API 必须稳定,否则每次破坏性变更都会让生态重新来一遍------这也是我现在最谨慎的地方。

六、现在它能做什么
目前官方集成的是 Claude Code 和 Codex,主要资产四类:
| 资产 | 库里存什么 | 能看到什么 | 投递到哪里 |
|---|---|---|---|
| MCP server | 一份声明:命令、参数、环境变量 | 命令、参数、环境变量、运行状态 | Claude Code 的 .mcp.json、Codex 的 config.toml |
| 技能 | 目录 + 元数据 | 封面、截图、GIF、视频、来源、更新时间 | 工作区或全局的技能目录,含共享的 .agents/skills |
| 提示词 | 正文 + 元数据 | 正文、封面/媒体、大小、更新时间 | command、rule、agent 文件,或指令文件里的一节 |
| 插件包 | 包文件 + 来源/版本 | 封面、展示图、文件树、更新状态 | Agent 的插件目录 |

媒体不是附属品。每个技能、提示词、插件都可以带一组资产:截图、GIF、视频。列表卡片直接用第一张资产做封面;详情页是可滑动的画廊;视频只在可见时自动播放,同时最多 6 个预览在解码,打开灯箱时全部暂停。GIF 按图片处理,视频支持 mp4/webm/mov 等。上传可以拖拽、粘贴或选择文件,也可以填远程地址。
技能和插件包会记录来源和版本。检查上游后,列表里会显示是否落后;自动更新只覆盖未手改的资产,手改过的仍显示有更新,但不会自动动它。检查时机可选手动、启动时或每天,自动更新默认关闭。
环境变量更像系统级配置:库只存名字和分组,值写进系统环境。
三种形态共用同一套本地库:Electron 桌面端、独立 CLI、本地网页。资产最终仍然落在 .claude、.codex、.agents 这些 Agent 自己的目录里,没有云端黑盒。项目是 MIT 协议。
七、只用一种 Agent,为什么也值得用
跨 Agent 同步是起点,但不是唯一的价值。只用 Claude Code 或只用 Codex 的人,也会遇到另外两个问题。
第一,你不知道库里有什么。 技能和提示词不只是 Markdown;它们经常带截图、演示视频、GIF。打开 Context Hub 的首页,先看到的不是一串文件名,而是每个资产的封面和预览;点开详情,是完整的画廊,视频在可见时自动播放。你不用打开文件夹一个个读 SKILL.md,先看它长什么样、能做什么。
第二,你不知道上游变了没有。 技能来自不同仓库,插件包也各有来源。库里能看到来源、版本和上次检查时间;检查后发现落后,可以一键更新,并且自动更新只碰没手改过的内容。手改过的资产会保留,不会被静默覆盖。
再加上本地库本身的价值:所有资产在一个地方,按工作区/全局、按 Agent、按类型筛选;要投递时选一个位置,不用记路径。即使只用一个 Agent,这也是一个比文件夹好用的资产管理器。

八、为什么值得做
因为它解决的不是"少点几下鼠标",而是同一份事实只维护一次 ,以及不用来回折腾。
即使只用一个 Agent,预览和更新追踪也足够让它有价值:你不用翻目录猜一个技能是干什么的,也不用隔一段时间手动去上游仓库看有没有更新。
当你有 10 个 MCP server、20 个技能、几十条提示词,并且同时在两个 Agent 里用时,真正消耗时间的不是添加,而是:
- 这个 server 两边参数是不是一致?
- 这个技能上游更新了,我本地改过没有?
- 这条提示词在 Claude Code 里是 command,在 Codex 里到底落在哪?
- 我删掉这一节,会不会把
AGENTS.md里别人的内容一起删了?
这些问题都有确定答案,也应该由工具来回答,而不是靠人记。
项目还在早期,代码在 GitHub:
如果你也在用 Claude Code 或 Codex,我最想知道的是:你现在怎么管理技能、提示词和插件?有没有哪个资产,你根本不知道它更新了? 评论区聊聊,也欢迎直接提 issue。