cli-consumption 0.3.0__tar.gz → 0.3.2__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 (60) hide show
  1. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/CHANGELOG.md +53 -1
  2. cli_consumption-0.3.2/PKG-INFO +198 -0
  3. cli_consumption-0.3.2/README.md +161 -0
  4. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/pyproject.toml +22 -5
  5. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/_shared.py +4 -1
  6. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/opencode.py +253 -84
  7. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/registry.py +184 -0
  8. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/api.py +24 -3
  9. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/cli.py +217 -19
  10. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/dashboard.py +21 -21
  11. cli_consumption-0.3.2/src/cli_consumption/dashboard_calculations.js +543 -0
  12. cli_consumption-0.3.2/src/cli_consumption/exporting.py +117 -0
  13. cli_consumption-0.3.2/src/cli_consumption/migrations/versions/v0005_sync_receipts.py +38 -0
  14. cli_consumption-0.3.2/src/cli_consumption/qualifications.py +97 -0
  15. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/schema.py +35 -9
  16. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/storage.py +161 -90
  17. cli_consumption-0.3.2/src/cli_consumption/sync.py +169 -0
  18. cli_consumption-0.3.0/PKG-INFO +0 -368
  19. cli_consumption-0.3.0/README.md +0 -332
  20. cli_consumption-0.3.0/src/cli_consumption/exporting.py +0 -51
  21. cli_consumption-0.3.0/src/cli_consumption/sync.py +0 -80
  22. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/.gitignore +0 -0
  23. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/LICENSE +0 -0
  24. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/NOTICE +0 -0
  25. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/__init__.py +0 -0
  26. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/__main__.py +0 -0
  27. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/__init__.py +0 -0
  28. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/aider.py +0 -0
  29. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/amazon_q.py +0 -0
  30. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/amp.py +0 -0
  31. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/base.py +0 -0
  32. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/claude.py +0 -0
  33. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/cline.py +0 -0
  34. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/codex.py +0 -0
  35. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/continue_cli.py +0 -0
  36. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/copilot.py +0 -0
  37. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/crush.py +0 -0
  38. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/cursor.py +0 -0
  39. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/gemini.py +0 -0
  40. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/goose.py +0 -0
  41. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/grok.py +0 -0
  42. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/kilo.py +0 -0
  43. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/kimi.py +0 -0
  44. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/mistral_vibe.py +0 -0
  45. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/openhands.py +0 -0
  46. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/pi.py +0 -0
  47. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/plandex.py +0 -0
  48. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/adapters/qwen.py +0 -0
  49. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/migrations/__init__.py +0 -0
  50. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/migrations/env.py +0 -0
  51. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/migrations/versions/__init__.py +0 -0
  52. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/migrations/versions/v0001_baseline.py +0 -0
  53. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/migrations/versions/v0002_minimize_subagents.py +0 -0
  54. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/migrations/versions/v0003_canonical_timestamps.py +0 -0
  55. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/migrations/versions/v0004_subagent_scope_freshness.py +0 -0
  56. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/models.py +0 -0
  57. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/py.typed +0 -0
  58. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/reporting.py +0 -0
  59. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/retention.py +0 -0
  60. {cli_consumption-0.3.0 → cli_consumption-0.3.2}/src/cli_consumption/timestamps.py +0 -0
@@ -6,6 +6,56 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.3.2] - 2026-08-31
10
+
11
+ ### Changed
12
+
13
+ - Version releases now attach the validated wheel and source distribution to an
14
+ automatically generated GitHub Release after PyPI publication succeeds.
15
+
16
+ ### Fixed
17
+
18
+ - OpenCode 1.18.23 SQLite stores now extract model calls and token usage from
19
+ `message.data` and tool calls from `part.data`; incomplete current schemas are
20
+ reported as incompatible instead of silently producing zero usage.
21
+
22
+ ## [0.3.1] - 2026-08-31
23
+
24
+ ### Changed
25
+
26
+ - Python 3.11 is now supported and tested alongside Python 3.12, 3.13, and 3.14.
27
+ - Collection errors now distinguish provider limits, incompatible formats, invalid
28
+ snapshots, and unexpected adapter failures with privacy-safe human messages and
29
+ deterministic JSON codes.
30
+ - A pinned, privacy-preserving single-host production deployment example now covers
31
+ the central collector, PostgreSQL, and automatic TLS proxy operations.
32
+ - The README now leads with a reproducible synthetic dashboard preview and routes
33
+ operational and provider-qualification detail to dedicated guides.
34
+ - CI now performs scheduled Python security, locked dependency, and offline workflow
35
+ audits; third-party actions are pinned to immutable commits with least privileges.
36
+ - Provider adapters now carry auditable format qualification metadata backed by
37
+ synthetic fixtures, with a weekly check that flags qualifications older than 90
38
+ days and homogeneous privacy-minimized compatibility criteria.
39
+ - Linear is now the source of truth for new repository tasks and their progress, while
40
+ the roadmap remains focused on durable product direction.
41
+ - Dashboard token totals now include conversation aggregates and latest-context
42
+ snapshots for conversations overlapping the selected period, with explicit labels
43
+ distinguishing them from additive usage.
44
+ - Dashboard selection, period, aggregation, percentile, and comparison calculations
45
+ now use an independently tested JavaScript contract embedded in the offline report.
46
+ - Each detailed CSV export now uses a synchronized temporary file and atomic
47
+ replacement, preserving that table's previous file when generation fails early.
48
+ - Multi-provider sync now reuses one HTTP client, negotiates capabilities once, and
49
+ performs bounded idempotent retries when the collector advertises replay receipts.
50
+ - Sync automation now supports strict preflight refusal and deterministic JSON with
51
+ malformed/duplicate diagnostics, explicit partial success, and generic remote
52
+ errors that do not expose response or provider content.
53
+
54
+ ### Fixed
55
+
56
+ - Reject timezone-naive provider timestamps instead of interpreting them in the host
57
+ timezone.
58
+
9
59
  ## [0.3.0] - 2026-08-29
10
60
 
11
61
  ### Added
@@ -65,7 +115,9 @@ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
65
115
 
66
116
  - Refreshed the provider guide for the first minor release ([#26]).
67
117
 
68
- [Unreleased]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.3.0...HEAD
118
+ [Unreleased]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.3.2...HEAD
119
+ [0.3.2]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.3.1...v0.3.2
120
+ [0.3.1]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.3.0...v0.3.1
69
121
  [0.3.0]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.2.1...v0.3.0
70
122
  [0.2.1]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.2.0...v0.2.1
71
123
  [0.2.0]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.1.1...v0.2.0
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.5
2
+ Name: cli-consumption
3
+ Version: 0.3.2
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: Changelog, https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/CHANGELOG.md
8
+ Project-URL: Issues, https://github.com/Guillaume-Lombardo/cli-consumption/issues
9
+ Project-URL: Repository, https://github.com/Guillaume-Lombardo/cli-consumption.git
10
+ Author-email: Guillaume Lombardo <lombardo.guillaume@gmail.com>
11
+ License-Expression: Apache-2.0
12
+ License-File: LICENSE
13
+ License-File: NOTICE
14
+ Keywords: ai,cli,codex,observability,tokens,usage
15
+ Classifier: Development Status :: 3 - Alpha
16
+ Classifier: Environment :: Console
17
+ Classifier: License :: OSI Approved :: Apache Software License
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Classifier: Topic :: Software Development :: Quality Assurance
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: alembic>=1.14
26
+ Requires-Dist: pydantic>=2.10
27
+ Requires-Dist: sqlalchemy>=2.0
28
+ Requires-Dist: typer>=0.15
29
+ Provides-Extra: postgres
30
+ Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
31
+ Provides-Extra: server
32
+ Requires-Dist: fastapi>=0.115; extra == 'server'
33
+ Requires-Dist: uvicorn>=0.34; extra == 'server'
34
+ Provides-Extra: sync
35
+ Requires-Dist: httpx>=0.27; extra == 'sync'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # CLI Consumption
39
+
40
+ CLI Consumption turns local AI coding CLI metadata into one private, self-contained
41
+ view of models, tokens, tools, conversations, turns, context pressure, and workflow
42
+ health. It can consolidate trusted offline copies from several machines or send
43
+ metadata-only snapshots to a central collector.
44
+
45
+ It never stores prompts, responses, tool arguments, credentials, or raw provider
46
+ events. Local token counters are usage metadata, not billing records. Read the
47
+ [privacy boundary](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
48
+ before sharing a database or report.
49
+
50
+ [![Synthetic CLI Consumption dashboard](https://raw.githubusercontent.com/Guillaume-Lombardo/cli-consumption/main/docs/demo/dashboard.png)](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/demo/dashboard.html)
51
+
52
+ The preview and
53
+ [self-contained demo dashboard](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/demo/dashboard.html)
54
+ contain only
55
+ deterministic synthetic records. Rebuild the HTML with:
56
+
57
+ ```bash
58
+ uv run python docs/demo/generate.py
59
+ ```
60
+
61
+ The generator never reads provider directories and creates its temporary SQLite
62
+ database outside the repository. The demo HTML, image, documentation, tests, and other
63
+ repository assets are excluded from Python distribution artifacts.
64
+
65
+ ## Installation
66
+
67
+ CLI Consumption requires Python 3.11 or newer. Run it directly from PyPI with `uv`:
68
+
69
+ ```bash
70
+ uv tool run cli-consumption providers
71
+ ```
72
+
73
+ The default package covers local collection, SQLite storage, and exports. Install only
74
+ the optional runtime capabilities you use:
75
+
76
+ - `cli-consumption[sync]` for the sync client;
77
+ - `cli-consumption[server]` for the collector service;
78
+ - `cli-consumption[postgres]` for PostgreSQL.
79
+
80
+ Extras can be combined, for example `cli-consumption[server,postgres]` on a central
81
+ collector.
82
+
83
+ ## Quick start
84
+
85
+ From a checkout, detect supported local CLIs, collect their metadata, and create an
86
+ offline dashboard:
87
+
88
+ ```bash
89
+ uv sync --all-extras
90
+ uv run cli-consumption collect --provider all
91
+ uv run cli-consumption export --output reports
92
+ ```
93
+
94
+ Open `reports/dashboard.html` locally. It makes no network requests. Detailed CSV
95
+ tables are generated only when `--csv` is passed.
96
+
97
+ To collect one provider or select another database:
98
+
99
+ ```bash
100
+ uv run cli-consumption collect --provider codex --database usage.sqlite
101
+ ```
102
+
103
+ Use `--source [LABEL=]PATH` for trusted offline copies and repeated
104
+ `--project NAME=PATH_PREFIX` mappings for stable project labels. See the
105
+ [usage and operations guide](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/usage.md)
106
+ for multi-machine collection, reporting,
107
+ PostgreSQL, retention, synchronization, readiness, and automation.
108
+
109
+ ## Supported CLIs
110
+
111
+ The current registry supports Aider, Amazon Q Developer CLI, Amp, Claude Code, Cline,
112
+ Codex, Continue, Crush, Cursor CLI, Gemini CLI, GitHub Copilot CLI, Goose, Grok Build,
113
+ Kilo Code, Kimi Code CLI, Mistral Vibe CLI, OpenCode, OpenHands CLI, Pi, Plandex, and
114
+ Qwen Code.
115
+
116
+ Provider formats are internal and can change without notice. Exact source locations,
117
+ token semantics, extraction limits, synthetic qualification fixtures, provenance, and
118
+ known gaps live in the
119
+ [provider support ledger](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/provider-support.md).
120
+ Inspect the
121
+ local registry without exposing paths or content:
122
+
123
+ ```bash
124
+ uv run cli-consumption providers --json
125
+ ```
126
+
127
+ ## Essential limits
128
+
129
+ - Provider files are untrusted. Collection enforces discovery, file, line, SQLite row,
130
+ structured-field, and total normalized-record limits; direct provider-file symlinks
131
+ are refused.
132
+ - `collect --strict` and `sync --strict` refuse a batch when any provider skipped
133
+ malformed records. Collection distinguishes `provider_limit_exceeded`,
134
+ `provider_format_incompatible`, `invalid_snapshot`, and the unexpected-failure
135
+ fallback `provider_collection_failed`; machine-readable results use these fixed codes
136
+ without paths, payloads, response bodies, tokens, or exception text.
137
+ - Dashboards are self-contained and network-free. Share-safe mode pseudonymizes
138
+ labels, groups tools, rounds timestamps, and hides small cohorts, but still exposes
139
+ aggregate work patterns.
140
+ - CSV and normalized databases remain detailed private operational data. Never treat a
141
+ technically completed turn as a measure of quality or productivity.
142
+ - Central collection requires TLS, token rotation, backups, limits, monitoring, and a
143
+ reverse proxy. The application does not replace those operator controls.
144
+
145
+ See [Privacy](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
146
+ for the exact data boundary and
147
+ [Architecture](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/architecture.md)
148
+ for ingestion, idempotency, migrations, report limits, and collector behavior.
149
+
150
+ ## Commands
151
+
152
+ | Command | Purpose |
153
+ | --- | --- |
154
+ | `collect` | Collect local or copied provider data into SQL. |
155
+ | `sync` | Collect and send metadata-only snapshots to a central API. |
156
+ | `serve` | Run the central collection API. |
157
+ | `export` | Write the HTML dashboard and optional CSV tables. |
158
+ | `providers` | List provider names and compatibility status. |
159
+ | `retention` | Preview or apply deletion outside a retention window. |
160
+
161
+ Run `uv run cli-consumption COMMAND --help` for every option. The
162
+ [usage guide](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/usage.md)
163
+ contains copy-ready examples.
164
+
165
+ ## Documentation
166
+
167
+ - [Usage and operations](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/usage.md)
168
+ - [Production deployment](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/deployment.md)
169
+ - [Provider support and qualification](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/provider-support.md)
170
+ - [Privacy boundary](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
171
+ - [Architecture](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/architecture.md)
172
+ - [Roadmap](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/roadmap.md)
173
+ - [Contributing](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/CONTRIBUTING.md)
174
+ - [Security policy](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/SECURITY.md)
175
+
176
+ ## Development
177
+
178
+ ```bash
179
+ uv sync --all-extras --all-groups
180
+ uv run pre-commit install
181
+ uv run pre-commit run --all-files
182
+ uv run ruff format --check .
183
+ uv run ruff check .
184
+ uv run ty check
185
+ uv run pytest --cov --cov-report=term-missing
186
+ uv build
187
+ ```
188
+
189
+ Development uses short-lived branches and squash-merged pull requests into protected
190
+ `main`. Read
191
+ [CONTRIBUTING.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/CONTRIBUTING.md)
192
+ and [AGENTS.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/AGENTS.md)
193
+ before changing the project.
194
+
195
+ ## License
196
+
197
+ Licensed under the
198
+ [Apache License 2.0](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/LICENSE).
@@ -0,0 +1,161 @@
1
+ # CLI Consumption
2
+
3
+ CLI Consumption turns local AI coding CLI metadata into one private, self-contained
4
+ view of models, tokens, tools, conversations, turns, context pressure, and workflow
5
+ health. It can consolidate trusted offline copies from several machines or send
6
+ metadata-only snapshots to a central collector.
7
+
8
+ It never stores prompts, responses, tool arguments, credentials, or raw provider
9
+ events. Local token counters are usage metadata, not billing records. Read the
10
+ [privacy boundary](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
11
+ before sharing a database or report.
12
+
13
+ [![Synthetic CLI Consumption dashboard](https://raw.githubusercontent.com/Guillaume-Lombardo/cli-consumption/main/docs/demo/dashboard.png)](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/demo/dashboard.html)
14
+
15
+ The preview and
16
+ [self-contained demo dashboard](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/demo/dashboard.html)
17
+ contain only
18
+ deterministic synthetic records. Rebuild the HTML with:
19
+
20
+ ```bash
21
+ uv run python docs/demo/generate.py
22
+ ```
23
+
24
+ The generator never reads provider directories and creates its temporary SQLite
25
+ database outside the repository. The demo HTML, image, documentation, tests, and other
26
+ repository assets are excluded from Python distribution artifacts.
27
+
28
+ ## Installation
29
+
30
+ CLI Consumption requires Python 3.11 or newer. Run it directly from PyPI with `uv`:
31
+
32
+ ```bash
33
+ uv tool run cli-consumption providers
34
+ ```
35
+
36
+ The default package covers local collection, SQLite storage, and exports. Install only
37
+ the optional runtime capabilities you use:
38
+
39
+ - `cli-consumption[sync]` for the sync client;
40
+ - `cli-consumption[server]` for the collector service;
41
+ - `cli-consumption[postgres]` for PostgreSQL.
42
+
43
+ Extras can be combined, for example `cli-consumption[server,postgres]` on a central
44
+ collector.
45
+
46
+ ## Quick start
47
+
48
+ From a checkout, detect supported local CLIs, collect their metadata, and create an
49
+ offline dashboard:
50
+
51
+ ```bash
52
+ uv sync --all-extras
53
+ uv run cli-consumption collect --provider all
54
+ uv run cli-consumption export --output reports
55
+ ```
56
+
57
+ Open `reports/dashboard.html` locally. It makes no network requests. Detailed CSV
58
+ tables are generated only when `--csv` is passed.
59
+
60
+ To collect one provider or select another database:
61
+
62
+ ```bash
63
+ uv run cli-consumption collect --provider codex --database usage.sqlite
64
+ ```
65
+
66
+ Use `--source [LABEL=]PATH` for trusted offline copies and repeated
67
+ `--project NAME=PATH_PREFIX` mappings for stable project labels. See the
68
+ [usage and operations guide](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/usage.md)
69
+ for multi-machine collection, reporting,
70
+ PostgreSQL, retention, synchronization, readiness, and automation.
71
+
72
+ ## Supported CLIs
73
+
74
+ The current registry supports Aider, Amazon Q Developer CLI, Amp, Claude Code, Cline,
75
+ Codex, Continue, Crush, Cursor CLI, Gemini CLI, GitHub Copilot CLI, Goose, Grok Build,
76
+ Kilo Code, Kimi Code CLI, Mistral Vibe CLI, OpenCode, OpenHands CLI, Pi, Plandex, and
77
+ Qwen Code.
78
+
79
+ Provider formats are internal and can change without notice. Exact source locations,
80
+ token semantics, extraction limits, synthetic qualification fixtures, provenance, and
81
+ known gaps live in the
82
+ [provider support ledger](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/provider-support.md).
83
+ Inspect the
84
+ local registry without exposing paths or content:
85
+
86
+ ```bash
87
+ uv run cli-consumption providers --json
88
+ ```
89
+
90
+ ## Essential limits
91
+
92
+ - Provider files are untrusted. Collection enforces discovery, file, line, SQLite row,
93
+ structured-field, and total normalized-record limits; direct provider-file symlinks
94
+ are refused.
95
+ - `collect --strict` and `sync --strict` refuse a batch when any provider skipped
96
+ malformed records. Collection distinguishes `provider_limit_exceeded`,
97
+ `provider_format_incompatible`, `invalid_snapshot`, and the unexpected-failure
98
+ fallback `provider_collection_failed`; machine-readable results use these fixed codes
99
+ without paths, payloads, response bodies, tokens, or exception text.
100
+ - Dashboards are self-contained and network-free. Share-safe mode pseudonymizes
101
+ labels, groups tools, rounds timestamps, and hides small cohorts, but still exposes
102
+ aggregate work patterns.
103
+ - CSV and normalized databases remain detailed private operational data. Never treat a
104
+ technically completed turn as a measure of quality or productivity.
105
+ - Central collection requires TLS, token rotation, backups, limits, monitoring, and a
106
+ reverse proxy. The application does not replace those operator controls.
107
+
108
+ See [Privacy](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
109
+ for the exact data boundary and
110
+ [Architecture](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/architecture.md)
111
+ for ingestion, idempotency, migrations, report limits, and collector behavior.
112
+
113
+ ## Commands
114
+
115
+ | Command | Purpose |
116
+ | --- | --- |
117
+ | `collect` | Collect local or copied provider data into SQL. |
118
+ | `sync` | Collect and send metadata-only snapshots to a central API. |
119
+ | `serve` | Run the central collection API. |
120
+ | `export` | Write the HTML dashboard and optional CSV tables. |
121
+ | `providers` | List provider names and compatibility status. |
122
+ | `retention` | Preview or apply deletion outside a retention window. |
123
+
124
+ Run `uv run cli-consumption COMMAND --help` for every option. The
125
+ [usage guide](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/usage.md)
126
+ contains copy-ready examples.
127
+
128
+ ## Documentation
129
+
130
+ - [Usage and operations](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/usage.md)
131
+ - [Production deployment](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/deployment.md)
132
+ - [Provider support and qualification](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/provider-support.md)
133
+ - [Privacy boundary](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
134
+ - [Architecture](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/architecture.md)
135
+ - [Roadmap](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/roadmap.md)
136
+ - [Contributing](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/CONTRIBUTING.md)
137
+ - [Security policy](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/SECURITY.md)
138
+
139
+ ## Development
140
+
141
+ ```bash
142
+ uv sync --all-extras --all-groups
143
+ uv run pre-commit install
144
+ uv run pre-commit run --all-files
145
+ uv run ruff format --check .
146
+ uv run ruff check .
147
+ uv run ty check
148
+ uv run pytest --cov --cov-report=term-missing
149
+ uv build
150
+ ```
151
+
152
+ Development uses short-lived branches and squash-merged pull requests into protected
153
+ `main`. Read
154
+ [CONTRIBUTING.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/CONTRIBUTING.md)
155
+ and [AGENTS.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/AGENTS.md)
156
+ before changing the project.
157
+
158
+ ## License
159
+
160
+ Licensed under the
161
+ [Apache License 2.0](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/LICENSE).
@@ -4,10 +4,10 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cli-consumption"
7
- version = "0.3.0"
7
+ version = "0.3.2"
8
8
  description = "Analyze and consolidate AI coding CLI consumption across machines."
9
9
  readme = "README.md"
10
- requires-python = ">=3.12"
10
+ requires-python = ">=3.11"
11
11
  license = "Apache-2.0"
12
12
  license-files = ["LICENSE", "NOTICE"]
13
13
  authors = [{ name = "Guillaume Lombardo", email = "lombardo.guillaume@gmail.com" }]
@@ -17,6 +17,7 @@ classifiers = [
17
17
  "Environment :: Console",
18
18
  "License :: OSI Approved :: Apache Software License",
19
19
  "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
20
21
  "Programming Language :: Python :: 3.12",
21
22
  "Programming Language :: Python :: 3.13",
22
23
  "Programming Language :: Python :: 3.14",
@@ -49,6 +50,7 @@ dev = [
49
50
  "fastapi>=0.115",
50
51
  "httpx>=0.27",
51
52
  "hypothesis>=6.165.10",
53
+ "pip-audit>=2.10.1",
52
54
  "pre-commit>=4.6.2",
53
55
  "psycopg[binary]>=3.2",
54
56
  "pytest>=8.3",
@@ -56,6 +58,7 @@ dev = [
56
58
  "ruff>=0.11",
57
59
  "ty>=0.0.74",
58
60
  "uvicorn>=0.34",
61
+ "zizmor>=1.29.0",
59
62
  ]
60
63
 
61
64
  [tool.hatch.build.targets.wheel]
@@ -86,10 +89,24 @@ show_missing = true
86
89
 
87
90
  [tool.ruff]
88
91
  line-length = 88
89
- target-version = "py312"
92
+ target-version = "py311"
90
93
 
91
94
  [tool.ruff.lint]
92
- select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
95
+ select = ["E", "F", "I", "UP", "B", "SIM", "RUF", "S"]
93
96
 
94
97
  [tool.ruff.lint.per-file-ignores]
95
- "src/cli_consumption/dashboard.py" = ["E501"]
98
+ "src/cli_consumption/adapters/_shared.py" = ["S608"]
99
+ "src/cli_consumption/adapters/cline.py" = ["S608"]
100
+ "src/cli_consumption/adapters/crush.py" = ["S608"]
101
+ "src/cli_consumption/adapters/kilo.py" = ["S608"]
102
+ "src/cli_consumption/adapters/opencode.py" = ["S608"]
103
+ "src/cli_consumption/adapters/registry.py" = ["S105", "S106"]
104
+ "src/cli_consumption/api.py" = ["S608"]
105
+ "src/cli_consumption/cli.py" = ["S107"]
106
+ "src/cli_consumption/dashboard.py" = ["E501", "S608"]
107
+ "tests/**" = ["S101"]
108
+ "tests/smoke_minimal_install.py" = ["S603", "S607"]
109
+ "tests/test_codex_adapter.py" = ["S608"]
110
+ "tests/test_dashboard_calculations.py" = ["S607"]
111
+ "tests/test_demo.py" = ["S603"]
112
+ "tests/test_packaging.py" = ["S603", "S607"]
@@ -144,7 +144,10 @@ def timestamp(value: object) -> datetime | None:
144
144
  scale = 1000 if abs(value) > 10_000_000_000 else 1
145
145
  return datetime.fromtimestamp(value / scale, UTC)
146
146
  if isinstance(value, str) and value:
147
- return datetime.fromisoformat(value.replace("Z", "+00:00")).astimezone(UTC)
147
+ parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
148
+ if parsed.tzinfo is None or parsed.utcoffset() is None:
149
+ return None
150
+ return parsed.astimezone(UTC)
148
151
  except (OSError, OverflowError, ValueError):
149
152
  pass
150
153
  return None