Grok, Mistral, Kimi, GLM, ChatGPT, Qwen and Gemini use the normal site's send
handler in an existing signed-in tab. They do not copy cookies, passwords or
Google OAuth tokens into the bridge. Each provider has a separate queue and
scoped conversation ids. All integrations are opt-in and use the selected web model. Browser adapters for
Qwen, Kimi, GLM, Mistral, Grok, ChatGPT, Claude and Gemini have been live-checked;
DeepSeek stays HTTP-only. Website frontends and account limits can still break a
session at any time. For Qwen set QWEN_ENABLED=1 and QWEN_TRANSPORT=browser
(the default http transport still uses python -m qwen.auth plus the direct
API client). For Gemini set GEMINI_ENABLED=1 and GEMINI_TRANSPORT=browser
(the default cli transport still uses the Antigravity CLI and GEMINI_MODELS).
Kimi's JSON Connect parser binds root answer blocks to the matching user and
successfully completed assistant message; thinking blocks are excluded.
Only this verified wire text can be parsed as requested OpenCode tool calls;
unsupported snapshots and ambiguous message identities fail the request.
The two scripts work with Userscripts for Safari, distributed through the developer's App Store link. The observer runs in the page context without privileged APIs. The controller runs in the isolated content context and keeps its local pairing key out of page JavaScript.
- Run
python -m providers.tab_bridgein this repository. It writes personalized scripts tosession/browser-bridge/userscripts/with private permissions. Never upload, commit or share that directory: the controller contains your local pairing key. The generic files inbrowser/contain no key. - Install Userscripts and add the two exported
.user.jsfiles to its scripts directory. Grant access only tochat.z.ai,grok.com,chat.mistral.ai,www.kimi.com(orwww.kimi.ai),chat.qwen.ai,chatgpt.com(andchat.openai.comif still used),claude.ai,chat.chatgbot.ai,gemini.google.com, andwww.google.com; the bridge does not need access to Google Account settings pages beyond the chat UI. After adding or replacing files, open the Userscripts toolbar popup and wait until both script names appear. The extension must rescan externally edited files before the next page load, as described in its linked README. After upgrading the bridge, export and replace the scripts again. The current controller is 0.3.35 and observer is 0.3.18 (ChatGBot Claude/en/chat). On a failed job the badge showsERROR: …with the reason (hover for full text). Older loaded scripts do not include all lease checks. - Keep the API bound to
127.0.0.1:8000. SetBROWSER_BRIDGE_ENABLED=1and enable the provider you want, e.g.GROK_ENABLED=1,MISTRAL_ENABLED=1,GLM_ENABLED=1,CHATGPT_ENABLED=1, orCLAUDE_ENABLED=1(browser-only — no transport flag). For Qwen useQWEN_TRANSPORT=browser; for GeminiGEMINI_TRANSPORT=browser. Then restart the API. - Open the provider in your normal signed-in browser and reload once to load
both scripts. Click Подключить вкладку к OpenCode. Keep that tab open.
Userscripts may separately ask for
127.0.0.1access for local job exchange; grant only that address, without choosing all websites. The controller checks that its observer is ready before sending a prompt. Do not use it for manual chat while a bridge request is running. - Point an OpenAI-compatible client at the same
/v1URL. Model ids aregrok-web,mistral-web,kimi-web,glm-web,chatgpt-web,claude-web,qwen-web, andgemini-web. They deliberately do not claim a specific model version; select the desired model in the site's UI. Stateless clients (OpenCode) that resend fullmessages[]resume the same browser chat via the local conversation cache; only the new user/tool turn is typed into the tab after the first reply. An uncertain send/capture outcome retains a durable pause and pending attempt. Inspect the site before explicitly resolving it; visibility in a browser is not proof that a generation never started.
Requests to the local job endpoints require the private pairing key and a loopback client address. There is no CORS grant. A claimed job is tied to one tab, provider, document instance, random id and lease. Sending requires a one-time server authorization; only explicit navigation can hand an unsubmitted job to a new document. Cancelled, late and replayed results fail, and the controller checks lease liveness while waiting for a response. Unsent drafts cause a failure rather than being overwritten. A reload during generation fails the job instead of automatically repeating its prompt.
Completed text is buffered and validated before any tool calls are returned. SSE keepalives protect client timeouts. Quota, security and region rejections are terminal; the bridge does not rotate accounts, solve captchas, change fingerprints, or retry through another endpoint.
All adapters are opt-in. The API attempts a prompt once; quota, security, regional or uncertain upstream failures persist a provider pause across restarts. Later requests return HTTP 403 before any browser job or CLI process is created. A failure after SSE starts is a terminal error event. This does not undo account restrictions or guarantee that website automation is permitted.
Inspect python -m providers.access status. Only after manually checking normal
website access, use python -m providers.access resume PROVIDER. A new sign-in
or a different model cannot silently clear the pause. The default 10-second
interval between attempts and continuations is pacing, not a website allowance.
Use one server process; multiple workers do not share an in-flight queue.
Free access is subject to the website's account, model and feature allowances. The bridge does not provide an unlimited API or a separate quota. An OpenCode task can consume several website messages because tool results require another model turn. A resumed conversation consumes allowance too.
- Mistral/Vibe: the official Free plan
limits messages and web searches. During the 2026-10-02 live test a new
completion succeeded, then the resumed request returned HTTP
429; the user also observed the free allowance warning. Further requests stopped. No fixed message count or reset time was established. Website plan allowances are distinct from Studio/developer API rate limits. - Kimi: the official chat FAQ documents a conversation frequency limit and peak-load throttling. Selected membership features/models also consume a shared credit pool. Kimi Code limits apply to Kimi Code and must not be presented as this browser chat adapter's quota. Large composer pastes (~4KB+, typical OpenCode system+tools) are turned into a TXT attachment by the site instead of chat text — keep bridge prompts shorter, or use the HTTP transport after session capture.
- DeepSeek: our account received a temporary restriction (
biz_code=5,user is muted) on 2026-10-02. The exact trigger is unknown; no live retest was attempted after the safety changes. Automated website access can restrict an account even without an observed quota warning. - Qwen and GLM: no exhausted web-chat quota was observed in our controlled qualification tests. This is not proof of unlimited usage. We have not established a fixed current web-chat allowance; API/CLI quota tables must not be substituted for website limits.
On 429 or a website quota notice, stop the task and inspect the normal account
UI for the relevant allowance and reset time. The bridge does not automatically
switch accounts or models, create another conversation to evade the quota,
purchase credits or retry the rejected turn. Limits can change; check the
provider's current plan before relying on it for sustained agent work.
ChatGPT is browser-only (CHATGPT_ENABLED=1, no transport flag). Pair a signed-in
tab on https://chatgpt.com/ (or https://chat.openai.com/), use model id
chatgpt-web, and select the model in the site UI. The observer captures
/backend-api/conversation and /backend-api/f/conversation SSE only for the
active bridge job. Conversation tokens use /c/<id>. Captchas, Sentinel
challenges and plan limits must be resolved in the normal tab; the bridge does
not automate them. Live browser-adapter checks for this provider have passed;
account quotas, captchas and Sentinel challenges still apply per session.
Claude is browser-only (CLAUDE_ENABLED=1, no transport flag). Pair a signed-in
tab on ChatGBot (preferred) or
https://claude.ai/, use model id claude-web, and select the model in the
site UI. The controller fills the ProseMirror composer
([data-testid="chat-input"]) and clicks Send. On ChatGBot the empty chat is
/en/chat and threads are /en/chat/<id>; bridge tokens stay /chat/<id>.
The observer captures only
/api/organizations/.../chat_conversations/<id>/completion SSE for the active
job (line-oriented content_block_delta / message_stop; thinking frames with
"stop_reason": null are not treated as done). An incomplete wire body is
rejected; visible DOM text cannot substitute for a terminal network response.
Do not point OpenCode small_model / session-title at claude-web
while a long turn is running — use another provider or disable title LLM
(Harness already disables session-title-llm). Captchas and plan limits must be
resolved in the normal tab. Live browser-adapter checks for this provider have
passed; account quotas and challenges still apply per session.
Set GEMINI_ENABLED=1, GEMINI_TRANSPORT=browser, and BROWSER_BRIDGE_ENABLED=1.
Export and install the userscripts, open a signed-in Gemini tab — either
https://www.google.com/search?udm=50 (AI Mode empty chat) or
https://gemini.google.com/app — connect it, and use model id gemini-web.
The site UI selects the model. Conversation tokens use /app/<id> when the
SPA exposes one (not Antigravity UUIDs).
Answer capture. The controller forwards only request-bound network captures. It never substitutes visible DOM text or synthesizes completion markers. Google AI Mode HTML prompt echoes are removed only at an exact normalized prefix; ambiguous embedded echoes are rejected. A stalled capture stops the turn and retains the safety pause. These changes were verified offline, not against live Gemini accounts.
Install the official Antigravity CLI and complete its Google account sign-in yourself. Individual free access to the old Gemini CLI was retired; do not reuse its OAuth credentials in this bridge.
Run agy models and put the account's real slugs into GEMINI_MODELS, for
example a JSON object mapping your chosen gemini-... public name to the exact
CLI slug. Set GEMINI_ENABLED=1. No Gemini models are advertised when the map
is empty. The adapter runs the official CLI in an empty temporary workspace,
with a custom text agent containing tools: [], no slash commands and no
permission bypass. OpenCode remains responsible for tool execution.
The CLI's streaming initialization must confirm the selected model, custom
agent, empty tool list and normal permission mode before the prompt is sent.
Only one successful terminal result is accepted; tool/subagent events fail.
An available model list does not prove account eligibility: the CLI checks
regional access again when starting a completion.
The adapter currently requires POSIX process groups and terminates the entire
owned group before deleting its temporary workspace, including descendants
whose parent has already exited.
If the official CLI's token exchange fails specifically on an IPv6 socket,
python -m providers.antigravity_ipv4 runs the same official CLI through a
loopback CONNECT tunnel using IPv4 on your existing network route. Google TLS
is not decrypted; OAuth traffic is not logged. This optional workaround refuses
to override an existing proxy. It is not a region-access workaround: stop if
Google rejects your account or region. No system, browser, DNS or VPN settings
are modified.
python -m unittest discover -s tests -q checks routing, authentication, queue
ownership, cancellation, protocol completion and CLI isolation. To also run the
owned browser fixtures, install Playwright Chromium and use
RUN_BROWSER_FIXTURES=1 python -m unittest tests.test_userscripts -q. Those
fixtures intercept all requests; they do not authenticate or contact providers.
Passing fixtures are not proof of a successful live Safari/provider integration.
On 2026-10-02, a signed-in Safari account using GLM-5.3-Flash passed a controlled
new completion, resumed SSE with the same conversation id, and an OpenCode
plan request with a completed native read followed by the exact fixture
contents. This used both 0.1.4 scripts and the matching server protocol. It
qualifies that account/session and test, not all GLM models or arbitrary tasks.
With both 0.2.4 scripts on 2026-10-02, Kimi passed an exact new completion and
resumed SSE with the same conversation id, stop and [DONE], followed by an
OpenCode plan request with a completed native read and the exact owned fixture
contents. This qualifies that account/session and controlled test. Large Kimi
composer pastes (~4KB+, typical OpenCode system+tools) are still turned into a
TXT attachment by the site — confirmed on later live checks; keep bridge prompts
shorter or use HTTP after session capture.
As of 2026-10-11, live browser-adapter checks also passed for Mistral
(mistral-web), Grok (grok-web), ChatGPT (chatgpt-web), Claude
(claude-web), Qwen (qwen-web) and Gemini (gemini-web). Earlier partial
failures (Mistral 429 on continuation, Grok capture gaps) do not overturn those
later adapter checks; quotas and UI challenges still apply per account.
Official Antigravity CLI login and model listing succeeded, but completion was
rejected by Google's regional eligibility check; further CLI attempts stopped.
Prefer GEMINI_TRANSPORT=browser / gemini-web when the tab path works.