cliproxy · git:20260618.e501626 · 2026-06-18 · sha256 6ca92344c9b6febb

cliproxy git:20260618.e501626B

Immutable. This exact content is served forever at /api/v1/blob/6ca92344c9b6febb.

---
name: cliproxy
description: >
  Check and restart the CLIProxy sidecar (port 8317). CLIProxy bridges
  ChatGPT subscription OAuth tokens to an Anthropic-compatible /v1/messages
  endpoint so Overdeck agents can use GPT models without an OpenAI API key.
  Use when GPT-model agents are returning API errors or when cliproxy is down.
triggers:
  - cliproxy is down
  - restart cliproxy
  - cliproxy not running
  - GPT API errors
  - GPT5 errors
  - gpt5 not working
  - check cliproxy
  - cliproxy status
  - fix GPT routing
allowed-tools:
  - Bash
  - Read
---

# CLIProxy — Check and Restart

CLIProxy is a background sidecar that proxies Anthropic-compatible API calls to GPT
models via ChatGPT subscription OAuth tokens. Overdeck agents talk to it via
`ANTHROPIC_BASE_URL=http://127.0.0.1:8317`.

## Quick Status Check

```bash
# Is it running?
ss -tlnp | grep 8317

# Check PID file
cat ~/.overdeck/cliproxy/cliproxy.pid 2>/dev/null

# Verify process is alive
kill -0 $(cat ~/.overdeck/cliproxy/cliproxy.pid 2>/dev/null) 2>/dev/null && echo "alive" || echo "dead"
```

## Restart CLIProxy

```bash
# Kill any existing instance
lsof -ti:8317 2>/dev/null | xargs -r kill 2>/dev/null || true
rm -f ~/.overdeck/cliproxy/cliproxy.pid

# Start fresh
nohup ~/.overdeck/bin/cliproxy -config ~/.overdeck/cliproxy/config.yaml \
  >> ~/.overdeck/cliproxy/cliproxy.log 2>&1 &
echo $! > ~/.overdeck/cliproxy/cliproxy.pid

# Confirm it's up (give it 2 seconds)
sleep 2 && ss -tlnp | grep 8317
```

## Check Recent Logs

```bash
# Last 30 lines of cliproxy log
tail -30 ~/.overdeck/cliproxy/cliproxy.log

# Watch live
tail -f ~/.overdeck/cliproxy/cliproxy.log
```

## Config and Auth

| Path | Purpose |
|---|---|
| `~/.overdeck/bin/cliproxy` | Binary (v6.9.24, built from eltmon/cliproxy fork) |
| `~/.overdeck/cliproxy/config.yaml` | Server config (host, port, auth-dir, api-keys) |
| `~/.overdeck/cliproxy/auth/codex-primary.json` | Codex OAuth credentials (bridged from `~/.codex/auth.json`) |
| `~/.overdeck/cliproxy/cliproxy.pid` | PID file written on manual start |
| `~/.overdeck/cliproxy/cliproxy.log` | Append-only log |

Config contents:
```yaml
host: "127.0.0.1"
port: 8317
auth-dir: "~/.overdeck/cliproxy/auth"
api-keys:
  - "overdeck-local-cliproxy-key"
debug: false
```

## Lifecycle in Overdeck

Overdeck's `startCliproxy()` in `src/lib/cliproxy.ts` handles:
1. Ensuring binary is installed
2. Writing `~/.overdeck/cliproxy/config.yaml`
3. Bridging `~/.codex/auth.json` → `auth/codex-primary.json`
4. Spawning the process detached with a PID file

CLIProxy is normally started automatically by `pan up`. If it crashed or was never
started, use the restart snippet above.

## Auth Token Refresh

If 502 errors are appearing in the log, the Codex OAuth token may be expired.
CLIProxy has an auto-refresh loop, but if it fails:

```bash
# Check if auth file exists and has tokens
cat ~/.codex/auth.json | python3 -c "import sys,json; d=json.load(sys.stdin); print('access_token:', bool(d.get('tokens',{}).get('access_token')))"

# Re-bridge auth (re-runs the mapping from ~/.codex/auth.json)
# This is done automatically by pan up — or run pan install to re-authenticate
```

## Dashboard Re-Auth Flow (PAN-913)

The Overdeck dashboard can trigger interactive Codex re-authentication when
ChatGPT subscription tokens expire. This avoids requiring the user to run
`codex login` manually in a terminal.

### Flow

1. **Detection** — Dashboard polls `GET /api/settings/codex-auth` every 2 min.
   Status can be `valid`, `expired`, `burned`, `missing`, or `unknown`.
2. **Initiation** — User clicks **Re-authenticate** in Settings or the top banner.
   Dashboard calls `POST /api/settings/codex-reauth` (idempotent — returns an
   existing live session if one is already running).
3. **Terminal login** — Backend spawns a tmux session named `reauth-<uuid>`
   running `codex login` (or `codex login --device-auth` when headless), sets an
   HttpOnly `pan_codex_reauth` cookie for `/ws/terminal`, and the frontend opens
   `/terminal/<sessionName>` so the user can complete OAuth in a live terminal panel.
4. **Polling** — Frontend polls `POST /api/settings/codex-reauth/status` with the
   session name and status token every 3 s. The session is considered complete when
   the tmux pane exits.
5. **Bridge** — On completion, the backend calls `bridgeCodexAuthToCliproxyAsync()`
   to rewrite `~/.overdeck/cliproxy/auth/codex-primary.json` from the fresh
   `~/.codex/auth.json`, then returns the updated auth status.
6. **Auto-retry** — If an agent spawn was blocked by expired auth, the frontend
   automatically retries `POST /api/agents` once auth becomes valid.

### Security

- Re-auth terminal tokens are short-lived UUIDs stored only in an HttpOnly
  cookie scoped to `/ws/terminal`; they are required for `reauth-*` WebSockets.
- Sessions expire from the in-memory registry after 1 hour.
- The tmux session name is a random UUID — not guessable.

### API Endpoints

| Method | Path | Purpose |
|---|---|---|
| `GET` | `/api/settings/codex-auth` | Current auth status (`valid`/`expired`/etc.) |
| `POST` | `/api/settings/codex-reauth` | Spawn (or reuse) a re-auth tmux session and set the terminal cookie |
| `POST` | `/api/settings/codex-reauth/status` | Poll for completion with `{ session, token }` |

### Manual Fallback

If the dashboard re-auth flow fails, fall back to terminal login:

```bash
# Interactive login
codex login

# Headless / device-auth flow
codex login --device-auth

# Re-bridge into cliproxy format
node -e "require('./src/lib/cliproxy.js').bridgeCodexAuthToCliproxyAsync().then(console.log)"
```

## See Also

- `src/lib/cliproxy.ts` — full lifecycle implementation in Overdeck
- `/pan:health` — overall Overdeck health check
- `/pan:up` — start Overdeck (also starts cliproxy)