Why developer workflows break even when the browser works
A developer rarely uses only one network destination during a normal coding session. A single pull request can involve GitHub for repository access, a separate identity provider for authentication, an SSH connection to a self-hosted Git server, a package registry for dependencies, and a cloud service for deployment. On macOS, Homebrew adds another group of endpoints for formula metadata, bottles, casks, and version checks. On Windows, Git for Windows, PowerShell, WSL, and language-specific package managers may each use different proxy settings.
That is why “the browser opens GitHub” is not a sufficient connectivity test. A browser usually follows the operating system proxy, a PAC file, or its own extension. Git may use http.proxy and https.proxy, SSH uses a completely different transport, and Homebrew may rely on environment variables or GitHub release URLs. A successful browser tab can therefore coexist with git clone timeouts, stalled brew update operations, and remote development sessions that disconnect after authentication.
Clash is useful here because it gives these connections a shared policy layer without forcing every destination through the same exit. The practical objective is not “proxy everything.” It is to make related developer traffic predictable: Git hosting, package metadata, release assets, and remote development services should use deliberate rules, while private intranet hosts, loopback addresses, and approved corporate endpoints can remain DIRECT where policy requires it.
Map Git, SSH, Homebrew, and remote-development traffic first
Begin with an inventory instead of copying a large “developer rules” list from an unrelated configuration. Write down the tools you actually use, the hostnames they contact, and whether each connection is short-lived HTTPS, long-lived SSH, or a local process talking to a Clash listener. This small map makes troubleshooting much faster because you can distinguish a DNS failure from a proxy-selection failure and a credential problem from a transport problem.
| Workflow | Typical transport | What to observe | Common policy choice |
|---|---|---|---|
| GitHub or GitLab over HTTPS | HTTPS on port 443 | Repository host, API host, release assets | Use a stable developer proxy group when required |
| Git over SSH | SSH on port 22 or an alternate port | SSH destination, key exchange, keepalive behavior | Route through a supported local SOCKS or relay path |
| Homebrew metadata | HTTPS and Git | Formula repositories and API requests | Keep metadata and bottle downloads consistent |
| Remote development | HTTPS, SSH, WebSocket, or vendor protocol | Gateway, authentication, websocket, and tunnel hosts | Prefer a stable group instead of frequent node switching |
| Private services | Internal DNS, HTTPS, or SSH | Company domains, RFC1918 addresses, split DNS | Follow the organization’s approved direct route |
GitHub is not always one hostname in practice. A clone may begin at github.com, authentication may involve an API endpoint, and a release download can redirect to an asset host or a content delivery network. GitLab installations can be even more varied because the organization may expose the web interface, registry, package repository, and SSH service under separate names. Treat the visible URL as the beginning of a flow rather than a complete inventory.
Homebrew deserves similar care. brew update may touch Git repositories, while brew install can fetch a prebuilt bottle from a release or CDN host. A rule that makes the formula index reachable does not automatically guarantee that the binary artifact will download. If the index updates successfully but installation hangs at “Pouring” or “Downloading,” inspect the actual endpoint shown in the terminal and then confirm that Clash recorded the connection.
Configure a stable Clash baseline on macOS and Windows
Choose a maintained Clash client that supports the core features you need, such as system proxy mode, rule-based routing, local HTTP and SOCKS listeners, and useful connection logs. Clash Verge Rev and other Mihomo-based clients expose different menus, but the underlying reasoning remains similar. First import a trusted profile, verify that the profile parses successfully, and select a known-good proxy group before attempting to solve a Git or Homebrew issue.
Avoid changing several layers at once. On macOS, check whether the client is setting the system proxy under the active Wi-Fi or Ethernet service. On Windows, inspect the operating system proxy page, WinHTTP state, Git configuration, PowerShell environment variables, and any WSL-specific settings separately. A graphical “connected” indicator only confirms that the client has selected a profile; it does not prove that Git, SSH, or Homebrew is using the listener.
A practical baseline uses one stable mixed port for ordinary HTTP and SOCKS traffic, then assigns a clear policy group for developer services. The exact port is not universal, so read it from the client’s settings rather than pasting a number from an old tutorial. Test the listener locally before editing application configuration:
curl -I --proxy http://127.0.0.1:YOUR_MIXED_PORT https://github.com
curl -I --proxy socks5h://127.0.0.1:YOUR_MIXED_PORT https://github.com
The socks5h form is valuable during diagnosis because hostname resolution happens through the SOCKS proxy. If HTTP proxying works but SOCKS5 with remote DNS fails, you have narrowed the issue to listener support, DNS behavior, or the selected rule path rather than GitHub itself. Do not interpret a successful request to the home page as proof that every API or asset host will follow the same route.
On macOS, remember that terminal applications inherit environment variables only when those variables exist in the shell process. A GUI launched from Finder may not receive the same values as a terminal launched from your profile. On Windows, a new PowerShell or Command Prompt may be required after changing user-level variables. WSL has another boundary: Linux processes inside WSL do not automatically inherit the Windows host’s localhost assumptions in every networking mode, so verify the reachable host and port from inside the distribution.
Make Git HTTPS and Git SSH behave predictably
Git over HTTPS
Git HTTPS is usually the easiest developer path because it uses the same broad transport family as web traffic. Configure it only when necessary and prefer a narrow setting over a global value that follows every repository. A global proxy can be convenient on a personal machine, but it can also break an internal Git server that must remain direct. Repository-level configuration is often safer when public and private remotes coexist.
git config --global http.proxy http://127.0.0.1:YOUR_MIXED_PORT
git config --global https.proxy http://127.0.0.1:YOUR_MIXED_PORT
git config --global --get-regexp 'http.*proxy'
If a proxy requires authentication, do not place a long-lived password directly into a command that will remain in shell history. Use the credential mechanism supported by your environment, or let Clash handle the local listener without adding unnecessary application credentials. When testing, compare git ls-remote with a normal clone because the former is a small, repeatable request that reveals whether authentication and remote negotiation begin successfully.
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git ls-remote https://github.com/ORG/REPO.git
The trace should help you identify whether Git is contacting the intended host, honoring the configured proxy, following a redirect, and receiving a TLS response. Avoid publishing trace output in an issue report without reviewing it first; URLs, usernames, repository names, and authorization-related details may appear in verbose logs. If Git reports a certificate error after introducing a proxy, investigate the certificate chain and enterprise inspection policy instead of disabling SSL verification.
Git over SSH
SSH is different. A Git remote such as [email protected]:ORG/REPO.git does not use Git’s HTTP proxy settings. It creates an SSH connection to the host and port defined by SSH configuration. That is why setting https.proxy can fix HTTPS clones while SSH pushes continue to time out. First test the transport independently:
ssh -T [email protected]
ssh -vT [email protected]
The verbose command reveals name resolution, the selected port, key exchange, identity files, and the point at which the session stops. If your network permits direct SSH but the remote host is unreachable, use an approved SSH proxy mechanism supported by your environment. A common pattern is to expose a local SOCKS listener and reference it through an SSH ProxyCommand, but the syntax depends on the installed OpenSSH version and the client’s capabilities.
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 30
ServerAliveCountMax 3
The keepalive values above do not repair a blocked route; they only help detect dead idle connections and keep some stateful paths from expiring. Use them carefully on corporate or metered networks. If port 22 is unavailable, do not assume that moving SSH to another port is automatically legitimate or supported. Check the Git provider’s documented SSH endpoints and your organization’s policy, then configure the exact host and port deliberately.
A useful operational choice is to keep one remote style per repository while diagnosing. Switching repeatedly between HTTPS and SSH changes authentication, proxy behavior, host keys, and credential helpers at the same time. Once the route is stable, choose the style that fits your security model: SSH keys may be convenient for frequent pushes, while HTTPS with an approved token or credential manager may integrate better with managed devices.
Route Homebrew and package managers without breaking updates
Homebrew on macOS is a chain of operations rather than a single download. Updating taps can use Git, formula metadata can be fetched through HTTPS, and bottles may come from a different release or CDN hostname. Start with the smallest useful checks:
brew config
brew doctor
brew update --verbose
brew fetch --force FORMULA_NAME --verbose
Run these commands one at a time and note the first endpoint that stalls. If brew update fails before any package download, inspect Git access to the tap repositories and the Git proxy configuration. If metadata updates but brew fetch fails, inspect the bottle URL and its redirect chain. This separation prevents a misleading fix where a developer changes the GitHub rule even though the actual bottle host was the failing destination.
Environment variables can help command-line tools, but they are not a universal solution. Some programs honor HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY; others read lowercase variants, application settings, or no proxy variables at all. A SOCKS URL may also require a client-specific syntax. Set variables temporarily for a single diagnostic command when possible, then remove them after testing so they do not unexpectedly affect Docker, language package managers, cloud CLIs, or internal services.
HTTPS_PROXY=http://127.0.0.1:YOUR_MIXED_PORT \
HTTP_PROXY=http://127.0.0.1:YOUR_MIXED_PORT \
brew update --verbose
Node, Python, Rust, Go, Ruby, and Java tooling each has its own history of proxy behavior. npm may read environment variables and npm configuration; pip can use configuration files; Cargo can use environment variables or its own network settings; Go may decide between direct and proxy module access according to GOPROXY. Do not create a single giant rule set merely because several tools install packages. Instead, observe which host each tool contacts and give shared registries a coherent route while preserving direct access to private package servers.
Homebrew also checks the local environment more broadly than many users expect. A stale proxy variable, an old Git setting, a corporate certificate requirement, or an incorrect system clock can produce errors that look like Clash failures. Before changing rules, compare the command with Clash disabled, then repeat it with Clash enabled and the same shell environment. The comparison is not about proving that “direct is better”; it isolates whether the failure belongs to the path, the application, or the upstream service.
Keep remote development sessions stable
Remote development tools are more sensitive than ordinary page loads because they may maintain several concurrent channels: an initial HTTPS login, an SSH bootstrap, a websocket for terminal or editor events, and a separate tunnel for file synchronization or port forwarding. A rule that selects a different node for each new connection can create inconsistent source IPs, session cookies, or long-lived transport behavior. For these tools, stability is usually more valuable than the lowest latency result from a single probe.
Select a reliable group for the entire remote-development workflow during testing. Avoid combining a fast but unstable node for authentication with a slower node for the editor tunnel unless the application explicitly supports that architecture. If the tool opens a browser for login, compare the browser’s observed domains with the terminal logs. Authentication may succeed while the later gateway or websocket host remains unreachable, which creates the confusing impression that credentials are invalid.
Websocket failures deserve special attention. A normal HTTPS request may receive a quick response, while a websocket upgrade is rejected by a proxy, interrupted by an idle timeout, or routed to an exit that does not preserve the expected session. Inspect Clash connection logs during the exact moment the editor disconnects. Look for repeated reconnects, changes in policy group, DNS mismatches, and connections that remain pending without receiving a server response.
SSH-based remote development adds another layer. The editor may invoke the system’s OpenSSH binary, an embedded SSH implementation, or a helper process inside WSL. Confirm which executable is actually running and test the same command outside the editor. If ordinary SSH remains stable but the editor disconnects, inspect its keepalive, server installation, port-forwarding, and shell initialization settings rather than repeatedly changing Clash nodes.
DNS mode can affect developer tooling in subtle ways. A hostname may resolve to an address that is reachable only through a particular route, while fake-IP or local resolution changes what the application sees. Keep the resolver strategy consistent during diagnosis and read the client’s DNS logs where available. Do not mix a manually hard-coded hosts entry with rule changes unless you document it; otherwise, a later developer may spend hours debugging Clash for a mapping that lives in an unrelated file.
Diagnose failures with evidence and maintain the setup
Use a repeatable sequence whenever a developer command fails. First, record the exact command, destination, timestamp, and whether the client is in system proxy, rule, or tunnel mode. Second, reproduce a simple request to the same hostname with a known tool such as curl. Third, watch the Clash connection log while running the failing command. If no connection appears, the application is bypassing the listener, resolving another hostname, or failing before network access. If a connection appears and is rejected, inspect the selected rule and policy group. If it connects but stalls, compare DNS, TLS, idle timeout, and upstream health.
- Check local listeners: confirm that the configured HTTP, SOCKS, and mixed ports are open and owned by the intended Clash process.
- Check application settings: inspect Git configuration, shell variables, SSH configuration, WSL networking, and package-manager settings independently.
- Check rule matching: verify the actual hostname, not merely the product name shown in a menu or error message.
- Check the selected group: use a stable, known-good policy during diagnosis instead of a rapidly changing latency group.
- Check upstream response: compare timeout, TLS, authentication, and HTTP status behavior before declaring the proxy broken.
Maintainability matters as much as the first successful clone. Keep developer rules narrow and comment why a special route exists. Put specific Git hosting, registry, and remote-development rules above broad geographic or catch-all rules. Review remote rule providers after updates because a new rule can change a previously reliable destination without any local edit. Export a backup of the working profile and record the client version, core version, listener ports, and important application settings.
Security should remain part of the workflow. Never paste private access tokens, SSH private keys, or full verbose logs into a public issue. Keep private Git hosts and internal package registries on their required route. Avoid disabling certificate validation to make a clone succeed, and do not assume that a proxy provider is appropriate for source code, package credentials, or deployment tokens. A technically successful connection can still violate an organizational data-handling rule.
Compared with browser-only proxy extensions, a Clash setup gives Git, SSH-compatible tooling, Homebrew, and remote-development processes a visible policy layer instead of leaving each application to guess its own route. Lightweight per-app proxy utilities can be simpler for one terminal command, but they often lack unified rule logs, mixed-protocol handling, and a practical way to compare several developer flows. Clash V.CORE is a stronger fit when you need one maintainable profile, clear connection observability, stable policy groups, and flexible handling for both macOS and Windows workflows; after validating your organization’s requirements, you can download Clash V.CORE and build the routing baseline described here.
// Editor's Pick
Clash V.CORE for developer networking
Keep Git, SSH, Homebrew, registries, and remote development sessions visible and manageable from one practical routing workspace.
- Clear rules for Git hosting and package registries
- Stable groups for long-running SSH sessions
- HTTP, SOCKS, and mixed-port listener support
- Connection logs for fast hostname diagnosis
- Flexible workflows across macOS and Windows