MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / scanCodexPlugins

Function scanCodexPlugins

packages/plugins/mcp/src/sdk/codex-plugins.ts:388–453  ·  view source on GitHub ↗
(options?: {
  readonly codexHome?: string;
  /** Explicit `codex` CLI path (tests); default resolves PATH + fallbacks. */
  readonly codexCli?: string;
})

Source from the content-addressed store, hash-verified

386 * as scanned and spawned directly.
387 */
388export const scanCodexPlugins = (options?: {
389 readonly codexHome?: string;
390 /** Explicit `codex` CLI path (tests); default resolves PATH + fallbacks. */
391 readonly codexCli?: string;
392}): readonly CodexPluginEntry[] => {
393 const codexHome =
394 options?.codexHome ?? process.env["CODEX_HOME"] ?? path.join(os.homedir(), ".codex");
395
396 const codexCli = resolveCodexCli(options?.codexCli);
397 const computerUseApp = isExecutableFile(clientBinaryPath(codexHome));
398 const browserClient = browserClientPath(codexHome);
399 const chromePlugin = isReadableFile(browserClient);
400
401 /** Each curated card states what it needs; the `codex` CLI is required by
402 * all of them because every one is reached through `codex app-server`. */
403 const requirementMet: Record<CuratedCodexPlugin["requires"], boolean> = {
404 "computer-use-app": computerUseApp,
405 "chrome-plugin": chromePlugin,
406 codex: true,
407 };
408
409 const curated: readonly CodexPluginEntry[] = CURATED_CODEX_PLUGINS.map((entry) => {
410 const display = curatedDisplayMetadata(codexHome, entry.pluginName);
411 const available = codexCli !== undefined && requirementMet[entry.requires];
412 return {
413 id: entry.id,
414 name: entry.name,
415 summary: entry.summary,
416 available,
417 slug: entry.slug,
418 source: "curated" as const,
419 command: codexCli ?? "codex",
420 args: ["app-server"],
421 env: { CODEX_HOME: codexHome },
422 appServer: {
423 server: entry.server,
424 ...(entry.surface === undefined ? {} : { surface: entry.surface }),
425 ...(entry.surface === "browser" ? { modulePath: browserClient } : {}),
426 },
427 ...(available
428 ? {}
429 : { setupHint: setupHint(entry.requires, entry.name), setupUrl: setupUrl(entry.requires) }),
430 fallbackIcon: entry.publicIcon ?? "https://integrations.sh/logo/openai.com",
431 ...display,
432 };
433 });
434
435 const cacheDir = path.join(codexHome, "plugins", "cache");
436 const scanned = listDirs(cacheDir).flatMap((sourceName) => {
437 const sourceDir = path.join(cacheDir, sourceName);
438 return listDirs(sourceDir)
439 .filter((pluginName) => !CURATED_PLUGIN_NAMES.has(pluginName))
440 .flatMap((pluginName) =>
441 scanCachedPlugin(codexHome, path.join(sourceDir, pluginName), pluginName),
442 );
443 });
444
445 // One card per id: the same plugin can appear under several cache sources

Callers 1

Calls 12

setupHintFunction · 0.90
setupUrlFunction · 0.90
resolveCodexCliFunction · 0.85
isExecutableFileFunction · 0.85
clientBinaryPathFunction · 0.85
browserClientPathFunction · 0.85
isReadableFileFunction · 0.85
curatedDisplayMetadataFunction · 0.85
listDirsFunction · 0.85
scanCachedPluginFunction · 0.85
valuesMethod · 0.80
setMethod · 0.65

Tested by

no test coverage detected