Skill: symbolstar/agent-token-usage (version 0.2.2)

--- name: agent-token-usage description: Summarize per-agent LLM token consumption for OpenClaw multi-agent setups by parsing `~/.openclaw/agents/*/sessions/*.trajectory.jsonl`. Ships both a CLI (Python) and an optional 📊 button injected into the Control UI header next to Search. Use when the user asks "今天哪个 agent 用了多少 token / 消耗了多少 token / token 排行 / token 统计 / how much did agent X spend today / which agent burns the most tokens / token usage breakdown / billable token estimate", or asks to install/remove the 📊 token-usage button in Control UI. Returns a ranked table with input / output / cacheRead / cacheWrite / total (and equivalent-billable token estimate). NOT for: dollar cost (use codexbar/model-usage skill), per-message inspection (use sessions_history), or non-OpenClaw runtimes. --- # agent-token-usage 📊 Accurately attribute LLM token consumption across all OpenClaw agents for a given day. ![📊 button next to Control UI search](https://raw.githubusercontent.com/SymbolStar/echoCue/main/docs/agent-token-usage/header-button.png) ![Modal with per-agent token breakdown](https://raw.githubusercontent.com/SymbolStar/echoCue/main/docs/agent-token-usage/modal.png) Ships two things in one skill: 1. **CLI** — `scripts/agent_token_usage.py`, always works, zero setup 2. **UI button** — optional `apply-ui.sh` injects a 📊 button into Control UI's header next to Search; clicking shows today's per-agent table in a modal ## Why this exists `sessions_list` returns each session's `totalTokens` field which is the **last context window size**, NOT the cumulative consumption across all LLM calls in that session. For long-running sessions, real consumption can be **100×+ larger**. This skill reads `trajectory.jsonl` (the authoritative source) and sums real `usage` objects per agent. ## Quick start (CLI) ```bash # default = today, local date python ~/.openclaw/workspace/skills/agent-token-usage/scripts/agent_token_usage.py # specific date python …/agent_token_usage.py --date 2026-05-20 # equivalent billable (cacheRead × 0.1 + cacheWrite × 1.25 + input + output) python …/agent_token_usage.py --date 2026-05-20 --billable # JSON python …/agent_token_usage.py --format json ``` ## Optional: 📊 button in Control UI ```bash bash ~/.openclaw/workspace/skills/agent-token-usage/apply-ui.sh ``` Then refresh the Control UI tab. The button appears next to Search; clicking shows the modal. Uninstall: ```bash bash ~/.openclaw/workspace/skills/agent-token-usage/remove-ui.sh ``` Per-browser toggle: ```js localStorage.setItem('milly.tokenUsageBtn', 'off') localStorage.removeItem('milly.tokenUsageBtn') ``` ### How the UI part works ``` launchd (5min) → refresh-data.sh → <ui>/data/agent-token-usage.json │ same-origin fetch ▼ Control UI bundle (patched IIFE) 📊 button → modal table ``` CSP-friendly (`connect-src 'self'`) because data is served from the UI's own origin. No extra daemon, no extra port. After `openclaw update` overwrites `dist/control-ui/*`, just re-run `apply-ui.sh` — idempotent. ## Column semantics | Field | Meaning | Billing weight | |---|---|---| | `input` | new, non-cached prompt tokens | 1.0× | | `output` | model-generated tokens | 1.0× (typically 5× input price) | | `cacheRead` | prompt tokens served from prompt cache | ~0.1× | | `cacheWrite` | prompt tokens written to cache | ~1.25× | | `total` | sum of all four (real LLM throughput) | — | | `~bill` | weighted billable-equivalent tokens | — | Use `total` to see "who's burning the most LLM compute"; use `~bill` to see "who's actually most expensive". High-cacheRead agents look huge but are cheap; high-input agents look small but cost more. ## How it works 1. Walk `~/.openclaw/agents/<agent>/sessions/*.trajectory.jsonl` 2. For each line, check `ts` startswith target date 3. DFS-search the `data` field for a `usage` dict with token counters 4. Sum per agent; also track session count and models used ## Caveats - Only counts LLM calls (events with a `usage` object) — non-LLM tool calls excluded by design - Cache multipliers are Anthropic ballpark numbers; adjust for other providers mentally - Does NOT compute USD cost — use the `model-usage` skill for $ amounts - `--date` matches ISO timestamps in trajectory (UTC); late-night events can shift by a day for non-UTC users - UI auto-refresh job (launchd) is macOS only; on Linux, run `scripts/refresh-data.sh` via cron/systemd timer ## Files | File | Purpose | |---|---| | `scripts/agent_token_usage.py` | CLI aggregator | | `scripts/refresh-data.sh` | Writes JSON into every patched Control UI dist | | `scripts/token-usage-button.iife.js` | UI patch payload (button + modal + same-origin fetch) | | `apply-ui.sh` | Inject IIFE, cache-bust, install launchd refresh job | | `remove-ui.sh` | Restore bundle, remove launchd job, delete data dir |

path: scripts/refresh-data.sh
content: #!/usr/bin/env bash
# Regenerate agent-token-usage.json for every patched Control UI dist.
set -euo pipefail

AGG="$HOME/.openclaw/workspace/skills/agent-token-usage/scripts/agent_token_usage.py"
[[ -f "$AGG" ]] || { echo "✗ aggregator missing: $AGG" >&2; exit 2; }

ROOTS=()
[[ -n "${OPENCLAW_HOME:-}" && -d "$OPENCLAW_HOME" ]] && ROOTS+=("$OPENCLAW_HOME")
if command -v npm >/dev/null 2>&1; then
  R="$(npm root -g 2>/dev/null || true)"; [[ -n "$R" && -d "$R/openclaw" ]] && ROOTS+=("$R/openclaw")
fi
for NVM_BASE in "$HOME/.nvm/versions/node" "/usr/local/n/versions/node"; do
  [[ -d "$NVM_BASE" ]] || continue
  while IFS= read -r d; do [[ -n "$d" ]] && ROOTS+=("$d"); done \
    < <(find "$NVM_BASE" -maxdepth 4 -path "*/lib/node_modules/openclaw" -type d 2>/dev/null)
done

DATA="$(python3 "$AGG" --format json 2>/dev/null || echo '{}')"
for ROOT in "${ROOTS[@]:-}"; do
  for REL in "dist/control-ui" "ui/dist"; do
    BASE="$ROOT/$REL"
    [[ -d "$BASE/assets" ]] || continue
    mkdir -p "$BASE/data"
    printf '%s' "$DATA" > "$BASE/data/agent-token-usage.json.tmp"
    mv "$BASE/data/agent-token-usage.json.tmp" "$BASE/data/agent-token-usage.json"
  done
done


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (MEDIUM)