Skip to main content

2 posts tagged with "Claude-Code"

View all tags

Fix WSL2 Cannot Access Windows Host Proxy — Three Invisible Pitfalls

¡ 5 min read

Encountered this issue while using AI coding tools (Claude Code, Roo) in WSL2 that need to access APIs through the Windows host proxy. After fixing the firewall, encountered two more hidden pitfalls. Documenting all root causes and solutions.

TL;DR​

WSL2's vEthernet (WSL) virtual NIC is created on every launch. Windows Firewall cannot assign a Network Profile to it, so all inbound rules are ineffective (EnforcementStatus: NotApplicable). Don't add rules — disable the firewall on that interface directly:

# Run in Windows PowerShell (Administrator)
Set-NetFirewallProfile -DisabledInterfaceAliases "vEthernet (WSL)"

Additionally, after fixing the firewall, you may encounter two more pitfalls:

  1. Dynamic IP Issue: Host IP changes after WSL/Windows restart
  2. Config Cache Issue: Stale API keys in ~/.claude.json and ~/.claude/settings.json cause auth conflicts

Problem​

Environment: Windows 10 21H2 + WSL2 2.5.10.0 (NAT mode), Clash Verge on host (port 7897, Allow LAN enabled).

Symptoms:

# Ping host from WSL — no response
ping 172.22.80.1

# Test proxy port — no response
nc -zv 172.22.80.1 7897

# Claude Code / Roo error
# API Error: ConnectionRefused

# But direct external access works fine
curl https://example.com # OK

On the Windows side, Clash is healthy: netstat shows 0.0.0.0:7897 listening, and Test-NetConnection localhost 7897 succeeds.

Root Cause 1: Firewall Blocking​

vEthernet (WSL) is a virtual NIC dynamically created by WSL2 on every launch. Windows Firewall's Network Profiles (Domain / Private / Public) cannot be associated with this interface.

This means:

  1. Firewall inbound rules bind to Profiles
  2. vEthernet(WSL) belongs to no Profile
  3. All inbound rules show EnforcementStatus: NotApplicable for this interface
  4. Rules are simply skipped — not denied, not evaluated at all

No amount of port rules or InterfaceAlias bindings will work, because the rules never execute against this interface.

Solution 1: Fix Firewall with One Command​

Step 1: Confirm the Root Cause​

In Windows PowerShell (Administrator):

# Check the virtual NIC
Get-NetAdapter | Where-Object { $_.Name -like "*WSL*" }

# Check rule enforcement status
Get-NetFirewallRule -DisplayName "*7897*" |
Get-NetFirewallInterfaceFilter |
Get-NetFirewallPortFilter |
Format-Table -Property * -AutoSize

If rules exist but WSL still can't connect, Profile enforcement is the issue.

Step 2: Fix with One Command​

# Disable firewall on the WSL virtual NIC only
Set-NetFirewallProfile -DisabledInterfaceAliases "vEthernet (WSL)"

Effects:

  • Only applies to the vEthernet (WSL) virtual NIC
  • Physical adapters (Wi-Fi, Ethernet) remain fully protected
  • Setting persists across reboots

Step 3: Verify​

# Test connectivity from WSL
nc -zv 172.22.80.1 7897
# Output: Connection to 172.22.80.1 7897 port [tcp/*] succeeded!

# Test proxy
curl -x http://172.22.80.1:7897 https://api.anthropic.com

Root Cause 2: Dynamic IP Changes​

After fixing the firewall, proxy may still fail. Why? vEthernet (WSL) IP changes on every launch.

If you hardcoded the IP in .bashrc like:

export http_proxy=http://172.22.80.1:7897  # This IP may change!

Fix: Dynamically detect host IP in .bashrc:

# Auto-detect host IP from DNS server
export WINDOWS_IP=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')
export http_proxy="http://${WINDOWS_IP}:7897"
export https_proxy="http://${WINDOWS_IP}:7897"

Root Cause 3: Config File Cached Keys​

After fixing firewall and dynamic IP, Claude Code/GLM may still report auth conflicts. Why? Stale keys cached in:

  1. ~/.bashrc global export of ANTHROPIC_API_KEY
  2. ~/.claude.json stores previously approved keys in customApiKeyResponses.approved
  3. ~/.claude/settings.json may have hardcoded environment variables

When switching to GLM mode, unset ANTHROPIC_API_KEY works temporarily, but bashrc reload re-exports it. Claude Code reads all three sources and reports conflict.

Solution 3: Clear Cached Keys​

# 1. Check for conflicts
echo $ANTHROPIC_API_KEY $ANTHROPIC_AUTH_TOKEN

# 2. Clear ~/.claude.json cache
cat ~/.claude.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('customApiKeyResponses', {}))"

# 3. Check ~/.claude/settings.json
cat ~/.claude/settings.json | grep -A2 '"env"'

Fix: Remove hardcoded values from settings.json:

python3 -c "
import json
with open('/home/aptop/.claude/settings.json') as f:
d = json.load(f)
d['env'].pop('ANTHROPIC_API_KEY', None)
d['env'].pop('HTTPS_PROXY', None)
d['env'].pop('HTTP_PROXY', None)
with open('/home/aptop/.claude/settings.json', 'w') as f:
json.dump(d, f, indent=2)
"

For ~/.claude.json, manually edit the file to remove stale entries from customApiKeyResponses.approved.

Important Notes

  • Firewall Fix

    • If your Clash port is not 7897, replace it with your actual port — the key is fixing the firewall interface, not the port
    • WSL updates or major Windows updates may reset the virtual NIC config; re-run the same command if the issue recurs
    • Windows 10 does not support WSL2's mirrored networking mode (only Windows 11 23H2+), do not try this direction
  • Dynamic IP

    • Always use dynamic IP detection in .bashrc — never hardcode the host IP
    • The DNS server IP in /etc/resolv.conf is stable across WSL restarts
  • Config Cache

    • After clearing cached keys, restart Claude Code to apply changes
    • If auth still fails, check all three sources: environment variables, ~/.claude.json, and ~/.claude/settings.json

Troubleshooting Checklist (For Future Reference)​

  1. echo $ANTHROPIC_API_KEY $ANTHROPIC_AUTH_TOKEN — confirm if both exist (conflict)
  2. cat ~/.claude.json | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('customApiKeyResponses', {}))" — check cached keys
  3. cat ~/.claude/settings.json | grep -A2 '"env"' — check for hardcoded env vars
  4. curl https://open.bigmodel.cn — confirm GLM API is accessible

Dead Ends: 5 Directions Ruled Out​

For anyone currently troubleshooting, here are the paths already confirmed as dead ends:

#DirectionResultReason
1Proxy environment variablesRuled out.bashrc unset/export pattern is by design for model switching
2Clash Allow LAN not enabledRuled outAllow LAN is on, listening on 0.0.0.0:7897, localhost works
3Firewall port ruleRuled outAdded port 7897 inbound rule, still blocked — NotApplicable
4Bind rule to InterfaceAliasRuled outSet-NetFirewallRule -InterfaceAlias "vEthernet (WSL)" had no effect
5Mirrored networking modeRuled outWindows 10 does not support it

The key insight: We kept trying to add rules, but the problem wasn't missing rules — it was that rules don't apply to this interface at all.


Save 70% of Your AI Coding Plan Quota by Replacing ZhiPu Search with Tavily MCP

¡ 3 min read

When using ZhiPu GLM Coding Plan with Claude Code, I noticed my monthly quota draining faster than expected. The culprit? Built-in MCP tools — web-search-prime and web-reader — were consuming coding conversation quota for every web search and page fetch.

TL;DR​

Replace ZhiPu's built-in web-search-prime and web-reader MCP services with Tavily MCP. Result: free 1000 searches/month with zero impact on coding quota.

The Problem: Every Search Costs Quota​

ZhiPu GLM Coding Plan includes several built-in MCP services:

web-search-prime   → web search (consumes quota)
web-reader → web page reading (consumes quota)
zread → GitHub repo reading (consumes quota)

In my case, searching WooCommerce documentation, reading API pages, and checking marketplace standards during theme development consumed roughly 30% of my monthly MCP quota in just a few days.

MCP usage over one week showing search and reader consuming most calls

The 16% / 30% usage shown above was reached in less than a week, with web search being the primary consumer.

Solution: Tavily MCP​

Tavily provides a free tier with 1000 API calls/month, completely independent of your coding plan quota.

Step 1: Get Tavily API Key​

Register at tavily.com, free tier includes 1000 calls/month.

Step 2: Add Tavily MCP to Claude Code​

claude mcp add tavily-search -s user -- npx -y tavily-mcp@latest

Step 3: Configure API Key​

Edit ~/.claude.json, find the tavily-search entry and add the environment variable:

{
"mcpServers": {
"tavily-search": {
"type": "stdio",
"command": "npx",
"args": ["-y", "tavily-mcp@latest"],
"env": {
"TAVILY_API_KEY": "tvly-your-key-here"
}
}
}
}

Step 4: Remove ZhiPu's search services​

claude mcp remove web-search-prime -s user
claude mcp remove web-reader -s user

Also clean up settings.json permissions — remove mcp__web-search-prime__* and mcp__web-reader__* from the allow list, add mcp__tavily-search__* instead.

Step 5: Verify​

claude mcp list
# Should show: tavily-search: npx -y tavily-mcp@latest - Connected
# Should NOT show: web-search-prime, web-reader

Comparison​

FeatureZhiPu Built-inTavily MCP
CostConsumes coding plan quotaFree 1000 calls/month
Search qualityOptimized for ChineseBalanced for EN/CN
Page extractionSeparate toolBuilt-in extract
ConfigurationPlatform-injected, can't disableOne claude mcp add command
After free tierSqueezes coding conversation budgetPay-as-you-go continues

Notes​

Important Notes

  1. ZhiPu services are platform-injected — they may reappear after restart even after removal. Add them to settings.json deny list to block permanently.
  2. Keep zread (GitHub repo reading) — low consumption and unique functionality.
  3. Keep doubao-vision (image analysis) — Tavily doesn't cover this scenario.

Recommendation​

Also using ZhiPu GLM Coding Plan?

Learn More About ZhiPu GLM Coding Plan