Why Your Browser Works While git and curl Do Not
Clash on Windows often proves itself the moment you open a foreign site in Edge or Chrome. That success can trick you into believing the whole operating system is “proxied.” In practice, HTTPS traffic from a browser usually rides whatever profile the GUI client set—system proxy, PAC, or a per-browser extension—while PowerShell, CMD, Git Bash, and many build tools start with no forward proxy unless you give them one. They resolve DNS and open TCP connections on their own, so your split rules still apply only after the packet reaches Clash; if the packet never goes there, you see bare timeouts or reset behavior that feels random.
TUN mode can capture a large fraction of OS traffic, yet developers still hit cases where a particular terminal build, antivirus filter driver, or corporate policy leaves a console binary on a direct path. Rather than debating those edge cases in the abstract, the reliable fix for Git and curl is explicit: set HTTP_PROXY and HTTPS_PROXY to the same mixed-port HTTP listener your Meta core already exposes—typically something like http://127.0.0.1:7890, though your YAML is authoritative. This page walks that setup for native Windows shells. If your workload lives inside WSL2 instead, treat our WSL2 apt and git guide as the companion piece: the host IP and namespace rules differ, but the HTTP proxy idea is the same.
HTTP_PROXY / HTTPS_PROXY for interactive shells and CI-like jobs, a tight NO_PROXY list, and Git http.proxy only when it clarifies team defaults.
Read Your Real Clash Mixed-Port (Not a Blog Constant)
Every tutorial mentions 7890; your running config might use 7897 after a conflict. Open the profile your GUI loads, find mixed-port (or separate port values if you run split listeners), and note whether the core binds 127.0.0.1 only or also accepts LAN. For loopback-only consoles on the same machine, http://127.0.0.1:<mixed-port> is enough. If something still refuses to connect, compare with our Windows port conflict checklist so another process is not squatting the listener you think belongs to Clash.
GUI clients such as Clash Verge Rev may mirror system proxy settings when you click a toggle; that helps WinINET consumers, not every console. Keep a human-readable note of the numeric mixed-port beside your shell snippets so teammates stop copying stale screenshots from three releases ago.
HTTP_PROXY, HTTPS_PROXY, and Lowercase Cousins
Most CLI stacks follow a de facto rule: uppercase variables are widely honored; some tools also read lowercase http_proxy / https_proxy. On Windows, sticking to uppercase in documentation reduces confusion when you mix PowerShell and CMD. The value is a URL, not a bare host: http://127.0.0.1:7890 for HTTP CONNECT through a typical Clash mixed listener. HTTPS_PROXY should mirror it unless you deliberately route HTTP and HTTPS through different forwarders—a rare desktop layout.
ALL_PROXY matters when a tool wants one SOCKS endpoint; Clash mixed ports often speak both HTTP and SOCKS on the same socket, but Git on Windows frequently takes the HTTP path for https:// remotes. If you standardize on HTTP CONNECT, prioritize HTTP_PROXY and HTTPS_PROXY first, then add ALL_PROXY only when a stubborn binary insists on SOCKS.
PowerShell: Session Variables vs Persistent User Profile
For a quick test, set variables only for the current window:
$env:HTTP_PROXY = "http://127.0.0.1:7890"
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
$env:NO_PROXY = "localhost,127.0.0.1,::1"
Run curl.exe -I https://www.cloudflare.com/cdn-cgi/trace or a small git ls-remote against a public repo. If this works while it failed before, you have isolated the problem to missing env, not to your subscription rules. To persist for your user account across new windows, use [Environment]::SetEnvironmentVariable with User scope, then open a fresh terminal so the process inherits updated values. Avoid scattering duplicate definitions in both machine and user scopes unless IT requires it—whichever wins last in your profile scripts can surprise you months later.
CMD, setx, and the “Not This Window” Gotcha
setx writes the registry for future processes but does not touch the current cmd.exe session. Typical pattern: setx HTTP_PROXY "http://127.0.0.1:7890", close the window, open another, and verify with echo %HTTP_PROXY%. Pair with HTTPS_PROXY and a conservative NO_PROXY. Remember setx truncates long strings; keep your list short or manage proxy through PowerShell instead.
Git Bash, MSYS2, and Path-Style Environment
Git Bash inherits Windows user environment variables when launched from Start or Explorer, but terminals spawned from an IDE sometimes get a trimmed environment. If echo $HTTP_PROXY is empty inside Bash while PowerShell shows a value, fix the IDE’s terminal integration or source a small ~/.bashrc snippet that exports the same URLs. Mixed path separators rarely break proxy URLs; forgetting quotes around values with commas in NO_PROXY does.
Git http.proxy, https.proxy, and When to Prefer Env
Git respects http.proxy / https.proxy in addition to environment variables. A common team pattern is:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
Global config travels with your user profile; repository-local config overrides when you need an exception. Some engineers prefer env-only setups so CI mirrors laptops without touching .gitconfig. Either works if you stay consistent. For SSH remotes ([email protected]:), these settings do nothing—you need ssh -o ProxyCommand=... through a CONNECT-capable helper, or switch the remote to HTTPS while testing. Do not confuse HTTPS_PROXY with SSH transport; they solve different layers.
curl, Invoke-WebRequest, and Quick Proof
Windows 10 and 11 ship curl.exe. A verbose check:
curl.exe -v https://api.github.com/zen --proxy http://127.0.0.1:7890
If that succeeds without disabling certificate validation, your Clash path and MITM posture are sane. PowerShell’s Invoke-WebRequest can honor system proxy settings depending on parameters and version; when debugging, prefer curl.exe with explicit --proxy to remove variables. Once explicit proxy works, align env so scripts stop hard-coding ports.
NO_PROXY for Intranet, Docker, and Local APIs
A blanket HTTP proxy breaks internal npm registries, company GitLab, and localhost health checks if you forget exceptions. Maintain NO_PROXY with comma-separated hostnames and suffix patterns your stack documents—often localhost,127.0.0.1,::1,.local,.corp.example. Tools vary in how they parse suffixes; when something still leaks through the proxy, add the exact hostname you see in the error, not a guess.
IDEs, Dev Containers, and Background Jobs
Visual Studio, JetBrains, and VS Code often spawn child processes that do not reload your shell profile when you change env mid-session. Fully quit the IDE after updating user-level variables, or configure the IDE’s own HTTP proxy page to the same Clash listener. Build scripts launched by scheduled tasks use the service account environment—another place setx on your interactive user never reaches.
WinINET, WinHTTP, and Why “System Proxy” Is Not Your Shell
Windows separates the user-facing “proxy” settings that Edge consults from the WinHTTP stack some services use. A GUI Clash client may call InternetSetOption for the interactive desktop while curl.exe in PowerShell still uses whatever process environment it inherited. That is why copying the address from Settings > Network > Proxy into HTTP_PROXY manually is a feature, not redundancy: you are wiring a second, explicit contract for CLI tools. If IT pushed a machine-wide WinHTTP proxy via policy, netsh winhttp show proxy can reveal a conflicting story; align with administrators before you blend corporate PAC files and a local mixed-port.
When TUN Is Enough—and When Explicit Env Still Wins
TUN captures traffic at the IP layer for many executables, which feels magical until you meet a signed binary that bypasses the interface or a VPN that reorders adapters. Keeping HTTP_PROXY in your profile is cheap insurance for Git, curl, npm, pip, and Go modules that already honor env. For a deeper capture story, read our Clash TUN mode guide; it pairs with this page rather than replacing it.
Verification Ladder Before You Blame the Subscription
Work top-down: confirm Clash dashboard shows the core running and the mixed-port matches your env. Hit a simple HTTPS URL through curl.exe --proxy. Then unset the explicit flag and rely on env only. Finally run git ls-remote on a tiny public repo. If step one fails, fix the listener. If step two fails but one succeeds, your variables are not visible to that shell. If both fail but the browser works, you are still on a split path—return to port binding and firewall prompts, especially after a Windows update.
Tie It to a Maintainable Client Install
Proxy env vars are only as stable as the core behind them. If you are standardizing a Windows client for a team, start from a documented installer channel and a pinned major version, then encode the mixed-port and NO_PROXY defaults in an internal runbook. For a full walkthrough of Verge-style GUIs on this platform, see our Clash Verge Rev Windows setup guide. When the stack is coherent—one listener, one set of env vars, one place to look when ports collide—Git and curl stop being the odd ones out compared with the browser you already trusted. If you are choosing a client build today, → Download Clash for free and experience the difference between a maintained release channel and ad hoc binaries from random forum links.