A resilient, cross-platform proxy bridge and zero-correlation privacy shield for OpenCode.
Eliminates shared campus Wi-Fi rate limits (Free usage limit reached / Resets at 5:30 AM) using Cloudflare WARP via a local Privoxy translation bridge, while dynamically randomizing project tracking identifiers on demand.
Install and activate on Linux (CachyOS, Arch, Ubuntu, Debian, Fedora) or macOS:
curl -fsSL https://raw.githubusercontent.com/pritkr/opencode-warp-proxy/main/install.sh | bashTip
This command auto-detects your OS, installs/configures Privoxy, deploys the opencode-proxy CLI to ~/.local/bin, installs the privacy shield plugin, and performs an initial IP rotation & reset.
- The Problem
- How It Works
- Command Reference
- The
resetCommand Explained - Automatic Retry Runner
- Model Selection Gotcha
- Architecture & File Structure
- Compatibility
- License
- Shared IP Depletion: On campus, dorm, or office Wi-Fi, hundreds of students share a single public NAT IPv4 address. OpenCode rate-limits free-tier models (such as
opencode/deepseek-v4.1-flash-free) by public IP in Upstash Redis. When the shared IP runs out of hourly quota, everyone on that Wi-Fi gets blocked. - Bun's SOCKS5 Incompatibility: OpenCode runs on the Bun runtime. Bun's native
fetch()does not supportsocks5://proxy schemes and throwsUnsupportedProxyProtocol. - Session Correlation: OpenCode attaches persistent project identifiers (
x-opencode-project) and directory paths across requests, preventing users from separating conversations or refreshing their rate-limit bucket. - Anti-Bot Throttling: Deleting headers entirely or setting
DO_NOT_TRACK: 1triggers anti-bot scrutiny on the Cloudflare inference gateway, causing stricter rate limits.
flowchart TD
subgraph Client["OpenCode Client (Bun Runtime)"]
CLI["OpenCode CLI / TUI / Daemon"]
Plugin["Privacy Shield Plugin\n(randomizes x-opencode-project)"]
end
subgraph Bridge["Local Proxy Translation Layer"]
Privoxy["Privoxy HTTP Bridge\n(127.0.0.1:8118)"]
WARP["Cloudflare WARP Client\n(Port 40000, MASQUE SOCKS5)"]
end
subgraph Cloudflare["Cloudflare Edge & Gateway"]
Anycast["Rotatable Public Anycast IP\n(warp-cli tunnel rotate-keys)"]
Worker["OpenCode Inference Worker\n(Fresh Quota Bucket)"]
end
CLI -->|model.request| Plugin
Plugin -->|HTTP Proxy| Privoxy
Privoxy -->|forward-socks5| WARP
WARP -->|WireGuard / MASQUE| Anycast
Anycast --> Worker
- WARP in Proxy Mode: Runs Cloudflare WARP locally on port
40000via MASQUE protocol without hijacking your entire system's default network routing. - Privoxy SOCKS5 Bridge: Privoxy listens on port
8118and transparently translates OpenCode's HTTP requests to WARP's SOCKS5 interface. - On-Demand Key Rotation (
reset): Generates new WireGuard/MASQUE cryptographic keys (warp-cli tunnel rotate-keys), immediately acquiring a fresh public egress IP and clearing the rate-limit budget. - Privacy Shield Plugin: Injects standard-format, valid, but strictly randomized 40-character project IDs into outgoing requests. The server sees a 100% normal, valid client with 0% correlation to past sessions.
The opencode-proxy CLI provides simple verbs to manage your connection:
opencode-proxy <command>| Command | Action |
|---|---|
reset |
Full Privacy & Quota Reset: Generates a new random project ID, rotates Cloudflare IP, flushes memory caches, restarts daemon, and actively tests up to 8 IPs until an unexhausted quota is confirmed. |
rotate |
Rotates Cloudflare WARP egress IP and verifies the new IP has fresh quota (retrying automatically if exhausted). |
test |
Quota Diagnostic: Probes the current egress IP against OpenCode and reports whether quota is active or exhausted. |
titles |
Fix Thread Titles: Ensures the title agent is configured with deepseek-v4.1-flash-free and automatically backfills descriptive titles for all untitled sessions. |
status |
Displays WARP connection status, Privoxy state, direct & proxy egress IPs, and current active identity profile. |
on |
Configures WARP proxy mode, starts Privoxy, sets OpenCode daemon proxy environment variables, and enables the privacy plugin. |
off |
Disables proxy environment variables in OpenCode and routes traffic directly. |
run <args> |
Runs an OpenCode prompt with automatic 3x retry and IP rotation if a rate limit is hit. |
Whenever you hit a limit or want to start a completely fresh, uncorrelatable session, run:
opencode-proxy resetHere is exactly what happens under the hood:
[opencode-proxy reset]
│
├── 1. Generate Fresh Cryptographic Rotation Salt
│ ├── Telemetry Salt: Fresh 32-character hex salt in identity.json
│ └── Local Database Preserved: Project records, worktrees & sessions
│ in opencode.db remain 100% UNTOUCHED (useful identifiers intact!)
│
├── 2. Clean Environment & Telemetry Flags
│ ├── Unset DO_NOT_TRACK & OTEL (prevents gateway anti-bot throttling)
│ └── Clear past FreeUsageLimitError banners from session records
│
├── 3. Rotate Cloudflare WARP Egress IP (warp-cli tunnel rotate-keys)
│ └── Requests a fresh Anycast public IP from Cloudflare's regional pool
│
├── 4. Restart Background Daemon (opencode service restart)
│ └── Flushes in-memory connection pools & loads the new salt
│
└── 5. Multi-Attempt Quota Verification (Self-Healing Loop)
└── Actively probes the new IP against OpenCode. If another user
in the region exhausted that specific IP, it automatically
rotates again (up to 8 attempts) until a 100% clean IP is locked in!
Note
Per-Project Isolation & Quota Preservation:
The privacy-shield plugin derives outgoing telemetry IDs per project using HMAC-SHA256(realProjectId, salt).
- Project A and Project B get different virtual project IDs on the server and do not share a quota bucket. Working in Project A will never quickly exhaust Project B's quota!
- When
opencode-proxy resetis run, the salt rotates outgoing project IDs for the server while keeping your local workspace and database identifiers completely intact. - The plugin also subscribes to
session.errorevents to trigger background self-healing rotation automatically if a limit is reached.
You can wrap any OpenCode command to automatically detect rate limits, rotate the IP, and retry:
opencode-proxy run run -m opencode/deepseek-v4.1-flash-free "Your prompt here"If OpenCode exits with Free usage limit reached, the script intercepts the error, calls rotate_ip to grab a fresh Cloudflare egress IP, and retries up to 3 times automatically.
For free-tier usage without an OpenCode Go subscription, always use the standard base model:
opencode run -m opencode/deepseek-v4.1-flash-free "Your message"Warning
Avoid compute-heavy model variants like #high or #max (e.g. deepseek-v4.1-flash-free#max) on the free tier. These variants trigger OpenCode Go subscription requirements (FreeUsageLimitError) regardless of IP.
If your OpenCode sessions were remaining as "Untitled session" or generic timestamps like "New session - 2026-...", here is the exact root cause:
OpenCode generates session titles via an internal background agent named title. Under the hood, OpenCode resolves which model to use via SessionContext.selectTitle:
- If
agents.title.modelis not explicitly declared inopencode.jsonc, OpenCode attempts fallback discovery viaModel.small(providerID). Model.smallhardcodes lookup for families:["gpt-luna", "gemini-flash-lite", "gemini-flash", "claude-haiku"].- For the
opencodeprovider (e.g.deepseek-v4.1-flash-free), none of these model families exist! - The fallback chain fails to resolve any model, causing the title generation task to abort silently and leave threads as generic or untitled.
Explicitly bind the title agent in your ~/.config/opencode/opencode.jsonc:
You can automate this configuration and backfill all past untitled sessions with one command:
opencode-proxy titles| Path | Purpose |
|---|---|
~/.local/bin/opencode-proxy |
Main control script (symlinked to ~/.opencode/bin/opencode-proxy). |
~/.config/opencode/plugins/privacy-shield.js |
OpenCode plugin that hooks model.request and injects randomized headers. |
~/.config/opencode/identity.json |
Stores the active randomized 40-char project ID and directory token. |
~/.config/opencode/privoxy.conf |
User-space Privoxy configuration with forward-socks5 / 127.0.0.1:40000 .. |
- Linux:
- Arch Linux / CachyOS / Manjaro (
pacman -S privoxy) - Ubuntu / Debian / Pop!_OS (
apt-get install privoxy) - Fedora / RHEL (
dnf install privoxy)
- Arch Linux / CachyOS / Manjaro (
- macOS:
- macOS Sequoia, Sonoma, Ventura (
brew install privoxy) - Native Apple Silicon (M1/M2/M3/M4) and Intel (x86_64)
- macOS Sequoia, Sonoma, Ventura (
This project is licensed under the MIT License.
{ "model": "opencode/deepseek-v4.1-flash-free", "agents": { "build": { "model": "opencode/deepseek-v4.1-flash-free" }, "title": { "model": "opencode/deepseek-v4.1-flash-free" } } }