claude-carbon

Track the carbon footprint of your Claude Code sessions.
1. Install (or update):
curl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | bash
Same command to install and to update to the latest version.
2. Restart Claude Code. Your CO2 appears in the status line:
claude-carbon ⌥ main | 🟢 Opus 4.7 ▓▓▓░░░░░░░ 35% | $0.50 · 65g CO₂ | Use 24% ↻13:00
Segments, left to right: project + git branch, model + context window %, session cost + CO2, 5h block usage % + reset time. A 🔥 prefix appears when the sustained burn rate would overshoot 100% of the limit by the end of the 5h block (after a 15 min grace window, only once usage reaches 15%).
5h quota source. The percentage comes directly from Anthropic's /api/oauth/usage endpoint (the same data Claude Code displays in /usage). No heuristic, no token-limit file to seed. Two sources in order:
- stdin (preferred): if Claude Code injects
rate_limits.five_hour.used_percentage in the statusline JSON, that value is used straight away.
- OAuth API fallback:
GET https://api.anthropic.com/api/oauth/usage with the bearer token from macOS Keychain, CLAUDE_CODE_OAUTH_TOKEN, or ~/.claude/.credentials.json. Cached 60s in ~/.claude/claude-carbon/oauth-usage.json.
Accurate on every plan, including Max 20x.
3. Use the slash commands:
/carbon-report - text report with totals, equivalences, top sessions
/carbon-card - generate shareable PNG report cards (requires playwright-core, see Dependencies)
What it does
- Adds a live CO2 estimate to the Claude Code status line, next to the session cost
- Persists each session to a local SQLite database
- Backfills historical data from existing
~/.claude transcripts
- Two slash commands:
/carbon-report (text) and /carbon-card (PNG)
Example report
Generate yours with /carbon-card in Claude Code. Exports summary and detailed PNGs to exports/.
Advanced options (CLI)
# Since a specific date
bash ~/code/claude-carbon/scripts/generate-report.sh --since 2026-03-01
# All time
bash ~/code/claude-carbon/scripts/generate-report.sh --all
Custom install directory
CLAUDE_CARBON_DIR=~/my-path/claude-carbon curl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | bash
Manual install
git clone https://github.com/gwittebolle/claude-carbon.git ~/code/claude-carbon
bash ~/code/claude-carbon/scripts/setup.sh
Then add to ~/.claude/settings.json:
{
"statusLine": {
"type": "command",
"command": "~/code/claude-carbon/scripts/statusline.sh"
},
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "~/code/claude-carbon/scripts/persist-session.sh"
}
]
}
]
}
}
Restart Claude Code.
How it works

Three data paths, two levels of accuracy:
| Script | Trigger | Data source | Subagents | Cache reads | Accuracy |
|---|
backfill.sh | Manual / setup | JSONL files | Included | Excluded | Best estimate |
persist-session.sh | Stop hook (session end) | JSONL files | Included | Excluded | Best estimate |
statusline.sh | Every turn (live) | context_window JSON | Not included | Included* | Approximate |
backfill and persist-session parse the raw JSONL transcripts (main session + subagent files), applying per-model emission factors. Only input_tokens and cache_creation_input_tokens are counted. These feed the SQLite database used by reports.
statusline reads context_window.total_input_tokens from Claude Code at each turn. This value represents the current context size (not a cumulative total), includes cache reads, and does not account for subagent tokens. It's an indicative live display, not a data source for reports.