Codex 本地插件更新与重装实战:基于 plugin-creator 的 cachebuster 流程详解
本文以仓库中 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.json(indent=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.0→0.1.0+codex.local-20260519-1845160.1.0+codex.old-token→0.1.0+codex.local-20260519-1845161.2.3-beta.1+codex.prev→1.2.3-beta.1+codex.local-20260519-184516dev-build+other-tag→dev-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.json或config.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.rs 与 manager.rs)中维护了 local_version 字段,取自插件 plugin.json 的 version,并参与"是否需要重新同步/重装"的判定(例如 manager 中的 previous_source.local_version == source.local_version 比较,以及 marketplace_upgrade、plugin_install 等 app-server 测试套件)。可以推断:cachebuster 机制正是通过让本地 manifest 的版本号发生变化,使版本比较不再相等,从而触发重装——这也解释了为什么"递增数字版本段"是被禁止的,语义化前缀应保持稳定。
重装之后:用新线程作为验证边界
重装完成后,提示用户开启一个新线程来测试。参考文档将其定义为"拾取更新后的插件及其 MCP 工具的安全边界":旧线程可能仍持有上一版本的 skills 与工具列表,新线程才会以重装后的状态初始化,避免把"插件没生效"误判为"代码有 bug"。
快速核对清单
- 插件已存在、市场条目已指向源码、目标是免手改更新 → 使用本流程;
update_plugin_cachebuster.py默认时间戳即可,特殊 token 才显式传--cachebuster;read_marketplace_name.py取市场名,默认读~/.agents/plugins/marketplace.json,非默认路径用--marketplace-path;codex plugin add <plugin-name>@<marketplace-name>重装;- 非个人市场先
codex plugin list确认来源市场且其为本地市场;未配置的本地市场先codex plugin marketplace add; - 版本只换
+codex.<cachebuster>后缀,绝不追加、绝不递增数字版本段; - 新线程中验证 skills 与 tools 已更新。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00