Plugin discovery, load, and registration
Overview
The whitelisted source does not contain a .claude/plugins directory scanner, manifest parser, capability gate, or tool-registration path for user plugins . What is visible is marketplace-entry loading, MCPB bundle loading, and delisted-plugin cleanup, which together only cover part of the question .
Steps
- Plugin discovery in this codebase is driven by marketplace entries rather than a raw
.claude/pluginsdirectory walk, withloadPluginFromMarketplaceEntryresolving each entry's source to a concretepluginPath. Local string sources are validated viapathExistsand then copied into a versioned cache, while external sources (npm, github, url, pip) route throughcachePlugin. cachePlugincreates the plugin cache directory withmkdir, generates a temp name viagenerateTemporaryCacheNameForPlugin, and dispatches on source kind toinstallFromLocal,installFromNpm,installFromGitHub,installFromGit, orinstallFromGitSubdir. Git-based installs go throughvalidateGitUrlandgitClone, runninggitviaexecFileNoThrow.installFromLocalverifies the source withpathExists, usescopyDirto stage files, and strips the nested.gitdirectory viarm.installFromNpminvokesnpm installthroughexecFileNoThrowinto a shared npm cache and thencopyDirs the package .- For MCPB-packaged plugins,
loadMcpbFilereads or extracts the archive, parsesmanifest.json, and — ifmanifest.user_configis non-empty — checks saved config viavalidateUserConfig, returning aneeds-configresult when required fields are missing . On success it produces anMcpbLoadResultcarrying manifest, generatedmcpConfig, andextractedPath. - The UI-side save path in
ManagePluginsre-invokesloadMcpbFilewith the user-suppliedUserConfigValuesto complete the capability/config gate before the plugin becomes usable . Uninstall flows go throughdoUninstall→uninstallPluginOp, and delisted plugins are swept bydetectAndUninstallDelistedPlugins. - At runtime, deferred plugin installation is awaited inside
run(bounded byCLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS), after which arefreshPluginStatecall makes new commands, agents, and hooks visible — this is the closest thing to "registration into the tool set" in the whitelist . Plugin-sourced slash commands are then resolved per-turn bygetCommand/findCommandagainstcontext.options.commandsand dispatched viaprocessSlashCommand→getMessagesForSlashCommand. - Plugin identity for telemetry and marketplace scoping is parsed by
parsePluginIdentifierand classified viaisOfficialMarketplaceName, withbuildPluginCommandTelemetryFieldsattaching fields when a plugin-sourced command is invoked . - The precise steps for scanning
.claude/plugins, validating a plugin manifest schema, checking declared capabilities, and inserting the plugin's tools into the activeToolsarray are not present in the whitelisted source, so the exact discovery→capability-check→tool-registration chain cannot be cited here .
State touched
- — filesystem operations used by
mkdir,rm,statduring install
Decisions
None of the whitelisted decision tokens apply to this flow .