Skip to content

clean undoes a user-scope plugin a project install collided with (cursor, codex, copilot) #829

Closed

Description

@blafourcade

What happens

Cursor plugins install at user scope only, into ~/.cursor/plugins/local/<plugin>: the directory is named by the plugin alone, with no marketplace or project in the path. When a plugin of that name is already there, whether the person installed it themselves or another project did, aidd plugin install <plugin> --tool cursor merges into it and overwrites its .cursor-plugin/plugin.json. aidd clean in the installing project then removes the files it laid down, the overwritten manifest included.

Net effect: a project-level install plus a project-level clean deletes the manifest of a user-global plugin that existed before either ran. One project's clean also removes files another project's install still relies on.

Reproduce (throwaway HOME, nothing real touched)

T=$(mktemp -d); U=$T/home/.cursor/plugins/local/aidd-telemetry
mkdir -p $U/.cursor-plugin && echo '{"name":"aidd-telemetry","version":"0.1.0","mine":true}' > $U/.cursor-plugin/plugin.json
mkdir $T/proj && cd $T/proj && git init -q
export HOME=$T/home AIDD_USER_CONFIG_DIR=$T/config
aidd setup --ai cursor --no-default-marketplace --plugins none --yes
aidd marketplace add probe <a catalog carrying aidd-telemetry> --scope project --yes
aidd plugin install aidd-telemetry --tool cursor --from probe --yes   # "mine" is gone from plugin.json
aidd clean --force                                                     # plugin.json is gone
Build After install After clean
published 5.2.2 the person's plugin.json overwritten the installed copy left behind
next at 42f572c the person's plugin.json overwritten plugin.json deleted

Expected

An install never overwrites a file it did not lay down: it refuses, or stops and names the collision. A clean removes only what this install wrote, and never a file that existed before it.

How it was found

A live journal check of aidd-telemetry on Cursor, run in a real HOME that already had aidd-telemetry installed globally. Afterwards the person's global plugin had no .cursor-plugin/plugin.json, and its directory had been modified during the check's cursor clean. Its skills/ survived.

Same class on Codex and Copilot

These hosts key a plugin by <plugin>@<catalog name>. A project that adds a catalog whose name the person already installed at user scope (here aidd-framework) shares that key. aidd clean in the project then undoes the person's own entry. Reproduced in a throwaway HOME seeded with the person's entry enabled, on the stack of open PRs:

Host Before After project install After project clean
Copilot settings.json "aidd-telemetry@aidd-framework": true true (marketplace add refused: already registered) false
Codex config.toml [plugins."aidd-telemetry@aidd-framework"] enabled = true unchanged section deleted
Codex plugins/cache/aidd-framework/aidd-telemetry/ the person's 0.1.0/ replaced by 0.2.0/, the person's version gone directory deleted

On the machine where this was found, backups from Sep 7 and Sep 8 show both entries enabled. After a live check that installed and cleaned under the aidd-framework catalog name, Copilot's key read false and Codex's section was gone. The flip itself was not observed; the mechanism above reproduces it.

Expected, all three hosts

clean undoes only what this project's install added. An entry that existed before the install is left as it was found.

Activity

  1. added theissue type on Sep 10, 2026
  2. moved this from Ideation to Todo in AIDD Roadmapon Sep 10, 2026
  3. changed the title [-]cursor: a plugin install overwrites a same-named user plugin, and clean deletes its manifest[/-] [+]clean undoes a user-scope plugin a project install collided with (cursor, codex, copilot)[/+] on Sep 10, 2026
  4. moved this from Todo to In Progress in AIDD Roadmapon Sep 10, 2026
  5. moved this from In Progress to In review in AIDD Roadmapon Sep 10, 2026
  6. moved this from In review to Done in AIDD Roadmapon Sep 10, 2026
  7. closed this as completedby moving to Done in AIDD Roadmapon Sep 10, 2026
  8. blafourcade commented on Sep 14, 2026

    @blafourcade
    ContributorAuthor

    The remaining collision is still in #829’s original scope.

    #834 protects a person’s pre-existing global installation, but the multi-project case remains: project A owns a user-scope directory, project B uses it, then cleaning A removes it and breaks B.

    Reopen this as a High Bug. A project-level clean must never delete a user-scope directory. Only an explicit clean --scope user may remove machine-wide AIDD state.

    Add the two-project scenario as the regression: install from A, use from B, clean A, then prove B still works. The explicit user-scope cleanup remains responsible for deleting the shared state.

  9. 6 remaining items

  10. blafourcade commented on Sep 20, 2026

    @blafourcade
    ContributorAuthor

    Corrigé par #870, mergé dans next (61138e0).

    Vérifié sur origin/next — 177 tests, 7 fichiers, 0 échec sur la surface clean :

    • clean-user-scope-use-case.integration.test.ts:432 — « refuses an active B Cursor user plugin but never treats project files as machine-owned », le cas Cursor décrit ici
    • clean-shared-ref-guard.integration.test.ts — huit scénarios Codex de ref partagée entre projets
    • clean-shared-ref-codex.e2e.test.ts — « keeps the plugin's ref enabled, names the other project, and never calls plugin remove »
    • clean-scope-user.e2e.test.ts — « purges its own whitelist only, leaving auth.json, telemetry/ and an unrelated marketplace entry untouched »

    Fermée à la main : la PR disait « Refs » et non « Closes », et elle a atterri sur next.

    Limite connue, hors périmètre de cette issue : Copilot CLI 1.0.83 ne sait pas prouver une source de catalogue native, donc une activation native fraîche est refusée. L'état utilisateur existant est préservé.

  11. moved this from In Progress to Done in AIDD Roadmapon Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Fields

Priority

High

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions