Skip to main content

Track, budget, and understand the cost of your AI API calls

Project description

tokenmeter

Track, budget, and understand the cost of your AI API calls.

Installation

# Core (zero dependencies)
uv pip install smalldreamcollective-tokenmeter

# With CLI
uv pip install "smalldreamcollective-tokenmeter[cli]"        # adds click

# With accurate token counting
uv pip install "smalldreamcollective-tokenmeter[openai]"     # adds tiktoken
uv pip install "smalldreamcollective-tokenmeter[anthropic]"  # adds anthropic SDK
uv pip install "smalldreamcollective-tokenmeter[all]"        # CLI + both providers

# With interactive terminal dashboard
uv pip install "smalldreamcollective-tokenmeter[tui]"        # adds textual + plotext

Quick Start

import tokenmeter

meter = tokenmeter.Meter()

# Estimate cost before calling an API
cost = meter.estimate("Explain quantum computing", model="claude-sonnet-4-5")
print(f"Estimated input cost: ${cost}")

# Record actual usage from an API response
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)
record = meter.record(response)
print(f"This call cost: ${record.total_cost}")

# Query spending
print(f"Session total: ${meter.total()}")
print(meter.summary(group_by="model"))

Works the same way with OpenAI:

import openai
client = openai.OpenAI()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)
record = meter.record(response)

Budgets & Alerts

meter = tokenmeter.Meter(storage="sqlite")

# Set spending limits
meter.set_budget(limit=10.00, period="daily", action="block")
meter.set_budget(limit=100.00, period="monthly", action="warn")

# Get notified at thresholds
meter.alerts.set_thresholds([0.5, 0.8, 0.95])
meter.on_alert(lambda status, msg: print(f"ALERT: {msg}"))

# Check before making expensive calls
estimated = meter.estimate(long_prompt, model="claude-opus-4-6")
if meter.budget.would_exceed(estimated):
    print("Would exceed budget — switching to cheaper model")

# Enforce hard limits (raises BudgetExceededError)
meter.budget.enforce(estimated)

Budget periods: "daily", "weekly", "monthly", "total"

Budget actions: "warn" (log to stderr) or "block" (raise BudgetExceededError)

Storage Backends

# In-memory (default) — fast, lost on exit
meter = tokenmeter.Meter(storage="memory")

# SQLite — persistent, queryable
meter = tokenmeter.Meter(storage="sqlite", db_path="~/.tokenmeter/usage.db")

# JSON Lines — simple file, easy to inspect
meter = tokenmeter.Meter(storage="jsonl", path="./usage.jsonl")

Filtering & Tags

# Tag your API calls
meter.record(response, feature="chatbot", env="production", user_id="alice")

# Filter spending
meter.total(provider="anthropic")
meter.total(model="claude-sonnet-4-5")
meter.total(user_id="alice")
meter.total(tags={"feature": "chatbot"})

# Aggregate
meter.summary(group_by="model")
meter.summary(group_by="provider")
meter.summary(group_by="user_id")

Adding Custom Providers

from tokenmeter.providers._base import Provider
from tokenmeter import Meter, ModelPricing
from decimal import Decimal

class GeminiProvider(Provider):
    @property
    def name(self):
        return "google"

    def count_tokens_local(self, text, model):
        return len(text) // 4  # heuristic

    def extract_usage(self, response):
        return {
            "input_tokens": response.usage_metadata.prompt_token_count,
            "output_tokens": response.usage_metadata.candidates_token_count,
        }

    def extract_model(self, response):
        return response.model_version

    def matches_response(self, response):
        return "google" in type(response).__module__

meter = Meter()
meter._provider_registry.register(GeminiProvider())
meter._pricing.register(ModelPricing(
    model_id="gemini-2.0-flash",
    provider="google",
    input_per_mtok=Decimal("0.10"),
    output_per_mtok=Decimal("0.40"),
))

Standalone Cost Calculation

You can use the cost calculator directly without tracking:

from tokenmeter import CostCalculator

calc = CostCalculator()
cost = calc.calculate(model="gpt-4o", input_tokens=1500, output_tokens=500)
print(f"Cost: ${cost}")

# Itemized breakdown
details = calc.calculate_detailed(model="claude-opus-4-6", input_tokens=10000, output_tokens=5000)
print(f"Input: ${details['input_cost']}, Output: ${details['output_cost']}")

API Reference

Meter (main entry point)

Method Description
Meter(storage, session_id, user_id) Create a meter. Storage: "memory", "sqlite", "jsonl"
.estimate(text, model) Estimate input cost for text
.record(response, user_id, **tags) Record actual usage from API response
.total(**filters) Get total spending (filterable)
.summary(group_by) Aggregate by "model", "provider", "user_id", "session_id"
.set_budget(limit, period, action) Set a spending limit
.check_budget() Check all budget statuses
.on_alert(callback) Register alert callback (BudgetStatus, str) -> None

Sub-components (accessible via meter.*)

Component Description
meter.cost CostCalculator — stateless cost math
meter.tokens TokenCounter — local + API-based token counting
meter.tracker UsageTracker — record/query/aggregate usage
meter.budget BudgetManager — limits & enforcement
meter.alerts AlertManager — thresholds & callbacks

Supported Models

Anthropic: Claude Opus 4.6, 4.5, 4.1, 4 | Sonnet 4.5, 4 | Haiku 4.5, 3.5, 3

OpenAI: GPT-5.1, 5, 5-mini, 5-nano | GPT-4.1, 4.1-mini, 4.1-nano | GPT-4o, 4o-mini | o3, o3-mini, o4-mini, o1

CLI

Install with uv pip install "smalldreamcollective-tokenmeter[cli]" to get the tokenmeter command.

# Send a prompt and track the cost
tokenmeter prompt "Explain quantum computing" --model claude-sonnet-4-5
echo "Long prompt..." | tokenmeter prompt --model gpt-4o --system "Be concise"

# Estimate cost without sending
tokenmeter estimate "Your prompt text here" --model claude-opus-4-6

# View spending
tokenmeter usage                         # total spending
tokenmeter usage --by model              # grouped by model
tokenmeter usage --by provider           # grouped by provider

# View individual records
tokenmeter history                       # last 20 records
tokenmeter history --limit 50 --provider anthropic

# Manage budgets
tokenmeter budget set 10.00 --period daily --action block
tokenmeter budget set 100.00 --period monthly
tokenmeter budget list                   # show all budgets with status
tokenmeter budget remove 0              # remove by index

# List supported models with pricing
tokenmeter models
tokenmeter models --provider anthropic

# Clear usage data
tokenmeter clear

API keys

Copy the example env file and fill in your keys:

cp .env.example .env
# then edit .env with your keys

Load the keys before running CLI commands:

# Option A — source once per shell session
source .env && tokenmeter prompt "Hello" --model claude-3-5-haiku-20241022

# Option B — pass the file to uv run (no sourcing needed)
uv run --env-file .env tokenmeter prompt "Hello" --model claude-3-5-haiku-20241022

.env is gitignored and will never be committed.

Run tokenmeter --help for full command reference, or tokenmeter.help() in a Python REPL.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smalldreamcollective_tokenmeter-0.1.1.tar.gz (43.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file smalldreamcollective_tokenmeter-0.1.1.tar.gz.

File metadata

  • Download URL: smalldreamcollective_tokenmeter-0.1.1.tar.gz
  • Upload date:
  • Size: 43.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for smalldreamcollective_tokenmeter-0.1.1.tar.gz
Algorithm Hash digest
SHA256 aa498ca39585837c268e5fea6466a3afcb9192a2196f32455a6a7fba023b1d00
MD5 1635d302327ac8bfab02b7a8a0302f57
BLAKE2b-256 fc628a8f8f6a5179d23986df83b1fe283147b770d04add7c8b0b50611d79f997

See more details on using hashes here.

File details

Details for the file smalldreamcollective_tokenmeter-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: smalldreamcollective_tokenmeter-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 48.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.22 {"installer":{"name":"uv","version":"0.9.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for smalldreamcollective_tokenmeter-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c2c0e34b1f1de1dbdca15dfed26efac1e012e603456a1db714dd1cd68ec4225f
MD5 5e72c75b33a3b7cf180f7dc892737a99
BLAKE2b-256 b16a41db0226fa3b398d4338cd607f7d712021746d5acaf5ef24af397e75767e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page