Estimate the CO₂ emissions of your coding-agent LLM usage (Claude Code, Codex, Cursor…). 100% offline Go CLI that wraps ccusage.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-30 09:06:16 +02:00
cmd/cco2usage ✨ feat(cli): wire flags, config, pipe/spawn 2026-07-29 23:07:28 +02:00
docs 📝 docs: README methodology, sources, uncertainty 2026-07-29 23:27:07 +02:00
internal 🐛 fix(app): emit valid JSON on empty data; drop dead ccusage.Read 2026-07-29 23:34:35 +02:00
testdata 🧪 test: capture ccusage JSON fixtures (real schema) 2026-07-29 20:08:56 +02:00
.gitignore 🎉 init: scaffold Go module and minimal CLI 2026-07-29 20:00:05 +02:00
go.mod ✨ feat(cli): wire flags, config, pipe/spawn 2026-07-29 23:07:28 +02:00
go.sum ✨ feat(cli): wire flags, config, pipe/spawn 2026-07-29 23:07:28 +02:00
LICENSE 📄 chore: add MIT LICENSE 2026-07-29 23:28:25 +02:00
README.md 📝 docs: README methodology, sources, uncertainty 2026-07-29 23:27:07 +02:00

cco2usage

cco2usage is a small Go CLI that estimates the CO₂ emissions of your coding-agent LLM usage — Claude Code, Codex, Cursor, Copilot, Gemini CLI, and anything else ccusage can read. It wraps ccusage's local usage data, attaches a carbon column to each period, and prints the table back with totals and everyday equivalents.

It is 100% offline: no network, no telemetry, no accounts. Static tables only.

⚠️ Everything here is an estimate — ±50% at best. Closed-model energy use is not published, so model tiers are inferred from open-model proxies; the frontier tier is an extrapolation; grid figures are national averages, not your datacenter's. Read the Methodology and Limitations sections before quoting a number. Do not use this for compliance or carbon accounting.


What it is

ccusage already does the hard part — parsing per-agent JSONL logs, reconciling token counts, and breaking usage down by model. cco2usage takes that, maps each model to an energy tier, multiplies by a grid carbon intensity, and shows grams CO₂e (estimated) per period. No fork, no rebase debt: ccusage is the acquisition layer, cco2usage is the carbon layer on top.

Install

Requires Go 1.22+ and ccusage on your machine:

npm i -g ccusage        # or: npx ccusage ... on every invocation
go install git.greil.fr/mat/cco2usage/cmd/cco2usage@latest

Or build from source:

git clone https://git.greil.fr/mat/cco2usage
cd cco2usage && go build -o cco2usage ./cmd/cco2usage

Verify:

cco2usage --version

Usage

Two invocation styles — pipe, or let cco2usage spawn ccusage for you:

# pipe (idiomatic Unix): ccusage emits JSON, cco2usage attaches CO₂
ccusage monthly --json | cco2usage

# direct: cco2usage runs ccusage --json internally
cco2usage monthly          # report: daily | weekly | monthly | session
cco2usage monthly --region eu
cco2usage daily  --grid 250 --no-equivalents
cco2usage session --json   # enriched JSON instead of the text table

Detection is automatic: if stdin is not a terminal, cco2usage reads ccusage --json from the pipe; otherwise it expects a report name and spawns ccusage <report> --json.

Sample output

Real output from the shipped renderer (golden test fixture; EU grid):

+------------+------------------------------+-------+--------+------------+-------------+
| Period     | Models                       | Input | Output | Cost (USD) | CO2 (est.)  |
+------------+------------------------------+-------+--------+------------+-------------+
| 2026-07-28 | claude-opus-4-7              | 4.50M | 36.9k  | $11.40     | 1.63 kgCO2e |
| 2026-07-29 | claude-sonnet-4, gpt-4o-mini | 1.20M | 80.0k  | $4.30      | 480 gCO2e   |
+------------+------------------------------+-------+--------+------------+-------------+
| Total      |                              |       |        | $15.70     | 2.11 kgCO2e |
+------------+------------------------------+-------+--------+------------+-------------+
≈ 8.65 km voiture · ≈ 459.17 charges smartphone
* estimation · réseau : EU · 242 gCO2e/kWh · méthodo : voir README

The total row sums each row's precomputed grams CO₂e — it is never recomputed from the totals block, because aggregated token counts cannot be re-split by tier.

Flags

Flag Description
--version Print the version and exit.
--region <code> Grid preset: world, eu, de, fr, uk, us, cn, in.
--grid <gCO₂e/kWh> Override the grid intensity directly (takes precedence over the region preset).
--json Emit enriched JSON (cco2usage's own schema) instead of the text table. In spawn mode, --json to ccusage is always passed internally.
--no-equivalents Hide the EPA equivalents footer line.

--cache-split (charging cache tokens at a reduced, price-proxied coefficient) is deferred to v2 and not accepted in this release. In v1, cache tokens are counted at the model's input coefficient — see Limitations.

Config & environment

Runtime config resolves from four sources with fixed precedence (flag > env > file > builtin):

# config file (Linux: ~/.config/cco2usage/config.json, macOS: ~/Library/Application Support/cco2usage/config.json)
{
  "region": "eu",
  "gridIntensity": 250
}
export CCO2_REGION=fr        # env, overrides the file
export CCO2_GRID=393         # env, overrides the file's gridIntensity

Precedence: --region/--grid beat CCO2_REGION/CCO2_GRID, which beat the config file, which beats the builtin default (world, 480 gCO₂e/kWh). The grid preset for the resolved region applies unless an explicit --grid/CCO2_GRID override is set.

How it estimates CO₂ (methodology)

For each usage row, cco2usage iterates per model, resolves that model's tier, and sums energy × PUE × grid:

grams = Σ_models [ (inputKind × InputCoeff/1e6 + outputKind × OutputCoeff/1e6) × PUE × GridIntensity ]

  inputKind  = Input + CacheCreation + CacheRead     (cache tokens use the input coeff in v1)
  outputKind = Output

Coefficients are in kWh per 1 million tokens; dividing by 1e6 yields per-token energy. PUE = 1.1 scales GPU energy up to whole-datacenter energy.

Energy coefficients

kWh per 1M tokens, by tier and token kind (× PUE 1.1):

tier input output example models
small 0.17 0.5 haiku, gpt-4o-mini, gemini-flash, nano
mid 0.33 1.0 sonnet, gpt-4o, gemini-pro, pro
frontier 0.67 2.0 opus, o1, o3, o4, gpt-4, ultra

These anchor the small and mid tiers on Samsi et al. (2023) — the only direct per-token energy measurement cited here. The input/output split is a 3:1 heuristic (autoregressive decode ≈ 2–3× prefill), not measured per tier. The frontier tier is an extrapolation: Samsi caps at 65B parameters, so frontier-class closed models are inferred, not measured. PUE 1.1 follows the Green Algorithms methodology framework (PUE × components × time).

Tier mapping

Model → tier is a case-insensitive substring match, tried small → frontier → mid (first match wins); an unknown name defaults to mid.

substring tier
haiku, mini, flash, nano small
opus, o1, o3, o4, gpt-4, ultra frontier
sonnet, pro, gemini mid

One collision is resolved explicitly: the small pattern mini is a substring of gemini (mid), so a naive small-first scan would mis-classify every gemini-* model as small. cco2usage resolves any name containing gemini to mid up front — unless it also carries flash/nano/haiku, in which case it is small. Net effect: gemini-pro → mid, gemini-2.5-flash → small.

Grid carbon intensity

2023 national grid averages (gCO₂e/kWh) — not datacenter-specific or marginal/real-time factors:

region gCO₂e/kWh region gCO₂e/kWh
world 480 uk 162
eu 242 us 393
de 371 cn 530
fr 32 in 630

Override any of these with --grid. Source: Ember (global/national annual averages) and RTE Bilan électrique 2023 (France). Treat as ±10–20% uncertain.

Equivalents

Grams CO₂e → everyday units, from US EPA Greenhouse Gas Equivalencies (eGRID2022):

  • Passenger car: 244 gCO₂e per km → km = grams / 244 (grid-independent).
  • Smartphone charge: 0.019 kWh per full charge → charges = grams / (0.019 × gridIntensity), valued at the chosen grid so the equivalent tracks your region.

Sources

What Source
Primary token-energy figures (small/mid anchors) Samsi et al., From Words to Watts: Estimating the Energy Consumption of Large Language Model Inference (2023) — arXiv:2310.03003. GPU-only, energy-per-output-token, measured on LLaMA 7B/13B/65B; closed models are inferred by tier from these open-model proxies.
LLM request footprint (cross-check) Luccioni et al., Power Hungry Processing: Watts Driving the Cost of AI Deployment? (2024) — arXiv:2311.16863.
Methodology framework (PUE × components × time) Green Algorithms — Lannelongue et al., Quantifying the carbon cost of a compute experiment, Advanced Science (2021). Not a per-token source.
Grid carbon intensity Ember — Global / European / US Electricity Review; RTE — Bilan électrique 2023 (France).
Equivalents factors US EPA — Greenhouse Gas Equivalencies Calculator (eGRID2022).
Usage data layer ccusage — cco2usage wraps it.

Limitations & uncertainty

cco2usage is an estimation tool, not a meter. Concretely:

  • Closed-model consumption is unpublished. Claude/GPT/Gemini tiers are inferred from open-model proxies. The frontier tier is an extrapolation (Samsi caps at 65B) with wide uncertainty.
  • Input/output split is a 3:1 heuristic (decode ≈ 2–3× prefill), labelled as a heuristic, not measured per model.
  • Grid figures are national averages, not your datacenter's marginal or real-time intensity.
  • Cache tokens (cache creation / cache read) are counted at the model's input coefficient. A reduced-coefficient --cache-split mode is deferred to v2; conflating Anthropic's prompt-caching price discount with a real energy saving would not be defensible against the cited references.
  • No live grid intensity (Electricity Maps / WattTime) — planned for v2.
  • No persistent history. Each run estimates from current ccusage data; there is no aggregation across runs.

If your use case needs defensible numbers — carbon accounting, reporting, offsets — this tool is not sufficient on its own. Use it for relative signals (model A vs model B, region X vs region Y, this week vs last week), and read it as an estimate.

Credit & license

Built on top of ccusage, which does all the usage-data heavy lifting. MIT licensed.