Clash TUN Proxy Setup For Developers: Git, npm, And AI Tools

The bouncing latency number in a client's panel is often treated as the sole proof that a line is "good." But between 80ms and a genuinely smooth connection sit four hidden factors: the test target, packet loss rate, bandwidth bottlenecks, and link congestion. This article breaks down how the latency number is actually measured, what it does and doesn't reflect, and offers several self-test methods that better mirror real browsing conditions.

Why a Browser Proxy Is Not Enough for Development

A browser can usually use the HTTP proxy configured by Clash, but development tools do not share one universal networking model. Git may use its own proxy settings or inherit variables from the shell. npm, pnpm, and Yarn may read package-manager configuration files. Docker separates the host network from build-time and run-time containers. A language server or AI coding assistant may use a desktop runtime, a background process, or a command-line helper with completely different environment variables.

This is why a browser can open a code-hosting website while git clone fails, or why a package registry works in the browser but npm install returns a timeout. The system proxy toggle mainly affects applications that explicitly honor the operating system's HTTP or SOCKS settings. It does not automatically intercept every TCP connection created by every process.

Clash TUN mode solves this at a different layer. Instead of asking each application to understand a proxy protocol, the client creates a virtual network interface and captures traffic from the operating system. The mihomo core then applies DNS handling, rule matching, and proxy selection to connections that would otherwise leave through the normal network route. This is particularly useful for tools that have no proxy setting, tools that only support one proxy type, and tools launched by scripts or IDE extensions.

Key point: TUN mode is a traffic-capture mechanism, not a replacement for every application-level proxy setting. Use it as the broad routing layer, then keep explicit Git, npm, and container settings only where they improve reliability or cover a separate network namespace.

Before changing configuration, identify the scope of the problem. If only a browser fails, check the browser and system proxy. If command-line tools fail but the browser works, inspect shell variables and application settings. If the host works but a container fails, configure the container or Docker daemon separately. This classification prevents a common mistake: repeatedly changing Clash rules when the traffic never reaches the Clash core in the first place.

Enable TUN Mode Without Breaking the Host Network

In Clash Verge Rev, Mihomo-based clients, and similar desktop interfaces, TUN mode is normally found under settings, services, or network options. The exact label varies, but the underlying requirements are similar: the core must support TUN, the client must be allowed to create a virtual network interface, and the operating system must permit the required route and DNS changes.

  1. Import and activate a working configuration first. Confirm that the client can reach a simple test domain in rule mode before enabling TUN.
  2. Enable the TUN option and grant administrator privileges when the operating system asks for them. Without elevated permission, the virtual interface may fail to start or may disappear after a short delay.
  3. Keep the client in rule mode rather than global mode for normal development work. Rules let domestic, local, and private destinations remain direct while selected code-hosting and registry domains use a proxy group.
  4. Enable the client's DNS service if you need domain-based matching for applications that do not use the system proxy. If Fake-IP is enabled, review exclusions for local domains and software that expects real address responses.
  5. Test the host with both a domain and an IP address. A successful browser page alone does not prove that command-line or UDP traffic is being captured.

A minimal Mihomo-style TUN section may look like this:

tun:
  enable: true
  stack: mixed
  dns-hijack:
    - any:53
  auto-route: true
  auto-detect-interface: true

Not every client exposes every field, and a subscription may already provide a TUN block. Do not paste a second competing block into an automatically generated configuration without checking the final merged result. The mixed stack is often a practical starting point because it can handle common TCP and UDP workloads through the platform's supported TUN implementation, but compatibility depends on the client, operating system, and core version.

Note: TUN changes routing at the system level. If it starts successfully but the entire network stops working, disable TUN from the client, restore the previous system proxy state, and inspect the core logs before trying another configuration. Avoid deleting network adapters or changing random routes while the client is still running.

DNS deserves separate attention. Domain rules such as DOMAIN-SUFFIX,github.com,Proxy require Clash to know the original domain. With Fake-IP, the core can map a synthetic address back to its domain before applying rules. With Redir-Host, the application receives a real address and the result depends more heavily on how the connection is intercepted. Local development domains, private corporate zones, and services that reject synthetic addresses may need entries under fake-ip-filter or a direct DNS policy.

Build Rules for Code Hosts, Registries, and Documentation

A developer-oriented rule set should be narrow enough to preserve direct access for ordinary traffic and broad enough to cover the domains actually used by tools. Matching only the main code-hosting website is rarely sufficient. Git operations may contact a web domain, an API domain, a release asset domain, or an object-storage endpoint. Package managers may follow redirects to a registry mirror or a content delivery domain.

Start with explicit domain suffixes for services you know you use:

rules:
  - DOMAIN-SUFFIX,github.com,DeveloperProxy
  - DOMAIN-SUFFIX,githubusercontent.com,DeveloperProxy
  - DOMAIN-SUFFIX,githubassets.com,DeveloperProxy
  - DOMAIN-SUFFIX,npmjs.org,DeveloperProxy
  - DOMAIN-SUFFIX,npmjs.com,DeveloperProxy
  - DOMAIN-SUFFIX,registry.npmjs.org,DeveloperProxy
  - DOMAIN-SUFFIX,pypi.org,DeveloperProxy
  - DOMAIN-SUFFIX,pythonhosted.org,DeveloperProxy
  - DOMAIN-SUFFIX,registry-1.docker.io,DeveloperProxy
  - DOMAIN-SUFFIX,docker.com,DeveloperProxy
  - DOMAIN-SUFFIX,openai.com,DeveloperProxy
  - DOMAIN-SUFFIX,anthropic.com,DeveloperProxy
  - DOMAIN-SUFFIX,local,DeveloperDirect
  - IP-CIDR,127.0.0.0/8,DeveloperDirect,no-resolve
  - IP-CIDR,192.168.0.0/16,DeveloperDirect,no-resolve
  - IP-CIDR,10.0.0.0/8,DeveloperDirect,no-resolve
  - MATCH,DIRECT

The group names in this example must exist in proxy-groups. Replace DeveloperProxy and DeveloperDirect with the names used by the active configuration. A rule pointing to a nonexistent group will not produce the intended result, even if the syntax looks correct.

Do not blindly proxy every domain containing a vendor name. A suffix rule can capture telemetry, login endpoints, package downloads, and unrelated subdomains. Start with the connection log, record the domains contacted by a failing command, and add only the domains needed for that workflow. When a service uses a new asset domain, the log gives a much clearer answer than guessing from the visible website address.

Rule order matters. Clash evaluates rules from top to bottom and uses the first match. Put specific developer rules before broad geographic, keyword, or final-match rules. Keep local networks above MATCH, and use no-resolve on private IP rules when DNS resolution would be unnecessary or could create a loop.

Practical method: run the failing command once, open the Clash connection log, filter by the process or destination, and classify each request as code hosting, registry, authentication, asset delivery, local service, or unrelated telemetry. Convert only the first five categories into rules.

Configure Git and Package Managers Deliberately

With TUN enabled, Git often works without any additional configuration because its TCP connections are captured by the virtual interface. An explicit Git proxy can still be useful on systems where TUN is unavailable, on remote shells, or when a particular Git process bypasses the expected route. The important part is to use the proxy protocol and local port exposed by the Clash client.

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

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

The h in socks5h tells the client to resolve the hostname through the SOCKS proxy. That can prevent local DNS resolution from selecting an unreachable address. Do not configure both HTTP and SOCKS values randomly; choose the port that the active Clash profile actually exposes. To inspect or remove an old setting, use:

git config --global --get-regexp 'http\..*proxy'
git config --global --unset http.proxy
git config --global --unset https.proxy

For npm, the equivalent settings are stored in npm configuration. A temporary shell variable is useful for one command, while a persistent npm setting affects future projects:

npm config set proxy http://127.0.0.1:7890
npm config set https-proxy http://127.0.0.1:7890
npm config get proxy
npm config get https-proxy

If the package manager is already successfully captured by TUN, adding an explicit proxy may be unnecessary. It can also become a problem when the client is stopped: npm will continue trying to connect to a proxy port that no longer exists. Keep a documented reset command available:

npm config delete proxy
npm config delete https-proxy

pnpm and Yarn have their own configuration layers but commonly honor environment variables and npm-compatible registry settings. A project may also contain a local .npmrc that overrides the user-level configuration. When results differ between a shell and an IDE terminal, compare the output of npm config list in both environments instead of assuming they use the same file.

Registry selection should be separated from proxy routing. A registry mirror may improve speed for one region, while Clash rules determine whether the connection uses a proxy. Changing both at once makes failures difficult to diagnose. First test the configured registry directly, then inspect Clash logs, then decide whether the registry URL or the route needs adjustment.

Handle Docker, Containers, SSH, and Remote Development

Containers are a frequent source of confusion because TUN captures host traffic, but container networking can involve a separate namespace, a virtual bridge, and a daemon process. A browser on the host may work perfectly while docker build cannot download a base image. In that case, check whether the Docker daemon is running inside a desktop VM, a native service, or a remote machine. The correct proxy location depends on that architecture.

For a Linux container that should use the host's HTTP proxy, pass the proxy explicitly and make the host address reachable from the container:

docker run --rm \
  -e HTTP_PROXY=http://host.docker.internal:7890 \
  -e HTTPS_PROXY=http://host.docker.internal:7890 \
  -e NO_PROXY=localhost,127.0.0.1,.local \
  node:latest node --version

The special hostname is supported by common desktop container environments, but it is not universal on native Linux. On Linux, you may need to add a host gateway mapping or use the bridge gateway address. Also confirm that the Clash listener is bound to an address reachable from the container. A listener bound only to 127.0.0.1 may accept host connections while rejecting connections arriving from the container network.

Build-time and run-time proxy settings are separate. A package download in a Dockerfile occurs during the image build, while the application may need proxy variables after the container starts. Configure both only when required, and keep internal services in NO_PROXY. Typical entries include database hosts, service names, loopback addresses, private domains, and the container platform's internal DNS name.

SSH uses its own transport rather than HTTP. TUN can capture SSH's TCP connection if the route and rules allow it, but an explicit SOCKS jump configuration may be more predictable for one host:

Host code-host
  HostName ssh.example.invalid
  User git
  ProxyCommand connect -S 127.0.0.1:7891 -a none %h %p

The command shown requires a separate SOCKS-aware helper and is only an example of the architecture. If the helper is not installed, remove the SSH override instead of leaving a broken ProxyCommand in the user configuration. For remote development over SSH, remember that commands run on the remote machine use the remote machine's DNS, proxy environment, and Clash availability. A working local TUN setup does not automatically route remote shell traffic through the local client.

Route AI Coding Assistants and IDE Background Processes

AI coding assistants are often harder to diagnose because the visible editor is not always the process making the request. An extension may call a language server, a helper executable, a desktop companion, or a background service. Some components honor system proxy settings; others read HTTP_PROXY, HTTPS_PROXY, and NO_PROXY; a few use their own configuration panel.

Set environment variables for command-line assistants and tools launched from a shell:

# POSIX shell
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
export NO_PROXY=localhost,127.0.0.1,::1,.local

# PowerShell
$env:HTTP_PROXY="http://127.0.0.1:7890"
$env:HTTPS_PROXY="http://127.0.0.1:7890"
$env:ALL_PROXY="socks5h://127.0.0.1:7891"

Do not export these values globally if local development services must remain isolated or if the proxy port is not always available. A project-specific launcher script is safer. The same principle applies to IDEs: an integrated terminal may inherit shell variables, while the IDE process itself may have started before those variables were defined.

When an AI tool reports authentication failure, distinguish a network failure from an account or endpoint problem. A timeout, connection reset, or DNS error usually points to routing, DNS, TLS interception, or a blocked destination. A fast HTTP response with an explicit authorization error means the request reached the service and should be investigated at the tool or account layer. Clash logs can show the destination and final rule, but they cannot validate an API key or repair an expired login session.

Security note: proxy environment variables can be inherited by child processes and may appear in diagnostic output. Never paste tokens, authorization headers, or complete authenticated URLs into a public log. Keep credentials in the tool's supported credential store and use the proxy only for transport.

Diagnose Failures from the Process Outward

When one development command fails, avoid changing five settings at once. Use a short sequence that identifies the layer where traffic stops:

  1. Check that the Clash core is running and that the active profile contains the expected proxy group and rules.
  2. Confirm the local listener ports with the client settings. A common error is using the HTTP port as a SOCKS port, or using a port from an old profile.
  3. Test DNS separately with the same hostname used by the tool. Compare a normal lookup with a request made through the configured proxy.
  4. Run the command with verbose logging. Git, npm, Docker, and many AI tools provide a debug or verbose mode that reveals redirects and connection stages.
  5. Watch the Clash connection log while the command runs. If no connection appears, investigate environment inheritance, TUN capture, container isolation, or the application's own network stack.
  6. If a connection appears, inspect the matched rule, selected group, destination domain, and final error. A DIRECT match, timeout, TLS failure, and remote authorization response require different fixes.

Common symptoms are highly specific. “Could not resolve host” points toward DNS, a blocked resolver, or a container-specific resolver. “Connection refused” often means the local proxy port is wrong or the Clash client is stopped. “Connection reset” can come from an unsuitable route, a remote policy, or an intermediate network device. A TLS certificate error should not be fixed by disabling certificate verification globally; first check system time, certificate stores, transparent interception, and whether the selected proxy path is appropriate.

If TUN causes local services to fail, add precise direct rules and Fake-IP exclusions for the affected domains. If a package manager works only after setting an explicit proxy, compare the process environment and verify whether the application bypasses the TUN interface. If direct traffic is unexpectedly proxied, inspect rule order and the final MATCH behavior.

A stable developer setup usually has three properties: TUN handles applications that cannot be configured individually, explicit proxy settings are limited to tools that genuinely need them, and rules are derived from connection logs rather than a huge copied list. Keep a small change record for proxy ports, DNS mode, TUN options, and package-manager settings. That record makes the next client update, profile replacement, or operating-system migration much easier to recover from.

Download Client
Download Client