cli-consumption 0.2.0__tar.gz → 0.3.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.3.0/CHANGELOG.md +84 -0
  2. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/PKG-INFO +104 -36
  3. cli_consumption-0.3.0/README.md +332 -0
  4. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/pyproject.toml +15 -1
  5. cli_consumption-0.3.0/src/cli_consumption/adapters/_shared.py +418 -0
  6. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/aider.py +44 -40
  7. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/amazon_q.py +16 -10
  8. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/amp.py +29 -40
  9. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/claude.py +41 -49
  10. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/cline.py +27 -14
  11. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/codex.py +53 -38
  12. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/continue_cli.py +26 -20
  13. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/copilot.py +32 -30
  14. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/crush.py +69 -74
  15. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/cursor.py +35 -26
  16. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/gemini.py +48 -55
  17. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/goose.py +66 -69
  18. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/grok.py +30 -28
  19. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/kilo.py +65 -72
  20. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/kimi.py +9 -4
  21. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/mistral_vibe.py +26 -20
  22. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/opencode.py +50 -66
  23. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/openhands.py +34 -44
  24. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/pi.py +39 -58
  25. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/plandex.py +12 -5
  26. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/qwen.py +36 -46
  27. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/registry.py +141 -16
  28. cli_consumption-0.3.0/src/cli_consumption/api.py +463 -0
  29. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/cli.py +141 -23
  30. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/dashboard.py +572 -233
  31. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/exporting.py +0 -4
  32. cli_consumption-0.3.0/src/cli_consumption/migrations/versions/v0003_canonical_timestamps.py +94 -0
  33. cli_consumption-0.3.0/src/cli_consumption/migrations/versions/v0004_subagent_scope_freshness.py +38 -0
  34. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/models.py +70 -11
  35. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/reporting.py +90 -30
  36. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/retention.py +10 -14
  37. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/schema.py +184 -12
  38. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/storage.py +109 -28
  39. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/sync.py +25 -0
  40. cli_consumption-0.3.0/src/cli_consumption/timestamps.py +17 -0
  41. cli_consumption-0.2.0/.agents/skills/add-cli-adapter/SKILL.md +0 -21
  42. cli_consumption-0.2.0/.agents/skills/add-cli-adapter/agents/openai.yaml +0 -4
  43. cli_consumption-0.2.0/.agents/skills/audit-usage-privacy/SKILL.md +0 -22
  44. cli_consumption-0.2.0/.agents/skills/audit-usage-privacy/agents/openai.yaml +0 -4
  45. cli_consumption-0.2.0/.agents/skills/evolve-storage-schema/SKILL.md +0 -21
  46. cli_consumption-0.2.0/.agents/skills/evolve-storage-schema/agents/openai.yaml +0 -4
  47. cli_consumption-0.2.0/.agents/skills/yeet-github/SKILL.md +0 -66
  48. cli_consumption-0.2.0/.agents/skills/yeet-github/agents/openai.yaml +0 -4
  49. cli_consumption-0.2.0/.agents/skills/yolo/SKILL.md +0 -50
  50. cli_consumption-0.2.0/.agents/skills/yolo/agents/openai.yaml +0 -4
  51. cli_consumption-0.2.0/.github/workflows/ci.yml +0 -64
  52. cli_consumption-0.2.0/.github/workflows/release.yaml +0 -154
  53. cli_consumption-0.2.0/.pre-commit-config.yaml +0 -35
  54. cli_consumption-0.2.0/.python-version +0 -1
  55. cli_consumption-0.2.0/AGENTS.md +0 -68
  56. cli_consumption-0.2.0/CONTRIBUTING.md +0 -50
  57. cli_consumption-0.2.0/README.md +0 -265
  58. cli_consumption-0.2.0/docs/architecture.md +0 -105
  59. cli_consumption-0.2.0/docs/decisions/0001-versioned-schema-migrations.md +0 -50
  60. cli_consumption-0.2.0/docs/privacy.md +0 -95
  61. cli_consumption-0.2.0/docs/provider-support.md +0 -419
  62. cli_consumption-0.2.0/docs/roadmap.md +0 -28
  63. cli_consumption-0.2.0/src/cli_consumption/adapters/_shared.py +0 -141
  64. cli_consumption-0.2.0/src/cli_consumption/api.py +0 -143
  65. cli_consumption-0.2.0/tests/conftest.py +0 -133
  66. cli_consumption-0.2.0/tests/smoke_minimal_install.py +0 -69
  67. cli_consumption-0.2.0/tests/test_aider_adapter.py +0 -204
  68. cli_consumption-0.2.0/tests/test_amazon_q_adapter.py +0 -67
  69. cli_consumption-0.2.0/tests/test_amp_adapter.py +0 -257
  70. cli_consumption-0.2.0/tests/test_api.py +0 -160
  71. cli_consumption-0.2.0/tests/test_claude_adapter.py +0 -218
  72. cli_consumption-0.2.0/tests/test_cli.py +0 -1083
  73. cli_consumption-0.2.0/tests/test_cline_adapter.py +0 -102
  74. cli_consumption-0.2.0/tests/test_codex_adapter.py +0 -256
  75. cli_consumption-0.2.0/tests/test_continue_adapter.py +0 -266
  76. cli_consumption-0.2.0/tests/test_copilot_adapter.py +0 -348
  77. cli_consumption-0.2.0/tests/test_crush_adapter.py +0 -304
  78. cli_consumption-0.2.0/tests/test_cursor_adapter.py +0 -230
  79. cli_consumption-0.2.0/tests/test_exporting.py +0 -85
  80. cli_consumption-0.2.0/tests/test_gemini_adapter.py +0 -275
  81. cli_consumption-0.2.0/tests/test_goose_adapter.py +0 -269
  82. cli_consumption-0.2.0/tests/test_grok_adapter.py +0 -304
  83. cli_consumption-0.2.0/tests/test_kilo_adapter.py +0 -292
  84. cli_consumption-0.2.0/tests/test_kimi_adapter.py +0 -82
  85. cli_consumption-0.2.0/tests/test_migrations_and_retention.py +0 -530
  86. cli_consumption-0.2.0/tests/test_mistral_vibe_adapter.py +0 -207
  87. cli_consumption-0.2.0/tests/test_opencode_adapter.py +0 -261
  88. cli_consumption-0.2.0/tests/test_openhands_adapter.py +0 -313
  89. cli_consumption-0.2.0/tests/test_packaging.py +0 -26
  90. cli_consumption-0.2.0/tests/test_pi_adapter.py +0 -287
  91. cli_consumption-0.2.0/tests/test_plandex_adapter.py +0 -68
  92. cli_consumption-0.2.0/tests/test_provider_registry.py +0 -158
  93. cli_consumption-0.2.0/tests/test_qwen_adapter.py +0 -295
  94. cli_consumption-0.2.0/tests/test_reporting.py +0 -240
  95. cli_consumption-0.2.0/tests/test_snapshot_contract.py +0 -75
  96. cli_consumption-0.2.0/tests/test_storage_and_exports.py +0 -301
  97. cli_consumption-0.2.0/tests/test_sync.py +0 -60
  98. cli_consumption-0.2.0/uv.lock +0 -987
  99. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/.gitignore +0 -0
  100. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/LICENSE +0 -0
  101. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/NOTICE +0 -0
  102. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/__init__.py +0 -0
  103. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/__main__.py +0 -0
  104. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/__init__.py +0 -0
  105. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/base.py +0 -0
  106. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/__init__.py +0 -0
  107. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/env.py +0 -0
  108. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/versions/__init__.py +0 -0
  109. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/versions/v0001_baseline.py +0 -0
  110. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/versions/v0002_minimize_subagents.py +0 -0
  111. {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/py.typed +0 -0
@@ -0,0 +1,84 @@
1
+ # Changelog
2
+
3
+ Notable user-visible changes to CLI Consumption are documented in this file. The
4
+ format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases
5
+ use [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.3.0] - 2026-08-29
10
+
11
+ ### Added
12
+
13
+ - Added privacy-safe database readiness checks and bounded request correlation for the
14
+ collector service ([#35]).
15
+
16
+ ### Changed
17
+
18
+ - Provider input processing now enforces cumulative discovery, byte, SQLite row, and
19
+ structured-field limits across a complete collection ([#31]).
20
+ - Dashboard generation now preflights bounded selections, streams its output, and
21
+ atomically replaces an existing report only after a successful write ([#32]).
22
+ - Concurrent schema initialization, upgrade, and downgrade are now serialized on
23
+ SQLite and PostgreSQL, with SQLite lock waits capped at 15 seconds ([#34]).
24
+ - Published source distributions exclude repository-only tests and automation while
25
+ retaining release metadata, the changelog and README, license notices, the runtime
26
+ package, and Hatchling's rebuild `.gitignore` ([#33]).
27
+ - Identical adapter primitives are shared while provider-specific parsing semantics
28
+ remain isolated ([#36]).
29
+
30
+ ### Fixed
31
+
32
+ - Older, identical, graph-only, and partially stale snapshots can no longer erase a
33
+ newer subagent relationship graph ([#30]).
34
+
35
+ ## [0.2.1] - 2026-08-29
36
+
37
+ ### Changed
38
+
39
+ - Hardened ingestion privacy and normalized persisted timestamps to canonical,
40
+ fixed-width UTC values ([#29]).
41
+
42
+ ## [0.2.0] - 2026-08-29
43
+
44
+ ### Added
45
+
46
+ - Added versioned SQLite and PostgreSQL schema migrations, retention previews, and a
47
+ metadata-only central collector and synchronization client ([#28]).
48
+ - Added streamed CSV exports, time-window selection, and a share-safe dashboard
49
+ profile ([#28]).
50
+
51
+ ### Changed
52
+
53
+ - Strengthened snapshot validation, transport defaults, storage deduplication, and
54
+ privacy regression coverage ([#28]).
55
+
56
+ ## [0.1.1] - 2026-08-27
57
+
58
+ ### Added
59
+
60
+ - Added the Mistral Vibe CLI adapter ([#27]).
61
+
62
+ ## [0.1.0] - 2026-08-27
63
+
64
+ ### Changed
65
+
66
+ - Refreshed the provider guide for the first minor release ([#26]).
67
+
68
+ [Unreleased]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.3.0...HEAD
69
+ [0.3.0]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.2.1...v0.3.0
70
+ [0.2.1]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.2.0...v0.2.1
71
+ [0.2.0]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.1.1...v0.2.0
72
+ [0.1.1]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.1.0...v0.1.1
73
+ [0.1.0]: https://github.com/Guillaume-Lombardo/cli-consumption/compare/v0.0.18...v0.1.0
74
+ [#26]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/26
75
+ [#27]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/27
76
+ [#28]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/28
77
+ [#29]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/29
78
+ [#30]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/30
79
+ [#31]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/31
80
+ [#32]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/32
81
+ [#33]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/33
82
+ [#34]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/34
83
+ [#35]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/35
84
+ [#36]: https://github.com/Guillaume-Lombardo/cli-consumption/pull/36
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cli-consumption
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Analyze and consolidate AI coding CLI consumption across machines.
5
5
  Project-URL: Homepage, https://github.com/Guillaume-Lombardo/cli-consumption
6
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
7
8
  Project-URL: Issues, https://github.com/Guillaume-Lombardo/cli-consumption/issues
8
9
  Project-URL: Repository, https://github.com/Guillaume-Lombardo/cli-consumption.git
9
10
  Author-email: Guillaume Lombardo <lombardo.guillaume@gmail.com>
@@ -41,7 +42,8 @@ machines, and can send metadata-only snapshots to a central collector.
41
42
 
42
43
  It never stores prompts, responses, tool arguments, credentials, or raw provider
43
44
  events. Local token counters are usage metadata, not billing records. Read the
44
- [privacy boundary](docs/privacy.md) before sharing a database or report.
45
+ [privacy boundary](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
46
+ before sharing a database or report.
45
47
 
46
48
  ## Quick start
47
49
 
@@ -94,33 +96,33 @@ uv tool run --from git+https://github.com/Guillaume-Lombardo/cli-consumption \
94
96
  `--provider all` detects the supported data stores found in their default locations.
95
97
  Use the provider name below with `--provider` to select one CLI explicitly.
96
98
 
97
- | CLI | Provider name | Default local source | Particularities and limits |
98
- | --- | --- | --- | --- |
99
- | Aider | `aider` | `~/.aider/analytics.jsonl` | Requires opt-in analytics logging; no projects, tools, cache/reasoning split, or provider-reported durations. |
100
- | Amazon Q Developer CLI | `amazon-q` | `~/.local/share/amazon-q/data.sqlite3` | Persistent conversations only; request timing is available, but token counters are not. |
101
- | Amp | `amp` | `~/.local/share/amp/threads/` | Per-inference tokens and context windows; no subthreads, compactions, reasoning split, or latency. |
102
- | Claude Code | `claude` | `~/.claude/projects/` | Main sessions, tokens, tools, and compactions; no subagents, context windows, or provider-reported durations. `claude-code` is accepted as an alias. |
103
- | Cline CLI | `cline` | `~/.cline/data/sessions/sessions.db` | Uses the session index and message artifacts; no costs or arbitrary task metadata. |
104
- | Codex | `codex` | `~/.codex/sessions/` | Richest support: timing, context pressure, settings, compactions, work items, and subagent relationships. |
105
- | Continue CLI | `continue` | `~/.continue/sessions/` | Token usage when present; session files lack reliable per-message timing and duration. |
106
- | Crush | `crush` | `~/.local/share/crush/` | Reads registered per-project SQLite stores; token counters are a latest-context snapshot, not additive usage. |
107
- | Cursor CLI | `cursor` | `~/.cursor/` | Composer 2 transcripts and chat metadata; no per-message time or tokens, and model attribution is incomplete. |
108
- | Gemini CLI | `gemini` | `~/.gemini/tmp/` | Replays active history and rewinds; hashed projects are not reversed and nested agents are excluded. |
109
- | GitHub Copilot CLI | `copilot` | `~/.copilot/session-state/` | Tokens are latest shutdown aggregates and cannot be assigned to individual turns. |
110
- | Goose | `goose` | `~/.local/share/goose/sessions/sessions.db` | Supports SQLite schema v16; no legacy JSONL, subagents, reasoning tokens, or latency. |
111
- | Grok Build | `grok` | `~/.grok/sessions/` | Per-prompt aggregates, reasoning effort, TTFT, and auto-compactions; no costs or subagent relationships. |
112
- | Kilo Code | `kilo` | `~/.local/share/kilo/kilo.db` | CLI SQLite store only; excludes legacy IDE tasks, cloud sessions, subagents, context windows, and costs. |
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. |
115
- | OpenCode | `opencode` | `~/.local/share/opencode/opencode.db` | SQLite v2 only; no legacy storage, child sessions, context windows, or costs. |
116
- | OpenHands CLI | `openhands` | `~/.openhands/conversations/` | SDK persistence with context windows, reasoning effort, and condensations; excludes cloud-only conversations and delegates. |
117
- | Pi | `pi` | `~/.pi/agent/sessions/` | Counts all persisted branches; no branch relationships, custom-directory auto-detection, context windows, or provider-reported durations. |
118
- | Plandex | `plandex` | `/plandex-server` | Requires an offline copy of a self-hosted `PLANDEX_BASE_DIR`; hosted accounts are not accessed, and models/tools are unavailable. |
119
- | Qwen Code | `qwen` | `~/.qwen/projects/` | Follows the active branch and records context windows and compactions; excludes archived and sidechain sessions. |
99
+ | CLI | Provider name | Aliases | Default local source | Token semantics | Particularities and limits |
100
+ | --- | --- | --- | --- | --- | --- |
101
+ | Aider | `aider` | — | `~/.aider/analytics.jsonl` | `additive` | Requires opt-in analytics logging; no projects, tools, cache/reasoning split, or provider-reported durations. |
102
+ | Amazon Q Developer CLI | `amazon-q` | — | `~/.local/share/amazon-q/data.sqlite3` | `unavailable` | Persistent conversations only; request timing is available, but token counters are not. |
103
+ | Amp | `amp` | — | `~/.local/share/amp/threads/` | `additive` | Per-inference tokens and context windows; no subthreads, compactions, reasoning split, or latency. |
104
+ | Claude Code | `claude` | `claude-code` | `~/.claude/projects/` | `additive` | Main sessions, tokens, tools, and compactions; no subagents, context windows, or provider-reported durations. |
105
+ | Cline CLI | `cline` | — | `~/.cline/data/sessions/sessions.db` | `additive` | Uses the session index and message artifacts; no costs or arbitrary task metadata. |
106
+ | Codex | `codex` | — | `~/.codex/sessions/` | `additive` | Richest support: timing, context pressure, settings, compactions, work items, and subagent relationships. |
107
+ | Continue CLI | `continue` | — | `~/.continue/sessions/` | `additive` | Token usage when present; session files lack reliable per-message timing and duration. |
108
+ | Crush | `crush` | — | `~/.local/share/crush/` | `context-snapshot` | Reads registered per-project SQLite stores; token counters are a latest-context snapshot, not additive usage. |
109
+ | Cursor CLI | `cursor` | — | `~/.cursor/` | `unavailable` | Composer 2 transcripts and chat metadata; no per-message time or tokens, and model attribution is incomplete. |
110
+ | Gemini CLI | `gemini` | — | `~/.gemini/tmp/` | `additive` | Replays active history and rewinds; hashed projects are not reversed and nested agents are excluded. |
111
+ | GitHub Copilot CLI | `copilot` | — | `~/.copilot/session-state/` | `conversation-aggregate` | Tokens are latest shutdown aggregates and cannot be assigned to individual turns. |
112
+ | Goose | `goose` | — | `~/.local/share/goose/sessions/sessions.db` | `additive` | Supports SQLite schema v16; no legacy JSONL, subagents, reasoning tokens, or latency. |
113
+ | Grok Build | `grok` | — | `~/.grok/sessions/` | `additive` | Per-prompt aggregates, reasoning effort, TTFT, and auto-compactions; no costs or subagent relationships. |
114
+ | Kilo Code | `kilo` | — | `~/.local/share/kilo/kilo.db` | `additive` | CLI SQLite store only; excludes legacy IDE tasks, cloud sessions, subagents, context windows, and costs. |
115
+ | Kimi Code CLI | `kimi` | — | `~/.kimi/sessions/` | `additive` | Wire v1 events, context windows, and compactions; selected model is not persisted and is reported as `unknown`. |
116
+ | Mistral Vibe CLI | `mistral-vibe` | — | `~/.vibe/logs/session/` | `conversation-aggregate` | Session-level token aggregates, user turns, tools, and compactions; no per-message timestamps or historical model attribution. |
117
+ | OpenCode | `opencode` | — | `~/.local/share/opencode/opencode.db` | `additive` | SQLite v2 only; no legacy storage, child sessions, context windows, or costs. |
118
+ | OpenHands CLI | `openhands` | — | `~/.openhands/conversations/` | `additive` | SDK persistence with context windows, reasoning effort, and condensations; excludes cloud-only conversations and delegates. |
119
+ | Pi | `pi` | — | `~/.pi/agent/sessions/` | `additive` | Counts all persisted branches; no branch relationships, custom-directory auto-detection, context windows, or provider-reported durations. |
120
+ | Plandex | `plandex` | — | `/plandex-server` | `additive` | Requires an offline copy of a self-hosted `PLANDEX_BASE_DIR`; hosted accounts are not accessed, and models/tools are unavailable. |
121
+ | Qwen Code | `qwen` | — | `~/.qwen/projects/` | `additive` | Follows the active branch and records context windows and compactions; excludes archived and sidechain sessions. |
120
122
 
121
123
  Provider formats are internal and can change without notice. The detailed extraction
122
124
  rules and qualification versions are documented in
123
- [Provider support](docs/provider-support.md).
125
+ [Provider support](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/provider-support.md).
124
126
 
125
127
  ## Collect copied data
126
128
 
@@ -140,7 +142,19 @@ uv run cli-consumption collect --provider codex \
140
142
 
141
143
  Copy only the required provider data. For Codex, copy the `sessions/` directory but
142
144
  never `auth.json` or other credentials. Globally identical conversation IDs are
143
- deduplicated, and the most complete copy wins.
145
+ deduplicated, and the most complete copy wins. After a subagent scope is first seen,
146
+ its relationship graph is replaced only when at least one conversation from that
147
+ provider and source machine is strictly more complete and none is less complete.
148
+ Identical, graph-only, or older copies cannot erase a newer graph.
149
+
150
+ Provider files are untrusted. Monolithic JSON files are limited to 64 MiB, JSONL files
151
+ to 256 MiB with an 8 MiB per-line limit, 512 MiB of provider-file bytes actually read,
152
+ and discovery to 10,000 candidate entries per provider collection. Provider SQLite
153
+ inputs share a cumulative 512 MiB limit across databases and active WAL, SHM, or
154
+ journal sidecars, plus 250,000 selected rows, 8 MiB per structured field, and 256 MiB
155
+ across structured fields. A snapshot is limited to 250,000 normalized records while it
156
+ is being built. Direct provider-file symlinks are refused. `collect --strict` refuses
157
+ to write a snapshot when malformed records were skipped.
144
158
 
145
159
  Map original working-directory prefixes to stable project labels with repeated
146
160
  `--project NAME=PATH_PREFIX` options. The longest matching prefix wins:
@@ -163,7 +177,7 @@ uv run cli-consumption collect --provider plandex \
163
177
 
164
178
  The dashboard can filter by time, provider, machine, project, and model. It reports
165
179
  activity, token composition, cache efficiency, latency and duration distributions,
166
- technical throughput, context pressure, work-item reliability, configuration cohorts,
180
+ turn rate, context pressure, work-item reliability, configuration cohorts,
167
181
  compactions, subagent delegation, and ingestion quality. Availability varies by
168
182
  provider, as summarized in the table above.
169
183
 
@@ -191,6 +205,19 @@ to the window. CSV rows are streamed in stable primary-key order. Spreadsheet fo
191
205
  prefixes in text cells are neutralized with a leading apostrophe; CSV remains a
192
206
  detailed operational-data export, not a share-safe format.
193
207
 
208
+ Dashboard generation preflights the selected report before streaming its tables. The
209
+ selection is limited to 250,000 rows and 128 MiB of selected scalar values, and the
210
+ final self-contained HTML is limited to 128 MiB of bytes actually encoded. If an
211
+ accumulated database exceeds these limits, narrow it with `--since` and/or `--until`.
212
+ A dashboard is streamed through a temporary file in its destination directory,
213
+ synchronized, and atomically replaces an older dashboard only after generation
214
+ succeeds.
215
+
216
+ When `--csv` and the dashboard are requested together, each CSV is still streamed
217
+ before dashboard generation. The dashboard file is atomic, but the output directory
218
+ as a whole is not: a dashboard limit or write failure can leave newly written CSV
219
+ files alongside the preserved older dashboard.
220
+
194
221
  ## SQLite and PostgreSQL
195
222
 
196
223
  A file path selects SQLite. A SQLAlchemy URL selects PostgreSQL:
@@ -209,8 +236,18 @@ unversioned databases that exactly match a published schema are adopted before t
209
236
  upgrade; unknown or modified schemas are refused. Back up production databases before
210
237
  upgrading and do not run mixed application versions against one database while a
211
238
  migration is in progress. See the
212
- [migration decision](docs/decisions/0001-versioned-schema-migrations.md) for rollback
213
- and compatibility rules.
239
+ [migration decision](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/decisions/0001-versioned-schema-migrations.md)
240
+ for rollback and compatibility rules.
241
+
242
+ Timezone-aware timestamps are normalized to fixed-width UTC strings during ingestion.
243
+ Revision `0003` rewrites legacy timestamp text in bounded batches and adds an indexed
244
+ conversation end-time path; see the
245
+ [timestamp decision](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/decisions/0002-canonical-utc-timestamps.md)
246
+ for the exact representation and downgrade boundary.
247
+
248
+ Revision `0004` adds internal per-scope state that serializes subagent graph freshness
249
+ decisions. It does not add snapshot or export fields; see the
250
+ [subagent freshness decision](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/decisions/0003-subagent-scope-freshness.md).
214
251
 
215
252
  Preview retention before deleting normalized metadata:
216
253
 
@@ -221,6 +258,9 @@ uv run cli-consumption retention --keep-days 90 --database usage.sqlite --apply
221
258
 
222
259
  The first command is a dry run. `--apply` deletes old conversations and their child
223
260
  rows, old subagent relationships, and old ingestion-run records.
261
+ Internal subagent-scope coordination rows remain as replay guards, so an older
262
+ graph-only copy cannot recreate relationships after retention. They contain only the
263
+ provider, source-machine label, and a lock counter and are never exported.
224
264
 
225
265
  ## Central collector API
226
266
 
@@ -243,8 +283,26 @@ uv run cli-consumption sync --provider all \
243
283
  ```
244
284
 
245
285
  The application refuses to bind beyond localhost without a token. Production
246
- deployments also need TLS and standard operational controls. See
247
- [Architecture](docs/architecture.md) for the trade-offs.
286
+ deployments also need TLS and standard operational controls. The sync client refuses
287
+ plain HTTP beyond loopback unless `--allow-insecure` is passed explicitly. See
288
+ [Architecture](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/architecture.md) for the trade-offs.
289
+
290
+ Use `GET /health` as the process liveness probe; it never opens the database. Use
291
+ `GET /ready` as the traffic readiness probe; it returns `200` only when the database
292
+ is reachable and its schema is the expected revision, otherwise a generic `503`.
293
+ The readiness path uses one fixed schema query and returns within a two-second
294
+ application deadline. PostgreSQL uses a separate unpooled engine with connection and
295
+ server-side timeouts configured at startup; SQLite lock waiting is capped at 1.5
296
+ seconds. If a network stack ignores its connection timeout, the single daemon probe
297
+ may continue after the response, but no second probe or connection starts until it
298
+ finishes. Configure the orchestrator probe timeout slightly above two seconds as an
299
+ independent safeguard.
300
+ Both endpoints are intentionally unauthenticated so infrastructure probes can call
301
+ them, and every HTTP response carries a bounded `X-Request-ID`. Put the collector
302
+ behind a TLS-terminating reverse proxy or platform ingress. Configure request rate
303
+ limits, connection limits, trusted proxy headers, and access-log redaction there; the
304
+ application does not implement a second rate limiter and disables Uvicorn access logs
305
+ to avoid recording untrusted URLs or query strings.
248
306
 
249
307
  Snapshots use strict schema version 1. The collector rejects request bodies larger
250
308
  than 32 MiB and snapshots containing more than 250,000 normalized records. A sync
@@ -263,7 +321,10 @@ uv run cli-consumption providers --json
263
321
  Each provider reports one of `no-data`, `detected`, `compatible`, `degraded`, or
264
322
  `unsupported-schema`. Diagnostics parse enough metadata to assess compatibility but do
265
323
  not persist it and never include paths, identifiers, record contents, counts, or parser
266
- errors in their output.
324
+ errors in their output. Schema version 2 also declares whether token counters are
325
+ additive, conversation aggregates, context snapshots, or unavailable. Dashboard token
326
+ per-turn percentiles use only additive providers rather than treating missing measures
327
+ as zero.
267
328
 
268
329
  ## Commands
269
330
 
@@ -278,6 +339,10 @@ errors in their output.
278
339
 
279
340
  Run `uv run cli-consumption COMMAND --help` for all options.
280
341
 
342
+ `collect`, `export`, and `retention` accept `--json` for deterministic
343
+ machine-readable results. `collect --strict` rejects snapshots containing malformed
344
+ provider records before opening the destination database.
345
+
281
346
  ## Development
282
347
 
283
348
  ```bash
@@ -292,9 +357,12 @@ uv build
292
357
  ```
293
358
 
294
359
  Development uses short-lived branches and squash-merged pull requests into protected
295
- `main`. Read [CONTRIBUTING.md](CONTRIBUTING.md) and [AGENTS.md](AGENTS.md) before
296
- changing the project.
360
+ `main`. Read
361
+ [CONTRIBUTING.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/CONTRIBUTING.md)
362
+ and [AGENTS.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/AGENTS.md)
363
+ before changing the project. Security issues follow the private reporting guidance in
364
+ [SECURITY.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/SECURITY.md).
297
365
 
298
366
  ## License
299
367
 
300
- Licensed under the [Apache License 2.0](LICENSE).
368
+ Licensed under the [Apache License 2.0](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/LICENSE).
@@ -0,0 +1,332 @@
1
+ # CLI Consumption
2
+
3
+ CLI Consumption measures how AI coding CLIs use models, tokens, tools,
4
+ conversations, and turns. It runs locally, can consolidate copied data from several
5
+ machines, and can send metadata-only snapshots to a central collector.
6
+
7
+ It never stores prompts, responses, tool arguments, credentials, or raw provider
8
+ events. Local token counters are usage metadata, not billing records. Read the
9
+ [privacy boundary](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/privacy.md)
10
+ before sharing a database or report.
11
+
12
+ ## Quick start
13
+
14
+ CLI Consumption requires Python 3.12 or newer and uses
15
+ [`uv`](https://docs.astral.sh/uv/).
16
+ Supporting 3.12–3.14 keeps the package usable on more existing development and CI
17
+ images without changing its architecture; the compatibility matrix exercises all
18
+ three versions.
19
+
20
+ From a checkout, collect every supported CLI detected on the machine and generate a
21
+ self-contained dashboard:
22
+
23
+ ```bash
24
+ uv sync --all-extras
25
+ uv run cli-consumption collect --provider all
26
+ uv run cli-consumption export --output reports
27
+ ```
28
+
29
+ Open `reports/dashboard.html` locally. It makes no network requests. Detailed
30
+ normalized CSV tables are generated only when `--csv` is passed.
31
+
32
+ To collect a single CLI, use its provider name. For example, with Codex:
33
+
34
+ ```bash
35
+ uv run cli-consumption collect --provider codex --database usage.sqlite
36
+ ```
37
+
38
+ From PyPI, no permanent installation is required:
39
+
40
+ ```bash
41
+ uv tool run cli-consumption collect --provider all
42
+ uv tool run cli-consumption export --output reports
43
+ ```
44
+
45
+ The default installation covers local collection, SQLite storage, and exports. Install
46
+ only the optional runtime capabilities you use: `cli-consumption[sync]` for the sync
47
+ client, `cli-consumption[server]` for the collector service, and
48
+ `cli-consumption[postgres]` for PostgreSQL. Extras can be combined, for example
49
+ `cli-consumption[server,postgres]` on a central collector.
50
+
51
+ To run the latest unreleased GitHub source:
52
+
53
+ ```bash
54
+ uv tool run --from git+https://github.com/Guillaume-Lombardo/cli-consumption \
55
+ cli-consumption providers
56
+ ```
57
+
58
+ ## Supported CLIs
59
+
60
+ `--provider all` detects the supported data stores found in their default locations.
61
+ Use the provider name below with `--provider` to select one CLI explicitly.
62
+
63
+ | CLI | Provider name | Aliases | Default local source | Token semantics | Particularities and limits |
64
+ | --- | --- | --- | --- | --- | --- |
65
+ | Aider | `aider` | — | `~/.aider/analytics.jsonl` | `additive` | Requires opt-in analytics logging; no projects, tools, cache/reasoning split, or provider-reported durations. |
66
+ | Amazon Q Developer CLI | `amazon-q` | — | `~/.local/share/amazon-q/data.sqlite3` | `unavailable` | Persistent conversations only; request timing is available, but token counters are not. |
67
+ | Amp | `amp` | — | `~/.local/share/amp/threads/` | `additive` | Per-inference tokens and context windows; no subthreads, compactions, reasoning split, or latency. |
68
+ | Claude Code | `claude` | `claude-code` | `~/.claude/projects/` | `additive` | Main sessions, tokens, tools, and compactions; no subagents, context windows, or provider-reported durations. |
69
+ | Cline CLI | `cline` | — | `~/.cline/data/sessions/sessions.db` | `additive` | Uses the session index and message artifacts; no costs or arbitrary task metadata. |
70
+ | Codex | `codex` | — | `~/.codex/sessions/` | `additive` | Richest support: timing, context pressure, settings, compactions, work items, and subagent relationships. |
71
+ | Continue CLI | `continue` | — | `~/.continue/sessions/` | `additive` | Token usage when present; session files lack reliable per-message timing and duration. |
72
+ | Crush | `crush` | — | `~/.local/share/crush/` | `context-snapshot` | Reads registered per-project SQLite stores; token counters are a latest-context snapshot, not additive usage. |
73
+ | Cursor CLI | `cursor` | — | `~/.cursor/` | `unavailable` | Composer 2 transcripts and chat metadata; no per-message time or tokens, and model attribution is incomplete. |
74
+ | Gemini CLI | `gemini` | — | `~/.gemini/tmp/` | `additive` | Replays active history and rewinds; hashed projects are not reversed and nested agents are excluded. |
75
+ | GitHub Copilot CLI | `copilot` | — | `~/.copilot/session-state/` | `conversation-aggregate` | Tokens are latest shutdown aggregates and cannot be assigned to individual turns. |
76
+ | Goose | `goose` | — | `~/.local/share/goose/sessions/sessions.db` | `additive` | Supports SQLite schema v16; no legacy JSONL, subagents, reasoning tokens, or latency. |
77
+ | Grok Build | `grok` | — | `~/.grok/sessions/` | `additive` | Per-prompt aggregates, reasoning effort, TTFT, and auto-compactions; no costs or subagent relationships. |
78
+ | Kilo Code | `kilo` | — | `~/.local/share/kilo/kilo.db` | `additive` | CLI SQLite store only; excludes legacy IDE tasks, cloud sessions, subagents, context windows, and costs. |
79
+ | Kimi Code CLI | `kimi` | — | `~/.kimi/sessions/` | `additive` | Wire v1 events, context windows, and compactions; selected model is not persisted and is reported as `unknown`. |
80
+ | Mistral Vibe CLI | `mistral-vibe` | — | `~/.vibe/logs/session/` | `conversation-aggregate` | Session-level token aggregates, user turns, tools, and compactions; no per-message timestamps or historical model attribution. |
81
+ | OpenCode | `opencode` | — | `~/.local/share/opencode/opencode.db` | `additive` | SQLite v2 only; no legacy storage, child sessions, context windows, or costs. |
82
+ | OpenHands CLI | `openhands` | — | `~/.openhands/conversations/` | `additive` | SDK persistence with context windows, reasoning effort, and condensations; excludes cloud-only conversations and delegates. |
83
+ | Pi | `pi` | — | `~/.pi/agent/sessions/` | `additive` | Counts all persisted branches; no branch relationships, custom-directory auto-detection, context windows, or provider-reported durations. |
84
+ | Plandex | `plandex` | — | `/plandex-server` | `additive` | Requires an offline copy of a self-hosted `PLANDEX_BASE_DIR`; hosted accounts are not accessed, and models/tools are unavailable. |
85
+ | Qwen Code | `qwen` | — | `~/.qwen/projects/` | `additive` | Follows the active branch and records context windows and compactions; excludes archived and sidechain sessions. |
86
+
87
+ Provider formats are internal and can change without notice. The detailed extraction
88
+ rules and qualification versions are documented in
89
+ [Provider support](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/provider-support.md).
90
+
91
+ ## Collect copied data
92
+
93
+ `--source [LABEL=]PATH` points to a provider home directory and can be repeated. With
94
+ `--provider all`, each path is inspected and unmatched sources are rejected. With one
95
+ provider selected, each path must contain that provider's expected store.
96
+
97
+ For example, consolidate trusted copies of Codex data from several machines:
98
+
99
+ ```bash
100
+ uv run cli-consumption collect --provider codex \
101
+ --source desktop=/data/codex/desktop \
102
+ --source laptop=/data/codex/laptop \
103
+ --source server=/data/codex/server \
104
+ --database usage.sqlite
105
+ ```
106
+
107
+ Copy only the required provider data. For Codex, copy the `sessions/` directory but
108
+ never `auth.json` or other credentials. Globally identical conversation IDs are
109
+ deduplicated, and the most complete copy wins. After a subagent scope is first seen,
110
+ its relationship graph is replaced only when at least one conversation from that
111
+ provider and source machine is strictly more complete and none is less complete.
112
+ Identical, graph-only, or older copies cannot erase a newer graph.
113
+
114
+ Provider files are untrusted. Monolithic JSON files are limited to 64 MiB, JSONL files
115
+ to 256 MiB with an 8 MiB per-line limit, 512 MiB of provider-file bytes actually read,
116
+ and discovery to 10,000 candidate entries per provider collection. Provider SQLite
117
+ inputs share a cumulative 512 MiB limit across databases and active WAL, SHM, or
118
+ journal sidecars, plus 250,000 selected rows, 8 MiB per structured field, and 256 MiB
119
+ across structured fields. A snapshot is limited to 250,000 normalized records while it
120
+ is being built. Direct provider-file symlinks are refused. `collect --strict` refuses
121
+ to write a snapshot when malformed records were skipped.
122
+
123
+ Map original working-directory prefixes to stable project labels with repeated
124
+ `--project NAME=PATH_PREFIX` options. The longest matching prefix wins:
125
+
126
+ ```bash
127
+ uv run cli-consumption collect --provider codex \
128
+ --source desktop=/data/codex/desktop \
129
+ --project cli-consumption=/home/me/dev/cli-consumption
130
+ ```
131
+
132
+ Plandex auto-detection checks `/plandex-server`. For any other trusted offline copy of
133
+ a self-hosted server data directory, pass the path explicitly:
134
+
135
+ ```bash
136
+ uv run cli-consumption collect --provider plandex \
137
+ --source server=/srv/plandex-server --database usage.sqlite
138
+ ```
139
+
140
+ ## Explore and share reports
141
+
142
+ The dashboard can filter by time, provider, machine, project, and model. It reports
143
+ activity, token composition, cache efficiency, latency and duration distributions,
144
+ turn rate, context pressure, work-item reliability, configuration cohorts,
145
+ compactions, subagent delegation, and ingestion quality. Availability varies by
146
+ provider, as summarized in the table above.
147
+
148
+ Generate a more shareable dashboard by pseudonymizing labels, grouping tool names,
149
+ rounding timestamps to days, and hiding small cohort rows:
150
+
151
+ ```bash
152
+ uv run cli-consumption export --output shared-report --share-safe
153
+ ```
154
+
155
+ Share-safe reports still disclose aggregate work patterns and remain private
156
+ operational data. A technically completed turn is not a measure of task quality or
157
+ productivity.
158
+
159
+ Limit an export to conversations whose activity overlaps a half-open UTC window:
160
+
161
+ ```bash
162
+ uv run cli-consumption export --output reports \
163
+ --since 2026-08-01 --until 2026-08-31
164
+ ```
165
+
166
+ Dates denote UTC calendar boundaries; timestamps must include a timezone. An included
167
+ conversation is exported with its complete child graph rather than partially redacted
168
+ to the window. CSV rows are streamed in stable primary-key order. Spreadsheet formula
169
+ prefixes in text cells are neutralized with a leading apostrophe; CSV remains a
170
+ detailed operational-data export, not a share-safe format.
171
+
172
+ Dashboard generation preflights the selected report before streaming its tables. The
173
+ selection is limited to 250,000 rows and 128 MiB of selected scalar values, and the
174
+ final self-contained HTML is limited to 128 MiB of bytes actually encoded. If an
175
+ accumulated database exceeds these limits, narrow it with `--since` and/or `--until`.
176
+ A dashboard is streamed through a temporary file in its destination directory,
177
+ synchronized, and atomically replaces an older dashboard only after generation
178
+ succeeds.
179
+
180
+ When `--csv` and the dashboard are requested together, each CSV is still streamed
181
+ before dashboard generation. The dashboard file is atomic, but the output directory
182
+ as a whole is not: a dashboard limit or write failure can leave newly written CSV
183
+ files alongside the preserved older dashboard.
184
+
185
+ ## SQLite and PostgreSQL
186
+
187
+ A file path selects SQLite. A SQLAlchemy URL selects PostgreSQL:
188
+
189
+ ```bash
190
+ uv run cli-consumption collect --provider all --database usage.sqlite
191
+ uv run cli-consumption collect --provider all \
192
+ --database postgresql+psycopg://usage@localhost/cli_consumption
193
+ ```
194
+
195
+ Pass credentials through environment variables or a secret manager rather than shell
196
+ history. `CLI_CONSUMPTION_DATABASE` can provide the database setting.
197
+
198
+ Database schemas are upgraded automatically when a command opens them. Existing
199
+ unversioned databases that exactly match a published schema are adopted before the
200
+ upgrade; unknown or modified schemas are refused. Back up production databases before
201
+ upgrading and do not run mixed application versions against one database while a
202
+ migration is in progress. See the
203
+ [migration decision](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/decisions/0001-versioned-schema-migrations.md)
204
+ for rollback and compatibility rules.
205
+
206
+ Timezone-aware timestamps are normalized to fixed-width UTC strings during ingestion.
207
+ Revision `0003` rewrites legacy timestamp text in bounded batches and adds an indexed
208
+ conversation end-time path; see the
209
+ [timestamp decision](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/decisions/0002-canonical-utc-timestamps.md)
210
+ for the exact representation and downgrade boundary.
211
+
212
+ Revision `0004` adds internal per-scope state that serializes subagent graph freshness
213
+ decisions. It does not add snapshot or export fields; see the
214
+ [subagent freshness decision](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/decisions/0003-subagent-scope-freshness.md).
215
+
216
+ Preview retention before deleting normalized metadata:
217
+
218
+ ```bash
219
+ uv run cli-consumption retention --keep-days 90 --database usage.sqlite
220
+ uv run cli-consumption retention --keep-days 90 --database usage.sqlite --apply
221
+ ```
222
+
223
+ The first command is a dry run. `--apply` deletes old conversations and their child
224
+ rows, old subagent relationships, and old ingestion-run records.
225
+ Internal subagent-scope coordination rows remain as replay guards, so an older
226
+ graph-only copy cannot recreate relationships after retention. They contain only the
227
+ provider, source-machine label, and a lock counter and are never exported.
228
+
229
+ ## Central collector API
230
+
231
+ Copied files are simplest for personal or air-gapped use. For recurring collection
232
+ across machines, start the metadata-only API:
233
+
234
+ ```bash
235
+ export CLI_CONSUMPTION_API_TOKEN="$(your-secret-provider)"
236
+ uv run cli-consumption serve \
237
+ --database postgresql+psycopg://usage@localhost/cli_consumption \
238
+ --host 0.0.0.0
239
+ ```
240
+
241
+ Then send all locally detected snapshots from another machine:
242
+
243
+ ```bash
244
+ export CLI_CONSUMPTION_API_TOKEN="$(your-secret-provider)"
245
+ uv run cli-consumption sync --provider all \
246
+ --endpoint https://usage.example.test
247
+ ```
248
+
249
+ The application refuses to bind beyond localhost without a token. Production
250
+ deployments also need TLS and standard operational controls. The sync client refuses
251
+ plain HTTP beyond loopback unless `--allow-insecure` is passed explicitly. See
252
+ [Architecture](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/docs/architecture.md) for the trade-offs.
253
+
254
+ Use `GET /health` as the process liveness probe; it never opens the database. Use
255
+ `GET /ready` as the traffic readiness probe; it returns `200` only when the database
256
+ is reachable and its schema is the expected revision, otherwise a generic `503`.
257
+ The readiness path uses one fixed schema query and returns within a two-second
258
+ application deadline. PostgreSQL uses a separate unpooled engine with connection and
259
+ server-side timeouts configured at startup; SQLite lock waiting is capped at 1.5
260
+ seconds. If a network stack ignores its connection timeout, the single daemon probe
261
+ may continue after the response, but no second probe or connection starts until it
262
+ finishes. Configure the orchestrator probe timeout slightly above two seconds as an
263
+ independent safeguard.
264
+ Both endpoints are intentionally unauthenticated so infrastructure probes can call
265
+ them, and every HTTP response carries a bounded `X-Request-ID`. Put the collector
266
+ behind a TLS-terminating reverse proxy or platform ingress. Configure request rate
267
+ limits, connection limits, trusted proxy headers, and access-log redaction there; the
268
+ application does not implement a second rate limiter and disables Uvicorn access logs
269
+ to avoid recording untrusted URLs or query strings.
270
+
271
+ Snapshots use strict schema version 1. The collector rejects request bodies larger
272
+ than 32 MiB and snapshots containing more than 250,000 normalized records. A sync
273
+ client checks `/api/v1/capabilities` before sending when the endpoint exposes it.
274
+ Upgrade the server before clients whenever supported snapshot schemas change.
275
+
276
+ ## Provider diagnostics
277
+
278
+ `providers` reads the central adapter registry. Its machine-readable mode checks local
279
+ default stores and emits deterministic JSON:
280
+
281
+ ```bash
282
+ uv run cli-consumption providers --json
283
+ ```
284
+
285
+ Each provider reports one of `no-data`, `detected`, `compatible`, `degraded`, or
286
+ `unsupported-schema`. Diagnostics parse enough metadata to assess compatibility but do
287
+ not persist it and never include paths, identifiers, record contents, counts, or parser
288
+ errors in their output. Schema version 2 also declares whether token counters are
289
+ additive, conversation aggregates, context snapshots, or unavailable. Dashboard token
290
+ per-turn percentiles use only additive providers rather than treating missing measures
291
+ as zero.
292
+
293
+ ## Commands
294
+
295
+ | Command | Purpose |
296
+ | --- | --- |
297
+ | `collect` | Collect local or copied provider data into SQL. |
298
+ | `sync` | Collect and send metadata-only snapshots to a central API. |
299
+ | `serve` | Run the central collection API. |
300
+ | `export` | Write the HTML dashboard and optional CSV tables. |
301
+ | `providers` | List provider names and support status. |
302
+ | `retention` | Preview or apply deletion of metadata outside a retention window. |
303
+
304
+ Run `uv run cli-consumption COMMAND --help` for all options.
305
+
306
+ `collect`, `export`, and `retention` accept `--json` for deterministic
307
+ machine-readable results. `collect --strict` rejects snapshots containing malformed
308
+ provider records before opening the destination database.
309
+
310
+ ## Development
311
+
312
+ ```bash
313
+ uv sync --all-extras --all-groups
314
+ uv run pre-commit install
315
+ uv run pre-commit run --all-files
316
+ uv run ruff format --check .
317
+ uv run ruff check .
318
+ uv run ty check
319
+ uv run pytest --cov --cov-report=term-missing
320
+ uv build
321
+ ```
322
+
323
+ Development uses short-lived branches and squash-merged pull requests into protected
324
+ `main`. Read
325
+ [CONTRIBUTING.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/CONTRIBUTING.md)
326
+ and [AGENTS.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/AGENTS.md)
327
+ before changing the project. Security issues follow the private reporting guidance in
328
+ [SECURITY.md](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/SECURITY.md).
329
+
330
+ ## License
331
+
332
+ Licensed under the [Apache License 2.0](https://github.com/Guillaume-Lombardo/cli-consumption/blob/main/LICENSE).