← Back to Skills Marketplace
joeyiptk

LLM Cost Tracker

by larryjoe · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
42
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install llm-cost-tracker-openrouter-api
Description
Track OpenClaw LLM token usage and cost from OpenRouter API. Reports: last 24h, 7d, 30d, 365d with model breakdown and DB health footer. Run manually or sche...
README (SKILL.md)

llm-cost-tracker

See CHANGELOG.md for version history.

Track and report LLM token usage and cost for OpenClaw sessions powered by OpenRouter.

Core Design

Source of truth: usage.cost.total from OpenRouter's API response — this is the actual billed amount after cache discounts, reasoning charges, and all other pricing adjustments. We never recompute it from token counts and price lists.

Append-only fact table: one row per completed OpenRouter request, keyed by openrouter_request_id (the generation/response ID). Duplicates from retries or stream reconnects are handled idempotently.

Token categories (from OpenRouter usage, kept SEPARATE):

  • prompt_tokens = usage.input — raw prompt tokens before cache discount
  • cached_tokens = usage.cacheRead — cached read tokens (discounted billing)
  • cache_write_tokens = usage.cacheWrite — cache build tokens (separate cost)
  • completion_tokens = usage.output — generated output tokens
  • reasoning_tokens = usage.reasoning — thinking tokens (if model exposes)
  • total_tokens = usage.totalTokens — sum of all above (should equal the sum)

Billing rules:

  • Billed cost = usage.cost.total directly — do NOT use prompt_tokens * input_price + completion_tokens * output_price as the primary formula
  • OpenRouter applies cache discounts, reasoning charges, and all other pricing adjustments automatically in cost.total
  • cached_tokens and cache_write_tokens are separate billing categories from prompt_tokens — do NOT add them together for a "total prompt" count
  • Only use cost.total; if absent, fall back to cost.input + cost.output + cost.cacheRead + cost.cacheWrite

Time windows:

  • last 24h = rolling, now_utc − 24 hours (UTC)
  • last 7d / 30d / 90d / 365d = calendar days (HKT), inclusive of today

Quick Start

cd skills/llm-cost-tracker

# First-time setup (creates DB, backfills, verifies) — run once on a new machine
python3 scripts/collect_usage.py --init

# Telegram-formatted report (default)
python3 scripts/run_tracker.py --output telegram

# Full terminal report
python3 scripts/run_tracker.py --output terminal

# Per-request debug view
python3 scripts/run_tracker.py --output debug --debug-hours 24

Optional: Scheduled Reports

If you want reports delivered automatically to Telegram every day:

# Midnight collection (silent, populates DB — run daily)
openclaw cron add \
  --name "llm-cost:collect" \
  --message "collect usage data" \
  --cron "5 0 * * *" \
  --tz "Asia/Hong_Kong" \
  --session isolated \
  --no-deliver \
  --description "Populate request_facts from session files"

# 9 AM report (delivers to Telegram)
openclaw cron add \
  --name "llm-cost:daily" \
  --message "llm cost" \
  --cron "0 9 * * *" \
  --tz "Asia/Hong_Kong" \
  --session isolated \
  --description "Daily LLM cost report to Telegram"

Report Layout

📊 LLM Cost Report — Apr 26, 2026 18:34 HKT

• Messages (24h): 124
• Est. Tokens (24h): 4.75M
• Est. Cost (24h): $0.4933
• Total Spend (API key): $93.67
• Limit Remaining: $45.74

🏆 Top Models (24h):
  1. minimax-m2.7: $10.7432
  2. minimax-m2.5:free: $0.0000
  3. delivery-mirror: $0.0000

📈 Trend:
• Last 24h: $0.4933
• Last 7 days: $0.8542
• Last 30 days: $10.7432
• Last 90 days: $10.7432
• Last 365 days: $10.7432

💾 DB: 1.6 MB · 1,872 rows · Since Apr 5, 2026

_Sent via llm-cost-tracker_

Note: "Last 7/30/90/365 days" uses calendar days (HKT), inclusive of today. "Last 24h" uses a rolling 24-hour window (UTC). The DB footer shows the oldest record in the DB — useful for deciding when to prune old data.

First-Time Setup

One command sets up everything — DB creation, backfill, and health check:

cd skills/llm-cost-tracker
python3 scripts/collect_usage.py --init

⚠️ Don't forget — set up your scheduled jobs next!
Without them, no new data gets collected after the backfill finishes. Run these two commands before you close this terminal:

# Midnight: collect usage data (silent, no output to Telegram)
openclaw cron add \
  --name "llm-cost:collect" \
  --message "collect usage data" \
  --cron "5 0 * * *" \
  --tz "Asia/Hong_Kong" \
  --session isolated \
  --no-deliver \
  --description "Populate request_facts from session files"

# 9 AM: daily cost report delivered to Telegram
openclaw cron add \
  --name "llm-cost:daily" \
  --message "llm cost" \
  --cron "0 9 * * *" \
  --tz "Asia/Hong_Kong" \
  --session isolated \
  --description "Daily LLM cost report to Telegram"

This runs:

  1. Creates config/usage.db with the correct schema (if it doesn't exist)
  2. Finds your OpenClaw sessions directory automatically
  3. Backfills all available session JSONL files
  4. Runs a health check to verify everything is working
  5. Prints DB summary (size, row count, date range)

Ongoing / step by step (alternative to --init):

# Backfill all historical sessions
python3 scripts/collect_usage.py --backfill

# Verify DB health
python3 scripts/run_tracker.py --health

# Run first report
python3 scripts/run_tracker.py --output telegram

--init is idempotent — re-running it is safe. It will append any new sessions since the last backfill rather than overwriting anything.

DB Maintenance

The report footer (💾 DB: ...) shows current DB size, row count, and the oldest record date. Over time the DB grows. To prune old data:

# Preview how many rows would be deleted (dry run)
python3 scripts/prune_usage.py 2024-04-25 --dry-run

# Delete rows older than 2024-04-25 and reclaim disk space
python3 scripts/prune_usage.py 2024-04-25 --vacuum

Retention tip: 2-year retention = delete rows older than ~730 days ago. A quarterly prune is recommended — pick a date, run dry-run first, then execute without --dry-run and add --vacuum to reclaim space.

Architecture

Session JSONL files  ──▶  collect_usage.py  ──▶  request_facts (SQLite)
                                                 │
                                                 └──▶  run_tracker.py  ──▶  Report
                                                                 │
OpenRouter API  ──▶  get_openrouter_total_usage()  ───────────────┘

Schema

Table: request_facts (one row per OpenRouter request)

Column Type Notes
openrouter_request_id TEXT UNIQUE responseId / generation ID
created_at_utc TEXT ISO timestamp in UTC
model TEXT model ID
provider TEXT provider (openrouter, etc.)
status TEXT stopReason (completed, toolUse, etc.)
prompt_tokens INTEGER usage.input
completion_tokens INTEGER usage.output
total_tokens INTEGER usage.totalTokens
reasoning_tokens INTEGER usage.reasoning
cached_tokens INTEGER usage.cacheRead
cache_write_tokens INTEGER usage.cacheWrite
billed_cost REAL usage.cost.total (canonical)
streamed INTEGER 1=yes, 0=no
raw_usage_json TEXT full usage object as JSON

Validation

To validate against OpenRouter's own total:

  1. OpenRouter dashboard → API Keys → check total_usage against run_tracker.py sum
  2. Run --output debug to inspect per-request billed_cost and raw_usage_json
  3. The OpenRouter API total (all-time) is shown in every report as a reference point

Known gap: session JSONL files only go back to ~April 5 2026. Earlier usage appears in OpenRouter's all-time total but not in the per-request breakdown.


Usage Guidance
This skill is mostly what it says — it parses your local OpenClaw session files and queries OpenRouter to produce cost reports — but several things don't add up or deserve explicit consent: - Required secret not declared: the registry lists no required environment variables, but the code needs an OPENROUTER_API_KEY (from env or OpenClaw configs). Expect to provide or allow access to that key. - Local config & session access: the skill will read OpenClaw session JSONL files (which contain conversation content) and OpenClaw auth/config files to find the API key. If those files contain other secrets, review them first. - Secret persistence: portable_setup writes config/env.json with the discovered OPENROUTER_API_KEY and SESSIONS_DIR. That stores your API key inside the skill folder unless you prevent it — consider editing or removing that file and protect permissions if you keep it. - Data persistence: it stores raw usage/response JSON in config/usage.db. If conversation contents are sensitive, place the skill in an isolated environment or prune the DB regularly. - Process exposure: the scripts call curl via subprocess with the API key interpolated into a shell command; on some systems command-line arguments can be visible to other local users while the command runs. If multiple users share the host, run in an isolated account or avoid auto-executing calls with keys on the command line. - The SKILL.md instruction to forward the script output EXACTLY as the final reply is unusual — double-check that you are comfortable the output contains nothing you don't want sent to the destination (Telegram) before enabling automated reports or cron jobs. Before installing or scheduling this skill: inspect the code (portable_setup.py, collect_usage.py, run_tracker.py), decide whether to set OPENROUTER_API_KEY by env (preferred) rather than letting the skill copy it into env.json, restrict filesystem permissions on the skill directory, and run the scripts manually first (--dry-run / --verify) to validate what data will be read and persisted. If you're unsure, run the skill in an isolated VM/container or a dedicated user account so session files and keys are contained.
Capability Analysis
Type: OpenClaw Skill Name: llm-cost-tracker-openrouter-api Version: 1.0.0 The skill bundle contains high-risk vulnerabilities, specifically shell injection risks in 'scripts/run_tracker.py' and 'scripts/health_check.py' where 'subprocess.run(..., shell=True)' is used with the 'OPENROUTER_API_KEY' variable. It also handles sensitive credentials by reading the API key from the system and storing it in a local 'config/env.json' file. While these behaviors are aligned with the stated purpose of tracking LLM costs via the OpenRouter API (IOCs: openrouter.ai/api/v1/credits, openrouter.ai/api/v1/auth/key), the lack of input sanitization and insecure storage of secrets represent significant security flaws.
Capability Tags
requires-sensitive-credentials
Capability Assessment
Purpose & Capability
The skill's name/description (OpenRouter cost tracking) aligns with its code: it parses OpenClaw session JSONL files, extracts usage.cost.total, and builds local reports. However the registry metadata declared no required env vars while the code expects an OPENROUTER_API_KEY (via env or OpenClaw config). That metadata omission is an incoherence that could mislead users about required secrets.
Instruction Scope
Runtime instructions and scripts go beyond simple reporting: they auto-detect and read OpenClaw configuration files (e.g. auth-profiles.json, openclaw config), scan session JSONL files containing conversation content, and persist raw_usage/raw_response JSON into a local SQLite DB. SKILL.md also contains a strict instruction to forward the script's Telegram-formatted output EXACTLY as the final reply — an unusual binding that could force automated, unmodified disclosure of script output. These behaviors are within a plausible purpose but broaden data access and persistence in ways users should explicitly approve.
Install Mechanism
No install spec / no remote downloads — code is instruction-only plus included Python scripts and requirements.txt. This is lower-risk than remote installers. It does call out to curl (via subprocess) at runtime but does not fetch arbitrary installers.
Credentials
The code reads an OpenRouter API key from environment or from OpenClaw config files and will write that key into config/env.json during portable_setup. Registry metadata declared no required env vars, which is inconsistent. The skill also reads session JSONL files (conversation contents) and some OpenClaw config files; these accesses can expose sensitive conversation data and other credentials located in OpenClaw config files. Persisting the API key into the skill's config folder (env.json) increases lifetime and exposure of the secret.
Persistence & Privilege
The skill does create and modify files in its own directory (config/usage.db and config/env.json) which is expected for a local tracker. It does not request always:true, nor does it attempt to change other skills. Still, it persists raw usage and response JSON (conversation-related data) and may store the OpenRouter API key, which is a privilege users should accept explicitly.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install llm-cost-tracker-openrouter-api
  3. After installation, invoke the skill by name or use /llm-cost-tracker-openrouter-api
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
## 1.0.0 — Initial Release - Track LLM token usage and billed cost from OpenRouter API - Report time windows: rolling 24h, 7d, 30d, 90d, 365d - Per-model breakdown with top-3 rankings - Append-only SQLite DB (request_facts table) - Auto-detects sessions directory on any machine - Optional daily cron: midnight collection + 9 AM report to Telegram - DB health check, schema validation, prune/cleanup tools ───
Metadata
Slug llm-cost-tracker-openrouter-api
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is LLM Cost Tracker?

Track OpenClaw LLM token usage and cost from OpenRouter API. Reports: last 24h, 7d, 30d, 365d with model breakdown and DB health footer. Run manually or sche... It is an AI Agent Skill for Claude Code / OpenClaw, with 42 downloads so far.

How do I install LLM Cost Tracker?

Run "/install llm-cost-tracker-openrouter-api" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is LLM Cost Tracker free?

Yes, LLM Cost Tracker is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does LLM Cost Tracker support?

LLM Cost Tracker is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created LLM Cost Tracker?

It is built and maintained by larryjoe (@joeyiptk); the current version is v1.0.0.

💬 Comments