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

@cliftonc/finius

v0.1.15

Published

Local-first Claude Code usage & cost tracker — OTLP + transcript ingest with a live dashboard.

Downloads

2,285

Readme

Finius

Local-first usage & cost tracker for Claude Code, Codex, and GitHub Copilot.

A Hono server ingests OTLP HTTP/JSON metrics & logs (and JSONL/rollout transcripts from Claude Code, Codex, and GitHub Copilot — both the copilot CLI and VS Code Copilot Chat) into SQLite — or PostgreSQL for a team server; a React + Vite dashboard renders cost, token, session, person, and model breakdowns with live SSE updates. Everything runs on your machine — no data leaves your laptop (unless you choose to deploy it on a server for your team!).

How Finius compares to ccusage, ccflare, the Grafana/OpenObserve OTEL route, and other Claude Code / Codex / Copilot usage trackers.

Quick start (local)

The fastest way to get running locally is the finius CLI. You need Node 22.5+ (Finius uses the built-in node:sqlite module; developed on Node 24).

npx @cliftonc/finius # first run: installs finius globally, then walks you through setup
finius serve         # start the server + dashboard at http://localhost:8787
finius import all    # optional: import old Claude Code + Codex + Copilot sessions

Then launch Claude Code, Codex, or GitHub Copilot in a new terminal and start coding — the dashboard at http://localhost:8787 updates live as telemetry arrives.

That's it. Three things just happened:

  1. npx @cliftonc/finius installed finius globally and ran finius setup, which saved ~/.finius/config.json and — with your consent — edited ~/.claude/settings.json to add the OTLP env vars plus a SessionEnd + PreCompact hook (finius hook) that uploads each session transcript. If Codex is installed, setup likewise offers to add its Stop hook and OTEL logging to ~/.codex/config.toml. If GitHub Copilot is installed, setup offers to enable VS Code Copilot Chat's OpenTelemetry exporter (in VS Code's settings.json) and to add the copilot CLI's OTLP env vars to your shell profile. Copilot reports usage live over OTLP, not via a session-end hook — unlike Claude Code/Codex there's no transcript-upload hook (Copilot exposes no SessionEnd equivalent), so token/cost arrive from the live OTLP stream and chat transcripts are picked up only when you run finius import copilot.
  2. finius serve started a single process exposing the API and the dashboard on one port. Its data lives under ~/.finius (override with FINIUS_DB_PATH / FINIUS_BLOB_DIR).
  3. Any Claude Code session you run now reports usage to that local server. If you ran finius import all, Finius also backfilled historical Claude Code, Codex, and VS Code Copilot Chat transcripts already on disk. Use finius import claude, finius import codex, or finius import copilot to import only one agent.

Re-run finius setup any time to reconfigure, or finius doctor to diagnose telemetry that isn't arriving.

Going further? setup/quick-start.md is a step-by-step guide covering the local (no-auth) flow above in more detail, team deployment on a shared server (real domain + TLS termination, choosing auth), and setting up GitHub OAuth login gated by org membership.

Running from source (development)

Prefer to hack on Finius itself? Clone the repo and run the dev servers.

1. Install & start

npm install
npm run dev

npm run dev runs the API and UI together (via concurrently):

  • UI → http://localhost:5173 (Vite dev server; proxies /api, /otlp, /events to the API)
  • API → http://localhost:8787

Run them separately if you prefer: npm run dev:server (API only) or npm run dev:client (UI only).

2. Point Claude Code at the server

In the shell where you launch Claude Code, use the bundled helper — it checks the server is up, exports the OTLP env vars, then runs claude:

./scripts/run-claude.sh                 # forwards any extra args to `claude`

Or export the variables manually:

export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_METRICS_EXPORTER=otlp
export OTEL_LOGS_EXPORTER=otlp
export OTEL_EXPORTER_OTLP_METRICS_PROTOCOL=http/json
export OTEL_EXPORTER_OTLP_LOGS_PROTOCOL=http/json
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://localhost:8787/otlp/v1/metrics
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://localhost:8787/otlp/v1/logs
claude

Run a Claude Code session and the dashboard updates live (SSE) as telemetry arrives.

3. (Optional) production build

npm run build   # tsc -> dist + vite build -> dist/client
npm start       # node dist/server/index.js, serves the built UI from dist/client on :8787

When a build exists, npm start serves the UI and API from the single port http://localhost:8787.

Using the dashboard

  • Home — KPIs (cost, tokens, cache, lines, edits, sessions, people), tokens/cost/lines/edits charts over time, plus Models / Users / Sources breakdowns.
  • Sessions, People, Models — lists ranked by recency / cost. Click any row (or any Home breakdown row) to drill into the Home view filtered to that session, person, or model.
  • Filters — time range, source, user, and model selects apply everywhere. All view and filter state lives in the URL query string, so any view is shareable/bookmarkable and back/forward works.

Importing transcripts

Besides live OTLP telemetry, you can backfill from JSONL transcripts:

  • POST /api/import/jsonl — body { content, source?, sessionId? } (or raw JSONL text).
  • POST /api/import/claude-hook — body { transcript_path, session_id?, cwd? }; reads a local Claude Code transcript file (restricted to ~/.claude/projects or the given cwd).

Imports are idempotent — re-sending the same file (matched by content hash) is detected and skipped. The original transcript is stored as a file and can be viewed from the session drill-down (GET /api/sessions/:id/transcript).

Storage

Data is stored in data/finius.sqlite by default. Override with FINIUS_DB_PATH=/path/to/db.sqlite. Override the API port with PORT. Imported transcript files live under <db-dir>/transcripts (override with FINIUS_BLOB_DIR).

PostgreSQL (server mode)

For a self-hosted / team server you can back finius serve with PostgreSQL instead of the local SQLite file. Choose it during finius setup and you get two paths:

  • Spin up a local Postgres in Docker — if setup detects a running Docker daemon, it offers to provision a managed container for you: a persistent finius-postgres (postgres:16-alpine) with a named volume and --restart unless-stopped, a generated password, and the resulting connection URL saved to ~/.finius/config.json. Nothing else to configure — finius serve just uses it. (The host port defaults to 55432 so it won't collide with a system Postgres on 5432.)
  • Connect to an existing Postgres — point setup at any server by URL (the only option when Docker isn't available).

Either way the URL is persisted to config; you can also bypass setup entirely with FINIUS_DATABASE_URL=postgres://user:pass@host:5432/finius. Postgres uses the pg driver, which is an optional peer dependency — install it alongside finius (npm i -g pg) since it isn't bundled. Migrations run automatically at startup; finius doctor reports Postgres reachability. Switching backends starts from an empty database (there's no cross-backend data migration). SQLite remains the zero-config default for local use.

To try Postgres against the test suite (requires Docker): npm run pg:up starts a throwaway instance, npm run test:pg runs the suite against it, and npm run pg:down tears it down.

Dashboard reads are served from a pre-aggregated hourly metric_rollup; raw metric_points keep the full-resolution data for the live view and drill-downs.

Raw batch retention

The full OTLP payload of each ingest batch is kept in raw_batches only to allow replaying history into new metric classifications. Control it with:

  • FINIUS_RAW_PAYLOADS=retain (default) | offoff keeps only the dedup hash, not the payload.

  • FINIUS_RAW_RETENTION_DAYS=7 (default) — age cutoff used by the prune endpoint below.

  • FINIUS_CRON_TOKEN=<secret> — enables POST /api/maintenance/prune-raw-batches. Without it the endpoint is disabled (returns 503). Wire a cron to it:

    curl -fsS -X POST -H "Authorization: Bearer $FINIUS_CRON_TOKEN" \
      http://127.0.0.1:8787/api/maintenance/prune-raw-batches

Other commands

npm test         # vitest run
npm run typecheck # tsc --noEmit (strict)