Track energy, carbon, and cost of ML experiments and LLM API calls — CLI and Python module with automatic token counting.
Project description
Carbon Trace
Track the energy, carbon, and cost of ML training runs and LLM API calls — automatically, with no changes to your existing code.
pip install carbonwatcher
Why
Every GPU training job and every LLM API call burns electricity. The carbon footprint depends on where that electricity comes from. A model trained in Ireland emits 8× less CO₂ than the same job run in India. Most teams have no idea what their AI compute actually costs the planet.
Carbon Trace makes it automatic: wrap your training loop or your API client, and it logs energy, carbon, and cost to a ledger you can query and share.
Quick start
Wrap a training script (no code changes)
carbonwatcher run python train.py
carbonwatcher run --region eu-west-1 --log-dir ./logs -- python train.py
Context manager
from carbonwatcher import CarbonTracker
with CarbonTracker(experiment_name="resnet50", model_name="ResNet50") as ct:
train(...)
# prints summary automatically
Epoch-based API (recommended for long runs)
from carbonwatcher import CarbonTracker
tracker = CarbonTracker(epochs=100, monitor_epochs=2, experiment_name="bert-ft")
for epoch in range(100):
tracker.epoch_start()
train_one_epoch(...)
tracker.epoch_end() # prints per-epoch stats + prediction after epoch 2
tracker.stop()
After monitor_epochs epochs it extrapolates and prints:
[Predicted for 100 epochs]
Time: 01:24:00
Energy: 840.0000 Wh
Carbon: 168.0000 gCO2e
Decorator
from carbonwatcher import CarbonTracker
@CarbonTracker.track(experiment="gpt2-finetune", model="GPT-2")
def train():
...
LLM token tracking
Track carbon and cost of LLM API calls — token counts come from the API response, no manual counting needed.
Anthropic / Claude
from carbonwatcher.llm.anthropic_wrapper import TrackedAnthropic
client = TrackedAnthropic() # drop-in for anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": "Explain transformers."}],
)
# carbon + cost logged automatically
OpenAI
from carbonwatcher.llm.openai_wrapper import TrackedOpenAI
client = TrackedOpenAI() # drop-in for openai.OpenAI()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}],
)
Ollama (local)
from carbonwatcher.llm.ollama_wrapper import TrackedOllama
client = TrackedOllama() # drop-in for ollama.Client()
response = client.chat(model="llama3.2", messages=[{"role": "user", "content": "Hi"}])
HuggingFace (local)
from carbonwatcher.llm.huggingface_wrapper import TrackedHuggingFace
model = TrackedHuggingFace("gpt2")
output = model.generate("Once upon a time")
llama.cpp (local)
from carbonwatcher.llm.llamacpp_wrapper import TrackedLlamaCpp
llm = TrackedLlamaCpp("models/llama-3.2-3b.gguf")
response = llm.chat([{"role": "user", "content": "Hello"}])
CLI reference
carbonwatcher --help
| Command | Description |
|---|---|
run |
Wrap any script — carbonwatcher run python train.py |
runs |
List all recorded training runs |
compare |
Rank runs by carbon efficiency |
estimate |
Quick carbon estimate for energy + region |
regions |
Compare carbon intensity across all regions |
config |
Set your region, name, and organization |
dashboard |
Monthly emissions with ASCII bar charts |
goals set |
Set monthly/yearly carbon targets |
goals progress |
Show progress toward your targets |
team |
Compare carbon across team members |
llm-runs |
List all LLM API calls |
llm-estimate |
Estimate carbon for one LLM call |
llm-compare |
Rank all known models by carbon footprint |
llm-models |
List all supported models |
logs |
Parse structured log files |
Config
# Set your location and identity once
carbonwatcher config --region India --user-name Alice --organization Acme
# Show current config
carbonwatcher config --show
Dashboard
carbonwatcher dashboard
carbonwatcher dashboard --export-json report.json
carbonwatcher dashboard --export-csv report.csv
Goals
# Set a monthly carbon budget of 500 gCO2e and $5 cost cap
carbonwatcher goals set --monthly 500 --cost-monthly 5.0
# Set a yearly budget
carbonwatcher goals set --yearly 5000
# Check progress
carbonwatcher goals progress
Team reports
# Compare team members (each person has their own ledger)
carbonwatcher team alice_ledger.json bob_ledger.json carol_ledger.json
# Filter by month
carbonwatcher team *.json --month 2026-05
# Include LLM usage
carbonwatcher team alice_ledger.json --llm-ledger alice_llm_ledger.json
Location-aware carbon
Carbon Trace automatically detects your location and uses the local grid's carbon intensity.
| Region | Intensity |
|---|---|
| Norway | 28 gCO2/kWh |
| France | 58 gCO2/kWh |
| Ireland (EU West) | 88 gCO2/kWh |
| California | 220 gCO2/kWh |
| USA average | 386 gCO2/kWh |
| India | 708 gCO2/kWh |
| Australia | 790 gCO2/kWh |
For LLM API calls, the server's grid is used, not yours:
- Anthropic (Claude): ~200 gCO2/kWh (AWS + GCP blended)
- OpenAI: ~200 gCO2/kWh
- Mistral AI: 58 gCO2/kWh (French grid)
Python module API
from carbonwatcher import CarbonTracker
from carbonwatcher.llm.tracker import LLMTracker
from carbonwatcher.dashboard.monthly import combined_monthly, print_monthly_dashboard
from carbonwatcher.dashboard.goals import set_goal, print_goals_progress
from carbonwatcher.team.report import print_team_report
from carbonwatcher.parser import parse_all_logs, aggregate_logs
# Monthly dashboard data
data = combined_monthly("ledger.json", "llm_ledger.json")
# Team stats
print_team_report(["alice.json", "bob.json"], month="2026-05")
# Parse log files
logs = parse_all_logs("./logs", experiment="bert-ft")
agg = aggregate_logs(logs)
Installation
# Core (training tracking + CLI)
pip install carbonwatcher
# With Claude/Anthropic support
pip install "carbonwatcher[anthropic]"
# With OpenAI support
pip install "carbonwatcher[openai]"
# With local model support (Ollama + HuggingFace + llama.cpp)
pip install "carbonwatcher[ollama,huggingface,llamacpp]"
# Everything
pip install "carbonwatcher[all]"
Requirements
- Python 3.9+
- macOS, Linux (Windows: CPU power estimated via TDP, no RAPL)
Hardware power measurement
| Platform | Method |
|---|---|
| Intel CPU (Linux) | RAPL — direct energy counter, exact |
| Apple Silicon (macOS) | powermetrics — accurate but needs sudo for real-time; falls back to TDP estimate |
| NVIDIA GPU | NVML — direct power sensor |
| Other | TDP-based estimate (conservative) |
Output example
Run: a3f2c1b8
Experiment: bert-finetune | Model: bert-base-uncased
CPU: Apple M1 [tdp_estimate]
GPU: None detected
Duration: 142.3s
Energy: 3.1200 Wh (CPU: 2.8400 GPU: 0.0000 DRAM: 0.0560) PUE×1.10
Carbon: 2.209 gCO2e (0.00000221 kg)
Grid: India @ 708.0 gCO2/kWh [static_table]
Cost: $0.0312 USD
Equiv: 0.0002 phone charges | 0.000014 km driven
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file carbonwatcher-0.3.0.tar.gz.
File metadata
- Download URL: carbonwatcher-0.3.0.tar.gz
- Upload date:
- Size: 52.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5e33d002b0e4c4fc2b33452c7f1fc7cdb2ccc67f03e7d32fe94335640063e92
|
|
| MD5 |
a1444e68ecc04d779a1dedd1e826a575
|
|
| BLAKE2b-256 |
6790e9bbaf17b568fa915b34dd4377c89f85bad8ebad3dda7abe7ce2e4d53e4a
|
File details
Details for the file carbonwatcher-0.3.0-py3-none-any.whl.
File metadata
- Download URL: carbonwatcher-0.3.0-py3-none-any.whl
- Upload date:
- Size: 58.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4eed52f1c66a1cda624b10f593732d336d131a21eaf3c3c967b254df98510f09
|
|
| MD5 |
80666a55bb6fcb343c5fea2f76d53815
|
|
| BLAKE2b-256 |
49abd96858df56ec5747a6b99b62c2b81c5753f69b6dbb86a5cd2636b8afc9c2
|