Summary
The unified plugin target's generated AGENTS.md instructs, for Cursor:
Cursor: clone (or symlink) this directory to ~/.cursor/plugins/local/<name>; the manifest is .cursor-plugin/plugin.json.
The symlink half of that instruction does not work in current Cursor: the local-plugin loader (cursor-agent-exec, observed in server build 9746bf00534f29fc29f1deb9ddfb5448f7905eb0) resolves symlinked entries and rejects any whose target is outside the local plugins root (containment check). A symlinked artifact directory — the natural dev setup, and what the instruction suggests — is silently skipped except for a warn-level log line most users will never see:
[warn] loadUserLocalPlugin cargo-conductor rejected: symlink target /fast/projects/agent-plugins/cargo-conductor/artifact/plugin is outside /home/zack/.cursor/plugins/local
Symptom from the consumer side: plugin absent from Cursor, MCP server not registered, hooks never fire — with no visible error. Cost us a full trust-nothing debugging pass on a freshly built plugin (manifest, hook schema, and wrapper had all been verified working in isolation; the loader never read them).
Decompiled loader behavior for reference: entries may be dirs or symlinks; dot-names skipped; symlinks are realpath'd and must remain inside the plugins root and resolve to a directory; manifest candidates are .cursor-plugin/plugin.json, .claude-plugin/plugin.json, plugin.json.
Suggestion
- Change the generated AGENTS.md Cursor line to "copy (or clone) this directory into
~/.cursor/plugins/local/<name>" and explicitly note that symlinks must not point outside the plugins root.
- Optionally: since copies go stale on rebuild, consider emitting a tiny
install-cursor helper (or documenting an rsync one-liner) that syncs the built target into the plugins root after agent-bundle build.
Observed with agent-bundle preview 560124af output installed on Cursor server 9746bf0.
Summary
The unified
plugintarget's generatedAGENTS.mdinstructs, for Cursor:The symlink half of that instruction does not work in current Cursor: the local-plugin loader (
cursor-agent-exec, observed in server build9746bf00534f29fc29f1deb9ddfb5448f7905eb0) resolves symlinked entries and rejects any whose target is outside the local plugins root (containment check). A symlinked artifact directory — the natural dev setup, and what the instruction suggests — is silently skipped except for a warn-level log line most users will never see:Symptom from the consumer side: plugin absent from Cursor, MCP server not registered, hooks never fire — with no visible error. Cost us a full trust-nothing debugging pass on a freshly built plugin (manifest, hook schema, and wrapper had all been verified working in isolation; the loader never read them).
Decompiled loader behavior for reference: entries may be dirs or symlinks; dot-names skipped; symlinks are realpath'd and must remain inside the plugins root and resolve to a directory; manifest candidates are
.cursor-plugin/plugin.json,.claude-plugin/plugin.json,plugin.json.Suggestion
~/.cursor/plugins/local/<name>" and explicitly note that symlinks must not point outside the plugins root.install-cursorhelper (or documenting an rsync one-liner) that syncs the built target into the plugins root afteragent-bundle build.Observed with agent-bundle preview
560124afoutput installed on Cursor server9746bf0.