Skip to content

fix(proxy): honor Windows system proxy and PAC settings - #571

Open
nadavsinai-philips wants to merge 1 commit into
codemie-ai:mainfrom
nadavsinai-philips:users/nadav/fix-proxy
Open

nadavsinai-philips wants to merge 1 commit into
codemie-ai:mainfrom
nadavsinai-philips:users/nadav/fix-proxy

Conversation

@nadavsinai-philips

@nadavsinai-philips nadavsinai-philips commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Summary

On Windows behind a corporate PAC-based proxy (Zscaler and similar), codemie setup fails at "Fetching available projects" with Request timeout, even though a browser reaches the same instance fine.

Root cause: the core HTTPClient builds raw https.request options with no agent, and Node's http/https modules never consult proxy configuration on their own. Every CodeMie API call went direct and hung. Setting HTTPS_PROXY did not help either, because nothing on that code path read it — only ProxyHTTPClient (the runtime LLM proxy) had proxy support.

This makes the CLI resolve a proxy itself, so no manual env var is needed:

  • Per-request resolution in HTTPClient (both request() and the redirect-following getRaw() path), in precedence order:
    1. HTTPS_PROXY / HTTP_PROXY / NO_PROXY — explicit overrides still win, so existing setups are unchanged
    2. Windows Internet Settings — static ProxyServer, or AutoConfigURL (PAC)
  • PAC evaluation via pac-resolver inside the QuickJS WASM sandbox rather than node:vm. PAC scripts are fetched over plain HTTP from whatever AutoConfigURL points at, so a hostile or MITM'd PAC must not be able to reach the host process.
  • Reachability probing when a PAC returns several proxies — the first that answers a TCP connect wins, so a dead first entry doesn't stall every request. (Observed in practice: one Zscaler node returned in 0.7s while another timed out after 41s.)
  • Loopback is never proxied, keeping the CLI's own LLM proxy on 127.0.0.1 reachable.
  • ProxyHTTPClient and spawned agent CLIs: the proxy daemon seeds HTTP(S)_PROXY / NO_PROXY from the proxy resolved for its real --target-url, so both inherit working settings without each needing its own detection.
  • Opt out with CODEMIE_NO_SYSTEM_PROXY=1.

Also removes ~160 lines of NO_PROXY parsing that ProxyHTTPClient carried privately, moving it into the shared module. The shared version additionally understands the Windows token forms <local>, <-loopback> and *.example.com.

New dependencies

pac-resolver (+ quickjs-wasi), adding 8 packages total: pac-resolver, degenerator, ast-types, escodegen, esprima, netmask, quickjs-wasi, source-map. All MIT/BSD; license-check passes. Both are lazily imported, so users without a PAC never load them.

Cost

Resolution is cached per process. On a PAC machine the first request pays ~1.8s (registry read + PAC fetch + WASM init); subsequent resolutions are ~0ms, and a different host is ~19ms. Windows without a PAC pays one reg query. Non-Windows is a no-op.

Test plan

  • npm run typecheck — clean
  • npm run lint — clean (--max-warnings=0)
  • npm run build — clean
  • npm run license-check — clean
  • vitest --project unit — 279 files, 4054 passed
  • vitest --project cli — 37 files, 279 passed
  • Existing proxy-http-client.test.ts NO_PROXY routing tests still pass unchanged after the refactor
  • PAC path, real network: verified on a Zscaler PAC host with all proxy env vars unset — registry PAC detected, correct proxy auto-selected, loopback resolved DIRECT, and HTTPClient.getRaw() against the previously-timing-out /v1/llm_models endpoint returned 200 in 2.5s
  • Static path, new unit tests (src/utils/__tests__/system-proxy.test.ts, registry stubbed so they run on any platform): bare host:port; per-protocol http=..;https=.. selection and http fallback; ProxyEnable=0 meaning direct; *.domain and <local> ProxyOverride bypasses; loopback never proxied; HTTPS_PROXY overriding the registry; CODEMIE_NO_SYSTEM_PROXY=1 skipping detection without spawning reg
  • Interactive codemie setup against an on-prem instance behind a PAC proxy — reaches the project list
  • Sanity check on macOS/Linux that behavior is unchanged (detection is Windows-gated)

Note: the local pre-commit gitleaks scan was skipped via the hook's documented CODEMIE_SKIP_SECRETS_SCAN=1 (no Docker daemon on the dev machine). CI gitleaks still covers this PR; the diff contains no credentials.

Comment thread .husky/pre-commit Outdated

@vadimvlasenko vadimvlasenko left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this — the Windows/PAC proxy support is a real gap and this is a solid step toward fixing it. I ran a full review and found a couple of things that need attention before merge, mostly around two files that look like they may have been included by accident, plus some gaps in the new proxy code. Left inline notes on each one below so they're easy to find. Happy to help however's useful — thank you for the contribution!

Comment thread .codemie/codemie-cli.config.json Outdated
Comment thread .husky/pre-commit Outdated
Comment thread src/utils/__tests__/system-proxy.test.ts
Comment thread src/utils/system-proxy.ts Outdated
Comment thread src/agents/core/BaseAgentAdapter.ts Outdated
Comment thread src/providers/core/base/http-client.ts Outdated
Comment thread src/cli/commands/proxy/connectors/vscode-claude-code.ts Outdated
@nadavsinai-philips
nadavsinai-philips force-pushed the users/nadav/fix-proxy branch 2 times, most recently from b749ddd to d6095c6 Compare September 22, 2026 17:08

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants