Bundle of 9 AI-agent-native CLIs for web AI platforms — no API keys needed. Each CLI authenticates via browser cookies or a session token and returns token-efficient JSON pointer output.
# Install
pip install playwright && playwright install chromium
git clone https://github.com/lesterppo/hermes-web-clis
cd hermes-web-clis
pip install -r requirements.txt
# Login (one-time, opens visible browser)
python scripts/cdp_server.py login
# Start CDP daemon (headed — required for ChatGPT & Minimax)
python scripts/cdp_server.py start --headed
# Use any CLI
python cli/claude.py "Explain quantum computing"
python cli/grok.py "Write a haiku about coding"
python cli/qwen.py "Debug this Python error: ..."Two approaches, chosen per platform:
| Approach | Platforms | Latency | Auth |
|---|---|---|---|
| HTTP API | Claude | ~5s | Firefox sessionKey cookie |
| Direct HTTP + PoW | DeepSeek | ~3-5s | localStorage session token + on-device proof-of-work |
| Direct HTTP (signed) | MiniMax | ~2s | localStorage token + device fingerprint, md5-signed |
| Direct HTTP (Connect-RPC) | Kimi | 5-15s | localStorage access/refresh tokens, auto-refresh |
| Direct HTTP (Chrome TLS) | Qwen | ~5s | token cookie + Alibaba WAF bx-* fingerprint (curl_cffi impersonate) |
| Direct HTTP (SSE + ph param) | MiMo | ~1-3s | xiaomi cookies + xiaomichatbot_ph query param |
| CDP (Chrome DevTools Protocol) | ChatGPT | 3-20s | Persistent Chrome profile (headed daemon) |
| Playwright native profile | Kimi (fallback) | 3-15s | --login reusable Chrome profile (no CDP) |
| Playwright standalone | Grok, MiMo | 2-15s | Firefox cookies injected into Chromium |
Claude exposes an internal API at claude.ai/api/organizations/{org}/chat_conversations/{id}/completion.
The CLI extracts the sessionKey cookie from Firefox and calls this endpoint directly.
DeepSeek's web app has no public endpoint — it's protected by a session token
stored in localStorage (not a cookie) and a proof-of-work challenge
(DeepSeekHashV1). deepseek.py extracts the token once via a headed
--login flow (reusing your Firefox Google sign-in), then solves the PoW
on-device (~40ms) using DeepSeek's own WebAssembly SHA3 module through
wasmtime. The CLI then calls the internal chat API directly — ~3-5s, no
browser needed after login.
Covers the full web UI: DeepSeek-V3, DeepThink (R1) reasoning, web search, file upload, and multi-turn.
These platforms use aggressive anti-bot protection (Cloudflare, Akamai, Alibaba WAF).
A long-lived headed Chromium instance runs as a daemon with --remote-debugging-port=9223.
CLIs connect via Playwright's connect_over_cdp().
ChatGPT also runs headed Chromium (Cloudflare Turnstile requires it) but is now
self-contained — it auto-injects the Firefox session into its own profile per call
(no CDP daemon needed) and supports the full logged-in feature set (see below). It also
has a hybrid CDP mode (Aug 2026): when the CDP daemon (scripts/cdp_server.py start --headed) is reachable, calls reuse the daemon's warm logged-in profile with a solved
cf_clearance — no per-call browser launch, ~2-11s vs 40-60s. --cdp/--no-cdp force
either mode; auto-detection falls back to the standalone browser when the daemon is down.
Why headed? Cloudflare Turnstile detects headless browsers. Some platforms (Minimax) render responses in virtualized DOM containers invisible in headless mode.
These platforms work with Firefox cookies injected into a fresh headless Chromium per query. No persistent browser needed.
gem-pw.py launches its own Chromium per call with a persistent profile at
~/.gemini-cli/cr-profile/. Sign in once via gem-pw-login, then all subsequent
calls reuse the session. No CDP server needed — each call is self-contained.
Supports Gem CRUD (create, edit, delete), file uploads, image generation,
knowledge management (files, GitHub repos, photos, folders), model selection,
and extended thinking with configurable timeouts.
| # | CLI | Platform | Auth Source | Approach | Latency |
|---|---|---|---|---|---|
| 1 | claude.py |
claude.ai | Firefox sessionKey | HTTP API | ~5s |
| 2 | grok.py |
grok.com | Firefox sso cookie | Playwright standalone | ~2s |
| 3 | mimo_http.py |
aistudio.xiaomimimo.com | xiaomi cookies + ph query param | Direct HTTP (SSE) | ~1-3s |
| 4 | mimo.py |
aistudio.xiaomimimo.com | Firefox cookies | Playwright standalone (fallback) | ~12s |
| 5 | qwen_http.py |
chat.qwen.ai | token cookie + WAF bx-* fingerprint | Direct HTTP (curl_cffi Chrome TLS) | ~5s |
| 6 | qwen.py |
chat.qwen.ai | Chrome CDP profile | CDP (fallback) | ~18s |
| 7 | kimi_http.py |
kimi.com | localStorage token | Direct HTTP (Connect-RPC) | ~5-15s |
| 8 | minimax_http.py |
agent.minimax.io | localStorage token + fingerprint | Direct HTTP (md5-signed) | ~2s |
| 9 | kimi.py |
kimi.com | --login native profile |
Playwright native profile (fallback) | ~10s |
| 10 | minimax.py |
agent.minimax.io | Chrome CDP profile | CDP (headed, fallback) | ~4s |
| 11 | chatgpt.py |
chatgpt.com | Firefox session (auto-inject) | Playwright headed + full features | ~5s |
| 12 | gem-pw.py |
gemini.google.com | Chrome CDP profile | Playwright standalone | ~5-15s |
| 13 | deepseek.py |
chat.deepseek.com | localStorage token |
Direct HTTP + PoW | ~3-5s |
The CDP server is the backbone for platforms requiring persistent authentication:
python scripts/cdp_server.py start --headed # launch daemon (headed)
python scripts/cdp_server.py start # launch daemon (headless)
python scripts/cdp_server.py status # check health
python scripts/cdp_server.py stop # shut down
python scripts/cdp_server.py login # one-time interactive loginThe daemon double-forks to survive terminal disconnection and survives Node.js v24 EPIPE crashes.
All CLIs share a common interface:
# Basic prompt
python cli/<name>.py "Your prompt"
# Token-efficient JSON pointer output (for AI agents)
python cli/<name>.py -o /tmp/out.md "Your prompt"
# → {"ok":true,"f":"/tmp/out.md","s":450,"b":0}
# Multi-turn conversation
python cli/<name>.py -c chat.json "Turn 1"
python cli/<name>.py -c chat.json "Turn 2"
# Model selection (platform-dependent)
python cli/claude.py -m claude-sonnet-4-6 "prompt"
python cli/grok.py -m think "reasoning task"
python cli/qwen.py -m qwen3-max "complex task"
# Disable thinking (faster, where supported)
python cli/qwen.py --no-thinking "quick question"
python cli/minimax.py --no-thinking "quick question"
# DeepSeek (direct HTTP + PoW, no browser after login)
python cli/deepseek.py "What is 2+2?" # DeepSeek-V3
python cli/deepseek.py -m r1 "reasoning task" # DeepThink R1 (exposes CoT)
python cli/deepseek.py -s "latest AI news" # web search + sources
python cli/deepseek.py -f report.pdf "summarize" # file upload
python cli/deepseek.py -c sess.json "turn 1" # multi-turn
# Kimi (direct HTTP Connect-RPC, no browser after --login)
python cli/kimi_http.py --login # one-time token harvest
python cli/kimi_http.py "Say hello" # single turn
python cli/kimi_http.py -c chat.json "turn 1" # multi-turn (chat_id)
python cli/kimi_http.py -c chat.json "turn 2"
python cli/kimi_http.py --no-thinking "quick question"
python cli/kimi_http.py --show-thinking "reasoning task" # include CoT in output
python cli/kimi_http.py -f report.pdf "summarize" # attach file (repeatable)
python cli/kimi_http.py -f photo.png "what is this?" # attach image (vision)Kimi is served by a Connect-RPC API (kimi.gateway.chat.v1.ChatService/Chat)
with a 15-min access token + 30-day refresh token stored in the web client's
localStorage (not cookies). kimi_http.py harvests those tokens once from
the --login profile, auto-refreshes, and talks to the chat endpoint directly
— no browser at runtime. Multi-turn works by sending the top-level chat_id
from the previous response.
python cli/kimi_http.py --login # harvest tokens from ~/.kimi-cli/chrome-profile
python cli/kimi_http.py --status # show auth state
python cli/kimi_http.py "prompt" # single turn
python cli/kimi_http.py -c chat.json "t1" && python cli/kimi_http.py -c chat.json "t2"Full protocol notes in skills/kimi-http.md.
MiniMax Agent's web client signs every request with two md5 headers (yy +
x-signature). The algorithm was reverse-engineered from the site's own JS
bundles (2026-08-24) and reproduced exactly in Python — so minimax_http.py
talks to the session + streaming endpoints directly, no browser at runtime,
~2s per turn. Multi-turn keeps the same session_id, which preserves memory.
python cli/minimax_http.py --login # harvest auth from browser profile (one-time)
python cli/minimax_http.py --status # show account + agent
python cli/minimax_http.py "prompt" # single turn
python cli/minimax_http.py -c chat.json "t1" && python cli/minimax_http.py -c chat.json "t2"
python cli/minimax_http.py --no-thinking "quick q" # variant=normal (skip CoT)
python cli/minimax_http.py -m MiniMax-M3 "prompt" # pick modelThe signing details (URLSearchParams form-encoding, op_ticket quirk, double
body encoding) are documented in skills/minimax-http.md.
Qwen Chat's completions endpoint is gated by Alibaba baxia WAF. The gate is
the TLS fingerprint: plain urllib/requests get a punish page no matter how
perfect the headers are. qwen_http.py uses curl_cffi with
impersonate="chrome" (Chrome JA3/JA4), plus the site's bx-ua /
bx-umidtoken fingerprint headers (harvested once from a real Chrome session
logged in via Google OAuth) — the WAF then accepts the request over pure HTTP,
~5s per turn, no browser at runtime.
python cli/qwen_http.py --login # harvest auth from CDP browser (Google OAuth login)
python cli/qwen_http.py "prompt" # single turn
python cli/qwen_http.py -c chat.json "t1" && python cli/qwen_http.py -c chat.json "t2"
python cli/qwen_http.py --no-thinking "quick q"
python cli/qwen_http.py -m qwen3.7-plus "prompt"WAF details (TLS impersonation, bx-* headers, referer, cookie consistency) in
skills/qwen-http.md.
Xiaomi MiMo Studio's chat is a plain SSE POST (/open-apis/bot/chat) — the
trick is auth: every request needs the xiaomichatbot_ph cookie value as a
URL-encoded query param (?xiaomichatbot_ph=...) in addition to the
xiaomichatbot_serviceToken/userId cookies. Without the ph param the API
returns 401 even with valid cookies. mimo_http.py harvests the cookies once
(--login, CDP browser or Firefox) and talks directly — no browser at runtime,
~1-3s.
python cli/mimo_http.py --login # harvest auth from CDP browser / Firefox
python cli/mimo_http.py "prompt" # single turn
python cli/mimo_http.py -c chat.json "t1" && python cli/mimo_http.py -c chat.json "t2"
python cli/mimo_http.py --list # recent conversations
python cli/mimo_http.py -m mimo-v2-pro "prompt"Protocol notes (ph query param, 32-hex conversationId, SSE format, tokenPlan
gate) in skills/mimo-http.md.
chatgpt.py is the most feature-complete CLI. It auto-injects the Firefox ChatGPT session
(no manual login) and exposes the full logged-in feature set:
python cli/chatgpt.py "prompt" # text chat
python cli/chatgpt.py --search "query" # web search (live + citations)
python cli/chatgpt.py --image-gen "a red fox" # image generation
python cli/chatgpt.py --deep-research "topic" # deep research report (minutes)
python cli/chatgpt.py --image /tmp/x.png "describe" # image upload / analysis
python cli/chatgpt.py --file /tmp/x.pdf "summarize" # document upload / analysis
python cli/chatgpt.py -c chat.json "turn 1" # multi-turn continuityThe CLI uses the Firefox session by default. To use a different account (e.g. a spare account with fresh quotas) without re-logging Firefox:
python scripts/capture_ff_session.py NAME # log into ChatGPT in Firefox, then capture
python cli/chatgpt.py --account NAME "prompt" # shorthand
python cli/chatgpt.py --cookie-file ~/.chatgpt-cli/NAME_cookies.json "prompt"
python scripts/verify_account.py NAME # confirm which account the cookies belong to- Deep research completes server-side (
Research completed in Nm) but the report is canvas-rendered — not extractable via DOM. Read it back with a vision model (muse exec --image <screenshot>) or the report's download button. - Files / images / data analysis hit a daily free-plan quota; text + web search are effectively unlimited. Image generation has a separate "Instant" quota.
- Deep research is one-at-a-time per account.
All CLIs support -o FILE for agent-optimized output:
{"ok":true,"f":"/tmp/out.md","s":450,"b":2,"m":"fast","t":2.3}Fields: f=file path, s=bytes, b=code blocks, m=model, t=elapsed seconds.
The calling agent reads the output file with a standard file-read tool.
This saves 60-90% tokens vs returning raw response text.
Open each platform in Firefox/Chrome and sign in:
- https://claude.ai (Firefox)
- https://grok.com (Firefox)
- https://aistudio.xiaomimino.com (Firefox)
- https://chat.qwen.ai (Chrome)
- https://kimi.com (Chrome)
- https://agent.minimax.io (Chrome)
- https://chatgpt.com (Firefox — auto-injected, no explicit step)
- https://gemini.google.com (Chrome — sign in once, session persists)
- https://chat.deepseek.com (Google sign-in — one-time, via
deepseek.py --login)
For HTTP API & Playwright standalone (Claude, Grok, MiMo):
python cli/claude.py --save-all # extract Firefox sessionKey
python cli/grok.py --save-auth # extract Firefox sso cookie
python cli/mimo.py --login # extract Firefox cookies
python cli/kimi.py --login # headed Chrome: sign in once, reuse profileFor CDP platforms (Qwen, Minimax):
python scripts/cdp_server.py login # opens visible Chrome, log in, close when doneFor DeepSeek (direct HTTP + PoW):
python cli/deepseek.py --login # opens browser, complete Google sign-in once
python cli/deepseek.py --status # verify token + accountpython scripts/cdp_server.py start --headedEach CLI has a companion skill file in skills/ for Hermes Agent integration.
Skills provide:
- Trigger conditions (when to use this CLI)
- Quick reference commands
- Pitfalls and platform quirks
- DOM selectors and extraction patterns
- Auth refresh procedures
For other AI agents: load the relevant skill file before using the CLI.
- Python 3.10+
- Playwright (
pip install playwright && playwright install chromium) curl_cffi,httpx(HTTP),wasmtime+numpy(DeepSeek PoW solver)- Firefox (for cookie extraction on Claude, Grok, MiMo)
- Chrome/Chromium (for CDP platforms)
- WSL or Linux (Firefox cookie extraction uses SQLite; native Linux snap + standard profiles supported)
- ChatGPT + Minimax require headed CDP. Headless mode triggers Cloudflare or DOM virtualization issues.
- ChatGPT Cloudflare cookies are fingerprint-bound —
cf_clearance/__cf_bmfrom Firefox must NOT be injected into Chromium (Turnstile loops forever). The CLI skips them and lets Chromium solve its own headed challenge (~5s, up to 45s poll). Fixed Aug 2026. - Native Linux first: claude.py and chatgpt.py
--save-allscan native Linux Firefox (snap + standard) before Windows/WSL mounts. Fixed Aug 2026 — previously WSL-hardcoded. - Cookie expiry. Auth cookies expire in hours to days. Re-run
--save-authorcdp_server.py loginwhen queries fail. - Node.js v24 EPIPE. The CDP server daemonizes to avoid this. Standalone CLIs suppress stderr during cleanup.
- Rate limits. All platforms enforce rate limits. The CLIs include cooldown handling.
- DOM fragility. CSS selectors may change with platform updates. Check
skills/for current selectors.
When a platform changes its DOM, update the extraction selectors in both:
- The CLI script in
cli/ - The skill file in
skills/
Test with a simple prompt before submitting.
MIT