cli-consumption 0.1.0__tar.gz → 0.2.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 (111) hide show
  1. cli_consumption-0.2.0/.github/workflows/ci.yml +64 -0
  2. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.github/workflows/release.yaml +6 -1
  3. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/AGENTS.md +2 -1
  4. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/CONTRIBUTING.md +11 -3
  5. cli_consumption-0.1.0/README.md → cli_consumption-0.2.0/PKG-INFO +99 -3
  6. cli_consumption-0.1.0/PKG-INFO → cli_consumption-0.2.0/README.md +64 -31
  7. cli_consumption-0.2.0/docs/architecture.md +105 -0
  8. cli_consumption-0.2.0/docs/decisions/0001-versioned-schema-migrations.md +50 -0
  9. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/docs/privacy.md +28 -3
  10. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/docs/provider-support.md +41 -0
  11. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/docs/roadmap.md +5 -2
  12. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/pyproject.toml +16 -7
  13. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/__init__.py +2 -0
  14. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/amazon_q.py +2 -1
  15. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/base.py +4 -0
  16. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/cline.py +4 -1
  17. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/codex.py +54 -6
  18. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/crush.py +4 -1
  19. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/goose.py +4 -1
  20. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/kilo.py +4 -1
  21. cli_consumption-0.2.0/src/cli_consumption/adapters/mistral_vibe.py +281 -0
  22. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/opencode.py +4 -1
  23. cli_consumption-0.2.0/src/cli_consumption/adapters/registry.py +169 -0
  24. cli_consumption-0.2.0/src/cli_consumption/api.py +143 -0
  25. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/cli.py +141 -117
  26. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/dashboard.py +49 -17
  27. cli_consumption-0.2.0/src/cli_consumption/exporting.py +55 -0
  28. cli_consumption-0.2.0/src/cli_consumption/migrations/__init__.py +1 -0
  29. cli_consumption-0.2.0/src/cli_consumption/migrations/env.py +20 -0
  30. cli_consumption-0.2.0/src/cli_consumption/migrations/versions/__init__.py +1 -0
  31. cli_consumption-0.2.0/src/cli_consumption/migrations/versions/v0001_baseline.py +269 -0
  32. cli_consumption-0.2.0/src/cli_consumption/migrations/versions/v0002_minimize_subagents.py +78 -0
  33. cli_consumption-0.2.0/src/cli_consumption/models.py +338 -0
  34. cli_consumption-0.2.0/src/cli_consumption/reporting.py +213 -0
  35. cli_consumption-0.2.0/src/cli_consumption/retention.py +70 -0
  36. cli_consumption-0.2.0/src/cli_consumption/schema.py +261 -0
  37. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/storage.py +97 -133
  38. cli_consumption-0.2.0/src/cli_consumption/sync.py +55 -0
  39. cli_consumption-0.2.0/tests/smoke_minimal_install.py +69 -0
  40. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_aider_adapter.py +16 -1
  41. cli_consumption-0.2.0/tests/test_api.py +160 -0
  42. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_cli.py +239 -1
  43. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_codex_adapter.py +83 -1
  44. cli_consumption-0.2.0/tests/test_exporting.py +85 -0
  45. cli_consumption-0.2.0/tests/test_migrations_and_retention.py +530 -0
  46. cli_consumption-0.2.0/tests/test_mistral_vibe_adapter.py +207 -0
  47. cli_consumption-0.2.0/tests/test_packaging.py +26 -0
  48. cli_consumption-0.2.0/tests/test_provider_registry.py +158 -0
  49. cli_consumption-0.2.0/tests/test_reporting.py +240 -0
  50. cli_consumption-0.2.0/tests/test_snapshot_contract.py +75 -0
  51. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_storage_and_exports.py +20 -2
  52. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_sync.py +27 -0
  53. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/uv.lock +257 -12
  54. cli_consumption-0.1.0/.github/workflows/ci.yml +0 -26
  55. cli_consumption-0.1.0/docs/architecture.md +0 -80
  56. cli_consumption-0.1.0/src/cli_consumption/api.py +0 -66
  57. cli_consumption-0.1.0/src/cli_consumption/exporting.py +0 -31
  58. cli_consumption-0.1.0/src/cli_consumption/models.py +0 -60
  59. cli_consumption-0.1.0/src/cli_consumption/sync.py +0 -25
  60. cli_consumption-0.1.0/tests/test_api.py +0 -61
  61. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/add-cli-adapter/SKILL.md +0 -0
  62. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/add-cli-adapter/agents/openai.yaml +0 -0
  63. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/audit-usage-privacy/SKILL.md +0 -0
  64. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/audit-usage-privacy/agents/openai.yaml +0 -0
  65. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/evolve-storage-schema/SKILL.md +0 -0
  66. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/evolve-storage-schema/agents/openai.yaml +0 -0
  67. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/yeet-github/SKILL.md +0 -0
  68. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/yeet-github/agents/openai.yaml +0 -0
  69. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/yolo/SKILL.md +0 -0
  70. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.agents/skills/yolo/agents/openai.yaml +0 -0
  71. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.gitignore +0 -0
  72. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.pre-commit-config.yaml +0 -0
  73. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/.python-version +0 -0
  74. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/LICENSE +0 -0
  75. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/NOTICE +0 -0
  76. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/__init__.py +0 -0
  77. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/__main__.py +0 -0
  78. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/_shared.py +0 -0
  79. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/aider.py +0 -0
  80. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/amp.py +0 -0
  81. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/claude.py +0 -0
  82. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/continue_cli.py +0 -0
  83. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/copilot.py +0 -0
  84. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/cursor.py +0 -0
  85. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/gemini.py +0 -0
  86. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/grok.py +0 -0
  87. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/kimi.py +0 -0
  88. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/openhands.py +0 -0
  89. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/pi.py +0 -0
  90. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/plandex.py +0 -0
  91. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/adapters/qwen.py +0 -0
  92. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/src/cli_consumption/py.typed +0 -0
  93. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/conftest.py +0 -0
  94. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_amazon_q_adapter.py +0 -0
  95. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_amp_adapter.py +0 -0
  96. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_claude_adapter.py +0 -0
  97. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_cline_adapter.py +0 -0
  98. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_continue_adapter.py +0 -0
  99. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_copilot_adapter.py +0 -0
  100. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_crush_adapter.py +0 -0
  101. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_cursor_adapter.py +0 -0
  102. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_gemini_adapter.py +0 -0
  103. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_goose_adapter.py +0 -0
  104. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_grok_adapter.py +0 -0
  105. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_kilo_adapter.py +0 -0
  106. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_kimi_adapter.py +0 -0
  107. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_opencode_adapter.py +0 -0
  108. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_openhands_adapter.py +0 -0
  109. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_pi_adapter.py +0 -0
  110. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_plandex_adapter.py +0 -0
  111. {cli_consumption-0.1.0 → cli_consumption-0.2.0}/tests/test_qwen_adapter.py +0 -0
@@ -0,0 +1,64 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ quality:
13
+ runs-on: ubuntu-latest
14
+ env:
15
+ TEST_POSTGRESQL_URL: postgresql+psycopg://postgres:postgres@127.0.0.1:5432/cli_consumption_test
16
+ services:
17
+ postgres:
18
+ image: postgres:17-alpine
19
+ env:
20
+ POSTGRES_DB: cli_consumption_test
21
+ POSTGRES_PASSWORD: postgres
22
+ POSTGRES_USER: postgres
23
+ ports:
24
+ - 5432:5432
25
+ options: >-
26
+ --health-cmd "pg_isready -U postgres -d cli_consumption_test"
27
+ --health-interval 5s
28
+ --health-timeout 5s
29
+ --health-retries 10
30
+ steps:
31
+ - uses: actions/checkout@v7.0.1
32
+ - uses: astral-sh/setup-uv@v10.0.1
33
+ with:
34
+ enable-cache: true
35
+ python-version: "3.14"
36
+ - run: uv sync --locked --all-groups --all-extras
37
+ - run: uv run pre-commit run --all-files --show-diff-on-failure
38
+ - run: uv run ruff format --check .
39
+ - run: uv run ruff check .
40
+ - run: uv run ty check --output-format github
41
+ - run: uv run pytest --cov --cov-report=term-missing
42
+ - run: uv build
43
+ - name: Smoke test the minimal wheel
44
+ run: |
45
+ wheel="$(find dist -maxdepth 1 -name '*.whl' -print -quit)"
46
+ uv run --isolated --no-project --python 3.14 \
47
+ --with "${wheel}" python tests/smoke_minimal_install.py
48
+
49
+ compatibility:
50
+ runs-on: ubuntu-latest
51
+ env:
52
+ UV_PYTHON: ${{ matrix.python-version }}
53
+ strategy:
54
+ fail-fast: false
55
+ matrix:
56
+ python-version: ["3.12", "3.13", "3.14"]
57
+ steps:
58
+ - uses: actions/checkout@v7.0.1
59
+ - uses: astral-sh/setup-uv@v10.0.1
60
+ with:
61
+ enable-cache: true
62
+ python-version: ${{ matrix.python-version }}
63
+ - run: uv sync --locked --all-groups --all-extras
64
+ - run: uv run pytest
@@ -84,13 +84,18 @@ jobs:
84
84
  with:
85
85
  enable-cache: true
86
86
  python-version: "3.14"
87
- - run: uv sync --locked --all-groups
87
+ - run: uv sync --locked --all-groups --all-extras
88
88
  - run: uv run pre-commit run --all-files --show-diff-on-failure
89
89
  - run: uv run ruff format --check .
90
90
  - run: uv run ruff check .
91
91
  - run: uv run ty check --output-format github
92
92
  - run: uv run pytest --cov --cov-report=term-missing
93
93
  - run: uv build
94
+ - name: Smoke test the minimal wheel
95
+ run: |
96
+ wheel="$(find dist -maxdepth 1 -name '*.whl' -print -quit)"
97
+ uv run --isolated --no-project --python 3.14 \
98
+ --with "${wheel}" python tests/smoke_minimal_install.py
94
99
  - name: Upload distributions
95
100
  uses: actions/upload-artifact@v7.0.1
96
101
  with:
@@ -6,7 +6,7 @@ Read this file, `README.md`, `CONTRIBUTING.md`, and the relevant documents under
6
6
  `docs/` before changing the repository. Keep changes scoped to one short-lived branch
7
7
  and one coherent pull request.
8
8
 
9
- The project is a Python 3.14+ package managed exclusively with `uv`. Do not introduce
9
+ The project is a Python 3.12+ package managed exclusively with `uv`. Do not introduce
10
10
  another package manager, task runner, ORM, web framework, or migration tool without an
11
11
  accepted architecture decision.
12
12
 
@@ -39,6 +39,7 @@ accepted architecture decision.
39
39
  Run all of the following before requesting review:
40
40
 
41
41
  ```bash
42
+ uv sync --all-extras --all-groups
42
43
  uv run pre-commit run --all-files
43
44
  uv run ruff format --check .
44
45
  uv run ruff check .
@@ -6,7 +6,7 @@
6
6
  git switch main
7
7
  git pull --ff-only
8
8
  git switch -c feat/short-description
9
- uv sync --all-groups
9
+ uv sync --all-extras --all-groups
10
10
  uv run pre-commit install
11
11
  ```
12
12
 
@@ -16,12 +16,20 @@ file manually.
16
16
  ## Make a change
17
17
 
18
18
  Keep provider parsing behind the adapter interface and normalized persistence behind
19
- the storage module. A new field must have a documented meaning across providers or be
20
- explicitly namespaced as provider-specific.
19
+ the storage module. Register providers once in the adapter registry rather than adding
20
+ parallel CLI or detection lists. A new field must have a documented meaning across
21
+ providers or be explicitly namespaced as provider-specific.
21
22
 
22
23
  Do not add telemetry. Test fixtures must be synthetic and must not contain copied user
23
24
  conversations or credentials.
24
25
 
26
+ Schema changes require a forward Alembic migration for both SQLite and PostgreSQL, an
27
+ explicit downgrade boundary, legacy-adoption tests, and mixed-version deployment notes.
28
+ Snapshot protocol changes must preserve strict validation, bounded payloads, generic
29
+ errors, and the documented server-first upgrade sequence. Export changes must preserve
30
+ deterministic ordering, bounded-memory CSV streaming, complete selected conversation
31
+ graphs, and spreadsheet-formula neutralization.
32
+
25
33
  ## Validate and review
26
34
 
27
35
  Run the quality gates documented in `AGENTS.md`, inspect the complete diff, then open a
@@ -1,3 +1,38 @@
1
+ Metadata-Version: 2.5
2
+ Name: cli-consumption
3
+ Version: 0.2.0
4
+ Summary: Analyze and consolidate AI coding CLI consumption across machines.
5
+ Project-URL: Homepage, https://github.com/Guillaume-Lombardo/cli-consumption
6
+ Project-URL: Documentation, https://github.com/Guillaume-Lombardo/cli-consumption#readme
7
+ Project-URL: Issues, https://github.com/Guillaume-Lombardo/cli-consumption/issues
8
+ Project-URL: Repository, https://github.com/Guillaume-Lombardo/cli-consumption.git
9
+ Author-email: Guillaume Lombardo <lombardo.guillaume@gmail.com>
10
+ License-Expression: Apache-2.0
11
+ License-File: LICENSE
12
+ License-File: NOTICE
13
+ Keywords: ai,cli,codex,observability,tokens,usage
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Environment :: Console
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Requires-Python: >=3.12
23
+ Requires-Dist: alembic>=1.14
24
+ Requires-Dist: pydantic>=2.10
25
+ Requires-Dist: sqlalchemy>=2.0
26
+ Requires-Dist: typer>=0.15
27
+ Provides-Extra: postgres
28
+ Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
29
+ Provides-Extra: server
30
+ Requires-Dist: fastapi>=0.115; extra == 'server'
31
+ Requires-Dist: uvicorn>=0.34; extra == 'server'
32
+ Provides-Extra: sync
33
+ Requires-Dist: httpx>=0.27; extra == 'sync'
34
+ Description-Content-Type: text/markdown
35
+
1
36
  # CLI Consumption
2
37
 
3
38
  CLI Consumption measures how AI coding CLIs use models, tokens, tools,
@@ -10,14 +45,17 @@ events. Local token counters are usage metadata, not billing records. Read the
10
45
 
11
46
  ## Quick start
12
47
 
13
- CLI Consumption requires Python 3.14 or newer and uses
48
+ CLI Consumption requires Python 3.12 or newer and uses
14
49
  [`uv`](https://docs.astral.sh/uv/).
50
+ Supporting 3.12–3.14 keeps the package usable on more existing development and CI
51
+ images without changing its architecture; the compatibility matrix exercises all
52
+ three versions.
15
53
 
16
54
  From a checkout, collect every supported CLI detected on the machine and generate a
17
55
  self-contained dashboard:
18
56
 
19
57
  ```bash
20
- uv sync
58
+ uv sync --all-extras
21
59
  uv run cli-consumption collect --provider all
22
60
  uv run cli-consumption export --output reports
23
61
  ```
@@ -38,6 +76,12 @@ uv tool run cli-consumption collect --provider all
38
76
  uv tool run cli-consumption export --output reports
39
77
  ```
40
78
 
79
+ The default installation covers local collection, SQLite storage, and exports. Install
80
+ only the optional runtime capabilities you use: `cli-consumption[sync]` for the sync
81
+ client, `cli-consumption[server]` for the collector service, and
82
+ `cli-consumption[postgres]` for PostgreSQL. Extras can be combined, for example
83
+ `cli-consumption[server,postgres]` on a central collector.
84
+
41
85
  To run the latest unreleased GitHub source:
42
86
 
43
87
  ```bash
@@ -67,6 +111,7 @@ Use the provider name below with `--provider` to select one CLI explicitly.
67
111
  | Grok Build | `grok` | `~/.grok/sessions/` | Per-prompt aggregates, reasoning effort, TTFT, and auto-compactions; no costs or subagent relationships. |
68
112
  | Kilo Code | `kilo` | `~/.local/share/kilo/kilo.db` | CLI SQLite store only; excludes legacy IDE tasks, cloud sessions, subagents, context windows, and costs. |
69
113
  | Kimi Code CLI | `kimi` | `~/.kimi/sessions/` | Wire v1 events, context windows, and compactions; selected model is not persisted and is reported as `unknown`. |
114
+ | Mistral Vibe CLI | `mistral-vibe` | `~/.vibe/logs/session/` | Session-level token aggregates, user turns, tools, and compactions; no per-message timestamps or historical model attribution. |
70
115
  | OpenCode | `opencode` | `~/.local/share/opencode/opencode.db` | SQLite v2 only; no legacy storage, child sessions, context windows, or costs. |
71
116
  | OpenHands CLI | `openhands` | `~/.openhands/conversations/` | SDK persistence with context windows, reasoning effort, and condensations; excludes cloud-only conversations and delegates. |
72
117
  | Pi | `pi` | `~/.pi/agent/sessions/` | Counts all persisted branches; no branch relationships, custom-directory auto-detection, context windows, or provider-reported durations. |
@@ -133,6 +178,19 @@ Share-safe reports still disclose aggregate work patterns and remain private
133
178
  operational data. A technically completed turn is not a measure of task quality or
134
179
  productivity.
135
180
 
181
+ Limit an export to conversations whose activity overlaps a half-open UTC window:
182
+
183
+ ```bash
184
+ uv run cli-consumption export --output reports \
185
+ --since 2026-08-01 --until 2026-08-31
186
+ ```
187
+
188
+ Dates denote UTC calendar boundaries; timestamps must include a timezone. An included
189
+ conversation is exported with its complete child graph rather than partially redacted
190
+ to the window. CSV rows are streamed in stable primary-key order. Spreadsheet formula
191
+ prefixes in text cells are neutralized with a leading apostrophe; CSV remains a
192
+ detailed operational-data export, not a share-safe format.
193
+
136
194
  ## SQLite and PostgreSQL
137
195
 
138
196
  A file path selects SQLite. A SQLAlchemy URL selects PostgreSQL:
@@ -146,6 +204,24 @@ uv run cli-consumption collect --provider all \
146
204
  Pass credentials through environment variables or a secret manager rather than shell
147
205
  history. `CLI_CONSUMPTION_DATABASE` can provide the database setting.
148
206
 
207
+ Database schemas are upgraded automatically when a command opens them. Existing
208
+ unversioned databases that exactly match a published schema are adopted before the
209
+ upgrade; unknown or modified schemas are refused. Back up production databases before
210
+ upgrading and do not run mixed application versions against one database while a
211
+ migration is in progress. See the
212
+ [migration decision](docs/decisions/0001-versioned-schema-migrations.md) for rollback
213
+ and compatibility rules.
214
+
215
+ Preview retention before deleting normalized metadata:
216
+
217
+ ```bash
218
+ uv run cli-consumption retention --keep-days 90 --database usage.sqlite
219
+ uv run cli-consumption retention --keep-days 90 --database usage.sqlite --apply
220
+ ```
221
+
222
+ The first command is a dry run. `--apply` deletes old conversations and their child
223
+ rows, old subagent relationships, and old ingestion-run records.
224
+
149
225
  ## Central collector API
150
226
 
151
227
  Copied files are simplest for personal or air-gapped use. For recurring collection
@@ -170,6 +246,25 @@ The application refuses to bind beyond localhost without a token. Production
170
246
  deployments also need TLS and standard operational controls. See
171
247
  [Architecture](docs/architecture.md) for the trade-offs.
172
248
 
249
+ Snapshots use strict schema version 1. The collector rejects request bodies larger
250
+ than 32 MiB and snapshots containing more than 250,000 normalized records. A sync
251
+ client checks `/api/v1/capabilities` before sending when the endpoint exposes it.
252
+ Upgrade the server before clients whenever supported snapshot schemas change.
253
+
254
+ ## Provider diagnostics
255
+
256
+ `providers` reads the central adapter registry. Its machine-readable mode checks local
257
+ default stores and emits deterministic JSON:
258
+
259
+ ```bash
260
+ uv run cli-consumption providers --json
261
+ ```
262
+
263
+ Each provider reports one of `no-data`, `detected`, `compatible`, `degraded`, or
264
+ `unsupported-schema`. Diagnostics parse enough metadata to assess compatibility but do
265
+ not persist it and never include paths, identifiers, record contents, counts, or parser
266
+ errors in their output.
267
+
173
268
  ## Commands
174
269
 
175
270
  | Command | Purpose |
@@ -179,13 +274,14 @@ deployments also need TLS and standard operational controls. See
179
274
  | `serve` | Run the central collection API. |
180
275
  | `export` | Write the HTML dashboard and optional CSV tables. |
181
276
  | `providers` | List provider names and support status. |
277
+ | `retention` | Preview or apply deletion of metadata outside a retention window. |
182
278
 
183
279
  Run `uv run cli-consumption COMMAND --help` for all options.
184
280
 
185
281
  ## Development
186
282
 
187
283
  ```bash
188
- uv sync --all-groups
284
+ uv sync --all-extras --all-groups
189
285
  uv run pre-commit install
190
286
  uv run pre-commit run --all-files
191
287
  uv run ruff format --check .
@@ -1,31 +1,3 @@
1
- Metadata-Version: 2.5
2
- Name: cli-consumption
3
- Version: 0.1.0
4
- Summary: Analyze and consolidate AI coding CLI consumption across machines.
5
- Project-URL: Homepage, https://github.com/Guillaume-Lombardo/cli-consumption
6
- Project-URL: Documentation, https://github.com/Guillaume-Lombardo/cli-consumption#readme
7
- Project-URL: Issues, https://github.com/Guillaume-Lombardo/cli-consumption/issues
8
- Project-URL: Repository, https://github.com/Guillaume-Lombardo/cli-consumption.git
9
- Author-email: Guillaume Lombardo <lombardo.guillaume@gmail.com>
10
- License-Expression: Apache-2.0
11
- License-File: LICENSE
12
- License-File: NOTICE
13
- Keywords: ai,cli,codex,observability,tokens,usage
14
- Classifier: Development Status :: 3 - Alpha
15
- Classifier: Environment :: Console
16
- Classifier: License :: OSI Approved :: Apache Software License
17
- Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.14
19
- Classifier: Topic :: Software Development :: Quality Assurance
20
- Requires-Python: >=3.14
21
- Requires-Dist: fastapi>=0.115
22
- Requires-Dist: httpx>=0.27
23
- Requires-Dist: psycopg[binary]>=3.2
24
- Requires-Dist: sqlalchemy>=2.0
25
- Requires-Dist: typer>=0.15
26
- Requires-Dist: uvicorn>=0.34
27
- Description-Content-Type: text/markdown
28
-
29
1
  # CLI Consumption
30
2
 
31
3
  CLI Consumption measures how AI coding CLIs use models, tokens, tools,
@@ -38,14 +10,17 @@ events. Local token counters are usage metadata, not billing records. Read the
38
10
 
39
11
  ## Quick start
40
12
 
41
- CLI Consumption requires Python 3.14 or newer and uses
13
+ CLI Consumption requires Python 3.12 or newer and uses
42
14
  [`uv`](https://docs.astral.sh/uv/).
15
+ Supporting 3.12–3.14 keeps the package usable on more existing development and CI
16
+ images without changing its architecture; the compatibility matrix exercises all
17
+ three versions.
43
18
 
44
19
  From a checkout, collect every supported CLI detected on the machine and generate a
45
20
  self-contained dashboard:
46
21
 
47
22
  ```bash
48
- uv sync
23
+ uv sync --all-extras
49
24
  uv run cli-consumption collect --provider all
50
25
  uv run cli-consumption export --output reports
51
26
  ```
@@ -66,6 +41,12 @@ uv tool run cli-consumption collect --provider all
66
41
  uv tool run cli-consumption export --output reports
67
42
  ```
68
43
 
44
+ The default installation covers local collection, SQLite storage, and exports. Install
45
+ only the optional runtime capabilities you use: `cli-consumption[sync]` for the sync
46
+ client, `cli-consumption[server]` for the collector service, and
47
+ `cli-consumption[postgres]` for PostgreSQL. Extras can be combined, for example
48
+ `cli-consumption[server,postgres]` on a central collector.
49
+
69
50
  To run the latest unreleased GitHub source:
70
51
 
71
52
  ```bash
@@ -95,6 +76,7 @@ Use the provider name below with `--provider` to select one CLI explicitly.
95
76
  | Grok Build | `grok` | `~/.grok/sessions/` | Per-prompt aggregates, reasoning effort, TTFT, and auto-compactions; no costs or subagent relationships. |
96
77
  | Kilo Code | `kilo` | `~/.local/share/kilo/kilo.db` | CLI SQLite store only; excludes legacy IDE tasks, cloud sessions, subagents, context windows, and costs. |
97
78
  | Kimi Code CLI | `kimi` | `~/.kimi/sessions/` | Wire v1 events, context windows, and compactions; selected model is not persisted and is reported as `unknown`. |
79
+ | Mistral Vibe CLI | `mistral-vibe` | `~/.vibe/logs/session/` | Session-level token aggregates, user turns, tools, and compactions; no per-message timestamps or historical model attribution. |
98
80
  | OpenCode | `opencode` | `~/.local/share/opencode/opencode.db` | SQLite v2 only; no legacy storage, child sessions, context windows, or costs. |
99
81
  | OpenHands CLI | `openhands` | `~/.openhands/conversations/` | SDK persistence with context windows, reasoning effort, and condensations; excludes cloud-only conversations and delegates. |
100
82
  | Pi | `pi` | `~/.pi/agent/sessions/` | Counts all persisted branches; no branch relationships, custom-directory auto-detection, context windows, or provider-reported durations. |
@@ -161,6 +143,19 @@ Share-safe reports still disclose aggregate work patterns and remain private
161
143
  operational data. A technically completed turn is not a measure of task quality or
162
144
  productivity.
163
145
 
146
+ Limit an export to conversations whose activity overlaps a half-open UTC window:
147
+
148
+ ```bash
149
+ uv run cli-consumption export --output reports \
150
+ --since 2026-08-01 --until 2026-08-31
151
+ ```
152
+
153
+ Dates denote UTC calendar boundaries; timestamps must include a timezone. An included
154
+ conversation is exported with its complete child graph rather than partially redacted
155
+ to the window. CSV rows are streamed in stable primary-key order. Spreadsheet formula
156
+ prefixes in text cells are neutralized with a leading apostrophe; CSV remains a
157
+ detailed operational-data export, not a share-safe format.
158
+
164
159
  ## SQLite and PostgreSQL
165
160
 
166
161
  A file path selects SQLite. A SQLAlchemy URL selects PostgreSQL:
@@ -174,6 +169,24 @@ uv run cli-consumption collect --provider all \
174
169
  Pass credentials through environment variables or a secret manager rather than shell
175
170
  history. `CLI_CONSUMPTION_DATABASE` can provide the database setting.
176
171
 
172
+ Database schemas are upgraded automatically when a command opens them. Existing
173
+ unversioned databases that exactly match a published schema are adopted before the
174
+ upgrade; unknown or modified schemas are refused. Back up production databases before
175
+ upgrading and do not run mixed application versions against one database while a
176
+ migration is in progress. See the
177
+ [migration decision](docs/decisions/0001-versioned-schema-migrations.md) for rollback
178
+ and compatibility rules.
179
+
180
+ Preview retention before deleting normalized metadata:
181
+
182
+ ```bash
183
+ uv run cli-consumption retention --keep-days 90 --database usage.sqlite
184
+ uv run cli-consumption retention --keep-days 90 --database usage.sqlite --apply
185
+ ```
186
+
187
+ The first command is a dry run. `--apply` deletes old conversations and their child
188
+ rows, old subagent relationships, and old ingestion-run records.
189
+
177
190
  ## Central collector API
178
191
 
179
192
  Copied files are simplest for personal or air-gapped use. For recurring collection
@@ -198,6 +211,25 @@ The application refuses to bind beyond localhost without a token. Production
198
211
  deployments also need TLS and standard operational controls. See
199
212
  [Architecture](docs/architecture.md) for the trade-offs.
200
213
 
214
+ Snapshots use strict schema version 1. The collector rejects request bodies larger
215
+ than 32 MiB and snapshots containing more than 250,000 normalized records. A sync
216
+ client checks `/api/v1/capabilities` before sending when the endpoint exposes it.
217
+ Upgrade the server before clients whenever supported snapshot schemas change.
218
+
219
+ ## Provider diagnostics
220
+
221
+ `providers` reads the central adapter registry. Its machine-readable mode checks local
222
+ default stores and emits deterministic JSON:
223
+
224
+ ```bash
225
+ uv run cli-consumption providers --json
226
+ ```
227
+
228
+ Each provider reports one of `no-data`, `detected`, `compatible`, `degraded`, or
229
+ `unsupported-schema`. Diagnostics parse enough metadata to assess compatibility but do
230
+ not persist it and never include paths, identifiers, record contents, counts, or parser
231
+ errors in their output.
232
+
201
233
  ## Commands
202
234
 
203
235
  | Command | Purpose |
@@ -207,13 +239,14 @@ deployments also need TLS and standard operational controls. See
207
239
  | `serve` | Run the central collection API. |
208
240
  | `export` | Write the HTML dashboard and optional CSV tables. |
209
241
  | `providers` | List provider names and support status. |
242
+ | `retention` | Preview or apply deletion of metadata outside a retention window. |
210
243
 
211
244
  Run `uv run cli-consumption COMMAND --help` for all options.
212
245
 
213
246
  ## Development
214
247
 
215
248
  ```bash
216
- uv sync --all-groups
249
+ uv sync --all-extras --all-groups
217
250
  uv run pre-commit install
218
251
  uv run pre-commit run --all-files
219
252
  uv run ruff format --check .
@@ -0,0 +1,105 @@
1
+ # Architecture
2
+
3
+ ## Goals
4
+
5
+ CLI Consumption separates provider-specific extraction from provider-neutral storage
6
+ and reporting. This lets users compare multiple AI coding CLIs without forcing their
7
+ local formats into one parser.
8
+
9
+ ```text
10
+ provider files -> adapter -> metadata-only snapshot -> SQL storage -> dashboard/CSV
11
+ |
12
+ +-> HTTPS collector -> central SQL storage
13
+ ```
14
+
15
+ ## Components
16
+
17
+ - `adapters`: parse a CLI's local data into conversations, turns, model calls, tool
18
+ calls, context-pressure samples, bounded turn settings, compactions, and content-free
19
+ work-item intervals. Codex exposes the complete analytics contract. Aider, Amazon Q
20
+ Developer CLI, Amp, Cline CLI, Claude Code, Continue CLI, Crush, Cursor CLI, Gemini
21
+ CLI, GitHub Copilot CLI, Goose, Grok Build, Kilo Code, Kimi Code CLI, OpenCode,
22
+ OpenHands CLI, Pi, Plandex, and Qwen Code expose the reliable subset available in
23
+ each local store. The exact differences are maintained in
24
+ [Provider support](provider-support.md).
25
+ - `models`: define the strict, versioned transport boundary shared by offline and API
26
+ ingestion.
27
+ - `storage`, `schema`, and `migrations`: own the normalized schema, idempotent
28
+ replacement rules, automatic Alembic upgrades, legacy adoption, SQLite, and
29
+ PostgreSQL engine creation.
30
+ - `api` and `sync`: offer an optional push workflow for recurring multi-machine use.
31
+ - `dashboard`, `reporting`, and `exporting`: select complete conversation graphs,
32
+ provide an offline HTML view by default, and stream deterministic portable CSV tables
33
+ when explicitly requested.
34
+ - `adapters.registry`: is the single source for canonical names, aliases, adapter
35
+ classes, default homes, detection markers, and support state.
36
+ - `cli`: exposes the same capabilities through one executable.
37
+
38
+ When Codex exposes its local thread graph, the adapter also records metadata-only
39
+ subagent relationships. Agent filesystem paths and nicknames are intentionally
40
+ discarded. Roles and statuses are reduced to fixed provider-neutral vocabularies, and
41
+ the stored conversation `source` is a normalized format label rather than an arbitrary
42
+ provider value.
43
+
44
+ ## Multi-machine alternatives
45
+
46
+ ### Copied files
47
+
48
+ Copy provider metadata directories to a trusted machine and pass repeated `--source`
49
+ options. This has no listening service, works offline, and is easiest to audit. It is
50
+ recommended for personal use, occasional reports, and air-gapped environments.
51
+
52
+ The trade-off is operational: users must schedule copies and keep machine clocks
53
+ synchronized if they later analyze overlapping activity.
54
+
55
+ ### Central API
56
+
57
+ Run `serve` with PostgreSQL and send snapshots using `sync`. Parsing stays on the source
58
+ machine, so raw provider files do not cross the network. This works well for recurring
59
+ collection and several workstations.
60
+
61
+ The API is intentionally small. A bearer token protects ingestion; a production
62
+ deployment still needs TLS, token rotation, backups, monitoring, and a reverse proxy
63
+ or platform ingress. Read access is not exposed. The collector limits bodies to 32 MiB
64
+ including chunked requests, accepts snapshot schema v1, and caps a snapshot at 250,000
65
+ normalized records. `/api/v1/capabilities` publishes these limits and the supported
66
+ schema range so clients can fail before uploading incompatible data.
67
+
68
+ ## Storage
69
+
70
+ SQLite is the zero-configuration default. PostgreSQL is selected by passing a
71
+ `postgresql+psycopg://` URL. Every database open upgrades through packaged Alembic
72
+ migrations. An unversioned database is adopted only when its tables exactly match a
73
+ published schema; an unknown, newer, or locally modified schema is refused. Migration
74
+ revisions support SQLite and PostgreSQL and define a bounded downgrade, but application
75
+ rollback can still require restoring a pre-upgrade backup. Operators must upgrade the
76
+ server first and avoid mixed-version access during migration. The detailed policy is
77
+ recorded in [ADR 0001](decisions/0001-versioned-schema-migrations.md).
78
+
79
+ Conversation records use a provider-qualified stable ID. Repeated ingestion skips an
80
+ identical or less complete record. A more complete copy atomically replaces the
81
+ conversation and its child records.
82
+
83
+ Workflow analytics use additive child tables: `work_items`, `context_samples`,
84
+ `turn_settings`, and `compaction_events`. Snapshot schema v1 validates every record,
85
+ rejects unknown fields, enforces normalized labels and relationships, and exposes only
86
+ generic validation errors. A newer client sent to an older strict API is rejected
87
+ before ingestion, so central deployments must upgrade the server first.
88
+
89
+ Retention is an explicit two-step operation: `retention --keep-days N` reports what
90
+ would be deleted, while `--apply` deletes old conversations (with cascading children),
91
+ subagent relationships, and ingestion runs in one transaction.
92
+
93
+ Time-bounded reporting selects conversations whose recorded activity overlaps the
94
+ half-open `[since, until)` window. Once selected, the complete conversation and all its
95
+ children are included; this is graph consistency, not timestamp-level redaction.
96
+ Related subagent edges are included when either endpoint belongs to a selected
97
+ conversation, while ingestion runs are filtered by their own timestamp. All tables are
98
+ ordered by primary key. CSV output consumes streamed batches rather than materializing
99
+ each table, and neutralizes text that spreadsheet software could execute as a formula.
100
+
101
+ ## Adapter qualification
102
+
103
+ Adapters are introduced one at a time because local data formats are undocumented or
104
+ can evolve independently. Each adapter must have synthetic fixtures, format detection,
105
+ privacy tests, and a documented support level before it appears as supported.
@@ -0,0 +1,50 @@
1
+ # ADR 0001: Versioned schema migrations
2
+
3
+ - Status: Accepted
4
+ - Scope: SQLite and PostgreSQL normalized storage
5
+
6
+ ## Context
7
+
8
+ `create_all` can create missing tables but cannot safely evolve published columns,
9
+ constraints, indexes, or data. CLI Consumption must preserve repeatable ingestion on
10
+ both supported databases while rejecting unknown schemas rather than guessing how to
11
+ modify them.
12
+
13
+ ## Decision
14
+
15
+ Package Alembic revisions with the application and upgrade the database to the known
16
+ head whenever storage is initialized. Every schema change must provide SQLite and
17
+ PostgreSQL coverage, deterministic data conversion, and an explicit downgrade boundary.
18
+
19
+ For databases created before revision tracking, inspect every recognized table before
20
+ adoption. Stamp and migrate only an exact published layout, including explicitly known
21
+ transitional layouts. Refuse databases with unknown columns, missing columns, unknown
22
+ revision heads, or revisions newer than the running application. Do not fall back to
23
+ `create_all` after a compatibility failure.
24
+
25
+ The initial baseline records the published normalized schema. The next migration
26
+ normalizes retained subagent roles and statuses and removes `agent_nickname`, which has
27
+ no required analytical purpose. Its downgrade can recreate the column only with a
28
+ content-free placeholder; it cannot recover discarded nicknames.
29
+
30
+ ## Deployment and rollback
31
+
32
+ Back up a production database before upgrading. Stop or drain writers, deploy and
33
+ initialize the server first, then upgrade sync clients. Do not run mixed application
34
+ versions against a database during migration: an older writer may not understand the
35
+ new layout or replacement semantics.
36
+
37
+ Use the packaged downgrade only to a documented known revision and only after stopping
38
+ newer writers. A schema downgrade does not guarantee application-level recovery when a
39
+ migration deliberately discarded or transformed metadata. Restore the pre-upgrade
40
+ backup when exact rollback is required.
41
+
42
+ ## Consequences
43
+
44
+ - Fresh, legacy SQLite, legacy PostgreSQL, and already-versioned databases follow one
45
+ migration history.
46
+ - Unknown or locally modified schemas fail closed with a generic compatibility error.
47
+ - Releases that change storage must include migration, adoption, idempotency,
48
+ upgrade/downgrade, and both-dialect tests.
49
+ - Operators gain automatic upgrades but remain responsible for backups, writer
50
+ coordination, and retention of those backups.
@@ -11,7 +11,8 @@ CLI Consumption measures activity; it does not archive conversations.
11
11
  - Whitelisted work-item categories, normalized technical status, and timing
12
12
  - Model input-to-context-window samples and bounded provider configuration labels
13
13
  - Timestamped compaction counts without replacement content or window identifiers
14
- - Metadata-only subagent relationships, roles, status, timing, and token counters
14
+ - Metadata-only subagent relationships, normalized roles and status, timing, and token
15
+ counters; provider nicknames are not retained
15
16
  - Content hashes and event counts used only for deduplication
16
17
 
17
18
  ## Prohibited data
@@ -24,6 +25,7 @@ CLI Consumption measures activity; it does not archive conversations.
24
25
  - Commands, exit output, file-change details, MCP arguments/results, and item content
25
26
  - Raw rate-limit, credit, plan, or spend-control payloads
26
27
  - Original working directories and rollout paths in shared exports
28
+ - Provider-supplied subagent nicknames and arbitrary role, status, or source labels
27
29
 
28
30
  Adapters may inspect a working directory transiently to apply an explicit project
29
31
  mapping, but persistence records only the resulting project label and mapping source.
@@ -36,8 +38,12 @@ objects, exit output, commands, paths, patches, messages, and item-specific payl
36
38
  discarded. Context samples persist only the latest model-call input-token count and the
37
39
  reported context-window size; cumulative payloads and rate-limit metadata are ignored.
38
40
  Turn configuration labels accept only bounded identifier-like values. Snapshot
39
- validation rejects unknown work categories, arbitrary statuses, malformed timestamps,
40
- out-of-range counters, and unconstrained analytics labels before opening a transaction.
41
+ validation rejects unknown fields, unknown work categories, arbitrary roles or
42
+ statuses, malformed timestamps, inconsistent token compositions, out-of-range
43
+ counters, unconstrained analytics labels, broken relationships, snapshots above
44
+ 250,000 records, and API requests above 32 MiB before opening a transaction. Errors
45
+ use generic codes and do not echo rejected values. Snapshot schema v1 is advertised by
46
+ the collector capabilities endpoint so an incompatible client can stop before upload.
41
47
 
42
48
  ## Threat model
43
49
 
@@ -68,3 +74,22 @@ pseudonymized per-turn rows remain embedded so local filtering works. Provider n
68
74
  daily activity, durations, counts, token counters, configuration labels, statuses, and
69
75
  aggregate work patterns remain disclosed. Share-safe is a minimization profile, not
70
76
  anonymization.
77
+
78
+ Time filters select complete conversations that overlap the requested window. They do
79
+ not redact child records whose individual timestamps fall outside it; related subagent
80
+ edges can also reveal activity around the boundary. Ingestion-run rows are selected by
81
+ their own timestamp. CSV output neutralizes leading spreadsheet formula and control
82
+ prefixes with an apostrophe, but still contains detailed normalized operational data.
83
+
84
+ Provider diagnostics inspect local stores transiently and emit only provider name,
85
+ documented aliases, support state, and one coarse compatibility status. They do not
86
+ persist snapshots or reveal paths, conversation identifiers, record counts, malformed
87
+ values, or exception text.
88
+
89
+ Retention removes normalized rows, not provider source files, existing exports,
90
+ database backups, database engine logs, reverse-proxy logs, or snapshots already sent
91
+ elsewhere. A dry run reports aggregate deletion counts; `--apply` is required to
92
+ delete. Operators remain responsible for retention and secure disposal of those
93
+ residual copies. Project names, machine labels, model/tool names, stable IDs,
94
+ timestamps, and activity aggregates remain sensitive wherever normalized databases or
95
+ detailed CSV files survive.