命令行
命令
共享选项组
源码命令(build、prepack、validate、eval):
产物命令(mcp list、mcp invoke、mcp run、serve-app、hooks list、hooks simulate):同样的
--root、--config、--mode 与 --json,外加 --artifact <path>(精确使用某一份已构建产物)与
--target <target>(选择宿主投影)。对 mcp list、mcp invoke、mcp run 与 serve-app 来说,
--target 是可选的:省略时,产物的 agent-bundle.manifest.json projections[] 会给出运行该服务器的
唯一一个具备 MCP 能力的宿主;若投影让这一选择产生歧义,命令会以一条点名候选宿主的错误失败。
hooks simulate 仍然必填,因为钩子 wrapper 是按宿主编译的。serve-app 不接受 --json。
dev
dev 在前台运行,并在收到终止信号时关闭会话。见
开发者 Workbench。
dev proxy
proxy 从父命令 dev 继承 --root,并把诊断写到 stderr。
serve-app
在一个普通浏览器标签页里独立提供一个已构建的 MCP App,不在任何 MCP 宿主之内,也不需要
Workbench:该命令以与 mcp run 完全相同的方式启动插件打包好的 MCP 服务器,通过 Workbench App 工作区
所用的同一套宿主栈(沙箱代理、同意授权、桥接)把 App 绑定到它上面,先调用一次 App 的工具让它带着数据
打开,然后打印 loopback URL。它的输出是一份契约:宿主开始监听后,stdout 恰好携带一行
MCP App <app> at <url> (tool <tool>; Ctrl-C stops the server),<app> 为命令行上给出的原样,<tool> 为
打开该 App 的工具,而每条诊断都写到 stderr。随后命令在前台运行:SIGINT 或 SIGTERM 会关闭宿主及其
服务器并以 0 退出;当被绑定的 MCP 服务器自行退出时,一条 AB5000 诊断会写到 stderr,命令以 1 退出。
<plugin> web 打印同一条就绪行契约。
宿主只绑定 127.0.0.1,只提供一份文档与经过认证的 /api/mcp/... 路由(每次启动一个令牌,加同源检查;
拒绝时为 AB8003 / AB8004),并且只通过桥接暴露所选的那个服务器。App 文档本身运行在框架沙箱内的第二个
loopback origin 上。它是本地预览宿主,不是部署目标。面向脚本与测试的编程形式是 agent-bundle/api 中的
serveApp。从已安装产物出发,受支持的命令是 <plugin> web,它从 bin/<plugin>.mjs
运行同一套宿主栈,机器上不需要框架,见
在浏览器中暴露 App。
<plugin> web
组合产物 bin/<plugin>.mjs 上由框架拥有的 web 命令。只要项目配置了
web,即使 src/cli/** 没有编译出任何命令,也会输出该 bin,并出现在
它的 --help 里。从已构建产物或已安装插件根目录运行,agent-bundle.manifest.json 必须位于
bin/ 旁边(否则退出码 1)。
该命令启动插件自己的 MCP 服务器(node <root>/mcp/<entry>.mjs,AGENT_BUNDLE_PLUGIN_ROOT=<root>,
已声明的静态 env 并展开路径令牌,plugin-data 令牌解析到产物之外的
~/.agent-bundle/web-data/<plugin>-<digest>/<server>,因此只读安装也能启动)。被拉起的服务器自己的
持久框架状态同样落在产物之外的 ~/.agent-bundle/state/<plugin>-<digest>(或
AGENT_BUNDLE_STATE_ROOT)。随后先调用一次开场工具,然后在 http://127.0.0.1:<port>/ 上用
loopback origin 提供 App,并为 App 文档再开一个 loopback 沙箱 origin,与 agent-bundle serve-app
以及 Workbench 同一套宿主栈与同意行为。人类模式打印
MCP App <server>/<app> at <url> (tool <tool>; Ctrl-C stops the server),并一直运行到 Ctrl-C /
SIGTERM。当配置了 web 时,手写的 src/cli/web.ts(或任何拼作 web 的生成式命令或顶层别名)会被
AB4341 拒绝。
build 与 prepack
两者都接受源码选项组,外加:
当项目声明了 bin 或 lib 时,两者都会构建包输出。根目录的布局见
Target 与产物。
生成的包装模块以相对项目根目录的说明符导入项目模块,因此当所有被编译的模块都位于项目根目录内(包括其
自身的 node_modules)时,同一份源码从两个检出路径构建会输出逐字节相同的文件和相同的清单。解析到根目录
之外的模块会保留相对根目录的路径。
仅 build 还接受:
JSON 文档在 hostValidation 下携带这些报告,每个被校验的投影一份;加载检查运行过时,每份报告带有
load 结论(loaded、refused、unregistered 或 failed)。以编程方式调用 build() 时,除非传入
hostValidation: true,否则绝不运行宿主校验。
若编译过程中项目源码发生变化,build 与 build() 会在编译和校验之后、暂存树替换现有产物或
包输出之前以 AB7101 拒绝结果,因此不会发布编译器元数据与已编译字节来自不同源码快照的产物;
此前已发布的产物或包输出保持原样。重新运行构建即可;抢跑的那次改动已经在磁盘上。
install
输出的独立 install.mjs 接受同样的 --replace。Cursor 副本携带安装回执
(.agent-bundle-install.json),替换只触碰归属文件;没有指向本插件回执的目录(包括回执出现之前放置的副本)
是外来目录,带不带 --replace 都会被拒绝;Claude 的替换
先运行 claude plugin uninstall --keep-data 再重新安装。Codex 的替换只执行 codex plugin add,以便保留插件设置与嵌套
MCP 覆盖。已禁用或启用状态未知的 Codex 替换会被拒绝(AB7004),因为原生 plugin CLI 没有可保留设置的合格更新 API。
每次安装都会写入生命周期回执(格式 agent-bundle-install-receipt/2:版本、内容哈希、模式、作用域、归属路径、
宿主注册、时间戳),Cursor 与 Amp 本地副本写在树内,Claude、Codex 与 Cursor 市场模式写在
<宿主根目录>/agent-bundle/receipts/ 下,uninstall 与 doctor 都消费它。
安装期间,尚不存在的显式状态根会由安装器创建,并写入记录安装身份的
.agent-bundle-state-owner.json。为到达该根而创建的父目录不会被声明为归属内容,也绝不会被递归删除。
uninstall
uninstall 只删除回执归属的内容:记录的文件与安装器创建的目录(Cursor 本地,包括安装本身创建的
~/.cursor/plugins[/local] 目录;Amp 项目/系统副本只限 .amp/plugins/<name>)、暂存仓库(Cursor 市场模式,在其 HEAD 与记录的提交匹配之后),或宿主注册
(claude plugin uninstall <id> --scope <scope> --keep-data + claude plugin marketplace remove,
codex plugin remove + codex plugin marketplace remove,若另一个已安装插件仍在使用该市场,则保留市场,
包括仅记录在 Claude 的 plugins/installed_plugins.json 注册表中、位于另一作用域或另一项目的 Claude 安装)。
非归属条目被保留并列出,插件旁的 state/ 目录也在其中;缺少仓库回执为 AB7009,不匹配为 AB7007,除非 --force;
没有回执的 Cursor 本地目录即使带 --force 也是外来目录(AB7007);再次运行是 not-installed
空操作。类型化的 data.outcome 按宿主如实说明持久状态的去向:Cursor 为 kept / purged / absent;
Claude 为 retained-by-host(缓存副本在 Claude 约 14 天的宽限期内被标为 orphaned;purge 会删除归属的框架状态根、
推导出的 web-data 与 plugins/data/<id>/);Codex 默认保留外部状态,在确认 purge 时删除它,
而 codex plugin remove 会删除缓存树。输出的 install.mjs 接受
--uninstall,并支持 --mode、--keep-data、--purge-data --confirm-purge、--force 与 --plan。
状态回执把三件事分开:已安装的 MCP 文档决定每个服务器的运行时位置(相对覆盖值从该服务器的执行目录解析);
回执记录本次安装观察到的位置;只有独立的归属证据才允许删除。默认的
~/.agent-bundle/state/<plugin>-<digest>(或
$XDG_STATE_HOME/agent-bundle/<plugin>-<digest>)命名空间按构造归该安装独占。显式
AGENT_BUNDLE_STATE_ROOT 只有在安装时原本不存在、由安装器创建并写入安装身份标记时才归该安装所有。
预先存在的目录绝不会仅因服务器声明或卸载时的当前环境指向它而被递归删除。多个服务器与多个根会分别记录、分别判断。
如果回执没有 state 块,当前环境或 home 就不能提供 purge 权限:
Doctor 与 uninstall 会把观察到的根报告为 unrecorded / 无法证明并予以保留,即使之前运行过 --keep-data 也一样。
只读取 agent-bundle-install-receipt/2;携带更早回执的副本是外来目录。
doctor
当 Doctor 报告任何 error 级诊断时以 1 退出,并且绝不修改任何东西。带 --from 时,它按宿主把已安装副本报告为
current、stale(版本相同、内容不同,AB7308)、version-mismatch(AB7309)、foreign(AB7321)、
load-failed(AB7325,Claude Code 在 claude plugin list --json 中列出了该副本但带有 errors,拒绝加载它;
消息原样携带宿主的文本)或 not-installed(AB7307)。对 Claude,它还会读取每一行的 enabled 标志:被列为
enabled: false 的副本在清点中为 disabled,并在其内容结论旁携带 enabled: false,附带一条点名
claude plugin enable 命令的 AB7327 warning;它还会对 --from 捆绑包以及每一份已安装副本运行 Claude Code
开发者校验器(对 plugin.json、再对 marketplace.json 执行 claude plugin validate --strict),把发现报告为带有
Bundle at … 或 Installed copy at … 前缀的 AB6020–AB6022。对 Cursor,它还会根据已安装清单证明插件级 hook 的注册(AB7322),在
~/.cursor/hooks.json 会把某个插件 hook 再投递一次时发出警告(AB7323),并跟踪暂存的市场从 unregistered
到 Cursor 导入后的 registered(AB7324)。对 Agent Plugins 安装,它还会证明输出的安装器所做的占位符展开,
expanded、unexpanded(Cursor 3.18.25 无法启动的规范形式)或 drifted(AB7326)。带 --from 时,它还按宿主报告
生命周期阶段,placed → registered → enabled → active,每一阶段要么被观察到(Claude 与 Codex 的 plugin list --json
行及其 enabled 标志、Cursor 本地目录、Cursor 市场导入缓存),要么被类型化为 unavailable 并给出没有只读表面能暴露它
的原因(AB7330)。它还清点每个宿主根目录下的 Agent Bundle 回执仓库,对宿主已不再认可的回执发出警告(AB7328)。
uninstall --keep-data 连同残留回执留下的 Cursor 目录会以 AB7307 info 报告为 missing,而不是 corrupt 或 foreign;
没有该回执时,仅包含 state/ 的目录既是 corrupt(AB7304)也是 foreign(AB7321)。
对于每份已安装副本,Doctor 会报告每个服务器对应的框架状态根、其 native 或 derived 来源、回执归属
(derived、marker、unowned 或 unrecorded)、当前证据是否允许 purge、使用它的服务器、是否存在以及是否可写。
插件旁的 state/ 目录是普通的非归属条目,不是持久状态。
validate
eval
eval compare <baseline> <candidate> 接受两个已持久化的运行 id,并从 eval 继承源码选项。
inspect
inspect 接受 --root、--config、--mode、--json 与单个 --target <target> 过滤器
(不可重复),外加至多一个聚焦标志。--artifact <path> 改为通过已复制构建产物根目录上的
agent-bundle.manifest.json 检查该根,而不是检查项目源码树;它与 --root、--config 互斥
(用法错误)。清单缺失或非规范时以 AB7001 失败。
传入多个聚焦标志是错误。当规范化模型无效时,inspect 以 1 退出。
带 --json 时,只要产物输出位置存在已构建的 agent-bundle.manifest.json,文档就会多出一份
output.manifest 摘要,已构建的 projections[] 与 executables,因此 JSON 消费者无需自行探测根目录就能
看到上一次构建输出了什么。源码侧的模型与计划视图不变。
inspect --artifact <path> 不加载项目配置。--json 打印 { manifest, application }:与
output.manifest 相同的 InspectManifestSummary,以及 Workbench 渲染的同一份 application
投影(applicationExplorerFor),其中包括 distribution.payloads[],每个预构建负载的 name、
hosts 与 runtimeDependencies(产物专用消费者读取的、必须存在于消费者运行时的包行;见
definePrebuilt)。不带 --json 时,
人类可读输出是应用 id/名称/版本、带 builtInHost 的投影、带工具计数的服务器、按宿主分组的钩子、
以及 bins、scripts 与 payload 行。
每份检查计划都会以规范组件类型报告每个组件,agent、cli、command、event-route、hook、lsp、
mcp-app、mcp-server、native-diagnostics、native-extension、rule、script、skill(来自
agent-bundle/api 的 AgentComponentKind),标为 selected 或带原因的 skipped,并附一份 kinds 矩阵:
每种类型一条,包含该 target 自己的四态能力判定以及选中/省略计数。人类可读输出为每个 target 打印一行、每条
省略及其原因,然后是 kinds this host cannot emit:。文件系统 src/events 路由报告为 event-route,按宿主的
event:<规范事件> 行判定,而不是 hook。
mcp
mcp list 需要 --server <server>。mcp invoke 需要 --server 与 --tool <tool>,并且只接受
--input <json> 与 --input-file <path> 二者之一;解析出的值必须是 JSON 对象,而不是数组或标量。
三者都从产物的 agent-bundle.manifest.json 解析服务器:编译后的入口(及其 Flight worker)来自
executables.mcpServers[].entry,App 来自 executables.mcpServers[].apps[],省略 --target 时宿主来自唯一
具备 MCP 能力的 projections[] 行;有歧义的选择是一条点名候选宿主的错误。
mcp run 需要 --server,并以继承的 stdio 在前台运行一个 stdio 服务器:
由于在整个前台运行期间由服务器持有 JSON-RPC 通道,mcp run 自身不向 stdout 写任何东西。.env 优先级
规则,以及 plugin-root 锚点改变了什么,见运行时环境。
hooks
hooks list 报告某份产物中的钩子,即其 agent-bundle.manifest.json 的 executables.hooks[] 行。
hooks simulate 需要 --hook <hook>(id 或名字),以及与 mcp invoke 相同的 --input / --input-file
二选一。
退出码
当任何一次试验失败或结论不明时,eval 运行以 1 退出,结论不明的试验没有产生证据,因此它同样不能
报告成功。