cli-consumption 0.0.1__tar.gz → 0.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/yolo/SKILL.md +6 -6
  2. cli_consumption-0.0.3/.agents/skills/yolo/agents/openai.yaml +4 -0
  3. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.github/workflows/ci.yml +2 -2
  4. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.github/workflows/release.yaml +43 -16
  5. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/CONTRIBUTING.md +4 -0
  6. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/PKG-INFO +30 -6
  7. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/README.md +29 -5
  8. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/architecture.md +5 -3
  9. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/privacy.md +2 -1
  10. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/provider-support.md +18 -1
  11. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/roadmap.md +3 -2
  12. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/pyproject.toml +1 -1
  13. cli_consumption-0.0.3/src/cli_consumption/adapters/__init__.py +4 -0
  14. cli_consumption-0.0.3/src/cli_consumption/adapters/claude.py +394 -0
  15. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/cli.py +98 -32
  16. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/dashboard.py +31 -20
  17. cli_consumption-0.0.3/tests/test_claude_adapter.py +218 -0
  18. cli_consumption-0.0.3/tests/test_cli.py +216 -0
  19. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/test_storage_and_exports.py +7 -0
  20. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/uv.lock +1 -1
  21. cli_consumption-0.0.1/.agents/skills/yolo/agents/openai.yaml +0 -4
  22. cli_consumption-0.0.1/src/cli_consumption/adapters/__init__.py +0 -3
  23. cli_consumption-0.0.1/tests/test_cli.py +0 -101
  24. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/add-cli-adapter/SKILL.md +0 -0
  25. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/add-cli-adapter/agents/openai.yaml +0 -0
  26. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/audit-usage-privacy/SKILL.md +0 -0
  27. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/audit-usage-privacy/agents/openai.yaml +0 -0
  28. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/evolve-storage-schema/SKILL.md +0 -0
  29. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/evolve-storage-schema/agents/openai.yaml +0 -0
  30. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/yeet-github/SKILL.md +0 -0
  31. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/yeet-github/agents/openai.yaml +0 -0
  32. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.gitignore +0 -0
  33. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.pre-commit-config.yaml +0 -0
  34. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.python-version +0 -0
  35. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/AGENTS.md +0 -0
  36. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/LICENSE +0 -0
  37. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/NOTICE +0 -0
  38. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/__init__.py +0 -0
  39. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/__main__.py +0 -0
  40. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/adapters/base.py +0 -0
  41. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/adapters/codex.py +0 -0
  42. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/api.py +0 -0
  43. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/exporting.py +0 -0
  44. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/models.py +0 -0
  45. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/py.typed +0 -0
  46. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/storage.py +0 -0
  47. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/sync.py +0 -0
  48. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/conftest.py +0 -0
  49. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/test_api.py +0 -0
  50. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/test_codex_adapter.py +0 -0
  51. {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/test_sync.py +0 -0
@@ -1,16 +1,16 @@
1
1
  ---
2
2
  name: yolo
3
- description: Publish the current Codex work in a GitHub pull request, squash-merge it, then clean up its local and remote branches. Use only when the user explicitly invokes `$yolo` or requests the full publish, merge, and cleanup sequence.
3
+ description: Publish the current Codex work in a GitHub pull request, squash-merge it, then clean up its local and remote branches without additional approval prompts. Use only when the user explicitly invokes `$yolo` or requests the full publish, merge, and cleanup sequence.
4
4
  ---
5
5
 
6
6
  # Publish, merge, and clean up
7
7
 
8
- Run each phase in order from the repository root. The implicit pull request is the one for the current Codex work and current branch.
8
+ Run each phase in order from the repository root. The implicit pull request is the one for the current Codex work and current branch. Treat the explicit `$yolo` invocation as advance approval to push, create or ready the pull request, squash-merge it, and delete its exact source branch. Do not pause for additional confirmation during a successful, unambiguous run.
9
9
 
10
10
  ## 1. Publish
11
11
 
12
12
  1. Read all repository instructions and the product specification referenced by `AGENTS.md`.
13
- 2. Load and follow `$yeet-github` in full to inspect, validate, commit, push, and open a draft pull request.
13
+ 2. Load and follow `$yeet-github` in full to inspect, validate, commit, push, and open a draft pull request, except do not request its approval before pushing or publishing: the explicit `$yolo` invocation already provides that approval.
14
14
  3. Retain the exact source and target branches, pushed SHA, pull-request number, and URL.
15
15
  4. Stop after any failure or ambiguous external result. Never merge or clean up after a partial failure.
16
16
 
@@ -21,8 +21,8 @@ Run each phase in order from the repository root. The implicit pull request is t
21
21
  3. Inspect required checks, reviews, conversations, and protections with `gh pr checks` and `gh pr view --json mergeStateStatus,reviewDecision,statusCheckRollup`.
22
22
  4. Mark a ready draft with `gh pr ready <number>`.
23
23
  5. Watch pending checks with `gh pr checks <number> --watch --interval 10`; stop and report any failing check.
24
- 6. Present the final state and obtain explicit approval immediately before merging and deleting branches.
25
- 7. After approval, use `gh pr merge <number> --squash --delete-branch --match-head-commit <source-sha>`.
24
+ 6. Present the verified final state as a progress update, then continue without requesting approval.
25
+ 7. Use `gh pr merge <number> --squash --delete-branch --match-head-commit <source-sha>`.
26
26
  8. If GitHub queues the merge, keep monitoring. Clean up only after `gh pr view <number> --json state,mergedAt,mergeCommit` reports `MERGED`.
27
27
 
28
28
  ## 3. Clean up
@@ -32,7 +32,7 @@ Run each phase in order from the repository root. The implicit pull request is t
32
32
  3. Run `git fetch --prune origin`.
33
33
  4. Switch to the target branch and update it only by fast-forward with `git switch <target-branch>` and `git pull --ff-only origin <target-branch>`.
34
34
  5. Delete the exact local source branch if it remains. `git branch -D <source-branch>` is allowed only after verified squash merge.
35
- 6. If the unprotected remote branch remains, obtain fresh explicit approval before `git push origin --delete <source-branch>`.
35
+ 6. If the exact unprotected remote source branch remains, delete it with `git push origin --delete <source-branch>` without requesting additional approval.
36
36
  7. Run `git status --short --branch` and report the final state.
37
37
 
38
38
  ## Guardrails
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Yolo GitHub"
3
+ short_description: "Publish, squash-merge, and clean up without prompts"
4
+ default_prompt: "Use $yolo to publish, squash-merge, and clean up the current GitHub work without additional approval prompts."
@@ -12,8 +12,8 @@ jobs:
12
12
  quality:
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
- - uses: actions/checkout@v4
16
- - uses: astral-sh/setup-uv@v6
15
+ - uses: actions/checkout@v7.0.1
16
+ - uses: astral-sh/setup-uv@v10.0.1
17
17
  with:
18
18
  enable-cache: true
19
19
  python-version: "3.14"
@@ -4,6 +4,12 @@ on:
4
4
  push:
5
5
  branches: [main]
6
6
  paths: [pyproject.toml]
7
+ workflow_dispatch:
8
+ inputs:
9
+ release_sha:
10
+ description: Commit on main where the version first appeared
11
+ required: true
12
+ type: string
7
13
 
8
14
  concurrency:
9
15
  group: release
@@ -16,32 +22,49 @@ jobs:
16
22
  contents: read
17
23
  outputs:
18
24
  changed: ${{ steps.version.outputs.changed }}
25
+ release-sha: ${{ steps.version.outputs.release-sha }}
19
26
  version: ${{ steps.version.outputs.version }}
20
27
  steps:
21
- - uses: actions/checkout@v4
28
+ - uses: actions/checkout@v7.0.1
22
29
  with:
23
30
  fetch-depth: 0
24
- - uses: astral-sh/setup-uv@v6
25
- with:
26
- python-version: "3.14"
31
+ ref: ${{ inputs.release_sha || github.sha }}
27
32
  - name: Detect project version change
28
33
  id: version
29
34
  env:
30
35
  BEFORE_SHA: ${{ github.event.before }}
36
+ EVENT_NAME: ${{ github.event_name }}
31
37
  run: |
32
38
  set -euo pipefail
33
39
 
34
- current_version="$(uv version --short)"
40
+ release_commit="$(git rev-parse HEAD)"
41
+ if ! git merge-base --is-ancestor "${release_commit}" origin/main; then
42
+ echo "Release commit ${release_commit} is not on main." >&2
43
+ exit 1
44
+ fi
45
+
46
+ current_version="$(
47
+ python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml", "rb"))["project"]["version"])'
48
+ )"
35
49
  previous_version=""
36
- if git cat-file -e "${BEFORE_SHA}:pyproject.toml" 2>/dev/null; then
50
+ comparison_sha="${BEFORE_SHA}"
51
+ if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then
52
+ comparison_sha="${release_commit}^"
53
+ fi
54
+ if git cat-file -e "${comparison_sha}:pyproject.toml" 2>/dev/null; then
37
55
  previous_version="$(
38
- git show "${BEFORE_SHA}:pyproject.toml" |
39
- python -c 'import sys, tomllib; print(tomllib.load(sys.stdin.buffer)["project"]["version"])'
56
+ git show "${comparison_sha}:pyproject.toml" |
57
+ python3 -c 'import sys, tomllib; print(tomllib.load(sys.stdin.buffer)["project"]["version"])'
40
58
  )"
41
59
  fi
42
60
 
61
+ echo "release-sha=${release_commit}" >> "${GITHUB_OUTPUT}"
43
62
  echo "version=${current_version}" >> "${GITHUB_OUTPUT}"
44
63
  if [[ "${current_version}" == "${previous_version}" ]]; then
64
+ if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then
65
+ echo "Version ${current_version} did not first appear in ${release_commit}." >&2
66
+ exit 1
67
+ fi
45
68
  echo "changed=false" >> "${GITHUB_OUTPUT}"
46
69
  else
47
70
  echo "changed=true" >> "${GITHUB_OUTPUT}"
@@ -54,8 +77,10 @@ jobs:
54
77
  permissions:
55
78
  contents: read
56
79
  steps:
57
- - uses: actions/checkout@v4
58
- - uses: astral-sh/setup-uv@v6
80
+ - uses: actions/checkout@v7.0.1
81
+ with:
82
+ ref: ${{ needs.detect-version.outputs.release-sha }}
83
+ - uses: astral-sh/setup-uv@v10.0.1
59
84
  with:
60
85
  enable-cache: true
61
86
  python-version: "3.14"
@@ -67,7 +92,7 @@ jobs:
67
92
  - run: uv run pytest --cov --cov-report=term-missing
68
93
  - run: uv build
69
94
  - name: Upload distributions
70
- uses: actions/upload-artifact@v4
95
+ uses: actions/upload-artifact@v7.0.1
71
96
  with:
72
97
  name: python-package-distributions
73
98
  path: dist/
@@ -80,11 +105,13 @@ jobs:
80
105
  permissions:
81
106
  contents: write
82
107
  steps:
83
- - uses: actions/checkout@v4
108
+ - uses: actions/checkout@v7.0.1
84
109
  with:
85
110
  fetch-depth: 0
111
+ ref: ${{ needs.detect-version.outputs.release-sha }}
86
112
  - name: Tag version commit
87
113
  env:
114
+ RELEASE_SHA: ${{ needs.detect-version.outputs.release-sha }}
88
115
  RELEASE_VERSION: ${{ needs.detect-version.outputs.version }}
89
116
  run: |
90
117
  set -euo pipefail
@@ -93,14 +120,14 @@ jobs:
93
120
  git fetch --tags origin
94
121
  if git rev-parse --verify --quiet "refs/tags/${tag}" >/dev/null; then
95
122
  tagged_commit="$(git rev-list -n 1 "${tag}")"
96
- if [[ "${tagged_commit}" != "${GITHUB_SHA}" ]]; then
97
- echo "Tag ${tag} already points to ${tagged_commit}, not ${GITHUB_SHA}." >&2
123
+ if [[ "${tagged_commit}" != "${RELEASE_SHA}" ]]; then
124
+ echo "Tag ${tag} already points to ${tagged_commit}, not ${RELEASE_SHA}." >&2
98
125
  exit 1
99
126
  fi
100
127
  else
101
128
  git config user.name "github-actions[bot]"
102
129
  git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
103
- git tag --annotate "${tag}" --message "Release ${RELEASE_VERSION}" "${GITHUB_SHA}"
130
+ git tag --annotate "${tag}" --message "Release ${RELEASE_VERSION}" "${RELEASE_SHA}"
104
131
  git push origin "refs/tags/${tag}"
105
132
  fi
106
133
 
@@ -114,7 +141,7 @@ jobs:
114
141
  id-token: write
115
142
  steps:
116
143
  - name: Download distributions
117
- uses: actions/download-artifact@v4
144
+ uses: actions/download-artifact@v8.0.1
118
145
  with:
119
146
  name: python-package-distributions
120
147
  path: dist/
@@ -36,3 +36,7 @@ Update the project version with `uv version <version>` and include the resulting
36
36
  squash-merged into `main`, the release workflow reruns the quality gates, builds the
37
37
  distributions, tags the merge commit as `v<version>`, and publishes to PyPI through
38
38
  Trusted Publishing. Do not create the release tag manually.
39
+
40
+ If a release fails before publication, rerun it for the original version commit with
41
+ `gh workflow run release.yaml --ref main -f release_sha=<merge-commit>`. The workflow
42
+ rejects commits outside `main` and conflicting existing tags.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cli-consumption
3
- Version: 0.0.1
3
+ Version: 0.0.3
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
@@ -33,8 +33,8 @@ models, tokens, tools, conversations, and turns. It can analyze one workstation,
33
33
  consolidate copied data from several machines, or send metadata-only snapshots to a
34
34
  central collector.
35
35
 
36
- Codex is fully supported. Claude Code, OpenCode, Kilo Code, and Pi are planned behind
37
- the same provider-neutral adapter contract.
36
+ Codex and the core Claude Code local transcript format are supported. OpenCode, Kilo
37
+ Code, and Pi are planned behind the same provider-neutral adapter contract.
38
38
 
39
39
  The collector deliberately excludes prompts, responses, tool arguments, and
40
40
  credentials. See [Privacy](docs/privacy.md) before sharing a database or export.
@@ -53,7 +53,7 @@ uv run cli-consumption export --output reports
53
53
  ```
54
54
 
55
55
  Open `reports/dashboard.html` locally. The generated dashboard is self-contained and
56
- makes no network requests.
56
+ makes no network requests. Detailed normalized CSV tables are opt-in with `--csv`.
57
57
 
58
58
  The dashboard supports time, provider, machine, project, and model filters. It reports
59
59
  period-over-period activity, token composition, cache efficiency, turn latency and
@@ -62,7 +62,7 @@ duration and reliability, configuration cohorts, compactions, subagent delegatio
62
62
  ingestion quality. Token events are local usage metadata rather than billing records,
63
63
  and a technically completed turn is not a measure of task quality or productivity.
64
64
 
65
- For a dashboard that is safer to share, omit the detailed CSV exports, pseudonymize
65
+ For a dashboard that is safer to share, pseudonymize
66
66
  machine, project, model, and role labels, group tool names, round timestamps to days,
67
67
  and hide small rows in the cohort-comparison view:
68
68
 
@@ -96,6 +96,22 @@ hostname:
96
96
  uv run cli-consumption collect --database usage.sqlite
97
97
  ```
98
98
 
99
+ Select Claude Code to read `~/.claude/projects/` instead:
100
+
101
+ ```bash
102
+ uv run cli-consumption collect --provider claude --database usage.sqlite
103
+ ```
104
+
105
+ Use `all` to detect and collect every supported provider present on the machine:
106
+
107
+ ```bash
108
+ uv run cli-consumption collect --provider all --database usage.sqlite
109
+ ```
110
+
111
+ With explicit copied sources, each path is inspected for the provider-specific
112
+ `sessions/` or `projects/` directory. Sources that contain no supported provider data
113
+ are rejected instead of silently skipped.
114
+
99
115
  For an offline multi-machine workflow, copy only each machine's Codex `sessions/`
100
116
  directory into a trusted analysis location. Do not copy `auth.json` or other
101
117
  credentials. Then repeat `--source`:
@@ -118,6 +134,14 @@ uv run cli-consumption collect \
118
134
  --project cli-consumption=/home/me/dev/cli-consumption
119
135
  ```
120
136
 
137
+ Copied Claude Code sources point to the configuration directory containing `projects/`:
138
+
139
+ ```bash
140
+ uv run cli-consumption collect --provider claude \
141
+ --source desktop=/data/claude/desktop \
142
+ --source laptop=/data/claude/laptop
143
+ ```
144
+
121
145
  ## SQLite and PostgreSQL
122
146
 
123
147
  A file path selects SQLite. A SQLAlchemy URL selects PostgreSQL:
@@ -162,7 +186,7 @@ server. See [Architecture](docs/architecture.md) for trade-offs.
162
186
  cli-consumption collect Collect local or copied provider data into SQL
163
187
  cli-consumption sync Collect and send a snapshot to a central API
164
188
  cli-consumption serve Run the central collection API
165
- cli-consumption export Write CSV tables and the HTML dashboard
189
+ cli-consumption export Write the HTML dashboard and optional CSV tables
166
190
  cli-consumption providers Show supported and planned providers
167
191
  ```
168
192
 
@@ -5,8 +5,8 @@ models, tokens, tools, conversations, and turns. It can analyze one workstation,
5
5
  consolidate copied data from several machines, or send metadata-only snapshots to a
6
6
  central collector.
7
7
 
8
- Codex is fully supported. Claude Code, OpenCode, Kilo Code, and Pi are planned behind
9
- the same provider-neutral adapter contract.
8
+ Codex and the core Claude Code local transcript format are supported. OpenCode, Kilo
9
+ Code, and Pi are planned behind the same provider-neutral adapter contract.
10
10
 
11
11
  The collector deliberately excludes prompts, responses, tool arguments, and
12
12
  credentials. See [Privacy](docs/privacy.md) before sharing a database or export.
@@ -25,7 +25,7 @@ uv run cli-consumption export --output reports
25
25
  ```
26
26
 
27
27
  Open `reports/dashboard.html` locally. The generated dashboard is self-contained and
28
- makes no network requests.
28
+ makes no network requests. Detailed normalized CSV tables are opt-in with `--csv`.
29
29
 
30
30
  The dashboard supports time, provider, machine, project, and model filters. It reports
31
31
  period-over-period activity, token composition, cache efficiency, turn latency and
@@ -34,7 +34,7 @@ duration and reliability, configuration cohorts, compactions, subagent delegatio
34
34
  ingestion quality. Token events are local usage metadata rather than billing records,
35
35
  and a technically completed turn is not a measure of task quality or productivity.
36
36
 
37
- For a dashboard that is safer to share, omit the detailed CSV exports, pseudonymize
37
+ For a dashboard that is safer to share, pseudonymize
38
38
  machine, project, model, and role labels, group tool names, round timestamps to days,
39
39
  and hide small rows in the cohort-comparison view:
40
40
 
@@ -68,6 +68,22 @@ hostname:
68
68
  uv run cli-consumption collect --database usage.sqlite
69
69
  ```
70
70
 
71
+ Select Claude Code to read `~/.claude/projects/` instead:
72
+
73
+ ```bash
74
+ uv run cli-consumption collect --provider claude --database usage.sqlite
75
+ ```
76
+
77
+ Use `all` to detect and collect every supported provider present on the machine:
78
+
79
+ ```bash
80
+ uv run cli-consumption collect --provider all --database usage.sqlite
81
+ ```
82
+
83
+ With explicit copied sources, each path is inspected for the provider-specific
84
+ `sessions/` or `projects/` directory. Sources that contain no supported provider data
85
+ are rejected instead of silently skipped.
86
+
71
87
  For an offline multi-machine workflow, copy only each machine's Codex `sessions/`
72
88
  directory into a trusted analysis location. Do not copy `auth.json` or other
73
89
  credentials. Then repeat `--source`:
@@ -90,6 +106,14 @@ uv run cli-consumption collect \
90
106
  --project cli-consumption=/home/me/dev/cli-consumption
91
107
  ```
92
108
 
109
+ Copied Claude Code sources point to the configuration directory containing `projects/`:
110
+
111
+ ```bash
112
+ uv run cli-consumption collect --provider claude \
113
+ --source desktop=/data/claude/desktop \
114
+ --source laptop=/data/claude/laptop
115
+ ```
116
+
93
117
  ## SQLite and PostgreSQL
94
118
 
95
119
  A file path selects SQLite. A SQLAlchemy URL selects PostgreSQL:
@@ -134,7 +158,7 @@ server. See [Architecture](docs/architecture.md) for trade-offs.
134
158
  cli-consumption collect Collect local or copied provider data into SQL
135
159
  cli-consumption sync Collect and send a snapshot to a central API
136
160
  cli-consumption serve Run the central collection API
137
- cli-consumption export Write CSV tables and the HTML dashboard
161
+ cli-consumption export Write the HTML dashboard and optional CSV tables
138
162
  cli-consumption providers Show supported and planned providers
139
163
  ```
140
164
 
@@ -7,7 +7,7 @@ and reporting. This lets users compare multiple AI coding CLIs without forcing t
7
7
  local formats into one parser.
8
8
 
9
9
  ```text
10
- provider files -> adapter -> metadata-only snapshot -> SQL storage -> CSV/dashboard
10
+ provider files -> adapter -> metadata-only snapshot -> SQL storage -> dashboard/CSV
11
11
  |
12
12
  +-> HTTPS collector -> central SQL storage
13
13
  ```
@@ -16,12 +16,14 @@ provider files -> adapter -> metadata-only snapshot -> SQL storage -> CSV/dashbo
16
16
 
17
17
  - `adapters`: parse a CLI's local data into conversations, turns, model calls, tool
18
18
  calls, context-pressure samples, bounded turn settings, compactions, and content-free
19
- work-item intervals. Codex is the first complete implementation.
19
+ work-item intervals. Codex exposes the complete analytics contract; Claude Code
20
+ exposes the core dimensions available in its local transcripts.
20
21
  - `models`: define the transport boundary shared by offline and API ingestion.
21
22
  - `storage`: owns the normalized schema, idempotent replacement rules, SQLite, and
22
23
  PostgreSQL engine creation.
23
24
  - `api` and `sync`: offer an optional push workflow for recurring multi-machine use.
24
- - `exporting` and `dashboard`: provide portable CSV files and an offline HTML view.
25
+ - `dashboard` and `exporting`: provide an offline HTML view by default and portable CSV
26
+ tables when explicitly requested.
25
27
  - `cli`: exposes the same capabilities through one executable.
26
28
 
27
29
  When Codex exposes its local thread graph, the adapter also records metadata-only
@@ -59,7 +59,8 @@ and period comparisons are computed inside the document. The remaining project n
59
59
  machine labels, model names, tool names, roles, token counters, statuses, and activity
60
60
  timestamps are still private operational metadata.
61
61
 
62
- `export --share-safe` writes only the HTML dashboard and omits CSV tables. Within that
62
+ The normal `export` command writes only the HTML dashboard; detailed CSV tables require
63
+ the explicit `--csv` option. `export --share-safe` rejects that option. Within its HTML
63
64
  document, machine, project, model, and subagent-role labels are replaced with local
64
65
  aliases; tools are reduced to broad categories; timestamps are rounded to UTC days;
65
66
  and the comparison table hides cohorts smaller than five closed turns. The underlying
@@ -3,7 +3,7 @@
3
3
  | Provider | Status | Initial source |
4
4
  | --- | --- | --- |
5
5
  | Codex | Supported | Local rollout JSONL and optional metadata-only subagent state |
6
- | Claude Code | Planned | To be verified before implementation |
6
+ | Claude Code | Supported (core) | Local project transcript JSONL |
7
7
  | OpenCode | Planned | To be verified before implementation |
8
8
  | Kilo Code | Planned | To be verified before implementation |
9
9
  | Pi | Planned | To be verified before implementation |
@@ -12,6 +12,10 @@
12
12
  models, token usage, and tool names when available, and passes privacy regression tests.
13
13
  It does not mean that token counters are equivalent to invoices.
14
14
 
15
+ `--provider all` detects every supported provider from its expected data directory and
16
+ ingests each metadata-only snapshot independently. With no explicit source it checks
17
+ the local default homes; repeated `--source` paths are filtered by detected format.
18
+
15
19
  Codex additionally exposes provider-reported turn duration and TTFT, model context
16
20
  window samples, bounded reasoning/collaboration/service-tier labels, timestamped
17
21
  compactions, technical work-item categories and durations, and local thread-spawn
@@ -19,6 +23,19 @@ relationships. Work-item content and rate-limit payloads are deliberately exclud
19
23
  Subagent state can remain `open` after a child thread is technically closed; reporting
20
24
  therefore derives closure from collected child turns when they are available.
21
25
 
26
+ Claude Code reads top-level sessions from
27
+ `~/.claude/projects/<project>/<session-id>.jsonl` (or `CLAUDE_CONFIG_DIR`). It extracts
28
+ main-session turns, models, token usage, tool names, and compaction timestamps while
29
+ discarding prompts, responses, tool inputs/results, paths, branches, and arbitrary
30
+ metadata. Streaming fragments are deduplicated by request or message identifier.
31
+
32
+ Claude Code emits uncached, cache-read, and cache-creation input separately. Normalized
33
+ `input_tokens` is their sum, with each component retained in its corresponding field.
34
+ The internal transcript schema can change between Claude Code releases and local usage
35
+ is not billing data. This first increment does not collect subagent transcripts,
36
+ context-window sizes, effort/service-tier settings, TTFT, provider-reported duration,
37
+ or technical work-item intervals.
38
+
22
39
  Provider formats can change without notice. Unknown fields are ignored; malformed JSONL
23
40
  records are counted and skipped. Compatibility fixes should add a fixture for both the
24
41
  old and new format whenever possible.
@@ -3,15 +3,16 @@
3
3
  ## Current foundation
4
4
 
5
5
  - Complete Codex local collector
6
+ - Core Claude Code local transcript collector
6
7
  - Offline multi-machine deduplication
7
8
  - SQLite and PostgreSQL storage
8
9
  - Metadata-only central collection API
9
- - CSV exports, a self-contained dashboard, and a share-safe dashboard profile
10
+ - Opt-in CSV exports, a self-contained dashboard, and a share-safe dashboard profile
10
11
  - Context-pressure, work-item reliability, configuration-cohort, and delegation views
11
12
 
12
13
  ## Next provider increments
13
14
 
14
- 1. Validate Claude Code's local and endpoint formats, then add its adapter.
15
+ 1. Extend Claude Code support only where local metadata has reliable semantics.
15
16
  2. Add OpenCode with the same normalized contract.
16
17
  3. Add Kilo Code and Pi after format and licensing review.
17
18
  4. Add cross-provider comparison views once at least two adapters expose reliable model
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "cli-consumption"
7
- version = "0.0.1"
7
+ version = "0.0.3"
8
8
  description = "Analyze and consolidate AI coding CLI consumption across machines."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.14"
@@ -0,0 +1,4 @@
1
+ from cli_consumption.adapters.claude import ClaudeAdapter
2
+ from cli_consumption.adapters.codex import CodexAdapter
3
+
4
+ __all__ = ["ClaudeAdapter", "CodexAdapter"]