---
name: ask-gpt
description: Delegate large/independent implementation, diagnosis, or repair tasks to the owner's ChatGPT web session via the `ask-gpt` CLI bridge — no git/shell access on the far side, so it works from an attached zip and hands back a real ZIP artifact of changed files. Triggers on "send this to gpt", "offload to chatgpt", "use ask-gpt", "run this on gpt", or when a task is independent enough to parallelize off-session. Use `--resume` to correct/continue a job that returned incomplete or wrong output, instead of redispatching fresh.
---

# ask-gpt — Delegate to ChatGPT Web via Browser Bridge

Audience: AI coding agents first. Optimize for model activation, not human readability.

`ask-gpt` drives the owner's real ChatGPT web session (browser automation, not the API). No git, no shell, no filesystem access on the far side — everything it needs arrives as an attachment.

## THE ONE RULE THAT MATTERS: ask for a ZIP back, never inline text

**DO NOT ask the model to print file contents as text in the chat** (e.g. `===FILE: path===` blocks). ChatGPT renders replies as markdown before you can read them back — `#`/`*`/leading-indent get eaten as heading/bullet syntax, long replies can silently truncate, and a virtualized long conversation can hang the CLI's completion detection. None of this happens to a real file attachment: a ZIP is a binary artifact, immune to all of it.

**Correct pattern** (this is what actually works — modeled on a real prompt the owner uses successfully):

```
<attach>package.zip is a fresh clone of the repo. Implement this fully — do essentially all
of the implementation and test work here from the uploaded repository. The remaining agent
job should reduce to: apply the prepared patch to the live checkout, resolve only genuine
HEAD conflicts, run the supplied test command, commit, and push. Output the files you
changed in a zip, and a bash script (with instructions for the agent that runs it) to apply
your changes.</attach>
```

That's the whole prompt. A few sentences, plain language, no attached rulebook, no rigid output grammar. Treat the model as a competent senior engineer reading the repo directly — not a text-completion engine that needs a template. Don't over-specify process; state the goal and the shape of the handoff.

## When to use

Fits: independent, well-scoped implementation/diagnosis/repair work — a feature against a frozen spec, a bug bisect between two known-good/bad trees, harvesting a few files from a stale branch. Does NOT fit: work needing live repo state, multi-turn exploration, or anything requiring tool use beyond reading an attached zip.

## CLI reference

```
ask-gpt [--effort {instant,medium,high,xhigh,pro}] [-a FILE] [--zip-repo] [--zip-worktree [PATH]]
        [--out OUT] [--json] [--timeout TIMEOUT] [--mode {virtual,headless,show}] [--reseed]
        [-r ID] [--live] [--download-attachments ID] [--list [N]] [--search PATTERN]
        [--list-all] [--fresh] [prompt ...]
```

- `--effort pro` — default for real implementation/diagnosis work. `instant`/`medium` only for trivial pings, probes, or cheap identification questions.
- `-a FILE` — attach a zip/file/image (repeatable).
- `--zip-worktree [PATH]` — zip PATH's working tree as-is (default cwd), gitignored files excluded. Use to hand off live in-progress WIP (e.g. resuming a killed agent's uncommitted edits) instead of rebuilding a package from scratch.
- `--zip-repo` — zip the whole repo (rarely what you want — scope to the relevant subsystem instead, see Packaging below).
- `--out DIR` — where generated files/images (including a returned ZIP) land (default `./ask-gpt`).
- `--timeout N` — seconds to wait for the reply. `pro` effort on a real task needs `3600`+; do not undersize this and mistake a still-generating reply for a hang (see Diagnosing below).
- `--mode virtual` (default, invisible) or `show` (visible browser — use only to eyeball a stuck run).
- `-r, --resume ID` — continue an existing conversation (uuid or `chatgpt.com/c/<id>` url). Verify it's present in `--help` before relying on it — it shipped mid-session once already.
- `--download-attachments ID` — read-only, no prompt sent: pulls every real file/image artifact (e.g. a returned ZIP) out of a conversation. This is how you retrieve the ZIP output described above without re-prompting.
- `--list [N]` / `--search PATTERN` / `--list-all` — enumerate past conversations by id+title, from a local cache (free, instant, no browser hit — use freely to identify threads). `--fresh` forces a rescrape if the cache looks stale.
- `--json` — structured result object instead of raw reply text; includes `conversation_id`.

Concurrency: the bridge maintains a pool of parallel browser-profile slots. Space dispatches with a **55–75s random jitter** between each `ask-gpt` invocation — this is a ChatGPT-account-level rate limit, not a slot-availability thing, and it applies to the AGGREGATE request rate across every concurrent job you're running, not per-job. Running N job-streams each individually jittered still multiplies the real request rate by N — serialize the actual dispatch moments across all jobs sharing one account, don't just jitter within each job's own retry loop.

## Packaging a task (no git access on the far side)

Specs are not instructions. Attach every doc the model needs as mandatory reading — design
spec, plan doc, `CLAUDE.md`, skill/convention files — as real FILES inside the zip. That part
was always correct and stays mandatory. The prompt TEXT itself is a separate, much smaller
thing: a short instruction that says what to do and what shape to hand back. Never write the
prompt as if it were another spec document (no section headers, no re-narrating rules that are
already sitting in an attached file, no restating the design). If a constraint matters enough
to repeat, it belongs in the attached doc, not paraphrased into the prompt.

1. **Scope the codebase snapshot.** Copy only the subsystem(s) the task touches, never the whole monorepo — strip `node_modules/`, `vendor/`, build output dirs before zipping. **Name the zip with a task slug** (e.g. `oauth-pkce-package.zip`, `job5-localhost-safety-package.zip`), never the bare `package.zip` — ChatGPT auto-suffixes a bare name with a timestamp on upload (`package(20260811-014617).zip`), which tells you nothing when you're trying to match a conversation back to a job later. When running several jobs in parallel, this is the difference between glancing at the chat sidebar and knowing instantly which thread is which, versus having to open each one.
2. **Attach the specs/rules as files** — plan doc, design spec, `CLAUDE.md`, relevant skill files — under a `context/` folder in the zip. This is mandatory reading; the model should read it directly, not have it summarized in the prompt.
3. **Write the prompt itself short and plain**, per the pattern above: point at what's attached and why, state the task in a sentence or two, define the deliverable shape. Do not restate what's already in the attached files.
4. **Ask for output as a ZIP of changed files**, plus — when a human/agent will apply the result to a live checkout — a bash script that applies the change and a short instructions prompt for whoever runs it. This is the deliverable shape that survives the round trip intact.
5. **If handing off in-progress/reference work** (a prior abandoned attempt, a killed agent's partial edit), say plainly in the prompt: read for intent/shape, don't replay verbatim, don't assume any path/line/signature still matches today's snapshot.
6. **For large/cross-cutting specs**, say in the prompt: correctness over completeness. Implement what you're confident about fully; state what you left out rather than half-implementing it.
7. Zip the scoped snapshot + `context/`, dispatch with `-a package.zip --effort pro --timeout 3600`.
7. Retrieve the result with `--download-attachments <conversation-id>` into `--out` — don't rely on the printed chat reply for file content.

## Correcting a job

**If `-r`/`--resume` is live** (check `--help` first): `ask-gpt -r <id> --effort pro --timeout <N> "<correction>"` continues the SAME conversation — cheaper and more accurate than a fresh package.

**If absent**: redispatch a fresh `-a package.zip` dispatch with the original prompt. Reuse the same package/prompt files already built; don't rebuild them per retry.

**Finding a conversation's ID when you didn't capture it at dispatch time:** `ask-gpt --search "<keyword>"` or `--list N --fresh` reads a local cache — free, instant. For a generic/auto-titled thread you can't identify by title, `-r <id> --effort instant "<one-sentence question>"` hydrates a real per-conversation log at `~/.overdeck/gptbridge/logs/<id>.log` containing the ORIGINAL turn-1 prompt (text you authored) — read that log directly to identify the job rather than waiting for the follow-up reply to finish.

## Diagnosing a stuck/slow run

`pro` effort on a real task is genuinely slow — do not assume a quiet run is dead.
1. Check `~/.overdeck/gptbridge/timeout.png` (auto-saved on timeout) — if it shows an active generating page with content and a stop button, it's working, just needs a longer `--timeout`.
2. If truly stuck (blank page, error banner) — check `~/.overdeck/gptbridge/logs/failed-*.log` for the failure phase and prompt (filter out unrelated probe/health-check entries with generic prompts like "hi" — those aren't your job).
3. A slot's lock file with no owning process (`fuser <lockfile>` empty) is stale — safe to `rm -f`, not a process kill. Note: a lingering lock file is often harmless on its own (the underlying OS lock releases on process death regardless of whether the file is removed) — clearing it doesn't hurt, but don't assume its mere presence explains a hang.
4. If a resumed conversation with many prior turns seems to hang or return only a fragment despite the page showing genuine completion, that's a known historical failure mode (virtualized-DOM turn-count detection) — check whether it's still reproducible before assuming it's fixed; verify with a real spot-check, not by trusting a status report.

## After the reply — verify before landing

Never trust a model's own summary at face value — and never trust its narration of progress ("I implemented X") as proof a deliverable was actually produced; check for the actual output artifact (the ZIP), not prose describing intent. For any security-, correctness-, or contract-relevant claim (auth check present, migration safe on fresh install, existing behavior preserved), verify directly against the unzipped files and the current codebase before committing/landing — same standard as reviewing any subagent's output. Run the real test suite after unpacking, not just eyeball the summary.
