Skip to content

claude-ops plugins skill: converge predicts the wrong settings-write behavior for uninstall -s project #2520

Description

@kyle-sexton

What's wrong

skills/plugins/context/converge.md Step 5 says claude plugin uninstall -s project
"can remove an enabledPlugins entry" from a project's committed .claude/settings.json.
That phrasing licenses a run to predict "no enabledPlugins key, therefore no write" and skip the
diff check. The prediction is wrong: the call always writes that file.

Hit live while running /claude-ops:plugins converge over 18 project-scope pins. The skill reported
the mutations as machine-local, then both affected checkouts turned out to have a dirty tracked
.claude/settings.json.

Verified behavior (Claude Code 2.1.228)

Single calls, against a clean tracked .claude/settings.json, git-diffed after every step:

Call Writes committed settings? Effect
install -s project yes adds the id to enabledPlugins (true)
update -s project no the existing documented exemption still holds
uninstall -s project yes removes the entry, leaves "enabledPlugins": {}

Both writing calls rewrite the whole file in Claude Code's key order, so unrelated sibling keys move.
uninstall writes the enabledPlugins key even into a file that never had one, which is what
produces a diff that changes no behavior — an empty map plus a key reorder.

Also missing

  • Project scope keys on the working directory, not the repository. Verified by uninstalling one
    id in a repo's main checkout and watching its git worktree's record for the same id survive. Two
    checkouts sharing one .git and one tracked .claude/settings.json pin independently.
    converge.md Step 2 already mandates a per-projectPath cd, but justifies it as "a different
    repo" — understating the worktree case.
  • sync.md write-timing uncertainty. The "Version capture" section notes the skill has not
    established when the CLI writes installed_plugins.json relative to the "restart to apply"
    message. One observation is now available and worth recording without retiring the fallback.

Expected

Step 5 should check every touched project unconditionally and classify the diff — inert (empty map
plus reorder) versus substantive (an entry actually removed) — because the two warrant opposite
advice. scope-semantics.md should carry install/uninstall as verified facts beside the update
exemption.

Notes

Upstream anthropics/claude-code#81058 reports a related but more destructive variant on 2.1.220
(the key deleted from user settings, disabling a surviving user-scope install). That did not
reproduce on 2.1.228 — the user-scope enabledPlugins entries survived the converge run intact.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: needs-triageDefault until a priority tier is assigned.work-class: scopedA briefed fix or small feature; blast radius bounded by the brief, tests exist.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions