agent-footprint 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. agent_footprint-0.1.0/.github/workflows/release.yml +56 -0
  2. agent_footprint-0.1.0/.gitignore +9 -0
  3. agent_footprint-0.1.0/LICENSE +21 -0
  4. agent_footprint-0.1.0/PKG-INFO +134 -0
  5. agent_footprint-0.1.0/README.md +111 -0
  6. agent_footprint-0.1.0/docs/details.md +182 -0
  7. agent_footprint-0.1.0/docs/next-steps.md +133 -0
  8. agent_footprint-0.1.0/pyproject.toml +47 -0
  9. agent_footprint-0.1.0/scripts/stale_factors.py +60 -0
  10. agent_footprint-0.1.0/scripts/update_factors.py +136 -0
  11. agent_footprint-0.1.0/src/agent_footprint/__init__.py +1 -0
  12. agent_footprint-0.1.0/src/agent_footprint/__main__.py +3 -0
  13. agent_footprint-0.1.0/src/agent_footprint/cli.py +153 -0
  14. agent_footprint-0.1.0/src/agent_footprint/config.py +166 -0
  15. agent_footprint-0.1.0/src/agent_footprint/data/countries.json +2344 -0
  16. agent_footprint-0.1.0/src/agent_footprint/default_config.json +41 -0
  17. agent_footprint-0.1.0/src/agent_footprint/factors.json +161 -0
  18. agent_footprint-0.1.0/src/agent_footprint/hooks.py +401 -0
  19. agent_footprint-0.1.0/src/agent_footprint/launch.py +414 -0
  20. agent_footprint-0.1.0/src/agent_footprint/model.py +318 -0
  21. agent_footprint-0.1.0/src/agent_footprint/periods.py +143 -0
  22. agent_footprint-0.1.0/src/agent_footprint/server.py +232 -0
  23. agent_footprint-0.1.0/src/agent_footprint/sources/__init__.py +154 -0
  24. agent_footprint-0.1.0/src/agent_footprint/sources/base.py +207 -0
  25. agent_footprint-0.1.0/src/agent_footprint/sources/claude.py +58 -0
  26. agent_footprint-0.1.0/src/agent_footprint/sources/codex.py +118 -0
  27. agent_footprint-0.1.0/src/agent_footprint/sources/copilot.py +162 -0
  28. agent_footprint-0.1.0/src/agent_footprint/sources/gemini.py +82 -0
  29. agent_footprint-0.1.0/src/agent_footprint/sources/opencode.py +120 -0
  30. agent_footprint-0.1.0/src/agent_footprint/sources/vibe.py +116 -0
  31. agent_footprint-0.1.0/src/agent_footprint/store.py +272 -0
  32. agent_footprint-0.1.0/src/agent_footprint/summary.py +177 -0
  33. agent_footprint-0.1.0/src/agent_footprint/updates.py +138 -0
  34. agent_footprint-0.1.0/src/agent_footprint/views.py +91 -0
  35. agent_footprint-0.1.0/src/agent_footprint/watch.py +674 -0
  36. agent_footprint-0.1.0/src/agent_footprint/web/index.html +698 -0
  37. agent_footprint-0.1.0/tests/__init__.py +0 -0
  38. agent_footprint-0.1.0/tests/fixtures/codex/sessions/2026/10/09/rollout-2026-10-09T10-00-00-0b7e2c1a-1111-2222-3333-444455556666.jsonl +9 -0
  39. agent_footprint-0.1.0/tests/fixtures/gemini/tmp/myproj/chats/0b7e2c1a-aaaa-bbbb-cccc-000000000001/sub-1.jsonl +2 -0
  40. agent_footprint-0.1.0/tests/fixtures/gemini/tmp/myproj/chats/session-2026-09-01T12-00-legacy.json +4 -0
  41. agent_footprint-0.1.0/tests/fixtures/gemini/tmp/myproj/chats/session-2026-10-09T09-00-0b7e2c1a.jsonl +8 -0
  42. agent_footprint-0.1.0/tests/test_figures.py +109 -0
  43. agent_footprint-0.1.0/tests/test_hooks.py +391 -0
  44. agent_footprint-0.1.0/tests/test_model.py +122 -0
  45. agent_footprint-0.1.0/tests/test_periods.py +108 -0
  46. agent_footprint-0.1.0/tests/test_sources.py +434 -0
  47. agent_footprint-0.1.0/tests/test_watch.py +37 -0
  48. agent_footprint-0.1.0/uv.lock +543 -0
@@ -0,0 +1,56 @@
1
+ # Publishes to PyPI when a version tag (v0.1.0, ...) is pushed. Uses trusted publishing: PyPI has a
2
+ # pending/registered publisher for this repo, workflow release.yml and environment pypi, so no token
3
+ # is stored. Uploads with `uv publish` instead of twine, which rejects the Metadata 2.5 hatchling writes.
4
+ name: release
5
+
6
+ on:
7
+ push:
8
+ tags: ["v*"]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v5
18
+ - uses: astral-sh/setup-uv@v6
19
+ - run: uv run python -m pytest
20
+
21
+ build:
22
+ needs: test
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v5
26
+ - uses: astral-sh/setup-uv@v6
27
+ - name: Tag matches the version in pyproject.toml
28
+ run: |
29
+ version=$(uv version --short)
30
+ if [ "v$version" != "$GITHUB_REF_NAME" ]; then
31
+ echo "::error::tag $GITHUB_REF_NAME does not match pyproject.toml version $version"
32
+ exit 1
33
+ fi
34
+ - run: uv build
35
+ - name: Smoke-test the wheel
36
+ run: uv run --no-project --isolated --with dist/*.whl agent-footprint --help
37
+ - uses: actions/upload-artifact@v4
38
+ with:
39
+ name: dist
40
+ path: dist/
41
+
42
+ publish:
43
+ needs: build
44
+ runs-on: ubuntu-latest
45
+ environment:
46
+ name: pypi
47
+ url: https://pypi.org/project/agent-footprint/
48
+ permissions:
49
+ id-token: write # OIDC token for trusted publishing
50
+ steps:
51
+ - uses: actions/download-artifact@v4
52
+ with:
53
+ name: dist
54
+ path: dist/
55
+ - uses: astral-sh/setup-uv@v6
56
+ - run: uv publish --trusted-publishing always dist/*
@@ -0,0 +1,9 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .pytest_cache/
4
+ .venv/
5
+ dist/
6
+ build/
7
+ *.egg-info/
8
+ *.log
9
+ *.swp
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Steven Warmelink
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.5
2
+ Name: agent-footprint
3
+ Version: 0.1.0
4
+ Summary: Live environmental footprint (energy, water, carbon) of AI coding agents: Claude Code, Codex CLI, Gemini CLI, OpenCode, Mistral Vibe and GitHub Copilot, computed with EcoLogits.
5
+ Project-URL: Homepage, https://github.com/warmelinks/agent-footprint
6
+ Project-URL: Methodology, https://ecologits.ai/latest/methodology/llm_inference/
7
+ Author: Steven Warmelink
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: carbon,claude-code,codex,ecologits,gemini-cli,github-copilot,llm,mistral-vibe,opencode,sustainability
11
+ Classifier: Environment :: Console
12
+ Classifier: Environment :: Web Environment
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Operating System :: Microsoft :: Windows
15
+ Classifier: Operating System :: POSIX
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Requires-Python: >=3.10
19
+ Requires-Dist: ecologits<1,>=0.11
20
+ Provides-Extra: zstd
21
+ Requires-Dist: zstandard>=0.22; (python_version < '3.14') and extra == 'zstd'
22
+ Description-Content-Type: text/markdown
23
+
24
+ # agent-footprint
25
+
26
+ A live view of the environmental footprint of your AI coding agents: electricity, water, carbon and
27
+ mineral/metal depletion, across the full life cycle (running the servers plus a time-share of
28
+ manufacturing them). It reads the logs your agents already write, compares the numbers to everyday
29
+ things (phone charges, glasses of water, km driven) and shows day, week, month and year overviews.
30
+ The impact model is [EcoLogits](https://ecologits.ai).
31
+
32
+ ## Install
33
+
34
+ Python 3.10+. Until it is on PyPI, install from a checkout of this repository:
35
+
36
+ ```bash
37
+ uv tool install --editable ".[zstd]"
38
+ ```
39
+
40
+ Once published:
41
+
42
+ ```bash
43
+ uvx agent-footprint serve # try it without installing
44
+ uv tool install agent-footprint # or: pipx install agent-footprint
45
+ ```
46
+
47
+ Optionally, open the view automatically whenever you start a coding agent (run from an installed
48
+ copy, not `uvx`):
49
+
50
+ ```bash
51
+ agent-footprint setup # asks per agent; --yes for all, --status to check, --remove to undo
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ```bash
57
+ agent-footprint serve # browser dashboard at http://localhost:8765
58
+ agent-footprint watch # terminal view: today, all agents, live
59
+ agent-footprint watch --week # also --month, --year; e.g. --month 2026-09
60
+ agent-footprint watch latest # follow the newest session (or pass a session id)
61
+ agent-footprint watch --once # print a snapshot and exit
62
+ agent-footprint open # open the terminal view in a split next to this one
63
+ agent-footprint info # versions, agents and log folders found, history size
64
+ agent-footprint config # create the config file and print its path
65
+ agent-footprint update # upgrade agent-footprint and EcoLogits
66
+ ```
67
+
68
+ **watch keys:** ←/→ step through Year, Month, Week, Today and active sessions · ↓/↑ previous/next
69
+ period · `y m w d` jump to a period · `1–9` Today or an active session · `f` follow newest · `q` quit.
70
+
71
+ ## Supported agents
72
+
73
+ ✅ works · 🧪 implemented, not yet tried on a real install · ❌ not supported
74
+
75
+ | Agent | Reads usage | Opens view on session start (`setup`) |
76
+ |---|:-:|:-:|
77
+ | Claude Code (CLI, VS Code, JetBrains) | ✅ | ✅ |
78
+ | Codex CLI (and its IDE extensions) | 🧪 | 🧪 |
79
+ | Gemini CLI | 🧪 | 🧪 |
80
+ | OpenCode | 🧪 | 🧪 |
81
+ | Mistral Vibe | ✅ | ❌ |
82
+ | GitHub Copilot, VS Code chat¹ | ✅ | ❌ |
83
+ | Copilot CLI, Cursor, Windsurf, Cline / Roo Code, Continue, Aider | ❌ | ❌ |
84
+
85
+ ¹ Copilot logs one prompt size per request, so its input tokens are estimated.
86
+
87
+ Past sessions are read too, and usage is kept in a local history after agents delete their logs.
88
+ Only token counts, timestamps, model names and session/project ids are stored; no prompts or
89
+ responses (session titles are opt-in).
90
+
91
+ ## Supported systems
92
+
93
+ | System | Works | Notes |
94
+ |---|:-:|---|
95
+ | Linux | ✅ | |
96
+ | WSL | ✅ | Also reads agents installed on the Windows side; run `setup` in Windows for their hooks |
97
+ | Windows | ✅ | PowerShell, cmd, Windows Terminal, VS Code |
98
+ | macOS | 🧪 | No Mac tested yet; iTerm2/Terminal ask once for Automation permission |
99
+
100
+ `agent-footprint open` (and the `setup` hook) picks the right way to show the view:
101
+
102
+ | Terminal | Opens | Tried |
103
+ |---|---|:-:|
104
+ | Terminator | split pane | ✅ |
105
+ | tmux, zellij, kitty², WezTerm, iTerm2, Windows Terminal | split pane | 🧪 |
106
+ | GNOME Terminal, Konsole, macOS Terminal | new tab or window | 🧪 |
107
+ | IDE terminals and anything else | browser dashboard | ✅ |
108
+
109
+ ² needs `allow_remote_control yes` in `kitty.conf`.
110
+
111
+ ## How the numbers are computed
112
+
113
+ Each response's model and token counts go into EcoLogits'
114
+ [LLM inference methodology](https://ecologits.ai/latest/methodology/llm_inference/). Because coding
115
+ agents re-send large cached contexts, input tokens are also counted, at a small weight relative to
116
+ output tokens (configurable; set to 0 for pure EcoLogits figures). Treat the results as
117
+ order-of-magnitude estimates, not measurements.
118
+
119
+ More in [docs/details.md](docs/details.md): log locations, history, the methodology and its
120
+ assumptions, how figures are kept current, and configuration.
121
+
122
+ ## Development
123
+
124
+ ```bash
125
+ uv sync --extra zstd
126
+ uv run python -m pytest
127
+ ```
128
+
129
+ To add an agent, subclass `FileSource` in `src/agent_footprint/sources/base.py` (see the existing
130
+ sources) and register it in `sources/__init__.py`.
131
+
132
+ ## License
133
+
134
+ MIT; see `LICENSE`. EcoLogits is MPL-2.0 and is installed as a dependency, not bundled.
@@ -0,0 +1,111 @@
1
+ # agent-footprint
2
+
3
+ A live view of the environmental footprint of your AI coding agents: electricity, water, carbon and
4
+ mineral/metal depletion, across the full life cycle (running the servers plus a time-share of
5
+ manufacturing them). It reads the logs your agents already write, compares the numbers to everyday
6
+ things (phone charges, glasses of water, km driven) and shows day, week, month and year overviews.
7
+ The impact model is [EcoLogits](https://ecologits.ai).
8
+
9
+ ## Install
10
+
11
+ Python 3.10+. Until it is on PyPI, install from a checkout of this repository:
12
+
13
+ ```bash
14
+ uv tool install --editable ".[zstd]"
15
+ ```
16
+
17
+ Once published:
18
+
19
+ ```bash
20
+ uvx agent-footprint serve # try it without installing
21
+ uv tool install agent-footprint # or: pipx install agent-footprint
22
+ ```
23
+
24
+ Optionally, open the view automatically whenever you start a coding agent (run from an installed
25
+ copy, not `uvx`):
26
+
27
+ ```bash
28
+ agent-footprint setup # asks per agent; --yes for all, --status to check, --remove to undo
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ```bash
34
+ agent-footprint serve # browser dashboard at http://localhost:8765
35
+ agent-footprint watch # terminal view: today, all agents, live
36
+ agent-footprint watch --week # also --month, --year; e.g. --month 2026-09
37
+ agent-footprint watch latest # follow the newest session (or pass a session id)
38
+ agent-footprint watch --once # print a snapshot and exit
39
+ agent-footprint open # open the terminal view in a split next to this one
40
+ agent-footprint info # versions, agents and log folders found, history size
41
+ agent-footprint config # create the config file and print its path
42
+ agent-footprint update # upgrade agent-footprint and EcoLogits
43
+ ```
44
+
45
+ **watch keys:** ←/→ step through Year, Month, Week, Today and active sessions · ↓/↑ previous/next
46
+ period · `y m w d` jump to a period · `1–9` Today or an active session · `f` follow newest · `q` quit.
47
+
48
+ ## Supported agents
49
+
50
+ ✅ works · 🧪 implemented, not yet tried on a real install · ❌ not supported
51
+
52
+ | Agent | Reads usage | Opens view on session start (`setup`) |
53
+ |---|:-:|:-:|
54
+ | Claude Code (CLI, VS Code, JetBrains) | ✅ | ✅ |
55
+ | Codex CLI (and its IDE extensions) | 🧪 | 🧪 |
56
+ | Gemini CLI | 🧪 | 🧪 |
57
+ | OpenCode | 🧪 | 🧪 |
58
+ | Mistral Vibe | ✅ | ❌ |
59
+ | GitHub Copilot, VS Code chat¹ | ✅ | ❌ |
60
+ | Copilot CLI, Cursor, Windsurf, Cline / Roo Code, Continue, Aider | ❌ | ❌ |
61
+
62
+ ¹ Copilot logs one prompt size per request, so its input tokens are estimated.
63
+
64
+ Past sessions are read too, and usage is kept in a local history after agents delete their logs.
65
+ Only token counts, timestamps, model names and session/project ids are stored; no prompts or
66
+ responses (session titles are opt-in).
67
+
68
+ ## Supported systems
69
+
70
+ | System | Works | Notes |
71
+ |---|:-:|---|
72
+ | Linux | ✅ | |
73
+ | WSL | ✅ | Also reads agents installed on the Windows side; run `setup` in Windows for their hooks |
74
+ | Windows | ✅ | PowerShell, cmd, Windows Terminal, VS Code |
75
+ | macOS | 🧪 | No Mac tested yet; iTerm2/Terminal ask once for Automation permission |
76
+
77
+ `agent-footprint open` (and the `setup` hook) picks the right way to show the view:
78
+
79
+ | Terminal | Opens | Tried |
80
+ |---|---|:-:|
81
+ | Terminator | split pane | ✅ |
82
+ | tmux, zellij, kitty², WezTerm, iTerm2, Windows Terminal | split pane | 🧪 |
83
+ | GNOME Terminal, Konsole, macOS Terminal | new tab or window | 🧪 |
84
+ | IDE terminals and anything else | browser dashboard | ✅ |
85
+
86
+ ² needs `allow_remote_control yes` in `kitty.conf`.
87
+
88
+ ## How the numbers are computed
89
+
90
+ Each response's model and token counts go into EcoLogits'
91
+ [LLM inference methodology](https://ecologits.ai/latest/methodology/llm_inference/). Because coding
92
+ agents re-send large cached contexts, input tokens are also counted, at a small weight relative to
93
+ output tokens (configurable; set to 0 for pure EcoLogits figures). Treat the results as
94
+ order-of-magnitude estimates, not measurements.
95
+
96
+ More in [docs/details.md](docs/details.md): log locations, history, the methodology and its
97
+ assumptions, how figures are kept current, and configuration.
98
+
99
+ ## Development
100
+
101
+ ```bash
102
+ uv sync --extra zstd
103
+ uv run python -m pytest
104
+ ```
105
+
106
+ To add an agent, subclass `FileSource` in `src/agent_footprint/sources/base.py` (see the existing
107
+ sources) and register it in `sources/__init__.py`.
108
+
109
+ ## License
110
+
111
+ MIT; see `LICENSE`. EcoLogits is MPL-2.0 and is installed as a dependency, not bundled.
@@ -0,0 +1,182 @@
1
+ # agent-footprint: details
2
+
3
+ Reference material behind the [README](../README.md).
4
+
5
+ ## Opening the view automatically
6
+
7
+ Python packages can't run anything at install time, so this is a separate step. Run it from an
8
+ installed copy, not through `uvx`: the hooks call the program that set them up. `setup` adds a
9
+ session-start hook to Claude Code, Codex CLI and Gemini CLI, and a small plugin to OpenCode (not to
10
+ Vibe yet: its sessions are read, but nothing opens when one starts). Each one
11
+ runs `agent-footprint open`, which opens the terminal view next to the agent:
12
+
13
+ | Terminal | What opens |
14
+ |---|---|
15
+ | tmux, zellij, Terminator, kitty¹, WezTerm, iTerm2, Windows Terminal (native or WSL) | a split pane |
16
+ | GNOME Terminal, Konsole, macOS Terminal | a new tab or window |
17
+ | anything else (e.g. an IDE's terminal) | the browser dashboard, started once; it stops by itself 15 minutes after its last browser tab closes |
18
+
19
+ ¹ kitty needs `allow_remote_control yes` in `kitty.conf`.
20
+
21
+ Inside an IDE (VS Code, JetBrains), including an agent extension's hooks, the browser dashboard
22
+ opens: the terminal the IDE was started from isn't the one you're working in. tmux started in the
23
+ IDE's terminal is split as usual.
24
+
25
+ **macOS:** the first time the view opens in iTerm2 or Terminal, macOS asks whether agent-footprint
26
+ may control that app. Run `agent-footprint open` there once by hand to answer it (or allow it under
27
+ System Settings › Privacy & Security › Automation); from a hook, the question may go unseen. kitty's
28
+ and WezTerm's command-line tools are also found inside their app bundles. Install with `uv tool
29
+ install` (or pipx on a Python ≥ 3.10): the Python that comes with macOS is 3.9.
30
+
31
+ Only one terminal view opens at a time, however many sessions you start. Set `"launch"` in the config
32
+ to force a terminal (`"terminal": "wezterm"`), to turn off the browser fallback, or to resize the split.
33
+ `setup` only changes its own entries in each agent's config file, and backs up the file
34
+ (`*.agent-footprint.bak`) the first time. `setup --status` (and `info`) reports a hook whose program
35
+ no longer exists, e.g. after its virtualenv was deleted; running `setup` again repairs it.
36
+
37
+ `setup` also asks whether to name sessions after their first prompt (off by default; see [What is stored](#history-is-kept-after-agents-purge-their-logs)).
38
+
39
+ ## Where logs are read
40
+
41
+ | Agent | Where it reads | Notes |
42
+ |---|---|---|
43
+ | Claude Code | `~/.claude/projects/*/<session>.jsonl` and subagent logs | Responses deduplicated by request id |
44
+ | Codex CLI | `~/.codex/sessions/**/rollout-*.jsonl` and `archived_sessions/` | Compressed `.jsonl.zst` with the `zstd` extra or Python 3.14+ |
45
+ | Gemini CLI | `~/.gemini/tmp/*/chats/session-*.jsonl` (and legacy `.json`) | Subagent chats counted under their parent session |
46
+ | OpenCode | `~/.local/share/opencode/opencode.db` (and legacy `storage/`) | Read-only; child sessions counted under their parent |
47
+ | Mistral Vibe | `~/.vibe/logs/session/*/meta.json` (or `save_dir` in its `config.toml`) | Vibe logs running token totals per session (updated after each turn), not per response: each increase is recorded when seen, so a session read afterwards counts at its last activity |
48
+ | GitHub Copilot (VS Code chat) | VS Code's `workspaceStorage/*/chatSessions/` and `globalStorage/emptyWindowChatSessions/` (Code and Code - Insiders) | Output tokens and model calls are exact; Copilot logs one prompt size per request, so input tokens are estimated (see below). The model "Auto" picked is used |
49
+
50
+ No hooks or plugins are needed in the agents just for reading, and past sessions work too. The
51
+ Claude Code and Codex extensions for VS Code and JetBrains write the same logs, so they are counted.
52
+
53
+ **Logs in other places.** An agent can have several log folders, and all of them are read:
54
+
55
+ - **Environment variables:** default locations follow each agent's own variables: `CLAUDE_CONFIG_DIR`,
56
+ `CODEX_HOME`, `GEMINI_CLI_HOME`, `XDG_DATA_HOME`, `OPENCODE_DB` and `VIBE_HOME`.
57
+ - **Hooks:** with `setup` hooks installed, every session start reports its transcript path, so a
58
+ folder used through an alias or a per-project variable is picked up automatically.
59
+ - **WSL:** agents installed on the Windows side are found in each Windows user profile on `C:`
60
+ (add other drives with `"path"`).
61
+ - **Config:** `"path"` under `"sources"` takes one folder or a list, for anything else
62
+ (e.g. a synced folder from another machine).
63
+
64
+ Records are keyed by agent and request id, so a folder reached twice is never counted twice.
65
+ `agent-footprint info` lists every folder in use.
66
+
67
+ **Windows** works natively (PowerShell, cmd, Windows Terminal, VS Code's terminal) and under WSL.
68
+ Files go to the same places under your user folder: `~\.config\agent-footprint`,
69
+ `~\.local\share\agent-footprint` and `~\.cache\agent-footprint`. WSL reads the Windows-side agents'
70
+ logs too, but `setup` there only installs hooks in the WSL-side agents; run `setup` in Windows for the
71
+ others.
72
+
73
+ **Adding an agent:** subclass `FileSource` in `src/agent_footprint/sources/base.py`. Implement
74
+ `default_root()`, `units()` (its log files) and `parse_line()` (one JSON line to usage records with
75
+ model and token counts), then register it in `sources/__init__.py` and add a fixture test.
76
+
77
+ ## History is kept after agents purge their logs
78
+
79
+ Claude Code deletes transcripts after `cleanupPeriodDays` (30 days by default), and Gemini CLI after
80
+ `general.sessionRetention.maxAge` (also 30 days by default). Each time agent-footprint runs, it copies
81
+ new usage records into `~/.local/share/agent-footprint/history.sqlite` (`$XDG_DATA_HOME`), and they
82
+ stay there after the source logs are gone. That is what makes month and year views possible.
83
+ (Version 0.1.0 kept it in `~/.cache`; it is moved automatically.)
84
+
85
+ **What is stored:** token counts, timestamps, model names, and each session's id and project folder
86
+ name. No prompt or response content, with one opt-in exception: with `"store_titles": true` (or
87
+ `agent-footprint setup --titles on`), sessions are named after the first 90 characters of their first
88
+ prompt, and those titles are stored. Turning it off erases stored titles.
89
+
90
+ - A stored response takes about 320 bytes including indexes: around 15 MB a year at 4,000 responses a month.
91
+ - `serve` and `watch` sync continuously. To capture history when neither runs, add
92
+ `agent-footprint sync` to cron or to an agent's session-start hook at least every few weeks.
93
+ - Only files that changed since the last sync are read, and only from where reading stopped.
94
+
95
+ ## How the numbers are computed
96
+
97
+ Each response's model and token counts go into the
98
+ [EcoLogits LLM inference methodology](https://ecologits.ai/latest/methodology/llm_inference/), using
99
+ EcoLogits' model size estimates, provider datacenter defaults (PUE, WUE, location) and
100
+ electricity mixes. The tests check the results against EcoLogits' own API.
101
+
102
+ - **Model size:** most providers don't publish parameter counts. EcoLogits estimates a range, which is
103
+ the main source of the low–high spread.
104
+ - **Model names:** Bedrock, Vertex and OpenRouter ids, dated snapshots and `[1m]` suffixes are
105
+ normalised. A model EcoLogits doesn't know yet is estimated as the closest known model of the same
106
+ family. The dashboard lists every such substitution, and also says when a request had no model in
107
+ the log, ran on Bedrock or Vertex (the model maker's datacenter defaults are used), or ran locally
108
+ (e.g. Ollama through OpenCode; estimated as if served from a datacenter).
109
+ - **Input tokens:** EcoLogits counts only generated tokens. Agent sessions re-send large cached
110
+ contexts on every request, so input tokens are added as weighted "output-token equivalents" (new
111
+ input ×0.05, cache reads ×0.005). Set the weights to 0 in the config for pure EcoLogits figures.
112
+ - **Not counted:** requests an agent doesn't log (for example, title generation), sessions that ran on
113
+ other machines (cloud or SSH sessions), networking, and your own device.
114
+
115
+ - **GitHub Copilot's input tokens** are estimated: it logs the prompt size of the last model call of each
116
+ request only. The calls in a request are taken to grow linearly from the previous request's prompt
117
+ to that one, and only the growth counts as new input; the rest as cache reads. The dashboard says so
118
+ whenever Copilot is in view.
119
+
120
+ Treat the results as order-of-magnitude estimates, not measurements.
121
+
122
+ ### Why input tokens are weighted
123
+
124
+ EcoLogits counts only generated (output) tokens. Coding agents re-send their whole context on every
125
+ request, mostly as cache reads: in a typical month of Claude Code use that is ~1,300M cache-read
126
+ tokens against ~6M output tokens. Reading context isn't free (the model still runs over it), but
127
+ per token it is much cheaper than generating:
128
+
129
+ - Prefill processes all input tokens in parallel and is compute-bound, while generation produces one
130
+ token at a time and is memory-bandwidth-bound. So prefill energy per token is a small fraction of
131
+ decode energy.
132
+ - A cache read skips recomputing the cached part and mostly costs memory traffic, so it is cheaper again.
133
+
134
+ The weights (new input ×0.05, cache writes ×0.05, cache reads ×0.005 output-token equivalents) are a
135
+ **judgement, not a measurement**. API prices put the ratios higher: input costs about 0.2× output,
136
+ and cache reads 0.1× input. Prices reflect cost and margin, not just energy, so they are an upper
137
+ reference. The choice matters: for the history above, EcoLogits' own method gives 8–14 kg CO₂e;
138
+ the default weights give 16–28 kg; price ratios would give 43–73 kg. The dashboard shows the
139
+ EcoLogits-only figure next to the assumption, and setting all weights to 0 in the config reproduces
140
+ EcoLogits exactly.
141
+
142
+ **One person's day.** Each indicator is also shown as a share of one person's daily footprint:
143
+
144
+ - **Electricity and greenhouse gases:** electricity generated per person and greenhouse-gas emissions
145
+ per person (incl. land use) for the world, from Our World in Data (Ember; Jones et al.). Set
146
+ `"compare_country"` (an ISO code such as `"NLD"` or `"DEU"`) to add your country's average.
147
+ - **Water:** full water footprints (Mekonnen & Hoekstra), including rainwater taken up by crops. An
148
+ agent's water is cooling and power-plant water only, so its share is a lower bound. A national
149
+ water figure is shown only where a sourced one is on file (currently the Netherlands).
150
+ - **Carbon budget:** a 1.5 °C-compatible budget of 2.5 t per person per year (~6.85 kg/day).
151
+
152
+ Past 100%, the share is shown in person-days. Sources are listed in the dashboard.
153
+
154
+ ## Keeping the figures up to date
155
+
156
+ | Figures | Kept current by |
157
+ |---|---|
158
+ | Models, datacenters, electricity grids (EcoLogits) | Dependabot proposes each EcoLogits release; CI tests it and it is merged when green; a weekly job tests the newest release |
159
+ | Electricity and greenhouse gases per person (world and countries) | `scripts/update_factors.py` refetches Our World in Data monthly and opens a pull request for review (changes over 25% are flagged) |
160
+ | Everyday comparisons, water footprints, the 1.5 °C budget | each figure has an `as_of` year and a review interval; a yearly job opens an issue listing those due (`scripts/stale_factors.py`) |
161
+
162
+ Users get new figures through releases. `serve` and `watch` check PyPI at most once a day and show a
163
+ notice when newer EcoLogits data or a newer agent-footprint is available (turn off with
164
+ `"auto_update_check": false`). `agent-footprint update` upgrades both in the tool's own environment
165
+ (`uv tool`, `pipx` or `pip`); for a source checkout, `git pull` brings new figures.
166
+
167
+ ## Configuration
168
+
169
+ ```bash
170
+ agent-footprint config # creates ~/.config/agent-footprint/config.json and prints its path
171
+ agent-footprint info # versions, agents found, history size, update status
172
+ ```
173
+
174
+ The config holds the grid zone (ISO-3 code, e.g. `"FRA"`), datacenter PUE/WUE, batch size, hardware
175
+ lifetime, input-token weights, per-provider overrides, which agents to read (and where), the
176
+ country to compare with, session titles, and what `agent-footprint open` does. Both views pick up
177
+ changes live. A setting that can't be used (a typo, an unknown country code, a value of the wrong
178
+ type, or a file that isn't valid JSON) is reported by `info`, the dashboard and `watch`, and the
179
+ default is used instead.
180
+
181
+ The dashboard only answers requests addressed to `localhost`, so other web pages can't read it.
182
+ `serve --host 0.0.0.0` makes it reachable from other machines, without authentication.
@@ -0,0 +1,133 @@
1
+ # Next steps
2
+
3
+ State as of 2026-10-11: everything is committed on `master` and pushed to `github.com/warmelinks/agent-footprint`.
4
+ Tests pass: 77 passed, 2 skipped on Linux; 76 passed, 3 skipped under Windows Python 3.13
5
+ (`uv run python -m pytest`, which installs the `dev` group). Skips are platform-specific tests.
6
+
7
+ The review of 2026-10-11 (privacy, history location, hooks, ports, config, dashboard access,
8
+ syncing, Windows) is done except for the items under "Open from the review" below.
9
+
10
+ ## Before publishing
11
+
12
+ - [ ] **Repository and package name.** `pyproject.toml`, the README and the dashboard link to
13
+ `github.com/warmelinks/agent-footprint`. Check that `agent-footprint` is free on
14
+ PyPI, create the GitHub repo, and update the links if the name differs.
15
+ - [ ] **Commit author email.** The commits use `steven@soundappraisal.eu` from the local git config;
16
+ decide which address to use publicly before pushing.
17
+ - [ ] **GitHub settings** the workflows rely on:
18
+ - "Allow auto-merge", plus a branch protection rule on `master` that requires the CI checks (`automerge.yml`).
19
+ - A PyPI trusted publisher for `release.yml` (environment `pypi`).
20
+ - Labels `ecologits` and `data`, used by the scheduled jobs.
21
+ - [ ] **First release:** tag `v0.1.0`; `release.yml` builds and publishes.
22
+
23
+ ## Verification still missing
24
+
25
+ - [ ] **Codex CLI, Gemini CLI and OpenCode readers** were built from those tools' source code (checked
26
+ 2026-10-10) and tested on fixture logs, but never on real installs. Try each with real sessions.
27
+ - [ ] **Session-start hooks** for Codex, Gemini and OpenCode: format checked against source, not run
28
+ in the real agents. Codex may ask to trust the hook once.
29
+ - [ ] **Terminal launchers:** only Terminator (WSL) was seen live; the tmux, zellij, kitty, WezTerm,
30
+ iTerm2, Windows Terminal, GNOME Terminal, Konsole and macOS Terminal commands are untested.
31
+ - [x] **Local setup:** `setup` has been run for Claude Code on both WSL and Windows (the old
32
+ `open_split.sh` hook is gone); session titles are switched on in both configs.
33
+
34
+ ## Windows / VS Code checks (run Claude Code natively in Windows for these)
35
+
36
+ Native Windows support was built and tested from WSL on 2026-10-11: the test suite passes under
37
+ Windows Python 3.13, and `info`, `watch --once`, `serve` (Host check, busy port) and `open`'s browser
38
+ fallback were run natively. What only a native session can check:
39
+
40
+ - [x] **Install:** `uv tool install --editable` of the WSL checkout (`\\wsl.localhost\Ubuntu\...`) works;
41
+ `agent-footprint` is on PATH. Not yet tried: a checkout on a Windows drive.
42
+ - [x] **Hook from the VS Code extension:** Claude Code's SessionStart hook runs the bare
43
+ `agent-footprint open --hook --agent claude` and opens the browser dashboard (`hook.log`).
44
+ An empty console window that came with it is fixed (f110e58).
45
+ - [ ] **Hook from the CLI** in Windows Terminal, and which shell runs hooks there (Git Bash, cmd,
46
+ PowerShell). A double-quoted absolute path (used when `agent-footprint` isn't on PATH) would not run
47
+ in PowerShell.
48
+ - [x] **Hook input:** the Windows log folder was learned from the hook (`roots.json`).
49
+ - [ ] **Windows Terminal split:** from a Claude Code session in Windows Terminal, `agent-footprint open`
50
+ should split the pane (`wt.exe -w 0 split-pane`) and run `watch` there.
51
+ - [ ] **watch keys** in Windows Terminal, conhost (cmd.exe window) and VS Code's terminal: arrows, y m w d,
52
+ 1–9, q; colours and box characters render; resizing redraws.
53
+ - [ ] **VS Code fallback:** the dashboard starts once and the browser opens (seen). Still to see: it
54
+ stops 15 minutes after the last tab closes (`serve.log`), and no window appears since f110e58.
55
+ - [ ] **Locked files:** `setup` while Claude Code is running (settings.json open); syncing while sessions
56
+ are being written; two Claude Code windows starting at once (`roots.json`, pid file).
57
+ - [ ] **Codex, Gemini CLI, OpenCode on Windows**, if installed: their log locations and hooks.
58
+ - [x] **Mistral Vibe and GitHub Copilot (VS Code chat)** update live in `watch` and the dashboard
59
+ (checked 2026-10-11). Neither has a session-start hook in `setup` yet; the Copilot CLI is unsupported.
60
+ - [ ] **CI:** the `windows-latest` jobs pass once the repository is on GitHub.
61
+
62
+ ## macOS checks (no Mac available yet)
63
+
64
+ Reviewed by reading the code on 2026-10-11; the `macos-latest` CI jobs will run the unit tests.
65
+ Only a Mac can check:
66
+
67
+ - [ ] **iTerm2:** `agent-footprint open` splits the agent's own session (targeted through
68
+ `ITERM_SESSION_ID`), also with several iTerm windows open; the Automation prompt appears once.
69
+ - [ ] **Terminal.app:** a new window opens with `watch`; the same Automation prompt.
70
+ - [ ] **kitty / WezTerm** without their CLIs on PATH: found in `/Applications/*.app/Contents/MacOS/`.
71
+ - [ ] **Claude Code from VS Code** started from iTerm (`code .`): the hook opens the browser, not an iTerm split.
72
+ - [ ] **Copilot:** chats found under `~/Library/Application Support/Code/User`.
73
+ - [ ] **watch keys** in iTerm2 and Terminal.app.
74
+
75
+ ## Figures reviewed
76
+
77
+ Reviewed 2026-10-11; `python scripts/stale_factors.py` reports nothing due until 2027.
78
+ - EU household electricity: 3,600 → 3,525 kWh/year (Eurostat 2024), so a day is now 9.7 kWh.
79
+ - Petrol car: 170 → 162 g/km (DESNZ 2026).
80
+ - Transatlantic flight: still ~0.8 t (DESNZ 2026 with radiative forcing and well-to-tank). The source text now shows the calculation.
81
+ - Water footprints and the 1.5 °C budget: no newer edition exists, so only `as_of` was bumped.
82
+
83
+ ## Open from the review
84
+
85
+ - [ ] **`agent-footprint update` on an "externally managed" Python** (Debian/Ubuntu system Python,
86
+ Homebrew; PEP 668): the `pip install` path fails. Detect it and point to `uv tool` or `pipx`.
87
+ - [ ] **One watch view at a time, machine-wide:** a second terminal window or tmux session never gets a
88
+ pane. Document it, or make it per terminal window.
89
+ - [ ] **Headline figure:** label the dashboard's main numbers as "EcoLogits + input-token extension"
90
+ (both figures are already shown under "What's behind these numbers?").
91
+ - [ ] **Titles erased while switched off** don't come back when they are switched on again (parser state
92
+ marks them "found, not kept"). Option: when titles are on, re-read the title from logs that still
93
+ exist. The WSL history has titles for 15 of 152 sessions because of this.
94
+ - [ ] **Code quality:** type hints; a table-driven rewrite of `model.resolve_model` with more cases;
95
+ split `watch.py` (rendering vs input); `logging` instead of `print` in `serve`; a ruff config.
96
+
97
+ ## More agents
98
+
99
+ - [ ] **Session-start hooks for Vibe and Copilot**, so the view opens with them too (their sessions are
100
+ read already). Vibe has some kind of hooks (its stats count hook-denied tool calls): check its docs.
101
+ - [ ] **Copilot CLI:** not supported; no session data on the maintainer's machine. Look at what it
102
+ writes after a real session (`~/.copilot/`).
103
+ - [ ] **Cursor, Windsurf, Cline / Roo Code, Continue, Aider:** need real sessions to build and test against.
104
+
105
+ ## Known limitations / ideas
106
+
107
+ - **The input-token weights** (×0.05 new input and cache writes, ×0.005 cache reads) are a judgement and
108
+ roughly double totals versus EcoLogits alone (see README, "Why input tokens are weighted").
109
+ Measured prefill/cache energy data would let this be grounded better.
110
+ - **Remote and cloud sessions** (claude.ai/code, SSH hosts) aren't counted. Options: an rsync mirror as
111
+ an extra source, or an OTLP receiver in `serve` (agents can export usage via OpenTelemetry).
112
+ - **Under WSL**, Windows-side agents are read, but `setup` only installs hooks in the WSL-side agent
113
+ configs; Windows-side hooks need `setup` run in Windows.
114
+ - **National water footprints** exist only for the Netherlands; other countries show world only.
115
+ - **Mistral Vibe** logs running totals per session only: timing is per turn while a view runs, but a
116
+ session first read afterwards counts in full at its last activity.
117
+ - **GitHub Copilot's input tokens are estimated** (one prompt size per request is logged); output tokens
118
+ and model calls are exact. Its "Auto" model may be one EcoLogits doesn't know (e.g. Microsoft's
119
+ `mai-*`), estimated as the closest model of that maker and size.
120
+ - **Inside an IDE** the browser opens rather than a split; zellij run in an IDE's terminal therefore
121
+ gets the browser too (its variables look the same as inherited ones).
122
+
123
+ ## Where things are
124
+
125
+ | Area | Files |
126
+ |---|---|
127
+ | Impact model (EcoLogits wrapper, model-name resolution, baselines) | `src/agent_footprint/model.py` |
128
+ | Agent log readers and folder discovery | `src/agent_footprint/sources/` (claude, codex, gemini, opencode, vibe, copilot) |
129
+ | History store (kept after agents purge logs) | `src/agent_footprint/store.py`, `~/.local/share/agent-footprint/history.sqlite` |
130
+ | Periods and aggregation | `periods.py`, `summary.py`, `views.py` |
131
+ | Dashboard and terminal | `server.py` + `web/index.html`, `watch.py` |
132
+ | Hooks and launching | `hooks.py` (`setup`), `launch.py` (`open`) |
133
+ | Figure upkeep | `scripts/update_factors.py`, `scripts/stale_factors.py`, `.github/workflows/` |