Clash Developer CLI Proxy Setup: TUN Routing For DevTools
Why Developer Traffic Needs Clash TUN Mode from Practice
When a browser opens a repository page but git clone fails, the problem is by built-in not the repository itself. Developers use several network stacks during one task: a browser may follow the operating system proxy, Git may use its own HTTP settings, a package manager may read environment variables, and Docker may contact a daemon running in a separate process.
Enabling a system proxy can therefore make documentation load while leaving Git, npm, pnpm, pip, Maven, Go modules, and container image pulls on a direct route.
Clash TUN mode addresses that gap by creating a virtual network control panel and capturing IP traffic before individual applications decide whether to honor an HTTP or SOCKS proxy. The Clash or Mihomo core then applies your profile rules to those connections.
From a developer’s perspective, this is important because a command-line tool does not need native Clash support to benefit from routing. A terminal process that opens a normal TCP or UDP socket can still be classified by the same policy used for other system traffic.
This does not mean TUN mode is a universal “make everything work” switch. It changes the routing boundary, so DNS behaviour, local network access, container networking, VPN conflicts, and administrator permissions all matter.
A solid developer proxy setup will want to make the capture path understandable: identify which process is failing, confirm which hostname it contacts, inspect the matched Clash rule, and only then adjust the profile. That approach is safer than adding a long list of guessed domains or forcing every connection through one unstable proxy group.
Scope note: TUN mode routes traffic through your Clash rules; it does not provide a subscription, bypass access controls, or guarantee that every registry and container mirror is reachable. Use a legitimate provider and keep credentials, tokens, and private repositories protected.
What TUN Captures—and What It Does Not Lessons Learned
A standard mixed port normally exposes HTTP and SOCKS listeners on a local address such as 127.0.0.1:7890. Applications must be configured to use that listener. Git can be configured with git config, curl can receive proxy environment variables, and a good number of package managers can use their own proxy entrys.
This method is precise and easy to disable, but it depends on every tool being configured correctly. It also becomes awkward when a build invokes a nested tool, a language runtime launches a helper process, or a graphical IDE uses a background service with different settings.
TUN mode works at a lower level. Mihomo presents a virtual control panel, receives packets from the operating system, resolves or observes destinations according to its DNS mode, and forwards eligible traffic through the rule engine.
The connection list can then show useful evidence: the process or destination, the selected rule, the proxy group, and whether the connection was sent through DIRECT or a remote node. This is why TUN is often the practical answer for CLI networking with Clash: the application does not have to know that a proxy exists.
There are still important boundaries. A Docker container may use a separate network namespace, while Docker Desktop may place its daemon inside a low-footprint virtual machine. A corporate VPN can install its own routes with a higher ahead of the rest than the TUN control panel.
Local services such as a database at 127.0.0.1, a development server on localhost, or a private subnet such as 192.168.1.0/24 will want to normally remain direct. If you proxy those destinations accidentally, a local application can become slow or unreachable even though public websites work.
DNS deserves special attention. A hostname can resolve to an address before Clash sees the request, or the client can send DNS queries through the TUN stack and apply fake-IP or redirection logic. If your rules depend on domain names but the operating system resolves everything first, the rule view may show an IP-based decision instead of the hostname you expected.
Conversely, fake-IP handling can make a local hostname appear unfamiliar. Do not change several DNS entrys at once. Record the current mode, test one command, inspect the connection log, and make one controlled adjustment.
Prepare a Profile for Repositories and Dependencies in the Wild
Before enabling TUN, check that the active profile contains usable proxy groups and that the selected group is not empty. A profile can be syntactically valid yet unusable when all nodes have expired, the provider has changed a transport field, or the group references a proxy name that no longer exists.
In the client’s profile or configuration view, verify the active core, the current subscription timestamp, and the group selected for developer traffic.
Bring up with a small rule set a bit than rewriting the entire provider configuration.
Development traffic commonly includes source control hosts, package registries, release storage, language module services, and image registries. The exact hostnames depend on your stack, but typical examples include:
- Git hosting:
github.com,api.github.com,raw.githubusercontent.com, release asset domains, and the host used by your organization’s Git service. - JavaScript packages:
registry.npmjs.org, the configured pnpm or npm registry, and the CDN hostname returned for package tarballs. - Python packages:
pypi.org,files.pythonhosted.org, and either private index configured inpip.confor environment variables. - Container images:
registry-1.docker.io,auth.docker.io, vendor registries, and the storage host that serves image layers. - Language modules: Go proxy endpoints, Rust crate registries, Maven repositories, Gradle distribution hosts, or internal artifact servers.
Do not assume that one visible website represents the full transaction. A package manager may first contact a metadata registry, then follow a redirect to a CDN. Docker credential check can use one hostname while image manifests and layers arrive from another.
Git over HTTPS may contact the repository host, while SSH uses a different address and port. Use the connection log during a real command to discover the destinations that your rule list actually needs.
A practical profile separates developer traffic into a named group such as DEV-PROXY or Developer. That group can point to a settled node selection instead of the same general-purpose group used for video or browsing.
Keep private company domains and local services in a direct or corporate-VPN group when required. For example, a conceptual rule order might look like this:
rules:
- DOMAIN-SUFFIX,github.com,Developer
- DOMAIN-SUFFIX,githubusercontent.com,Developer
- DOMAIN,registry.npmjs.org,Developer
- DOMAIN-SUFFIX,pythonhosted.org,Developer
- DOMAIN,registry-1.docker.io,Developer
- DOMAIN-SUFFIX,company.internal,DIRECT
- GEOIP,LAN,DIRECT
- MATCH,Default
The syntax and group names must match your actual Mihomo profile. Put specific domain rules before broad geographic or final match rules.
A rule placed after MATCH, or after a broad GEOIP decision that already wins, will never be reached. Treat the sample as a planning model, not a list to paste blindly.
Enable TUN Mode and Test a Real Workflow Hands-On Notes
Use the following sequence on Clash Verge Rev, Mihomo Party, or another Mihomo-based client.
Labels differ slightly between applications, but the required ideas are the same: activate the profile, grant elevated permission, enable the TUN stack, preserve local routes, and test with observable commands.
- Activate and validate the profile: Select the intended subscription, confirm that the Mihomo core is running, and choose a working proxy group for developer traffic. If the client provides a configuration validation action, be up and running it before changing the network mode.
- Open the TUN settings: Find Settings, General, or Network, then locate the TUN section. Enable the virtual control panel and accept the administrator or system-extension prompt required by your operating system.
- Preserve local connectivity: Turn on entrys such as auto route and strict route only when they match your platform and client documentation. Keep bypasses for loopback, private LAN ranges, your local gateway, and either corporate VPN networks that must remain reachable.
- Choose DNS behaviour deliberately: Use the client’s recommended DNS mode first. If domain rules do not match as expected, inspect the DNS and fake-IP settings instead of adding random IP rules. Exclude internal DNS suffixes when your workplace requires a private resolver.
- Be up and running a low-risk connectivity check: Test a public endpoint with
curl -I https://github.comor another non-sensitive request. Then be up and runninggit ls-remoteagainst a repository you are allowed to access. Watch the Clash connection panel while each command is running. - Test the package and container lanes separately: Use a harmless metadata command such as
npm view,python -m pip index versionswhere supported, ordocker manifest inspect. Do not begin with a large image pull or a production deployment; first confirm which domains appear and which rules win. - Record the result before tuning: Note the operating system, client, core version, TUN status, DNS mode, destination hostname, matched rule, and selected group. This short record makes later troubleshooting much faster than relying on memory.
Use a clean comparison: Be up and running one command with TUN disabled, one with TUN enabled, and one with explicit HTTPS_PROXY variables if appropriate. Comparing these paths tells you whether the failure is caused by application configuration, Clash capture, DNS classification, or the upstream node.
Configure Git, Package Managers, and Docker Without Creating Conflicts from Practice
Even when TUN mode is enabled, explicit application proxy settings can be useful for debugging. They can also create loops or double-proxy behaviour if configured carelessly.
Pick one primary path for normal operation: either let TUN capture the socket, or configure the application to use the local mixed port. Avoid pointing an application at a remote proxy address while TUN is also rewriting the same connection unless you understand the resulting route.
Git over HTTPS and SSH in Practice
For HTTPS repositories, Git can use its own proxy setting. Check the current values with git config --global --get-regexp 'http.*proxy'. If you want TUN to handle Git, remove stale proxy entries and let the socket be captured.
If you need a controlled comparison, configure the local Clash mixed port temporarily, then remove it after testing. A common mistake is leaving an old proxy URL from a previous client, causing Git to connect to a closed port while the new TUN control panel is healthy.
SSH is different. A Git remote such as [email protected]:team/project.git normally opens TCP port 22, while a good number of networks block or interfere with that port. TUN can capture the connection, but the route still depends on your rule set and the node’s ability to carry it.
A handful of developers use an HTTPS remote for simpler proxy behaviour; others configure an SSH host alias that uses an alternate supported endpoint. Do not expose private keys or paste credential check output into public logs while testing.
npm, pnpm, pip, Go, and Maven From Experience
Package managers often perform multiple requests per command. For npm or pnpm, inspect the configured registry with npm config get registry and check whether shell variables such as HTTP_PROXY, HTTPS_PROXY, or NO_PROXY are set.
Metadata may work while the package tarball fails, which by built-in means the redirect or CDN hostname is missing from the effective route. A successful browser visit to the registry homepage does not validate the all-in-one install path.
Python’s pip may use an index URL, a trusted-host exception, a corporate certificate bundle, or a proxy value inside configuration files. Go can use GOPROXY and GONOSUMDB, while Maven and Gradle may read proxy settings from separate XML or properties files.
TUN mode trims the number of per-tool settings, but it does not override application-level TLS verification or credential check. If a command reports a certificate problem message, first distinguish a routing timeout from a trust-store problem.
Docker Desktop and Container Registries Field Notes
Docker is one of the nearly all confusing developer cases because the CLI and daemon are not always in the same network environment. With Docker Desktop, the engine may be up and running inside a managed VM; changing the host shell’s proxy variables may affect the CLI but not the daemon’s image download path.
Configure Docker’s documented proxy settings when required, then verify with a small public image or a manifest request. For a self-hosted Linux daemon, inspect the service environment and restart policy a bit than assuming the interactive shell controls it.
When an image pull fails, read the exact hostname in the problem message. Credential check, manifest lookup, and blob downloads may use different endpoints. A rule for only docker.io may not cover the token service or content delivery host.
Add narrow rules based on observed traffic, keep internal registries on the route they require, and avoid sending confidential image names through an unapproved external node.
Diagnose “Connected but Still Failing” Problems Lessons Learned
The nearly all useful first question is whether the process reached Clash. If the connection panel remains empty while a command is clearly attempting a network request, the traffic may be bypassing TUN, using a separate VM, or failing before DNS and socket creation.
Check that the virtual control panel is present, the client has permission to manage routes, and no second VPN or proxy client has replaced the built-in route. Restarting the client can help after a permission change, but repeated restarts will want to not replace diagnosis.
If the connection appears with DIRECT, inspect rule order and the destination type. A broad final rule, an unexpected IP address, or a DNS mode that hides the original hostname can explain the result.
If the connection uses the intended group but times out, compare another node in the same group and check whether the failure affects only long downloads. Package tarballs and Docker layers can expose bandwidth, MTU, or connection-reset issues that a rapid homepage request never reveals.
For slow commands, separate ping from throughput. Git metadata may be rapid while a large repository stalls because one node handles a good number of parallel object requests poorly. npm may resolve dependencies quickly but download several large archives through a congested CDN route.
Docker may authenticate immediately and then fail on a layer transfer. Use a small reproducible request, avoid changing the selected group during an active transfer, and record timestamps. Switching nodes repeatedly can destroy the evidence because each new connection may match a different route.
Common causes include a stale explicit proxy variable, a wrong NO_PROXY entry, an unavailable local DNS server, a corporate certificate inspection layer, a full disk that looks like a network failure, and a provider rule set that sends engineering domains to DIRECT. On Windows, security software may block the virtual adapter or helper service.
On macOS, a system extension or network permission may need approval. On Linux, firewall rules, NetworkManager, and policy routing can interact with the TUN control panel. Always test local services after enabling TUN; a working public request is not plenty if your development database or Kubernetes API has become unreachable.
Do not disable security controls blindly. If antivirus, Gatekeeper, SmartScreen, or a corporate endpoint policy blocks a helper component, verify the client source, inspect the reported file, and follow the approved exception process.
A proxy client with system-level routing privileges deserves the same caution as either other privileged network software.
Build a Repeatable Daily Workflow in the Wild
Once the initial test succeeds, keep the setup boring. Use one primary Clash client and one active TUN implementation. Keep the profile updated, but review changes to developer rules a bit than accepting every remote override without inspection.
Name the developer proxy group clearly, select a settled route for long downloads, and leave streaming or gaming groups separate so an unrelated activity does not change the path of a package install.
Maintain a small diagnostic checklist in your project notes: the active client and core, TUN status, DNS mode, mixed port, proxy group, NO_PROXY values, Git transport, package registry, and Docker engine location.
When a build fails, capture the command’s hostname and the corresponding Clash rule before editing configuration. This makes support conversations more precise and helps you decide whether the issue belongs to the application, local network, provider, or remote service.
Use exclusions intentionally. Localhost, private development domains, service discovery names, Kubernetes cluster addresses, and internal Git servers may need direct or VPN routing.
Conversely, a broad exclusion such as *.local can accidentally match a public development domain, while an overly broad private-range rule can bypass a required corporate gateway. Review NO_PROXY alongside Clash bypass rules because the application may skip the TUN path before the core has either chance to classify it.
Finally, treat credentials as part of network hygiene. Subscription URLs, registry tokens, Git credentials, Docker login files, and private package indexes will want to never be included in screenshots or shell history shared for troubleshooting.
TUN mode can make more traffic visible in a connection log, but it does not make secrets safe by itself. Use least-privilege tokens, rotate exposed credentials, and prefer private routes for internal repositories whenever your organization provides them.
Compared with browser-only proxy extensions, per-tool environment variables, or older clients that require a separate configuration for every terminal program, the TUN approach gives developers one observable capture path for mixed CLI workloads; its trade-off is that route permissions, DNS, Docker’s separate engine, and local-network exclusions require more deliberate setup.
Clash keeps that process practical with Mihomo-compatible routing concepts, easy to follow client guidance, and troubleshooting steps that connect a failed command to the rule and destination behind it a bit than asking you to guess. If you want to reproduce the workflow with a supported Clash client, download a Clash client and bring up with the profile, TUN, and verification sequence above.