1. Symptoms That Point to CDN or GHCR Routing, Not “Slow Wi‑Fi”
Slow downloads feel identical until you read the stall surface. A timeout that always lands on the same package usually means the oversized bottle never started, not that your ISP degraded globally. Watch for curl exit codes bubbling through brew, repeated retries against ghcr.io, or JSON fetches that succeed while blobs hang—classic split-path evidence. Browser tests mislead because Chromium might ride system proxy tables while Terminal inherits nothing unless you export variables. Another mimic is a corporate SSL appliance: TLS succeeds to an internal root while GitHub objects fail policy checks; treat certificate errors as their own class before rewriting Clash YAML.
Collect one failing hostname before touching broad rules. Run HOMEBREW_NO_AUTO_UPDATE=1 brew install --verbose <formula> during reproduction, copy the URL host, then confirm how mihomo classifies it in live connections. If logs show the flow jumping to DIRECT while your LAN cannot reach GHCR, fix policy order instead of upgrading bandwidth. Similarly, if everything tunnels through an unhealthy node, rotate groups using the patterns in url-test failover guidance so massive tarball pulls do not share an exit with chatty APIs.
Remember Apple laptops sleep aggressively. A stalled download after lid-open might be resume semantics rather than routing—rerun once with fresh verbose logs before rewriting DNS. When multiple VPN extensions compete, disconnect the corporate client briefly to isolate whether kernel routes—not Homebrew—own the default path.
2. What Homebrew Actually Downloads: Formula JSON, Bottles, and GitHub
Understanding artifacts prevents cargo-cult rulesets. Core formula definitions resolve through the Homebrew JSON API hosted on formulae.brew.sh, while bottles increasingly originate from GitHub Packages endpoints under ghcr.io. Taps and legacy workflows still hit github.com, raw.githubusercontent.com, or codeload.github.com. Large release binaries sometimes surface via objects.githubusercontent.com. Each hostname can inherit different policy precedence depending on whether your profile buckets “GitHub” as one vague keyword or lists precise suffixes.
Because brew shells out to curl, anything that breaks non-interactive HTTPS transfers breaks installs: stale CA bundles, forced HTTP proxies requiring domain exclusions, or accidental IPv6 blackholes. After routing fixes, if checksum failures appear, verify you did not swap mirrors mid-download—integrity errors differ from timeouts and deserve mirror rollback rather than tunnel tweaks.
Developers comparing ecosystems should recognize parallels to other package managers we cover—npm and pnpm split routing—but keep Homebrew’s Git-centric topology in mind: ignoring GHCR while polishing generic “CDN” keywords misses the highest-impact choke point on Apple desktops in 2026.
3. macOS Proxy Layers: System Settings, TUN, and Terminal Environment
Apple exposes proxy configuration both to GUI apps and POSIX tools, yet adoption is uneven. Enabling system proxy through Clash Verge Rev or similar menus updates macOS network settings that Safari and some frameworks honor. Terminal sessions started outside those inheritance chains—common with IDEs—still need explicit exports. TUN mode pushes capture toward completeness by steering packets before reluctant apps opt in, at the cost of extension approvals documented in our Apple Silicon walkthrough.
Avoid double capture: system proxy plus sloppy TUN defaults can duplicate TLS attempts or reorder DNS unexpectedly. When triaging brew, adopt a deliberate baseline—either exported proxy variables into a single Terminal profile or TUN with documented DNS—and change only one knob per iteration. Mixed stacks explain mysterious “it worked yesterday” reports when login items toggled competing clients overnight.
For engineers who live in both Terminal and GUI Git tools, align policies with GitHub-oriented routing guidance; host overlap means fixes often benefit both workflows simultaneously once suffix lists converge.
4. HTTP_PROXY, HTTPS_PROXY, and NO_PROXY for brew and curl
Export standard variables toward your local mixed inbound—replace the port with yours:
# zsh or bash session on macOS — send curl (used by brew) through Clash HTTP CONNECT export HTTP_PROXY=http://127.0.0.1:7890 export HTTPS_PROXY=http://127.0.0.1:7890 export ALL_PROXY=http://127.0.0.1:7890 export NO_PROXY=localhost,127.0.0.1,::1,.local
Notice HTTPS_PROXY still uses the http:// scheme because the hop speaks HTTP CONNECT even when the target URL is HTTPS—mirroring the nuance explained for Node tooling in cross-platform guides. Expand NO_PROXY with internal registry hosts, artifact domains, or on-prem Git servers so sensitive TLS never crosses an unrelated exit node.
Persist exports in ~/.zprofile or ~/.zshrc consistently with team docs; mismatched shells cause “works in iTerm, fails in VS Code integrated terminal” drift. For one-off debugging, prefix a command instead of polluting global state: HTTPS_PROXY=http://127.0.0.1:7890 curl -I https://ghcr.io/v2/.
5. Domain Checklist for Split Rules in mihomo
Start precise, then widen only with evidence. Baseline overseas pulls commonly touch:
ghcr.io— bottle registry and manifest traffic for many core formulae.github.com— web UI-less APIs, redirects, and auxiliary metadata.objects.githubusercontent.com— large GitHub-hosted blobs.codeload.github.com— archive ZIP downloads for taps or edge cases.raw.githubusercontent.com— raw tap files or installer scripts.formulae.brew.sh— Homebrew JSON API and docs-backed endpoints.brew.sh— marketing and occasional redirects; usually lightweight but easy to overlook.
Corporate environments sometimes pin internal mirrors—reflect those hosts as DIRECT early in your ruleset and in NO_PROXY. Public suffix fanatics may attempt one giant DOMAIN-SUFFIX,githubusercontent.com row; prefer finer rows until logs justify aggregation, because oversized CDN buckets accidentally steer unrelated telemetry through expensive exits.
| Hostname pattern | Typical brew role | Routing note |
|---|---|---|
ghcr.io |
Bottle layers and manifests | Often the largest tarball egress; verify policy group bandwidth. |
formulae.brew.sh |
Formula JSON metadata | Fast failure here mimics outdated taps even when bottles work. |
objects.githubusercontent.com |
Large GitHub artifacts | May differ from API routes; avoid assuming one GitHub rule covers all. |
6. Example YAML Snippets: Ordering and Narrow Suffixes
Place explicit brew-related rows ahead of catch-all GEOIP or final MATCH entries. Swap PROXY for your real policy group name:
# Example rules — tune group names and upstream health checks
rules:
- DOMAIN-SUFFIX,ghcr.io,PROXY
- DOMAIN-SUFFIX,github.com,PROXY
- DOMAIN-SUFFIX,githubusercontent.com,PROXY
- DOMAIN-SUFFIX,formulae.brew.sh,PROXY
- DOMAIN-SUFFIX,brew.sh,PROXY
Pair domain precision with outbound reliability. If your provider tags streaming nodes separately from DC exits, bind heavy downloads to the stable subgroup. Rule providers help track evolving CDN lists yet still deserve review—auto-generated lists that silently downgrade GitHub to DIRECT recreate intermittent timeouts whenever regional peering degrades.
Advanced readers orchestrating subscription merges should revisit profile merge and overrides so team baselines append brew suffix rows without forking an entire upstream ruleset.
7. DNS Pitfalls: fake-ip, Encrypted DNS, and Corporate Split Horizon
Routing decisions ride on names. Profiles using fake-ip can accelerate lookups yet confuse tooling when fake ranges leak into captures not mapped back through redir-host or equivalent mechanisms. If dig ghcr.io disagrees with what Clash logs display, pause and reconcile DNS modes before stacking more domain rows.
macOS-specific headaches include iCloud Private Relay, standalone encrypted DNS profiles, or enterprise split DNS that resolves GitHub differently on VPN versus off. Cross-check against our deeper DNS architecture notes such as fake-ip and redir-host routing and the broader setup primer DoH baseline examples; although the headline mentions Windows, resolver concepts translate directly when harmonizing mihomo stacks across teammates.
When Apple pushes minor OS upgrades, cached DNS profiles occasionally linger—toggle airplane mode once or flush DNS cautiously, then retest curl before rewriting YAML. Logging verbosity beats superstition.
8. When HOMEBREW_* Mirrors Help—and When They Hide Real Failures
Environment knobs such as HOMEBREW_BOTTLE_DOMAIN, HOMEBREW_API_DOMAIN, or HOMEBREW_ARTIFACT_DOMAIN redirect download roots without teaching your shell anything about proxies. They can unblock offices that mandate domestic caching yet introduce skew when mirrors lag upstream signatures. Treat mirrors as supply-chain choices: document versions, rotate credentials if mirrors authenticate, and monitor checksum failures separately from latency.
Prefer fixing egress first—stable GHCR via Clash keeps security posture closer to upstream defaults. If compliance demands mirrors, still align rules so debugging traffic can fall back to official endpoints during incident response without reinstalling Homebrew.
Container developers juggling similar CDN pain should contrast strategies with registry mirror routing; lessons about artifact domains and authenticated pulls rhyme even though Docker speaks a different protocol stack.
9. Verification Commands and Log Reading Habits
Build a repeatable script mentally: first prove loopback listeners, then isolated curl, then full brew operations. Useful probes include curl -I https://formulae.brew.sh/api/formula.json, curl -I https://ghcr.io/v2/, and authenticated-free HEAD checks against GitHub object hosts when failures mention specific URLs.
Inside Clash dashboards, filter connections while rerunning brew fetch. You want to see consistent policy selection, realistic handshake timings, and byte counters climbing on bottle downloads. Spikes with immediate teardown often indicate TLS MITM or firewall resets rather than mere congestion.
After changes, capture one-line summaries for teammates: which domains moved to PROXY, which stayed DIRECT, and which DNS mode applies. Future you troubleshooting Xcode downloads benefits from the same document without guesswork.
10. Frequently Asked Questions
Does Apple Silicon change brew networking? Architecture does not alter HTTPS semantics, yet ARM laptops often ship stricter sandboxed terminals and modern DNS profiles. Focus on resolver parity rather than chip lore.
Should brew itself be proxied while gems or pip are direct? Mixed defaults invite inconsistent lockfiles across languages. Align baseline proxy policy per developer machine and carve exceptions consciously via NO_PROXY.
What about self-signed taps? Internal Git hosts belong in both split rules and bypass lists; otherwise TLS succeeds only when accidentally tunneled through the wrong MITM-friendly exit.
11. Closing Thoughts
Reliable Homebrew on macOS is mostly disciplined networking: align what curl inherits from your shell, route GHCR and GitHub CDNs through an outbound you trust, and treat DNS as part of the rule story—not an afterthought. Consumer VPN apps that only expose a giant power toggle rarely expose per-domain economics for bottle-sized downloads; when they funnel everything through congested exits or forbid split intranet bypass cleanly, brew hangs return the moment your formula pulls multi-hundred-megabyte tarballs from ghcr.io. A maintained Clash-family client paired with transparent mihomo rules keeps developer traffic observable: you see exactly which CDN hostname stalled, adjust only that suffix row, and resume installs without surrendering fine-grained corporate compatibility. Compared with chasing opaque system-wide VPN throughput limits, this workflow scales across engineering teams who already version-control dotfiles and YAML anyway.
Grab an installer build from our curated hub when you want Core updates without hunting forum attachments, then layer the exports and rule tweaks above on top.
Related Reading · topic cluster
Hand-picked deep-dives on the same topic — practical Clash routing guides in the same category.
Install ClashX Pro on Intel Mac: System Proxy and Enhanced Mode First Setup
ClashX Pro on Intel Mac: install, import subscription, turn on system proxy & Enhanced Mode—macOS approvals and first-run checks.
Read moreClash Verge Rev on Intel Mac: System Proxy and TUN Setup Guide (2026)
Intel Mac: install the x86_64 dmg, import subscription & mihomo profile—enable system proxy first, then TUN; approve Network Extensions and troubleshoot coexist…
Read moreInstall Clash Verge Rev on Apple Silicon Mac: System Proxy and TUN First-Time Setup
Install Clash Verge Rev on M1–M4 Macs: system proxy vs TUN, Network Extension prompts, helper permissions, DNS, and common Apple-only pitfalls on macOS.
Read more