← 返回 Skills 市场
joeyiptk

LLM Cost Tracker

作者 larryjoe · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ⚠ suspicious
42
总下载
0
收藏
0
当前安装
1
版本数
在 OpenClaw 中安装
/install llm-cost-tracker-openrouter-api
功能描述
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...
使用说明 (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.


安全使用建议
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.
功能分析
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.
能力标签
requires-sensitive-credentials
能力评估
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.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install llm-cost-tracker-openrouter-api
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /llm-cost-tracker-openrouter-api 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
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 ───
元数据
Slug llm-cost-tracker-openrouter-api
版本 1.0.0
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 1
常见问题

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... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 42 次。

如何安装 LLM Cost Tracker?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install llm-cost-tracker-openrouter-api」即可一键安装,无需额外配置。

LLM Cost Tracker 是免费的吗?

是的,LLM Cost Tracker 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

LLM Cost Tracker 支持哪些平台?

LLM Cost Tracker 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 LLM Cost Tracker?

由 larryjoe(@joeyiptk)开发并维护,当前版本 v1.0.0。

💬 留言讨论