Clash Developer Setup: Proxy Git, SSH & Homebrew

GitHub clones stall, SSH sessions fail, and package downloads time out when developer traffic bypasses the proxy. This guide shows engineers how to connect Clash with terminal tools, TUN mode, and practical routing rules for a smoother coding workflow.

Map the developer traffic path before changing settings

Developer tools do not all use the same network path. A browser may follow the operating system proxy, while Git reads its own configuration, OpenSSH uses its own connection rules, and Homebrew delegates downloads to tools such as curl, git, or Ruby-based fetchers. This is why enabling the system proxy can make a web page load while git clone, ssh -T [email protected], or brew install still hangs.

A useful troubleshooting model has three layers. First, the Clash or mihomo core must be running and listening on a local inbound port. Second, the developer tool must be configured to send traffic to that port, unless TUN mode is capturing the traffic transparently. Third, the active routing rules must send the destination to a usable policy group. A failure in any layer can look like a generic timeout.

Tool Typical default behavior Recommended control point
Git over HTTPS Uses Git configuration and sometimes environment variables git config or temporary proxy variables
Git over SSH Uses OpenSSH configuration, not Git’s HTTP proxy setting ~/.ssh/config and a SOCKS-aware command
Homebrew Uses its download tools, Git, and the shell environment Environment variables, Git settings, and Clash rules
Docker or language package managers Varies by daemon, shell, and package manager Tool-specific proxy configuration or TUN mode

In FlClash, Clash Verge Rev, ClashX, or another graphical client, first confirm the active core, the current configuration, and the local port. A common configuration is mixed-port: 7890, which accepts HTTP and SOCKS5 connections on one port. Some clients instead expose separate ports such as 7890 for HTTP and 7891 for SOCKS5. Never assume the port from an online tutorial is correct; inspect the client’s settings or generated YAML.

mixed-port: 7890
mode: rule
allow-lan: false
external-controller: 127.0.0.1:9090
log-level: info

Keep allow-lan: false unless another device genuinely needs to use this computer as a proxy. Binding a proxy to all interfaces can expose it to the local network. If LAN access is required, restrict the listening address with the client’s supported options, set an authentication policy where available, and review firewall rules before testing development traffic.

Configure Git over HTTPS without hiding the failure

GitHub and other code hosts commonly support repository access over HTTPS. This is usually the simplest path to proxy because Git understands an HTTP proxy URL and can use a Clash mixed port for both HTTP and HTTPS requests. The proxy URL describes the local connection from Git to Clash; it does not mean that Git should use the remote website’s URL as a proxy.

For a temporary test, set the proxy only for one command. This keeps the result easy to compare with a direct connection:

git -c http.proxy=http://127.0.0.1:7890 \
    clone https://github.com/example/project.git

If the test works, configure Git globally for future HTTPS operations:

git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890

When the Clash inbound is SOCKS5-only, use a SOCKS URL instead:

git config --global http.proxy socks5h://127.0.0.1:7891
git config --global https.proxy socks5h://127.0.0.1:7891

The socks5h form asks the proxy to resolve the hostname. That can be useful when local DNS resolution is unreliable or when the routing decision should be made using the destination domain. With socks5, hostname resolution may occur locally depending on the library and command path, which can produce inconsistent results.

Inspect and remove stale Git proxy settings

A frequent cause of confusion is an old proxy saved months earlier. Check where the current value comes from:

git config --show-origin --get-regexp 'http\..*proxy|https\..*proxy'
git config --global --list --show-origin | grep -i proxy

If the port belongs to a closed Clash process, Git may report Could not connect to proxy, Connection refused, or wait until its timeout expires. Remove the global setting when you want Git to follow another method:

git config --global --unset http.proxy
git config --global --unset https.proxy

Git can also inherit proxy variables from the shell. These variables are convenient for a short development session, but they affect more commands than Git:

export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5h://127.0.0.1:7891

git ls-remote https://github.com/example/project.git

Do not set incompatible HTTP and SOCKS values randomly. Use the protocol that the local Clash port actually supports, and keep the variable names consistent with the tool being tested. To return the shell to its previous state, use unset HTTP_PROXY HTTPS_PROXY ALL_PROXY. Lowercase variants such as http_proxy and https_proxy may also be read by Unix tools, so check them when behavior remains unexpected.

Route Git SSH through a SOCKS5 proxy

Git’s http.proxy setting does not affect repositories whose remote starts with git@ or uses an ssh:// URL. Those connections are opened by OpenSSH. When SSH traffic bypasses Clash, port 22 may stall even though HTTPS cloning works. The usual solution is to let OpenSSH create a connection through the local SOCKS5 inbound.

On many systems, the OpenSSH client includes a netcat implementation with SOCKS support. Add a host-specific entry to ~/.ssh/config:

Host github.com
    HostName github.com
    User git
    Port 22
    IdentityFile ~/.ssh/id_ed25519
    ProxyCommand nc -x 127.0.0.1:7891 -X 5 %h %p
    ServerAliveInterval 30
    ServerAliveCountMax 3

The -x option identifies the SOCKS proxy, -X 5 selects SOCKS5, and %h and %p expand to the target host and port. The exact nc flags differ between macOS, BSD, and Linux packages. If the command returns an “unknown option” error, check the installed netcat variant rather than changing the SSH key or repository permissions.

Some installations provide a separate proxy helper. For example, a SOCKS-aware utility can be used as the ProxyCommand instead. The important requirement is that the helper supports SOCKS5 and passes the destination hostname and port correctly. Avoid using a plain nc %h %p command: it opens a direct connection and does not involve Clash.

GitHub also provides an SSH endpoint on port 443, which can be useful on networks where outbound port 22 is filtered. Use a separate alias so existing repository URLs remain unchanged:

Host github-ssh
    HostName ssh.github.com
    User git
    Port 443
    IdentityFile ~/.ssh/id_ed25519
    ProxyCommand nc -x 127.0.0.1:7891 -X 5 %h %p
    ServerAliveInterval 30
    ServerAliveCountMax 3

Then test the alias directly:

ssh -T git@github-ssh

To use it for a repository, either clone with the alias:

git clone git@github-ssh:example/project.git

or change an existing remote:

git remote set-url origin git@github-ssh:example/project.git
git remote -v

Run SSH in verbose mode when the connection still fails:

ssh -vvv -T git@github-ssh

Make Homebrew and package downloads use the same route

Homebrew operations combine several kinds of traffic. A formula or cask may come from a bottle URL, metadata may be fetched from a repository, and taps may use Git. Consequently, a working Git proxy does not guarantee that brew install will work, and a successful browser download does not prove that Homebrew can reach its bottle host.

Start by testing the shell environment for the current terminal session:

export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=socks5h://127.0.0.1:7891

brew update
brew install jq

Use a small package for the first test rather than a large SDK or compiler toolchain. Watch the Clash connection panel while the command runs. You should see the relevant domains and the selected policy group. If no connection appears, Homebrew or its underlying process is not inheriting the variables, or the traffic is being handled by another network layer.

Homebrew’s Git-based taps still obey Git’s configuration. Check both the environment and Git values before changing anything:

env | grep -i proxy
git config --show-origin --get-regexp 'http\..*proxy|https\..*proxy'
brew config

Some corporate networks require a custom certificate authority for HTTPS inspection. Do not disable TLS verification globally to bypass certificate errors. Instead, install the organization’s trusted certificate through the operating system or configure the specific tool according to the organization’s security policy. A certificate error and a proxy timeout are different failures and should not be treated with the same workaround.

If Homebrew continues to bypass the explicit proxy, TUN mode may be a better fit. Enable TUN only after confirming that the client has the required administrator or VPN permissions, then test with a command that does not set proxy variables. On macOS and Linux, TUN can capture applications that ignore the system proxy, but it also changes DNS and route behavior. Disable the shell variables during this test to avoid sending TUN-captured traffic into an explicit proxy again.

Write rules for development domains rather than every port

Routing by domain is generally easier to maintain than routing every TCP connection on a port. A minimal rule section might look like this:

rules:
  - DOMAIN-SUFFIX,github.com,Developer
  - DOMAIN-SUFFIX,githubusercontent.com,Developer
  - DOMAIN-SUFFIX,githubassets.com,Developer
  - DOMAIN-SUFFIX,homebrew.sh,Developer
  - DOMAIN-SUFFIX,brew.sh,Developer
  - DOMAIN-SUFFIX,rubygems.org,Developer
  - DOMAIN-SUFFIX,pypi.org,Developer
  - DOMAIN-SUFFIX,registry.npmjs.org,Developer
  - MATCH,DIRECT

Replace Developer with the actual policy group name in the imported configuration. The order matters: Clash evaluates rules from top to bottom. If a broad MATCH,DIRECT rule appears first, later developer-specific rules will never be reached. Likewise, if an earlier rule sends these domains to REJECT or a different group, moving the new rules below it will not fix the result.

Do not add every service domain from an unverified list without review. GitHub, package registries, release CDNs, container registries, and company services can change their hostnames. Begin with the domain shown in the Clash log, add only necessary suffixes, and confirm that the rule does not accidentally route internal company domains through a public proxy. For private repositories, DNS services, artifact servers, and self-hosted Git platforms, use the organization’s approved routing policy.

Verify the path with layered tests

Testing one command at a time makes the result meaningful. First check whether Clash is listening locally:

curl -x http://127.0.0.1:7890 -I --connect-timeout 10 https://github.com
curl --proxy socks5h://127.0.0.1:7891 -I --connect-timeout 10 https://github.com

These tests validate the HTTP and SOCKS paths separately. A successful response proves that the local inbound accepted the request and that the selected policy could reach the destination. It does not prove that Git or SSH uses the same path.

Next test Git without modifying the working tree:

GIT_CURL_VERBOSE=1 git ls-remote https://github.com/example/project.git

For SSH, inspect the effective configuration and then connect verbosely:

ssh -G github-ssh | grep -E 'hostname|port|proxycommand'
ssh -vvv -T git@github-ssh

Finally, test Homebrew and observe the Clash logs at the same time:

brew update
brew fetch --force jq

Interpret the evidence in order. If curl through the local port fails, fix Clash, the port, or the active policy before touching Git. If curl works but git ls-remote fails, inspect Git configuration and inherited variables. If HTTPS Git works but SSH fails, inspect ProxyCommand, the SOCKS port, SSH host aliases, and authentication separately. If all explicit proxy tests work but a tool still bypasses them, enable TUN or configure that tool’s own proxy support.

Developer proxy FAQ

Why does HTTPS cloning work while SSH cloning times out?

Git HTTPS uses Git’s HTTP or SOCKS proxy setting, but SSH is controlled by OpenSSH. Configure a SOCKS5-aware ProxyCommand in ~/.ssh/config, confirm that it points to the correct Clash SOCKS or mixed port, and test the SSH alias with ssh -vvv. If port 22 is filtered, try the code host’s supported SSH-over-443 endpoint rather than changing unrelated Git settings.

Which Clash port should terminal tools use?

Use the port shown by the active client and configuration. A mixed-port such as 7890 can accept HTTP and SOCKS5 requests, while a separate SOCKS port may be required for OpenSSH. Do not copy a port from another computer or assume that the graphical client’s control port is a traffic proxy port; external-controller is for API control, not ordinary web requests.

Should TUN mode replace proxy environment variables?

Not always. Explicit variables are clearer for Git and package managers that support them, while TUN is useful for applications that ignore proxy settings. Use one method while diagnosing a problem. If TUN is enabled, temporarily clear HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY to determine whether the application is already captured transparently.

Why does Homebrew still time out after Git is configured?

Homebrew downloads may use different tools and domains from Git taps. Test the shell proxy variables, run brew config, inspect the Clash connection log, and identify the exact host that fails. Add a narrow domain rule or use TUN when the download process does not inherit the shell environment. Keep TLS verification enabled and solve certificate errors through the trusted certificate configuration instead of disabling security checks.

FlClash Downloads View clients for every platform