Transparently proxy to expose the Gemini Code Assist API through standard APIs that you can plug into different tools such as OpenCode or Xcode
┌───────────────┐ ┌───────────────────┐ ┌───────────────────────┐
│ External Tool │ │ Proxy │ │ Google Cloud Endpoint │
│ (OpenCode/etc)│ │ (Local or Worker) │ │ (Gemini Code Assist) │
└───────┬───────┘ └─────────┬─────────┘ └───────────┬───────────┘
│ │ │
│ Standard API Request │ Internal API Request │
│ ─────────────────────────▶ │ ─────────────────────────────▶ │
│ (Gemini or OpenAI format) │ (Wrapped + OAuth credentials) │
│ │ │
│ │ │
│ Standard API Response │ Internal API Response │
│ ◀───────────────────────── │ ◀───────────────────────────── │
│ (Unwrapped + SSE Stream) │ (JSON or Internal Stream) │
│ │ │
▼ ▼ ▼
This proxy exposes Gemini Code Assist through:
/v1beta/<model>:streamGenerateContentfor Gemini API compatible clients/v1/chat/completionsfor OpenAI API compatible clients (experimental)
To run locally, or to deploy to Cloudflare Workers
Option 1 (recommended): prebuilt binary via npm (macOS, Linux, Windows)
npm install -g @dvcrn/gemini-code-assist-proxyOption 2: install from source with Go
go install github.com/dvcrn/gemini-code-assist-proxy/cmd/gemini-code-assist-proxy@latest
Then to start:
ADMIN_API_KEY=123abc gemini-code-assist-proxy
On first launch, it will attempt to copy your OAuth chain from ~/.gemini/oauth_creds.json when running locally
For hosted version, see the docs below
You can use either the native Gemini-supported API at http://localhost:9877/v1beta, or the OpenAI transform endpoint at http://localhost:9877/v1/messages
Recommended to use the Google / Gemini API when available as it's the native format
"gemini": {
"npm": "@ai-sdk/google",
"name": "Code Assist",
"options": {
"baseURL": "http://localhost:9877/v1beta",
"apiKey": "xxxx" # whatever you set as ADMIN_API_KEY
},
"models": {
"gemini-3-flash-preview": {
"name": "Gemini 3 Flash (Code Assist)"
},
"gemini-3-pro-preview": {
"name": "Gemini 3 Pro (Code Assist)"
},
}
}, "gemini": {
"name": "Code Assist",
"options": {
"baseURL": "http://localhost:9877/v1",
"apiKey": "xxxx" # whatever you set as ADMIN_API_KEY
},
"models": {
"gemini-3-flash-preview": {
"name": "Gemini 3 Flash (Code Assist)"
},
"gemini-3-pro-preview": {
"name": "Gemini 3 Pro (Code Assist)"
},
}
},The proxy supports two main authentication methods, with the following order of precedence:
- GCP Project ID: If you set the
CLOUDCODE_GCP_PROJECT_IDenvironment variable, the proxy will use this ID for all requests. This method is suitable for users who want to use a specific GCP project. - OAuth Credentials (Automatic Discovery): If
CLOUDCODE_GCP_PROJECT_IDis not set, the proxy will attempt to automatically discover a project ID using your OAuth credentials. It loads credentials in the following order:CLOUDCODE_OAUTH_CREDS_PATH: The file path to youroauth_creds.jsonfile.- Default Location:
~/.gemini/oauth_creds.json(the default Gemini CLI location)
CLOUDCODE_OAUTH_CREDS: The raw JSON content of your credentials.
- Set an
ADMIN_API_KEYenvironment variable and set your IDE or editor to pass it along as Gemini API Key
Configure the proxy using environment variables:
| Variable | Description | Default | Workers Setup |
|---|---|---|---|
PORT |
The port for the proxy server. | 9877 |
Not applicable |
CLOUDCODE_GCP_PROJECT_ID |
The Google Cloud Project ID. | (none) | wrangler secret put CLOUDCODE_GCP_PROJECT_ID |
ADMIN_API_KEY |
Secure key for protecting admin endpoints | (none) | wrangler secret put ADMIN_API_KEY |
CLOUDCODE_OAUTH_CREDS_PATH |
Path to the oauth_creds.json file. |
(none) | Use Admin API instead |
CLOUDCODE_OAUTH_CREDS |
Raw JSON content of the credentials. | (none) | Use Admin API instead |
SSE_BUFFER_SIZE |
Buffer size for SSE streaming pipeline | 3 |
Environment variable |
DEBUG_SSE |
Enable detailed SSE event logging | false |
Environment variable |
Note: For Cloudflare Workers deployment, OAuth credentials are managed via the Admin API instead of environment variables or files.
For production deployment on Cloudflare Workers:
-
Create KV namespace (required for credential storage):
wrangler kv namespace create "gemini-code-assist-proxy-kv"This will output a namespace ID. Add it to your
wrangler.toml:kv_namespaces = [ { binding = "gemini_code_assist_proxy_kv", id = "YOUR_NAMESPACE_ID_HERE" } ]
-
Build for Workers:
mise run build-worker
-
Deploy to Cloudflare:
wrangler deploy
-
Set up Admin API Key (required for credential management):
# Generate a secure admin key (alphanumeric only, URL-safe) head -c 32 /dev/urandom | base64 | tr -d "=+/" | tr -d "\n" | head -c 32 # Store it as a secret in Workers wrangler secret put ADMIN_API_KEY
-
Upload OAuth credentials (see Admin API section below)
The Admin API provides secure endpoints for managing OAuth credentials. This is essential for deployments that don't have access to the local filesystem.
All admin endpoints require authentication via one of these methods:
Authorization: Bearer YOUR_ADMIN_API_KEYheaderkey=YOUR_ADMIN_API_KEYquery parameter
Security Note: The admin API key prevents unauthorized access to credential management endpoints. Keep this key secure and never commit it to version control.
Updates OAuth credentials stored in Cloudflare KV. Accepts the exact same JSON format as ~/.gemini/oauth_creds.json:
curl -X POST https://your-worker.workers.dev/admin/credentials \
-H "Authorization: Bearer YOUR_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d @~/.gemini/oauth_creds.jsonResponse:
{
"success": true,
"message": "Credentials saved successfully"
}Check the status of stored OAuth credentials:
curl https://your-worker.workers.dev/admin/credentials/status \
-H "Authorization: Bearer YOUR_ADMIN_API_KEY"Response:
{
"type": "oauth",
"hasCredentials": true,
"provider": "CloudflareKVProvider",
"is_expired": false,
"expiry_date": 1752516043000,
"expiry_date_formatted": "2025-07-14T17:53:04Z",
"has_refresh_token": true
}-
Generate and set admin key:
# Generate admin key (alphanumeric only, URL-safe) ADMIN_KEY=$(head -c 32 /dev/urandom | base64 | tr -d "=+/" | tr -d "\n" | head -c 32) echo "Generated admin key: $ADMIN_KEY" # Set it in Workers wrangler secret put ADMIN_API_KEY
-
Upload OAuth credentials:
# Replace with your actual worker URL and admin key WORKER_URL="https://your-worker.workers.dev" ADMIN_KEY="YOUR_ADMIN_API_KEY" # Upload credentials from local file curl -X POST $WORKER_URL/admin/credentials \ -H "Authorization: Bearer $ADMIN_KEY" \ -H "Content-Type: application/json" \ -d @~/.gemini/oauth_creds.json
-
Verify credentials:
# Check credential status curl $WORKER_URL/admin/credentials/status \ -H "Authorization: Bearer $ADMIN_KEY"
Transforms standard Gemini API paths to Gemini Code Assist's internal format:
- From:
/v1beta/models/gemini-1.5-pro:generateContent - To:
/v1internal:generateContent
Automatically converts model names to Gemini Code Assist's supported models:
- Any model containing "pro" →
gemini-2.5-pro - Any model containing "flash" →
gemini-2.5-flash - Any model containing "lite" →
gemini-2.5-flash-lite
Examples:
gemini-1.5-pro→gemini-2.5-progemini-1.5-flash→gemini-2.5-flashgemini-pro-latest→gemini-2.5-pro
The proxy uses a goroutine pipeline for efficient SSE streaming:
- Reader goroutine: Reads from Code Assist response
- Transformer goroutine: Transforms Code Assist SSE to Gemini format
- Writer goroutine: Writes to client with immediate flushing
Tune the pipeline buffer size with SSE_BUFFER_SIZE (default: 3).
The proxy maintains persistent HTTP/2 connections to Code Assist:
- Max idle connections: 100
- Max idle connections per host: 10
- Idle connection timeout: 90 seconds
Code Assist can take 7+ seconds to start streaming responses. This is normal behavior from the Code Assist API, not a proxy issue. Enable debug logging to see detailed timing:
export DEBUG_SSE=trueIf you receive 401 errors:
- Check that
CLOUDCODE_OAUTH_CREDScontains valid OAuth tokens - Refresh your OAuth tokens if they've expired
- Ensure your GCP project has Gemini Code Assist API access
Enable detailed logging:
export DEBUG_SSE=true # Show SSE event timingCheck logs for:
- Request transformation details
- Code Assist response times
- SSE event delivery timing