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