
using-ask-question-cli
by johnnymo87
A CLI for headlessly prompting your ChatGPT web UI
SKILL.md
name: Using ask-question CLI description: Send prompts to ChatGPT via browser automation. Use this when you need to query ChatGPT from the command line or integrate with the /ask-question slash command. allowed-tools: [Bash, Read]
Using ask-question CLI
Send prompts to ChatGPT via Playwright browser automation with headless operation.
Architecture
ask-question CLI ──► HTTP POST /ask ──► ask-question-server (daemon)
│
▼
Chromium (headless)
+ storageState session
│
▼
ChatGPT response
Prerequisites
- Node.js installed
- Playwright with Chromium (
npm installdownloads it) - npm link run in the chatgpt-relay directory
Setup (One-Time)
cd ~/Code/chatgpt-relay
npm install
npm link
ask-question-login # Opens browser, log into ChatGPT
Starting the Daemon
cd ~/Code/chatgpt-relay
npm run server:log
Keep this running in a dedicated terminal or tmux pane. It runs headless (no visible browser).
Why tee to a log file? This allows Claude Code to check logs via tail ~/.local/state/chatgpt-relay/daemon.log even when the daemon runs in a separate terminal.
Expected output:
[ask-question-server] Starting headless browser...
[ask-question-server] Using session: ~/.chatgpt-relay/storage-state.json
[ask-question-server] ChatGPT page opened.
[ask-question-server] Login verified.
[ask-question-server] HTTP server listening on http://127.0.0.1:3033
Usage
Direct prompt
ask-question "What is the capital of France?"
From file
ask-question -f question.md -o answer.md
Pipe input
echo "Explain async/await in JavaScript" | ask-question
Options
| Option | Description |
|---|---|
-f, --file <path> | Read prompt from file |
-o, --output <path> | Write response to file |
-t, --timeout <ms> | Response timeout (default: 1200000 / 20 min) |
--continue | Continue existing chat (default: start new chat) |
-h, --help | Show help |
Integration with /ask-question Slash Command
The /ask-question slash command in Claude Code uses this CLI:
- Claude drafts a Stack Exchange-formatted question
- Claude invokes:
ask-question -f question.md -o answer.md - CLI blocks while ChatGPT responds (typically 1-10 minutes)
- Claude reads the answer file and discusses
Use /ask-question draft topic to skip automation and just draft the question.
Troubleshooting
"Server not running or not responding"
Start the daemon:
ask-question-server
"No session found"
Run login helper:
ask-question-login
Session expired
ChatGPT sessions expire after a while. Re-run login:
ask-question-login
Response timeout
Default is 20 minutes. Adjust if needed:
# Shorter timeout for quick questions
ask-question -t 120000 "What is 2+2?"
# Longer timeout for complex responses
ask-question -t 1800000 "Write a comprehensive analysis..."
Debugging
Request ID Tracing
Each request gets a unique ID (e.g., [a1b2c3d4]) logged on both CLI and server sides:
[ask-question] [a1b2c3d4] Attempt 1/2...
[ask-question-server] [a1b2c3d4] Received (500 chars)
[ask-question-server] [a1b2c3d4] Processing...
[ask-question-server] [a1b2c3d4] Sending response (1200 chars)
[ask-question] [a1b2c3d4] Success
Use this to correlate CLI errors with server logs.
Connection Failures
The CLI automatically retries once on connection errors (fetch failed, ECONNREFUSED, etc.). If you see:
[ask-question] [a1b2c3d4] Error: fetch failed
[ask-question] [a1b2c3d4] Cause: ...
[ask-question] [a1b2c3d4] Cause code: UND_ERR_HEADERS_TIMEOUT
This indicates Undici's internal timeout fired. The CLI will retry automatically.
Environment Variables
| Variable | Default | Description |
|---|---|---|
ASK_QUESTION_SERVER_URL | http://127.0.0.1:3033 | Server URL |
ASK_QUESTION_PORT | 3033 | Server port |
ASK_QUESTION_STORAGE_STATE_FILE | ~/.chatgpt-relay/storage-state.json | Session file |
Files
| Path | Purpose |
|---|---|
~/.chatgpt-relay/storage-state.json | Saved ChatGPT session (cookies/localStorage) |
Architecture Deep Dive
Components
┌─────────────────────────────────────────────────────────────────────────┐
│ Claude Code │
│ │ │
│ ▼ │
│ /ask-question (slash command) │
│ │ │
│ ▼ │
│ CLI (ask-question) ─► HTTP POST /ask ─► ask-question-server (daemon) │
│ │ │
│ ▼ │
│ Chromium (headless) │
│ + storageState session │
│ │ │
│ ▼ │
│ ChatGPT tab │
│ (DOM automation) │
└─────────────────────────────────────────────────────────────────────────┘
Design Decisions
HTTP Daemon over WebSocket Connect
launchServer()doesn't support persistent sessions- HTTP is curl-debuggable and simpler
- Request queue handles serialization naturally
- Browser runs headless (no focus-stealing)
Headless with StorageState
ask-question-login: One-time headed browser for manual login, saves cookiesask-question-server: Headless browser loads saved session- Session persists across server restarts
Reliability Features
| Feature | Description |
|---|---|
| Request ID Tracing | 8-char ID correlates CLI and server logs |
| Automatic Retry | CLI retries once on connection failures |
| Network Failure Detection | Tracks streaming response via response.finished() |
| Hard Reset on Errors | Closes and recreates page on failure |
| Login Verification | Server verifies login state at startup |
Fragile Components (Maintenance Required)
These rely on ChatGPT's DOM structure and may break when ChatGPT updates their UI:
- Composer selectors (
div[contenteditable],#prompt-textarea) - Send button selectors (
button[data-testid="send-button"]) - Message extraction (copy button, innerText fallback)
- Login detection (chat history panel visibility)
- Stop button lifecycle (generation progress)
Mitigation: Multiple selector fallbacks, semantic selectors where possible, clear error messages.
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon