MCPcopy Create free account
hub / github.com/claude-code-best/claude-code / pluginListHandler

Function pluginListHandler

src/cli/handlers/plugins.ts:147–419  ·  view source on GitHub ↗
(options: {
  json?: boolean
  available?: boolean
  cowork?: boolean
})

Source from the content-addressed store, hash-verified

145
146// plugin list (lines 5217–5416)
147export async function pluginListHandler(options: {
148 json?: boolean
149 available?: boolean
150 cowork?: boolean
151}): Promise<void> {
152 if (options.cowork) setUseCoworkPlugins(true)
153 logEvent('tengu_plugin_list_command', {})
154
155 const installedData = loadInstalledPluginsV2()
156 const { getPluginEditableScopes } = await import(
157 '../../utils/plugins/pluginStartupCheck.js'
158 )
159 const enabledPlugins = getPluginEditableScopes()
160
161 const pluginIds = Object.keys(installedData.plugins)
162
163 // Load all plugins once. The JSON and human paths both need:
164 // - loadErrors (to show load failures per plugin)
165 // - inline plugins (session-only via --plugin-dir, source='name@inline')
166 // which are NOT in installedData.plugins (V2 bookkeeping) — they must
167 // be surfaced separately or `plugin list` silently ignores --plugin-dir.
168 const {
169 enabled: loadedEnabled,
170 disabled: loadedDisabled,
171 errors: loadErrors,
172 } = await loadAllPlugins()
173 const allLoadedPlugins = [...loadedEnabled, ...loadedDisabled]
174 const inlinePlugins = allLoadedPlugins.filter(p =>
175 p.source.endsWith('@inline'),
176 )
177 // Path-level inline failures (dir doesn't exist, parse error before
178 // manifest is read) use source='inline[N]'. Plugin-level errors after
179 // manifest read use source='name@inline'. Collect both for the session
180 // section — these are otherwise invisible since they have no pluginId.
181 const inlineLoadErrors = loadErrors.filter(
182 e => e.source.endsWith('@inline') || e.source.startsWith('inline['),
183 )
184
185 if (options.json) {
186 // Create a map of plugin source to loaded plugin for quick lookup
187 const loadedPluginMap = new Map(allLoadedPlugins.map(p => [p.source, p]))
188
189 const plugins: Array<{
190 id: string
191 version: string
192 scope: string
193 enabled: boolean
194 installPath: string
195 installedAt?: string
196 lastUpdated?: string
197 projectPath?: string
198 mcpServers?: Record<string, unknown>
199 errors?: string[]
200 }> = []
201
202 for (const pluginId of pluginIds.sort()) {
203 const installations = installedData.plugins[pluginId]
204 if (!installations || installations.length === 0) continue

Callers 1

runFunction · 0.85

Calls 15

setUseCoworkPluginsFunction · 0.85
logEventFunction · 0.85
loadInstalledPluginsV2Function · 0.85
getPluginEditableScopesFunction · 0.85
loadAllPluginsFunction · 0.85
parsePluginIdentifierFunction · 0.85
loadPluginMcpServersFunction · 0.85
getPluginErrorMessageFunction · 0.85
getInstallCountsFunction · 0.85
createPluginIdFunction · 0.85

Tested by

no test coverage detected