npm.io
0.3.0 • Published 1 month agoCLI

token-proxy

Licence
MIT
Version
0.3.0
Deps
1
Size
575 kB
Vulns
0
Weekly
0

token-proxy

Multi-provider API token proxy: an authentication gateway with key rotation and request logging, providing unified access for AI clients such as Claude Code.

中文文档

Why

Claude Code only sends Authorization: Bearer <token> to custom endpoints, but some upstreams (e.g. opencode go) only accept x-api-key and enforce risk controls on the Claude Code User-Agent. token-proxy acts as a middle layer that:

  • Authentication — multi-user (username + key) with three auth methods, ready for teams
  • Header conversion — Bearer → the header the upstream requires (x-api-key, etc.)
  • User-Agent spoofing — bypass upstream risk controls on AI-client user agents
  • Key rotation — multiple upstream keys rotated round-robin to spread quotas
  • Multiple upstreams — adapter-based support for anthropic / openai-compatible endpoints, fully configurable
  • Full logging — complete request/response details stored in SQLite, with token usage & cost per request

Features

  • SQLite-backed management (users / backends / key pools / routes / models / aliases / admins) — single token-proxy.<env>.db, WAL mode, high performance
  • Zero-DB hot path — auth/routing/backends/models are served from an in-memory snapshot that hot-reloads within ~1s of any admin change (no restart)
  • Usage & cost tracking — input/output tokens and cost parsed from streaming and non-streaming responses, with per-model pricing
  • Model management — catalog, pricing, aliases (client names rewritten to real model names), enable/disable, and per-model backend routing
  • Auto model sync — the catalog auto-syncs from OpenCode Zen / Go every 12 hours (or on demand via a one-click button in the console), keeping models per backend with official pricing when available
  • Request log archiving — expired logs are gzip-archived instead of deleted (downloadable .db.gz / .db, selectable time range, super-admin only), keeping history without growing the main database
  • Web admin console (/admin) — dashboard, users, backends, routes, models, request logs, settings, audit log, and maintenance; fully internationalized (English primary, 中文 available)
  • Environment isolation — dev / test / prod each with its own config file, port and database, selected via .env
  • pm2 cluster — production deployment with 2 instances by default

Architecture

Client (Claude Code / codex / ...)
   │  auth: Bearer user[@backend]:key (Basic / x-api-key also supported)
   ▼
token-proxy (Fastify, prod :3501)
   │  ① parse auth {user, key, upstream}
   │  ② pick adapter by route (anthropic / openai / anthropic-to-openai)
   │  ③ header conversion + UA spoofing + key round-robin + model resolution
   ▼
Upstream (opencode go / DeepSeek / OpenAI-compatible...)

Data:
  config        config.<env>.json (project root / XDG config)
  database      token-proxy.<env>.db (WAL, users/backends/routes/models/logs)
  text logs     logs/token-proxy.YYYY-MM-DD.log (per day)
  admin console http://<host>:<port>/admin

Quick start

Requirements
  • Node.js >= 24 (volta install node@24.16.0 recommended)
Install & run

Option 1 — CLI global install

npm install -g token-proxy
token-proxy init          # create config (prints the initial admin password once)
token-proxy set-password  # set the super-admin password (scrypt hash)
token-proxy start         # start in the background
token-proxy logs          # tail request logs
token-proxy status        # show status
token-proxy stop          # stop

Option 2 — from source

npm install
npm run dev               # dev with hot reload (port 3502)
npm test                  # run all tests

# production with pm2 (cluster, 2 instances, port 3501)
pm2 start ecosystem.config.cjs
pm2 logs token-proxy
Environments

The run environment comes from .env (TOKEN_PROXY_ENV, default dev), copied from .env.example. Each environment is isolated:

Env Config file Database Default port
prod config.prod.json token-proxy.prod.db 3501
dev config.dev.json token-proxy.dev.db 3502
test config.test.json token-proxy.test.db 3503

Config files live in the project root (source mode) or ~/.config/token-proxy/ (CLI global mode). First boot migrates any legacy config.json users/backends/routes into the database.

Client setup (Claude Code)
export ANTHROPIC_BASE_URL="http://<host>:<port>/v1"
export ANTHROPIC_AUTH_TOKEN="username:your-api-key"

Token format: username[@backend]:key — the optional @backend overrides the backend bound to the route.

Configuration

config.json (or config.<env>.json) only holds static settings:

{
  "server": { "host": "0.0.0.0", "port": 3502, "apiPrefix": "/v1", "basePath": "" },
  "admin":  { "username": "admin", "passwordHash": "$scrypt$16384,8,1$..." },
  "security": { "sessionTtlHours": 168 },
  "auth":   { "methods": ["bearer", "basic", "apiKey"] },
  "logging": {
    "directory": "./logs",
    "retentionDays": 365,
    "detailRetentionDays": 30,
    "enableDetailDatabase": true,
    "enableTextLog": true
  },
  "database": { "path": "" }
}

Everything else — users, backends, key pools, routes, models, aliases, admins — is managed from the web console (/admin), stored in SQLite, and applied without restart.

Web console

Open http://<host>:<port>/admin and sign in with the super-admin credentials from config.json. Features:

  • Home — welcome page with system overview and quick-start snippets
  • Dashboard — request volume, success rate, latency, token & cost trends (7/30 days), top users, status distribution, recent requests
  • Users — create/disable users, reset keys (shown once), quotas, per-user usage stats
  • Backends — upstream connection info, key pool management, connectivity tests
  • Routes — entry path → protocol adapter → backend
  • Models — catalog, pricing, aliases, per-model backend routing, enable/disable
  • Requests — paginated logs with multi-field filters and request/response body details
  • Settings — auth methods, log retention, body storage, sub-admins, audit log, VACUUM

Language (English / 中文) is switchable in the sidebar and persisted in the browser.

CLI

token-proxy start | stop | restart | status
token-proxy logs [N]
token-proxy stats
token-proxy init
token-proxy set-password
token-proxy migrate       # import legacy per-day log databases
token-proxy backup        # online SQLite backup

Development

npm run dev        # hot reload on port 3502
npm run check      # syntax check
npm test           # all tests (unit + integration)
npm run cli -- --help

Structure:

src/
├── index.js               # entry: Fastify assembly, forwarding, lifecycle
├── config.js              # config hot-reload + validation (server/admin/security/logging/database)
├── env.js                 # environment (.env) + per-env defaults
├── daemon.js              # process daemon (pid file + detached)
├── db/                    # SQLite: schema/migration, records, legacy import
├── store/                 # in-memory snapshot + 1s hot-reload polling
├── usage.js               # token usage & cost parsing
├── auth/                  # inbound auth (bearer / basic / x-api-key)
├── upstream/              # routing, backend selection, adapters, protocol conversion
├── logger/                # text summary + SQLite detail logs
└── admin/                 # web console: sessions, REST API, static SPA (i18n)

Security

  • Super-admin password is stored in config.json as a scrypt hash (never plaintext); set it with token-proxy set-password
  • The server refuses to start without admin credentials (prevents an open login)
  • Upstream keys are stored locally in SQLite (file mode 0600) and masked in the UI; log in with caution on shared hosts
  • Login rate-limiting (5 failures locks for 5 minutes) and full audit logging
  • For public deployments, put nginx + HTTPS in front

License

MIT

Keywords