Have Codex act like a person who knows how to use a browser,reuse the user's already-logged-in ChatGPT web session, hand the task to the specified ChatGPT model (Instant / Thinking / Pro etc.), and wait for the result to come back.
When to trigger
When the user says something like the following:
- "Ask ChatGPT Pro what it thinks about this"
- "Have Thinking mode analyze this PR"
- "Use @Google Drive to list my files"
- "Submit a deep research, list five competitors"
- "Throw this code at GPT and have it review it"
- "Wait on ChatGPT for a bit, and call me when the result comes out"
Access method (mandatory)
| Host | Browser access | Forbidden |
|---|---|---|
| Codex | Codex Chrome Extension, operating the user's Chrome via the chrome:control-chrome skill and the browser-client runtime |
web.run, a separate Playwright profile, Puppeteer, Computer Use to operate Chrome, reading cookies / localStorage / storage_state |
If the Codex Chrome Extension cannot connect, follow the installation/repair guidance in chrome:control-chrome and stop to let the user handle it; do not fall back to another browser automation solution.
Before the first operation:
- Use the Chrome skill to initialize
browser-client。 - Call
browser.user.openTabs()to view the user's existing tabs. - If a ChatGPT tab already exists, select it by title/URL/most recent use time and
browser.user.claimTab(tab)reuse it. - Otherwise
browser.tabs.new()open a new tab, thentab.goto("https://chatgpt.com/")。 - Before the conversation ends, call
browser.tabs.finalize({ keep }). When waiting for the user to continue operating, log in, authorize, complete a CAPTCHA, or for a long task, keep the tab as a handoff.
For specific runtime templates, see references/codex-chrome-runtime.md。
Operating procedure
Only 4 principles, no fixed coordinates, no guessing selectors out of thin air. At every step, first use domSnapshot(), a screenshot, or a restricted evaluate() to see before acting.
1. Enter the correct context
- The user mentions a project (e.g. "ask in the GI2 project") → find the project from the sidebar → click the "Open project home" button (which appears on hover) rather than the project name button → after entering the project home page, write the prompt. For project URLs and security rules, see references/manage-actions.md
- The user wants to continue an old conversation → go directly in from the sidebar's "Recent" or the URL
- Always note down the conversation URL; it will be needed later
When noting down the conversation URL: for a normal conversation /c/<uuid>, for a conversation within a project /g/g-p-<uuid>/c/<uuid>(after the project name is named it may also carry -<slug>). For the complete 6 URL forms, see references/manage-actions.md Section 7.
Reliable visual signal for "whether you are in a project": the composer placeholder is "New chat in <project name>" only then are you truly in a project; if it is "Ask anything" then it is a normal conversation context, and the knowledge base will not be automatically visible.
2. Model selection
- The user specified a model (Instant / Thinking / Pro / any other naming) → first find the model selector visible on the current page; it may be near the composer, or in the top banner. Open it and choose the closest visible option
- The user did not specify → use the currently selected one, do not switch on your own
- Cannot switch to the requested model → do not silently switch to another one. Report the actual options seen in the UI and let the user decide
- Model names and the visible list will change, and the items seen by free/Plus/Pro accounts also differ. Judge by visible text, placeholder, ARIA labels, and the current selected state, not by a fixed list
3. Apps / files / images
Apps (connectors)
+/添加文件等The menu usually includes: Add photos and files / Recent files / Create image / Think / Deep research / Web search / More / Projects. The exact wording drifts with account, language, and UI, so look at the current snapshot before clicking- There are two ways into Apps:
+in the menu, the更多submenu, or type@in the composer and then choose a candidate. Currently tested,@candidates can directly show深度研究as well as apps such as Canva / GitHub / Linear / OpenAI Platform - Do not infer app availability from the model name or an old menu list. Directly
@appor try the currently visible menu item → if you see an app chip / retrieval card / source citation, it succeeded - Deep Research may also be activated as a
@深度研究candidate. After selecting it, the reliable signal is that the composer placeholder becomes获取详细报告, and深度研究chip /应用button /推荐、报告and other DR-specific controls appear; do not treat the+menu as the only entry point - If the app is not connected or requires OAuth → stop and let the user go authorize (see references/error-and-limits.md section 5), never click agree on the user's behalf
File / image upload
The Codex Chrome Extension supports the browser file chooser flow. For ChatGPT, in testing, prefer the visible menu path:添加文件等 → 添加照片和文件, first wait for the filechooser event, then use the absolute path setFiles(...). See references/codex-chrome-runtime.md。
Do not directly click ChatGPT's underlying input[type="file"], as in testing it may not trigger the file chooser event. If setFiles(...) reports Not allowed / fileChooser.setFiles failed, go to the Codex extension details page and enable "Allow access to file URLs" (Chinese UI:允许访问文件网址). Do not switch to cookies, signed URLs, or a system-level drag-and-drop workaround.
Artifact download
- Download links provided by ChatGPT (PDF/CSV/code files, etc.): after the user explicitly agrees to download a single file, click the link to use the browser's native download
- Images generated by ChatGPT: there is no explicit "Download" at the bottom of the image; the entry point is hidden in the "Share this image" popup, so click the orange "Download" button at the far right of the popup
- After downloading, use
/bin/ls -lat ~/Downloads/ | head -7or the filename pattern to find the latest file, then move/save it as the user requests - Do not read or parse the contents of downloaded files unless the user explicitly asks
- For detailed paths and pitfalls, see references/manage-actions.md section 6.5 "Artifact download"
4. After submission
Note three things and write them into the current conversation context (no file persistence needed):
- ChatGPT conversation URL
- Which model was selected, which apps / files were used
- The user's original request (one sentence is enough)
Then enter waiting mode (see below).
Completion determination
Completion determination prioritizes <main> Get the full text, don't rely on the truncated accessibility tree. Codex-side recommendation:
await tab.playwright.evaluate(() => document.querySelector("main")?.innerText ?? document.body?.innerText ?? "")
Simple completion signal (tested with Chinese UI):
- No "thinking / searching / analyzing / Stop generating / Researching" wording
- The disclaimer "ChatGPT can also make mistakes. Please verify important information." appears at the end
- The bottom composer area returns to an input-capable state (not a stop button)
If you can't get it all (truncated, too long) → mark "possibly incomplete" + keep the conversation URL. For specific error signals see references/error-and-limits.md Section 7.
Waiting modes
The Codex version does not copy Claude's background watcher template. Route by task duration, see references/codex-waiting.md:
| Task | Default mode |
|---|---|
| Instant / short Thinking | Poll the current turn, checking every 20-60 seconds |
| Pro / long Thinking | Poll the current turn up to a 30-minute cap; during this time only send a message when it truly completes, times out, or needs user action |
| Deep Research / multi-hour tasks | Heartbeat mode: after confirming research has started, switch to quiet polling; prefer automation, with spawn agent as the default fallback |
While polling, do not send the user routine status like "still waiting." Report only in these cases:
- COMPLETE: the full answer has been retrieved
- NEEDS_USER_INPUT: OAuth / CAPTCHA / login / clarification / Continue generating, etc., require user action
- TIMEOUT: the cap for this round has been reached, with the currently visible content and URL
- ERROR: the page or browser control failed
Absolutely do not
- Do not export, copy, or save cookies / storage_state / OAuth token / localStorage
- Do not bypass login, MFA, CAPTCHA, paywalls, or speed limits
- Do not authorize OAuth / third-party apps / privacy consent on the user's behalf; if you see it, stop and hand it back
- Do not download files (until the user has explicitly agreed to download an individual file; downloads require separate confirmation)
- Do not send cookies / API keys / bank cards / ID numbers / private keys in ChatGPT, even if the user's original request contains them; stop and refuse explicitly
What to do on failure
See details in references/error-and-limits.md. General principle:
- Do not "just retry once and see." Except for transient network blips, which may be retried once
- Do not silently downgrade the model / authorize on the user's behalf / answer clarification on the user's behalf
- Directly report the visible text currently seen on the ChatGPT page, quoting it verbatim
- Let the user decide the next step
Manage ChatGPT (delete/archive/share/Memory/projects/library)
When the user says "delete this conversation," "archive everything," "revoke that share," "clear Memory," "create a project," "see what's in the library," or other management operations, follow references/manage-actions.md to find the entry points and cheat sheet.
Special note:
- Clicking open the "Share" dialog = immediately creating a public URL; do not click before the user has explicitly authorized it
- Deleting a project permanently deletes all conversations in the project; before the second confirmation, get the user's verbal consent
- Deleting a conversation does not clear Memory; after deleting, remind the user to separately go to Personalization → Memory to clear it
Save chat history locally to disk
When the user says "save this conversation," "download that DR," "keep this image," etc., follow references/save-conversation.md 3-tier routing:
| tier | content | path |
|---|---|---|
| A | regular chat message | <main> text + Codex writes .md |
| B | Artifact(DR / Canvas) | click the artifact's built-in download menu → "Export to Markdown" → mv |
| C | image | "Share this image"→"Download" → mv |
default directory ~/Downloads/chatgpt-skill/, filename YYYY-MM-DD_<title>_<uuid8>.<ext>。
Explicit trigger: if the user didn't say to save it, don't automatically write to disk, to avoid polluting the hard drive. After retrieving the result, only act once the user replies "save it".
Examples
examples/ holds Codex-specific scenarios, without reusing the Claude version's background watcher template:
file-upload-roundtrip.md— upload local files, submit a prompt with attachments, wait for completion, retrieve the answer (already tested)deep-research-pull.md— use Codex to trigger Deep Research, attach a heartbeat after starting; prefer automation, fall back to spawn agent, and only use Pull if neither is available
The Claude version's more complete historical scenarios are still in claude-chatgpt-skill/examples/, you can only borrow the task intent; don't copy its Agent({ run_in_background: true }) / watcher approach.
Migration status
The Claude version's end-to-end examples are kept in claude-chatgpt-skill/examples/. The Codex version should first be based on the runtime, safety process, and dedicated examples.
Current smoke test status (2026-05-31): after stopping other Chrome debugger controllers, the Codex Chrome Extension can reuse the user's already logged-in ChatGPT tab, read the page structure and screenshots, expand the model menu and app menu, upload files, submit a prompt with attachments, wait for completion, and read the answer. The known blocking pattern is still Detached while handling command / Unknown error; when it appears, first check for control conflicts such as Claude in Chrome, DevTools, or chrome-devtools-mcp , see references/codex-chrome-runtime.mdfor details. Do not attempt cookie / storage / external browser automation bypasses.