copilot-session-usage 0.9.4__tar.gz → 1.0.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.
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/PKG-INFO +120 -39
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/README.md +119 -38
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/conf.py +1 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/explanation/how-cost-estimation-works.md +137 -64
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/analyze-specific-session.md +4 -4
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/batch-and-spending.md +27 -13
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/copilot-cli-provider.md +36 -40
- copilot_session_usage-1.0.0/docs/source/how-to/export-json.md +85 -0
- copilot_session_usage-1.0.0/docs/source/reference/api.md +71 -0
- copilot_session_usage-1.0.0/docs/source/reference/cli.md +55 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/reference/pricing.md +36 -29
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/tutorials/getting-started.md +9 -6
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/skills/copilot-session-usage/SKILL.md +60 -17
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/skills/copilot-session-usage/references/span-analysis-template.md +30 -16
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/copilot_cli.py +267 -276
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/core.py +852 -656
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/vscode.py +25 -1
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/api.py +190 -40
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/cli.py +253 -79
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/models-and-pricing.lock +3 -3
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/models-and-pricing.yml +22 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/conftest.py +19 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_api.py +235 -2
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_cli.py +185 -9
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_copilot_cli.py +291 -196
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_core.py +501 -151
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_rendering.py +51 -50
- copilot_session_usage-1.0.0/tests/test_review_regressions.py +418 -0
- copilot_session_usage-0.9.4/docs/source/how-to/export-json.md +0 -65
- copilot_session_usage-0.9.4/docs/source/reference/api.md +0 -31
- copilot_session_usage-0.9.4/docs/source/reference/cli.md +0 -23
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.editorconfig +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.gitattributes +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/changes/requests/skill-breakdown/01-request.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/guidelines/git-commit-message.guideline.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/guidelines/knowledge-base.guidelines.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/pull_request_template.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/consolidate-knowledge-base/SKILL.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-commit-changes/SKILL.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-create-pull-request/SKILL.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-release-notes/SKILL.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-release-notes/scripts/generate_release_notes.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/record-finding/README.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/record-finding/SKILL.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/ci.yml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/publish.yml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/refresh-pricing.yml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/release-notes.yml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/release.yml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.gitignore +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.readthedocs.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/AGENTS.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/CHANGELOG.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/CONSTITUTION.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/CONTRIBUTING.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/LICENSE +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/articles/presentation.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/internal/automated_release_proces.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/_static/changelog.js +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/_static/custom.css +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/changelog.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/explanation/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/add-commit-trailer.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/wsl2.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/installation.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/reference/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/tutorials/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/guidelines.yml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/justfile +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Base.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Concept.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Experiment.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Finding.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Hypothesis.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Outcome.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Playbook.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Principle.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Reference.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Structure.schema.yaml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/copilot-cli.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/overview.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/session-cost-analysis.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/threshold-based-pricing.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/experiments/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/experiments/verify-subagent-cost-attribution.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.07.02-00.00-subagent-logs-runsubagent-prefix.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.07.02-22.00-title-generation-not-counted-as-model-turn.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.07.02-23.00-cache-write-approximation.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.07.13-14.27-release-notes-overreported-maintainer-changes.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.07.24-15.01-actions-token-cannot-create-pr.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.08.05-16.24-utility-models-appear-in-logs-but-are-not-billed.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.10.07-17.30-cli-billed-nanoaiu-and-cache-write.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/2026.10.07-request-billing-and-cache-write.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/automation-scripts.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/cost-optimization.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/wsl2-setup.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/ideas/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/ideas/multi-session-efficiency-analytics.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/log.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/principles/findings-are-immutable.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/principles/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/reference/debug-log-format.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/reference/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/reference/pricing-formats.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/cache-cost-approximation.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/index.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/knowledge-base-information-types.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/session-discovery-algorithm.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/subagent-cost-tracking.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/vscode-copilot-extension.md +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/pyproject.toml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/scripts/refresh_pricing.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/__init__.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/__init__.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/git.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/__init__.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/custom-models-pricing.yml +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_coverage_gaps.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_generate_release_notes.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_git.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_pricing_runtime.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_release_notes.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_vscode.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_vscode_platform.py +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/uv.lock +0 -0
- {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/uv.toml +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: copilot-session-usage
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: Usage and cost analytics for GitHub Copilot and Copilot-CLI session logs
|
|
5
5
|
Project-URL: Homepage, https://github.com/gsemet/copilot-session-usage
|
|
6
6
|
Project-URL: Documentation, https://copilot-session-usage.readthedocs.io/en/stable/
|
|
@@ -32,6 +32,48 @@ VS Code Copilot debug logs and/or local Copilot CLI/Copilot App session logs.
|
|
|
32
32
|
|
|
33
33
|
**Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/en/stable/)
|
|
34
34
|
|
|
35
|
+
## Why not just ask Copilot to write a script?
|
|
36
|
+
|
|
37
|
+
You can: the logs are local JSONL. But every ad-hoc script re-learns the log
|
|
38
|
+
formats, and the plausible-looking answer is often wrong. This tool encodes the
|
|
39
|
+
rules once, is tested against them, and proves its own result on every run
|
|
40
|
+
(`reconciliation` block). An agent calls one command instead of spending tokens
|
|
41
|
+
on re-deriving, and possibly mis-deriving, the calculation.
|
|
42
|
+
|
|
43
|
+
How hard it is depends on the provider:
|
|
44
|
+
|
|
45
|
+
| | VS Code (`--agent vscode`) | Copilot CLI / App (`--agent cli`) |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| Where the billed cost is | One event type (`llm_request`) carries the billed `copilotUsageNanoAiu` per call | Spread over several event types: `session.usage_record` per call, `session.compaction_complete` for compactions, and cumulative `session.shutdown` / `session.usage_checkpoint` snapshots |
|
|
48
|
+
| Obvious script | Sum the per-call nanoAIU | Read the last shutdown snapshot |
|
|
49
|
+
| Is the obvious script right? | **Total: mostly yes.** Breakdowns still need care | **No.** Snapshots miss everything after the last shutdown, sessions that never shut down, and (inconsistently) compactions |
|
|
50
|
+
| Traps the tool handles | Errored requests without usage, free utility models, subagent files (`runSubagent-*.jsonl`), no cache-write count logged | Dedup by `accounting.usageId`, compaction calls and their nested `requestCount`, per-agent skill timeline, utility models, sessions resumed long after creation |
|
|
51
|
+
| Value of the tool | Convenience and reproducible breakdowns (model, subagent, skill, time window) | **Correct totals in the first place**, plus the same breakdowns |
|
|
52
|
+
|
|
53
|
+
Pitfalls that affect both providers:
|
|
54
|
+
|
|
55
|
+
- `input_tokens` already **includes** cached and cache-written tokens. Adding
|
|
56
|
+
`input + cached` doubles the token count and halves "cost per token".
|
|
57
|
+
- A cache ratio averaged per session is not the real one. Weight it by tokens.
|
|
58
|
+
- A time window must select **calls by timestamp**. Selecting sessions by creation
|
|
59
|
+
date drops long-running sessions and counts calls outside the window.
|
|
60
|
+
- Recomputing from a price table needs the cache-write premium and the
|
|
61
|
+
long-context tier per call. The tool uses the billed amount whenever it is
|
|
62
|
+
logged, and keeps the price table as a cross-check.
|
|
63
|
+
|
|
64
|
+
Errors measured on ten days of real usage before these rules were in place:
|
|
65
|
+
|
|
66
|
+
| Mistake | Impact |
|
|
67
|
+
| --- | --- |
|
|
68
|
+
| CLI cost from the last shutdown snapshot | ~32% of the cost not attributed to any model, ~28% of input tokens missing |
|
|
69
|
+
| CLI compactions ignored | ~3% of the CLI cost missing |
|
|
70
|
+
| `input + cached` as total tokens | Token count ~2× too high |
|
|
71
|
+
| Unweighted cache ratio | 0.80 reported instead of 0.95 |
|
|
72
|
+
|
|
73
|
+
With the per-call pipeline, totals match an independent sum of billed amounts
|
|
74
|
+
to the micro-dollar on both providers. The token-based recomputation stays
|
|
75
|
+
within 0.2% (`reconciliation.delta_pct`).
|
|
76
|
+
|
|
35
77
|
## Chronicle and copilot-session-usage
|
|
36
78
|
|
|
37
79
|
GitHub Copilot provides **Chronicle** session tools for conversational access to your
|
|
@@ -70,7 +112,7 @@ Copilot CLI/App event logs and turns them into repeatable reports. It provides:
|
|
|
70
112
|
| Estimated cost (`$`) **per model** | ❌ No accurate cost per breakdown | ✅ |
|
|
71
113
|
| Tokens **per subagent** | ⚠️ LLM digging each time; consumes tokens | ✅ |
|
|
72
114
|
| Estimated cost (`$`) **per subagent** | ❌ No accurate cost per breakdown | ✅ |
|
|
73
|
-
| Cost attribution to skills | ❌ Cannot provide cost per breakdown | ✅ Limited timeline attribution
|
|
115
|
+
| Cost attribution to skills | ❌ Cannot provide cost per breakdown | ✅ Limited timeline attribution |
|
|
74
116
|
| Tool-call counts by skill and subagent | ⚠️ LLM digging each time | ✅ |
|
|
75
117
|
| Batch analysis, filtering, and aggregation | Limited/conversational | ✅ |
|
|
76
118
|
| Stable JSON, table, and detailed output | No stable contract | ✅ |
|
|
@@ -82,11 +124,11 @@ In the table, `⚠️` means that Chronicle may answer the question in a particu
|
|
|
82
124
|
environment or with additional analysis, but does not guarantee a stable, reproducible
|
|
83
125
|
breakdown for it.
|
|
84
126
|
|
|
85
|
-
Skill token and cost attribution is limited: VS Code
|
|
86
|
-
|
|
87
|
-
later work until another invocation.
|
|
88
|
-
or cost caused by the skill;
|
|
89
|
-
|
|
127
|
+
Skill token and cost attribution is limited: requests (VS Code) and calls
|
|
128
|
+
(CLI/App, per agent) are grouped under the latest explicit skill invocation,
|
|
129
|
+
including the whole request context and later work until another invocation.
|
|
130
|
+
This is not an isolated measurement of tokens or cost caused by the skill;
|
|
131
|
+
automatically loaded and overlapping skills cannot be separated. See
|
|
90
132
|
[Skill attribution](docs/source/explanation/how-cost-estimation-works.md#skill-attribution).
|
|
91
133
|
|
|
92
134
|
Use Chronicle for **“What did I do?”** and use this project for **“How much did it cost,
|
|
@@ -106,12 +148,46 @@ with `--agent` (default `vscode`):
|
|
|
106
148
|
Commands never mix providers unless `--agent all` is passed. Missing
|
|
107
149
|
provider roots are ignored, including when both roots are absent.
|
|
108
150
|
|
|
109
|
-
Both providers
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
151
|
+
Both providers feed **one per-call pipeline**: every LLM call becomes a
|
|
152
|
+
normalized record, and all totals, model rows, subagent rows and skill rows are
|
|
153
|
+
sums of those records (export them with `copilot-session-usage calls`). They
|
|
154
|
+
share the same model catalog, pricing data, cache rules, and estimated-USD
|
|
155
|
+
calculation. JSON reports carry `"schema_version": 2`. Missing evidence is
|
|
156
|
+
never turned into a fabricated zero: a CLI/App session with no usage records
|
|
157
|
+
yields `null` totals and a `diagnostics` entry.
|
|
158
|
+
|
|
159
|
+
## Don't recompute costs yourself
|
|
160
|
+
|
|
161
|
+
This tool is the reference calculation. Scripts that re-derive costs from token
|
|
162
|
+
counts routinely get these wrong, so rely on `span`, `calls` and the
|
|
163
|
+
`reconciliation` block instead:
|
|
164
|
+
|
|
165
|
+
- `input_tokens` **includes cache reads and cache writes**. `cached_tokens` and
|
|
166
|
+
`cache_write_tokens` are subsets; `uncached_input_tokens` is the remainder.
|
|
167
|
+
Adding them up double-counts (the old `total_tokens` field was removed).
|
|
168
|
+
- **Cache writes are billed at a premium** over the base input rate.
|
|
169
|
+
- **VS Code logs no cache-write count** (`cache_write_tokens` is `null`).
|
|
170
|
+
- **CLI compactions are separate events** (`session.compaction_complete`); they
|
|
171
|
+
are included as `kind: "compaction"` calls.
|
|
172
|
+
- **CLI shutdown snapshots are incomplete**; they are used only for the
|
|
173
|
+
`snapshot_usd`/`snapshot_delta_usd` reconciliation check.
|
|
174
|
+
- **Utility models are free** (`gpt-4o*`, `gpt-4.1*`, `gpt-5.4-nano*`) and
|
|
175
|
+
excluded from totals on both providers.
|
|
176
|
+
- **The long-context tier is chosen per call**, from that call's input size.
|
|
177
|
+
|
|
178
|
+
Billed nanoAIU is used whenever logged (`cost_source: "billed"`); the price
|
|
179
|
+
table is only a fallback (`"estimated"`). Every session and span carries
|
|
180
|
+
`reconciliation` (`billed_usd`, `estimated_from_tokens_usd`, `delta_pct`,
|
|
181
|
+
`calls_without_billing`) to verify the formula. See
|
|
182
|
+
[Don't recompute costs yourself](docs/source/explanation/how-cost-estimation-works.md#dont-recompute-costs-yourself).
|
|
183
|
+
|
|
184
|
+
Analysis is **offline**: pricing is never refreshed automatically. Run
|
|
185
|
+
`copilot-session-usage pricing refresh` to update it, or pass
|
|
186
|
+
`auto_refresh=True` in the Python API.
|
|
187
|
+
|
|
188
|
+
`--since`, `--until` and `--last` select **calls** by their own timestamp; a
|
|
189
|
+
session is kept only if it has an in-window call, and its totals count only
|
|
190
|
+
those calls.
|
|
115
191
|
|
|
116
192
|
```bash
|
|
117
193
|
# Analyze the latest Copilot CLI/App session
|
|
@@ -151,6 +227,9 @@ copilot-session-usage --agent all span \
|
|
|
151
227
|
--until 2026-07-08T00:00:00Z \
|
|
152
228
|
--format table
|
|
153
229
|
|
|
230
|
+
# Export every priced LLM call as JSONL (the building block of all totals)
|
|
231
|
+
copilot-session-usage --agent cli calls --last 7d --output calls.jsonl
|
|
232
|
+
|
|
154
233
|
# Aggregate cost across all sessions matching a PRD path
|
|
155
234
|
copilot-session-usage analyze --name "PRD: /path/to/prd" --aggregate --format table
|
|
156
235
|
|
|
@@ -173,11 +252,12 @@ copilot-session-usage list --dir /path/to/debug-logs --format table
|
|
|
173
252
|
- **Aggregation** — roll up costs across many sessions in one command
|
|
174
253
|
- **Skill-aware cost attribution** — detect skills, attribute LLM and tool calls to the active skill
|
|
175
254
|
- **Skill-source detection** — inspect slash commands, discovery events, system prompts, and skill tools
|
|
176
|
-
- **Skill cost breakdown** — per-skill token counts and estimated cost (
|
|
255
|
+
- **Skill cost breakdown** — per-skill token counts and estimated cost (both providers)
|
|
177
256
|
- **Tool-call attribution** — per-skill/per-subagent tool-call counts
|
|
178
257
|
- **Title filtering** — find sessions by title substring
|
|
179
258
|
- **Metadata cache** — reuse session indexes until the workspace database changes
|
|
180
|
-
- **Efficiency summaries** — cache ratio, model split,
|
|
259
|
+
- **Efficiency summaries** — token-weighted cache ratio, model split, reconciliation of billed vs. token-formula cost
|
|
260
|
+
- **Per-call export** — `calls` emits normalized JSONL records; `list_calls`/`iter_calls` in the API
|
|
181
261
|
- **Field extraction** — pull specific values with `--query`
|
|
182
262
|
|
|
183
263
|
## How it works
|
|
@@ -222,27 +302,22 @@ can be determined (from the directory name or a `session.start` event) —
|
|
|
222
302
|
otherwise it is rejected with an actionable error instead of being analyzed
|
|
223
303
|
with a fabricated identity.
|
|
224
304
|
|
|
225
|
-
Per-model token totals and cost come from the session's
|
|
226
|
-
`session.
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
`provider_usage
|
|
237
|
-
|
|
305
|
+
Per-model token totals and cost come from the session's per-call records:
|
|
306
|
+
`session.usage_record` (one per LLM call, de-duplicated by `accounting.usageId`)
|
|
307
|
+
plus `session.compaction_complete` events (compactions, `kind: "compaction"`).
|
|
308
|
+
Each call uses its billed `totalNanoAiu` when present, else the shared
|
|
309
|
+
token-based pricing with the exact cache-write count. The cumulative
|
|
310
|
+
`session.shutdown`/`session.usage_checkpoint` snapshots are incomplete and used
|
|
311
|
+
only for the reconciliation diagnostic (`snapshot_usd`, `snapshot_delta_usd`).
|
|
312
|
+
A session that never shut down is therefore fully analyzed; only a session with
|
|
313
|
+
no usage records and no compaction usage has `null` totals, with `diagnostics`
|
|
314
|
+
explaining why. Calls are attributed to the subagent (`agentId`) and active
|
|
315
|
+
skill of their own agent, so the CLI/App provider has a costed skills
|
|
316
|
+
breakdown. `provider_usage` keeps informational counters such as
|
|
317
|
+
`total_premium_requests` and `resume_count`. Parsing
|
|
238
318
|
tolerates unrecognized event types and schema versions other than the one
|
|
239
319
|
currently validated, recording a diagnostic instead of failing.
|
|
240
320
|
|
|
241
|
-
Pricing lookups for `--agent cli`/`--agent all` are local-only by default
|
|
242
|
-
(no runtime pricing refresh attempt over the network), unlike the `vscode`
|
|
243
|
-
provider's default daily refresh attempt. Run
|
|
244
|
-
`copilot-session-usage pricing refresh` to update pricing explicitly.
|
|
245
|
-
|
|
246
321
|
## Knowledge base
|
|
247
322
|
|
|
248
323
|
This project includes an OKF knowledge bundle in `knowledge/` with structured
|
|
@@ -264,7 +339,8 @@ just knowledge-validate
|
|
|
264
339
|
| `id SESSION_ID` | Analyze a session by exact UUID |
|
|
265
340
|
| `list` | List recent sessions (metadata only by default) |
|
|
266
341
|
| `batch N` | Analyze the N most recent sessions in one pass |
|
|
267
|
-
| `span` | Emit a compact total, per-model, and per-session
|
|
342
|
+
| `span` | Emit a compact total, per-model, and per-session report (calls in the window) |
|
|
343
|
+
| `calls` | Export every priced LLM call as JSONL (one object per line) |
|
|
268
344
|
| `skills` | List skills used across sessions with aggregated cost |
|
|
269
345
|
|
|
270
346
|
### Analysis options
|
|
@@ -273,9 +349,9 @@ just knowledge-validate
|
|
|
273
349
|
|--------|-------------|
|
|
274
350
|
| `--name REGEX` | Filter sessions by title/ID regex (case-insensitive) |
|
|
275
351
|
| `--title SUBSTRING` | Filter sessions by title substring (case-insensitive) |
|
|
276
|
-
| `--since DATE` | Only
|
|
277
|
-
| `--until DATE` | Only
|
|
278
|
-
| `--last DURATION` |
|
|
352
|
+
| `--since DATE` | Only calls at or after DATE (ISO 8601 with timezone); sessions with no in-window call are dropped |
|
|
353
|
+
| `--until DATE` | Only calls at or before DATE (ISO 8601 with timezone) |
|
|
354
|
+
| `--last DURATION` | Rolling call window such as `7d`, `24h`, or `30m` (`span`, `skills`, `calls`) |
|
|
279
355
|
| `--workspace PATH` | Only sessions from this workspace folder |
|
|
280
356
|
| `--aggregate` | Aggregate all matching sessions into one summary |
|
|
281
357
|
| `--summary` | Output a cost-efficiency summary |
|
|
@@ -326,11 +402,12 @@ Title: Implementation of new feature X
|
|
|
326
402
|
Started: 2026-07-01T20:37:34Z
|
|
327
403
|
Duration: 40588s (active: 1083s)
|
|
328
404
|
Models: claude-sonnet-4.6, claude-haiku-4.5, Kimi-K2.6-azure
|
|
329
|
-
Input: 1,425,790 tokens
|
|
405
|
+
Input: 1,425,790 tokens (incl. cache)
|
|
330
406
|
Output: 22,166 tokens
|
|
331
407
|
Cached: 1,224,340 (86%)
|
|
408
|
+
Uncached: 201,450
|
|
332
409
|
LLM calls: 28
|
|
333
|
-
|
|
410
|
+
Cost: $1.0880 (billed)
|
|
334
411
|
# Per-skill cost breakdown
|
|
335
412
|
$ copilot-session-usage id 19e03be0-9cfa-4f21-a19a-4bdb754b3965 --skill-breakdown --format table
|
|
336
413
|
Per-Skill Breakdown:
|
|
@@ -403,6 +480,7 @@ from copilot_session_usage.api import (
|
|
|
403
480
|
batch_analyze,
|
|
404
481
|
aggregate_sessions,
|
|
405
482
|
list_sessions,
|
|
483
|
+
list_calls,
|
|
406
484
|
)
|
|
407
485
|
|
|
408
486
|
# Analyze a session by path
|
|
@@ -428,6 +506,9 @@ sessions = list_sessions(
|
|
|
428
506
|
# providers with the explicit opt-in agent="all"
|
|
429
507
|
cli_result = analyze_session(Path("~/.copilot/session-state/<uuid>"), agent="cli")
|
|
430
508
|
combined = list_sessions(agent="all")
|
|
509
|
+
|
|
510
|
+
# Normalized per-call records (calls filtered by timestamp)
|
|
511
|
+
calls = list_calls(agent="cli", since="2026-07-01T00:00:00Z")
|
|
431
512
|
```
|
|
432
513
|
|
|
433
514
|
## Development
|
|
@@ -14,6 +14,48 @@ VS Code Copilot debug logs and/or local Copilot CLI/Copilot App session logs.
|
|
|
14
14
|
|
|
15
15
|
**Full documentation:** [copilot-session-usage.readthedocs.io](https://copilot-session-usage.readthedocs.io/en/stable/)
|
|
16
16
|
|
|
17
|
+
## Why not just ask Copilot to write a script?
|
|
18
|
+
|
|
19
|
+
You can: the logs are local JSONL. But every ad-hoc script re-learns the log
|
|
20
|
+
formats, and the plausible-looking answer is often wrong. This tool encodes the
|
|
21
|
+
rules once, is tested against them, and proves its own result on every run
|
|
22
|
+
(`reconciliation` block). An agent calls one command instead of spending tokens
|
|
23
|
+
on re-deriving, and possibly mis-deriving, the calculation.
|
|
24
|
+
|
|
25
|
+
How hard it is depends on the provider:
|
|
26
|
+
|
|
27
|
+
| | VS Code (`--agent vscode`) | Copilot CLI / App (`--agent cli`) |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Where the billed cost is | One event type (`llm_request`) carries the billed `copilotUsageNanoAiu` per call | Spread over several event types: `session.usage_record` per call, `session.compaction_complete` for compactions, and cumulative `session.shutdown` / `session.usage_checkpoint` snapshots |
|
|
30
|
+
| Obvious script | Sum the per-call nanoAIU | Read the last shutdown snapshot |
|
|
31
|
+
| Is the obvious script right? | **Total: mostly yes.** Breakdowns still need care | **No.** Snapshots miss everything after the last shutdown, sessions that never shut down, and (inconsistently) compactions |
|
|
32
|
+
| Traps the tool handles | Errored requests without usage, free utility models, subagent files (`runSubagent-*.jsonl`), no cache-write count logged | Dedup by `accounting.usageId`, compaction calls and their nested `requestCount`, per-agent skill timeline, utility models, sessions resumed long after creation |
|
|
33
|
+
| Value of the tool | Convenience and reproducible breakdowns (model, subagent, skill, time window) | **Correct totals in the first place**, plus the same breakdowns |
|
|
34
|
+
|
|
35
|
+
Pitfalls that affect both providers:
|
|
36
|
+
|
|
37
|
+
- `input_tokens` already **includes** cached and cache-written tokens. Adding
|
|
38
|
+
`input + cached` doubles the token count and halves "cost per token".
|
|
39
|
+
- A cache ratio averaged per session is not the real one. Weight it by tokens.
|
|
40
|
+
- A time window must select **calls by timestamp**. Selecting sessions by creation
|
|
41
|
+
date drops long-running sessions and counts calls outside the window.
|
|
42
|
+
- Recomputing from a price table needs the cache-write premium and the
|
|
43
|
+
long-context tier per call. The tool uses the billed amount whenever it is
|
|
44
|
+
logged, and keeps the price table as a cross-check.
|
|
45
|
+
|
|
46
|
+
Errors measured on ten days of real usage before these rules were in place:
|
|
47
|
+
|
|
48
|
+
| Mistake | Impact |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| CLI cost from the last shutdown snapshot | ~32% of the cost not attributed to any model, ~28% of input tokens missing |
|
|
51
|
+
| CLI compactions ignored | ~3% of the CLI cost missing |
|
|
52
|
+
| `input + cached` as total tokens | Token count ~2× too high |
|
|
53
|
+
| Unweighted cache ratio | 0.80 reported instead of 0.95 |
|
|
54
|
+
|
|
55
|
+
With the per-call pipeline, totals match an independent sum of billed amounts
|
|
56
|
+
to the micro-dollar on both providers. The token-based recomputation stays
|
|
57
|
+
within 0.2% (`reconciliation.delta_pct`).
|
|
58
|
+
|
|
17
59
|
## Chronicle and copilot-session-usage
|
|
18
60
|
|
|
19
61
|
GitHub Copilot provides **Chronicle** session tools for conversational access to your
|
|
@@ -52,7 +94,7 @@ Copilot CLI/App event logs and turns them into repeatable reports. It provides:
|
|
|
52
94
|
| Estimated cost (`$`) **per model** | ❌ No accurate cost per breakdown | ✅ |
|
|
53
95
|
| Tokens **per subagent** | ⚠️ LLM digging each time; consumes tokens | ✅ |
|
|
54
96
|
| Estimated cost (`$`) **per subagent** | ❌ No accurate cost per breakdown | ✅ |
|
|
55
|
-
| Cost attribution to skills | ❌ Cannot provide cost per breakdown | ✅ Limited timeline attribution
|
|
97
|
+
| Cost attribution to skills | ❌ Cannot provide cost per breakdown | ✅ Limited timeline attribution |
|
|
56
98
|
| Tool-call counts by skill and subagent | ⚠️ LLM digging each time | ✅ |
|
|
57
99
|
| Batch analysis, filtering, and aggregation | Limited/conversational | ✅ |
|
|
58
100
|
| Stable JSON, table, and detailed output | No stable contract | ✅ |
|
|
@@ -64,11 +106,11 @@ In the table, `⚠️` means that Chronicle may answer the question in a particu
|
|
|
64
106
|
environment or with additional analysis, but does not guarantee a stable, reproducible
|
|
65
107
|
breakdown for it.
|
|
66
108
|
|
|
67
|
-
Skill token and cost attribution is limited: VS Code
|
|
68
|
-
|
|
69
|
-
later work until another invocation.
|
|
70
|
-
or cost caused by the skill;
|
|
71
|
-
|
|
109
|
+
Skill token and cost attribution is limited: requests (VS Code) and calls
|
|
110
|
+
(CLI/App, per agent) are grouped under the latest explicit skill invocation,
|
|
111
|
+
including the whole request context and later work until another invocation.
|
|
112
|
+
This is not an isolated measurement of tokens or cost caused by the skill;
|
|
113
|
+
automatically loaded and overlapping skills cannot be separated. See
|
|
72
114
|
[Skill attribution](docs/source/explanation/how-cost-estimation-works.md#skill-attribution).
|
|
73
115
|
|
|
74
116
|
Use Chronicle for **“What did I do?”** and use this project for **“How much did it cost,
|
|
@@ -88,12 +130,46 @@ with `--agent` (default `vscode`):
|
|
|
88
130
|
Commands never mix providers unless `--agent all` is passed. Missing
|
|
89
131
|
provider roots are ignored, including when both roots are absent.
|
|
90
132
|
|
|
91
|
-
Both providers
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
133
|
+
Both providers feed **one per-call pipeline**: every LLM call becomes a
|
|
134
|
+
normalized record, and all totals, model rows, subagent rows and skill rows are
|
|
135
|
+
sums of those records (export them with `copilot-session-usage calls`). They
|
|
136
|
+
share the same model catalog, pricing data, cache rules, and estimated-USD
|
|
137
|
+
calculation. JSON reports carry `"schema_version": 2`. Missing evidence is
|
|
138
|
+
never turned into a fabricated zero: a CLI/App session with no usage records
|
|
139
|
+
yields `null` totals and a `diagnostics` entry.
|
|
140
|
+
|
|
141
|
+
## Don't recompute costs yourself
|
|
142
|
+
|
|
143
|
+
This tool is the reference calculation. Scripts that re-derive costs from token
|
|
144
|
+
counts routinely get these wrong, so rely on `span`, `calls` and the
|
|
145
|
+
`reconciliation` block instead:
|
|
146
|
+
|
|
147
|
+
- `input_tokens` **includes cache reads and cache writes**. `cached_tokens` and
|
|
148
|
+
`cache_write_tokens` are subsets; `uncached_input_tokens` is the remainder.
|
|
149
|
+
Adding them up double-counts (the old `total_tokens` field was removed).
|
|
150
|
+
- **Cache writes are billed at a premium** over the base input rate.
|
|
151
|
+
- **VS Code logs no cache-write count** (`cache_write_tokens` is `null`).
|
|
152
|
+
- **CLI compactions are separate events** (`session.compaction_complete`); they
|
|
153
|
+
are included as `kind: "compaction"` calls.
|
|
154
|
+
- **CLI shutdown snapshots are incomplete**; they are used only for the
|
|
155
|
+
`snapshot_usd`/`snapshot_delta_usd` reconciliation check.
|
|
156
|
+
- **Utility models are free** (`gpt-4o*`, `gpt-4.1*`, `gpt-5.4-nano*`) and
|
|
157
|
+
excluded from totals on both providers.
|
|
158
|
+
- **The long-context tier is chosen per call**, from that call's input size.
|
|
159
|
+
|
|
160
|
+
Billed nanoAIU is used whenever logged (`cost_source: "billed"`); the price
|
|
161
|
+
table is only a fallback (`"estimated"`). Every session and span carries
|
|
162
|
+
`reconciliation` (`billed_usd`, `estimated_from_tokens_usd`, `delta_pct`,
|
|
163
|
+
`calls_without_billing`) to verify the formula. See
|
|
164
|
+
[Don't recompute costs yourself](docs/source/explanation/how-cost-estimation-works.md#dont-recompute-costs-yourself).
|
|
165
|
+
|
|
166
|
+
Analysis is **offline**: pricing is never refreshed automatically. Run
|
|
167
|
+
`copilot-session-usage pricing refresh` to update it, or pass
|
|
168
|
+
`auto_refresh=True` in the Python API.
|
|
169
|
+
|
|
170
|
+
`--since`, `--until` and `--last` select **calls** by their own timestamp; a
|
|
171
|
+
session is kept only if it has an in-window call, and its totals count only
|
|
172
|
+
those calls.
|
|
97
173
|
|
|
98
174
|
```bash
|
|
99
175
|
# Analyze the latest Copilot CLI/App session
|
|
@@ -133,6 +209,9 @@ copilot-session-usage --agent all span \
|
|
|
133
209
|
--until 2026-07-08T00:00:00Z \
|
|
134
210
|
--format table
|
|
135
211
|
|
|
212
|
+
# Export every priced LLM call as JSONL (the building block of all totals)
|
|
213
|
+
copilot-session-usage --agent cli calls --last 7d --output calls.jsonl
|
|
214
|
+
|
|
136
215
|
# Aggregate cost across all sessions matching a PRD path
|
|
137
216
|
copilot-session-usage analyze --name "PRD: /path/to/prd" --aggregate --format table
|
|
138
217
|
|
|
@@ -155,11 +234,12 @@ copilot-session-usage list --dir /path/to/debug-logs --format table
|
|
|
155
234
|
- **Aggregation** — roll up costs across many sessions in one command
|
|
156
235
|
- **Skill-aware cost attribution** — detect skills, attribute LLM and tool calls to the active skill
|
|
157
236
|
- **Skill-source detection** — inspect slash commands, discovery events, system prompts, and skill tools
|
|
158
|
-
- **Skill cost breakdown** — per-skill token counts and estimated cost (
|
|
237
|
+
- **Skill cost breakdown** — per-skill token counts and estimated cost (both providers)
|
|
159
238
|
- **Tool-call attribution** — per-skill/per-subagent tool-call counts
|
|
160
239
|
- **Title filtering** — find sessions by title substring
|
|
161
240
|
- **Metadata cache** — reuse session indexes until the workspace database changes
|
|
162
|
-
- **Efficiency summaries** — cache ratio, model split,
|
|
241
|
+
- **Efficiency summaries** — token-weighted cache ratio, model split, reconciliation of billed vs. token-formula cost
|
|
242
|
+
- **Per-call export** — `calls` emits normalized JSONL records; `list_calls`/`iter_calls` in the API
|
|
163
243
|
- **Field extraction** — pull specific values with `--query`
|
|
164
244
|
|
|
165
245
|
## How it works
|
|
@@ -204,27 +284,22 @@ can be determined (from the directory name or a `session.start` event) —
|
|
|
204
284
|
otherwise it is rejected with an actionable error instead of being analyzed
|
|
205
285
|
with a fabricated identity.
|
|
206
286
|
|
|
207
|
-
Per-model token totals and cost come from the session's
|
|
208
|
-
`session.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
`provider_usage
|
|
219
|
-
|
|
287
|
+
Per-model token totals and cost come from the session's per-call records:
|
|
288
|
+
`session.usage_record` (one per LLM call, de-duplicated by `accounting.usageId`)
|
|
289
|
+
plus `session.compaction_complete` events (compactions, `kind: "compaction"`).
|
|
290
|
+
Each call uses its billed `totalNanoAiu` when present, else the shared
|
|
291
|
+
token-based pricing with the exact cache-write count. The cumulative
|
|
292
|
+
`session.shutdown`/`session.usage_checkpoint` snapshots are incomplete and used
|
|
293
|
+
only for the reconciliation diagnostic (`snapshot_usd`, `snapshot_delta_usd`).
|
|
294
|
+
A session that never shut down is therefore fully analyzed; only a session with
|
|
295
|
+
no usage records and no compaction usage has `null` totals, with `diagnostics`
|
|
296
|
+
explaining why. Calls are attributed to the subagent (`agentId`) and active
|
|
297
|
+
skill of their own agent, so the CLI/App provider has a costed skills
|
|
298
|
+
breakdown. `provider_usage` keeps informational counters such as
|
|
299
|
+
`total_premium_requests` and `resume_count`. Parsing
|
|
220
300
|
tolerates unrecognized event types and schema versions other than the one
|
|
221
301
|
currently validated, recording a diagnostic instead of failing.
|
|
222
302
|
|
|
223
|
-
Pricing lookups for `--agent cli`/`--agent all` are local-only by default
|
|
224
|
-
(no runtime pricing refresh attempt over the network), unlike the `vscode`
|
|
225
|
-
provider's default daily refresh attempt. Run
|
|
226
|
-
`copilot-session-usage pricing refresh` to update pricing explicitly.
|
|
227
|
-
|
|
228
303
|
## Knowledge base
|
|
229
304
|
|
|
230
305
|
This project includes an OKF knowledge bundle in `knowledge/` with structured
|
|
@@ -246,7 +321,8 @@ just knowledge-validate
|
|
|
246
321
|
| `id SESSION_ID` | Analyze a session by exact UUID |
|
|
247
322
|
| `list` | List recent sessions (metadata only by default) |
|
|
248
323
|
| `batch N` | Analyze the N most recent sessions in one pass |
|
|
249
|
-
| `span` | Emit a compact total, per-model, and per-session
|
|
324
|
+
| `span` | Emit a compact total, per-model, and per-session report (calls in the window) |
|
|
325
|
+
| `calls` | Export every priced LLM call as JSONL (one object per line) |
|
|
250
326
|
| `skills` | List skills used across sessions with aggregated cost |
|
|
251
327
|
|
|
252
328
|
### Analysis options
|
|
@@ -255,9 +331,9 @@ just knowledge-validate
|
|
|
255
331
|
|--------|-------------|
|
|
256
332
|
| `--name REGEX` | Filter sessions by title/ID regex (case-insensitive) |
|
|
257
333
|
| `--title SUBSTRING` | Filter sessions by title substring (case-insensitive) |
|
|
258
|
-
| `--since DATE` | Only
|
|
259
|
-
| `--until DATE` | Only
|
|
260
|
-
| `--last DURATION` |
|
|
334
|
+
| `--since DATE` | Only calls at or after DATE (ISO 8601 with timezone); sessions with no in-window call are dropped |
|
|
335
|
+
| `--until DATE` | Only calls at or before DATE (ISO 8601 with timezone) |
|
|
336
|
+
| `--last DURATION` | Rolling call window such as `7d`, `24h`, or `30m` (`span`, `skills`, `calls`) |
|
|
261
337
|
| `--workspace PATH` | Only sessions from this workspace folder |
|
|
262
338
|
| `--aggregate` | Aggregate all matching sessions into one summary |
|
|
263
339
|
| `--summary` | Output a cost-efficiency summary |
|
|
@@ -308,11 +384,12 @@ Title: Implementation of new feature X
|
|
|
308
384
|
Started: 2026-07-01T20:37:34Z
|
|
309
385
|
Duration: 40588s (active: 1083s)
|
|
310
386
|
Models: claude-sonnet-4.6, claude-haiku-4.5, Kimi-K2.6-azure
|
|
311
|
-
Input: 1,425,790 tokens
|
|
387
|
+
Input: 1,425,790 tokens (incl. cache)
|
|
312
388
|
Output: 22,166 tokens
|
|
313
389
|
Cached: 1,224,340 (86%)
|
|
390
|
+
Uncached: 201,450
|
|
314
391
|
LLM calls: 28
|
|
315
|
-
|
|
392
|
+
Cost: $1.0880 (billed)
|
|
316
393
|
# Per-skill cost breakdown
|
|
317
394
|
$ copilot-session-usage id 19e03be0-9cfa-4f21-a19a-4bdb754b3965 --skill-breakdown --format table
|
|
318
395
|
Per-Skill Breakdown:
|
|
@@ -385,6 +462,7 @@ from copilot_session_usage.api import (
|
|
|
385
462
|
batch_analyze,
|
|
386
463
|
aggregate_sessions,
|
|
387
464
|
list_sessions,
|
|
465
|
+
list_calls,
|
|
388
466
|
)
|
|
389
467
|
|
|
390
468
|
# Analyze a session by path
|
|
@@ -410,6 +488,9 @@ sessions = list_sessions(
|
|
|
410
488
|
# providers with the explicit opt-in agent="all"
|
|
411
489
|
cli_result = analyze_session(Path("~/.copilot/session-state/<uuid>"), agent="cli")
|
|
412
490
|
combined = list_sessions(agent="all")
|
|
491
|
+
|
|
492
|
+
# Normalized per-call records (calls filtered by timestamp)
|
|
493
|
+
calls = list_calls(agent="cli", since="2026-07-01T00:00:00Z")
|
|
413
494
|
```
|
|
414
495
|
|
|
415
496
|
## Development
|