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.
Files changed (134) hide show
  1. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/PKG-INFO +120 -39
  2. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/README.md +119 -38
  3. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/conf.py +1 -0
  4. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/explanation/how-cost-estimation-works.md +137 -64
  5. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/analyze-specific-session.md +4 -4
  6. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/batch-and-spending.md +27 -13
  7. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/copilot-cli-provider.md +36 -40
  8. copilot_session_usage-1.0.0/docs/source/how-to/export-json.md +85 -0
  9. copilot_session_usage-1.0.0/docs/source/reference/api.md +71 -0
  10. copilot_session_usage-1.0.0/docs/source/reference/cli.md +55 -0
  11. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/reference/pricing.md +36 -29
  12. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/tutorials/getting-started.md +9 -6
  13. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/skills/copilot-session-usage/SKILL.md +60 -17
  14. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/skills/copilot-session-usage/references/span-analysis-template.md +30 -16
  15. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/copilot_cli.py +267 -276
  16. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/core.py +852 -656
  17. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/vscode.py +25 -1
  18. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/api.py +190 -40
  19. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/cli.py +253 -79
  20. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/models-and-pricing.lock +3 -3
  21. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/models-and-pricing.yml +22 -0
  22. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/conftest.py +19 -0
  23. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_api.py +235 -2
  24. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_cli.py +185 -9
  25. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_copilot_cli.py +291 -196
  26. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_core.py +501 -151
  27. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_rendering.py +51 -50
  28. copilot_session_usage-1.0.0/tests/test_review_regressions.py +418 -0
  29. copilot_session_usage-0.9.4/docs/source/how-to/export-json.md +0 -65
  30. copilot_session_usage-0.9.4/docs/source/reference/api.md +0 -31
  31. copilot_session_usage-0.9.4/docs/source/reference/cli.md +0 -23
  32. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.editorconfig +0 -0
  33. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.gitattributes +0 -0
  34. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  35. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  36. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/changes/requests/skill-breakdown/01-request.md +0 -0
  37. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/guidelines/git-commit-message.guideline.md +0 -0
  38. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/guidelines/knowledge-base.guidelines.md +0 -0
  39. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/pull_request_template.md +0 -0
  40. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/consolidate-knowledge-base/SKILL.md +0 -0
  41. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-commit-changes/SKILL.md +0 -0
  42. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-create-pull-request/SKILL.md +0 -0
  43. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-release-notes/SKILL.md +0 -0
  44. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/gh-release-notes/scripts/generate_release_notes.py +0 -0
  45. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/record-finding/README.md +0 -0
  46. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/skills/record-finding/SKILL.md +0 -0
  47. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/ci.yml +0 -0
  48. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/publish.yml +0 -0
  49. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/refresh-pricing.yml +0 -0
  50. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/release-notes.yml +0 -0
  51. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.github/workflows/release.yml +0 -0
  52. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.gitignore +0 -0
  53. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/.readthedocs.yaml +0 -0
  54. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/AGENTS.md +0 -0
  55. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/CHANGELOG.md +0 -0
  56. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/CONSTITUTION.md +0 -0
  57. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/CONTRIBUTING.md +0 -0
  58. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/LICENSE +0 -0
  59. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/articles/presentation.md +0 -0
  60. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/internal/automated_release_proces.md +0 -0
  61. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/_static/changelog.js +0 -0
  62. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/_static/custom.css +0 -0
  63. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/changelog.md +0 -0
  64. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/explanation/index.md +0 -0
  65. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/add-commit-trailer.md +0 -0
  66. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/index.md +0 -0
  67. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/how-to/wsl2.md +0 -0
  68. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/index.md +0 -0
  69. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/installation.md +0 -0
  70. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/reference/index.md +0 -0
  71. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/docs/source/tutorials/index.md +0 -0
  72. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/guidelines.yml +0 -0
  73. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/justfile +0 -0
  74. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Base.schema.yaml +0 -0
  75. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Concept.schema.yaml +0 -0
  76. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Experiment.schema.yaml +0 -0
  77. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Finding.schema.yaml +0 -0
  78. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Hypothesis.schema.yaml +0 -0
  79. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Outcome.schema.yaml +0 -0
  80. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Playbook.schema.yaml +0 -0
  81. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Principle.schema.yaml +0 -0
  82. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Reference.schema.yaml +0 -0
  83. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/_schema/Structure.schema.yaml +0 -0
  84. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/copilot-cli.md +0 -0
  85. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/index.md +0 -0
  86. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/overview.md +0 -0
  87. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/session-cost-analysis.md +0 -0
  88. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/concepts/threshold-based-pricing.md +0 -0
  89. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/experiments/index.md +0 -0
  90. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/experiments/verify-subagent-cost-attribution.md +0 -0
  91. {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
  92. {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
  93. {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
  94. {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
  95. {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
  96. {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
  97. {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
  98. {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
  99. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/findings/index.md +0 -0
  100. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/automation-scripts.md +0 -0
  101. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/cost-optimization.md +0 -0
  102. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/index.md +0 -0
  103. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/guides/wsl2-setup.md +0 -0
  104. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/ideas/index.md +0 -0
  105. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/ideas/multi-session-efficiency-analytics.md +0 -0
  106. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/index.md +0 -0
  107. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/log.md +0 -0
  108. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/principles/findings-are-immutable.md +0 -0
  109. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/principles/index.md +0 -0
  110. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/reference/debug-log-format.md +0 -0
  111. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/reference/index.md +0 -0
  112. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/reference/pricing-formats.md +0 -0
  113. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/cache-cost-approximation.md +0 -0
  114. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/index.md +0 -0
  115. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/knowledge-base-information-types.md +0 -0
  116. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/session-discovery-algorithm.md +0 -0
  117. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/subagent-cost-tracking.md +0 -0
  118. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/knowledge/structures/vscode-copilot-extension.md +0 -0
  119. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/pyproject.toml +0 -0
  120. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/scripts/refresh_pricing.py +0 -0
  121. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/__init__.py +0 -0
  122. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/__init__.py +0 -0
  123. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/_internal/git.py +0 -0
  124. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/__init__.py +0 -0
  125. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/src/copilot_session_usage/data/custom-models-pricing.yml +0 -0
  126. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_coverage_gaps.py +0 -0
  127. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_generate_release_notes.py +0 -0
  128. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_git.py +0 -0
  129. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_pricing_runtime.py +0 -0
  130. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_release_notes.py +0 -0
  131. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_vscode.py +0 -0
  132. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/tests/test_vscode_platform.py +0 -0
  133. {copilot_session_usage-0.9.4 → copilot_session_usage-1.0.0}/uv.lock +0 -0
  134. {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.9.4
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 (VS Code) |
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 requests are grouped under
86
- the latest explicit slash-command skill, including the whole request context and
87
- later work until another invocation. This is not an isolated measurement of tokens
88
- or cost caused by the skill; automatically loaded and overlapping skills cannot be
89
- separated. CLI/App per-skill tokens and costs are unavailable. See
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 share the same model catalog, pricing data, cache rules, and
110
- estimated-USD calculation. Copilot CLI/App sessions additionally expose
111
- provider-native counters (`provider_usage`: nanoAiu, premium requests) as
112
- separate fields, and never turn missing evidence (for example, a session that
113
- has not shut down yet) into a fabricated zero — see `diagnostics` in the
114
- output when data is unavailable.
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 (VS Code provider)
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, cost per 1M tokens
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 final
226
- `session.shutdown` event and use the same shared, token-based pricing
227
- calculation as the VS Code provider. GitHub Copilot's own `totalNanoAiu`
228
- billing figure is kept separate under `provider_usage.total_nano_aiu` and
229
- never substituted into the shared cost calculation. For a session that has
230
- not shut down yet (still active, or interrupted), only provider-native
231
- counters from the last usage checkpoint are available; token totals and cost
232
- are reported as unavailable (`null`) via the shared `total` block, with
233
- `diagnostics` explaining why, rather than as fabricated zeros. Tool calls and
234
- skill attribution are scoped to the subagent that made them, using
235
- `subagent.started`/`subagent.completed` events and each event's `agentId`;
236
- `provider_usage.subagents` separately preserves the raw per-subagent evidence
237
- available (name, model, tool-call count, reported tokens, duration). Parsing
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 date-span report |
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 sessions created after DATE (ISO 8601 with timezone) |
277
- | `--until DATE` | Only sessions created before DATE (ISO 8601 with timezone) |
278
- | `--last DURATION` | Use a rolling window such as `7d`, `24h`, or `30m` with `span` |
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
- Est. cost: $1.0880
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 (VS Code) |
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 requests are grouped under
68
- the latest explicit slash-command skill, including the whole request context and
69
- later work until another invocation. This is not an isolated measurement of tokens
70
- or cost caused by the skill; automatically loaded and overlapping skills cannot be
71
- separated. CLI/App per-skill tokens and costs are unavailable. See
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 share the same model catalog, pricing data, cache rules, and
92
- estimated-USD calculation. Copilot CLI/App sessions additionally expose
93
- provider-native counters (`provider_usage`: nanoAiu, premium requests) as
94
- separate fields, and never turn missing evidence (for example, a session that
95
- has not shut down yet) into a fabricated zero — see `diagnostics` in the
96
- output when data is unavailable.
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 (VS Code provider)
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, cost per 1M tokens
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 final
208
- `session.shutdown` event and use the same shared, token-based pricing
209
- calculation as the VS Code provider. GitHub Copilot's own `totalNanoAiu`
210
- billing figure is kept separate under `provider_usage.total_nano_aiu` and
211
- never substituted into the shared cost calculation. For a session that has
212
- not shut down yet (still active, or interrupted), only provider-native
213
- counters from the last usage checkpoint are available; token totals and cost
214
- are reported as unavailable (`null`) via the shared `total` block, with
215
- `diagnostics` explaining why, rather than as fabricated zeros. Tool calls and
216
- skill attribution are scoped to the subagent that made them, using
217
- `subagent.started`/`subagent.completed` events and each event's `agentId`;
218
- `provider_usage.subagents` separately preserves the raw per-subagent evidence
219
- available (name, model, tool-call count, reported tokens, duration). Parsing
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 date-span report |
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 sessions created after DATE (ISO 8601 with timezone) |
259
- | `--until DATE` | Only sessions created before DATE (ISO 8601 with timezone) |
260
- | `--last DURATION` | Use a rolling window such as `7d`, `24h`, or `30m` with `span` |
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
- Est. cost: $1.0880
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
@@ -22,6 +22,7 @@ extensions = [
22
22
  ]
23
23
 
24
24
  myst_enable_extensions = ["colon_fence", "deflist"]
25
+ myst_heading_anchors = 3
25
26
 
26
27
  html_theme = "furo"
27
28
  html_theme_options = {