/plugin TUI cannot reliably uninstall plugins; only CLI claude plugin uninstall works end-to-end
Summary
The /plugin TUI is the most visible way users interact with plugins, but its uninstall flow is inconsistent with the working claude plugin uninstall CLI. As a user I have 32 plugins installed at user scope, and no combination of actions inside /plugin actually removes one — the commands and skills keep reappearing after restart. Only dropping to the shell and running claude plugin uninstall <name>@<marketplace> actually removes the plugin.
The TUI is also confusing because "Uninstall" and "Disable" appear to be collapsed into a single "remove at user scope" action, which is not how the state actually works.
Environment
- Claude Code CLI (latest as of 2026-04-23)
- macOS (Darwin 25.2.0)
- Single-user machine, all plugins installed at
scope: "user" - 32 plugins from 5 marketplaces registered in
~/.claude/plugins/installed_plugins.json
Steps to reproduce
- Install any plugin, e.g.
claude plugin install searchfit-seo@claude-plugins-official - Open
/pluginin an interactive session - Navigate to the plugin and choose the remove option
- Exit and restart Claude Code
- Type
/— the plugin's commands are still present; the skill list at session start still includes its skills
Expected
- A clear, distinct "Uninstall" action in
/pluginthat: - Removes the entry from
~/.claude/plugins/installed_plugins.json - Removes the
enabledPluginsflag from both~/.claude/settings.jsonand~/.claude/settings.local.json - Deletes the cached directory at
~/.claude/plugins/cache/<marketplace>/<plugin>/ - Refreshes the session's skill/command registry (or tells the user a restart is required)
- A separate, clearly labeled "Disable" action that only toggles the enabled flag.
Actual
- The TUI shows what appears to be a single "remove at user scope" action.
- After using it, at least one of the four state locations (registry, cache, user-scope flag, local-scope flag) remains dirty, so the plugin re-appears on the next session.
- The
enabledPluginsentry insettings.local.jsonis especially easy to miss — a plugin disabled at user scope but enabled insettings.local.jsonsilently re-enables itself. - There is no in-TUI indication that a restart is required, so the uninstall looks like it silently failed even when it partially succeeded.
Workaround
Run this from the shell instead — it works correctly every time:
\\\bash\
claude plugin uninstall <name>@<marketplace>
\\
Example: \claude plugin uninstall searchfit-seo@claude-plugins-official\
This makes the TUI/CLI asymmetry the core bug: the CLI already does the right thing, the TUI should call the same code path.
Proposed fix
- In \
/plugin\, split "Uninstall" and "Disable" into two separate actions with distinct labels. - Route "Uninstall" through the same code path as \
claude plugin uninstall\, including the cache deletion and clearing of \enabledPlugins\flags in both \settings.json\and \settings.local.json\. - After uninstall, either hot-reload the session's skill/command registry, or surface a banner: \
Uninstalled <name>. Restart Claude Code to clear loaded skills and commands.\ - Consider surfacing \
settings.local.json\overrides in the TUI — they're currently invisible and cause the "why did this plugin come back?" class of bug.
Why this matters
Plugins are now the main surface for adding skills and commands, and users install a lot of them. When uninstall doesn't work reliably, the skill list becomes permanently cluttered and users can't trust the UI to manage their own setup. The CLI proves the underlying system works — this is purely a TUI/UX gap.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗