dsh-proxy
> 🌐 English | 中文
DSH global proxy manager — configure system proxy / manual proxy graphically in the DHS settings page under "General Settings". The config is persisted to ~/.dsh/settings.yaml and injected as environment variables when DSH-GUI launches, so the entire DHS network stack (LLM calls / built-in search / MCP client) goes through the proxy.
DHS network stack & proxy mechanics (background)
Current state: DHS connects directly
Every network request in DHS goes through Node's global fetch() — LLM calls (llm-deepseek/adapter.ts), built-in search/fetch tools (web-search-*, web-fetch-http), MCP clients (AnySearch and other Streamable HTTP services) — the whole chain has no custom proxy dispatcher (no ProxyAgent / EnvHttpProxyAgent found in the source).
This leads to three facts:
1. Node's fetch() does not read the Windows system proxy. The ProxyServer in the registry Internet Settings (e.g. 127.0.0.1:7897) only affects WinHTTP apps like browsers; Node completely ignores it. 2. Node 24+ supports environment-variable proxies. With NODE_USE_ENV_PROXY=1, the global fetch() reads HTTP_PROXY / HTTPS_PROXY / NO_PROXY. 3. DSH's proxy variables are bootstrap-only (an app-boot security design): HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY can only be provided by the process environment that launches DSH — .env files are forbidden from setting them (prevents a malicious .env from redirecting network traffic to an attacker's proxy).
Conclusion: making DSH use a proxy = inject env vars before launch
NODE_USE_ENV_PROXY=1
HTTP_PROXY=http://127.0.0.1:7897
HTTPS_PROXY=http://127.0.0.1:7897
NO_PROXY=localhost,127.0.0.1 # loopback (e.g. local MCP servers) bypasses the proxyWhat this plugin does: graphical config in settings
DHS natively has no proxy configuration entry (you can only set env vars manually in the launching shell). This plugin turns proxy config into a single row in DHS settings → "General Settings":
- Toggle switch: master switch — proxy env vars are only injected when enabled
- Mutually exclusive options (choose one):
- Use system proxy by default: reads the ProxyServer from the Windows registry Internet Settings (auto-prepends http://) - Manual config: fill in the proxy address directly; default http://127.0.0.1:7897, backspace to change the port
- Save hint: "Restart the app after saving to apply" — proxy env vars are injected at host startup, so changing the config requires a host restart
- Persistence: written to the
proxy:section of~/.dsh/settings.yaml(shape-preserving read/write — other sections and comments in the file are kept)
The UI matches DHS native settings rows (figma Setting-Cell): title 14px/400, selector h36 r18, --dsw-alias-bg-module-platform background, solid accent toggle --dsw-alias-accent, inputs aligned with native Input (h32/r8/bg-layer-1, brand-color highlight on focus), fonts inherit the system font stack (zh/en bilingual).
Coordination: who does the injection
The plugin itself only handles config persistence and display (it runs inside the host process, whose env is fixed at startup — changing env vars at runtime has no effect on already-initialized fetch).
The actual injection is done by whoever launches DSH:
| Launch method | Injection implementation |
|---|---|
| DSH-GUI (recommended) | the main process reads the proxy section of settings.yaml when starting the host → resolves the proxy address (mode: system reads the registry / mode: manual uses the url) → injects NODE_USE_ENV_PROXY=1 + HTTP(S)_PROXY + NO_PROXY=localhost,127.0.0.1 → spawns the host |
| dsh web directly | no GUI injection — set the env vars manually in the launching shell (see "Conclusion" above) |
DSH-GUI injection log: [dsh-gui] host proxy: http://127.0.0.1:7897 (NODE_USE_ENV_PROXY=1).
HTTP API
| Method | Path | Description |
|---|---|---|
| GET | /dsh-proxy/get | Read the current proxy config { enabled, mode, url } and the config file path |
| POST | /dsh-proxy/update | Write the proxy config (shape-preserving update of the proxy: section in settings.yaml) |
Install
# From GitHub (first install requires allowing the build; dsh will prompt you to add the package key to the profile's pnpm-workspace.yaml allowBuilds)
dsh plugin add github:EricXu20266/dsh-proxy
# Or from npm (prebuilt artifacts, no build authorization needed)
dsh plugin add dsh-proxyUsage
After installing, restart dsh, go to Settings → General Settings, and find the "System Proxy" row:
1. Turn on the toggle switch 2. Choose "Use system proxy by default" (reads the registry) or "Manual config" (fill in the proxy address; default http://127.0.0.1:7897) 3. Click "Save", then restart the app to apply
Once active, DHS's LLM calls, built-in search, and MCP clients all go through the proxy (loopback excluded). Turn the toggle off and save to restore direct connection.
Development
pnpm install
pnpm build # tsc compiles host side → lib/
pnpm bundle:client # tsdown bundles client side → client/client.js> During development, if the profile references this repo via a file: dependency, you must manually sync build artifacts into the profile's node_modules after changes (pnpm file: deps are copied once and don't watch source changes), then restart the host.
License
MIT