dsh-cliproxy
August 23, 2026 · View on GitHub
Routes Claude, OpenAI/Codex, and Gemini through Antigravity OAuth in DeepSeek Harness through one local CLIProxyAPI instance.
The Gemini route uses your Google/Antigravity account — not a Gemini API key. CLIProxyAPI owns the browser login, refresh token, Google project, native request fingerprint, and translation; this plugin is its OpenAI-compatible DSH client.
| DSH provider | Authentication owned by CLIProxyAPI |
|---|---|
cliproxy-claude | Claude Code subscription |
cliproxy-openai | Codex/OpenAI subscription |
cliproxy-gemini | Google Antigravity OAuth |
Install
dsh plugin --profile web add github:DevViking-Persike/dsh-cliproxy
Restart DSH. All three routes then appear in the model catalog.
Gemini / Antigravity Login
CLIProxyAPI 7.x already implements the public Antigravity OAuth client. Run this once:
cliproxyapi -config /opt/homebrew/etc/cliproxyapi.conf -antigravity-login
Authorize the Google account in the browser. CLIProxyAPI writes antigravity-<email>.json under its configured auth-dir (normally ~/.cli-proxy-api) and refreshes it itself. This DSH plugin never reads the Google access or refresh tokens.
The key named below is only the local proxy's access control between DSH and 127.0.0.1:8317; it is not a Gemini API key. For a loopback endpoint, the plugin reads the first api-keys entry from the local CLIProxyAPI config by default, so no environment variable is required and the key is never displayed.
Requirements
- A running CLIProxyAPI instance; default endpoint
http://127.0.0.1:8317/v1. - For Gemini, a completed
-antigravity-login. - Either a proxy access key in the harness credential store /
CLIPROXY_API_KEY, or a readable local proxy config. Local config discovery is allowed only for loopback URLs; a local key is never sent to a remote endpoint implicitly.
Configuration
Every field is optional.
| Field | Default | Meaning |
|---|---|---|
baseURL | http://127.0.0.1:8317/v1 | Endpoint including /v1. |
apiKeyEnv | CLIPROXY_API_KEY | Optional credential reference/environment variable for the proxy access key. |
proxyConfigPath | /opt/homebrew/etc/cliproxyapi.conf | Local CLIProxyAPI YAML from which the first proxy access key may be read. |
readLocalProxyKey | true | Allow local config discovery for loopback endpoints only. |
claudeModels | six Claude entries | Catalog for cliproxy-claude; a supplied array replaces the default. |
openaiModels | five GPT entries | Catalog for cliproxy-openai. |
geminiModels | eight Gemini entries | Antigravity catalog for cliproxy-gemini. |
streamIdleTimeoutMs | 300000 | Budget between stream reads. |
defaultContextWindow | 200000 | Context assumed for an uncatalogued model. |
maxTokens | 32000 | Default output cap. |
retryPolicy | normal, 3 retries | Merged over the harness-compatible default. |
- id: dsh-cliproxy
name: dsh-cliproxy
config:
baseURL: http://127.0.0.1:8317/v1
geminiModels:
- id: gemini-pro-agent
name: Gemini 3.1 Pro High
contextWindow: 1048576
maxTokens: 65535
Why the Proxy Owns Antigravity
A direct client is significantly more than an OAuth bearer token. The upstream wire requires:
- Google OAuth scopes and the registered Antigravity public client;
- project discovery/onboarding through
loadCodeAssist; daily-cloudcode-pa.googleapis.com/cloudcode-pa.googleapis.comrouting;- an
antigravity/hub/<version>user agent and HTTP/1.1 fingerprint; - a Gemini body nested inside an Antigravity envelope with project, request, and session ids;
- tool-schema sanitization, encrypted reasoning replay, model-specific output caps, and token refresh.
CLIProxyAPI already owns and tests those facts. Duplicating them here would produce two token writers and a second independently drifting protocol implementation. This plugin therefore sends OpenAI-compatible streaming requests to the loopback proxy and never copies Google's client secret or account tokens.
Model Experience
The adapter is transparent to the model: it registers provider routes and streams responses, adding no tool, prompt section, or context. Usage counts are disjoint — inputTokens excludes cache reads already counted inside prompt_tokens.
Text only. Image, audio, and video are refused before a request is sent, although some Antigravity models support them upstream; this adapter's serializer does not yet preserve those inputs.
Safety
- Google access/refresh tokens remain entirely inside CLIProxyAPI's
auth-dir. - The proxy access key is read per request and never enters an error or log. Local-config discovery is disabled automatically for non-loopback destinations.
- A truncated stream raises
STREAM_CLOSEDinstead of looking complete. retry-afterreaches the harness retry plugin; idle timeout measures server silence, never a slow consumer.- Chunk fields are checked at load against a fixed payload, so harness protocol drift refuses to mount instead of corrupting tool calls silently.
Known Limitations
- Model catalogs are static defaults copied from CLIProxyAPI's Antigravity registry; an uncatalogued model still resolves when named explicitly. Supplying
geminiModelsreplaces the defaults. - No image/audio/video serialization yet.
- The plugin has no settings-directory entry; it is configured by
cordis.yml. - Tests use local HTTP servers and recorded harness translator/serializer output. Real OAuth and model availability remain vendor-controlled.
Tests
npm install && node --test test/*.test.js
64 tests, no network and no credential required.