--- summary: "Usage tracking surfaces and credential requirements" read_when: - You are wiring provider usage/quota surfaces - You need to explain usage tracking behavior or auth requirements title: "Usage tracking" --- ## What it is - Pulls provider usage/quota directly from their usage endpoints. - No estimated costs; only provider-reported quota windows or account-state summaries. - Human-readable quota-window status output is normalized to `X% left`, even when an upstream API reports consumed quota, remaining quota, or only raw counts. Providers without resettable quota windows can show provider summary text instead, such as a balance. - Session-level `/status` and `session_status` can fall back to the latest transcript usage entry when the live session snapshot is sparse. That fallback fills missing token/cache counters, can recover the active runtime model label, and prefers the larger prompt-oriented total when session metadata is missing or smaller. Existing nonzero live values still win. ## Where it shows up - `/status` in chats: emoji-rich status card with session tokens + estimated cost (API key only). Provider usage shows for the **current model provider** when available as a normalized `X% left` window or provider summary text. - `/usage off|tokens|full` in chats: per-response usage footer (OAuth shows tokens only). - `/usage cost` in chats: local cost summary aggregated from OpenClaw session logs. - CLI: `openclaw status --usage` prints a full per-provider breakdown. - CLI: `openclaw channels list` prints the same usage snapshot alongside provider config (use `--no-usage` to skip). - macOS menu bar: "Usage" section under Context (only if available). ## Custom `/usage full` footer `/usage full` shows a built-in compact footer with model, reasoning, fast/slow, context window, turn tokens, cache, and cost when those fields are available. No template file is required. `messages.usageTemplate` is only for advanced custom layouts. The value is a JSON file path (supports `~`) or an inline object, and it replaces the built-in footer when valid: ```json { "messages": { "usageTemplate": "~/.openclaw/usage-footer.json" } } ``` Missing or empty templates fall back to the built-in footer quietly. Unreadable or invalid configured templates also fall back to the built-in footer and emit an operator warning. Start custom templates from the built-in shape, then edit the parts you want to change: ```jsonc { "schema": "openclaw.usageBar.v1", "scales": { "braille": "⠐⡀⡄⡆⡇⣇⣧⣷⣿", "block": "░▏▎▍▌▋▊▉█", "shade": "░▒▓█", "moon": "🌑🌘🌗🌖🌕", "level": "▁▂▃▄▅▆▇█", "weather": ["🥶", "☁️", "🌥", "⛅️", "🌤", "☀️"], "plants": ["🪾", "🍂", "🌱", "☘️", "🍀", "🌿"], "moons6": ["🌑", "🌚", "🌘", "🌗", "🌖", "🌝"], }, "aliases": { "models": { "claude-opus-4-6": "opus46", "claude-opus-4-8": "opus48", "claude-sonnet-4-6": "sonnet46", "claude-haiku-4-5": "haiku45", "gpt-5.5": "gpt5.5", }, "reasoning": { "off": "🌑", "minimal": "🌚", "low": "🌘", "medium": "🌗", "high": "🌕", "xhigh": "🌝", }, }, "output": { "sep": "", "default": [ { "text": "{model.provider}{identity.emoji|🤖} {model.display_name|alias:models}" }, { "map": "model.is_fallback", "cases": { "true": " 🔄" } }, { "map": "model.is_override", "cases": { "true": " 📌" } }, { "when": "model.reasoning", "text": " {model.reasoning|alias:reasoning}" }, { "map": "state.fast_mode", "cases": { "true": " ⚡", "false": " 🐌" } }, { "when": "context.max_tokens", "text": " | 📚 [{context.pct_used|meter:5:braille}]{context.max_tokens|num}", }, { "when": "usage.has_split_tokens", "text": " ↕️ {usage.input_tokens|num|?}/{usage.output_tokens|num|?}", }, { "when": "usage.has_total_only_tokens", "text": " ↕️ {usage.total_tokens|num}" }, { "when": "usage.cache_hit_pct", "text": " 🗄 {usage.cache_hit_pct|pct}" }, { "when": "cost.turn_usd", "text": " 💰{cost.turn_usd|fixed:4}" }, ], "surfaces": { "discord": [ { "text": "-# -\n" }, { "text": "-# {model.provider}{identity.emoji|🤖} {model.display_name|alias:models}" }, { "map": "model.is_fallback", "cases": { "true": "🔄" } }, { "map": "model.is_override", "cases": { "true": "📌" } }, { "when": "model.reasoning", "text": " {model.reasoning|alias:reasoning}" }, { "map": "state.fast_mode", "cases": { "true": " ⚡️", "false": " 🐌" } }, { "when": "context.max_tokens", "text": " | 📚 [{context.pct_used|meter:5:braille}]{context.max_tokens|num}", }, { "when": "usage.has_split_tokens", "text": " ↕️ {usage.input_tokens|num|?}/{usage.output_tokens|num|?}", }, { "when": "usage.has_total_only_tokens", "text": " ↕️ {usage.total_tokens|num}" }, { "when": "usage.cache_hit_pct", "text": " 🗄 {usage.cache_hit_pct|pct}" }, { "when": "cost.turn_usd", "text": " 💰{cost.turn_usd|fixed:4}" }, ], }, }, } ``` ### Shape ```jsonc { "schema": "openclaw.usageBar.v1", "scales": { "": "low-to-high glyphs" }, // string (1 glyph/char) or array "aliases": { "": { "": "