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

teamclaude-cloud

v1.13.5

Published

Multi-account Claude proxy with quota-based rotation + cloud token sync and auth-key control

Readme

TeamClaude Cloud

Multi-account Claude proxy with automatic quota-based rotation for Claude Code — plus a cloud SaaS layer that syncs authenticated tokens to the cloud and controls, per auth key, which accounts each machine may use.

Cloud SaaS (teamclaude-cloud)

The base proxy runs locally. The cloud layer lets you authenticate every account once on one PC, sync those tokens to the cloud, and let other machines pull only the accounts you allow them — via an auth key, without re-authenticating each account per PC.

[Admin PC]   teamclaude login ×N   →   teamclaude cloud push
                                         │
                                         ▼
[Cloud]  teamclaude.cloud: encrypted tokens (AES-256-GCM) + auth keys (hashed) + key→account mapping
         Cloud API: sync push/pull, auth-key issue/revoke/map
                                         ▲
                                         │  auth key
[Consumer PC]  teamclaude cloud pull --key tck_…   →   teamclaude server

Security model: tokens are encrypted at rest and token storage is server-only (row-level security denies all client roles); auth keys are stored as a SHA-256 hash (for pull-time lookup) and an AES-256-GCM ciphertext under the same key as the tokens, so the owner can re-copy the full teamclaude cloud pull --key … command from the dashboard at any time (owner-only GET /auth-keys/:id/reveal, revoked keys return 409). Keys issued before this change are hash-only and non-revealable — re-issue to get a copyable key. Access control (which key may use which account) is enforced server-side in the cloud API.

Web dashboard

A browser dashboard (signup/login + auth-key issuance and control) is served on Vercel:

https://teamclaude-cloud.vercel.app

Sign up there, then use the same account with teamclaude cloud login on the admin PC. The dashboard shows your synced accounts with their usage (5h session, weekly, and the model-scoped "Fable" weekly window — as measured by the proxy at push time, with the push timestamp shown), toggles accounts globally, manages groups (create/rename/delete, per-group account enable + priority ordering), and issues/moves/revokes auth keys per group. The dashboard is a static SPA (public/) plus a health endpoint (api/health.js); GET /api/health returns service status JSON.

Cloud commands

# Admin PC: authenticate to the cloud, then push local account tokens
# (the proxy's quota snapshot rides along so the dashboard shows 5h/weekly/Fable usage)
teamclaude cloud login --email <[email protected]>
teamclaude cloud push

# Groups: an auth key belongs to ONE OR MORE groups (default "main"); accounts are
# allowed per GROUP, and a key's pull returns the UNION of all its groups' accounts.
# Assign a key to multiple groups from the dashboard (Auth Keys → group checkboxes).
teamclaude cloud group list
teamclaude cloud group create team-a
teamclaude cloud group allow  team-a --accounts <uuid1>,<uuid2>   # order = priority (#0 first)
teamclaude cloud group rename team-a --to team-alpha
teamclaude cloud group delete team-a                              # its keys move to "main"

# Auth keys (raw key printed once)
teamclaude cloud key create --label laptop --group team-a
teamclaude cloud key list
teamclaude cloud key move   <key-id> --group main
teamclaude cloud key revoke <key-id>

# Global account switch (excluded from EVERY group's pull when disabled)
teamclaude cloud account disable <accountUuid|localName>
teamclaude cloud account enable  <accountUuid|localName>

# Consumer PC: pull the key's group's accounts (tokens + priority) into the local config
# (key-only — no `cloud login`; the endpoint is built in). The key is saved so the
# running server keeps syncing on its own.
teamclaude cloud pull --key tck_…
teamclaude server

Group exclusivity: an account can be enabled in at most one group at a time (DB-enforced with a partial unique index; the API answers 409 account_in_use naming the conflicting group) — so two groups can never pull, and therefore never concurrently use, the same account.

Priority & selection: the group's account order is delivered as each pulled account's priority, which the local proxy's existing selection consumes unchanged — explicit priority first, then the same use-or-lose algorithm (weekly reset soonest, session reset, lowest usage) as always.

Live sync (running server ⇄ cloud). cloud pull stores the endpoint + auth key, so a running teamclaude server re-pulls on an interval (config.cloudSyncIntervalMs, default 30 s; 0 disables) and applies changes without a restart: refreshed tokens are updated in place (freshest-token-wins), accounts added to / removed from the group appear / disappear live, and revoking the key drops all of its accounts and the proxy refuses new requests (it self-heals the moment you re-pull with a valid key). The rotation/quota/failover handling still runs entirely in the local proxy (unchanged algorithm) — the cloud is only the control plane feeding it fresh config. A cloud outage is non-blocking: a transient pull error keeps the last-known accounts and retries next interval; only an explicit 403 (revoked/invalid key) removes accounts.

What revocation does and does not do. A pull hands the consumer both the access and refresh tokens for each allowed account. Server-side controls — revoking the key (it can no longer pull) and disabling/removing the account from the group (it stops being handed out) — only cut off future pulls. They do not invalidate a token a consumer already pulled: that consumer holds the refresh token and can keep minting new access tokens directly against Anthropic until Anthropic itself revokes it (this proxy cannot remotely invalidate an OAuth grant). So treat a pulled key/account as "access granted until the underlying OAuth credential is rotated at the source." The client-side prune (dropping local accounts a key no longer allows, scoped per key) — applied automatically by the running server's live sync (above), or via TUI R / restart — is hygiene/convenience, not a hard revocation boundary. One consumer is expected to use one key.

Sync is freshest-token-wins: a push/pull never overwrites a newer token with an older one (compared by normalized expiresAt), so a token refreshed on any machine wins. Pulled priority applies even when the token itself is kept-local (control-plane vs token freshness). The cloud layer is additive — if the cloud is unreachable the local proxy still runs on whatever accounts are in the local config.

The cloud API lives at auth.teamclaude.cloud — the CLI ships no backing-infrastructure hosts or keys; consumers authenticate with their auth key, admins with cloud login.


Base proxy

Sits transparently between Claude Code and the Anthropic API, managing multiple Claude Max (or API key) accounts and automatically switching when one approaches its session or weekly quota limit.

TeamClaude TUI

Features

  • Use-or-lose account priority — measures each account once at startup, then prioritizes the account whose weekly (7d) quota resets soonest (then soonest session reset, then lowest usage), so quota about to renew unused is drained first; re-evaluates every 5 minutes and switches immediately when the active account reaches the quota threshold (default 98%). Pin explicit ranks in the TUI (o) or via teamclaude priority for the accounts you want first — everything unranked stays on this automatic (auto) ordering
  • Instant failover on 429 — an exhausted account (token quota hit) is throttled for its retry-after (clamped to 1s–5m) and skipped; a rate/concurrency 429 (quota left but hit too fast) fails the request over to another account so concurrent overflow spreads instead of erroring. Either way nothing blocks, and a request-global 429 only passes through after every account has been tried — never throttling the fleet
  • Interactive TUI — real-time dashboard with color-coded quota bars showing usage %, reset countdowns, an activity log, and keyboard controls (switch, enable/disable, reorder accounts)
  • Manual account controls — enable/disable accounts and pin an explicit account order from the TUI or CLI (teamclaude disable|enable|priority); a disabled account is excluded from rotation while its in-flight requests drain, and everything unranked stays on automatic use-or-lose ordering
  • Quota survives restarts — per-account quota state and the warm-up probe template are snapshotted to <config>.quota.json (every minute and on exit) and restored at startup, so a restart doesn't blank the dashboard, blind the account ordering, or leave forced re-measure (R) dead until traffic flows again
  • Active warm-up — after a (re)start the proxy probes still-unmeasured accounts with a minimal request (reusing the shape of the first real request, restored across restarts), so the whole fleet's quota populates within seconds instead of waiting for traffic to reach each account
  • Server lifecycleteamclaude stop / teamclaude restart cleanly stop or replace the running server from any terminal
  • OAuth token management — automatically refreshes tokens nearing expiry and persists them to config; client token refreshes pass through untouched
  • Hot-reload accounts — add accounts via import or login while the server is running, press R to pick them up; R also force-re-measures the whole fleet's quota, so the dashboard reflects usage spent outside this proxy (other devices/sessions) — and works right after a restart, since the probe template is restored from the snapshot
  • Account deduplication — detects duplicate accounts by UUID and keeps the most recent
  • Request logging — optional full request/response logging for debugging
  • Zero dependencies — uses only Node.js built-in modules

Quick Start

Requires Node.js 18+.

# Install (published to npm — auto-updates via `npm update -g` or `teamclaude update`)
npm install -g teamclaude-cloud

# Add your first account (opens browser for OAuth)
teamclaude login

# Add a second account
teamclaude login

# Start the proxy
teamclaude server

# In another terminal, run Claude Code through the proxy
teamclaude run

You can also import existing Claude Code credentials instead of logging in:

claude /login           # Log into an account in Claude Code
teamclaude import       # Import its credentials

Adding Accounts

OAuth Login (recommended)

The easiest way to add accounts — opens your browser for authentication:

teamclaude login

Uses the same OAuth flow as Claude Code. Auto-detects the account email and subscription tier. Logging in with the same account again updates its credentials.

You can add accounts while the server is running — press R in the TUI to reload.

Import from Claude Code

If you already have Claude Code set up, you can import its credentials directly:

claude /login           # Log into an account in Claude Code
teamclaude import       # Import its credentials

Re-importing the same account updates its credentials. You can also import from a custom path:

teamclaude import --from /path/to/credentials.json

API Key

For Anthropic API key accounts (billed via Console):

teamclaude login --api

Usage

Start the proxy server

teamclaude server

When running from a TTY, shows an interactive TUI with:

  • Account table with numbered rows and session/weekly quota progress bars (usage % overlaid, plus a reset countdown when space allows); wide terminals add a third Fbl bar with the model-scoped weekly limit (the separate "Fable" weekly limit from Claude's usage UI). Ranked accounts are listed first, then the auto accounts in their actual drain order (weekly reset soonest first)
  • Real-time activity log with request tracking
  • Keyboard shortcuts (see below)

Falls back to plain log output when not a TTY (e.g. running as a service).

If the configured port is already in use — for example another TeamClaude proxy is already running — the server prints a clear message and exits instead of crashing with an unhandled error. Inspect the existing one with teamclaude status, or find the listener with lsof -nP -iTCP:<port> -sTCP:LISTEN.

TUI Keyboard Shortcuts

| Key | Action | |-----|--------| | / | Move the selection cursor over the accounts | | s | Switch active account (to the selected one) | | e | Enable / disable the selected account | | o | Order the selected account: / move its rank, a resets the WHOLE order to auto (weekly-reset ordering), c clears just this account's rank | | a | Add account (import or API key) | | d | Delete an account (with confirmation) | | R | Reload accounts from config and re-measure every account's quota — revives lapsed OAuth tokens first, includes the model-scoped Fable window, and reports an honest M/N when some accounts fail or are skipped | | q | Quit |

In selection mode, use j/k or arrow keys to navigate, Enter to confirm, Esc to cancel.

Stop / restart the server

teamclaude stop       # SIGTERM the running server (escalates to SIGKILL if needed)
teamclaude restart    # stop the running server (if any) and start a fresh one

The running server is discovered via its state file (<config>.server.json) with a port-probe fallback, so stop/restart work from any terminal — even after a config port change. Quota state is restored on restart (see below), so a restart doesn't lose the dashboard.

Note: if a Claude Code session is itself routed through the proxy (teamclaude run), running teamclaude stop inside that session severs its own API connection (Unable to connect to API (ConnectionRefused)). Stop or restart the proxy from a separate terminal instead — with restart, an in-flight session recovers on its own retries.

Account order & manual controls

By default every account is on auto ordering (use-or-lose: weekly reset soonest is drained first). You can layer manual controls on top:

teamclaude disable <name>            # exclude from rotation (in-flight requests drain)
teamclaude enable <name>             # re-enable
teamclaude priority <name> <n|auto>  # pin explicit order (lower = preferred); "auto" clears it

In the TUI, / select an account, e toggles enable/disable, and o grabs the selected account into order mode: / move its rank, a resets the WHOLE order back to auto, c clears just that account's rank, Enter/Esc done. Ranked accounts render as #1 #2 … and are preferred first; everything unranked stays on the automatic ordering — so you can pin a few accounts and let the rest rotate.

CLI changes made while the server is running are picked up with R (reload) in the TUI or teamclaude restart.

Run Claude Code through the proxy

teamclaude run

Or manually set the environment:

eval $(teamclaude env)
claude

Other commands

teamclaude accounts          # List accounts with subscription tier and token status
teamclaude accounts -v       # Also show token expiry times
teamclaude status            # Show live proxy status (requires running server)
teamclaude stop              # Stop the running proxy server
teamclaude restart           # Stop the running server and start a fresh one
teamclaude remove <name>     # Remove an account
teamclaude disable <name>    # Disable an account (excluded from rotation)
teamclaude enable <name>     # Re-enable a disabled account
teamclaude priority <name> <n|auto>  # Pin selection order (lower = preferred; "auto" clears)
teamclaude api <path>        # Call an API endpoint with account credentials
teamclaude help              # Show all commands

Request logging

Log full request/response details to a directory (one file per request):

teamclaude server --log-to /tmp/requests

Configuration

Config is stored at ~/.config/teamclaude.json (or $XDG_CONFIG_HOME/teamclaude.json). A random proxy API key is generated on first use.

Override the config path with TEAMCLAUDE_CONFIG:

TEAMCLAUDE_CONFIG=./my-config.json teamclaude server

Config format

{
  "proxy": {
    "port": 3456,
    "apiKey": "tc-auto-generated-key"
  },
  "upstream": "https://api.anthropic.com",
  "switchThreshold": 0.98,
  "accounts": [
    {
      "name": "[email protected]",
      "type": "oauth",
      "accountUuid": "...",
      "accessToken": "sk-ant-oat01-...",
      "refreshToken": "sk-ant-ort01-...",
      "expiresAt": 1774384968427,
      "enabled": true,
      "priority": 0
    }
  ]
}

| Field | Description | |-------|-------------| | proxy.port | Local port the proxy listens on | | proxy.apiKey | API key clients use to authenticate with the proxy | | upstream | Upstream API base URL | | switchThreshold | Quota utilization (0–1) at which an account is considered full and skipped | | reevalIntervalMs | How often (ms) to re-rank accounts by priority while the active one is healthy (optional, default 300000 = 5 min). Set to 0 to disable the timer entirely — the active account then only changes when it becomes unavailable or via per-request 429 failover | | activeWarmup | Probe unmeasured accounts after a restart to populate quota (optional, default true) | | warmupIntervalMs | How often (ms) the active warm-up re-probes accounts whose quota window reset (optional, default 300000 = 5 min; 0 = startup-only) | | accounts[].enabled | Set false to exclude the account from rotation (optional, default true) | | accounts[].priority | Explicit selection rank (lower = preferred first; optional — unset means automatic use-or-lose ordering) |

How It Works

  1. Claude Code connects to the local proxy instead of api.anthropic.com
  2. The proxy selects the active account and forwards requests with that account's credentials
  3. OAuth tokens expiring within 5 minutes are automatically refreshed and persisted to config
  4. Rate limit headers from the API (anthropic-ratelimit-unified-*) track session (5h) and weekly (7d) quota utilization. Model-scoped weekly windows (7d_oi — the separate "Fable" weekly limit) are tracked and displayed too, but never affect routing: an account over its Fable weekly limit still serves every other model
  5. Cold-start warm-up: quota is only known after a request flows through an account, so at startup the proxy first routes requests to any unmeasured account until every account has been measured once. An active warm-up additionally probes unmeasured accounts directly — a minimal 1-token request reusing the shape of the first real request — so the whole fleet is measured within seconds of the first post-restart request instead of waiting for traffic to reach each account (activeWarmup: false disables it). Then account selection becomes use-or-lose: among accounts still under the threshold, it prefers the one whose weekly (7d) quota resets soonest (tie-breaks: soonest session reset, then lowest usage), so quota about to renew unused is drained first. Explicitly ranked accounts (priority / TUI o) are preferred before all of that; disabled accounts are excluded entirely. The active account stays sticky to keep its prompt cache warm; priority is re-evaluated every reevalIntervalMs (default 5 min; set 0 to disable timer-based switching), and on reaching the threshold it switches immediately to the next-highest-priority account
  6. On a 429 the proxy classifies it (never sleeping holding the client connection):
    • Account-quota exhaustion (upstream reports the account is over its limit) → marks that account rate-limited for its retry-after (clamped to 1s–5m) and immediately re-dispatches to the next available account. If every account is throttled it returns 429 with a computed retry-after. (This also keeps cold-start warm-up fast: an exhausted account is skipped in one round-trip.)
    • Rate/concurrency or transient 429 (account has token quota left but was hit too fast, or a transient limit) → the request fails over to another available account (per-request, without throttling the account), so concurrent overflow spreads to an idle account instead of erroring. If every account has been tried for the request (→ effectively global), the 429 is passed through — still without throttling any account, so the fleet isn't poisoned.
  7. Transient network errors (connection reset, timeout) drop the connection so the client can retry
  8. If all accounts are exhausted, returns 429 with a retry-after computed from the soonest account reset — the real unified 5h/7d (or standard) reset of whichever over-threshold window is actually blocking each account, so clients back off until quota genuinely frees instead of retrying against a fixed 60s fallback. A merely concurrency-capped (but quota-healthy) fleet still gets the short fallback, since a freed slot is seconds away
  9. Quota survives restarts: the server snapshots per-account quota/throttle state — plus the committed warm-up probe template — to <config>.quota.json (every minute and on exit) and restores both at startup, so a restart doesn't blank the dashboard, blind the use-or-lose ordering, or leave warm-up probes and forced re-measure (TUI R) without a known-accepted request shape until traffic flows again. A restored template is provisional: the first freshly accepted request shape replaces it (the snapshot's model may have been retired since). Expired windows are swept lazily and re-measured from live traffic
  10. Client token refresh requests (/v1/oauth/token) are relayed to upstream untouched — the proxy and client manage their own token lifecycles independently

License

MIT