npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cokefenta/pi-switch

v0.3.9

Published

Lightweight profile switcher for pi models.json

Readme

pi-switch

Version Platform Built with Rust License

TUI + CLI dual-mode profile switcher for pi agent

Manage provider profiles and run a local model-name routing gateway with failover — via an interactive TUI or CLI.

English | 中文


📸 Screenshots


📥 Installation

# npm (recommended)
npm install -g @cokefenta/pi-switch

# or via pi
pi install npm:@cokefenta/pi-switch

Build from source (requires Node.js >= 20, Rust 1.80+):

git clone https://github.com/user/pi-switch.git
cd pi-switch
npm install
npm run build:native
node bin/pi-switch.js tui

System Compatibility

Supported platforms:

  • ✅ Windows (x64)
  • ✅ macOS (Intel & Apple Silicon)
  • ✅ Linux (x64) - glibc & musl

Linux users: This package includes prebuilt binaries for both glibc and musl systems. If you encounter a GLIBC version error, the package will automatically fallback to the musl binary which has broader compatibility.

Troubleshooting GLIBC errors:

# If you see "GLIBC_X.XX not found", build from source:
npm install -g @cokefenta/pi-switch --build-from-source

🚀 Quick Start

pi-switch tui          # Interactive TUI (recommended)
pi-switch webui start  # Browser UI at http://127.0.0.1:43110
pi-switch doctor       # Run environment diagnostics

Three ways, one core. CLI, TUI, and WebUI are thin adapters over the same Rust core. See WEBUI_GUIDE.md for the WebUI and how to keep the three interfaces in sync.

Essential CLI Commands

# Provider management
pi-switch provider add <name> [--preset <id>] [--api-key <key>]
pi-switch provider list
pi-switch provider show <name>
pi-switch provider delete <name>
pi-switch provider expose <name> <model-ids...>    # Expose models to pi agent
pi-switch provider fetch-models <name>             # Fetch models from API

# Proxy (gateway)
pi-switch proxy failover <p1,p2,...>               # Same-model fallback chain
pi-switch proxy start --daemon                     # Start proxy daemon
pi-switch proxy status

# WebUI (browser config)
pi-switch webui start [--host <ip>] [--port <port>] [--daemon]
pi-switch webui status
pi-switch webui stop

# Other
pi-switch presets list                             # List built-in presets
pi-switch config show                               # Display current config
pi-switch config backups                            # List backup files
pi-switch config export <passphrase>                # Encrypted export
pi-switch config import <path> <passphrase>         # Encrypted import
pi-switch stats                                     # View request statistics

✨ Features

| Category | Highlights | |----------|------------| | 🔌 Provider Management | CRUD, duplicate, search/filter, model management, expose to pi agent | | 💡 Built-in Presets | OpenRouter, Anthropic, DeepSeek, SiliconFlow, OpenAI — add profiles instantly | | 🌉 Model-Name Gateway | Stateless routing by profile/model in the request body, SSE streaming, User-Agent disguise, request-body filtering, OpenAI ↔ Anthropic conversion, failover, circuit breaker | | 🖥️ Interactive TUI | ratatui-powered, Dracula theme, mouse support, vim keys (hjkl) | | 🌐 Bilingual | English / 中文, persisted to config, toggle in Settings | | 📊 Usage Stats | Per-provider, per-model request metrics & latency | | 💾 Backup & Sync | Auto-backup on mutation, AES-256-CBC encrypted export/import | | 🩺 Diagnostics | doctor command checks config, models.json, structure |


🎯 Core Workflow

Gateway Routing & Failover

graph LR
    subgraph Setup["⚙️ Setup"]
        A[Add Provider] --> B[Configure Models]
        B --> C[Expose to Pi]
        C --> D[Set Failover Chain]
    end

    subgraph Runtime["🚀 Runtime"]
        E["Request<br/>model: provider-a/gpt-5.4"] --> F{Resolve Route}
        F --> G[Try provider-a]
        G --> H{Success?}
        H -->|✓| I[Response]
        H -->|✗ 429/5xx| J[Try provider-b]
        J --> K{Success?}
        K -->|✓| I
        K -->|✗| L[Circuit Breaker]
        L --> M[60s Cooldown]
        M --> N[Half-Open Probe]
        N -->|✓| G
        N -->|✗| M
    end

    Setup --> Runtime

    style A fill:#50fa7b,stroke:#50fa7b,color:#282a36
    style E fill:#8be9fd,stroke:#8be9fd,color:#282a36
    style I fill:#50fa7b,stroke:#50fa7b,color:#282a36
    style L fill:#ff5555,stroke:#ff5555,color:#f8f8f2

Step by Step

1. Add a provider (CLI or TUI)

pi-switch provider add provider-a --api openai-completions --base-url https://api.example.com/v1 \
    --api-key '$API_KEY' --models gpt-5.4,claude-sonnet-4-5

In TUI: Profiles → a → fill form → Ctrl+S

2. Expose models to pi agent — choose which models appear in ~/.pi/agent/models.json

pi-switch provider expose provider-a gpt-5.4

In TUI: Profiles → select provider → x

3. Start the proxy — it writes a single pi-switch gateway provider to pi

pi-switch proxy failover provider-b,provider-c          # optional same-model fallback
pi-switch proxy start --daemon

4. Use in pi — select the pi-switch provider, then pick a profile/model like provider-a/gpt-5.4

How Gateway Routing Works

Requests are routed by the model name in the request body — no out-of-band state, no "current target":

  • Model-name routing"model": "provider-a/gpt-5.4" resolves to profile provider-a, real model gpt-5.4; the proxy rewrites the body before forwarding upstream
  • Single gateway provider — pi sees one pi-switch provider advertising every exposed model as profile/realModelId; switching model in pi = sending a different model string = instant routing change
  • Automatic failover — same-model fallback across the configured chain on 429/5xx errors or network failures
  • Circuit breaker — after 3 consecutive failures, provider enters 60s cooldown; auto-recovery on half-open probe success
  • Streaming (SSE) — same-format requests (openai→openai, anthropic→anthropic) stream token-by-token; upstream response headers (Content-Type, etc.) are preserved
  • OpenAI ↔ Anthropic — transparently converts between chat completions and messages APIs
  • User-Agent disguise — built-in presets (Claude Code / Codex / Gemini) send the matching client's real User-Agent (and headers like anthropic-beta) to pass upstream client checks; settable globally or per-profile

Known limitation — the OpenAI ↔ Anthropic conversion path can't stream: it parses the full JSON to convert formats. If pi sends stream: true but the model routes to a cross-format upstream (OpenAI request → Anthropic upstream, or vice-versa), the reply comes back as a single non-streamed response. Same-format routes stream normally.


🏗️ Architecture

pi-switch/
├── bin/pi-switch.js         # CLI entry point
├── index.js                 # ESM wrapper for native addon
├── pi-switch-native.cjs     # NAPI loader (auto platform detection)
├── src-rust/                # Rust native core (napi-rs)
│   ├── lib.rs               # NAPI function exports
│   ├── config.rs            # Config load/save, types
│   ├── ops.rs               # Core operations
│   ├── presets.rs           # Built-in provider presets
│   ├── proxy.rs             # Proxy server (gateway routing, failover, circuit breaker)
│   ├── daemon.rs            # Daemon lifecycle
│   ├── stats.rs             # Request log aggregation
│   ├── sync.rs              # Encrypted export/import
│   └── tui/                 # Interactive terminal UI (ratatui)
│       ├── app.rs           # State machine + key handler
│       ├── form.rs          # Provider form state
│       ├── i18n.rs          # Bilingual (EN/ZH)
│       └── ui/              # Rendering (chrome, pages, overlays)
├── src/                     # JavaScript layer (pi extension support)
├── extensions/index.ts      # Pi agent extension (/piswitch)
└── Cargo.toml

Config files:

  • ~/.pi-switch/config.json — profiles, proxy settings, failover chain
  • ~/.pi-switch/backups/ — timestamped auto-backups on every mutation
  • ~/.pi/agent/models.json — pi's provider registry (pi-switch writes a single gateway provider)

❓ FAQ

In pi, open /model and pick any advertised profile/model (e.g. provider-a/gpt-5.4). The proxy routes by the model name in each request — no extra step needed.

To add more models, expose them in TUI (Profiles → select provider → x) or via CLI:

pi-switch provider expose <name> <model-id>...

In TUI: Settings → FailoverEnter → enter comma-separated profile names → Enter. Or via CLI:

pi-switch proxy failover provider-b,provider-c

Profiles in the failover chain that expose the same model are tried in order when the primary fails.

The [proxy] badge indicates this profile is a meta-profile (with "proxy": true). Proxy profiles are used to register a pi provider that points to the local gateway. They are excluded from upstream routing.

In the current gateway mode, proxy profiles are typically not needed — the proxy automatically writes a single pi-switch gateway provider to pi's models.json on startup.

The proxy advertises every exposed model as profile/realModelId under a single pi-switch provider. When pi sends a request with "model": "provider-a/gpt-5.4", the proxy:

  1. Splits on the first / — profile provider-a, real model gpt-5.4
  2. Routes to the provider-a profile's upstream, rewriting body.model to gpt-5.4
  3. On failure (429/5xx), tries the failover chain for any other profile exposing gpt-5.4
# 1. Expose models (per profile)
pi-switch provider expose provider-a gpt-5.4
pi-switch provider expose provider-b gpt-5.4

# 2. Set failover chain (optional)
pi-switch proxy failover provider-b

# 3. Start proxy daemon
pi-switch proxy start --daemon

In pi, select the pi-switch provider, then provider-a/gpt-5.4. The model name in each request determines the route — no "target" to manage.

Some upstream channels only accept requests from whitelisted clients (checking the User-Agent name prefix). pi-switch has three built-in presets that send the matching client's real identity:

| Preset | User-Agent | Extra headers | |--------|------------|---------------| | Claude Code | claude-cli/2.1.161 (external, cli) | anthropic-version, anthropic-beta | | Codex | codex_cli_rs/0.1.0 | — | | Gemini | gemini-cli/0.1.5 | x-goog-api-client |

  • Global: Settings → User-Agent, cycle with ←/→.
  • Per-profile: in a profile's detail view press u to cycle; a per-profile value overrides the global one. Useful when only some upstreams enforce a UA whitelist.

Note: this only passes checks that look at the client name. It does not fabricate deeper per-request tokens (turn state, session ids), which strict first-party endpoints validate.

Everything under ~/.pi-switch/. Pi's own registry is ~/.pi/agent/models.json. No data leaves your machine.


🛠️ Development

npm run build:native:debug     # Build Rust addon (debug)
npm run build:native           # Build Rust addon (release)
cargo build                    # Rust-only build
cargo clippy                   # Lint
cargo fmt                      # Format
cargo test --release --lib     # Run unit tests

Note: Stop the TUI/daemon before npm run build:native to avoid file-lock errors on Windows.


🙏 Acknowledgments

  • cc-switch — the original TUI-based profile switcher for Claude Code, which pioneered the interactive terminal UI pattern and proxy failover design
  • cc-switch-cli — the CLI counterpart, providing a clean command-line interface for provider management

Thanks also to the LINUX DO community for the discussions that sparked this project.


📜 License

MIT