Track the carbon footprint of your Claude Code sessions. 1. Install (or update): Or, if you have Node.js: Same command to install and to update to the latest version (both run the same installer). 2. Restart Claude Code.
> /plugin marketplace add gwittebolle/claude-carbon> /plugin install claude-carbon@claude-carbon
Repo: gwittebolle/claude-carbon
What's inside
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
Or, if you have Node.js:
npx claude-carbon
Same command to install and to update to the latest version (both run the same installer).
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%).
Terminal and IDE only. claude-carbon runs through the Claude Code status line and shell hooks, which execute in the terminal CLI and IDE extensions. They do not run in the web app (claude.ai/code) or the desktop app, so no CO2 is displayed or recorded there.
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:
rate_limits.five_hour.used_percentage in the statusline JSON, that value is used straight away.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)/carbon-update - update to the latest version and re-price history (see Updating)~/.claude transcripts/carbon-report (text) and /carbon-card (PNG)Generate yours with /carbon-card in Claude Code. Exports summary and detailed PNGs to exports/.
# 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
# A closed period (--until is an exclusive upper bound: this one stops at June 30th)
bash ~/code/claude-carbon/scripts/generate-report.sh --since 2026-01-01 --until 2026-07-01
curl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | CLAUDE_CARBON_DIR=~/my-path/claude-carbon bash
The env var has to sit on the bash side of the pipe, not the curl side, or the installer never sees it.
If you run a second Claude Code environment out of its own config directory, e.g.
alias claude-work="CLAUDE_CONFIG_DIR=~/.claude-work claude"
install claude-carbon into that same directory by passing CLAUDE_CONFIG_DIR to the installer:
curl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | CLAUDE_CONFIG_DIR=~/.claude-work bash
The status line, the hooks, the database and the /carbon-* commands all live under that config dir, so each environment tracks its own sessions independently. When CLAUDE_CONFIG_DIR is unset everything falls back to ~/.claude as before.
git clone https://github.com/gwittebolle/claude-carbon.git ~/code/claude-carbon
bash ~/code/claude-carbon/scripts/setup.sh
bash ~/code/claude-carbon/scripts/configure-settings.sh
The second script merges the block below into ~/.claude/settings.json (additively: an existing status line or third-party hooks are left alone) and symlinks the /carbon-* commands. To wire it by hand instead, skip it and add:
{
"statusLine": {
"type": "command",
"command": "~/code/claude-carbon/scripts/statusline.sh"
},
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "~/code/claude-carbon/scripts/persist-session.sh"
}
]
}
],
"SessionStart": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "~/code/claude-carbon/scripts/safety-rescan.sh"
}
]
}
]
}
}
The Stop hook records the session that just ended. The SessionStart one re-scans for sessions that hook missed (crash, kill) and drives the daily update check the status line reads; without it you are never told a new version exists.
Restart Claude Code.
claude-carbon measures one developer's sessions, locally. If the question comes from your CTO, a client RFP or a CSR committee, the same methodology exists as a hosted layer:
The only places the OSS points there are a one-line footer in /carbon-report and a small credit on the /carbon-card PNGs. No status-line promo, no email capture: nothing leaves your machine.

Three data paths, two levels of accuracy:
| Script | Trigger | Data source | Subagents | Cache reads | Accuracy |
|---|---|---|---|---|---|
backfill.sh | Manual / setup | JSONL files | Included | Counted (8% energy) | Best estimate |
persist-session.sh | Stop hook (session end) | JSONL files | Included | Counted (8% energy) | Best estimate |
statusline.sh | Every turn (live) | context_window JSON | Not included | Included (approx) | Approximate |
backfill and persist-session parse the raw JSONL transcripts (main session + subagent files), applying per-model emission factors. They deduplicate assistant messages by (message.id, requestId), so resumed and compacted sessions are not double-counted (this matches ccusage; without it the token sum inflates roughly 3x). Each session stores its raw token breakdown (input, cache write, cache read, output), which feeds the SQLite database used by reports.
Cost is the theoretical API list value (pay-as-you-go), not your subscription price: input, output, cache write (1.25x input), and cache read (0.1x input) at current Anthropic rates, set in data/prices.json. On deduplicated data it matches ccusage.
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.
Claude Code deletes JSONL transcripts after about 30 days, so the SQLite database is the durable record. The Stop hook captures each session before its transcript ages out, and a once-a-day background re-scan (SessionStart hook, safety-rescan.sh) catches any session the Stop hook missed while its transcript still exists. Because each row stores raw token counts, recompute.sh regenerates cost and CO2 from data/factors.json + data/prices.json at any time, with no transcript needed. When Anthropic changes a price or a factor is revised, edit the config and run:
bash scripts/recompute.sh
| Command | What it does |
|---|---|
/carbon-report | Text report with totals, equivalences, top sessions |
/carbon-card | Generate shareable PNG report cards |
/carbon-update | Update to the latest version and re-price history |
| Script | What it does |
|---|---|
setup.sh | Init database, backfill historical sessions, show total |
statusline.sh | Status line script (called automatically by Claude Code) |
persist-session.sh | Stop hook (saves session data on exit) |
safety-rescan.sh | SessionStart hook (throttled background re-scan, catches missed sessions) |
backfill.sh | Re-parse all historical JSONL transcripts (incl. subagents) |
recompute.sh | Re-derive cost/CO2 from stored tokens after a price/factor change (no transcripts needed) |
generate-report.sh | Export PNG report cards (CLI, with --since / --until / --all) |
Note: backfill now derives project names from the transcript's cwd (matching the live hook). Sessions backfilled before this change keep their old, possibly truncated names; delete those rows and re-run backfill.sh to normalize them.
Claude Code accepts a single statusLine command, so claude-carbon's full status line and ccstatusline cannot run side by side. If ccstatusline drives your status line, embed the CO2 segment instead: in the ccstatusline TUI, add a Custom Command widget pointing to
~/code/claude-carbon/scripts/statusline.sh --segment
(adjust the path if you installed with CLAUDE_CARBON_DIR). The widget receives the same status JSON on stdin and prints just the cost + CO2 pair, e.g. $0.68 ยท 35g COโ. Segment mode never touches the network. Recording to the local database is unaffected either way: persistence runs from hooks, not from the status line.
Factors from Jegham et al. 2025, an arXiv preprint that estimates the energy consumption of LLM inference on AWS infrastructure from public API performance data (latency, throughput) over inferred hardware configurations.
| Model | Input (gCO2e/Mtok) | Output (gCO2e/Mtok) | Basis |
|---|---|---|---|
| Fable | 156 | 3304 | Extrapolated (2x Opus) |
| Opus | 78 | 1652 | Extrapolated (2x Sonnet) |
| Sonnet | 39 | 826 | 3-point fit (Jegham v6) |
| Haiku | 20 | 413 | Extrapolated (0.5x Sonnet) |
Important: these are order-of-magnitude estimates, not precise measurements.
ANTHROPIC_BASE_URL) are stored with their raw tokens but zero cost/CO2 and excluded from reports - a datacenter factor doesn't apply to them. Add patterns to exclude_models in data/factors.json to exclude more models by name.data/factors.json). A cached token skips prefill compute but still incurs decode-phase memory reads, so it is cheap but not free. This is an engineering estimate derived from the literature, not Anthropic's 0.1x billing ratio. See METHODOLOGY.md.Factors are editable in data/factors.json. See METHODOLOGY.md for the full scientific basis, formula, and equivalences.
The methodology is pinned by golden test vectors in tests/methodology-vectors.json: hand-computed expected CO2/cost values for known token breakdowns, replayed by bash tests/run-vectors.sh in CI on every push. Downstream consumers (such as TokenClimate) keep a copy of this file and verify weekly that their implementation produces the same numbers. If you edit data/factors.json or data/prices.json, update the vectors in the same commit, otherwise CI fails.
When a newer version is available, the status line shows a discreet โฌ /carbon-update hint. The check runs in the background (at most once a day, never on the status line's hot path); opt out with CLAUDE_CARBON_NO_UPDATE_NOTIFIER=1.
To update, run /carbon-update in Claude Code, or re-run the installer:
curl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | bash
scripts/recompute.sh --with-cost yourself only after a price change.data/factors.json or data/prices.json locally, the update keeps your edits; on a conflict with upstream it saves yours to *.local.bak and tells you./plugin update instead.jq - JSON parsingsqlite3 - local databasegit - branch detection in status line (optional)curl - 5h quota usage via Anthropic's /api/oauth/usage endpoint (optional, 60s cache)playwright-core + Chromium - PNG export for /carbon-card (optional)jq and sqlite3 are pre-installed on macOS. On Linux: apt install jq sqlite3.
To use /carbon-card, install Playwright and its Chromium browser:
npm install -g playwright-core
npx playwright install chromium
Measuring is step one. Here are concrete levers to reduce your AI carbon footprint, ranked by impact.
Output tokens cost ~21x more energy than input tokens (the marginal output:input ratio fit on Jegham v6). Opus is estimated at ~2x Sonnet per token (uncertainty band 2x-5x, see METHODOLOGY.md).
{
"env": {
"CLAUDE_CODE_SUBAGENT_MODEL": "claude-haiku-4-5"
}
}
Use Opus for architecture and planning. Sonnet for daily work. Haiku for subagents (exploration, file reading, reviews). As an indicative estimate with this tool's factors, this alone can cut your emissions by up to ~60% vs all-Opus.
RTK is a CLI proxy that filters noise from shell outputs (progress bars, verbose logs, passing tests) before they hit the context window. 60-90% token reduction on CLI commands, zero quality loss.
brew install rtk-ai/tap/rtk
rtk init -g
Claude's extended thinking can use up to 32k hidden tokens per message. Capping it reduces consumption without degrading quality on routine tasks.
{
"env": {
"MAX_THINKING_TOKENS": "10000"
}
}
By default, Claude Code compacts context at 95% usage. Compacting earlier keeps context cleaner and avoids bloated sessions.
{
"env": {
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE": "50"
}
}
Every connected MCP server ships its full tool schemas into the context window with every request, whether the session uses them or not. Most of that overhead is served from prompt cache after the first turn, and cache reads carry a much lower energy factor (see METHODOLOGY.md), so the saving per turn is modest; the gain comes from repetition across every turn of every session.
claude mcp list
Keep the servers the project actually uses, remove the rest with claude mcp remove <name>.
Add to your project's CLAUDE.md:
Be concise. No preamble, no summaries unless asked.
Output tokens are the most expensive in both cost and energy.
These reductions are indicative estimates, not measurements on a benchmark workload. The RTK figure comes from RTK's own documentation. The Haiku rows follow from this tool's own factors (Haiku = 0.5x Sonnet = 0.25x Opus per token): -50% when your subagents would otherwise run Sonnet, -75% when they would run Opus. They inherit the 0.5x extrapolation, the widest uncertainty band in the tool (see METHODOLOGY.md); if most of your usage is already Haiku, your absolute total rides on that band, so read it as an order of magnitude.
| Lever | Estimated reduction |
|---|---|
| Right model per task | -60% vs all-Opus |
| RTK | -70% on CLI tokens |
| Thinking cap at 10k | -70% on thinking tokens |
| Haiku subagents | -75% vs Opus, -50% vs Sonnet |
| All combined | -50 to 70% total |
Every Claude Code session uses real compute, real energy, real emissions. The number is small per query, but it adds up. Making it visible is the first step to owning it.
If claude-carbon's numbers or methodology end up in your article, talk or product, a citation is appreciated. GitHub's "Cite this repository" button generates BibTeX/APA from CITATION.cff. Short form:
Wittebolle, G. (2026). claude-carbon: carbon footprint tracker for Claude Code sessions. https://github.com/gwittebolle/claude-carbon
The shareable report cards already carry this attribution in their footer, so reposting a card as-is credits the tool.
claude-carbon is free and open source under the MIT license. Contributions welcome.
Built by Gaetan Wittebolle.
.claude-plugin/
marketplace.json
plugin.json
.github/
ISSUE_TEMPLATE/
bug_report.yml
config.yml
feature_request.yml
PULL_REQUEST_TEMPLATE.md
workflows/
ci.yml
traffic.yml
.gitignore
bin/
claude-carbon.js
CHANGELOG.md
CITATION.cff
CODE_OF_CONDUCT.md
CONTRIBUTING.md
data/
factors.json
prices.json
docs/
data-flow.png
demo/
demo.gif
demo.tape
fake-session.sh
example-report-v2.png
hooks/
hooks.json
install.sh
LICENSE
METHODOLOGY.md
package.json
README.md
scripts/
backfill.sh
check-update.sh
check-versions.sh
configure-settings.sh
generate-report.sh
persist-session.sh
recompute.sh
release.sh
safety-rescan.sh
setup.sh
statusline.sh
traffic-snapshot.sh
update.sh
SECURITY.md
skills/
carbon-card/
SKILL.md
carbon-report/
SKILL.md
carbon-update/
SKILL.md
stats/
paths.jsonl
referrers.jsonl
traffic.json
templates/
logo.png
report-detailed-en.html
report-detailed.html
report-summary-en.html
report-summary.html
social-preview.html
tests/
methodology-vectors.json
run-install-tests.sh
run-vectors.shFAQ
claude-carbon is a Claude Code plugin with 3 hand-picked skills for monitoring work, indexed on Flowy. Install it with the command on its page. It includes carbon-card, carbon-report, carbon-update. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.