[BUG] [Cowork] Two plugins with the same name: the slash menu shows two unlabeled entries, and in a local session both load the marketplace copy
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (related: #94309, #95107)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code (Claude Desktop 2.19675.0 for macOS; agent 2.1.286 in the local session)
What's Wrong?
In a Team org, I had a plugin my-plugin installed from a marketplace (version 0.1.0), and I uploaded a private zip of a plugin with the same name (version 0.2.0). Customize → Plugins listed both, both enabled.
- Two identical, unlabeled menu entries. Typing
/and part of the skill name shows the skill twice. Nothing tells the user which copy each entry is. - Local session: the private copy can't be reached. In a local Cowork session, I picked each entry in turn (two new tasks). Both loaded the marketplace copy (0.1.0). The private copy had been delivered to the session: the session record lists both plugin ids, and both copies were staged on disk. It just could not be selected. (n=2, checked on disk.)
- The two upload routes handle the clash differently. When the same-name plugin is in the Organization library, the upload shows a dialog: "A plugin with this name is already in your organization's library." and "Give yours a different name to keep both, or use the org's version above." The name field defaults to
<name>-2. When the same-name plugin comes from a marketplace, the upload showed no dialog at all. (n=1 each.)
Disabling the marketplace copy in Customize fixed it: one menu entry, and the private copy loaded (n=1, local).
For comparison, a cloud session in the same org, with an Organization-library clash: the first menu entry loaded the private copy (n=1). Only the private copy was found in that container, though, so that run doesn't show whether both copies were delivered there.
What Should Happen?
Either refuse or rename a same-name upload consistently across both routes, or let the user tell the copies apart: label the menu entries by source (Local upload / Organization library / marketplace name), and make the chosen entry load that copy.
Error Messages/Logs
# None. The wrong copy loads silently.
Steps to Reproduce
- In an org, install plugin
my-pluginfrom a marketplace (version A) and enable it. Give its skill a line that prints the version, e.g.cat "${CLAUDE_PLUGIN_ROOT}/.claude-plugin/plugin.json". - Customize → Plugins → Upload a zip of a plugin with the same
nameinplugin.json, version B. (No dialog appears.) - Customize → Plugins now lists both, both enabled.
- Start a new local Cowork task. Type
/and part of the skill name: two identical entries appear. - Pick the first entry and send. Check which version the skill prints.
- Start another new task, pick the second entry, and check again. In our run both printed version A.
Claude Model
Not model-related: the copy is chosen before the model runs.
Is this a regression?
I don't know
Claude Code Version
Agent 2.1.286, as staged by Claude Desktop 2.19675.0 (5706e5) for macOS. The agent version in the cloud container is not known.
Platform
Anthropic API (Claude subscription: Team plan)
Operating System
macOS
Terminal/Shell
Other: Claude Desktop app (Cowork)
Additional Information
- Team org: one local session (marketplace clash, n=2 tasks, disk-checked) and one cloud session (Organization-library clash, n=1).
- Related: #95107 (the menu and the runner read different copies of a plugin), #94309 (a typed
/plugin:skillwithout the picker gives "Unknown skill"; we saw that here too, with and without a duplicate, so it is left out of this report).