- Go 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| cmd/cco2usage | ||
| docs | ||
| internal | ||
| testdata | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| README.md | ||
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-splitmode 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
ccusagedata; 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.