GitHub - APengX/proxi · GitHub
Skip to content
APengXPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

proxi

Interactive switcher for Claude Code / Codex / OpenCode / Pi proxy profiles.

Quickly switch between API relays, models, and keys: profiles live in local source directories. Claude/Codex apply by replacing the target global config; OpenCode/Pi merge providers into the live config. Optional auth files are updated the same way, with automatic backups.

Implemented as a single Rust binary — no Python / jq runtime required. The repo keeps proxi.py as a legacy reference.

Install

Pick one:

Method Notes Guide
Rust (recommended) Build a single binary, no runtime deps docs/install-rust.md
Windows (PowerShell) winget rustup + install.ps1 one-step installer docs/install-windows.md
Python + uv Run proxi.py directly when you don’t want Rust docs/install-python-uv.md

Option A: Build with Rust (recommended)

Requires Rust / rustup (build time only). Full steps: Rust setup guide.

git clone https://github.com/APengX/proxi.git
cd proxi
cargo build --release
ln -sfn "$(pwd)/target/release/proxi" ~/.local/bin/proxi   # ensure ~/.local/bin is on PATH

Profile sources default to setforclaude/, setforcodex/, setforopencode/, and setforpi/ at the repo root (resolved by walking up from the executable; override with env vars).

Option B: Python / uv (no compile)

Needs Python 3.11+ (stdlib tomllib). Prefer uv for the interpreter. Full steps: Python + uv setup guide.

The Python legacy version supports Claude Code / Codex only; use the Rust build for OpenCode or Pi.

# System Python
chmod +x proxi.py
ln -sfn "$(pwd)/proxi.py" ~/.local/bin/proxi

# Or uv (picks 3.12; no manual packages)
uv run --python 3.12 python proxi.py list

Quick start

  1. Add your profiles from the examples:
# Claude Code
cp setforclaude/settings.example.json setforclaude/settingsmyapi.json
# edit URL / token / model

# Codex
cp setforcodex/config.example.toml setforcodex/configmyapi.toml
cp setforcodex/auth.example.json setforcodex/authmyapi.json
# edit base_url / model / OPENAI_API_KEY

# OpenCode
cp setforopencode/config.example.json setforopencode/configmyapi.json
cp setforopencode/auth.example.json setforopencode/authmyapi.json
# edit provider / baseURL / model / key

# Pi
cp setforpi/models.example.json setforpi/modelsmyapi.json
cp setforpi/settings.example.json setforpi/settingsmyapi.json
cp setforpi/auth.example.json setforpi/authmyapi.json
# edit provider / baseUrl / model / key
  1. Switch:
proxi                 # interactive: pick claude/codex/opencode/pi, then a profile
proxi claude myapi    # apply Claude profile
proxi codex myapi     # apply Codex profile
proxi opencode myapi  # apply OpenCode profile
proxi pi myapi        # apply Pi profile
proxi list            # list all
proxi current         # show active profile

Interactive menu: ↑↓ / j k to move; in the profile list, Enter applies and → edits. For Claude, Codex, OpenCode, and Pi, → edits URL / Key, probes the provider’s model endpoint, then opens a model picker. In a model picker, type any part of a model ID to move the cursor to the best match; Backspace edits the query and Esc cancels. Claude tries the Anthropic-style /v1/models and /models endpoints; OpenAI-compatible targets use /models. OpenCode and Pi also merge the discovered model list into their native model catalogs. In submenus Esc / ← go back, q quits; at the root menu q / Esc cancels.

Profile layout

Target Source file Written to
Claude Code setforclaude/settings<name>.json ~/.claude/settings.json
Codex setforcodex/config<name>.toml ~/.codex/config.toml
Codex auth (optional) setforcodex/auth<name>.json ~/.codex/auth.json
OpenCode setforopencode/config<name>.json ~/.config/opencode/opencode.json
OpenCode auth (optional) setforopencode/auth<name>.json ~/.local/share/opencode/auth.json
Pi models setforpi/models<name>.json ~/.pi/agent/models.json
Pi settings (optional) setforpi/settings<name>.json ~/.pi/agent/settings.json
Pi auth (optional) setforpi/auth<name>.json ~/.pi/agent/auth.json

Claude Code / Codex switching is a full file replace (not a field merge).

OpenCode / Pi switching is an append/merge:

  • OpenCode: merges provider entries and shallow-applies other profile top-level keys into the live opencode.json; merges matching keys into auth.json.
  • Pi: merges providers into the live models.json; shallow-merges profile settings.json / auth.json keys. Unrelated providers and settings are preserved; same-named providers are overwritten by the selected profile.

Existing targets are backed up as *.bak first.

Platform paths (macOS / Linux / Windows)

Profile sources are always the four setfor* directories at the repo root — identical on every OS. Only the targets differ, and proxi resolves them at runtime, so the same profile files work unchanged across machines.

Claude Code, Codex, and Pi anchor their config to the home directory on all three platforms:

Target macOS / Linux Windows
Claude Code ~/.claude/settings.json %USERPROFILE%\.claude\settings.json
Codex ~/.codex/config.toml · ~/.codex/auth.json %USERPROFILE%\.codex\config.toml · auth.json
Pi ~/.pi/agent/models.json · settings.json · auth.json %USERPROFILE%\.pi\agent\models.json · …

OpenCode uses XDG paths on every platform

OpenCode does not use the OS-native config / data directories. On macOS and Windows it still reads XDG-style paths under the home directory, so proxi resolves them the same way:

Platform OpenCode config OpenCode auth
Linux ~/.config/opencode/opencode.json ~/.local/share/opencode/auth.json
macOS ~/.config/opencode/opencode.json ~/.local/share/opencode/auth.json
Windows %USERPROFILE%\.config\opencode\opencode.json %USERPROFILE%\.local\share\opencode\auth.json

XDG_CONFIG_HOME and XDG_DATA_HOME are honored on all three platforms (OpenCode honors them too), and an empty value counts as unset. OPENCODE_CONFIG_DIR / OPENCODE_CONFIG still take precedence over both.

Earlier builds derived these from dirs::config_dir() / dirs::data_dir(), which resolve to ~/Library/Application Support/opencode on macOS and %APPDATA%\opencode on Windows — directories OpenCode never reads, so switching silently had no effect on those two platforms. If you switched OpenCode profiles on macOS or Windows with an older build, delete those stale directories.

Other per-platform behavior

Behavior macOS / Linux Windows
Install ln -sfn "$(pwd)/target/release/proxi" ~/.local/bin/proxi .\install.ps1 → %USERPROFILE%\.local\bin\proxi.exe, writes a proxi.home repo locator, and sets user PATH / PROXI_HOME
Locating profile sources walks up from the executable (a symlink is resolved first), else $PWD PROXI_HOME first, then the proxi.home locator written beside the copied executable
Key file permissions 0600 on every key-bearing file proxi creates or overwrites no-op — relies on NTFS ACLs / per-user profile isolation
proxi <tool> edit editor $EDITOR → $VISUAL → vi $EDITOR → $VISUAL → notepad

Every path above can be overridden — see Environment variables.

Profile examples

Claude profile example

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://api.example.com",
    "ANTHROPIC_AUTH_TOKEN": "sk-..."
  },
  "model": "claude-opus-4-6"
}

Codex profile example

configmyapi.toml + optional matching authmyapi.json:

model_provider = "openai_http"
model = "gpt-5"

[model_providers.openai_http]
name = "My Provider"
base_url = "https://api.example.com/v1"
wire_api = "responses"
requires_openai_auth = true
{ "OPENAI_API_KEY": "sk-..." }

OpenCode profile example

configmyapi.json + optional matching authmyapi.json:

{
  "$schema": "https://opencode.ai/config.json",
  "model": "myapi/gpt-5",
  "provider": {
    "myapi": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "My API",
      "options": { "baseURL": "https://api.example.com/v1" },
      "models": { "gpt-5": { "name": "GPT-5" } }
    }
  }
}
{ "myapi": { "type": "api", "key": "sk-..." } }

OpenCode apply merges the profile’s providers into the existing global config instead of replacing the whole file. Same-named providers are overwritten; other providers and unrelated keys stay. Auth entries are merged by provider id. OpenCode’s database, sessions, and state directories are not switched. A project-local opencode.json or .opencode/ may still override the global config. The backend manages standard JSON files; if you use commented opencode.jsonc, point OPENCODE_CONFIG at a plain JSON profile entry.

Pi profile example

modelsmyapi.json + optional matching settingsmyapi.json and authmyapi.json:

{
  "providers": {
    "myapi": {
      "baseUrl": "https://api.example.com/v1",
      "api": "openai-completions",
      "headers": {
        "User-Agent": "codex_cli_rs/0.145.0 (Ubuntu 22.04; x86_64) unknown",
        "originator": "codex_cli_rs",
        "X-Stainless-Lang": "",
        "X-Stainless-Package-Version": "",
        "X-Stainless-OS": "",
        "X-Stainless-Arch": "",
        "X-Stainless-Runtime": "",
        "X-Stainless-Runtime-Version": "",
        "X-Stainless-Retry-Count": "",
        "X-Stainless-Timeout": ""
      },
      "models": [{ "id": "gpt-5", "name": "GPT-5", "reasoning": true }]
    }
  }
}
{ "defaultProvider": "myapi", "defaultModel": "gpt-5" }
{ "myapi": { "type": "api_key", "key": "sk-..." } }

Pi apply merges the profile’s providers into the existing models.json, and shallow-merges settings/auth keys. Same-named providers are overwritten; other providers and unrelated settings stay. Pi sessions, trust decisions, installed extensions, and models-store.json are not switched. A project-local .pi/settings.json may override the global settings. Pi accepts comments in its own models.json, but proxi profiles intentionally use standard JSON so they can be validated and edited safely. When a Pi provider uses an OpenAI-shaped API — its api field starts with openai (openai-completions, openai-responses, …) or is absent, which is what proxi pi add writes — proxi adds Codex CLI 0.145.0-compatible User-Agent / originator headers, clears every existing X-Stainless-* value, and writes empty values for the known SDK fingerprint headers. Existing unrelated custom headers are preserved. Model detection requests use the same compatibility headers.

This is not cosmetic: on its OpenAI path Pi sends User-Agent: OpenAI/JS <version>, and some relays reject that user agent outright with 403 Your request was blocked. — regardless of key, model, or request body. Overriding the User-Agent is what gets through. Providers on anthropic-messages / google-generative-ai are deliberately left alone, since they go through different SDKs where a Codex user agent would be wrong.

Commands

proxi                              pick target → pick profile
proxi claude | codex | opencode | pi    interactive menu for that tool
proxi claude <name>                apply directly
proxi codex <name>
proxi opencode <name>
proxi pi <name>
proxi list [claude|codex|opencode|pi]
proxi current
proxi dir
proxi claude add [<name>]          interactive add (URL / Key)
proxi codex add [<name>]
proxi claude edit <name>           edit raw files with $EDITOR
proxi codex edit <name>
proxi opencode add [<name>]        requires URL / Key / Model
proxi opencode edit <name>
proxi pi add [<name>]              URL / Key + Model(s) or auto-detection
proxi pi edit <name>
proxi pi models <name>             list configured models
proxi claude edit <name> --url URL --key KEY --model MODEL
proxi codex edit <name> --url URL --key KEY --model MODEL
proxi opencode edit <name> --url URL --key KEY --model MODEL
proxi pi edit <name> --url URL --key KEY --model MODEL
proxi pi models <name> --add MODEL,... [--detect] [--default MODEL]

Add / edit also accept flags:

proxi claude add myapi --url https://api.example.com --key sk-xxx
proxi claude add myapi --url https://api.example.com --key sk-xxx --no-use
proxi claude edit myapi --url https://api.example.com --key sk-new
proxi codex edit myapi --url https://api.example.com/v1 --key sk-new --use
proxi opencode add myapi --url https://api.example.com/v1 --key sk-new --model gpt-5
proxi opencode edit myapi --url https://api.example.com/v1 --model gpt-5 --use
proxi pi add myapi --url https://api.example.com/v1 --key sk-new --model gpt-5
proxi pi add myapi --url https://api.example.com/v1 --key sk-new \
  --model gpt-5 --models gpt-5,gpt-4.1,gpt-4o
proxi pi add myapi --url https://api.example.com/v1 --key sk-new --detect-models
proxi pi edit myapi --url https://api.example.com/v1 --model gpt-5 --use
proxi pi edit myapi --models gpt-5.6-sol,gpt-5.6-terra
proxi pi models myapi
proxi pi models myapi --add gpt-5.6-sol,gpt-5.6-terra --default gpt-5.6-sol
proxi pi models myapi --detect --use

edit <name> without --url / --key / --model / --models / --detect-models keeps the old behavior and opens $EDITOR. With flags, only those fields are updated; editing the currently active profile syncs to the target config unless you pass --no-use.

For Pi, --model selects the default model while --models adds a list of available models. --detect-models (or pi models <name> --detect) requests the provider base URL with /models appended, accepts common OpenAI-style data[].id and models[] responses, and merges newly found IDs without removing existing model metadata. In the interactive Pi add flow, enter auto at the model prompt to run detection.

Environment variables

Variable Purpose
PROXI_HOME Data root (contains the four setfor* source dirs)
PROXI_DIR / PROXI_CLAUDE_DIR Override Claude profile source dir
PROXI_CODEX_DIR Override Codex profile source dir
PROXI_OPENCODE_DIR Override OpenCode profile source dir
PROXI_PI_DIR Override Pi profile source dir
CLAUDE_CONFIG_DIR Override ~/.claude
CODEX_HOME Override ~/.codex
OPENCODE_CONFIG_DIR Override OpenCode global config dir (default ~/.config/opencode on all platforms)
OPENCODE_CONFIG Point at a specific OpenCode config file
PI_CODING_AGENT_DIR Override Pi config dir (default ~/.pi/agent)
XDG_CONFIG_HOME / XDG_DATA_HOME Override OpenCode’s config / data roots — honored on macOS, Linux, and Windows alike

Runtime dependencies (for end users)

Build User needs
Rust binary Nothing (just the proxi executable)
Python legacy Python 3.11+

Crates (clap, serde, toml, …) are fetched at build/release time and linked into the binary — not a user-side package burden.

Security

  • Only keep *.example.* samples in the repo; real settings*.json / models*.json / config*.toml / config*.json / auth*.json are gitignored.
  • Key-bearing files created or overwritten by proxi use mode 0600 on Unix.
  • Before pushing, confirm git status shows no token-bearing files.
  • Switching creates local backups (settings.json.bak / config.toml.bak, etc.) — do not commit those either.

Docs

Roadmap

Further agent adapters and UX items are tracked in TODO.md (Cursor, Gemini CLI, etc. not yet wired).

License

MIT

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages