首页
/ Codex 本地插件更新与重装实战:基于 plugin-creator 的 cachebuster 流程详解

Codex 本地插件更新与重装实战:基于 plugin-creator 的 cachebuster 流程详解

2026-09-06 15:57:18作者:舒璇辛Bertina

本文以仓库中 codex-rs/skills/src/assets/samples/plugin-creator 技能包内的更新参考文档为核心,完整讲解"插件已存在、市场条目已指向源码"这一场景下的本地插件迭代闭环:如何用 update_plugin_cachebuster.py 改写版本后缀、如何用 read_marketplace_name.py 读取市场名、如何执行 codex plugin add 重装并在新线程中验证。读完后,你可以不手改任何市场文件,就让 Codex 在本地开发循环中稳定拾取到插件的最新 skills 和 tools。

适用场景:先确认你在"更新"而非"创建"

更新流程(update loop)有明确的前置条件,只有当以下条件全部成立时才应使用:

  • 插件已在本机存在;
  • 市场(marketplace)条目已经指向你正在编辑的插件源码;
  • 用户希望 Codex 无需手工编辑市场文件就能看到更新后的插件。

如果用户还需要初始插件条目或市场结构,必须先走 scaffold 流程(即技能包 SKILL.md 中描述的 scripts/create_basic_plugin.py 流程),然后再切换到本文的重装流程。这个边界在 SKILL.md 中被反复强调:更新已有本地插件时,"不要手改市场配置或 marketplace.json",而是使用参考文档和脚本。

更新循环(Update Loop)逐步操作

以下所有脚本路径均相对于技能根目录(即包含 SKILL.md 的目录),执行前请按当前工作目录调整路径。

第 1 步:为插件版本写入单一 cachebuster 后缀

python3 scripts/update_plugin_cachebuster.py \
  <plugin-path>

推荐直接使用默认行为:省略 --cachebuster 时,脚本会用"精确到秒的 UTC 时间戳"作为 token,这是日常本地迭代的首选路径。只有当用户明确要求指定 token,或 Codex 之外的工作流依赖某个固定 token 时,才使用手动覆盖:

python3 scripts/update_plugin_cachebuster.py \
  <plugin-path> \
  --cachebuster local-20260519-184516

从源码看,这个脚本的行为与其文档描述完全一致(见 update_plugin_cachebuster.py):

  • 它读取 <plugin-path>/.codex-plugin/plugin.json,要求其中 version 是非空字符串,否则直接报错退出;
  • 默认 token 由 datetime.now(timezone.utc).strftime("%Y%m%d%H%M%S") 生成,即文档所说的"UTC 时间戳到秒";
  • sanitize_cachebuster() 会把 token 小写化,仅保留 a-z0-9-,合并连续连字符并去除首尾连字符,因此手动传入的 token 也会被规范化;
  • 最终版本通过 with_cachebuster() 构造:取 + 之前的部分作为前缀,拼上 +codex.<cachebuster> 后缀(CACHEBUSTER_PREFIX = "codex");
  • 脚本会原地回写 plugin.jsonindent=2 缩进加行尾换行),并打印 Updated plugin version: 旧 -> 新 供你核对。

第 2 步:读取个人市场的名字

默认 scaffold 流程下,市场名来自个人市场文件:

python3 scripts/read_marketplace_name.py

这里"个人市场(personal marketplace)"特指位于 ~/.agents/plugins/marketplace.json 的市场;Windows 上使用用户主目录下的等价路径。脚本借助 Python 的 home 目录解析来定位该文件,并把市场名打印出来,供你构造安装命令。

若要读取其他市场文件的名字,直接传路径:

python3 scripts/read_marketplace_name.py --marketplace-path <path-to-marketplace.json>

对应实现见 read_marketplace_name.py:默认路径为 Path.home() / ".agents" / "plugins" / "marketplace.json";它校验顶层是 JSON 对象且 name 为非空字符串,然后 print(name.strip())——只输出名字本身,方便直接嵌入 shell 命令。

第 3 步:按市场名重装插件

codex plugin add <plugin-name>@<marketplace-name-from-marketplace-json>

一个关键认知:默认个人市场是从 ~/.agents/plugins/marketplace.json 隐式发现的,你不需要为此运行 codex plugin marketplace add;同时 codex plugin marketplace list 也不是判断该默认市场是否存在的手段。

第 4 步:非个人市场时的确认动作

如果插件并不使用个人市场文件,先确认当前是哪个已配置的本地市场在暴露该插件:

codex plugin list
  • 确认哪个市场条目指向你正在编辑的插件源码,并确认该市场仍是本地市场;
  • 若是另一个本地市场,改用那个市场名重装,而不是强行套个人市场流程;
  • 若它不是本地市场,停下来帮用户先解决这个错配,再继续。

第 5 步:替换为已确认的本地市场名

如果插件位于另一个已确认的本地市场,直接替换市场名即可:

codex plugin add <plugin-name>@<local-marketplace>

第 6 步:新线程验证

重装完成后,提示用户在新线程中试用更新后的插件——这是 Codex 拾取新 skills 和 tools 的安全边界(详见文末"After Reinstall")。

Cachebuster 策略:只换后缀,不换版本主体

更新参考文档对版本改写规则给出了严格约定:

  • 保留现有版本前缀,只替换后缀
  • 前缀被定义为 + 之前的所有内容;
  • 统一格式为:
<base-version>+codex.<cachebuster>

参考文档给出的四个示例(原文完整保留):

  • 0.1.00.1.0+codex.local-20260519-184516
  • 0.1.0+codex.old-token0.1.0+codex.local-20260519-184516
  • 1.2.3-beta.1+codex.prev1.2.3-beta.1+codex.local-20260519-184516
  • dev-build+other-tagdev-build+codex.local-20260519-184516

两条红线:

  • 替换已有的 Codex cachebuster,而不是再追加一个新的;
  • 不要靠不停递增数字版本段来触发重装行为。

这与脚本实现一一对应:version.split("+", 1)[0] 恰好取"加号之前的全部前缀",无论旧版本是纯 0.1.0、带旧 token 的 0.1.0+codex.old-token,还是带非 codex 标签的 dev-build+other-tag,改写后都收敛为单一 +codex.<cachebuster> 后缀。

市场操作规则(Marketplace Rules)

更新/重装流程中有一组必须遵守的市场操作纪律:

  • 市场操作应通过命令完成,而不是在本流程中手改 marketplace.jsonconfig.toml
  • 默认 scaffold 流程优先使用个人市场文件;
  • python3 scripts/read_marketplace_name.py 读取个人市场名,并把打印值用于构造 codex plugin add <plugin-name>@<marketplace-name>
  • 非默认市场文件用 --marketplace-path <path-to-marketplace.json> 读取名字后再构造重装命令;
  • 默认个人市场流程中,不要让用户运行 codex plugin marketplace add——该市场由 Codex 隐式发现;
  • 若用户指定了其他市场路径,先确保该市场已安装,再给出安装/重装指令。非默认市场路径不会被隐式发现;
  • 插件位于其他已配置市场时,用 codex plugin list 确认是哪个市场在暴露它;
  • 非默认本地市场尚未配置时,先用 codex plugin marketplace add <path-to-marketplace-root> 安装它,再让用户执行 codex plugin add <plugin-name>@<marketplace-name>
  • 插件不在个人市场文件中时,先确认所选市场是本地市场,再给重装指令;
  • 所选市场不是本地市场时,停下来帮用户解决错配,而不是假装常规本地重装流程适用;
  • 插件源码若不是所选市场条目引用的源码,先停下来修复——更新流程不负责改写市场条目。

从仓库源码结构看,这些规则有对应实现支撑:core-plugins 模块(见 marketplace.rsmanager.rs)中维护了 local_version 字段,取自插件 plugin.jsonversion,并参与"是否需要重新同步/重装"的判定(例如 manager 中的 previous_source.local_version == source.local_version 比较,以及 marketplace_upgradeplugin_install 等 app-server 测试套件)。可以推断:cachebuster 机制正是通过让本地 manifest 的版本号发生变化,使版本比较不再相等,从而触发重装——这也解释了为什么"递增数字版本段"是被禁止的,语义化前缀应保持稳定。

重装之后:用新线程作为验证边界

重装完成后,提示用户开启一个新线程来测试。参考文档将其定义为"拾取更新后的插件及其 MCP 工具的安全边界":旧线程可能仍持有上一版本的 skills 与工具列表,新线程才会以重装后的状态初始化,避免把"插件没生效"误判为"代码有 bug"。

快速核对清单

  1. 插件已存在、市场条目已指向源码、目标是免手改更新 → 使用本流程;
  2. update_plugin_cachebuster.py 默认时间戳即可,特殊 token 才显式传 --cachebuster
  3. read_marketplace_name.py 取市场名,默认读 ~/.agents/plugins/marketplace.json,非默认路径用 --marketplace-path
  4. codex plugin add <plugin-name>@<marketplace-name> 重装;
  5. 非个人市场先 codex plugin list 确认来源市场且其为本地市场;未配置的本地市场先 codex plugin marketplace add
  6. 版本只换 +codex.<cachebuster> 后缀,绝不追加、绝不递增数字版本段;
  7. 新线程中验证 skills 与 tools 已更新。
登录后查看全文
热门项目推荐
相关项目推荐