Skip to content

Repository files navigation

Gentrek

Realtime token & cost tracker for every AI you use — multi-provider, multi-model, multi-app.

Gentrek is a proxy gateway + live dashboard. Point your apps' SDK base URL at Gentrek, and every call (streaming included) is metered the moment it finishes: tokens, cache reads/writes, reasoning tokens, latency, TTFT, and estimated cost — per provider, per model, per app.

Pages

Page What it shows
/ Dashboard — hero cost, KPI tiles, stacked tokens/cost over time, per-provider cards, per-model & per-app breakdowns, live call feed
/flow Live flow map — every call animates from its app, through the gateway, to its provider
/settings API keys (stored server-side, masked in UI), connection snippets, data-safety notes

Quick start

npm install
npm run dev        # http://localhost:3000

Open the dashboard and press Seed last hour to see it working with synthetic data (tagged demo), or Start live traffic for a continuous simulation. Clear all data removes everything.

Connect a real app

  1. Give the gateway a key (any one of these):
    • paste it on the Settings page (stored in .data/keys.json, localhost-only writes), or
    • create .env.local and set e.g. ANTHROPIC_API_KEY (see Configuration below), or
    • keep the key in your app — the gateway forwards your app's own auth header untouched.
  2. Point the SDK at the gateway (copy-paste snippets are on the Settings page):
// Anthropic
new Anthropic({ baseURL: "http://localhost:3000/api/v1/anthropic",
                defaultHeaders: { "x-gentrek-app": "my-app" } });

// OpenAI
new OpenAI({ baseURL: "http://localhost:3000/api/v1/openai/v1",
             defaultHeaders: { "x-gentrek-app": "my-app" } });

// Google Gemini
new GoogleGenAI({ httpOptions: { baseUrl: "http://localhost:3000/api/v1/google",
                                 headers: { "x-gentrek-app": "my-app" } } });

// OpenRouter (also asks OpenRouter for its real dollar cost per call)
new OpenAI({ baseURL: "http://localhost:3000/api/v1/openrouter/api/v1", ... });

// Any OpenAI-compatible endpoint (Groq, DeepSeek, Ollama, vLLM) — set CUSTOM_BASE_URL
new OpenAI({ baseURL: "http://localhost:3000/api/v1/custom/v1", ... });

x-gentrek-app / x-gentrek-tag are optional attribution headers.

Add your own providers

Settings has an Your own providers panel: give any AI endpoint a name and base URL and it becomes a first-class provider with its own gateway route, colour, logo and API key. One-click presets cover NVIDIA NIM, Kimi (Moonshot), DeepSeek, Groq, Mistral, xAI, Together and a local Ollama. Pick the dialect so the gateway knows how to read token usage from the response:

Dialect Use for
OpenAI compatible almost everything: NVIDIA NIM, Kimi, DeepSeek, Groq, Mistral, xAI, Together, vLLM, Ollama
Anthropic Messages API anything speaking /v1/messages
Google Gemini API anything speaking generateContent

A provider added as "Kimi" is served at /api/v1/kimi/v1 and stores its key under that id. Models missing from data/pricing.json are still tracked; their cost reads n/a until you add prices for them.

For calls that can't go through the proxy

POST usage events directly:

curl -X POST http://localhost:3000/api/ingest -H "content-type: application/json" \
  -d '{"provider":"anthropic","model":"claude-opus-5","input":1200,"output":300,"app":"batch-job"}'

API

Route Purpose
ALL /api/v1/{provider}/{...path} The metering proxy (anthropic, openai, google, openrouter, custom)
POST /api/ingest Push usage events (single or array, max 5000)
GET /api/stats?range=1h Aggregates: totals, by provider/model/app, time series
GET /api/stream SSE feed of usage events as they happen
GET /api/events?format=csv Raw events (JSON or CSV export) · DELETE wipes the log
GET/POST/DELETE /api/keys Key management (writes localhost-only)
GET /api/pricing The active pricing table
POST /api/demo Seed synthetic traffic / toggle live simulation

Pricing table

data/pricing.json — 63 models across Anthropic, OpenAI, Google Gemini, and OpenRouter, verified against official pricing pages on 2026-08-28. Costs are split per token class (input / output / cache read / cache write). OpenRouter calls prefer the real dollar cost the API reports over the table. Edit the file any time — it hot-reloads, no restart needed. Calls whose model isn't in the table are flagged unpriced rather than silently $0.

Cloud mode (multi-user)

Set the Supabase env vars (see SETUP-CLOUD.md) and Gentrek becomes a multi-user service: passwordless sign-in (Google / GitHub SSO or email magic link), one isolated workspace per user (Postgres row-level security), and gateway calls authenticated by hashed gtk_… workspace tokens. Leave the vars unset and everything stays single-user local.

Each user chooses how their provider key is handled. Save it and it is encrypted with AES-256-GCM under GENTREK_ENCRYPTION_KEY, which lives only in the environment, so their app then sends nothing but its workspace token. Leave it out and the app sends its own key per request and nothing is stored. Both are fully supported.

Data & safety

  • Prompts and responses are never stored — only token counts and call metadata.
  • Local mode: events in .data/events.jsonl, keys in .data/keys.json, both gitignored. Keys are masked in the UI and never sent to the browser.
  • Cloud mode: events in Postgres behind row-level security, so one workspace cannot read another's. A saved provider key is encrypted at rest and its table has no browser-readable policy at all.
  • The gateway never returns a wildcard CORS header, and never spends a saved key for a browser origin it does not vouch for.
  • Cost figures are estimates for awareness; the provider's billing page is the source of truth.

Configuration

No .env file is committed. Create .env.local locally, and set the same names in your host's dashboard when you deploy.

Variable Needed for Notes
ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, OPENROUTER_API_KEY local mode Optional. Your app can send its own key instead
NEXT_PUBLIC_SUPABASE_URL cloud mode Project URL
NEXT_PUBLIC_SUPABASE_ANON_KEY cloud mode Publishable key, safe for browsers
SUPABASE_SERVICE_ROLE_KEY cloud mode Secret. Server only, bypasses row level security
GENTREK_ENCRYPTION_KEY letting users save provider keys 32 random bytes, base64. Never rotate it once keys are stored, or they become unreadable
GENTREK_ALLOWED_ORIGINS optional Comma separated. Only if a browser app calls the gateway directly
GENTREK_GATEWAY_SECRET optional Required on every call when set. Use it before exposing a local instance on a network
GENTREK_RETENTION_DAYS optional Raw events older than this are pruned. Default 90, 0 disables
GENTREK_ALLOW_DEMO optional Set to 0 to refuse synthetic seed traffic
GENTREK_DATA_DIR optional Where local state lives. Default .data

Generate an encryption key with:

node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"

Tests

npm test   # SSE parsing, per-provider usage extraction, pricing math

About

Realtime token and cost tracker for every AI you use. Point your SDK's base URL at the gateway and watch tokens, cost, cache and latency per provider, model and app.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages