Python SDK

The official CLIMeter Python SDK. Supports Python 3.8+ with sync, async, context manager, and direct client usage. Zero runtime dependencies — stdlib only.

Bash
pip install climeter

configure()

Initialize the SDK before using any metering features. Call this once at startup, or rely on environment variables.

Python
from climeter import meter

meter.configure(
    api_key="clmtr_...",       # required (or set CLIMETER_API_KEY env var)
    tool_slug="my-tool",       # identifies this tool across events
    api_url="https://api.climeter.ai",  # default; override only if needed
)
ParameterTypeDefaultDescription
api_keystrCLIMETER_API_KEYYour CLIMeter API key (clmtr_...)
tool_slugstrCLIMETER_TOOL_SLUGDefault tool slug for all events
api_urlstr"https://api.climeter.ai"API base URL (rarely overridden)

Environment variables

All configuration can be set via environment — no code changes needed between environments.

.env
Bash
# Required
CLIMETER_API_KEY=clmtr_your_key_here

# Optional
CLIMETER_TOOL_SLUG=my-tool     # default tool slug
CLIMETER_API_URL=https://api.climeter.ai  # override API base URL

The SDK lazily reads these on first use — no explicit configure() call needed when using env vars.

@meter.track() decorator

The simplest way to meter a function. Works on both sync and async functions. Records an event after every call.

Python
from climeter import meter

# Sync function — event name defaults to function name
@meter.track()
def search_code(query: str, repo: str = ".") -> list[dict]:
    return run_search(query, repo)

# Async function — same decorator, works automatically
@meter.track()
async def fetch_results(query: str) -> list[dict]:
    return await async_search(query)

# Override event name and attach metadata
@meter.track(command="code-search-v2", metadata={"version": "2"})
def search_v2(query: str) -> list[dict]:
    ...
Note
Pricing is set per-tool in the CLIMeter dashboard — not in code. The SDK never accepts a price argument; the server enforces it for billing integrity.
OptionTypeDefaultDescription
commandstrfunction nameOverride event name (formerly "name")
metadatadictNoneExtra key-value pairs attached to every event

track_usage() context manager

Meter a block of code synchronously. The event is recorded when the with block exits.

Python
from climeter import meter

def process_document(file_path: str) -> dict:
    with meter.track_usage("pdf-analyzer"):
        result = run_pdf_analysis(file_path)
        return result

# With metadata
with meter.track_usage("search", metadata={"source": "cli"}):
    results = run_search(query)

Signature: track_usage(event_name, metadata=None) — pricing is set in the dashboard.

track_usage_async() — async context manager

Async version of track_usage for use in async code.

Python
from climeter import meter
import asyncio

async def handle_request(query: str) -> dict:
    async with meter.track_usage_async("search"):
        result = await async_search(query)
        return result

# With metadata
async with meter.track_usage_async(
    "batch-search",
    metadata={"batch_size": 10}
):
    results = await run_batch(queries)

meter.status()

Returns the current meter state — useful for health checks and debugging.

Python
from climeter import meter

state = meter.status()
print(state)
# {
#   "configured": True,
#   "tool_slug": "my-tool",
#   "queue_size": 3
# }
FieldTypeDescription
configuredboolTrue if the SDK has a valid API key (env or configure())
tool_slugstrThe active tool slug
queue_sizeintEvents currently buffered and waiting to flush

Buffer behavior

Events are batched in memory and sent in the background. Your code is never blocked by network calls.

BehaviorDescription
Batch flushEvents flushed every 5s or when the buffer reaches 50 events (internal defaults)
Offline bufferUp to 100 events held in memory if network fails; retried on next flush
Thread safetyAll methods are thread-safe
ShutdownCall meter.shutdown() to flush remaining events and stop the background thread
Lambda / serverless
In short-lived functions, call meter.flush() before returning to ensure all events are sent.
Python
def handler(event, context):
    result = my_tool(event["query"])
    meter.flush()   # flush before Lambda freezes the container
    return result
Python SDK — CLIMeter Docs