You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add `--mode local|marketplace` to `agent-bundle install cursor`, the generated installer bin, and the emitted `install.mjs`: marketplace mode stages a committed local `.cursor-plugin/marketplace.json` repository under `~/.cursor/agent-bundle/marketplaces/<name>` and prints the Cursor Customize import step, while local mode keeps the safe copy into `~/.cursor/plugins/local/<name>`. Doctor now proves Cursor hook registration from the plugin manifest (`AB7322`), warns about duplicate `~/.cursor/hooks.json` delivery (`AB7323`), and tracks staged marketplaces to imported (`AB7324`). Documents that plugin-scoped hooks fire without user-level registration, closing #407 (#414).
Copy file name to clipboardExpand all lines: docs/diagnostics.md
+26-1Lines changed: 26 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,7 +36,7 @@ even when no error diagnostic was reported.
36
36
|`AB7010`–`AB7013`| npm prepack inventory, artifact freshness, package bin targets, and release-version agreement. |
37
37
|`AB7200`–`AB7202`, `AB7210`–`AB7211`| Development rebuilds and live host surfaces: rebuild admission and phase failures, development host install sync, and the dev-epoch contract gate (see below). |
38
38
|`AB7xxx`| Project preparation and development rebuilds. |
39
-
|`AB7300`–`AB7321`| Read-only install Doctor: host probes, installed inventory, bundle comparison and registration proof, runtime endpoint health and identity, durable-state inventory, static bytes-at-rest validation, and foreign-install detection (`AB7321`; see below). |
39
+
|`AB7300`–`AB7324`| Read-only install Doctor: host probes, installed inventory, bundle comparison and registration proof, runtime endpoint health and identity, durable-state inventory, static bytes-at-rest validation, foreign-install detection (`AB7321`; see below), and Cursor plugin hook registration / marketplace staging (`AB7322`–`AB7324`; see below). |
40
40
|`AB8200`–`AB8209`| Workbench development runtime routes (`/api/runtime/**`): `AB8200` development runtime provider configuration, load, or lifecycle failure, `AB8201` runtime/session/run not available, `AB8202` invalid route path, `AB8203` invalid request shape, `AB8204` stale runtime generation or MCP session revision (409), `AB8205` runtime request could not be completed, `AB8206` Workbench runtime client failure, `AB8207` Agent Document decoding needs the optional `@agent-bundle/runtime` peer (503), `AB8208` stored Flight could not be decoded as an Agent Document (409), `AB8209` decoded Agent Document over the 16 MiB budget (413) or an invalid document response. |
41
41
|`AB8210`–`AB8214`| Workbench semantic lifecycle replay routes (`/api/lifecycles`, `/api/lifecycles/replays`): `AB8210` invalid path, `AB8211` malformed replay request or native envelope (400, carries the shared validator message), `AB8212` replay unavailable or could not be completed, `AB8213` stale manifest binding (409; the page repairs it with refresh → explicit re-run), `AB8214` replay over the 16 MiB budget (413). |
@@ -779,3 +779,28 @@ artifact epochs. A package build failure never invalidates the artifact epoch
779
779
that already committed; it surfaces as one `AB7103`**warning** on the
780
780
succeeded build attempt, and the package build retries on the next
781
781
invalidation. See `docs/entry-conventions.md` for the dev-watch contract.
782
+
783
+
## Read-only Doctor Cursor hook registration and marketplace staging (`AB7322`–`AB7324`)
784
+
785
+
Cursor delivers a plugin's hooks from its `.cursor-plugin/plugin.json``hooks`
786
+
declaration (observed 2026-09-03 on Cursor 3.18.25; see
787
+
`docs/audits/2026-09-03-cursor-plugin-hooks-registration.md`). Doctor proves
788
+
that registration statically and never writes `~/.cursor/hooks.json`.
789
+
790
+
| Code | Severity | Meaning | Recovery |
791
+
| --- | --- | --- | --- |
792
+
|`AB7322`| info / error | Info: an installed `.cursor-plugin/plugin.json` plugin registers plugin-scoped hooks (events and command count listed) and the script each command executes — `${CURSOR_PLUGIN_ROOT}/…` or any relative path, including an interpreter's entry operand — exists under the plugin root (`hooks.state = registered`). Error: the declared hooks file is missing (`missing`), is not a regular file or not a `{ version, hooks: { <event>: [{ command }] } }` document, or an executed script is absent (`stale`). Documents and scripts are probed with `stat` before any read, so a FIFO cannot stall Doctor. | Reinstall the plugin from a bundle whose emitted hooks document and scripts are intact. |
793
+
|`AB7323`| warning |`~/.cursor/hooks.json` registers a command whose executed file (after leading `NAME=value` assignments, `env`, and interpreter options) points into an installed plugin directory — compared on path-component boundaries, case-folded on Windows — so Cursor would deliver that hook twice; or the file is not a valid hooks document. | Remove the plugin-pointing entries or repair the file; manifest registration alone is sufficient. |
794
+
|`AB7324`| info / warning / error | A staged marketplace repository under `~/.cursor/agent-bundle/marketplaces/<name>` (from `install cursor --mode marketplace`) is imported by Cursor (matching plugin under `~/.cursor/plugins/cache`; info, `registered`), still awaiting the Customize "Add Plugins from Local Repository" step (warning, `unregistered`), or incomplete (error, `corrupt`: manifests missing or failing the pinned schemas, no resolvable Git HEAD, HEAD naming a commit object that does not exist, or a working tree that differs from committed HEAD — verified read-only through `git cat-file -e` / `git --no-optional-locks status` when `git` is available). | Complete the Customize import, use `--mode local`, or remove the staged directory and rerun the installer. |
795
+
796
+
The installer side reuses the `AB700x` codes: `AB7002` when `git` is missing
797
+
in marketplace mode, `AB7003` when a mode is passed for a non-Cursor host, when
798
+
marketplace mode is requested for a bundle without `.cursor-plugin/plugin.json`,
799
+
or when the bundle contains nested Git metadata (`.git`, which `git add` would
800
+
record as an empty gitlink), `AB7004` when a `git` step fails or the committed
801
+
tree does not hold the staged bundle bytes (the installer disables `text`,
802
+
`eol`, `filter`, `ident` and `working-tree-encoding` attributes through
803
+
`.git/info/attributes`, adds with `core.autocrlf=false`, and proves every
804
+
blob id in `git ls-tree -r HEAD` against the staged files; requires Git ≥ 2.29
805
+
for `git init --object-format=sha1`), and `AB7005` for staged version or
806
+
content collisions (including a working tree that differs from committed HEAD).
Copy file name to clipboardExpand all lines: packages/agent-bundle/README.md
+11-1Lines changed: 11 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,7 +117,7 @@ manifests at files inside those payloads without compiling them. Payload files c
117
117
| --- | --- |
118
118
|`agent-bundle build`| Build a validated artifact from source, plus the declared `dist/` package build. |
119
119
|`agent-bundle prepack`| Run the release build, dry-run npm packing without scripts, and verify packaged outputs, artifact hashes, bins, and versions (`--output` and `--json` supported). |
120
-
|`agent-bundle install <host>`| Install a built bundle into Claude, Codex, or Cursor (`--from`, `--scope`, `--replace`/`--force`, and `--json` supported). Same-version content drift of an agent-bundle-managed install is replaced automatically; identical reruns are a no-op. |
120
+
|`agent-bundle install <host>`| Install a built bundle into Claude, Codex, or Cursor (`--from`, `--scope`, `--replace`/`--force`, `--mode local\|marketplace` for Cursor, and `--json` supported). Same-version content drift of an agent-bundle-managed install is replaced automatically; identical reruns are a no-op. |
121
121
|`agent-bundle doctor`| Read-only host inspection: host probes, installed inventory, and, with `--from`, the installed copy compared against the built artifact by version and content hash (`current`, `stale`, `version-mismatch`, `foreign`, `not-installed`). |
122
122
|`agent-bundle validate`| Validate project source, or an artifact with `--artifact`. |
123
123
|`agent-bundle inspect`| Inspect normalized targets and adapter plans from source, with per-target component accounting: which skills, commands, rules, hooks, MCP surfaces, and scripts each host emits and, for every omission, whether the author excluded it or the host's pinned capability judgment (`degraded`/`unavailable`/`prohibited`, with reason) ruled it out. |
Copy file name to clipboardExpand all lines: packages/agent-bundle/src/adapters/capabilities/cursor-2026-08-28.json
+3-1Lines changed: 3 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -533,7 +533,9 @@
533
533
"retrieved 2026-09-02: https://cursor.com/docs/hooks documents subagentStop input as subagent_type, status (completed|error|aborted), task, description, summary, duration_ms, message_count, tool_call_count, loop_count, modified_files, and agent_transcript_path (string|null), with output { followup_message } consumed only when status is completed and capped by loop_limit (default 5). The canonical agent/stop deny lowers to followup_message with the reason, mirroring the stop family; no additional-context channel is documented, so Agent.Context fails closed.",
534
534
"retrieved 2026-09-02: https://cursor.com/docs/hooks documents the common input envelope (conversation_id, generation_id, model, model_id?, model_params?, hook_event_name, cursor_version, workspace_roots, user_email, transcript_path) for every agent hook; generated wrappers require session_id or conversation_id plus the per-event fields and reject anything else only when documented types are violated.",
535
535
"retrieved 2026-09-02: https://cursor.com/docs/hooks documents preToolUse output permission allow|deny (ask accepted by the schema but not enforced), user_message, agent_message, and updated_input; postToolUse output updated_mcp_tool_output (MCP tools only) and additional_context; sessionStart output env and additional_context (continue/user_message accepted but unenforced); stop output followup_message. The Cursor projections emit exactly those channels.",
536
-
"2026-09-02: local cursor-agent 2026.08.31-4057e58 capture attempts for subagentStart and subagentStop could not dispatch because the binary required unavailable authentication; the pinned official contract plus the wrapper fixture replay in tests are the evidence source for the subagent lifecycle envelopes."
536
+
"2026-09-02: local cursor-agent 2026.08.31-4057e58 capture attempts for subagentStart and subagentStop could not dispatch because the binary required unavailable authentication; the pinned official contract plus the wrapper fixture replay in tests are the evidence source for the subagent lifecycle envelopes.",
537
+
"2026-09-03 (#407): hooks registration is plugin-scoped via .cursor-plugin/plugin.json `hooks` -> hooks/hooks.json; no ~/.cursor/hooks.json entry is emitted or required. Observed on Cursor 3.18.25 (isolated HOME, Agents window, shell tool call): the emitted pack's preToolUse (matcher ^Shell$), postToolUse, and stop hooks fired with CURSOR_PLUGIN_ROOT substituted and cwd = plugin root, identical to the known-loading ~/.cursor/plugins/local/tracedecay and to official marketplace plugins (cursor-public/continual-learning uses `bun run ${CURSOR_PLUGIN_ROOT}/hooks/...`). https://cursor.com/docs/hooks: 'All matching hooks from every source run', so a user-level duplicate would double-fire; Doctor reports it (AB7323). See docs/audits/2026-09-03-cursor-plugin-hooks-registration.md.",
538
+
"2026-09-03 (#407): the #407 report (Cursor 3.16.21, ~/.cursor-server) is not reproducible on 3.18.25; https://cursor.com/docs/cli/changelog (August 11, 2026 release) records 'Plugin hooks run from installed plugins ... now execute and refresh when plugins reload', a vendor-side fix in that window. Installation: `install cursor --mode local` copies to ~/.cursor/plugins/local/<name> (https://cursor.com/docs/plugins#test-plugins-locally); `--mode marketplace` stages a committed .cursor-plugin/marketplace.json repository (https://cursor.com/docs/reference/plugins#cursor-multi-plugin-repositories) for Customize -> 'Add Plugins from Local Repository', because no plugin install deeplink exists and `cursor-agent plugin marketplace add` accepts hosted git URLs only."
0 commit comments