Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/amp-native-plugin-factory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"agent-bundle": minor
---

Add the `amp` target and `AmpSkillExtension`, emit PluginAPI factories with registered skills and events, install receipt-owned project or system copies through `agent-bundle install amp`, and advance artifacts to `manifestVersion: 4` with `projections[].documents.entry`; unrelocatable local MCP entries fail with `amp.mcp.generated-local` (#729)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# agent-bundle

agent-bundle compiles an agent plugin — skills, hooks, MCP servers, and scripts, described by one typed config — into one installable plugin root that Claude Code, Codex, Cursor, and portable Agent Plugins clients load. You write the plugin once; the compiler emits each selected host's manifests and wrappers into that root.
agent-bundle compiles an agent plugin — skills, hooks, MCP servers, and scripts, described by one typed config — into installable output for Amp, Claude Code, Codex, Cursor, and portable Agent Plugins clients. You write the plugin once; the compiler emits each selected host's entry, manifests, and wrappers into one composite root.

Documentation: [scriptedalchemy.github.io/agent-bundle](https://scriptedalchemy.github.io/agent-bundle/) (English and 简体中文; guide, reference, generated type API, host capability matrices).

Expand Down Expand Up @@ -51,7 +51,7 @@ npx agent-bundle build --root . # write the plugin root to artif
npx agent-bundle dev --root . # local workbench with live rebuilds
```

`agent-bundle build` writes one composite plugin root (`artifact/` by default; `--output` or `output.distPath` relocates it), and `targets` selects which host projections it carries: the `.claude-plugin/`, `.codex-plugin/`, and `.cursor-plugin/` manifests and the portable `plugin.json` sit at the root over shared `skills/`, `hooks/`, `mcp/`, and `scripts/` directories, emitted once. Every selected host installs from that same directory, and the generated `INSTALL.md` explains how. Omitting `targets` emits only the `portable` projection.
`agent-bundle build` writes one composite root (`artifact/` by default; `--output` or `output.distPath` relocates it), and `targets` selects which host projections it carries: Amp's `.amp/plugins/<name>/index.js`, the `.claude-plugin/`, `.codex-plugin/`, and `.cursor-plugin/` manifests, and the portable `plugin.json`. Amp installs its nested directory; the other hosts install the composite root, and the generated `INSTALL.md` explains how. Omitting `targets` emits only the `portable` projection.

The `portable` target is the [Agent Plugins open standard](https://agent-plugins.org/specification) (specification 1.0.0) adapter — the default projection, and the layout Cursor loads natively (Claude Code consumes it only through CLI translation). Every other client that reads this artifact is recorded with its tier, install command, and dated evidence in the `clients` section of that same capability table, rendered as the [hosts reference](https://scriptedalchemy.github.io/agent-bundle/reference/hosts). It emits the closed root `plugin.json` (canonical `$schema`, `name`, `version`, `description`, plus `author`, `homepage`, `repository`, `license`, `keywords`, and reverse-domain `extensions` authored under the `portable` config key), `skills/<name>/SKILL.md`, and `mcp.json` with stdio and Streamable HTTP servers whose `args`, `env` values, and `cwd` use the standard's `${PLUGIN_ROOT}`/`${PLUGIN_DATA}` placeholders. Rules, commands, hooks, marketplaces, and client extension directories are honestly unavailable there because the v1 standard packages only skills and MCP servers. Both documents are validated against the vendored, hash-pinned 1.0.0 schemas and the normative text at plan time (`portable.mcp.*.standard`), after every ordinary build and `validate --artifact` (`AB6011`/`AB6012` plus the Agent Plugins byte lane `AB6035`–`AB6037`), under `validate --artifact --host-validation` (same lane with the `AB6038` provenance note), and by `agent-bundle doctor` for installed Cursor local plugins that declare the standard's `$schema` (`AB7320`); see [Diagnostics](docs/diagnostics.md#agent-plugins-portable-validation-ab6035ab6038). Pins live in `packages/agent-bundle/src/adapters/schemas/portable/PROVENANCE.json`; the capability table `packages/agent-bundle/src/adapters/capabilities/portable-1.0.0.json` carries a dated row for every standard feature.

Expand Down
78 changes: 78 additions & 0 deletions docs/audits/2026-09-07-amp-native-adapter-proof.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Amp native adapter proof — 2026-09-07

## Pins and boundary

- `@ampcode/plugin@0.0.0-20260907001852-gf348fed`
- `@ampcode/cli@0.0.1788739286-gf348fe`
- Official Plugin, PluginAPI, Skills, and MCP pages retrieved 2026-09-07
- No Amp account was available. Live thread, model, and tool execution was not run and remains
**unverified**, not unsupported.

Everything below ran under `/tmp/agent-bundle-amp-proof` with
`HOME=/tmp/agent-bundle-amp-proof/home`.

## Build and static artifact proof

The disposable consumer installed the two pinned Amp packages, TypeScript, Node/Bun type
declarations, and the locally built `agent-bundle` package. npm 12 blocked the CLI postinstall by
default, so the proof completed the package's own `node node_modules/@ampcode/cli/install.cjs`
before invoking Amp.

`agent-bundle build --target amp` emitted:

```text
artifact/
├── .amp/plugins/amp-proof/index.js
├── .amp/plugins/amp-proof/skills/review/SKILL.md
├── INSTALL.md
├── agent-bundle.compile-evidence.json
└── agent-bundle.manifest.json
```

The manifest recorded `manifestVersion: 4`,
`builtInHost: "amp"`, `documents.entry: ".amp/plugins/amp-proof/index.js"`,
adapter revision `1.0.0`, and the pinned PluginAPI version. The compile evidence used
`closed-world-externals` revision 1 and recorded no compiled assets for the content-only plugin.

## PluginAPI type and fake-host proof

Two generated entries were checked with TypeScript 7.0.2 in strict `checkJs` mode:

1. the content-only factory with one explicit `registerSkill`;
2. a callback factory containing inline handlers for `session.start`, `tool.call`, `tool.result`,
`agent.start`, and `agent.end`.

The disposable `tsconfig.json` alone used `skipLibCheck: true`, because the pinned upstream
declaration references `Symbol.observable`, which the selected TypeScript libs do not declare.
No repository compiler setting was weakened.

Both entries passed. Neither has a runtime `@ampcode/plugin` import; its only reference is the
JSDoc type on the default async factory. A typed fake `PluginAPI` then imported the factories and
asserted:

- exactly `registerSkill({ path: "skills/review" })`;
- no event registrations for the content-only entry;
- exactly the five documented event registrations for the callback entry;
- `tool.call` native results preserved as `reject-and-continue`, `modify`, and `synthesize`;
- `tool.result` replacement preserved as `{ status: "done", output: "replaced" }`.

The repository adapter tests additionally cover `allow`, `agent.start` appended context,
`agent.end` continuation, generated wrapper execution, MCP/frontmatter precedence, relocation,
and receipt-owned install/replace/uninstall.

## Account-free CLI observations

- `amp --help`: exit 0; lists `plugins`, `skill`, and `mcp`.
- `amp skill add --help`: exit 0; source is `owner/repo[/path]`, a Git URL, or a local path;
`--global` targets `~/.config/agents/skills/`.
- `amp plugins list`: exit 1:

```text
Error: failed to load global plugins. Unable to connect to https://ampcode.com/.
```

- `amp skills list --json`: started the login flow with `No API key found. Starting login flow...`
and was terminated rather than opening or completing an account login.

Amp documents `plugins: reload` only as an interactive command-palette action. No standalone
plugin validator exists, so the implementation does not invent or automate either operation.
6 changes: 3 additions & 3 deletions docs/diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -1928,10 +1928,10 @@ the uninstall refusals `AB7007`–`AB7009`, have their own sections above.

| Code | Severity | Meaning | Recovery |
| --- | --- | --- | --- |
| `AB7000` | error | Install/uninstall: `Unsupported install host <host>.` / `Unsupported uninstall host <host>.` — the exhaustive host switch received a host that is not `claude`, `codex`, or `cursor`. Project preparation: `Unable to load project source.` — evaluating the configuration module or discovering source threw before validation. | Install: pass `--host claude`, `codex`, or `cursor`. Preparation: fix the Agent Bundle configuration and source files, then inspect again. |
| `AB7001` | error | Install/uninstall/doctor: the bundle identity or authoritative file inventory is unreadable from `agent-bundle.manifest.json` — no manifest directly under the `--from` directory (the composite root is every selected host's bundle root, so `<from>/<host>` is never probed and host documents are never read for identity); a manifest that is not the canonical `manifestVersion: 3` document (the message carries the parser's reason); a manifest with no projection whose `builtInHost` is the requested host (identity is the shipped adapter, never the selected name), whose projection has no `documents.plugin`, or whose `documents.plugin` / `documents.marketplace` pointer names a file the root does not contain; a `files[]` row whose path is missing or whose size, digest, bytes, or executable state is invalid after installation (a declared package bin must remain executable; a file the manifest does not declare executable must remain non-executable; another manifest executable may have lost its bit while being packed from a filesystem without executable modes); a Cursor `application.name` that is not a safe local plugin name; a Claude or Codex projection with no `marketplace.name`. `install` restores manifest modes before copying an npm-installed artifact into a host, while Doctor only compares. Project preparation: `Unable to validate project source.`, `Unable to normalize project source.`, `Unable to validate normalized project.`, or `Unable to create project context.` — the source validator, normalizer, adapter planner, or project-context factory threw; `inspectProject` adds `Unable to prepare inspection plans.` and, for `inspect --bundler`, `Unable to compose the bundler inspection: <reason>` — loading entries, generating the declaration tsconfig, or lowering and asserting the build's own Rslib/Rsbuild configuration failed. The reason carries the underlying source, project-tsconfig, toolchain, or invariant error, including a `tools` value the build would refuse. | Install: point `--from` at the unchanged composite root `agent-bundle build` wrote, rebuilt with the host among `targets`; if a listed file is missing or changed, rebuild or restore that file from the matching artifact. Preparation: fix normalized project configuration and source references, then inspect again. Bundler inspection: fix the source, project tsconfig, toolchain, or refused `tools` value named by the reason. |
| `AB7000` | error | Install/uninstall: `Unsupported install host <host>.` / `Unsupported uninstall host <host>.` — the exhaustive host switch received a host that is not `amp`, `claude`, `codex`, or `cursor`. Project preparation: `Unable to load project source.` — evaluating the configuration module or discovering source threw before validation. | Install: pass `--host amp`, `claude`, `codex`, or `cursor`. Preparation: fix the Agent Bundle configuration and source files, then inspect again. |
| `AB7001` | error | Install/uninstall/doctor: the bundle identity or authoritative file inventory is unreadable from `agent-bundle.manifest.json` — no manifest directly under the `--from` directory (the composite root is every selected host's bundle root, so `<from>/<host>` is never probed and host documents are never read for identity); a manifest that is not the canonical `manifestVersion: 4` document (the message carries the parser's reason); a manifest with no projection whose `builtInHost` is the requested host (identity is the shipped adapter, never the selected name), whose projection has neither its required `documents.plugin` nor Amp `documents.entry`, or whose `documents.entry` / `documents.plugin` / `documents.marketplace` pointer names a file the root does not contain; a `files[]` row whose path is missing or whose size, digest, bytes, or executable state is invalid after installation (a declared package bin must remain executable; a file the manifest does not declare executable must remain non-executable; another manifest executable may have lost its bit while being packed from a filesystem without executable modes); a Cursor or Amp `application.name` that is not a safe local plugin name; a Claude or Codex projection with no `marketplace.name`. `install` restores manifest modes before copying an npm-installed artifact into a host, while Doctor only compares. Project preparation: `Unable to validate project source.`, `Unable to normalize project source.`, `Unable to validate normalized project.`, or `Unable to create project context.` — the source validator, normalizer, adapter planner, or project-context factory threw; `inspectProject` adds `Unable to prepare inspection plans.` and, for `inspect --bundler`, `Unable to compose the bundler inspection: <reason>` — loading entries, generating the declaration tsconfig, or lowering and asserting the build's own Rslib/Rsbuild configuration failed. The reason carries the underlying source, project-tsconfig, toolchain, or invariant error, including a `tools` value the build would refuse. | Install: point `--from` at the unchanged composite root `agent-bundle build` wrote, rebuilt with the host among `targets`; if a listed file is missing or changed, rebuild or restore that file from the matching artifact. Preparation: fix normalized project configuration and source references, then inspect again. Bundler inspection: fix the source, project tsconfig, toolchain, or refused `tools` value named by the reason. |
| `AB7002` | error | Install/uninstall: `<host> is not installed or is not available on PATH.`, `Cursor is not installed in "<root>".` / `Cursor home "<root>" is not a directory.`, or `git` is missing for `--mode marketplace`. Project preparation: `Unable to prepare project paths.` — the project root or a configured output root could not be resolved inside the project. | Install: install the host CLI the message names; for the `git` refusal, install git or use `--mode local`. Preparation: ensure the project root and configured output roots are readable and remain inside the project root, then inspect again. |
| `AB7003` | error | Install/uninstall scope and mode refusals: `--mode` on a host other than `cursor`; `--scope` other than `user` for Codex or Cursor; `--mode marketplace` without `.cursor-plugin/plugin.json` or with bundle-internal Git metadata. Project preparation: `Unable to snapshot project source.` — the source snapshot could not be taken. | Install: use `--scope user`, drop `--mode` for non-Cursor hosts, or — as the message says — stage a Cursor Plugin bundle without `.git`, or use `--mode local`. Preparation: ensure project source files and ignore rules are readable and remain inside the project root, then inspect again. |
| `AB7003` | error | Install/uninstall scope and mode refusals: `--mode` on a host other than `cursor`; `--scope` other than `user` for Codex or Cursor; Amp `--scope local` instead of `project` or `user`; `--mode marketplace` without `.cursor-plugin/plugin.json` or with bundle-internal Git metadata. Project preparation: `Unable to snapshot project source.` — the source snapshot could not be taken. | Install: use a documented host scope, drop `--mode` for non-Cursor hosts, or — as the message says — stage a Cursor Plugin bundle without `.git`, or use `--mode local`. Preparation: ensure project source files and ignore rules are readable and remain inside the project root, then inspect again. |
| `AB7004` | error | Install/uninstall command and safety failures: `<host> plugin <operation> failed: <detail>` (a host CLI verb exited nonzero); `<host> plugin list --json` was unusable when `--replace` or an uninstall needed it; an installed copy could not be compared and `--replace` was not given; a rollback after a failed install also failed (the message lists the host verbs to run by hand); a Cursor marketplace `git` step failed or the committed tree differs from the staged bytes; or any non-diagnostic error thrown by a Cursor installer. `inspectProject`: `Requested inspection target "<name>" is not selected for this project.` | Install: read the host's detail in the message, then rerun (with `--replace` where the message says so). Inspection: choose a target selected by the project configuration, then inspect again. |

## Development server (`AB80xx`)
Expand Down
15 changes: 11 additions & 4 deletions packages/agent-bundle/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# agent-bundle

Compile a typed Agent Bundle configuration into portable, Codex, Claude Code, and Cursor artifacts. Node.js 22.19 or later is required.
Compile a typed Agent Bundle configuration into Amp, portable, Codex, Claude Code, and Cursor artifacts. Node.js 22.19 or later is required.

Full documentation: [scriptedalchemy.github.io/agent-bundle](https://scriptedalchemy.github.io/agent-bundle/).

Expand Down Expand Up @@ -189,6 +189,7 @@ so their public CLIs can install the emitted directory directly:
```sh
agent-bundle install claude --from artifact --scope user
agent-bundle install codex --from artifact
agent-bundle install amp --from artifact --scope user
```

The installer delegates to `claude plugin marketplace add` /
Expand All @@ -205,6 +206,11 @@ agent-bundle install cursor --from artifact
node ./install.mjs
```

Amp installs only `artifact/.amp/plugins/<name>/` into the project or system
plugin root. The generated `index.js` default-exports the async PluginAPI
factory, registers each bundled Skill once, and imports no Amp runtime.
Reloading remains the interactive Ctrl+O → `plugins: reload` action.

Cursor loads the copied `.cursor-plugin/plugin.json` and its manifest-declared
`.cursor-plugin/hooks.json` from that directory; plugin hooks run from the plugin root
with `${CURSOR_PLUGIN_ROOT}` substituted and need no `~/.cursor/hooks.json`
Expand All @@ -227,8 +233,9 @@ the shipped document in the install receipt (`cursorExpansion`), and
`agent-bundle doctor --host cursor` proves the expansion (`AB7326`). The bundle
itself stays spec-conformant for other Agent Plugins clients.

Cursor installation is user-scoped. Claude also accepts `--scope project` and
`--scope local`; Codex is user-scoped. `--from` names the composite root itself —
Cursor installation is user-scoped. Amp accepts project scope and user scope
(its system root). Claude also accepts `--scope project` and `--scope local`;
Codex is user-scoped. `--from` names the composite root itself —
the directory that holds `agent-bundle.manifest.json` — and a source-free copy
of that root is accepted. Identity (name, version, marketplace) and the host
plugin document come from that manifest's `application` and `projections[]`
Expand Down Expand Up @@ -305,7 +312,7 @@ Receipts (`agent-bundle-install-receipt/2`) are the single source of truth for
an install's lifecycle: version, content hash, delivery mode, scope, owned files
and directories, the host directories the installer created, the host
registrations it performed in order, and install/update timestamps. Cursor
local copies carry the receipt in-tree; Claude, Codex, and Cursor
local and Amp project/system copies carry the receipt in-tree; Claude, Codex, and Cursor
marketplace-mode installs keep theirs under `<host root>/agent-bundle/receipts/`
(`~/.claude`, `~/.codex`, `~/.cursor`, honouring `CLAUDE_CONFIG_DIR` and
`CODEX_HOME`). `agent-bundle uninstall <host> --from <bundle-dir>`, the package
Expand Down
2 changes: 1 addition & 1 deletion packages/agent-bundle/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "agent-bundle",
"version": "0.1.0",
"description": "Compile a typed Agent Bundle configuration into portable, Codex, Claude Code, and Cursor artifacts.",
"description": "Compile a typed Agent Bundle configuration into Amp, portable, Codex, Claude Code, and Cursor artifacts.",
"license": "Apache-2.0",
"keywords": [
"agent",
Expand Down
Loading
Loading