{"id":366037,"name":"claude-carbon","description":"Tracks the carbon footprint of Claude Code agent sessions with a live CO2 status line, per-model reports and shareable report cards.","url":"https://github.com/gwittebolle/claude-carbon","last_synced_at":"2026-08-24T00:09:55.536Z","repository":{"id":349429805,"uuid":"1202295583","full_name":"gwittebolle/claude-carbon","owner":"gwittebolle","description":"Track the carbon footprint of your Claude Code sessions","archived":false,"fork":false,"pushed_at":"2026-08-19T14:30:02.000Z","size":1935,"stargazers_count":161,"open_issues_count":0,"forks_count":16,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-08-19T20:07:21.818Z","etag":null,"topics":["ai-sustainability","anthropic","carbon-emissions","carbon-footprint","claude-code","claude-plugin","cli","climate","developer-tools","green-coding","green-it","statusline","sustainability"],"latest_commit_sha":null,"homepage":"https://tokenclimate.com","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gwittebolle.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null}},"created_at":"2026-04-05T21:21:28.000Z","updated_at":"2026-08-19T14:58:26.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gwittebolle/claude-carbon","commit_stats":null,"previous_names":["gwittebolle/claude-carbon"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/gwittebolle/claude-carbon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gwittebolle","download_url":"https://codeload.github.com/gwittebolle/claude-carbon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36864879,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-08-22T15:14:58.755Z","status":"online","status_checked_at":"2026-08-23T02:00:05.822Z","response_time":128,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"owner":{"login":"gwittebolle","name":null,"uuid":"52353111","kind":"user","description":null,"email":"","website":null,"location":null,"twitter":null,"company":null,"icon_url":"https://avatars.githubusercontent.com/u/52353111?u=d3f738efdb7d84c381bcbaa4837b0850b01f4b1e\u0026v=4","repositories_count":1,"last_synced_at":"2023-10-09T13:38:44.251Z","metadata":{"has_sponsors_listing":false},"html_url":"https://github.com/gwittebolle","funding_links":[],"total_stars":null,"followers":null,"following":null,"created_at":"2023-10-09T13:38:44.260Z","updated_at":"2023-10-09T13:38:44.260Z","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gwittebolle","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gwittebolle/repositories"},"packages":[{"id":14791162,"name":"claude-carbon","ecosystem":"npm","description":"Track the carbon footprint of your Claude Code sessions","homepage":"https://github.com/gwittebolle/claude-carbon#readme","licenses":"MIT","normalized_licenses":["MIT"],"repository_url":"https://github.com/gwittebolle/claude-carbon","keywords_array":["carbon-footprint","sustainability","claude-code","claude","green-it","co2"],"namespace":null,"versions_count":3,"first_release_published_at":"2026-07-19T10:43:55.867Z","latest_release_published_at":"2026-08-19T14:17:26.333Z","latest_release_number":"1.3.0","last_synced_at":"2026-08-19T14:29:53.905Z","created_at":"2026-07-19T12:01:21.867Z","updated_at":"2026-08-19T21:54:15.778Z","registry_url":"https://www.npmjs.com/package/claude-carbon","install_command":"npm install claude-carbon","documentation_url":null,"metadata":{"funding":null,"dist-tags":{"latest":"1.3.0"},"contentPolicy":null},"repo_metadata":{"id":349429805,"uuid":"1202295583","full_name":"gwittebolle/claude-carbon","owner":"gwittebolle","description":"Track the carbon footprint of your Claude Code sessions","archived":false,"fork":false,"pushed_at":"2026-08-03T16:25:10.000Z","size":1718,"stargazers_count":155,"open_issues_count":0,"forks_count":14,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-08-03T18:13:49.095Z","etag":null,"topics":["ai-sustainability","anthropic","carbon-emissions","carbon-footprint","claude-code","claude-plugin","cli","climate","developer-tools","green-it","statusline","sustainability"],"latest_commit_sha":null,"homepage":"https://tokenclimate.com","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gwittebolle.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":null,"gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null}},"created_at":"2026-04-05T21:21:28.000Z","updated_at":"2026-08-03T16:25:46.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gwittebolle/claude-carbon","commit_stats":null,"previous_names":["gwittebolle/claude-carbon"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/gwittebolle/claude-carbon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gwittebolle","download_url":"https://codeload.github.com/gwittebolle/claude-carbon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36783995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-08-06T04:43:03.162Z","status":"online","status_checked_at":"2026-08-19T02:00:06.185Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"},"tags":[]},"repo_metadata_updated_at":"2026-08-19T21:54:15.777Z","dependent_packages_count":0,"downloads":null,"downloads_period":"last-month","dependent_repos_count":0,"rankings":{"downloads":null,"dependent_repos_count":21.43945528123626,"dependent_packages_count":30.89740688972673,"stargazers_count":null,"forks_count":null,"docker_downloads_count":null,"average":26.168431085481494},"purl":"pkg:npm/claude-carbon","advisories":[],"docker_usage_url":"https://docker.ecosyste.ms/usage/npm/claude-carbon","docker_dependents_count":null,"docker_downloads_count":null,"usage_url":"https://repos.ecosyste.ms/usage/npm/claude-carbon","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/npm/claude-carbon/dependencies","status":null,"funding_links":[],"critical":null,"issue_metadata":{"last_synced_at":"2026-08-19T20:04:50.678Z","issues_count":2,"pull_requests_count":6,"avg_time_to_close_issue":2754.5,"avg_time_to_close_pull_request":103098.66666666667,"issues_closed_count":2,"pull_requests_closed_count":6,"pull_request_authors_count":2,"issue_authors_count":1,"avg_comments_per_issue":2.0,"avg_comments_per_pull_request":0.5,"merged_pull_requests_count":6,"bot_issues_count":0,"bot_pull_requests_count":0,"past_year_issues_count":2,"past_year_pull_requests_count":6,"past_year_avg_time_to_close_issue":2754.5,"past_year_avg_time_to_close_pull_request":103098.66666666667,"past_year_issues_closed_count":2,"past_year_pull_requests_closed_count":6,"past_year_pull_request_authors_count":2,"past_year_issue_authors_count":1,"past_year_avg_comments_per_issue":2.0,"past_year_avg_comments_per_pull_request":0.5,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":0,"past_year_merged_pull_requests_count":6,"issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/issues","maintainers":[{"login":"gwittebolle","count":4,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/gwittebolle"}],"active_maintainers":[{"login":"gwittebolle","count":4,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/gwittebolle"}]},"versions_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/claude-carbon/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/claude-carbon/version_numbers","latest_version_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/claude-carbon/latest_version","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/claude-carbon/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/claude-carbon/related_packages","codemeta_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages/claude-carbon/codemeta","maintainers":[{"uuid":"gwittebolle","login":"gwittebolle","name":null,"email":"gaetan.wittebolle@gmail.com","url":null,"packages_count":1,"html_url":"https://www.npmjs.com/~gwittebolle","role":null,"created_at":"2026-07-19T12:01:27.552Z","updated_at":"2026-07-19T12:01:27.552Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers/gwittebolle/packages"}],"registry":{"name":"npmjs.org","url":"https://registry.npmjs.org","ecosystem":"npm","default":true,"packages_count":5775834,"maintainers_count":1236038,"namespaces_count":420970,"keywords_count":881018,"github":"npm","metadata":{"funded_packages_count":189396,"rate_limit":2},"icon_url":"https://github.com/npm.png","created_at":"2022-04-04T15:19:23.081Z","updated_at":"2026-08-23T05:03:13.255Z","packages_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/packages","maintainers_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/maintainers","namespaces_url":"https://packages.ecosyste.ms/api/v1/registries/npmjs.org/namespaces"}}],"commits":null,"issues_stats":{"full_name":"gwittebolle/claude-carbon","html_url":"https://github.com/gwittebolle/claude-carbon","last_synced_at":"2026-08-19T20:04:50.678Z","status":null,"issues_count":2,"pull_requests_count":6,"avg_time_to_close_issue":2754.5,"avg_time_to_close_pull_request":103098.66666666667,"issues_closed_count":2,"pull_requests_closed_count":6,"pull_request_authors_count":2,"issue_authors_count":1,"avg_comments_per_issue":2.0,"avg_comments_per_pull_request":0.5,"merged_pull_requests_count":6,"bot_issues_count":0,"bot_pull_requests_count":0,"past_year_issues_count":2,"past_year_pull_requests_count":6,"past_year_avg_time_to_close_issue":2754.5,"past_year_avg_time_to_close_pull_request":103098.66666666667,"past_year_issues_closed_count":2,"past_year_pull_requests_closed_count":6,"past_year_pull_request_authors_count":2,"past_year_issue_authors_count":1,"past_year_avg_comments_per_issue":2.0,"past_year_avg_comments_per_pull_request":0.5,"past_year_bot_issues_count":0,"past_year_bot_pull_requests_count":0,"past_year_merged_pull_requests_count":6,"created_at":"2026-06-12T10:00:16.380Z","updated_at":"2026-08-19T20:04:50.679Z","repository_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon","issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/gwittebolle%2Fclaude-carbon/issues","issue_labels_count":{"enhancement":1,"bug":1},"pull_request_labels_count":{},"issue_author_associations_count":{"NONE":2},"pull_request_author_associations_count":{"OWNER":4,"CONTRIBUTOR":2},"issue_authors":{"jonaseberle":2},"pull_request_authors":{"gwittebolle":4,"dunglas":2},"host":{"name":"GitHub","url":"https://github.com","kind":"github","last_synced_at":"2026-08-24T00:00:06.384Z","repositories_count":16295454,"issues_count":42277446,"pull_requests_count":134597246,"authors_count":11513413,"icon_url":"https://github.com/github.png","host_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories","owners_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/owners","authors_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors"},"past_year_issue_labels_count":{"bug":1,"enhancement":1},"past_year_pull_request_labels_count":{},"past_year_issue_author_associations_count":{"NONE":2},"past_year_pull_request_author_associations_count":{"OWNER":4,"CONTRIBUTOR":2},"past_year_issue_authors":{"jonaseberle":2},"past_year_pull_request_authors":{"gwittebolle":4,"dunglas":2},"maintainers":[{"login":"gwittebolle","count":4,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/gwittebolle"}],"active_maintainers":[{"login":"gwittebolle","count":4,"url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/authors/gwittebolle"}]},"events":{"total":{"CreateEvent":4,"DeleteEvent":2,"IssueCommentEvent":3,"PullRequestEvent":1,"PushEvent":19,"WatchEvent":8},"last_year":{"CreateEvent":4,"DeleteEvent":2,"IssueCommentEvent":3,"PullRequestEvent":1,"PushEvent":19,"WatchEvent":8}},"keywords":["ai-sustainability","anthropic","carbon-emissions","carbon-footprint","claude-code","claude-plugin","cli","climate","developer-tools","green-coding","green-it","statusline","sustainability"],"dependencies":[],"score":5.081404364984463,"created_at":"2026-08-24T00:08:23.252Z","updated_at":"2026-08-24T00:09:55.556Z","avatar_url":"https://github.com/gwittebolle.png","language":"Shell","category":"Consumption","sub_category":"Computation and Communication","monthly_downloads":0,"total_dependent_repos":0,"total_dependent_packages":0,"readme":"# claude-carbon\n\n[![GitHub stars](https://img.shields.io/github/stars/gwittebolle/claude-carbon)](https://github.com/gwittebolle/claude-carbon/stargazers)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n[![GitHub release](https://img.shields.io/github/v/release/gwittebolle/claude-carbon)](https://github.com/gwittebolle/claude-carbon/releases)\n[![npm](https://img.shields.io/npm/v/claude-carbon)](https://www.npmjs.com/package/claude-carbon)\n[![CI](https://github.com/gwittebolle/claude-carbon/actions/workflows/ci.yml/badge.svg)](https://github.com/gwittebolle/claude-carbon/actions/workflows/ci.yml)\n\nTrack the carbon footprint of your Claude Code sessions.\n\n![Live CO2 in the Claude Code status line](docs/demo.gif)\n\n**1. Install (or update):**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | bash\n```\n\nOr, if you have Node.js:\n\n```bash\nnpx claude-carbon\n```\n\nSame command to install and to update to the latest version (both run the same installer).\n\n**2. Restart Claude Code.** Your CO2 appears in the status line:\n\n```\nclaude-carbon ⌥ main | 🟢 Opus 4.7 ▓▓▓░░░░░░░ 35% | $0.50 · 65g CO₂ | Use 24% ↻13:00\n```\n\nSegments, 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%).\n\n\u003e **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.\n\n**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:\n\n1. **stdin** (preferred): if Claude Code injects `rate_limits.five_hour.used_percentage` in the statusline JSON, that value is used straight away.\n2. **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`.\n\nAccurate on every plan, including Max 20x.\n\n**3. Use the slash commands:**\n\n- `/carbon-report` - text report with totals, equivalences, top sessions\n- `/carbon-card` - generate shareable PNG report cards (requires `playwright-core`, see [Dependencies](#dependencies))\n- `/carbon-update` - update to the latest version and re-price history (see [Updating](#updating))\n\n## What it does\n\n- Adds a live CO2 estimate to the Claude Code status line, next to the session cost\n- Persists each session to a local SQLite database\n- Backfills historical data from existing `~/.claude` transcripts\n- Two slash commands: `/carbon-report` (text) and `/carbon-card` (PNG)\n\n## Example report\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/example-report-v2.png\" alt=\"Claude Carbon Report\" width=\"540\"\u003e\n\u003c/p\u003e\n\nGenerate yours with `/carbon-card` in Claude Code. Exports summary and detailed PNGs to `exports/`.\n\n\u003cdetails\u003e\n\u003csummary\u003eAdvanced options (CLI)\u003c/summary\u003e\n\n```bash\n# Since a specific date\nbash ~/code/claude-carbon/scripts/generate-report.sh --since 2026-03-01\n\n# All time\nbash ~/code/claude-carbon/scripts/generate-report.sh --all\n\n# A closed period (--until is an exclusive upper bound: this one stops at June 30th)\nbash ~/code/claude-carbon/scripts/generate-report.sh --since 2026-01-01 --until 2026-07-01\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eCustom install directory\u003c/summary\u003e\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | CLAUDE_CARBON_DIR=~/my-path/claude-carbon bash\n```\n\nThe env var has to sit on the `bash` side of the pipe, not the `curl` side, or the installer never sees it.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eSecond Claude environment (CLAUDE_CONFIG_DIR)\u003c/summary\u003e\n\nIf you run a second Claude Code environment out of its own config directory, e.g.\n\n```bash\nalias claude-work=\"CLAUDE_CONFIG_DIR=~/.claude-work claude\"\n```\n\ninstall claude-carbon into that same directory by passing `CLAUDE_CONFIG_DIR` to the installer:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | CLAUDE_CONFIG_DIR=~/.claude-work bash\n```\n\nThe 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.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eManual install\u003c/summary\u003e\n\n```bash\ngit clone https://github.com/gwittebolle/claude-carbon.git ~/code/claude-carbon\nbash ~/code/claude-carbon/scripts/setup.sh\nbash ~/code/claude-carbon/scripts/configure-settings.sh\n```\n\nThe 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:\n\n```json\n{\n  \"statusLine\": {\n    \"type\": \"command\",\n    \"command\": \"~/code/claude-carbon/scripts/statusline.sh\"\n  },\n  \"hooks\": {\n    \"Stop\": [\n      {\n        \"matcher\": \"\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/code/claude-carbon/scripts/persist-session.sh\"\n          }\n        ]\n      }\n    ],\n    \"SessionStart\": [\n      {\n        \"matcher\": \"\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"~/code/claude-carbon/scripts/safety-rescan.sh\"\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\nThe `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.\n\nRestart Claude Code.\n\n\u003c/details\u003e\n\n## For teams\n\nclaude-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:\n\n- [Free calculator](https://tokenclimate.com/en/calculator?ref=github) and [per-model factor sheets](https://tokenclimate.com/en/models?ref=github) - the exact versioned factors of this repo, browsable.\n- [AI usage report](https://tokenclimate.com/bilan/en?ref=github) - a self-serve, shareable report of your organisation's real Claude usage (cost, CO2e, water, energy), generated in minutes from an Anthropic admin key. The key is never stored; the methodology annex is citation-ready.\n- [TokenClimate](https://tokenclimate.com/en?ref=github) - hosted team dashboards. Both sides share this repo's golden vectors, verified weekly in CI.\n\nThe 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.\n\n### PR dev footprint (/carbon-pr)\n\nThe number reviewers rarely see is what the PR cost to develop: your local Claude Code sessions while building the branch. `/carbon-pr` (or `scripts/generate-pr-report.sh`) sums the recorded sessions of the current branch and posts one sticky comment on its open PR, through your own `gh` auth. Run it after your push; running it again updates the same comment in place.\n\n```\n**Claude Code carbon report** · developing this PR\n124 g CO2e · $3.00 · 180k tokens · 1.5M cache reads · 2 sessions\n```\n\nHow the sessions are attributed: the Stop hook stores each session's git branch (read from the transcript), and the report selects `project + branch`. Sessions recorded before this column existed carry no branch; `scripts/backfill.sh` repairs them while their transcripts are still on disk (about 30 days). Sessions started from a subdirectory of the repo are stored under the subdirectory's name and stay out of the sum. A session that ends on another branch than it started is attributed to where it finished.\n\nTurning it off is the default: nothing is posted unless you run it. `--dry-run` previews the comment, `--pr \u003cnumber\u003e` targets a specific PR, and deleting the comment on GitHub is the full cleanup.\n\n## How it works\n\n![Data flow](docs/data-flow.png)\n\n**Three data paths, two levels of accuracy:**\n\n| Script               | Trigger                 | Data source           | Subagents    | Cache reads         | Accuracy      |\n| -------------------- | ----------------------- | --------------------- | ------------ | ------------------- | ------------- |\n| `backfill.sh`        | Manual / setup          | JSONL files           | Included     | Counted (8% energy) | Best estimate |\n| `persist-session.sh` | Stop hook (session end) | JSONL files           | Included     | Counted (8% energy) | Best estimate |\n| `statusline.sh`      | Every turn (live)       | `context_window` JSON | Not included | Included (approx)   | Approximate   |\n\n**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.\n\n**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`.\n\n**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.\n\n### Surviving the 30-day transcript purge\n\nClaude 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:\n\n```bash\nbash scripts/recompute.sh\n```\n\n## Commands\n\n| Command          | What it does                                        |\n| ---------------- | --------------------------------------------------- |\n| `/carbon-report` | Text report with totals, equivalences, top sessions |\n| `/carbon-card`   | Generate shareable PNG report cards                 |\n| `/carbon-badge`  | Shields.io badge of your total footprint for your READMEs |\n| `/carbon-pr`     | Post the dev footprint of the current branch on its PR |\n| `/carbon-update` | Update to the latest version and re-price history   |\n\n\u003cdetails\u003e\n\u003csummary\u003eScripts (run automatically, rarely needed manually)\u003c/summary\u003e\n\n| Script               | What it does                                                                              |\n| -------------------- | ----------------------------------------------------------------------------------------- |\n| `setup.sh`           | Init database, backfill historical sessions, show total                                   |\n| `statusline.sh`      | Status line script (called automatically by Claude Code)                                  |\n| `persist-session.sh` | Stop hook (saves session data on exit)                                                    |\n| `safety-rescan.sh`   | SessionStart hook (throttled background re-scan, catches missed sessions)                 |\n| `backfill.sh`        | Re-parse all historical JSONL transcripts (incl. subagents)                               |\n| `recompute.sh`       | Re-derive cost/CO2 from stored tokens after a price/factor change (no transcripts needed) |\n| `generate-report.sh` | Export PNG report cards (CLI, with `--since` / `--until` / `--all`)                                   |\n| `generate-badge.sh`  | Print the shields.io badge markdown + URL (CLI)                                           |\n| `generate-pr-report.sh` | Post the branch's dev footprint on its PR (CLI, `--dry-run` / `--pr`)                  |\n\nNote: 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.\n\n\u003c/details\u003e\n\n## Badge\n\n`/carbon-badge` prints a ready-to-paste shields.io badge with your measured all-time footprint, clickable back to this repo:\n\n[![Claude Code carbon footprint](https://img.shields.io/badge/claude--carbon-972.0%20kg%20CO2e-2f6f4f)](https://github.com/gwittebolle/claude-carbon)\n\n\u003csub\u003eThat badge is live, not a mockup: the author's own total, 1,025 sessions measured between 15 January 2026 and 20 August 2026. It is one developer's footprint, not the project's.\u003c/sub\u003e\n\n```markdown\n[![Claude Code carbon footprint](https://img.shields.io/badge/claude--carbon-972.0%20kg%20CO2e-2f6f4f)](https://github.com/gwittebolle/claude-carbon)\n```\n\nThe badge is a static image built from your local database, so the number is measured, not estimated on the fly. Re-run `/carbon-badge` whenever you want to refresh it.\n\nNumbers follow the locale the report uses (`fr` prints `12,4 kg`, `us` and the world default print `12.4 kg`); `CLAUDE_CARBON_LOCALE` forces a set.\n\n## Using with ccstatusline\n\nClaude Code accepts a single `statusLine` command, so claude-carbon's full status line and [ccstatusline](https://github.com/sirmalloc/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\n\n```\n~/code/claude-carbon/scripts/statusline.sh --segment\n```\n\n(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.\n\n## Emission factors\n\nFactors from [Jegham et al. 2025](https://arxiv.org/abs/2505.09598), 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.\n\n| Model  | Input (gCO2e/Mtok) | Output (gCO2e/Mtok) | Basis                      |\n| ------ | ------------------ | ------------------- | -------------------------- |\n| Fable  | 156                | 3304                | Extrapolated (2x Opus)     |\n| Opus   | 78                 | 1652                | Extrapolated (2x Sonnet)   |\n| Sonnet | 39                 | 826                 | 3-point fit (Jegham v6)    |\n| Haiku  | 20                 | 413                 | Extrapolated (0.5x Sonnet) |\n\n**Important: these are order-of-magnitude estimates, not precise measurements.**\n\n- Sonnet factors are a 3-point least-squares fit to the three Claude 3.7 Sonnet per-query energies estimated in Jegham et al. v6 (0.950 / 2.989 / 5.671 Wh), giving a ~21:1 output:input ratio. The value is consistent with [EcoLogits](https://ecologits.ai): its independent estimate for Sonnet brackets the same range (a wide band, so this is a consistency check, not proof). Fable, Opus and Haiku are extrapolated (no public data from Anthropic on per-model energy consumption); Opus = 2x Sonnet matches both the current EcoLogits Opus 4.5+ parameter ratio and the Anthropic price ratio (honest band 2x-5x).\n- Sessions run on non-Anthropic models (e.g. local models behind `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.\n- Cache read tokens are counted at a reduced factor (default 0.08 of an input token, set in `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](METHODOLOGY.md).\n- Carbon intensity uses the AWS region grid (location-based, 0.287 kgCO2e/kWh), not real-time grid data. This sits at the low end of the location-based range; the US national average is ~380 g/kWh.\n- Anthropic does not publish Scope 1, 2, or 3 emissions. These estimates are independent and based on academic research, not provider data.\n\nReport equivalences follow your locale, since a car and a kWh differ by ~2x between countries: ADEME/SNCF factors on a French or undetected locale, EPA ones in miles on a US locale, world-average ones otherwise (200 gCO2/km by car, 8.7 g per smartphone charge). Force a set with `CLAUDE_CARBON_LOCALE` (`fr`, `us`, `world`, or any locale string). The factors live in `data/factors.json` under `equivalences`.\n\nFactors are editable in `data/factors.json`. See [METHODOLOGY.md](METHODOLOGY.md) for the full scientific basis, formula, and equivalences.\n\n### Golden vectors\n\nThe methodology is pinned by golden test vectors in [`tests/methodology-vectors.json`](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.\n\n## Updating\n\nWhen 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`.\n\nTo update, run `/carbon-update` in Claude Code, or re-run the installer:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/gwittebolle/claude-carbon/main/install.sh | bash\n```\n\n- Updating re-prices your stored history with the new factors automatically (CO2 only; cost figures are left intact). Run `scripts/recompute.sh --with-cost` yourself only after a price change.\n- If you edited `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.\n- Installed via the plugin marketplace? Update with Claude Code's built-in `/plugin update` instead.\n\n## Dependencies\n\n- `jq` - JSON parsing\n- `sqlite3` - local database\n- `git` - branch detection in status line (optional)\n- `curl` - 5h quota usage via Anthropic's `/api/oauth/usage` endpoint (optional, 60s cache)\n- `playwright-core` + Chromium - PNG export for `/carbon-card` (optional)\n\n`jq` and `sqlite3` are pre-installed on macOS. On Linux: `apt install jq sqlite3`.\n\nTo use `/carbon-card`, install Playwright and its Chromium browser:\n\n```bash\nnpm install -g playwright-core\nnpx playwright install chromium\n```\n\n## Reduce your footprint\n\nMeasuring is step one. Here are concrete levers to reduce your AI carbon footprint, ranked by impact.\n\n### Use the right model for the task\n\nOutput 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).\n\n```json\n{\n  \"env\": {\n    \"CLAUDE_CODE_SUBAGENT_MODEL\": \"claude-haiku-4-5\"\n  }\n}\n```\n\nUse 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.\n\n### Install RTK (Rust Token Killer)\n\n[RTK](https://github.com/rtk-ai/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.\n\n```bash\nbrew install rtk-ai/tap/rtk\nrtk init -g\n```\n\n### Reduce thinking tokens\n\nClaude's extended thinking can use up to 32k hidden tokens per message. Capping it reduces consumption without degrading quality on routine tasks.\n\n```json\n{\n  \"env\": {\n    \"MAX_THINKING_TOKENS\": \"10000\"\n  }\n}\n```\n\n### Compact earlier\n\nBy default, Claude Code compacts context at 95% usage. Compacting earlier keeps context cleaner and avoids bloated sessions.\n\n```json\n{\n  \"env\": {\n    \"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE\": \"50\"\n  }\n}\n```\n\n### Disconnect unused MCP servers\n\nEvery 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.\n\n```bash\nclaude mcp list\n```\n\nKeep the servers the project actually uses, remove the rest with `claude mcp remove \u003cname\u003e`.\n\n### Write concise instructions\n\nAdd to your project's CLAUDE.md:\n\n```\nBe concise. No preamble, no summaries unless asked.\n```\n\nOutput tokens are the most expensive in both cost and energy.\n\n### Combined impact\n\nThese 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.\n\n| Lever                | Estimated reduction          |\n| -------------------- | ---------------------------- |\n| Right model per task | -60% vs all-Opus             |\n| RTK                  | -70% on CLI tokens           |\n| Thinking cap at 10k  | -70% on thinking tokens      |\n| Haiku subagents      | -75% vs Opus, -50% vs Sonnet |\n| **All combined**     | **-50 to 70% total**         |\n\n### Related projects\n\n- [EcoLogits](https://ecologits.ai) - Python library estimating the footprint of GenAI API calls across providers.\n- [CodeCarbon](https://github.com/mlco2/codecarbon) - measures the emissions of compute you run yourself (training, local inference).\n- [ImpactIA](https://github.com/SNCFdevelopers/ImpactIA) - AI impact calculator and guide by SNCF, Wavestone and Resilio.\n- [green-claude](https://github.com/Institut-du-Numerique-Responsable/green-claude) - Claude Code skill that steers generated code toward eco-design rules (RGESN, GR491).\n\n### Further reading\n\n- [IEA - Energy and AI (2025)](https://www.iea.org/reports/energy-and-ai/) - data center projections\n- [Jegham et al. - How Hungry is AI?](https://arxiv.org/abs/2505.09598) - per-model energy estimates\n- [UCL/UNESCO - 90% AI energy reduction](https://www.ucl.ac.uk/news/2025/jul/practical-changes-could-reduce-ai-energy-demand-90) - frugal AI approaches\n- [GreenIT.fr - AI impacts 2025-2030](https://www.greenit.fr/impacts-ia-monde-2025-2030-rapport/) - French data\n\n## Why\n\nEvery 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.\n\n## Citing\n\nIf 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](CITATION.cff). Short form:\n\n\u003e Wittebolle, G. (2026). claude-carbon: carbon footprint tracker for Claude Code sessions. https://github.com/gwittebolle/claude-carbon\n\nThe shareable report cards already carry this attribution in their footer, so reposting a card as-is credits the tool.\n\n## Open source\n\nclaude-carbon is free and open source under the [MIT license](LICENSE). Contributions welcome.\n\nBuilt by [Gaetan Wittebolle](https://github.com/gwittebolle).\n","funding_links":[],"readme_doi_urls":[],"works":{},"citation_counts":{},"total_citations":0,"keywords_from_contributors":[],"project_url":"https://ost.ecosyste.ms/api/v1/projects/366037","html_url":"https://ost.ecosyste.ms/projects/366037"}