Skip to content

Iweisc/pxbin

Repository files navigation

pxbin

A high-performance LLM protocol translation proxy. Routes requests between Anthropic and OpenAI API formats, tracks usage and costs, and provides a management dashboard.

Built for use cases like Claude Code talking to OpenAI-compatible upstreams — pxbin sits in the middle, translates the protocol, and logs everything.

Features

  • Protocol translation — Anthropic API to/from OpenAI-compatible format, including streaming (SSE)
  • Multi-upstream routing — Configure multiple upstream providers with per-model routing and priority
  • Tool use / function calling — Full translation of tool definitions and tool results between formats
  • Extended thinking — Anthropic extended thinking blocks are preserved through translation
  • Prompt caching — Cache control hints are translated; cache read/creation tokens are tracked
  • Cost tracking — Per-model input/output pricing with automatic cost calculation on every request
  • Async request logging — Buffered channel (10k capacity) with batch inserts every 500ms
  • API key management — Two key types: LLM keys (pxb_) for proxy access, management keys (pxm_) for admin
  • Dashboard — React frontend for logs, costs, keys, models, and upstream management
  • In-memory caching — Model and auth key caches with TTL to eliminate per-request DB overhead

Quick Start

Prerequisites

  • Go 1.23+
  • PostgreSQL 17
  • Node.js (for frontend development)

1. Start PostgreSQL

docker compose up -d postgres

2. Configure

Create a config.yaml or use environment variables (PXBIN_ prefix):

# config.yaml
listen_addr: ":8080"
database_url: "postgres://pxbin:pxbin@localhost:5432/pxbin?sslmode=disable"
database_schema: "public"  # set to a dedicated schema when sharing a PG cluster
management_bootstrap_key: ""  # set via PXBIN_MANAGEMENT_BOOTSTRAP_KEY env var
cors_origins:
  - "http://localhost:5173"

3. Build and run

make build
./bin/pxbin

Migrations run automatically on startup.

4. Bootstrap

Set the PXBIN_MANAGEMENT_BOOTSTRAP_KEY env var, then use it to create your first management key:

curl -X POST http://localhost:8080/api/v1/bootstrap \
  -H "Content-Type: application/json" \
  -d '{"bootstrap_key": "your-bootstrap-secret", "name": "admin"}'

5. Add an upstream

Use the management key (pxm_...) to register an upstream provider:

curl -X POST http://localhost:8080/api/v1/upstreams \
  -H "x-api-key: pxm_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "openai",
    "base_url": "https://api.openai.com",
    "api_key": "sk-...",
    "format": "openai"
  }'

6. Import models

Discover and import models from your upstream:

# Discover available models
curl -X POST http://localhost:8080/api/v1/models/discover \
  -H "x-api-key: pxm_..." \
  -H "Content-Type: application/json" \
  -d '{"upstream_id": "<upstream-uuid>"}'

# Import them
curl -X POST http://localhost:8080/api/v1/models/import \
  -H "x-api-key: pxm_..." \
  -H "Content-Type: application/json" \
  -d '{"upstream_id": "<upstream-uuid>", "models": ["gpt-4o", "gpt-4o-mini"]}'

7. Create an LLM key

curl -X POST http://localhost:8080/api/v1/keys \
  -H "x-api-key: pxm_..." \
  -H "Content-Type: application/json" \
  -d '{"type": "llm", "name": "my-llm-key"}'

8. Use the proxy

Point your client at pxbin. For Claude Code:

export ANTHROPIC_BASE_URL=http://localhost:8080
export ANTHROPIC_API_KEY=pxb_...

All upstream credentials are stored in the database — never in config files.

API

Proxy Endpoints

Method Path Auth Description
POST /v1/messages pxb_* Anthropic-format messages
POST /v1/chat/completions pxb_* OpenAI-format chat completions
GET /health none Health check

Authentication via Authorization: Bearer <key> or x-api-key header.

Management Endpoints

All require a pxm_* management key.

Method Path Description
GET/POST /api/v1/keys List / create API keys
PATCH/DELETE /api/v1/keys/{id} Update / deactivate key
GET/POST /api/v1/models List / create models
PATCH/DELETE /api/v1/models/{id} Update / delete model
POST /api/v1/models/discover Discover models from upstream
POST /api/v1/models/import Import discovered models
POST /api/v1/models/sync-pricing Sync pricing from upstream
GET/POST /api/v1/upstreams List / create upstreams
PATCH/DELETE /api/v1/upstreams/{id} Update / delete upstream
GET /api/v1/stats/overview Usage overview (period: 24h, 7d, 30d)
GET /api/v1/stats/by-key Stats grouped by API key
GET /api/v1/stats/by-model Stats grouped by model
GET /api/v1/stats/timeseries Time series data
GET /api/v1/stats/latency Latency percentiles (p50, p95, p99)
GET /api/v1/logs Request logs with filtering
POST /api/v1/bootstrap Create initial key (requires bootstrap key)

Configuration

Field Env Var Default Description
listen_addr PXBIN_LISTEN_ADDR :8080 HTTP listen address
database_url PXBIN_DATABASE_URL PostgreSQL connection string
database_schema PXBIN_DATABASE_SCHEMA public Schema used for all pxbin tables/migrations
log_buffer_size PXBIN_LOG_BUFFER_SIZE 10000 Async log buffer capacity
management_bootstrap_key PXBIN_MANAGEMENT_BOOTSTRAP_KEY Bootstrap key for initial setup
cors_origins PXBIN_CORS_ORIGINS Comma-separated allowed origins
encryption_key PXBIN_ENCRYPTION_KEY AES-256 key for upstream API key encryption

Upstream providers and their API keys are managed exclusively through the management API and stored in the database.

Running On A Shared PG17 Cluster

If pxbin shares a production PostgreSQL cluster with other apps, set a dedicated schema so pxbin migrations and unique constraints stay isolated:

export PXBIN_DATABASE_URL="postgres://user:pass@pg-primary,pg-replica/appdb?sslmode=require&target_session_attrs=read-write"
export PXBIN_DATABASE_SCHEMA="pxbin"

The pxbin role must be able to use (or create) the configured schema.

Frontend

The dashboard is a React SPA at frontend/.

cd frontend
npm install
npm run dev    # Dev server on :5173, proxies API to :8080
npm run build  # Production build to dist/

Pages: Dashboard, Logs, Costs, Keys, Models, Upstreams.

Development

make dev             # Run backend with go run
make test            # Run tests with -race
make lint            # golangci-lint
make frontend-dev    # Vite dev server
make frontend-build  # Production frontend build

Docker

docker compose up

Starts pxbin and PostgreSQL 17. The backend is available on :8080.

Architecture

Client (Claude Code, etc.)
  │
  ▼
pxbin proxy (:8080)
  ├── /v1/messages         → Translates to upstream format → Upstream Provider
  ├── /v1/chat/completions → Routes to upstream            → Upstream Provider
  ├── /api/v1/*            → Management API
  └── Async logger ───────→ PostgreSQL (request_logs)

Key design decisions:

  • net/http + chi over heavier frameworks for minimal proxy overhead
  • Async logging via buffered channel — proxy responses are never blocked by DB writes
  • In-memory caches with TTL for model lookups and auth key validation
  • Connection pooling (25 max connections) via pgxpool
  • SHA-256 key hashing — plaintext keys are never stored
  • No secrets in config — upstream API keys are managed via the API and stored in the database

License

All rights reserved.

About

I don't like litellm :3

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors