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.
- cli_consumption-0.3.0/CHANGELOG.md +84 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/PKG-INFO +104 -36
- cli_consumption-0.3.0/README.md +332 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/pyproject.toml +15 -1
- cli_consumption-0.3.0/src/cli_consumption/adapters/_shared.py +418 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/aider.py +44 -40
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/amazon_q.py +16 -10
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/amp.py +29 -40
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/claude.py +41 -49
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/cline.py +27 -14
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/codex.py +53 -38
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/continue_cli.py +26 -20
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/copilot.py +32 -30
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/crush.py +69 -74
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/cursor.py +35 -26
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/gemini.py +48 -55
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/goose.py +66 -69
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/grok.py +30 -28
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/kilo.py +65 -72
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/kimi.py +9 -4
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/mistral_vibe.py +26 -20
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/opencode.py +50 -66
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/openhands.py +34 -44
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/pi.py +39 -58
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/plandex.py +12 -5
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/qwen.py +36 -46
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/registry.py +141 -16
- cli_consumption-0.3.0/src/cli_consumption/api.py +463 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/cli.py +141 -23
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/dashboard.py +572 -233
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/exporting.py +0 -4
- cli_consumption-0.3.0/src/cli_consumption/migrations/versions/v0003_canonical_timestamps.py +94 -0
- cli_consumption-0.3.0/src/cli_consumption/migrations/versions/v0004_subagent_scope_freshness.py +38 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/models.py +70 -11
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/reporting.py +90 -30
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/retention.py +10 -14
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/schema.py +184 -12
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/storage.py +109 -28
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/sync.py +25 -0
- cli_consumption-0.3.0/src/cli_consumption/timestamps.py +17 -0
- cli_consumption-0.2.0/.agents/skills/add-cli-adapter/SKILL.md +0 -21
- cli_consumption-0.2.0/.agents/skills/add-cli-adapter/agents/openai.yaml +0 -4
- cli_consumption-0.2.0/.agents/skills/audit-usage-privacy/SKILL.md +0 -22
- cli_consumption-0.2.0/.agents/skills/audit-usage-privacy/agents/openai.yaml +0 -4
- cli_consumption-0.2.0/.agents/skills/evolve-storage-schema/SKILL.md +0 -21
- cli_consumption-0.2.0/.agents/skills/evolve-storage-schema/agents/openai.yaml +0 -4
- cli_consumption-0.2.0/.agents/skills/yeet-github/SKILL.md +0 -66
- cli_consumption-0.2.0/.agents/skills/yeet-github/agents/openai.yaml +0 -4
- cli_consumption-0.2.0/.agents/skills/yolo/SKILL.md +0 -50
- cli_consumption-0.2.0/.agents/skills/yolo/agents/openai.yaml +0 -4
- cli_consumption-0.2.0/.github/workflows/ci.yml +0 -64
- cli_consumption-0.2.0/.github/workflows/release.yaml +0 -154
- cli_consumption-0.2.0/.pre-commit-config.yaml +0 -35
- cli_consumption-0.2.0/.python-version +0 -1
- cli_consumption-0.2.0/AGENTS.md +0 -68
- cli_consumption-0.2.0/CONTRIBUTING.md +0 -50
- cli_consumption-0.2.0/README.md +0 -265
- cli_consumption-0.2.0/docs/architecture.md +0 -105
- cli_consumption-0.2.0/docs/decisions/0001-versioned-schema-migrations.md +0 -50
- cli_consumption-0.2.0/docs/privacy.md +0 -95
- cli_consumption-0.2.0/docs/provider-support.md +0 -419
- cli_consumption-0.2.0/docs/roadmap.md +0 -28
- cli_consumption-0.2.0/src/cli_consumption/adapters/_shared.py +0 -141
- cli_consumption-0.2.0/src/cli_consumption/api.py +0 -143
- cli_consumption-0.2.0/tests/conftest.py +0 -133
- cli_consumption-0.2.0/tests/smoke_minimal_install.py +0 -69
- cli_consumption-0.2.0/tests/test_aider_adapter.py +0 -204
- cli_consumption-0.2.0/tests/test_amazon_q_adapter.py +0 -67
- cli_consumption-0.2.0/tests/test_amp_adapter.py +0 -257
- cli_consumption-0.2.0/tests/test_api.py +0 -160
- cli_consumption-0.2.0/tests/test_claude_adapter.py +0 -218
- cli_consumption-0.2.0/tests/test_cli.py +0 -1083
- cli_consumption-0.2.0/tests/test_cline_adapter.py +0 -102
- cli_consumption-0.2.0/tests/test_codex_adapter.py +0 -256
- cli_consumption-0.2.0/tests/test_continue_adapter.py +0 -266
- cli_consumption-0.2.0/tests/test_copilot_adapter.py +0 -348
- cli_consumption-0.2.0/tests/test_crush_adapter.py +0 -304
- cli_consumption-0.2.0/tests/test_cursor_adapter.py +0 -230
- cli_consumption-0.2.0/tests/test_exporting.py +0 -85
- cli_consumption-0.2.0/tests/test_gemini_adapter.py +0 -275
- cli_consumption-0.2.0/tests/test_goose_adapter.py +0 -269
- cli_consumption-0.2.0/tests/test_grok_adapter.py +0 -304
- cli_consumption-0.2.0/tests/test_kilo_adapter.py +0 -292
- cli_consumption-0.2.0/tests/test_kimi_adapter.py +0 -82
- cli_consumption-0.2.0/tests/test_migrations_and_retention.py +0 -530
- cli_consumption-0.2.0/tests/test_mistral_vibe_adapter.py +0 -207
- cli_consumption-0.2.0/tests/test_opencode_adapter.py +0 -261
- cli_consumption-0.2.0/tests/test_openhands_adapter.py +0 -313
- cli_consumption-0.2.0/tests/test_packaging.py +0 -26
- cli_consumption-0.2.0/tests/test_pi_adapter.py +0 -287
- cli_consumption-0.2.0/tests/test_plandex_adapter.py +0 -68
- cli_consumption-0.2.0/tests/test_provider_registry.py +0 -158
- cli_consumption-0.2.0/tests/test_qwen_adapter.py +0 -295
- cli_consumption-0.2.0/tests/test_reporting.py +0 -240
- cli_consumption-0.2.0/tests/test_snapshot_contract.py +0 -75
- cli_consumption-0.2.0/tests/test_storage_and_exports.py +0 -301
- cli_consumption-0.2.0/tests/test_sync.py +0 -60
- cli_consumption-0.2.0/uv.lock +0 -987
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/.gitignore +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/LICENSE +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/NOTICE +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/__init__.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/__main__.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/__init__.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/adapters/base.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/__init__.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/env.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/versions/__init__.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/versions/v0001_baseline.py +0 -0
- {cli_consumption-0.2.0 → cli_consumption-0.3.0}/src/cli_consumption/migrations/versions/v0002_minimize_subagents.py +0 -0
- {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.
|
|
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)
|
|
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.
|
|
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
|
-
|
|
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)
|
|
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.
|
|
247
|
-
|
|
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
|
|
296
|
-
|
|
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).
|