Fix Gemini CLI Timeouts in 2026: Clash Domain Rules and DNS (Tested)

You already run Clash, yet Gemini CLI still throws timeouts, hangs on OAuth, or fails to reach the Google Generative Language API. Browsers are not terminals: the same YAML that fixes gemini.google.com tabs can miss the hostnames, DNS path, or capture mode your shell uses. This guide walks through a log-first workflow for terminal AI—pairing Clash split routing with Clash DNS settings that match how libc-based clients resolve names—so you can stop guessing and start proving which rule (or resolver) actually handled each connection.

Why Gemini CLI breaks when “the proxy is on”

Gemini-style command-line tools sit on top of ordinary HTTPS libraries. They open TLS connections to a small set of Google fronts, exchange OAuth codes through the web-style account stack, then stream or batch responses against API hosts that often live under googleapis.com. None of that is exotic—until you remember that your operating system may not send those sockets through Clash at all. A GUI toggle can set “system proxy” for WinINET-friendly apps while a Python or Node runtime still uses a direct resolver path. Conversely, TUN mode can be perfect for packets yet disagree with a terminal that pinned an old DNS cache entry from before you changed rules.

The failure mode users describe is eerily consistent: OAuth opens a browser, the browser completes a dance that looks successful, and the CLI nevertheless reports deadline exceeded, connection timed out, or an opaque error when listing models. Sometimes the inverse happens—login succeeds once, then subsequent calls fail because a different hostname (still on DIRECT) never joined the same policy bucket. Treat those reports as routing classification bugs, not as “AI server down,” until logs prove otherwise.

If you are new to policy-based proxies, skim the site Clash tutorial first; this article assumes you already know what a proxy-groups entry is and only need the Gemini-CLI-shaped overlay. For browser-centric Gemini traffic, our companion piece on Google Gemini with Clash explains overlapping hostnames from the Chromium side—read both if you split personal browsing and development terminals on the same machine.

The three planes you must align: capture, rules, and DNS

Think in three layers. Capture answers whether the CLI’s packets traverse the Clash core. Rules answer which outbound group handles a flow once the core sees it. DNS answers which names the core believes it is routing—critical in fake-ip modes where the client might otherwise disagree with the resolver upstream of policy. A mistake in any one layer mimics a “Gemini outage” forever.

Capture modes differ by platform. On macOS and Windows, setting an HTTP(S) proxy in the OS helps many GUI apps but not every language runtime unless you export HTTPS_PROXY explicitly—or run under a TUN adapter that wraps the stack at the IP layer. On Linux desktops, systemd-resolved stub listeners and per-user bus settings add another twist: the CLI might query 127.0.0.53 while Clash advertises a different local DNS port. The lesson is boring but important: pick one coherent strategy—either steer DNS into Clash deliberately or document why a parallel resolver is still policy-safe.

Rules fail for two blunt reasons: order and granularity. Clash evaluates matchers from top to bottom; the first hit wins. A coarse GEOIP line or an early MATCH can send Google API traffic to DIRECT while your carefully written Gemini lines never execute. Granularity matters because DOMAIN-SUFFIX,googleapis.com is powerful—and side-effectful. Start with the narrow hosts your logs show, then widen.

Hostnames you should expect for API access and login

No public list ages gracefully; Google introduces subdomains and shifts edges. Still, a practical baseline for Gemini CLI plus Google Generative Language API work usually includes the following families—always verify in your own connection logs after any client update.

  • REST and RPC fronts: generativelanguage.googleapis.com and sibling endpoints under *.googleapis.com depending on SDK version.
  • OAuth and account flows: accounts.google.com, oauth2.googleapis.com, and sometimes additional google.com hosts for consent pages and redirects.
  • Shared static infrastructure: gstatic.com, parts of googleusercontent.com, and other CDNs the login web UI touches while you authorize the CLI.
  • Developer consoles (optional): ai.google.dev or related documentation hosts if your workflow opens studio pages alongside the CLI.
💡 Tip Copy-pasting fifty random domains from a forum hurts more than it helps. Add lines only when your log shows a miss, then keep them above broad catch-all rules.

OAuth deserves emphasis. Users perceive OAuth as “the browser problem,” but the CLI still establishes background HTTPS sessions to token endpoints after you close the tab. If those sessions split across exits—because oauth2.googleapis.com matched a different policy than accounts.google.com—you can see intermittent authorization failures that look like flaky Google infrastructure. Route the whole identity family consistently once logs prove the names.

YAML fragment: CLI-friendly ordering

Assume a proxy group named Gemini-CLI. The block below is illustrative; rename the group to match your profile and keep LAN ranges on DIRECT before Google matchers.

# RFC1918 and loopback first (adapt to your LAN)
IP-CIDR,192.168.0.0/16,DIRECT
IP-CIDR,10.0.0.0/8,DIRECT
IP-CIDR,172.16.0.0/12,DIRECT
IP-CIDR,127.0.0.0/8,DIRECT

# OAuth + token stack (keep together; verify in logs)
DOMAIN,accounts.google.com,Gemini-CLI
DOMAIN-SUFFIX,oauth2.googleapis.com,Gemini-CLI
DOMAIN-SUFFIX,google.com,Gemini-CLI

# Generative Language API
DOMAIN,generativelanguage.googleapis.com,Gemini-CLI
DOMAIN-SUFFIX,googleapis.com,Gemini-CLI

# Shared assets for login pages
DOMAIN-SUFFIX,gstatic.com,Gemini-CLI
DOMAIN-SUFFIX,googleusercontent.com,Gemini-CLI

# Remaining traffic defers to your profile
# MATCH,YourDefaultGroup

Critics will rightly say that suffix-matching all of google.com is heavy-handed. It is—yet it often stabilizes OAuth faster than a minimalist list that forgets a single redirect host. The balanced approach is to start minimally, watch failures, then promote the smallest suffix that fixes them without dragging unrelated properties through the wrong exit. Maintain those decisions in a local override snippet so subscription refreshes do not vaporize your work. For merge and provider hygiene, read the custom rules tutorial.

DNS: the usual reason “the rule exists but never fires”

In fake-ip configurations, Clash may answer applications with synthetic addresses that map back to names internally. That is elegant until a terminal resolver bypasses Clash and learns the real public addresses first, or until cached answers disagree after you toggle modes mid-session. Symptoms include TLS handshakes that start then reset, stalled model listing, and “worked until reboot.”

Align deliberately. If Clash owns DNS for the system, confirm upstream resolvers are reachable through the exit you intend for DNS traffic. If some apps perform DNS over HTTPS directly, Clash may observe IP-only flows where your DOMAIN matchers never participate—either route known DoH hosts explicitly or accept IP-CIDR fallbacks and document the trade-off. For a deeper tour of TUN, sniffing, and resolver interplay, see the TUN deep dive.

Linux workstations and systemd-resolved

Developers on Ubuntu or Fedora frequently run systemd-resolved. The CLI might query a stub listener while Clash listens elsewhere; both can appear “correct” in isolation. When DNS is inconsistent, policy disagreements show up as partial OAuth or hung gRPC-style calls. Temporarily instrument with verbose resolver tracing—or compare against a tethered hotspot—to see whether the breakage tracks your LAN resolver rather than Clash upstream quality. Our Linux DNS walkthrough covers systemd-specific footguns.

Windows terminals and corporate agents

Enterprise endpoint software may inject its own forwarding proxy or filter HTTPS separately from user-level Clash GUIs. A shell launched as Administrator can see a different network profile than a standard user session. If OAuth succeeds in a clean user shell but fails under elevated automation, suspect parallel filters before rewriting YAML for the fifth time.

Environment variables versus transparent capture

Many CLI stacks honor HTTPS_PROXY or ALL_PROXY when set. That is convenient—until a child process unsets them, or until a tool uses a HTTP client that ignores standard variables. Transparent TUN captures regardless, at the cost of wrestling with other VPNs and occasionally MTU quirks. A sensible escalation path is: confirm OS-level proxy expectations, export variables for the shell you actually use, then enable TUN if logs still show stray DIRECT Google connections during reproduction.

If you run AI CLIs inside WSL2, remember the virtual network boundary: Windows Clash and Linux namespaces disagree unless you bridge carefully. Users combining Windows GUIs with Linux toolchains should read the WSL2 proxy guide before duplicating rules on both sides inconsistently.

Sniffing, QUIC, and long-lived streams

Some stacks attempt HTTP/3 where UDP paths differ from TCP. A proxy that handles TLS on TCP brilliantly may still look “timeout-prone” if UDP is filtered upstream or if two tools disagree about ALPN. When symptoms match mid-stream stalls rather than hard connection refusal, compare behavior with HTTP/2-only clients such as curl --http2 through the same outbound. Clash Meta’s sniffing options can help when applications expose ambiguous SNI patterns, but mis-sniffing also creates false positives—treat toggles as experiments with logs open.

When adjusting sniff settings, keep notes. A change that fixes Gemini CLI must not silently break banking or regional services that relied on prior classifications. Roll back aggressively when collateral damage appears.

A repeatable verification ritual (under five minutes)

Adopt a short sequence whenever you touch rules or DNS. First, print the active profile version your GUI claims to run and ensure merges did not replace your personal snippet. Second, open connection logs and clear noise filters. Third, run the smallest failing CLI command—often a models list or a trivial completion request. Fourth, identify three fields for each failing flow: destination hostname, matched rule, outbound group. Fifth, only then rotate nodes inside Gemini-CLI to hunt for peering issues.

Parallel-check with curl -v https://generativelanguage.googleapis.com/ through the same proxy environment. If curl cannot complete TLS while a generic non-Google HTTPS host succeeds through identical policy, you learned something about Google path health—not about YAML typos. If curl succeeds but the CLI fails, scrutinize certificate pinning assumptions, custom CA stores in language runtimes, or missing proxy variables for that specific interpreter.

When to widen rules versus fixing the exit

Beginners often stack dozens of DOMAIN-SUFFIX lines before swapping the upstream node once. That wastes time. After you confirm the CLI traffic hits Gemini-CLI consistently, test two exits in the same metro with similar protocols. If failures track a single ASN, no amount of additional suffix entries fixes a blackholed prefix. Conversely, if logs show DIRECT hits to obvious Google API hosts, no node swap helps until matchers fire.

Also watch for rate limits disguised as timeouts. Aggressive scripting against the Generative Language API can trigger backoff responses that feel like packet loss. Separate policy mistakes from quota mistakes by reading HTTP status lines when clients expose them.

Maintaining overrides through subscription churn

Commercial templates reorder rules when providers “optimize” GEOIP blocks. Your CLI matchers may drop below a new early MATCH. Guard personal lines in prepend-only snippets or local merge files, then rerun the five-minute verification after every Friday-evening refresh. If your team shares profiles via Git, commit the override layer separately from generated vendor YAML so diffs stay readable.

Privacy, compliance, and realistic expectations

Routing changes paths; it does not grant service entitlements in regions where offerings differ, and it does not override account or workplace policies. Assume every generative call is logged by Google per their terms. On corporate laptops, transparent TUN may violate security baselines—validate with IT before bypassing mandated agents.

FAQ-style symptoms (quick map)

Use this as orientation, not gospel; your logs remain authoritative.

  • Browser OAuth succeeds; CLI immediately errors: token exchange still on DIRECT or split across exits—align oauth2.googleapis.com with account hosts.
  • First model call works; later calls hang: possible connection pooling across hosts with mismatched policy or a flaky keep-alive through congested exits; capture logs across the full session window.
  • Everything times out only on office Wi-Fi: compare against tethering; captive portals and layered proxies masquerade as Gemini outages.
  • Works on laptop, fails in SSH session on a remote box: the remote host probably lacks Clash entirely—export policy there or SSH with a tunnel intentionally; do not expect magic from a local GUI.

macOS shells, Developer Tools, and the “GUI works, Terminal does not” trap

Apple’s ecosystem encourages a specific failure mode: Safari or Chrome inherits system proxy settings from a Clash menu, while zsh sessions launched from Terminal.app or iTerm2 inherit environment variables only if you exported them in .zprofile. Launch daemons started by launchd may ignore interactive shell configuration entirely, which means scheduled jobs that call Gemini overnight are still direct despite a glowing “connected” tray icon. When you debug, open the exact shell profile your automation uses—not the one you tested manually after pasting exports.

Another macOS wrinkle is Little Snitch–class filters or MDM profiles that bypass local proxies for binaries signed by certain vendors. Security tools sometimes trust Google endpoints enough to let them through directly while still MITM-testing others, which paradoxically fragments OAuth. If policy dictates a split, mirror those allowances in Clash logs so you can see who actually owns the socket.

Node version managers (nvm, fnm) and per-project .env files can also hide stale HTTPS_PROXY values. After rotating Clash’s mixed port, a forgotten file may point at a listener that no longer matches your client’s secure IP allowlist. When in doubt, print environment inside the failing process—not only in your interactive prompt.

API keys versus OAuth: two traffic shapes in one mental model

Some workflows use service accounts or API keys that skip the interactive browser dance. Even then, TLS fronts still resolve through the same Google edge families; you merely delete the human-facing redirects from your mind map. Others mix browser OAuth with long-lived refresh tokens stored under ~/.config. Token refresh failures often show up as sudden wholesale timeouts—not because the model vanished, but because the refresh path was downgraded to DIRECT after a rule reorder. Watch for quieter hosts tied to credential rotation, not only the blockbuster generative hostname.

Do not conflate “Generative Language API” hostnames with unrelated Google Cloud control planes unless your logs demand it. Blanket routing of every googleapis.com service simplifies life until a datastore or BigQuery client on the same laptop suddenly behaves differently. The disciplined practice remains: add suffix breadth only when narrowly targeted lines fail repeatedly for the same executable.

IPv6, happy eyeballs, and false “timeout” narratives

Dual-stack workstations race IPv4 and IPv6 during connection setup. If Clash handles one family differently—think missing IP-CIDR6 exemptions for ULA space—or if your upstream drops AAAA answers while the OS still prefers them, you can observe alternating success and failure across retries that superficially resemble AI instability. When symptoms correlate with moving between home and café networks, gather whether failing sessions logged v4 or v6 targets.

A practical mitigation is to log the address family in Clash alongside domain names, then test with v6 temporarily disabled at the OS layer as a controlled experiment. If stability returns, you narrowed the problem space from “Gemini hates me” to “this ASN mishandles UDP/IPv6 toward Google.” Document before reverting toggles.

Enterprise HTTP proxies and CONNECT tunnels

Corporations that mandate explicit forward proxies sometimes require CONNECT tunnels to nonstandard ports. Gemini CLIs that assume transparent HTTPS may need an additional layer—think proxy-aware transports or chained HTTPS_PROXY variables pointing at the enterprise forwarder first, then at Clash’s local mixed port, depending on policy. This article cannot prescribe architecture for every NTLM/Kerberos maze; the diagnostic point is that missing CONNECT privileges to *.googleapis.com masquerade as application bugs. Confirm with IT whether generative endpoints are categorized differently from ordinary Google web properties.

Containers, remote dev environments, and CI

Docker and Kubernetes pods inherit DNS from cluster services. A devcontainer that “worked locally” might point at kube-dns stub which never forwards to your laptop’s Clash listener. Mounting host network mode might appear tempting but collapses isolation; a cleaner pattern is injecting HTTP(S)_PROXY at build time from documented secrets or running a sidecar forwarder. For CI, explicit allowlists beat hoping GitHub Actions runners magically share your home YAML.

If you routinely pair Clash with local Kubernetes, our Docker Desktop-oriented proxy notes illustrate how bridge networks and host resolver assumptions fight policy routing—even when the AI workload is unrelated to Google at first glance.

Instrumenting without leaking secrets

Verbose logs risk exposing tokens. Redact authorization headers before sharing captures; prefer noting hostnames, rule names, and TLS failure phases instead of full payloads. When filing internal tickets, attach a timeline of profile merges—subscription updates often coincide with regressions more often than Gemini releases do.

After it works: lightweight monitoring habits

Once stable, schedule a calendar reminder to rerun the five-minute verification after major OS upgrades, browser engine refreshes that touch shared credential stores, and Clash core jumps. Automators might script a harmless metadata call and alert on changed rule-hit patterns. The goal is catching provider-side reorder early—not heroic surgery at 2 a.m. because months of drift finally collided.

Putting terminal AI on solid ground

Gemini CLI timeouts rarely need exotic tricks—they need consistent capture, ordered rules aimed at a dedicated group, and DNS that tells the same story your policy engine expects. Pair this workflow with browser-oriented notes from the Gemini browser guide when you use both surfaces daily.

Compared with one-size-fits-all VPN clients that blanket-route entire devices, many traditional tools make split tunneling opaque—you toggle a giant switch and hope developer CLIs follow suit, which they often do not. Clash keeps policy visible: you see the rule name, the outbound, and the domain in one log line, then adjust with small YAML edits instead of reinstalling monolithic profiles. If you still need a maintained client build, start from our Clash download page, install a Meta-capable GUI, then layer the OAuth and API overrides from this guide so browsers and terminals share one coherent split policy on the same workstation.