paddington
A fast status line and cost tracker for Claude Code and Pi, written in Rust.
Reads JSON status input from stdin and outputs a compact, color-coded multi-line status bar showing:
- Line 1 — Project path, git repo/branch, worktree, PR status, session name
- Line 2 — Model name, context window usage
- Line 3 — Session cost (with monthly total and optional budget tracking), duration, lines changed
Session cost data is persisted to a local SQLite database, enabling monthly analytics with breakdowns by day, model, and project.
Install
Usage
With Claude Code
Configure as your Claude Code status line command in ~/.claude/settings.json:
With Pi
Paddington integrates natively into pi as a footer extension, replacing pi's default footer with paddington's status bar.
-
Ensure paddington is installed via cargo or available in your
$PATH. -
Copy the extension to your global pi extensions directory:
The extension collects session data from pi's APIs (model, tokens, cost, cache stats, context usage, git info) and pipes it to the paddington binary. It updates on model changes, turn completions, thinking level changes, and session events.
Pi-specific features:
- Provider name and reasoning/thinking level
- Cache token stats (read, write, hit rate)
- Session duration computed from message timestamps
- Lines added/removed parsed from edit tool patches
- Git branch from pi's footer data (no extra shell calls)
If you are developing paddington, opening pi in this repository will automatically use the local debug/release build.
Custom Templates
Paddington's output is fully customizable via a MiniJinja template in $XDG_CONFIG_HOME/paddington/config.toml (defaults to ~/.config/paddington/config.toml):
[]
= """
{{ blue }}{{ path_raw }}{{ reset }} {{ yellow }}{{ branch_raw }}{{ reset }} {{ git_dirty }}
{{ model }} {{ gray }}[${{ cost_raw }}]{{ reset }}"""
Every variable has two forms:
- Auto-colored (
{{ model }}) — wraps the value in its default ANSI color - Raw (
{{ model_raw }}) — plain text, use with explicit color tags for custom coloring
Available Variables
| Variable | Description | Default Color |
|---|---|---|
path |
cwd relative to project root | blue |
repo_owner, repo_name |
GitHub owner/repo | yellow |
branch |
git branch or short SHA | yellow |
worktree |
worktree name | blue |
pr_number, pr_state |
PR number and review symbol (✓/✗/~) | magenta |
session_name |
session name | magenta |
model |
model display name | green |
model_id |
raw model identifier | gray |
context_used, context_total, context_pct |
context window (in k / %) | gray |
cost, monthly_cost |
session / monthly cost (USD, 2 decimal) | yellow |
duration |
session duration | gray |
lines_added, lines_removed |
lines changed | green / red |
project_name |
project directory basename | blue |
session_id |
session identifier | gray |
hostname, username |
machine / OS user | gray |
datetime |
current time (HH:MM) | gray |
paddington_version |
version string | gray |
git_dirty |
"dirty" if uncommitted changes | yellow |
budget_limit |
configured monthly budget limit | gray |
budget_remaining |
dollars remaining in budget (floors at 0) | green/yellow/red |
budget_pct |
percentage of budget used (uncapped) | green/yellow/red |
Pi-Specific Variables
These are populated when running under pi (via the extension or when agent is set to "pi"):
| Variable | Description | Default Color |
|---|---|---|
provider |
model provider (e.g. anthropic, openai) |
gray |
reasoning_level |
thinking level (e.g. off, high, max) |
magenta |
agent |
calling agent (pi or claude-code) |
gray |
is_pi |
boolean, true when agent is pi |
— |
cache_read |
cache read tokens (e.g. 145k) |
gray |
cache_write |
cache write tokens (e.g. 23k) |
gray |
cache_hit_rate |
cache hit rate percentage | gray |
tokens_input |
cumulative input tokens (e.g. 230k) |
gray |
tokens_output |
cumulative output tokens (e.g. 26k) |
gray |
Color tags: {{ blue }}, {{ yellow }}, {{ green }}, {{ red }}, {{ magenta }}, {{ gray }}, {{ reset }}
Example: Pi-Optimized Template
[]
= """{{ blue }}{{ path_raw }}{{ reset }}\
{% if repo_owner_raw and repo_name_raw %} {{ yellow }}{{ repo_owner_raw }}/{{ repo_name_raw }}\
{% if branch_raw %}:{{ branch_raw }}{% endif %}{{ reset }}{% elif branch_raw %} {{ yellow }}{{ branch_raw }}{{ reset }}{% endif %}\
{% if session_name_raw %} {{ gray }}|{{ reset }} {{ magenta }}{{ session_name_raw }}{{ reset }}{% endif %}
{{ green }}{{ model_raw }}{{ reset }}\
{% if provider_raw %} {{ gray }}({{ provider_raw }}){{ reset }}{% endif %}\
{% if reasoning_level_raw %} {{ magenta }}[{{ reasoning_level_raw }}]{{ reset }}{% endif %}\
{% if context_total_raw and context_pct_raw %} {{ gray }}[{{ context_used_raw }}k/{{ context_total_raw }}k ({{ context_pct_raw }}% used)]{{ reset }}{% endif %}
{% if cost_raw %}{{ yellow }}${{ cost_raw }}{{ reset }}{% if budget_limit_raw %} {{ gray }}(${{ monthly_cost_raw }}/${{ budget_limit_raw }}){{ reset }}{% elif monthly_cost_raw %} {{ gray }}(${{ monthly_cost_raw }}/mo){{ reset }}{% endif %}{% endif %}\
{% if duration_raw %}{% if cost_raw %} {{ gray }}·{{ reset }}{% endif %} {{ gray }}{{ duration_raw }}{{ reset }}{% endif %}\
{% if tokens_input_raw %} {{ gray }}· ↑{{ tokens_input_raw }} ↓{{ tokens_output_raw }}{{ reset }}{% endif %}\
{% if cache_read_raw %} {{ gray }}R{{ cache_read_raw }} W{{ cache_write_raw }} CH{{ cache_hit_rate_raw }}%{{ reset }}{% endif %}\
{% if lines_added_raw or lines_removed_raw %}{% if cost_raw or duration_raw %} {{ gray }}·{{ reset }}{% endif %} {{ green }}+{{ lines_added_raw }}{{ reset }}{{ gray }}/{{ reset }}{{ red }}-{{ lines_removed_raw }}{{ reset }} {{ gray }}lines{{ reset }}{% endif %}"""
Budget Tracking
Set a monthly spending limit in your config file to see budget status in the status line and stats output:
[]
= 500.00
The status line shows spend vs. limit: ($42.00/$500.00). Colors shift from green to yellow (80% used) to red (95% used).
Validate & Preview
Validates your config file and renders a preview with mock data — no live session needed.
If no config file exists, paddington uses a built-in default template that matches the standard output. If the config has errors, a warning is shown in the status line and the default template is used as a fallback.
Analytics
Monthly Stats
View cost breakdowns by day, model, and project:
Session History
Browse recent sessions:
Data is stored at $XDG_DATA_HOME/paddington/sessions.db (defaults to ~/.local/share/paddington/sessions.db).
Build
The release profile is configured with LTO and symbol stripping for a small binary.
Credits
Heavily inspired by Starship