宿主安装
build 输出的组合插件根目录包含一份生成的 INSTALL.md,每个所选宿主一节,其中的命令使用捆绑包真实
的插件名与市场名。其中每条命令都是宿主命令(claude plugin …、codex plugin …)或随行的 install.mjs,
因此无论从 npm、市场检出还是 zip 拿到已构建根目录的消费者,安装、重装或卸载它都不需要 agent-bundle CLI;
INSTALL.md 明言这一点,并在每处提及该 CLI 时标注其为可选。框架 CLI 为拥有它的开发者执行同样的操作,而且
所有宿主都从同一个目录安装:
--from 指定的是组合根目录:存放 agent-bundle.manifest.json 的那个目录。安装器只读这一个文件来了解
自己在安装什么,插件名与版本来自 application,市场名来自 projections[host].marketplace,宿主被指向的
文件来自 projections[host].documents.plugin(Amp 使用 documents.entry;见产物清单)。它不需要
项目源码,也不存在 <from>/<host> 查找:构建不会写出 artifact/<host> 子目录,根目录本身就是捆绑包。
以下情形会以 AB7001 拒绝:清单缺失或不是规范字节;没有该宿主的投影;投影没有宿主插件清单(或所指文件
不存在);claude 或 codex 没有声明市场身份;或 cursor 的插件名不是安全的本地插件名。
各宿主接受什么
由于 Claude 与 Codex 投影始终随行本地市场清单,它们的公开 CLI 可以直接安装该根目录。当所选宿主
二进制文件不可用时,安装器会以一条带类型的诊断失败,而不是报告一次它并未完成的成功。宿主安装诊断属于
AB700x 家族:捆绑包标识、宿主可用性、作用域、命令失败与冲突检查。
Amp 是实验性目标:已核对契约,运行时未验证。它没有非交互式 reload 或独立校验器。安装结果只记录交互式
reload 步骤,绝不自动执行。本环境没有 Amp 账号,因此 amp plugins list 与 amp skills list --json
会要求登录;实时注册、启用状态与工具执行记为 未验证,而不是不支持。
独立安装器
targets 中包含 cursor 或 portable 的根目录带有一个 install.mjs,它把根目录复制到
~/.cursor/plugins/local/<name>,且不会覆盖冲突内容:
它的分阶段复制对内容相同的情况是幂等的,并会拒绝版本或内容冲突。它绝不调用 sudo,也绝不修改 PATH。
存在 agent-bundle.manifest.json 时,安装器从所选投影读取插件与 MCP 指针;只有无清单的包才回退探测
.cursor-plugin/* 或根目录 Agent Plugins 路径。
对于 Cursor 会按 Agent Plugins 1.0.0 包加载的根目录,选中了 portable 而未选 cursor,因此根目录的
plugin.json 是 Cursor 能找到的唯一清单,安装器还会在 mcp.json 的 Cursor 副本中展开该标准的占位符,
因为 Cursor 3.18.25 自己不会展开:它把 args、env 值和 cwd 中的 ${PLUGIN_ROOT} / ${PLUGIN_DATA}
原样留下,不提供 PLUGIN_ROOT / PLUGIN_DATA 变量(规范 §9.1),把省略的 cwd 默认为主目录,并把相对插件的
./ 命令解析到工作区文件夹(规范 §7.2.1),因此每个符合规范的 stdio 服务器都无法启动。Cursor 副本会得到绝对的
插件根、作为数据目录的 ~/.cursor/agent-bundle/plugin-data/<name>(由安装器创建)、指向插件根的 cwd、已解析的
./ 命令,以及每个 stdio 服务器环境中的 PLUGIN_ROOT / PLUGIN_DATA。捆绑包本身不被改动,对其他 Agent Plugins
客户端仍然符合规范;展开前的文档保存在安装回执中(cursorExpansion),agent-bundle doctor --host cursor 以
AB7326 证明这次展开。这里没有任何内容是 Cursor 的行为:来源为 derived,而带有
.cursor-plugin/plugin.json 的根目录,选中了 cursor,会被原样复制,因为 Cursor 转而加载那份清单。
产物校验会拒绝缺少必需安装表面的根目录,因此捆绑包不可能在缺少它所承诺的安装器的情况下发布。
npm 安装的 CLI
npm 包根目录包含组合插件清单拥有的全部字节,并额外带有 npm 专属元数据与手写包入口。
validate --artifact 等命令仍接收纯组合产物;清单感知的 install --from 接受任一根目录。
对于生成的路由式 CLI,package.json 的 bin 指向产物公开的同一个
bin/<name>.mjs 可执行文件,不会再次编译,也没有包装器。因此它的完整命令面(包括 web)从
node_modules 运行时与从复制的产物运行完全一致。任何 npm 生命周期都不会执行宿主安装,安装一个包
绝不会改动宿主的插件状态。
仓库中的 AGENTS.md 作为作者编写的包元数据原样复制。生成的投影说明绝不会覆盖它;路径冲突会让包构建失败。
请用 npx agent-bundle install <host> --from node_modules/<package> 从该根目录显式安装任一受支持宿主。
这条清单感知路径会把 npm 专属元数据与手写包入口排除在宿主归属比较之外。
打包宿主证明会从已安装包重建清单拥有的产物,并在删除源 checkout 后执行
agent-bundle install --from。
与包绑定的安装器 bin
已发布的插件若希望提供 <name> install <host>,又不想要求用户安装 agent-bundle CLI,只需声明一个
bin 入口并委托给 agent-bundle/install:
runInstallCli 就是 agent-bundle CLI 自己的 install <host>、uninstall <host> 与 doctor
命令,同样的标志、回执、替换规则、--plan、数据策略、--json 输出与退出码,只是把 bundle 根目录固定为 from,因此该 bin 不暴露 --from,也绝不会去寻找别的产物根目录。
包构建会把生命周期实现内联进可执行文件;已安装的包在运行时不需要 agent-bundle。
该入口还导出 installBundle、uninstallBundle、runDoctor 与 format* 助手,供自行组合命令面的 bin 使用。
只读的状态检查是 doctor --host <host>:它报告已安装副本是最新、过期、版本不匹配、外来还是缺失。
退出码与 agent-bundle CLI 一致。0 表示成功。doctor 总是把报告(人类可读或 --json)写到 stdout,
当报告含有错误诊断时以 1 退出,请读取报告,而不是 stderr。失败的 install 或 uninstall,以及任何抛出异常的命令,
会把诊断作为一行 JSON 写到 stderr 并以 1 退出。用法错误以 2 退出。
开发期安装是另一回事
agent-bundle dev --install-host <host> 维护的是一个标记为开发用的安装,它跟随成功的重建 epoch,
带有原子的世代切换与一条稳定的 proxy 命令。这部分内容在
开发者 Workbench中,与 agent-bundle install 不是同一个操作。
Amp 不属于开发期安装宿主;请使用其有归属回执的 agent-bundle install amp 副本与交互式 reload。
重建后重新安装
每个输出的安装器,agent-bundle install <host> 与独立的 install.mjs,共用同一套替换策略。
内容完全相同的副本是 already-installed 空操作。版本相同但内容哈希不同的副本会被自动替换,因此不升版本
地重建不再需要卸载加 rm -rf。版本不同则以 AB7005 拒绝,除非传入 --replace;外来目录
(不是本插件安装器放置的)无论如何都会被拒绝。安装回执出现之前放置的副本没有回执,因此同样是外来目录,
无论字节是否一致:手动删除后重新安装。独立的 install.mjs 对没有回执的目标目录按其中实际存在的文件计算哈希,
以便拒绝信息能给出内容比对。存在 agent-bundle.manifest.json 时,产物哈希使用该清单的 files[],
清单列出而产物缺失的路径会使安装失败。外来或已暂存的目标目录中缺少的清单路径不进入目标哈希,因此两边哈希不同,安装拒绝该副本,而不是抛出 ENOENT。属于本安装器的同版本副本可以修复。Cursor 与 Amp 副本携带安装回执(.agent-bundle-install.json:
插件、版本、宿主、内容哈希、归属文件);替换就地进行,只触碰归属文件,绝不动插件旁的 state/ 目录之类的非归属条目。
产物构建把框架状态放在
~/.agent-bundle/state/<plugin>-<digest>(AGENT_BUNDLE_STATE_ROOT 覆盖该位置)。uninstall
配合 --purge-data --confirm-purge 只会删除回执证明归该安装独占的根;预先存在、共享、无标记或其他
无法证明归属的覆盖根都会保留。Claude 的替换先运行 claude plugin uninstall --keep-data 再重新安装,
因为 plugin update 受版本门控;Codex 的替换只执行 codex plugin add,以便保留 config.toml 中的插件设置与嵌套
MCP 覆盖。原生 add 会把插件级 enabled = false 重置为 true;原生 plugin CLI 没有可保留设置的合格更新 API,因此安装器会拒绝
已禁用或启用状态未知的替换(AB7004),并保持该安装不变。输出的
INSTALL.md 按宿主记录了同样的步骤。
框架 CLI 从 agent-bundle.manifest.json 的 files[] 派生产物侧哈希与复制集合,校验每个列出的摘要,
而不遍历产物目录。清单自身与约定的操作员 .env / .env.local 覆盖层也会被复制并哈希;未列出的
多余文件会被忽略。某个列出的文件缺失或已改变时以 AB7001 失败。
操作者配置:已安装包的 .env
通过环境变量配置的插件,会话 cookie、API 令牌、主机名,应在安装处配置,而不是在产物里:清单 env 是编译
产物,按内容寻址且每次构建都会重新输出,不是放置密钥的地方。取而代之,在已安装副本的插件根目录(存放
.claude-plugin/、.codex-plugin/ 或 .cursor-plugin/、与 mcp/、hooks/、bin/ 同级的目录)放一个
.env 文件,可选地再放一个 .env.local:
包输出的每个外壳,stdio MCP 服务器入口、运行插件代码的
hook 包装器、产物 CLI bin/<name>.mjs,在启动时按同一条规则读取该文件:
这与 agent-bundle mcp run 合成的顺序相同,清单 env 在文件之下,文件在操作者导出的变量之下。宿主把
清单 env 和自己导出的变量作为同一份环境交给 stdio 服务器,因此生成入口会把该服务器声明的 env 块作为
构建时字面量随行携带,并把仍持有清单默认值的变量视为未设置:文件可以覆盖它。取值与默认值不同的变量是
宿主或操作者导出的,予以保留。由此有两个推论。操作者恰好导出了与清单默认值相同的值时,无法与透传区分,
同样让位于文件。带有路径 token 的清单值(AGENT_BUNDLE_PLUGIN_ROOT,或使用了 token 的声明 env 值)
会在启动前被宿主展开,因此永远不等于其字面默认值,总是被保留。hook 包装器与产物 CLI 没有清单 env,
对它们而言宿主环境就是宿主导出的变量。
位置是包解析出的插件根目录,宿主设置了 AGENT_BUNDLE_PLUGIN_ROOT 时取它,否则取外壳自身所在目录
(mcp/、hooks/、bin/)的上一级。AGENT_BUNDLE_ENV_FILE 可指定改为读取的一个或多个文件(以平台路径
分隔符分隔),AGENT_BUNDLE_ENV_FILE=none 则关闭这一层。语法即 dotenv:KEY=value、export KEY=value、
# 注释、单引号、双引号或反引号包裹的值(双引号内展开 \n)、跨行的引号值,且不做 ${VAR} 插值。
文件缺失是常态且没有开销;无法读取的文件会被跳过,包照常启动。取值永远不会被记录。该文件不归安装回执
所有,因此 install --replace 与同版本重建都会保留它,而 uninstall 绝不移除非归属条目:卸载后该文件仍会
留下(Doctor 随后以 AB7307 把该目录报告为残留),凭据应当消失时请手动删除。这一层是每个应用它的
外壳的第一个导入,先于服务器模块、hook 处理器以及 CLI 的路由、provider 与 state 模块,因此插件代码即使
在模块顶层读取 process.env 看到的也是合成后的环境,而不只是在运行时。agent-bundle mcp run 自己也
合成同样的几层,并把 --env-file / --no-env 以 AGENT_BUNDLE_ENV_FILE 传给子进程,因此演练与已安装包
读取的是同一组文件。
agent-bundle doctor 会报告已安装副本是否带有 .env 或 .env.local 以及各自声明了多少个变量
(AB7331,信息级),绝不报告名字或取值。
按回执卸载
每次安装都会写入生命周期回执(agent-bundle-install-receipt/2):版本、内容哈希、投递模式、作用域、归属的文件与
目录、安装器创建的宿主目录、执行过的宿主注册,以及时间戳。Cursor 本地副本与 Amp 项目/系统副本以
.agent-bundle-install.json 携带它;Claude、Codex 与 Cursor 市场模式的安装把回执放在
<宿主根目录>/agent-bundle/receipts/ 下。uninstall 只删除回执
归属的内容,只撤销它记录的注册,绝不多删;非归属条目会被列为保留,插件旁的 state/ 目录也在其中。回执带归属证据记录的框架状态根、推导出的 web-data,以及 Agent Plugins
包的 Cursor 副本在回执中记录的 PLUGIN_DATA 目录,除非传入 --purge-data --confirm-purge 否则保留,且结果如实说明宿主自行决定而 Agent Bundle 无法左右的部分(Claude 把缓存
副本标为 orphaned 并保留约 14 天;Codex 删除缓存树且没有 keep-data 选项)。宿主已注册的安装缺少仓库回执(AB7009)或内容不匹配
(AB7007)会被拒绝,除非 --force。即使带 --force,缺少仓库回执的副本也绝不会被 purge:
--purge-data --confirm-purge 被拒绝(AB7009),因为没有任何证据表明该 bundle 拥有这些数据,请不带它卸载,再手动删除数据。没有回执的 Cursor 目录,或属于另一个插件的目录,是外来目录,无论如何都被拒绝(AB7007);
再次运行是 not-installed 空操作。只读取格式 2 的回执;携带更早回执的副本是外来目录。如果回执未记录状态归属,
从当前环境或 home 解析出的根只会列为无法证明并保留;--keep-data 也不能把这次观察变成以后 purge 的权限。
宿主安装证明会在安装前与卸载后对隔离的 home 做快照:Cursor 本地与可移植 Agent Plugins 包做到字节一致;Claude 与 Codex 做到零 Agent Bundle 残留,并逐项列出宿主自有的记录文件。
在不改动的前提下检查安装
Doctor 是只读的。--from 就是 install 接受的那个组合根目录,读取方式也相同:插件身份与每个被检查宿主的
插件清单都来自 agent-bundle.manifest.json(application、projections[host]),清单没有为该宿主描述的
根目录是 AB7001。它探测宿主、清点已安装的捆绑包、把它们与提供的捆绑包做比对、检查注册证明、采样运行时
端点的健康状况与身份、清点持久状态,并对已安装的字节重新运行被固定的、无进程的文档与加载器校验器。它
绝不修复任何东西。带 --from 时,它按宿主把已安装副本报告为 current、stale(AB7308)、version-mismatch
(AB7309)、foreign(AB7321)、load-failed(AB7325)或 not-installed(AB7307),以及它的生命周期阶段,placed →
registered → enabled → active,每一阶段要么从宿主观察得到,要么被类型化为 unavailable 并给出原因(AB7330)。load-failed 表示
Claude Code 列出了该副本却拒绝加载它,它在 claude plugin list --json 中的行带有 errors 数组,Doctor 会原样报告
该数组而不是 current,因为被拒绝的副本不会为会话提供任何 hook、MCP 服务器或技能。安装器读取同一数组:当刚安装的
(或字节完全相同的既有)副本带有 errors 时,agent-bundle install claude 以 AB7006 失败,而不是报告 installed。
Doctor 还会清点每个宿主根目录下的回执仓库并与宿主交叉核对(AB7328)。
对 Claude,Doctor 还会读取每一行的 enabled 标志并运行 Claude Code 开发者校验器。被列为 enabled: false
的副本(用 claude plugin disable 或 /plugin 菜单关闭)在清点中报告为 disabled,在 --from 比对中保留其内容
结论,并追加一条带 claude plugin enable 命令的 AB7327 warning,被禁用的插件不会加载任何内容,重新安装也不会启用它。
校验器(对 plugin.json、再对 marketplace.json 执行 claude plugin validate --strict,与 build 和
validate --artifact 执行的是同样的运行)覆盖 --from 捆绑包以及每一份已安装副本,其发现保留 AB6019–AB6022
代码,并带有 Bundle at … 或 Installed copy at … (scope …) 前缀。Doctor 绝不会重复运行 --plugin-dir 加载检查:
它的注册证明与各行的 errors 已经承载了该结论。