Turn SuperGrok into a REST API + CLI tool. No API key needed.
v3.1.1 is the publishable release candidate that supersedes the v3.1.0 release-candidate attempt. It keeps the stable v3 loopback/dedicated-tab boundary and highlights the grok.com Chinese UI submit-button fix.
Your Terminal/Script β Safari JS injection β grok.com β Response extracted via DOM
Two modes:
# Check local Safari/Grok setup first
python3 scripts/grok_bridge.py --doctor
# Start the server on your Mac
python3 scripts/grok_bridge.py --bind 127.0.0.1 --port 19998
# Default mode uses a dedicated background Safari tab named grok-bridge-agent.
# Use --shared-tab only when you intentionally want to drive the current Safari tab.
# Query from the Mac itself
curl -X POST http://127.0.0.1:19998/chat \
-H "Content-Type: application/json" \
-d '{"prompt":"What is the mass of the sun?","timeout":60}'
# Health check
curl http://127.0.0.1:19998/health
# Read current conversation
curl http://127.0.0.1:19998/historyUse --doctor --json when another tool or agent needs structured setup diagnostics.
Stable local deployment listens on 127.0.0.1:19998. This is intentional: the bridge drives the signed-in Safari session on the Mac, so it should not be exposed directly on LAN, Tailscale, or a public interface.
Remote Claw/agent access should use an operator-controlled tunnel or proxy:
# From the remote agent host:
ssh -N -L 19998:127.0.0.1:19998 user@your-mac
# Then call the tunnel-local endpoint:
curl -X POST http://127.0.0.1:19998/chat \
-H "Content-Type: application/json" \
-d '{"prompt":"hello","timeout":60}'If a deployment must listen beyond loopback, start it explicitly with --bind <trusted-interface-ip> and put host firewall / network ACLs in front of it. Do not use 0.0.0.0 as the stable default.
# Local
bash scripts/grok_chat.sh "Explain quantum tunneling"
# Remote via SSH
MAC_SSH="ssh user@your-mac" bash scripts/grok_chat.sh "Write a haiku" --timeout 90- macOS with Safari
- Logged into grok.com (free or SuperGrok)
- Safari > Settings > Advanced > Show features for web developers β
- Safari > Develop > Allow JavaScript from Apple Events β
- No Accessibility permission needed by default (v3 uses JS injection, not System Events)
- Optional
--foreground-fallbackmay activate Safari and use System Events Enter if pure JS submit fails.
| Method | Path | Description |
|---|---|---|
| POST | /chat |
Send prompt, wait for response |
| POST | /new |
Start new conversation |
| GET | /health |
Health check (Safari URL, grok status) |
| GET | /history |
Read current page conversation |
For reviewer-style onboarding, prefer these commands before sending any prompt:
python3 scripts/grok_bridge.py --help
python3 scripts/grok_bridge.py --doctor
curl -s http://127.0.0.1:19998/health
curl -s http://127.0.0.1:19998/history
lsof -nP -iTCP:19998 -sTCP:LISTEN
# if a listener exists, capture its PID provenance before trusting the output
ps -p <PID> -o pid=,ppid=,lstart=,command=Notes:
bash scripts/grok_chat.sh --helpis not read-only; the current script treats the first positional argument as a prompt and starts Safari automation.--doctordoes not send prompts. It only checks platform,osascript, Safari reachability, current Grok URL, and input availability.- By default, server and
--doctoroperate on a dedicated background tab marked withwindow.name="grok-bridge-agent". Use--shared-tabfor manual current-tab debugging. - If port
19998is already occupied, classify it as an environment conflict before blaming bridge logic. - If a listener already exists on
19998, captureps -p <PID> -o pid=,ppid=,lstart=,command=so reviewers can tell whether/healthand/historycame from the current checkout or a stale long-lived process. - See
docs/review-playbook.mdfor evidence format, error taxonomy, and multi-agent ownership split.
| v1 | v2 | v3.1.1 | |
|---|---|---|---|
| Input | Peekaboo UI | pbcopy + Cmd+V | JS execCommand('insertText') |
| Submit | UI click | System Events Return | JS visible button click / Enter fallback |
| UI support | English button labels | English button labels | English + Chinese send labels (Send, Submit, ει, ζδΊ€) |
| Permissions | Peekaboo + Accessibility | Accessibility | None by default (pure JS injection) |
| Interface | CLI only | CLI only | REST API + legacy CLI |
| Dependencies | Peekaboo (brew) | None | None (stdlib only) |
| Network boundary | N/A | SSH/manual | 127.0.0.1 by default; remote via tunnel/proxy |
| Speed | ~30s | ~3s | ~3s |
ββββββββββββββββ βββββββββββββββββββββββββ
β HTTP Client β POST /chat β macOS β
β (local/tunnel)β ββββββββββββββββββ β β
ββββββββββββββββ β grok_bridge.py β
β β osascript β
β Safari do JavaScript β
β β execCommand β
β grok.com textarea β
β β button.click() β
β Grok responds β
β β DOM poll β
β Response extracted β
βββββββββββββββββββββββββ
React controlled inputs ignore JavaScript value setter, synthetic InputEvent, and even nativeInputValueSetter.
What doesn't work from SSH:
- β
osascript keystrokeβ blocked by macOS Accessibility - β CGEvent (Swift) β HID events don't reach web content
- β JS
InputEvent/nativeInputValueSetterβ React ignores synthetic events
What does work:
- β
document.execCommand('insertText')β triggers real input in the browser - β
JS
button.click()on Send button β no System Events needed - β
Dedicated Safari tab via
window.name="grok-bridge-agent"β avoids taking over the user's current Grok tab
Zero Accessibility permissions by default, zero dependencies, pure JavaScript injection via AppleScript.
v3 architecture designed by Claude Opus 4.6 (via Antigravity), System Events bypass by ε°η΅ π¦.
MIT