When Clash is on but the Terminal still feels "direct"
You launched Clash Verge Rev, FlClash, ClashX Meta, or another Mihomo-based client on your Mac. You enabled the subscription, picked a healthy node, and maybe even turned on System Proxy so Safari respects the tunnel. Then you open Terminal, run curl https://api.ipify.org, and your residential ISP address comes back. Homebrew formula downloads crawl or fail on hosts that only resolve cleanly through your proxy path. Git pushes to a corporate host that requires the same exit as your browser never leave the wrong interface. Nothing crashes; the mismatch is quieter than that. You are seeing the normal split between applications that read macOS network settings and command-line tools that honor Unix environment variables unless configured otherwise.
This article answers the search pattern Clash macOS terminal proxy and Homebrew proxy with a reproducible sequence: read your local inbound port from the client, export http_proxy, https_proxy, and usually ALL_PROXY for SOCKS, prove the path with curl, extend the same variables to git and brew, and only then decide whether to bake the settings into ~/.zshrc. Along the way we clarify how this relates to system proxy on macOS and why the experience differs from our Windows 11 system proxy troubleshooting guide, where WinINET and UWP loopback dominate the story instead of shell exports.
If you have not installed a current client yet, start from our Clash download page; the steps below assume a working profile and a listening HTTP or mixed port on loopback.
127.0.0.1 plus a mixed or HTTP port such as 7890) and manual or scripted exports for zsh and bash. If you already run TUN mode, many symptoms vanish because packets are captured before user-space tools debate proxies—skip ahead to the TUN section if that is your end state.
Why macOS system proxy does not fix Terminal by itself
macOS exposes proxy settings through the network configuration database that GUI apps and frameworks consult. Safari, and many Electron apps configured to use the system configuration, will pick up a PAC file or manual proxy once Clash registers it. The Terminal shell you open from Spotlight or Dock, however, inherits a minimal environment. Unless something explicitly sets http_proxy family variables or you wrap commands with a proxy-aware launcher, tools like curl, wget, git, npm, and brew default to direct outbound TCP. That is not a Clash bug; it is how POSIX tooling has worked for decades.
Another layer of confusion is HTTPS interception semantics. Your Clash inbound speaks HTTP CONNECT for TLS tunnels. Clients must send https:// requests to an HTTP proxy using the CONNECT method. Setting only a lowercase http_proxy without https_proxy still trips people: many libraries consult both. Similarly, tools that speak SOCKS need ALL_PROXY or tool-specific keys. Until those names exist in the environment of the shell that launches the child process, Clash macOS terminal proxy behavior will not materialize no matter how green your menu-bar icon looks.
Finally, remember that rule routing still applies. Exporting proxy variables sends traffic into Mihomo; Mihomo then matches rules. If your profile sends the target domain DIRECT, you will still see a domestic exit even though the transport path changed. When something feels wrong after exports work, inspect logs or connection views instead of blaming the shell.
Step 1: Read the HTTP(S) or mixed port from your client
Open your Clash front-end and locate the inbound section. Mihomo derivatives almost always expose a mixed port that accepts both HTTP proxy requests and SOCKS on the same numeric port, or separate HTTP and SOCKS ports. Note the loopback address—almost always 127.0.0.1—and the port number. Common defaults are 7890 for mixed, 7891 for SOCKS-only setups, or custom YAML values if you changed port, socks-port, and mixed-port.
If you are unsure which number applies to HTTP, prefer the value labeled mixed or HTTP. For a pure SOCKS port, you will rely on ALL_PROXY=socks5://... rather than http_proxy for tools that support SOCKS. Homebrew and curl both handle HTTP proxies reliably; SOCKS support varies by invocation, so mixed ports are the friendliest default for a broad toolchain.
Sanity-check that the port is listening before editing shell files. In Terminal, run lsof -iTCP:7890 -sTCP:LISTEN with your port substituted. You should see your Clash or Mihomo process bound to localhost. If nothing listens, fix the client first—environment variables cannot forward traffic to a closed socket.
Step 2: Export http_proxy, https_proxy, and ALL_PROXY
Assume mixed port 7890 on 127.0.0.1. For a typical zsh or bash session, run:
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export ALL_PROXY="socks5://127.0.0.1:7890"
Duplicating uppercase variants helps tools that only read HTTP_PROXY. The SOCKS line covers utilities that prefer SOCKS5 for non-HTTP protocols. If your profile separates HTTP and SOCKS across two ports, point http_proxy at the HTTP port and ALL_PROXY at the SOCKS URL with the correct port number instead of blindly copying the snippet.
To clear the session when you are done:
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY
These exports affect only the current shell and child processes. Opening a new Terminal tab returns to a clean environment unless you added lines to a startup file—exactly what you want while testing.
proxy_on and proxy_off once you trust the values. That keeps daily work on DIRECT while letting you flip the tunnel on for a long brew upgrade session without editing YAML.
Step 3: Verify with curl and a public IP check
After exporting, run curl -s https://api.ipify.org and compare the result to the same command run in a browser through Clash. They should match when routing rules send the probe domain through the same outbound. If the IP is still wrong, first confirm you unset conflicting VPNs, then look at Mihomo logs to see whether the connection hits DIRECT by rule.
Add verbosity when debugging: curl -v https://example.com shows whether libcurl picked up http_proxy. For DNS-related surprises, remember that many stacks resolve names before they connect; pairing proxy exports with consistent Clash DNS settings is covered in depth in our Fake-IP and DNS guide.
Step 4: Point git at the same path
Git respects http_proxy for HTTP remotes and can use https_proxy for HTTPS when the underlying library does. For stubborn cases, configure Git explicitly:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
Remove later with git config --global --unset http.proxy and the HTTPS counterpart. SSH remotes ([email protected]:...) do not use HTTP proxies unless you tunnel SSH differently; this article focuses on HTTPS Git traffic, which is what most Homebrew taps and formula sources use when they interact with GitHub.
Step 5: Homebrew and the Homebrew proxy story
Homebrew subcommands generally inherit the shell environment. Once http_proxy and https_proxy are exported, brew update and brew install often succeed immediately on networks where GitHub and CDN hosts were previously unreachable. That is the practical core of Homebrew proxy support: there is rarely a Brew-specific toggle; you feed the same variables the rest of the ecosystem expects.
Some users also set export HOMEBREW_FORCE_BREWED_CURL=1 to ensure Brew uses its own curl build with consistent TLS behavior; it is optional and unrelated to routing unless your system curl is ancient. If a formula downloads via raw curl in a recipe, the environment still propagates. When a cask uses a GUI installer, all bets are off—those flows may ignore shell exports.
If Brew still resolves slowly, check whether your DNS queries bypass the tunnel. A machine using a public resolver that answers differently from your node region can look like a proxy failure when it is actually name resolution. Aligning Clash DNS with your rules prevents chasing ghosts.
Step 6: Persist responsibly in ~/.zshrc or ~/.bash_profile
After you validate ports and exports interactively, you may add a guarded block to your shell startup file. Prefer functions over unconditional exports so a broken port does not slow every login. One pattern for zsh:
# Clash proxy helpers — adjust port to match your YAML
export CLASH_MIXED_PORT=7890
proxy_on() {
export http_proxy="http://127.0.0.1:${CLASH_MIXED_PORT}"
export https_proxy="$http_proxy"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export ALL_PROXY="socks5://127.0.0.1:${CLASH_MIXED_PORT}"
echo "Proxy env enabled toward 127.0.0.1:${CLASH_MIXED_PORT}"
}
proxy_off() {
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY
echo "Proxy env cleared"
}
Reload with source ~/.zshrc and call proxy_on when needed. This avoids leaking proxy settings into graphical apps that spawn shells for unrelated tasks and keeps failure modes obvious if Clash is not running.
How this relates to System Settings and "system proxy"
On macOS, flipping Clash’s system proxy switch updates the network service configuration that GUI programs read. It does not magically inject http_proxy into every process. Think of the two mechanisms as complementary: system proxy for Cocoa and many browsers, environment variables for traditional Unix tooling. Some all-in-one utilities try to sync both; Mihomo clients vary in how much automation they provide. When in doubt, shell exports are explicit and auditable.
Users coming from Windows sometimes expect parity with WinINET-wide behavior. Our article on Clash system proxy on Windows 11 focuses on that platform’s stack—including UWP loopback—while this guide covers macOS shells. Together they map the two most common "everything except my terminal works" stories.
When exporting variables is the wrong long-term fix
If you juggle a dozen languages and package managers, maintaining perfect proxy awareness everywhere grows tedious. TUN mode moves interception below most applications, so even poorly behaved binaries follow your rules without per-tool configuration. The trade-off is elevated permissions, kernel extension or system extension prompts on Apple Silicon, and a higher responsibility to understand DNS hijack settings.
Read Clash TUN mode explained before enabling it on a production laptop. Many developers run TUN for daily work and keep shell exports as a narrow escape hatch for debugging.
Quick checklist you can reuse
- Port: Mixed or HTTP listener is up on
127.0.0.1and matches your exports. - Variables: Both lowercase and uppercase HTTP proxy names, plus
ALL_PROXYwhen SOCKS helps ancillary tools. - Session: Test in a fresh shell before persisting to rc files.
- Git: HTTPS remotes respect env or explicit
git configproxy keys. - Homebrew: Same env; watch for DNS or rule
DIRECTsurprises rather than Brew bugs. - Escalation: If coverage must be universal, plan TUN rather than infinite shell hacks.
Closing: make shell traffic as observable as browser traffic
Frustration with http_proxy and https_proxy usually comes from unclear ownership: the GUI shows green, the shell never received the memo. Once you treat Terminal as a separate consumer that needs explicit variables, behavior becomes predictable. Pair that mental model with occasional Mihomo log checks and your Clash macOS setup stops feeling like superstition.
For subscription hygiene and profile basics before you tune proxies further, see our subscription import tutorial. When you are ready to standardize on a maintained client build, download Clash for free from our official page and experience the difference.