OpenClaw plugin that bridges locally installed AI CLIs (Codex, Gemini, Claude Code, OpenCode, Pi) as model providers — with slash commands for instant model switching, restore, health testing, and model listing.
Current version: 2.1.3
Registers the openai-codex provider by reading OAuth tokens already stored by the Codex CLI (~/.codex/auth.json). No re-login needed.
Starts a local OpenAI-compatible HTTP proxy on 127.0.0.1:31337 and configures OpenClaw's vllm provider to route calls through gemini and claude CLI subprocesses.
Prompt delivery: always via stdin (never CLI args or @file) — avoids E2BIG for long sessions and Gemini agentic mode. Each message batch is truncated to the last 20 messages + system message (MAX_MESSAGES/MAX_MSG_CHARS in src/cli-runner.ts).
| Model reference | CLI invoked | Latency |
|---|---|---|
vllm/cli-gemini/gemini-2.5-pro |
gemini -m gemini-2.5-pro -p "" (stdin, cwd=/tmp) |
~8–10s |
vllm/cli-gemini/gemini-2.5-flash |
gemini -m gemini-2.5-flash -p "" (stdin, cwd=/tmp) |
~4–6s |
vllm/cli-gemini/gemini-3-pro-preview |
gemini -m gemini-3-pro-preview -p "" (stdin, cwd=/tmp) |
~8–10s |
vllm/cli-gemini/gemini-3-flash-preview |
gemini -m gemini-3-flash-preview -p "" (stdin, cwd=/tmp) |
~4–6s |
vllm/cli-claude/claude-sonnet-4-6 |
claude -p --output-format text --model claude-sonnet-4-6 (stdin) |
~2–4s |
vllm/cli-claude/claude-opus-4-6 |
claude -p --output-format text --model claude-opus-4-6 (stdin) |
~3–5s |
vllm/cli-claude/claude-haiku-4-5 |
claude -p --output-format text --model claude-haiku-4-5 (stdin) |
~1–3s |
vllm/opencode/default |
opencode run "prompt" (CLI arg) |
varies |
vllm/pi/default |
pi -p "prompt" (CLI arg) |
varies |
All commands use gateway-level commands.allowFrom for authorization (requireAuth: false at plugin level).
Claude Code CLI (routed via local proxy on :31337):
| Command | Model | Notes |
|---|---|---|
/cli-sonnet |
vllm/cli-claude/claude-sonnet-4-6 |
✅ Tested |
/cli-opus |
vllm/cli-claude/claude-opus-4-6 |
✅ Tested |
/cli-haiku |
vllm/cli-claude/claude-haiku-4-5 |
✅ Tested |
Gemini CLI (routed via local proxy on :31337, stdin + cwd=/tmp):
| Command | Model | Notes |
|---|---|---|
/cli-gemini |
vllm/cli-gemini/gemini-2.5-pro |
✅ Tested |
/cli-gemini-flash |
vllm/cli-gemini/gemini-2.5-flash |
✅ Tested |
/cli-gemini3 |
vllm/cli-gemini/gemini-3-pro-preview |
✅ Tested |
/cli-gemini3-flash |
vllm/cli-gemini/gemini-3-flash-preview |
✅ Tested |
Codex CLI (via openai-codex provider — OAuth auth, calls OpenAI API directly, not through the local proxy):
| Command | Model | Notes |
|---|---|---|
/cli-codex |
openai-codex/gpt-5.3-codex |
✅ Tested |
/cli-codex-spark |
openai-codex/gpt-5.3-codex-spark |
✅ Tested |
/cli-codex52 |
openai-codex/gpt-5.2-codex |
✅ Tested |
/cli-codex54 |
openai-codex/gpt-5.4 |
May require upgraded OAuth scope |
/cli-codex-mini |
openai-codex/gpt-5.1-codex-mini |
✅ Tested |
OpenCode CLI (via local proxy, prompt as CLI argument):
| Command | Model | Notes |
|---|---|---|
/cli-opencode |
vllm/opencode/default |
Requires opencode CLI installed |
Pi CLI (via local proxy, prompt as -p flag):
| Command | Model | Notes |
|---|---|---|
/cli-pi |
vllm/pi/default |
Requires pi CLI installed |
BitNet local inference (via local proxy → llama-server on 127.0.0.1:8082, no API key):
| Command | Model | Notes |
|---|---|---|
/cli-bitnet |
vllm/local-bitnet/bitnet-2b |
✅ Tested |
Utility:
| Command | What it does |
|---|---|
/cli-back |
Restore the model active before the last /cli-* switch |
/cli-test [model] |
One-shot proxy health check — does NOT switch your active model |
/cli-list |
Show all registered CLI bridge models with commands |
/cli-help |
Full reference card — CLI/Codex/Web/BitNet sections, expiry info, quick examples, dashboard links |
/cli-back details:
- Before every
/cli-*switch the current model is saved to~/.openclaw/cli-bridge-state.json /cli-backreads it, callsopenclaw models set <previous>, then clears the file- State survives gateway restarts — safe to use any time
/cli-test details:
- Accepts short form (
cli-sonnet) or full path (vllm/cli-claude/claude-sonnet-4-6) - Default when no arg given:
cli-claude/claude-sonnet-4-6 - Reports response content, latency, and confirms your active model is unchanged
/cli-list details:
- Lists all registered models grouped by provider (Claude CLI, Gemini CLI, Codex)
- No arguments required
Routes requests through real browser sessions on the provider's web UI. Requires a valid login session (free or paid tier). Uses persistent Chromium profiles — sessions survive gateway restarts.
Note: Only Grok and Gemini are active browser providers. Claude and ChatGPT browser routes were removed in v1.6.x — use
cli-claude/*(Claude CLI) andopenai-codex/*/copilot-proxyinstead.
Grok (grok.com — SuperGrok subscription):
| Model | Notes |
|---|---|
web-grok/grok-3 |
Full model |
web-grok/grok-3-fast |
Faster variant |
web-grok/grok-3-mini |
Lightweight |
web-grok/grok-3-mini-fast |
Fastest |
| Command | What it does |
|---|---|
/grok-login |
Authenticate via X.com OAuth, save session to ~/.openclaw/grok-profile/ |
/grok-status |
Show session validity + cookie expiry |
/grok-logout |
Clear session |
Gemini (gemini.google.com):
| Model | Notes |
|---|---|
web-gemini/gemini-2-5-pro |
Gemini 2.5 Pro |
web-gemini/gemini-2-5-flash |
Gemini 2.5 Flash |
web-gemini/gemini-3-pro |
Gemini 3 Pro |
web-gemini/gemini-3-flash |
Gemini 3 Flash |
| Command | What it does |
|---|---|
/gemini-login |
Authenticate, save cookies to ~/.openclaw/gemini-profile/ |
/gemini-status |
Show session validity + cookie expiry |
/gemini-logout |
Clear session |
Claude.ai (removed in v1.6.x) — use /cli-sonnet, /cli-opus, /cli-haiku instead.
ChatGPT (removed in v1.6.x) — use /cli-codex, openai-codex/*, or copilot-proxy instead.
Session lifecycle:
- First use: run
/xxx-loginonce — authenticates and saves cookies to persistent Chromium profile - No CDP required:
/xxx-loginno longer depends on the OpenClaw browser (CDP port 18800). If CDP is available, cookies are imported from it; otherwise a standalone persistent Chromium is launched automatically. - If headless login fails, a headed browser opens for manual login (5 min timeout)
- After gateway restart: sessions are automatically restored from saved profiles on startup (sequential, ~25s after start)
/bridge-status— shows all 4 providers at a glance with login state + expiry info
- OpenClaw gateway (tested with
2026.3.x) - One or more of:
@openai/codex—npm i -g @openai/codex+codex login@google/gemini-cli—npm i -g @google/gemini-cli+gemini auth@anthropic-ai/claude-code—npm i -g @anthropic-ai/claude-code+claude auth
# From ClawHub
clawhub install openclaw-cli-bridge-elvatis
# Or from workspace (development)
# Add to ~/.openclaw/openclaw.json:
# plugins.load.paths: ["~/.openclaw/workspace/openclaw-cli-bridge-elvatis"]
# plugins.entries.openclaw-cli-bridge-elvatis: { "enabled": true }// ~/.openclaw/openclaw.json → plugins.entries
"openclaw-cli-bridge-elvatis": { "enabled": true }openclaw gateway restart[cli-bridge] proxy ready on :31337
[cli-bridge] registered 14 commands: /cli-sonnet, /cli-opus, /cli-haiku,
/cli-gemini, /cli-gemini-flash, /cli-gemini3, /cli-gemini3-flash,
/cli-codex, /cli-codex-spark, /cli-codex52, /cli-codex54, /cli-codex-mini,
/cli-back, /cli-test, /cli-list
openclaw models auth login --provider openai-codex
# Select: "Codex CLI (existing login)"/cli-list
→ 🤖 CLI Bridge Models
Claude Code CLI
/cli-sonnet claude-sonnet-4-6
/cli-opus claude-opus-4-6
/cli-haiku claude-haiku-4-5
Gemini CLI
/cli-gemini gemini-2.5-pro
/cli-gemini-flash gemini-2.5-flash
/cli-gemini3 gemini-3-pro-preview
/cli-gemini3-flash gemini-3-flash-preview
Codex (OAuth)
/cli-codex gpt-5.3-codex
/cli-codex-spark gpt-5.3-codex-spark
/cli-codex52 gpt-5.2-codex
/cli-codex54 gpt-5.4
/cli-codex-mini gpt-5.1-codex-mini
Utility
/cli-back Restore previous model
/cli-test [model] Health check (no model switch)
/cli-list All models with slash commands + dashboard URL
/cli-help Full reference card (sections, expiry, examples, links)
Proxy: 127.0.0.1:31337
/cli-test
→ 🧪 CLI Bridge Test
Model: vllm/cli-claude/claude-sonnet-4-6
Response: CLI bridge OK
Latency: 2531ms
Active model unchanged: anthropic/claude-sonnet-4-6
/cli-test cli-gemini
→ 🧪 CLI Bridge Test
Model: vllm/cli-gemini/gemini-2.5-pro
Response: CLI bridge OK
Latency: 8586ms
Active model unchanged: anthropic/claude-sonnet-4-6
/cli-sonnet
→ ✅ Switched to Claude Sonnet 4.6 (CLI)
`vllm/cli-claude/claude-sonnet-4-6`
Use /cli-back to restore previous model.
... test things ...
/cli-back
→ ✅ Restored previous model
`anthropic/claude-sonnet-4-6`
In ~/.openclaw/openclaw.json → plugins.entries.openclaw-cli-bridge-elvatis.config:
{
"enableCodex": true, // register openai-codex from Codex CLI auth (default: true)
"enableProxy": true, // start local CLI proxy server (default: true)
"proxyPort": 31337, // proxy port (default: 31337)
"proxyApiKey": "cli-bridge", // key between OpenClaw vllm provider and proxy (default: "cli-bridge")
"proxyTimeoutMs": 120000 // CLI subprocess timeout in ms (default: 120s)
}routeToCliRunner enforces DEFAULT_ALLOWED_CLI_MODELS — only models registered in the plugin are accepted by the proxy. Unregistered models receive a clear error listing allowed options.
To disable the check (e.g. for custom vllm routing): pass allowedModels: null in RouteOptions.
OpenClaw agent
│
├─ openai-codex/* ──────────────────────────► OpenAI API (direct)
│ auth: ~/.codex/auth.json OAuth tokens
│ /cli-codex, /cli-codex-spark, /cli-codex52, /cli-codex54, /cli-codex-mini
│
└─ vllm/cli-gemini/* ─┐
vllm/cli-claude/* ─┤─► localhost:31337 (openclaw-cli-bridge proxy)
vllm/opencode/* ─┤ ├─ cli-gemini/* → gemini -m <model> -p ""
vllm/pi/* ─┘ │ stdin=prompt, cwd=/tmp
│ │ (neutral cwd prevents agentic mode)
│ ├─ cli-claude/* → claude -p --model <model>
│ │ stdin=prompt
│ ├─ opencode/* → opencode run "prompt"
│ │ prompt as CLI arg
│ └─ pi/* → pi -p "prompt"
│ prompt as -p flag
Slash commands (requireAuth=false, gateway commands.allowFrom is the auth layer):
/cli-sonnet|opus|haiku|gemini|gemini-flash|gemini3|gemini3-flash
/cli-codex|codex-spark|codex52|codex54|codex-mini
/cli-opencode|cli-pi
└─► saves current model → ~/.openclaw/cli-bridge-state.json
└─► openclaw models set <model>
/cli-back → reads state file, restores previous model, clears state
/cli-test → HTTP POST → localhost:31337, no global model change
/cli-list → formatted table of all registered models
Proxy endpoints:
/health → simple {"status":"ok"}
/healthz → detailed JSON (version, uptime, provider status, model count)
/status → HTML dashboard (auto-refreshes every 30s)
/v1/models → OpenAI-compatible model list
Model fallback (v1.9.0):
cli-gemini/gemini-2.5-pro → cli-gemini/gemini-2.5-flash
cli-gemini/gemini-3-pro-preview → cli-gemini/gemini-3-flash-preview
cli-claude/claude-opus-4-6 → cli-claude/claude-sonnet-4-6
cli-claude/claude-sonnet-4-6 → cli-claude/claude-haiku-4-5
Symptom: CLI error for cli-claude/…: spawn E2BIG after ~500+ messages.
Cause: Gateway injects large values into process.env at runtime. Spreading it into spawn() exceeds Linux's ARG_MAX (~2MB).
Fix: buildMinimalEnv() — only passes HOME, PATH, USER, and auth keys.
Symptom: /cli-test cli-claude/* times out after 30s; logs show 401 Invalid authentication credentials.
Cause: buildMinimalEnv() did not forward XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS to the spawned claude subprocess. Claude Code authenticated via claude.ai OAuth (Claude Max plan) stores its tokens in the system keyring (Gnome Keyring / libsecret) and needs these env vars to access it.
Affects: Only systems using claude auth OAuth login (Claude Max / Teams). API-key users (ANTHROPIC_API_KEY) are not affected.
Fix: Added XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS to the forwarded env keys in buildMinimalEnv().
Symptom: Gemini hangs, returns wrong answers, or says "directory does not exist".
Cause: @file syntax (gemini -p @/tmp/xxx.txt) triggers agentic mode — Gemini scans the working directory for project context and treats prompts as task instructions.
Fix: Stdin delivery (gemini -p "" with prompt via stdin) + cwd=/tmp.
npm run lint # eslint (TypeScript-aware)
npm run typecheck # tsc --noEmit
npm test # vitest run (121 tests)
npm run ci # lint + typecheck + test- docs: All documentation updated to reflect current version (README, SKILL.md, STATUS.md, MANIFEST.json)
- fix: Updated ChatGPT web session model list: gpt-4o, gpt-4o-mini, gpt-4.1, gpt-4.1-mini, o3, o4-mini, gpt-5, gpt-5-mini
- fix:
server.unref()— proxy server no longer keepsopenclaw doctorhanging indefinitely
- fix:
server.unref()on proxy server soopenclaw doctor(and short-lived CLI commands) exit cleanly
- feat: Session manager for isolated per-request workdirs
- feat: Register OpenCode and Pi slash commands (
/cli-opencode,/cli-pi) - feat: Codex auth auto-import support
- feat: Workdir isolation for all CLI runners
- fix: Correct
maxTokensandcontextWindowfor all CLI_MODELS — were hardcoded to 8192 output tokens- Claude Opus 4.6: 1M context / 128k output (was 200k/8k)
- Claude Sonnet 4.6: 1M context / 64k output (was 200k/8k)
- Claude Haiku 4.5: 200k context / 64k output (was 200k/8k)
- Gemini 2.5 Pro/Flash: 1M context / 65k output (was 1M/8k)
- Gemini 3 Pro/Flash Preview: 1M context / 65k output (was 1M/8k)
- Web-session Gemini models: same corrections
- feat: Full slash command mapping on status page — all models now show their /cli-* command
- fix: Register missing slash commands: /cli-codex-spark, /cli-codex52, /cli-codex-mini, /cli-gemini3-flash (documented but never registered)
- feat: /cli-help command — full reference with CLI/Codex/Web/BitNet sections, expiry info, quick examples, dashboard links
- feat: /cli-list now references /cli-help and shows dashboard URL
/
- feat: Auto-source version from
package.json— eliminates hardcoded version string sync issues (was stale across v1.8.2–v1.8.8) - feat: ESLint config (
eslint.config.js) — TypeScript-aware linting withnpm run lint, integrated into CI pipeline - refactor: Extract
/statusHTML dashboard intosrc/status-template.ts— easier to maintain and test - feat: System Chrome startup check — logs a clear warning with install instructions if
google-chrome/chromiumis not found (required for stealth mode browser launches) - refactor: Consolidate 4 cookie expiry files (
grok-,gemini-,claude-,chatgpt-cookie-expiry.json) into single~/.openclaw/cookie-expiry.json. Legacy files are auto-migrated on first load. - fix: Explicit
grokBrowsercleanup on plugin unload — prevents orphaned Chromium processes on hot-reload. Launch promises (_geminiLaunchPromiseetc.) are also cleared. - feat: Model fallback chain — when a CLI model fails (timeout, error), automatically retries with a lighter variant:
gemini-2.5-pro→flash,claude-opus→sonnet→haiku. Response includes the actual model used. - feat:
/healthzJSON endpoint — returns version, uptime, provider session status, and model count. Useful for monitoring scripts and health dashboards. - feat: Status page now shows slash commands (
/cli-codex,/cli-sonnet, etc.) next to model IDs
- fix: Add missing cli-gemini/gemini-3-flash-preview and all Codex models to status page model list
- fix: Remove duplicate cli-gemini/gemini-3-pro alias
/
- fix: Remove stale web-claude/* and web-chatgpt/* entries from model list (status page showed removed providers)
/
- fix: Replace full system prompt with 30-token mini stub for BitNet (prevents context overflow)
- fix: Truncate to last 6 non-system messages before forwarding to BitNet (4096 token limit)
- fix: Flatten multi-part content arrays to plain strings (llama-server crash fix)
- Intermediate BitNet crash fixes (superseded by v1.8.5)
/
- fix:
local-bitnet/*exempt from tool-call rejection — llama-server ignores tool schemas silently. OpenClaw always sends tools with every request, so this was blocking all BitNet usage.
- fix:
--nowflag now works when followed by additional text (e.g./cli-bitnet --now hello) — was using===instead ofstartsWith.
- feat: BitNet local inference —
local-bitnet/bitnet-2broutes to llama-server on 127.0.0.1:8082. No API key, no internet, pure CPU inference (2.87 tok/s on i7-6700K). Use/cli-bitnetto switch. - feat:
/bridge-statusshows BitNet server health as 5th provider.
- chore: Re-published to ClawHub with correct display name "OpenClaw CLI Bridge"
- docs: Handoff docs updated (DASHBOARD, LOG, STATUS, NEXT_ACTIONS)
- fix: Cookie expiry tracking for all 4 providers now uses the longest-lived auth cookie instead of the shortest. Previously, short-lived cookies caused false "session expired" alerts and unnecessary WhatsApp notifications on every gateway restart:
- Claude:
__cf_bm(Cloudflare, ~30 min) removed from scan list; now trackssessionKey(~1 year) - ChatGPT: sort reversed; now prefers
__Secure-next-auth.session-tokenover_puid(~7d) - Gemini: sort reversed; now uses longest of
__Secure-1PSID/__Secure-3PSID/SID - Grok: sort reversed; now uses longest of
sso/sso-rw
- Claude:
- fix: Startup restore now uses cookie expiry file as primary check — if cookies are still valid (>1h left), the persistent context is launched immediately without a fragile browser selector check. This eliminates false "not logged in" errors for Grok/Claude/ChatGPT caused by slow page loads or DOM selector changes.
- fix: Grok cookie file path corrected to
grok-cookie-expiry.json(wasgrok-session.json).
- feat:
/statusHTML dashboard — browser-accessible health page athttp://127.0.0.1:31337/status. Shows all 4 web providers with live status badge (Connected / Logged in / Expired / Never logged in), cookie expiry per provider, CLI and web model list. Auto-refreshes every 30s.
- fix: Startup restore timeout 3s → 6s with one retry, eliminates false "not logged in" for slow-loading pages (Grok)
- feat: Auto-relogin on startup — if cookies truly expired, attempt headless relogin before sending WhatsApp alert
- feat: Keep-alive (20h) now verifies session after touch and attempts auto-relogin if expired
- feat: Tests (vitest) — proxy tool rejection, models endpoint, auth, cookie expiry formatters
- feat: Automatic session keep-alive — every 20h, active browser sessions are silently refreshed by navigating to the provider home page. Prevents cookie expiry on providers like ChatGPT (7-day sessions) without storing credentials.
- chore: version bump (1.6.3 was already published on npm with partial changes)
- fix: CLI-proxy models (
cli-gemini/*,cli-claude/*) now return HTTP 400 withtools_not_supportedwhen a request includes tool/function call schemas — prevents agents from silently failing or hallucinating when assigned a CLI-proxy model - feat:
/v1/modelsresponse includescapabilities.tools: falsefor CLI-proxy models so OpenClaw can detect tool support upfront - fix: EADDRINUSE on hot-reload: re-probe after 1.5s wait before retrying bind; probe timeout 800ms → 2000ms
- docs: Add missing changelog entries (v1.5.1, v1.6.0, v1.6.1), fix /cli-codex54 command name in SKILL.md, add startup re-login alert description to SKILL.md.
- feat: WhatsApp re-login alerts on startup. After each gateway restart, the session restore loop collects any providers that failed to restore (cookies expired) and sends a single batched WhatsApp notification with the exact
/xxx-logincommands needed. No credential storage — remains fully 2FA-safe.
- feat: Persistent Chromium profiles for all 4 web providers (Grok, Gemini, Claude.ai, ChatGPT). Browser sessions now survive gateway restarts — cookies are stored in
~/.openclaw/{grok,gemini,claude,chatgpt}-profile/and restored automatically on startup. - feat: Re-added
/claude-login,/claude-status,/claude-logout,/chatgpt-login,/chatgpt-status,/chatgpt-logoutcommands with full persistent profile support. - feat:
/bridge-statusnow shows all 4 providers with session state and cookie expiry at a glance. - fix: Startup restore guard (
_startupRestoreDone) prevents duplicate browser launches on hot-reloads (SIGUSR1).
- fix: Hardcoded plugin version
1.3.1in plugin object updated to1.5.1. - docs: Added
CONTRIBUTING.mdwith release checklist and smoketest workflow.
- refactor: Removed
/claude-login,/claude-logout,/claude-status,/chatgpt-login,/chatgpt-logout,/chatgpt-statuscommands and all related browser automation code. Claude is fully covered bycli-claude/*via CLI proxy, ChatGPT byopenai-codex+copilot-proxy. - refactor: Removed
web-claude/*andweb-chatgpt/*proxy routes and model entries from proxy server. - refactor: Removed
getOrLaunchClaudeContext()andgetOrLaunchChatGPTContext()functions, claude/chatgpt session state, cookie expiry tracking, and startup restore for these providers. - cleanup: Deleted
test/claude-proxy.test.tsandtest/chatgpt-proxy.test.ts. - result: Cleaner codebase, no browser timeout on startup for unused providers. Only Grok and Gemini browser providers remain.
- fix: Full stealth mode for all browser launches -
ignoreDefaultArgs: ['--enable-automation']removes Playwright's automation flag,--disable-blink-features=AutomationControlledhidesnavigator.webdriver, and--disable-infobarssuppresses the "Chrome is being controlled by automated software" banner. Combined withchannel: "chrome"(v1.4.2), this bypasses Cloudflare human verification completely. - root cause: Even with system Chrome (
channel: "chrome"), Playwright injects--enable-automationby default, which setsnavigator.webdriver = trueand shows the automation infobar. Cloudflare checks both signals.
- fix: All browser launches now use
channel: "chrome"(real system Chrome) instead of Playwright's bundled Chromium. Cloudflare human verification no longer blocks/xxx-logincommands. - root cause: Playwright's bundled Chromium is fingerprinted by Cloudflare as an automation browser, triggering CAPTCHA challenges that cannot be completed. System Chrome is not flagged.
- fix:
/claude-login,/gemini-login,/chatgpt-loginnow fall back to a headed (visible) Chromium browser when headless login fails (no saved cookies in profile). The user can log in manually in the opened browser window (5 min timeout). After login, cookies are saved to the persistent profile for future headless use. - fix: Added missing
claude-opus-4-6andclaude-haiku-4-5entries to the Claude browser MODEL_MAP - root cause: Headless Chromium without saved cookies sees a login page, not the editor - the user cannot interact with a headless browser to log in
- feat: Persistent browser fallback for all providers -
/claude-login,/gemini-login,/chatgpt-loginno longer require the OpenClaw browser (CDP port 18800). If CDP is available, cookies are imported; otherwise a standalone persistent headless Chromium is launched automatically from the saved profile directory. - feat: New helper functions
getOrLaunchClaudeContext(),getOrLaunchGeminiContext(),getOrLaunchChatGPTContext()- same pattern as the existinggetOrLaunchGrokContext()(try CDP, fall back to persistent Chromium, coalesce concurrent launches) - fix: Proxy server
connectXxxContextcallbacks now use the persistent fallback too - no more "not logged in" errors when CDP is unavailable but a saved profile exists - fix:
cleanupBrowsers()now properly closes Claude, Gemini, and ChatGPT persistent contexts on plugin teardown (previously only cleaned up Grok + CDP) - root cause: All 3 login commands (Claude, Gemini, ChatGPT) called
connectToOpenClawBrowser()directly, which only tries CDP on 127.0.0.1:18800. If Chrome was not running with--remote-debugging-port=18800, login always failed. Grok already had the fallback pattern since v0.2.27 - now all 4 providers are consistent.
- fix: Startup session restore now runs only once per process lifetime —
_startupRestoreDonemodule-level guard prevents re-running on every hot-reload (SIGUSR1), which was triggered every ~60s by the openclaw-control-ui dashboard poll - root cause: Gateway
reload.mode=hybrid+ dashboard status polling caused plugin to reinitialize every 60s → each reload spawned a new Gemini Chromium instance → RAM/CPU OOM loop - behavior: First load after gateway start: sequential profile restore runs once. All subsequent hot-reloads: skip restore, reuse existing in-memory contexts
- feat: Safe sequential session restore on startup — if a saved profile exists, providers are reconnected automatically after gateway restart (one at a time, 3s delay between each, headless)
- fix: No manual
/xxx-loginneeded after reboot if profile is already saved - safety: Profile-gated — only restores if
~/.openclaw/<provider>-profile/or cookie file exists; never spawns a browser for an uninitialized provider
- fix: Removed auto-connect of all browser providers on plugin startup — caused OOM (load 195, 30GB RAM) by spawning 4+ persistent Chromium instances on every gateway start
- fix: Removed Grok session restore on startup — same root cause
- behavior change: Browsers are now started on-demand only via
/grok-login,/claude-login,/gemini-login,/chatgpt-login
- fix: Singleton promise guard on
ensureAllProviderContexts()— concurrent requests no longer each spawn their own Chromium; extra callers await the existing run - fix: Removed recursive
ensureAllProviderContexts()fallback from allconnect*Contextproxy callbacks — no more exponential browser spawn on CDP failure
- fix: /claude-login, /gemini-login, /chatgpt-login now bake cookies into persistent profile dirs
- fix: After gateway restart, providers auto-reconnect from saved profile (no browser tabs needed)
- fix: Better debug logging when persistent headless context fails (Cloudflare etc.)
- fix: Browser persistence after gateway restart — each provider launches its own persistent Chromium if OpenClaw browser is unavailable
- feat:
ensureAllProviderContexts()— unified startup connect for all 4 providers - feat: Lazy-connect fallback to persistent context when CDP unavailable
- fix: Fresh page per request — no more message accumulation across calls
- feat: ChatGPT model switching via URL param (?model=gpt-4o, o3, etc.)
- chore: Gemini model switching: TODO (requires UI interaction)
- feat: Auto-connect all providers on startup (no manual login after restart if browser is open)
- feat:
/bridge-status— all 4 providers at a glance with expiry info - fix: Removed obsolete CLI models: gpt-5.2-codex, gpt-5.3-codex-spark, gpt-5.1-codex-mini, gemini-3-flash-preview
- fix: Removed duplicate cli-gemini3-flash (was same as gemini-3-flash-preview)
- chore: Cleaned up CLI_MODEL_COMMANDS (8 models, down from 13)
All four major LLM providers are now available via browser automation. No CLI binaries required — just authenticated browser sessions.
- feat: Auto-connect all providers on startup (no manual login after restart if browser is open)
- feat:
/bridge-status— all 4 providers at a glance with expiry info - fix: Removed obsolete CLI models: gpt-5.2-codex, gpt-5.3-codex-spark, gpt-5.1-codex-mini, gemini-3-flash-preview
- fix: Removed duplicate cli-gemini3-flash (was same as gemini-3-flash-preview)
- chore: Cleaned up CLI_MODEL_COMMANDS (8 models, down from 13)
- feat:
chatgpt-browser.ts— chatgpt.com DOM-automation (#prompt-textarea+[data-message-author-role]) - feat:
web-chatgpt/*models: gpt-4o, gpt-4o-mini, gpt-4.1, o3, o4-mini, gpt-5, gpt-5-mini (updated in v1.6.3) - feat:
/chatgpt-login,/chatgpt-status,/chatgpt-logout+ cookie-expiry tracking - feat: All 4 providers headless: Grok ✅ Claude ✅ Gemini ✅ ChatGPT ✅
- test: 96/83 tests green (8 test files)
- fix: Singleton CDP connection, cleanupBrowsers() on plugin stop
- feat:
gemini-browser.ts— gemini.google.com DOM-automation (Quill editor + message-content polling) - feat:
web-gemini/*models in proxy (gemini-2-5-pro, gemini-2-5-flash, gemini-3-pro, gemini-3-flash) - feat:
/gemini-login,/gemini-status,/gemini-logoutcommands + cookie-expiry tracking - fix: Singleton CDP connection — no more zombie Chromium processes
- fix:
cleanupBrowsers()called on plugin stop — all browser resources released - test: 90/90 tests green (+6 gemini-proxy tests)
- feat:
claude-browser.ts— claude.ai DOM-automation (ProseMirror +[data-test-render-count]polling) - feat:
web-claude/*models in proxy (web-claude/claude-sonnet, claude-opus, claude-haiku) - feat:
/claude-login,/claude-status,/claude-logoutcommands - feat: Claude cookie-expiry tracking (
~/.openclaw/claude-cookie-expiry.json) - test: 84/84 tests green (+7 claude-proxy tests, +8 claude-browser unit tests)
- feat:
/grok-loginscans auth cookie expiry (sso cookie) and saves to~/.openclaw/grok-cookie-expiry.json - feat:
/grok-statusshows cookie expiry with color-coded warnings (🚨 <7d,⚠️ <14d, ✅ otherwise) - feat: Startup log shows cookie expiry and refreshes the expiry file on session restore
- fix: Flaky cli-runner test improved (was pre-existing)
- feat: Grok persistent Chromium profile (
~/.openclaw/grok-profile/) — cookies survive gateway restarts - feat:
/grok-loginimports cookies from OpenClaw browser into persistent profile automatically - fix:
verifySessionreuses existing grok.com page instead of opening a new one (avoids Cloudflare 403) - fix: DOM-polling strategy instead of direct fetch API — bypasses
x-statsig-idanti-bot check completely - fix: Lazy-connect:
connectGrokContextcallback auto-reconnects on first request after restart
- feat: Grok web-session bridge integrated into cli-bridge proxy — routes
web-grok/*models through grok.com browser session (SuperGrok subscription, no API credits needed) - feat:
/grok-login— opens Chromium for X.com OAuth login, saves session to~/.openclaw/grok-session.json - feat:
/grok-status— check session validity - feat:
/grok-logout— clear session - fix: Grok web-session plugin removed as separate plugin — consolidated into cli-bridge (fewer running processes, single proxy port)
- feat: Staged model switching —
/cli-*now stages the switch instead of applying it immediately. Prevents silent session corruption when switching models mid-conversation./cli-sonnet→ stages switch, shows warning, does NOT apply/cli-sonnet --now→ immediate switch (use only between sessions!)/cli-apply→ apply staged switch after finishing current task/cli-pending→ show staged switch (if any)/cli-back→ restore previous model + clear staged switch
- fix: Sleep-resilient OAuth token refresh — replaced single long
setTimeoutwithsetInterval(10min)polling. Token refresh no longer misses its window after system sleep/resume. - fix: Timer leak in
scheduleTokenRefresh()— old interval now reliably cleared viastopTokenRefresh()before scheduling a new one. - fix:
stopTokenRefresh()exported fromclaude-auth.ts; called automatically viaserver.on("close")when the proxy server closes.
- feat: Proactive OAuth token management (
src/claude-auth.ts) — the proxy now reads~/.claude/.credentials.jsonat startup, schedules a refresh 30 minutes before expiry, and callsensureClaudeToken()before everyclaudesubprocess invocation. On 401 responses, automatically retries once after refreshing. Eliminates the need for manual re-login after token expiry in headless/systemd deployments.
- fix:
runClaude()now detects expired/invalid OAuth tokens immediately (401 in stderr) and throws a clear actionable error instead of waiting for the 30s proxy timeout. Error message includes the exact re-login command.
- fix:
buildMinimalEnv()now forwardsXDG_RUNTIME_DIRandDBUS_SESSION_BUS_ADDRESSto Claude Code subprocesses — required for Gnome Keyring / libsecret access when Claude Code is authenticated viaclaude.aiOAuth (Claude Max). Without these, the spawnedclaudeprocess cannot read its OAuth token from the system keyring, resulting in401 Invalid authentication credentialsand a 30-second timeout on/cli-testand all/cli-claude/*requests.
- fix:
formatPromptnow defensively coercescontentto string viacontentToString()— prevents[object Object]reaching the CLI when WhatsApp group messages contain structured content objects instead of plain strings - feat:
ChatMessage.contentnow acceptsstring | ContentPart[] | unknown(OpenAI multimodal content arrays supported) - feat: New
contentToString()helper: handles string, OpenAI ContentPart arrays, arbitrary objects (JSON.stringify), null/undefined
- feat:
/cli-listcommand — formatted overview of all registered models grouped by provider - docs: Rewrite README to reflect current state (correct model names, command count, requireAuth, test count, /cli-list docs)
- feat: Add
/cli-gemini3-flash→gemini-3-flash-preview - feat: Add
/cli-codex-spark→gpt-5.3-codex-spark,/cli-codex52→gpt-5.2-codex,/cli-codex54→gpt-5.4 - fix: Update
DEFAULT_ALLOWED_CLI_MODELSwithgemini-3-flash-preview
- fix:
/cli-gemini3model corrected togemini-3-pro-preview(wasgemini-3-pro, returns 404 from Gemini API)
- feat(T-101): Expand test suite to 45 tests — new cases for
formatPrompt(mixed roles, boundary values, system messages) androuteToCliRunner(gemini paths, edge cases) - feat(T-103): Add
DEFAULT_ALLOWED_CLI_MODELSallowlist;routeToCliRunnernow rejects unregistered models by default; passallowedModels: nullto opt out
- docs: Rewrite changelog (entries for v0.2.12–v0.2.14 were corrupted); all providers verified working end-to-end
- fix: Strip
vllm/prefix inrouteToCliRunner— OpenClaw sends full provider path (vllm/cli-claude/...) but proxy router expected barecli-claude/... - test: Add 4 routing tests (9 total)
- fix: Set
requireAuth: falseon all/cli-*commands — plugin-level auth uses different resolution path thancommands.allowFrom; gateway allowlist is the correct security layer - fix: Hardcoded
version: "0.2.5"in plugin object now trackspackage.json
- fix: Critical — replace
fuser -k 31337/tcpwith safe health probe to prevent gateway SIGKILL on hot-reloads
- fix: Port leak on hot-reload —
registerServicestop() hook +closeAllConnections()
- fix:
openclaw.extensionsadded topackage.json; config patcher auto-adds vllm provider
- feat:
/cli-codex+/cli-codex-mini(Codex OAuth provider, direct API)
- fix: Gemini agentic mode — stdin delivery +
cwd=/tmp
- feat:
/cli-back+/cli-test
- feat: Phase 3 —
/cli-*slash commands
- fix:
spawn E2BIG+ unit tests
- feat: Phase 2 — local OpenAI-compatible proxy, stdin delivery, prompt truncation
- Phase 1: Codex CLI OAuth auth bridge
MIT