// --------------------------------------------------------------------------- // Curated Codex plugin metadata — the isomorphic half of Codex plugin // discovery. The names and summaries here are BOTH the searchable catalog // presets (presets.ts, bundled client-side) and the curated entries the // node-only scanner reports (codex-plugins.ts), so the two can never drift. // Keep the summaries carrying the words people actually search for // ("iMessage", "texts", "computer use", "screen activity"). // --------------------------------------------------------------------------- export interface CuratedCodexPlugin { /** Card/preset id, e.g. `codex-messages`. */ readonly id: string; /** The Codex plugin name in the plugin cache. */ readonly pluginName: string; readonly name: string; /** Suggested integration slug, e.g. `codex_messages`. */ readonly slug: string; /** The MCP server name this plugin registers inside Codex — the `server` * the app-server bridge calls tools against. */ readonly server: string; /** A public image for this plugin, used when the machine-local icon cannot * be read (i.e. Codex is not installed here). Only some plugins have one * published; the rest fall back to the provider's mark. */ readonly publicIcon?: string; /** Present when the plugin has no MCP server of its own and its API is * projected onto another one. Computer Use and Chrome both ship as * skills/`node-repl` content: Codex never starts a server for either, and * their APIs are driven through `node_repl` — see `codex-sky-tools.ts` and * `codex-browser-tools.ts`. */ readonly surface?: "sky" | "browser"; /** What must exist on disk for this card to be usable, beyond the `codex` * CLI itself. `computer-use-app` is the shared Codex Computer Use app; * `chrome-plugin` is the Chrome plugin's bundled browser client; `codex` * means the CLI alone is enough (a server Codex always carries). */ readonly requires: "computer-use-app" | "chrome-plugin" | "codex"; readonly summary: string; } /** What to do when a card is not usable yet. * * Written as numbered steps rather than one sentence: a person reading this * has just been told they cannot proceed, and the useful answer is the * shortest ordered path to being able to. Each step names where to go, and * the last one says to come back — otherwise the card is a dead end. The * plugin's own name is substituted in, so the instruction is about the thing * the person clicked rather than about plugins in general. */ export const setupSteps = ( requires: CuratedCodexPlugin["requires"], name: string, ): readonly string[] => { const install = "Install the Codex app from openai.com/codex, then sign in."; const finish = "Come back here and add it."; if (requires === "codex") return [install, finish]; if (requires === "chrome-plugin") { return [ install, "In Codex, open Settings \u2192 Computer use and install the ChatGPT browser extension.", "Use Chrome once inside Codex, so it can reach your browser.", finish, ]; } return [ install, `Open ${name} once inside Codex. macOS asks for its permissions the first time \u2014 Full Disk Access, Contacts, and Automation.`, finish, ]; }; /** The steps as one string, for the wire and for plain-text surfaces. */ export const setupHint = (requires: CuratedCodexPlugin["requires"], name: string): string => setupSteps(requires, name) .map((step, index) => `${index + 1}. ${step}`) .join("\n"); /** Where a person goes to get what a card needs. * * Linked rather than only described: a card that cannot be used is a dead end * unless it hands over the next step. Chrome's own requirement is documented * on the Computer Use page, so it points there instead of the app download. */ export const setupUrl = (requires: CuratedCodexPlugin["requires"]): string => requires === "chrome-plugin" ? "https://learn.chatgpt.com/docs/computer-use" : "https://openai.com/codex"; export const CURATED_CODEX_PLUGINS: readonly CuratedCodexPlugin[] = [ // Names are exactly the plugins' own displayNames — nothing invented, no // provenance suffix. Codex provenance shows in the summaries and on the // focused add screen; search keywords people type ("imessage", "apple", // "texts") live in the summaries. { id: "codex-messages", pluginName: "messages", name: "Messages", slug: "codex_messages", // Served by the app itself (`packages/app/public`), because the Messages // app icon is published nowhere hotlinkable: it is a system app, absent // from the App Store artwork API, and `messages.apple.com` resolves to // the plain Apple mark. Root-relative, so local and cloud both serve it. publicIcon: "/plugin-icons/messages.webp", requires: "computer-use-app", server: "messages", summary: "Read, search, and send iMessage/SMS texts through Apple's Messages app on this Mac, via the Codex plugin. Reads and sends are approved in its native dialogs.", }, { id: "codex-computer-use", pluginName: "computer-use", name: "Computer Use", slug: "codex_computer_use", publicIcon: "https://learn.chatgpt.com/images/codex/icons/computer-use-plugin-icon.png", requires: "computer-use-app", server: "node_repl", surface: "sky", summary: "Control macOS desktop apps via the Codex plugin: read the screen and accessibility tree, click, type, and scroll.", }, { // Chrome is skills-only: its API is the bundled `browser-client.mjs`, // driven through `node_repl` exactly as Computer Use drives `@oai/sky`. id: "codex-chrome", pluginName: "chrome", name: "Chrome", slug: "codex_chrome", publicIcon: "https://learn.chatgpt.com/images/codex/icons/chrome-production-large.png", server: "node_repl", surface: "browser", requires: "chrome-plugin", summary: "Control the Chrome browser on this Mac through the Codex plugin: open tabs, navigate to a URL, read the page, click, and type. Uses your real Chrome, with its logged-in sessions.", }, { // A server Codex carries itself — no plugin app, no local binary beyond // the CLI. id: "codex-openai-docs", pluginName: "openai-developers", name: "OpenAI Developer Docs", slug: "codex_openai_docs", server: "openaiDeveloperDocs", requires: "codex", summary: "Search and read OpenAI's developer documentation and API reference, including OpenAPI specs and endpoint listings, via the Codex plugin.", }, { id: "codex-computer-history", pluginName: "computer-history", name: "Computer History", slug: "codex_computer_history", requires: "computer-use-app", server: "computer-history", summary: "Ask about recent on-screen activity from Codex's private local record (requires Computer History enabled in Codex).", }, ]; export const isCodexPresetId = (id: string | undefined): boolean => id !== undefined && CURATED_CODEX_PLUGINS.some((plugin) => plugin.id === id);