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.
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/yolo/SKILL.md +6 -6
- cli_consumption-0.0.3/.agents/skills/yolo/agents/openai.yaml +4 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.github/workflows/ci.yml +2 -2
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.github/workflows/release.yaml +43 -16
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/CONTRIBUTING.md +4 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/PKG-INFO +30 -6
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/README.md +29 -5
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/architecture.md +5 -3
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/privacy.md +2 -1
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/provider-support.md +18 -1
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/docs/roadmap.md +3 -2
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/pyproject.toml +1 -1
- cli_consumption-0.0.3/src/cli_consumption/adapters/__init__.py +4 -0
- cli_consumption-0.0.3/src/cli_consumption/adapters/claude.py +394 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/cli.py +98 -32
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/dashboard.py +31 -20
- cli_consumption-0.0.3/tests/test_claude_adapter.py +218 -0
- cli_consumption-0.0.3/tests/test_cli.py +216 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/test_storage_and_exports.py +7 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/uv.lock +1 -1
- cli_consumption-0.0.1/.agents/skills/yolo/agents/openai.yaml +0 -4
- cli_consumption-0.0.1/src/cli_consumption/adapters/__init__.py +0 -3
- cli_consumption-0.0.1/tests/test_cli.py +0 -101
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/add-cli-adapter/SKILL.md +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/add-cli-adapter/agents/openai.yaml +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/audit-usage-privacy/SKILL.md +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/audit-usage-privacy/agents/openai.yaml +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/evolve-storage-schema/SKILL.md +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/evolve-storage-schema/agents/openai.yaml +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/yeet-github/SKILL.md +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.agents/skills/yeet-github/agents/openai.yaml +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.gitignore +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.pre-commit-config.yaml +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/.python-version +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/AGENTS.md +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/LICENSE +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/NOTICE +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/__init__.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/__main__.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/adapters/base.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/adapters/codex.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/api.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/exporting.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/models.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/py.typed +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/storage.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/src/cli_consumption/sync.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/conftest.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/test_api.py +0 -0
- {cli_consumption-0.0.1 → cli_consumption-0.0.3}/tests/test_codex_adapter.py +0 -0
- {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
|
|
25
|
-
7.
|
|
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,
|
|
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
|
|
@@ -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@
|
|
28
|
+
- uses: actions/checkout@v7.0.1
|
|
22
29
|
with:
|
|
23
30
|
fetch-depth: 0
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 "${
|
|
39
|
-
|
|
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@
|
|
58
|
-
|
|
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@
|
|
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@
|
|
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}" != "${
|
|
97
|
-
echo "Tag ${tag} already points to ${tagged_commit}, not ${
|
|
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}" "${
|
|
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@
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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
|
|
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
|
|
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
|
-
- `
|
|
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
|
|
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 |
|
|
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.
|
|
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
|