Repository navigation
Feature: macOS system proxy discovery for proxy: "auto" (slice 2 of #1525) #5853
Description
Area
Proxy and routing
What are you trying to accomplish?
Run OpenCodex on macOS while switching local proxy/VPN clients frequently (Clash Verge, Shadowrocket, a corporate VPN, and so on). Each switch moves the local proxy port. Today every such change silently breaks outbound requests with 502 Provider unreachable until config.proxy is updated by hand and the service is restarted.
On Windows, proxy: "auto" (#1525) already removes that maintenance. macOS has no equivalent, so a macOS user is left with the exact workflow #1525 set out to fix.
What prevents this today?
proxy: "auto" is Windows-only. In src/config/proxy-env.ts, applyProxyEnvWith() takes the "auto" branch, calls readWindowsSystemProxy(), and on macOS the reader returns kind: "unsupported", logging:
[opencodex] proxy "auto": only Windows system proxy discovery is supported; using direct egress on this OS
So on macOS the setting degrades to direct egress — which is precisely the case that fails when the OpenAI endpoints are only reachable through a local proxy.
There is no macOS reader wired into that call site, even though the test seam already accepts an injectable platform. macOS exposes the system proxy through the standard system configuration, so the missing piece is a reader, not an architectural change.
One implementation trap is worth recording, because it makes the obvious approach produce a false negative: on macOS the per-service queries (networksetup -getwebproxy <service> and friends) reported Enabled: No on every configured network service while the system proxy was in fact active and in use. Proxy clients commonly publish the proxy through the session-scoped system configuration dynamic store, which scutil --proxy (SCDynamicStoreCopyProxies) reports but the per-service preference reads do not. A macOS reader therefore has to be built on the dynamic store, not on networksetup.
What should OpenCodex do?
When config.proxy is "auto" on macOS, read the current macOS system proxy at startup and mirror it into HTTP_PROXY/HTTPS_PROXY, matching the Windows slice:
- HTTP/HTTPS proxy enabled → mirror them; never copy the literal
"auto"into the environment - proxy disabled, not configured, or unreadable → direct egress, routing unchanged
- precedence identical to Windows: a pre-existing
HTTP_PROXY/HTTPS_PROXYin the environment wins and the system proxy is not consulted - the same one-line
proxy "auto": ...startup banner naming the outcome
Two macOS-specific design questions I would rather settle before writing code:
-
SOCKS-only. Windows falls back to direct on a SOCKS-only system proxy, because
HTTP_PROXYcannot express it. On macOS a SOCKS-only system proxy is an ordinary configuration.config.proxyalready acceptssocks5://URLs and validates the scheme, so the macOS reader could map a SOCKS-only system proxy tosocks5://host:port(plusALL_PROXY) instead of giving up. Should it do that, or stay consistent with the Windowskind: "socks-only"→ direct behaviour? -
Refresh. Feature: auto-detect Windows system proxy with smart fallback ("proxy": "auto") #1525 slice 1 is deliberately a single startup read. If the proxy port changes while the service is already running, the mirrored value goes stale and the original symptom returns. Is a re-read — on connectivity failure, or on an interval — in scope here, or deliberately out of scope for this slice?
Example usage or interface
# today on macOS — the "auto" value silently degrades to direct egress
$ ocx config set proxy auto
$ ocx start
[opencodex] proxy "auto": only Windows system proxy discovery is supported; using direct egress on this OS
outbound proxy: (none)
# expected on macOS with a local proxy listening on 127.0.0.1:1082
$ ocx config set proxy auto
$ ocx start
[opencodex] proxy "auto": using macOS system proxy HTTP 127.0.0.1:1082, HTTPS 127.0.0.1:1082
outbound proxy: http://127.0.0.1:1082
The values come from the dynamic store, in this shape:
$ scutil --proxy
<dictionary> {
ExceptionsList : <array> {
0 : *.local
1 : localhost
}
ExcludeSimpleHostnames : 1
HTTPEnable : 1
HTTPPort : 1082
HTTPProxy : 127.0.0.1
HTTPSEnable : 1
HTTPSPort : 1082
HTTPSProxy : 127.0.0.1
ProxyAutoConfigEnable : 0
ProxyAutoDiscoveryEnable : 0
SOCKSEnable : 0
}
HTTPSEnable/HTTPSProxy/HTTPSPort and SOCKSEnable/SOCKSProxy/SOCKSPort follow the same shape, and ExceptionsList has an obvious noProxy mapping if that is wanted. ProxyAutoConfigEnable (PAC) and ProxyAutoDiscoveryEnable (WPAD) are the macOS analogues of the Windows unsupported cases and could keep the same "cannot express → direct egress" outcome.
Alternatives or workarounds
Workarounds in use or considered:
- Hardcode
config.proxyto the current port and edit it whenever the proxy client changes port — the manual maintenance Feature: auto-detect Windows system proxy with smart fallback ("proxy": "auto") #1525 exists to remove. - Run the proxy client in a TUN / full-tunnel mode so direct egress is intercepted below the application layer. It works, but it hides the misconfiguration rather than fixing it, and it changes the machine's whole network posture in order to route one client.
- An external launcher wrapper that reads
scutil --proxy, probes the reported port, and re-runsocx start --socks5 127.0.0.1:<port>before the client launches. This works and is effectively the macOS implementation of the missing slice, but it lives outside OpenCodex, has to re-implement the--socks5plumbing, and every macOS user would have to reinvent it.
I searched existing issues and the documentation for an existing macOS proposal and found none; #1525 is Windows-scoped and closed.
Additional context
Related: #1525 (Windows system proxy auto-detect with smart fallback — the slice 1 precedent), #2894 (SOCKS5 outbound provider calls, including fail-fast on unsupported proxy schemes), #5119 (SOCKS5 routing documentation alignment).
Source pointers: src/config/proxy-env.ts — applyProxyEnvWith() holds the "auto" branch and documents the injectable platform / reader test seam; the Windows reader is readWindowsSystemProxy.
I am willing to implement the macOS slice with regression tests against the existing seam if the direction above is acceptable. I would just like the answers to the two design questions first, so the tests assert the behaviour you actually want.
Checks
- I searched existing issues and documentation.
- This request describes a concrete OpenCodex workflow rather than merely naming a desired technology.
- I removed secrets and personal data.
Activity
merge: sync upstream v2.66.0 stable (87a78e5..e70b3d8)
feat(proxy): macOS system proxy auto-discovery (lidge-jun#5853)
lidge-jun commentedon Sep 27, 2026
Resolved on dev by #6124 (merge commit 296f0ce): macOS system proxy discovery for proxy: "auto" is now available. It ships with the next release.