pro-cli does not call the OpenAI API. It puppets a real, logged-in Chrome window over a localhost debug socket — and Chrome is the one that talks to ChatGPT. This manual walks the entire path, with diagrams.
$ pro-cli doctor --json → ready: true
Five actors sit between your keystroke and the Pro answer. Only one of them — Chrome — is allowed to cross the network boundary into the public internet. That single fact is the whole trick.
Your auth lives in ~/.pro-cli/cookies/ as ChatGPT session cookies — not as an API key. There is no API key. The web app's auth model is the auth model.
ChatGPT's frontend assembles request headers, Cloudflare challenges, and websocket sessions from inside the live page. Running them from a real, logged-in Chrome tab keeps the fingerprint identical to a human user.
"pro-cli" sounds like a Pro API client. It isn't. Closer to "a remote control for the ChatGPT tab you already have open."
Two places hold pro-cli on disk. One is the source code & binary (rebuildable). The other — ~/.pro-cli/ — is the irreplaceable state: your session cookies, your sandboxed Chrome profile, and the durable-job database.
The git checkout. Edit it, blow it away, re-clone it — none of that touches your auth. pro-cli update is just git pull --ff-only here plus a re-link.
A symlink Bun's bun link drops into your PATH. Resolves into the Projects clone. That's how typing pro-cli finds it from anywhere.
Your live ChatGPT web session, frozen to disk. 41 cookies across chatgpt.com, auth.openai.com, sentinel.openai.com, etc. Never paste, commit, or share these.
The ChatGPT session token (bearer-ish JWT). Current token expires 2026-05-31; re-capture via pro-cli auth capture when it lapses.
A throwaway Chrome user-data-dir whose only job is to hold the ChatGPT login. Keeping it separate means the open debug port can't snoop your personal browsing.
Async-job ledger. Direct pro-cli ask calls run as transient jobs (temporary: true) and don't persist. pro-cli job create calls do.
A real timeline. The example below is the exact call you just ran — "What's the best way to learn Rust in 2026?" against gpt-5-5-pro, 8,140 characters back, 4 minutes 5 seconds elapsed.
# Figure 3.0 — the one-liner $ pro-cli ask "What's the best way to learn Rust in 2026?" --json → job ask_6ad14479… · model gpt-5-5-pro · reasoning standard · 4m 5s · 8140 chars
The fetch() in step 5 runs inside the ChatGPT page context. That means Chrome auto-attaches the same cookies, CSRF tokens, and frontend headers that the ChatGPT UI would have sent if you'd clicked Send yourself. pro-cli never builds an Authorization header.
Three brittle points: Chrome closes (CDP socket dies on step 3) · session cookies expire (ChatGPT returns 401 on step 6) · the daemon at /tmp/pro-cli-501-…/ can't be reached (only matters for job create, not direct ask). pro-cli doctor covers all three.
Every pro-cli ask is, by default, a Temporary Chat. It consumes Pro quota, returns a real answer, and then evaporates — no sidebar entry, no memory contribution, no thread continuity. That's deliberate.
pro-cli is built for agentic use — scripts, Claude Code, cron jobs. If every call wrote into your real history, your sidebar would fill with bot-junk in a day and ChatGPT's memory would start "learning" from automated prompts. Temporary is the polite default.
Pass --save. The response surfaces a conversationId + messageId you can grab and pass back via --conversation + --parent to thread follow-ups in the same chat.
If you've used the Temporary Chat button on chatgpt.com (the icon next to the model picker), it's the same feature. pro-cli just flips that switch programmatically on every call.
One-shot agent queries → leave it temporary.
Conversations you want to come back to → --save, then thread with --conversation + --parent.
The OpenAI API and pro-cli reach different ChatGPT. The API is the developer surface — clean, billed per token, no Pro models. pro-cli is the consumer surface — your account, your Pro quota, your Deep Research and web search. They aren't substitutes; they're complements.
Two-hop call. Stateless. Your script owns auth. Billed per input/output token. Models capped at the API catalog — no gpt-5-5-pro, no Deep Research, no canvas.
Five-hop call. Only the last hop crosses the public internet. Chrome owns auth. Billed against your ChatGPT plan quota. Full Pro catalog including Deep Research, web search, canvas.
pro-cli isn't a Pro API client.
It's a remote control for the ChatGPT tab you already have open —
and the tab itself is the one making the call.
Five real scenarios. The shape of output below is faithful to pro-cli 0.1.0 (abbreviated for screen size). One thing to internalize: every command emits a JSON envelope to stdout — pipe it to jq, hand it to another agent, store it.
Notice "options.temporary": true — that's why this never showed up in your chatgpt.com sidebar. See § 04.
Run this before anything else. Never burns Pro quota.
Bare integer to stdout by default — prob=$(pro-cli odds "…") just works in shell.
If CDP_UNAVAILABLE persists after relaunch, your ChatGPT session probably expired — sign back in and run pro-cli auth capture --cdp http://127.0.0.1:9222 --json.
The five commands that cover ~95% of usage, plus the two recovery paths for when something snaps.
$ pro-cli doctor --json
Health check. Never consumes Pro quota. Always your first diagnostic.
$ pro-cli ask "…" --json $ pro-cli ask @prompt.md \ --reasoning extended --json
Direct blocking call. Default model gpt-5-5-pro.
$ pro-cli job create \
@prompt.md --wait --json
$ pro-cli job list --json
Persisted in jobs.sqlite, survives terminal exit.
$ pro-cli odds "…?" --json
Calibrated 0–100 probability of YES. Different code path than ask.
$ pro-cli models --json $ pro-cli limits --json $ pro-cli update --json
List models · check plan/usage · fast-forward your local clone.
# relaunch the dedicated profile $ open -na "Google Chrome" --args \ --user-data-dir=~/.pro-cli/chrome-profile \ --remote-debugging-port=9222 \ https://chatgpt.com/ # re-capture if you got logged out $ pro-cli auth capture \ --cdp http://127.0.0.1:9222 --json