Open Interpreter plugin-creator 技能深度解析:Codex 插件、marketplace 条目与本地迭代流程一站式脚手架
【免费下载链接】openinterpreterA coding agent for open models like Kimi K3 and GLM 5.3项目地址: https://gitcode.com/GitHub_Trending/op/openinterpreter
本文为 Open Interpreter 仓库内置的plugin-creator技能(位于 SKILL.md)配套的技术指南,覆盖插件目录脚手架、.codex-plugin/plugin.json清单契约、个人/仓库级 marketplace 条目生成,以及基于 cachebuster 的本地插件更新流程。读完后,你可以在 Codex 环境中用四个 Python 脚本完成"创建插件 → 写入 marketplace → 校验 → 重装迭代"的完整闭环,并理解每个参数背后的源码级校验规则。
1. 技能定位与目录结构
plugin-creator是随仓库分发的示例技能,位于 codex-rs/skills/src/assets/samples/plugin-creator/。它的 frontmatter 声明了触发条件——当 Codex 需要创建新的个人插件、添加可选的插件结构、为插件排序与可用性元数据生成或更新 marketplace 条目,或在使用 CLI 驱动的 cachebuster 与重装流程更新已有本地插件时,该技能会被调用:
name: plugin-creator description: Create and scaffold plugin directories for Codex with a required `.codex-plugin/plugin.json`, optional plugin folders/files, valid manifest defaults, and personal-marketplace entries by default. ...技能目录的完整布局如下:
plugin-creator/ ├── SKILL.md # 技能说明(本文主体来源) ├── agents/ │ └── openai.yaml # UI 展示元数据(图标、默认提示词) ├── assets/ │ ├── plugin-creator.png # 大图图标 │ └── plugin-creator-small.svg # 小图标 ├── references/ │ ├── plugin-json-spec.md # plugin.json 与 marketplace.json 规范样例 │ └── installing-and-updating.md # 本地插件更新/重装流程 └── scripts/ ├── create_basic_plugin.py # 脚手架主脚本 ├── read_marketplace_name.py # 读取 marketplace 顶层 name ├── update_plugin_cachebuster.py # 重写 version 的 cachebuster 后缀 └── validate_plugin.py # 插件校验器其中 agents/openai.yaml 声明了技能的展示名 "Plugin Creator"、短描述 "Scaffold plugins and marketplace entries" 与默认提示词,并引用 assets 下的两个图标文件——这份 YAML 的字段本身也受插件校验器约束(见第 5 节)。
需要说明的适用前提:本仓库中插件机制仍处于实验阶段,可能默认关闭。按 docs/plugins.md,需要在配置中显式开启:
[features] plugins = true文档同时给出的插件标准形态与本技能生成的结构一致:my-plugin/.codex-plugin/plugin.json为清单,skills/、hooks/、MCP 等组件随插件目录整体分发。插件内可能携带以 hooks、MCP server、skill 脚本形式运行的代码,会经过常规的信任、沙箱与审批控制,启用前应审查插件内容。
2. 快速上手:一条命令生成插件骨架
所有脚本均要求从技能根目录(包含SKILL.md的目录)执行:
# 插件名会被规范化为小写连字符形式,且长度不得超过 64 个字符; # 生成的文件夹名与 plugin.json 中的 name 始终相同。 # 默认创建在 ~/plugins/<plugin-name> 下。 python3 scripts/create_basic_plugin.py <plugin-name>第 2 步是编辑<plugin-path>/.codex-plugin/plugin.json:当用户需求中给出了具体元数据时再修改,脚手架本身已填入合法默认值,不允许残留[TODO: ...]占位符——校验器会把残留的 TODO 标记直接判为失败(见第 5 节)。
从源码看,create_basic_plugin.py 中的名称规范化逻辑为:
def normalize_plugin_name(plugin_name: str) -> str: normalized = plugin_name.strip().lower() normalized = re.sub(r"[^a-z0-9]+", "-", normalized) normalized = normalized.strip("-") normalized = re.sub(r"-{2,}", "-", normalized) return normalized即下划线、空格、标点统一转为-,首尾连字符剥离,连续连字符折叠。文档给出的示例与实现一一对应:My Plugin→my-plugin,My--Plugin→my-plugin。此外还有两条硬约束:规范化后的名称必须至少包含一个字母或数字,长度上限由常量MAX_PLUGIN_NAME_LENGTH = 64强制。
生成的plugin.json由build_plugin_json()构造,默认内容包含:name、version: "0.1.0"、description、author.name: "Local developer"、skills: "./skills/",以及一个interface块(displayName由插件名按连字符分词后逐词首字母大写生成,例如my-plugin→ "My Plugin",同时填充shortDescription、longDescription、developerName、category: "Productivity"、空capabilities数组和defaultPrompt)。注意:只有显式传入--with-mcp/--with-apps时,清单才会写入mcpServers: "./.mcp.json"或apps: "./.app.json"——这与"伴生文件不存在时清单不得声明对应字段"的规则严格一致。
3. 可选组件目录与脚手架完整参数
按需生成伴生目录与占位文件:
python3 scripts/create_basic_plugin.py my-plugin \ --path <parent-plugin-directory> \ --marketplace-path <marketplace-json-path> \ --with-skills --with-hooks --with-scripts --with-assets --with-mcp --with-apps --with-marketplace其中<parent-plugin-directory>是插件文件夹将被创建到的父目录(例如~/plugins)。各选项在源码中的行为是:
| 参数 | 默认值 | 源码行为 |
|---|---|---|
<plugin-name> | 必填 | 规范化后作为目录名与清单name |
--path | ~/plugins | 插件父目录;仅在明确创建 repo/team 插件时传仓库路径 |
--with-skills/--with-hooks/--with-scripts/--with-assets | 关闭 | 分别创建同名空目录(mkdir(parents=True, exist_ok=True)) |
--with-mcp | 关闭 | 创建.mcp.json占位文件,内容为{"mcpServers": {}},并往清单写入mcpServers字段 |
--with-apps | 关闭 | 创建.app.json占位文件,内容为{"apps": {}},并往清单写入apps字段 |
--with-marketplace | 关闭 | 创建或更新 marketplace.json,条目source.path恒为./plugins/<plugin-name> |
--marketplace-path | ~/.agents/plugins/marketplace.json | marketplace 文件路径;仅 repo/team 场景传仓库内路径 |
--marketplace-name | 空 | 只为"新建"marketplace 文件播种顶层name(见下节限制) |
--install-policy | AVAILABLE | 取值仅限NOT_AVAILABLE/AVAILABLE/INSTALLED_BY_DEFAULT |
--auth-policy | ON_INSTALL | 取值仅限ON_INSTALL/ON_USE |
--category | Productivity | marketplace 条目的category |
--force | 关闭 | 允许覆盖已存在的文件/条目 |
占位文件写入使用create_stub_file():目标已存在且未加--force时直接跳过,不会覆盖已有内容;而清单写入使用write_json(),目标已存在且未加--force时抛出FileExistsError提示加--force重试。
4. Marketplace 工作流:个人市场与仓库市场
4.1 位置选择
- 个人 marketplace(默认):
~/.agents/plugins/marketplace.json,插件存放在~/plugins/<plugin-name>/。该文件被 Codex 隐式发现,无需任何注册命令;Windows 上使用用户主目录下的等价路径。 - 仓库/团队 marketplace(显式选择):仅当用户明确要求该目标时,同时传
--path与--marketplace-path:
python3 scripts/create_basic_plugin.py my-plugin \ --path <repo-root>/plugins \ --marketplace-path <repo-root>/.agents/plugins/marketplace.json \ --with-marketplace注意:非默认的 marketplace 路径不会被隐式发现。在告知用户"从它重装"之前,必须先用codex plugin marketplace add <path-to-marketplace-root>确认该市场已安装。
4.2 常规生成与命名
# 个人 marketplace 条目默认写入 ~/.agents/plugins/marketplace.json python3 scripts/create_basic_plugin.py my-plugin --with-marketplace--marketplace-name是例外路径:只有当默认的personal市场名已被占用(或已安装)且需要播种一个不同的新市场文件时才使用:
python3 scripts/create_basic_plugin.py my-plugin \ --with-marketplace \ --marketplace-name team-local禁止用--marketplace-name就地重命名已存在的 marketplace 文件。源码中update_marketplace_json()对这一条有硬校验:当传入--marketplace-name而目标文件已存在时,若其顶层name与新名字不一致,直接抛出错误要求"创建新的 marketplace 文件"。市场名还受validate_marketplace_name()约束:只能包含 ASCII 字母、数字、_和-。
4.3 条目结构、排序与策略值
生成的条目形状固定为:
{ "name": "plugin-name", "source": { "source": "local", "path": "./plugins/plugin-name" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Productivity" }关键规则(SKILL.md "Marketplace workflow" 一节与 references/plugin-json-spec.md 共同确认):
policy.installation允许值:NOT_AVAILABLE、AVAILABLE、INSTALLED_BY_DEFAULT,新条目默认AVAILABLE;policy.authentication允许值:ON_INSTALL、ON_USE,新条目默认ON_INSTALL;- 无论是否取默认值,每个生成的条目都必须显式写出
policy.installation、policy.authentication与category; policy.products属于覆盖项,除非用户明确要求按产品门控,否则一律省略;displayName属于 marketplace 顶层的interface对象,不是单个plugins[]条目的字段;已存在的interface.displayName必须保留;plugins[]数组顺序即 Codex UI 的渲染顺序,默认只追加(append)新条目,除非用户明确要求重排;- 无论个人还是仓库市场,
source.path都保持相对 marketplace 根目录的./plugins/<plugin-name>(例如~/.agents/plugins/marketplace.json下的./plugins/<plugin-name>解析为~/plugins/<plugin-name>); --force仅在"有意识地替换同名插件的既有条目"时使用——源码中同名条目已存在而未加--force会抛FileExistsError,加了则原位替换。
全新 marketplace 文件的根对象应为:
{ "name": "personal", "interface": { "displayName": "Personal" }, "plugins": [ { "name": "plugin-name", "source": { "source": "local", "path": "./plugins/plugin-name" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Productivity" } ] }当目标文件不存在时,build_default_marketplace()会先播种顶层name、含displayName的interface与空plugins数组,再追加首条插件条目;displayName由市场名按连字符分词后逐词首字母大写生成。另有一个配套工具:scripts/read_marketplace_name.py(源码)无参数时读取默认个人市场,传--marketplace-path则读取任意仓库/团队市场,用于构造安装命令时取得顶层name。
最后,若 Codex 需要审批才能写 marketplace 文件,应事先征求审批;如果用户偏好自己执行写入,给出精确的脚手架命令后从校验或后续插件编辑继续,而不是把流程留在模糊状态。
5. 清单规范与校验器:validate_plugin.py 到底查什么
5.1 plugin.json 规范样例
references/plugin-json-spec.md 给出完整规范样例:
{ "name": "plugin-name", "version": "1.2.0", "description": "Brief plugin description", "author": { "name": "Author Name", "email": "author@example.com", "url": "https://github.com/author" }, "homepage": "https://docs.example.com/plugin", "repository": "https://github.com/author/plugin", "license": "MIT", "keywords": ["keyword1", "keyword2"], "skills": "./skills/", "hooks": "./hooks.json", "mcpServers": "./.mcp.json", "apps": "./.app.json", "interface": { "displayName": "Plugin Display Name", "shortDescription": "Short description for subtitle", "longDescription": "Long description for details page", "developerName": "OpenAI", "category": "Productivity", "capabilities": ["Interactive", "Write"], "websiteURL": "https://openai.com/", "privacyPolicyURL": "https://openai.com/policies/row-privacy-policy/", "termsOfServiceURL": "https://openai.com/policies/row-terms-of-use/", "defaultPrompt": [ "Summarize my inbox and draft replies for me.", "Find open bugs and turn them into Linear tickets.", "Review today's meetings and flag scheduling gaps." ], "brandColor": "#3B82F6", "composerIcon": "./assets/icon.png", "logo": "./assets/logo.png", "logoDark": "./assets/logo-dark.png", "screenshots": [ "./assets/screenshot1.png", "./assets/screenshot2.png", "./assets/screenshot3.png" ] } }顶层字段要点:name为 kebab-case 必填项(同时充当组件命名空间);version为语义化版本;author含name/email/url;skills、字符串型mcpServers与hooks路径是在默认组件发现之上的补充,不替代默认发现;路径值应相对且以./开头。mcpServers既可写成伴生文件路径("./.mcp.json"),也可以直接内联对象:
{ "mcpServers": { "counter": { "type": "http", "url": "https://sample.example/counter/mcp" } } }interface字段要点:defaultPrompt最多取前 3 条(第 4 条起被忽略),每条上限 128 字符(超长截断),建议控制在 50 字符左右;screenshots必须为 PNG 且存放在./assets/下、路径相对插件根;brandColor为#RRGGBB色值;logoDark是深色模式下的可选 logo。
5.2 校验器实现细节
交付前运行:
python3 scripts/validate_plugin.py <plugin-path>validate_plugin.py 镜像了工作区插件摄取(ingestion)契约,其检查项比规范文档更严格:
- TODO 占位符拒绝:递归遍历清单所有字符串值,发现
[TODO:前缀即报错(错误信息中带 JSON 路径,如$.interface.longDescription); - 白名单字段:顶层仅接受
id、name、version、description、skills、apps、mcpServers、interface、author、homepage、repository、license、keywords——因此**hooks字段会被拒绝**,脚手架也刻意不生成它(这正是 SKILL.md 中"Omit unsupported plugin manifest fields that validation rejects, includinghooks"的出处);interface内同样只接受 14 个约定字段(displayName、shortDescription、longDescription、developerName、category、capabilities、websiteURL、privacyPolicyURL、termsOfServiceURL、brandColor、composerIcon、logo、logoDark、screenshots、defaultPrompt/default_prompt); - 必填项:
name、version、description、author.name、interface五个必填字符串,interface内displayName/shortDescription/longDescription/developerName/category必填,defaultPrompt与default_prompt至少其一,capabilities必须是非空字符串数组; - 严格 semver:
version须匹配完整语义化版本正则(支持预发布与 build 元数据后缀); - URL 与颜色:
author.url、websiteURL、privacyPolicyURL、termsOfServiceURL必须是绝对https://URL;brandColor与技能 agent 的brand_color必须匹配#RRGGBB; - 伴生文件一致性:
skills必须解析为./skills/,apps必须解析为./.app.json,字符串型mcpServers必须解析为./.mcp.json;声明了apps则.app.json必须存在且apps为对象(每个 app 只允许id、category);声明了.mcp.json则其mcpServers须为对象且每个 server 为对象; - 资源路径安全:
composerIcon/logo/logoDark/screenshots必须是插件目录内真实存在的文件,且路径解析后不得逃逸出插件根(禁止绝对路径、..等); - 技能子清单:若插件含
skills/目录,逐个检查每个技能子目录:必须有SKILL.md且以 YAML frontmatter 开头,frontmatter 的name、description非空,disable-model-invocation不得为 true;若存在agents/openai.yaml,其顶层只允许interface/policy/dependencies,interface内display_name与short_description必填,icon_small/icon_large指向真实文件,policy.allow_implicit_invocation须为布尔值。
另外,编辑SKILL.md之后应运行技能级校验(位于同级示例技能 skill-creator 的脚本中):
python3 ../skill-creator/scripts/quick_validate.py .6. 本地开发迭代:cachebuster 与重装流程
当插件已存在、marketplace 条目已指向正在编辑的源码、且目标是让 Codex 看到更新后的插件时,使用 references/installing-and-updating.md 描述的更新循环,而不是手改 marketplace 文件。适用前提:插件本地已存在、marketplace 条目已指向待编辑的插件源码、用户希望不动 marketplace 文件就刷新插件。
更新循环共四步:
第 1 步:重写版本 cachebuster 后缀
python3 scripts/update_plugin_cachebuster.py <plugin-path>update_plugin_cachebuster.py 的默认行为是把 cachebuster 设为 UTC 精确到秒的时间戳(%Y%m%d%H%M%S),这是例行本地迭代的推荐路径;仅当用户明确要求特定 token(或 Codex 外部流程依赖某个固定值)时才用--cachebuster手动覆盖:
python3 scripts/update_plugin_cachebuster.py \ <plugin-path> \ --cachebuster local-20260519-184516其缓存策略在源码中是:保留+之前的前缀,整体替换为单个+codex.<cachebuster>后缀(token 会先经小写化与[a-z0-9-]清洗):
0.1.0 -> 0.1.0+codex.local-20260519-184516 0.1.0+codex.old-token -> 0.1.0+codex.local-20260519-184516 1.2.3-beta.1+codex.prev -> 1.2.3-beta.1+codex.local-20260519-184516 dev-build+other-tag -> dev-build+codex.local-20260519-184516规则要点:已有 Codex cachebuster 应被替换而非追加;不要靠递增数字版本位来触发重装。
第 2 步:读取 marketplace 名称
python3 scripts/read_marketplace_name.py # 或非默认市场: python3 scripts/read_marketplace_name.py --marketplace-path <path-to-marketplace.json>该脚本通过 Python 的 home 目录解析读取顶层name并打印,用于拼安装命令;若顶层name缺失或非字符串则报错退出。
第 3 步:按市场名重装
codex plugin add <plugin-name>@<marketplace-name-from-marketplace-json>默认个人市场从~/.agents/plugins/marketplace.json隐式发现,不需要codex plugin marketplace add,codex plugin marketplace list也不是检查该默认市场是否存在的正确手段——这两条是 SKILL.md 反复强调的纠偏点。
第 4 步:处理非个人市场的情形
若插件不在个人市场文件中,用codex plugin list确认实际是哪个已配置的本地市场在展示该插件:
codex plugin list确认指向源码的条目后,用该市场名重装(codex plugin add <plugin-name>@<local-marketplace>);若该市场尚未配置,先codex plugin marketplace add <path-to-marketplace-root>;若所选市场根本不是本地的,则停止并先帮用户解决错配——更新流程不会改写 marketplace 条目,若插件源码与所选条目引用的源码不一致,必须先修复。
重装之后:提示用户**开一个新会话(new thread)**再试更新后的插件,这是让 Codex 拾取新 skills 与 MCP 工具的安全边界。
市场操作的总原则:更新/重装流程中一律通过命令操作市场,不要手改marketplace.json或config.toml。
7. 交付前检查单与 Codex 应用深链
7.1 必须保持的行为(Required behavior)
SKILL.md 列出的强制规则,可归纳为交付前的核对清单:
- 外层文件夹名与
plugin.json的name永远是同一个规范化名称;.codex-plugin/plugin.json必须存在,不得删除必需结构; - 清单中不保留
[TODO: ...]占位符; - 除非伴生文件确实已创建,否则
apps与mcpServers不出现在plugin.json; - 校验拒绝的清单字段(如
hooks)一律省略; - 在既有插件路径内建文件时,仅当覆盖是有意行为才用
--force; - 保留既有 marketplace 的
interface.displayName;生成条目时始终写全三个必填字段;policy.products仅在用户明确要求时添加; - 默认个人市场流程不要让用户执行
codex plugin marketplace add——该命令只用于显式的非默认市场配置; - 更新现有本地插件时,不改手编市场文件,统一走 cachebuster + 重装流程;
- 若用户提供了非默认
--marketplace-path,在给出重装指引前先确认该市场已安装。
7.2 Codex 应用交付:View / Share 深链
当本次流程创建或更新了 marketplace 条目时,最终回复应以简短的 Codex 应用交接收尾:写To view this in the Codex app:,并以Markdown 链接(而非裸 URL 或代码片段)形式给出View <规范化插件名>与Share <规范化插件名>:
- View 深链:
codex://plugins/<normalized plugin name>?marketplacePath=<marketplace.json 绝对路径> - Share 深链:同一 URL 追加
&mode=share - 占位符必须替换为真实的规范化插件名与脚手架产出的
marketplace.json绝对路径,必要时对路径段与查询值做 URL 编码; - 不要添加
pluginName或hostId查询参数——Codex 会在用户点击后自行推导; - 若本次没有创建或更新任何 marketplace 条目,则不输出这两个链接。
8. 总结
plugin-creator技能把"手写 JSON 极易出错"的插件创建工作收敛为四个脚本加两条校验命令:create_basic_plugin.py负责目录、清单与 marketplace 条目的一致生成(名称规范化、策略取值、./plugins/<name>相对路径全部内置);validate_plugin.py用摄取契约做交付前门禁(TODO 占位、严格 semver、https URL、资源存在性与路径逃逸、技能子清单);update_plugin_cachebuster.py与read_marketplace_name.py支撑codex plugin add重装循环,最终以新会话作为更新生效的边界。所有约定——个人市场默认位置、条目必填策略字段、深链格式——都可在这份技能目录的脚本与 references 文档中逐条对照源码验证,适合作为在本仓库基础上开发或分发插件时的权威参照。
【免费下载链接】openinterpreterA coding agent for open models like Kimi K3 and GLM 5.3项目地址: https://gitcode.com/GitHub_Trending/op/openinterpreter
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考