MCPcopy
hub / github.com/codeaashu/claude-code / pluginListHandler

Function pluginListHandler

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

Source from the content-addressed store, hash-verified

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