coding-agent-cost 0.1.0__tar.gz → 0.1.1__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.
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/PKG-INFO +172 -22
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/README.md +168 -21
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/__init__.py +1 -1
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/aggregate.py +8 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/rates.json +42 -2
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/readers/codex.py +134 -3
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/coding_agent_cost.egg-info/PKG-INFO +172 -22
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/coding_agent_cost.egg-info/SOURCES.txt +1 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/pyproject.toml +11 -1
- coding_agent_cost-0.1.1/tests/test_astra_pricing.py +338 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/LICENSE +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/cli.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/config.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/facts.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/rates.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/readers/__init__.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/readers/claude.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/agent_cost/renderers.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/coding_agent_cost.egg-info/dependency_links.txt +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/coding_agent_cost.egg-info/entry_points.txt +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/coding_agent_cost.egg-info/top_level.txt +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/setup.cfg +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/tests/test_aggregate.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/tests/test_cli.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/tests/test_facts.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/tests/test_measure_v1_contract.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/tests/test_rates.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/tests/test_reader_claude.py +0 -0
- {coding_agent_cost-0.1.0 → coding_agent_cost-0.1.1}/tests/test_reader_codex.py +0 -0
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: coding-agent-cost
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Estimate AI coding agent (Claude Code / Codex CLI) token usage and cost from local logs
|
|
5
5
|
Author: shiki-yusuke
|
|
6
6
|
License: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/shiki-yusuke/agent-cost
|
|
8
|
+
Project-URL: Repository, https://github.com/shiki-yusuke/agent-cost
|
|
9
|
+
Project-URL: Issues, https://github.com/shiki-yusuke/agent-cost/issues
|
|
10
|
+
Keywords: ai-agents,claude-code,codex-cli,cost-estimation,local-first,token-usage
|
|
8
11
|
Classifier: Development Status :: 3 - Alpha
|
|
9
12
|
Classifier: Environment :: Console
|
|
10
13
|
Classifier: Intended Audience :: Developers
|
|
@@ -23,30 +26,159 @@ Dynamic: license-file
|
|
|
23
26
|
|
|
24
27
|
# agent-cost
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
> command (`agent-cost`) and import name (`agent_cost`) are unchanged. The name `agent-cost`
|
|
28
|
-
> itself is blocked by PyPI's name-similarity rule against `agentcost`, an unrelated project
|
|
29
|
-
> by a different author; this tool is not affiliated with it.
|
|
30
|
-
|
|
31
|
-
Estimate how many tokens Claude Code and Codex CLI actually used, and roughly
|
|
32
|
-
what that cost, by reading the local logs those tools already write to your
|
|
29
|
+
See Claude Code and Codex CLI token usage and estimated costs from the logs already on your
|
|
33
30
|
machine.
|
|
34
31
|
|
|
35
|
-
|
|
32
|
+
Keep pricing gaps visible: unknown models are marked `unpriced`, and cache-write estimates
|
|
33
|
+
with missing TTL information are marked `lower_bound`. JSON reports include the rate catalog
|
|
34
|
+
version and SHA-256 used for the calculation; the catalog records its pricing sources.
|
|
35
|
+
|
|
36
|
+
**These are estimates based on the selected rate catalog, not your actual bill.** The CLI makes
|
|
37
|
+
no runtime network calls and has zero runtime dependencies. On macOS and Linux with IANA
|
|
38
|
+
timezone data, no account, service, or project configuration is required. See the
|
|
39
|
+
[platform note](#report-and-export) for minimal Windows Python environments.
|
|
40
|
+
|
|
41
|
+
Need the result in another program? [`agent-cost measure`](#machine-consumption-agent-cost-measure)
|
|
42
|
+
returns versioned `measure/v1` JSON for session IDs you supply. Task and PR attribution remain
|
|
43
|
+
the caller's responsibility.
|
|
44
|
+
|
|
45
|
+
[日本語サマリ](#日本語サマリ) · [Synthetic output example](#synthetic-output-example)
|
|
46
|
+
|
|
47
|
+
## Try it on your machine
|
|
48
|
+
|
|
49
|
+
With [`uvx`](https://docs.astral.sh/uv/guides/tools/), no persistent install is needed:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uvx --from coding-agent-cost agent-cost doctor
|
|
53
|
+
uvx --from coding-agent-cost agent-cost report
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The package runner may need network access to download the tool. The CLI itself does not upload
|
|
57
|
+
your logs.
|
|
58
|
+
|
|
59
|
+
The first command checks the expected local paths, the Codex database, and the bundled rate
|
|
60
|
+
catalog. It does not open every Claude JSONL file. The second command performs the real scan,
|
|
61
|
+
prints the result, and exposes unreadable inputs in `data_quality.skipped_files`. This path was
|
|
62
|
+
exercised on macOS from a clean temporary directory against the published `0.1.0` package on
|
|
63
|
+
2026-08-23.
|
|
64
|
+
|
|
65
|
+
Prefer a persistent command? Install the PyPI distribution, then run the same two commands:
|
|
36
66
|
|
|
37
67
|
```bash
|
|
38
|
-
pip install coding-agent-cost
|
|
39
|
-
agent-cost doctor
|
|
68
|
+
pip install coding-agent-cost
|
|
69
|
+
agent-cost doctor
|
|
40
70
|
agent-cost report
|
|
41
71
|
```
|
|
42
72
|
|
|
43
|
-
`agent-cost
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
73
|
+
The PyPI distribution is named [`coding-agent-cost`](https://pypi.org/project/coding-agent-cost/),
|
|
74
|
+
while the command remains `agent-cost` and the import remains `agent_cost`. The shorter PyPI
|
|
75
|
+
name is unavailable because of PyPI's similarity rule; this project is not affiliated with the
|
|
76
|
+
unrelated `agentcost` distribution.
|
|
77
|
+
|
|
78
|
+
## Synthetic output example
|
|
79
|
+
|
|
80
|
+
This is **synthetic Claude data**, not observed usage, a bill, or evidence of savings. The
|
|
81
|
+
CLI output below was reproduced with PyPI package `coding-agent-cost==0.1.0` and source
|
|
82
|
+
commit `d170ea301ed0c46351749214bd299e75ae8a7786` (only trailing space padding is omitted).
|
|
83
|
+
The [two-event fixture](examples/synthetic-claude.jsonl) contains known-model input, cache
|
|
84
|
+
writes without a TTL breakdown, and unknown-model input.
|
|
48
85
|
|
|
86
|
+
```text
|
|
87
|
+
Month Agent Model Token Kind Tokens Priced Unpriced Est. Cost (USD) Credits Status
|
|
88
|
+
------- ------ -------------------- ------------------- ------- ------- -------- --------------- ------- -----------
|
|
89
|
+
2026-06 claude claude-opus-4-8 cache_write_unknown 1000000 1000000 0 6.2500 - lower_bound
|
|
90
|
+
2026-06 claude claude-opus-4-8 input_nocache 1000000 1000000 0 5.0000 - priced
|
|
91
|
+
2026-06 claude model-not-in-catalog input_nocache 500 0 500 0.0000 - unpriced
|
|
92
|
+
|
|
93
|
+
Total tokens: 2,000,500 Total estimated cost: $11.2500
|
|
94
|
+
Rates catalog: 2026-07-29 (sha256=5d86e11b3c95...)
|
|
95
|
+
Data quality: malformed_events=0 skipped_files=0 negative_deltas=0 unpriced_tokens=500
|
|
49
96
|
```
|
|
97
|
+
|
|
98
|
+
- `priced`: $5.0000 is a catalog-based estimate for 1,000,000 input tokens, not a confirmed charge.
|
|
99
|
+
- `lower_bound`: $6.2500 uses the 5-minute cache-write rate because the TTL is missing. This is
|
|
100
|
+
a lower bound under the catalog and observed token data, not a lower bound on your actual bill.
|
|
101
|
+
- `unpriced`: `0.0000` does not mean free. Read `pricing_status` (the `Status` column) together
|
|
102
|
+
with `unpriced_tokens` (`Unpriced`): 500 tokens have no price and are excluded from the dollar
|
|
103
|
+
total. The $11.2500 total also includes the cache-write lower-bound estimate.
|
|
104
|
+
|
|
105
|
+
<details>
|
|
106
|
+
<summary>Reproduce with synthetic data only (Python 3.9+ and uvx)</summary>
|
|
107
|
+
|
|
108
|
+
Run from this repository's root. Both log locations and the config file are explicitly set
|
|
109
|
+
inside a temporary directory. Inherited log-location overrides are removed for the child
|
|
110
|
+
process, so it cannot fall back to your real Claude or Codex logs. The temporary data is
|
|
111
|
+
removed when the command exits. The package runner may download the pinned package.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
python3 - <<'PY'
|
|
115
|
+
import json
|
|
116
|
+
import os
|
|
117
|
+
from pathlib import Path
|
|
118
|
+
import shutil
|
|
119
|
+
import subprocess
|
|
120
|
+
import tempfile
|
|
121
|
+
|
|
122
|
+
fixture = Path("examples/synthetic-claude.jsonl").resolve()
|
|
123
|
+
with tempfile.TemporaryDirectory(prefix="agent-cost-example-") as directory:
|
|
124
|
+
root = Path(directory)
|
|
125
|
+
project = root / "claude" / "projects" / "synthetic"
|
|
126
|
+
project.mkdir(parents=True)
|
|
127
|
+
(root / "codex").mkdir()
|
|
128
|
+
shutil.copyfile(fixture, project / "session.jsonl")
|
|
129
|
+
config = root / "config.json"
|
|
130
|
+
config.write_text(json.dumps({
|
|
131
|
+
"claude_home": str(root / "claude"),
|
|
132
|
+
"codex_home": str(root / "codex"),
|
|
133
|
+
}))
|
|
134
|
+
env = dict(os.environ)
|
|
135
|
+
for key in ("CLAUDE_HOME", "CODEX_HOME", "PYTHONPATH"):
|
|
136
|
+
env.pop(key, None)
|
|
137
|
+
env["AGENT_COST_CONFIG"] = str(config)
|
|
138
|
+
subprocess.run([
|
|
139
|
+
"uvx", "--from", "coding-agent-cost==0.1.0", "agent-cost",
|
|
140
|
+
"report", "--agent", "claude", "--since", "2026-06-01",
|
|
141
|
+
"--until", "2026-06-02", "--format", "table",
|
|
142
|
+
], cwd=root, env=env, check=True)
|
|
143
|
+
PY
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Use `--format json` in the same command to see the full catalog SHA-256 and field names.
|
|
147
|
+
|
|
148
|
+
</details>
|
|
149
|
+
|
|
150
|
+
## Why this exists
|
|
151
|
+
|
|
152
|
+
Many usage trackers are designed as rich, convenient dashboards. That can be the right choice
|
|
153
|
+
when broad agent coverage and interactive exploration matter most. `agent-cost` is for a
|
|
154
|
+
different trust model:
|
|
155
|
+
|
|
156
|
+
- **Local-first and zero-network:** source logs stay on disk; the package has zero runtime
|
|
157
|
+
dependencies.
|
|
158
|
+
- **Auditable:** token facts, the versioned rate catalog, its digest, and data-quality counters
|
|
159
|
+
are available for inspection and machine consumption.
|
|
160
|
+
- **Fail-closed pricing:** unknown models remain `unpriced`; ambiguous cache-write TTLs are
|
|
161
|
+
labeled `lower_bound` instead of silently receiving a best-guess price.
|
|
162
|
+
- **Explicit attribution boundary:** `measure` accepts named session ids, but agent-cost does
|
|
163
|
+
not infer a task from a branch or PR. A workflow such as
|
|
164
|
+
[`spec-lane`](https://github.com/shiki-yusuke/spec-lane) can own the session-to-task binding
|
|
165
|
+
and consume the versioned JSON result.
|
|
166
|
+
|
|
167
|
+
This is not a claim that local CLI accounting is universally better than a dashboard. It is a
|
|
168
|
+
smaller primitive for environments where data egress, dependency surface, custom metrics, or
|
|
169
|
+
task attribution need to remain under the operator's control.
|
|
170
|
+
|
|
171
|
+
See [Choosing by use case and trust model](https://github.com/shiki-yusuke/agent-cost/blob/main/docs/comparison.md)
|
|
172
|
+
for a dated, source-linked comparison with broader CLI trackers, local dashboards, and
|
|
173
|
+
observability stacks.
|
|
174
|
+
|
|
175
|
+
## Report and export
|
|
176
|
+
|
|
177
|
+
`agent-cost report` turns each local usage event into a canonical fact (one model, one token
|
|
178
|
+
kind, one timestamp, one count), prices each fact against the bundled rate catalog, and prints
|
|
179
|
+
an aggregated table:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
50
182
|
agent-cost report --since 2026-06-01 --until 2026-07-01 --format table
|
|
51
183
|
agent-cost report --group-by month,agent --format csv
|
|
52
184
|
agent-cost report --format json > usage.json
|
|
@@ -58,6 +190,11 @@ interpreted in `--timezone`, default UTC), `--agent claude,codex`,
|
|
|
58
190
|
`--group-by month,agent,model,token-kind`, `--rates PATH` (use a different
|
|
59
191
|
catalog entirely, see below), `--exclude-archived` (Codex threads).
|
|
60
192
|
|
|
193
|
+
**Platform note:** `report`, `export`, and `measure` use Python's IANA timezone database even
|
|
194
|
+
when the timezone is `UTC`. macOS and typical Linux installations provide it through the
|
|
195
|
+
operating system. A minimal Windows Python environment may require `pip install tzdata` first;
|
|
196
|
+
`tzdata` is not currently a declared package dependency.
|
|
197
|
+
|
|
61
198
|
If another program wants to parse agent-cost's output for one or more
|
|
62
199
|
specific session ids, see `agent-cost measure` below rather than
|
|
63
200
|
scraping `report`.
|
|
@@ -75,10 +212,12 @@ network, never calls `gh`, and never resolves branches or PRs.
|
|
|
75
212
|
at the 5-minute rate as an explicit **lower bound** and flagged
|
|
76
213
|
`lower_bound` rather than guessed at the (more expensive) 1-hour rate.
|
|
77
214
|
- **Codex CLI**: rollout files record a *cumulative* token count after each
|
|
78
|
-
turn; agent-cost turns that into per-turn deltas.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
215
|
+
turn; agent-cost turns that into per-turn deltas. Under the Codex token-rate
|
|
216
|
+
tariff used here, cache writes are not added as a separate charge. The current
|
|
217
|
+
reader does not emit independent cache-write facts; newer logs can include
|
|
218
|
+
`cache_write_input_tokens`, but this field is not used to add a cache-write
|
|
219
|
+
charge. This differs from older logs where that signal was unavailable.
|
|
220
|
+
Codex's `output` fact is `output_tokens` alone: cross-checking
|
|
82
221
|
real rollout files confirms `total_tokens == input_tokens + output_tokens`
|
|
83
222
|
in every sample, which means `reasoning_output_tokens` is a breakdown of
|
|
84
223
|
output tokens already counted, not an additional charge -- adding it in
|
|
@@ -115,6 +254,15 @@ network, never calls `gh`, and never resolves branches or PRs.
|
|
|
115
254
|
|
|
116
255
|
## Updating the rate catalog
|
|
117
256
|
|
|
257
|
+
**GPT-6 Astra:** Codex Standard/Fast estimates use exact ID `gpt-6-astra` and
|
|
258
|
+
owned settings matched to turn/model context in the public Codex 0.153.4 JSONL
|
|
259
|
+
format. Explicit `default` uses Standard; `priority` uses 2.5x. Missing/ambiguous
|
|
260
|
+
tier or model attribution stays `unpriced`, with tokens preserved. These are
|
|
261
|
+
request-setting estimates, not confirmed processing tiers or actual bills.
|
|
262
|
+
The catalog observation cutoff is not an official launch time; earlier usage
|
|
263
|
+
is `unpriced`. See [evidence, synthetic tests and model-switch limits](docs/astra-pricing.md).
|
|
264
|
+
API pricing and legacy message billing are outside this entry.
|
|
265
|
+
|
|
118
266
|
Prices live in `agent_cost/rates.json`, not in code. It's a historical
|
|
119
267
|
catalog: each model can have several time-bounded rate periods, so a price
|
|
120
268
|
change is recorded as a new period rather than overwriting the old one (see
|
|
@@ -224,8 +372,10 @@ MIT. See [LICENSE](LICENSE).
|
|
|
224
372
|
|
|
225
373
|
- 集計の最小単位は「1 イベント = 1 モデル × 1 token 種別」の fact であり、session 単位でモデルを
|
|
226
374
|
丸めません。Claude の prompt cache は TTL 内訳(5分/1時間)が取れればそれを使い、取れない場合は
|
|
227
|
-
5分単価で **下限推計**(`lower_bound
|
|
228
|
-
|
|
375
|
+
5分単価で **下限推計**(`lower_bound`)として明示します。対象の Codex トークン料金体系では
|
|
376
|
+
cache write を別料金として加算せず、現行 reader は独立した cache-write fact を出力しません。
|
|
377
|
+
新しいログに `cache_write_input_tokens` が含まれていても追加料金の計算には使用しません。
|
|
378
|
+
これは、旧ログでその情報を観測できないこととは区別します。
|
|
229
379
|
- 出力フィールドは `estimated_cost_usd`(推計であることを明示)。Codex は `credits` も併記します。
|
|
230
380
|
未知のモデル・単価表にない token 種別は `unpriced` として扱い、憶測の価格を出しません。
|
|
231
381
|
- 単価表 (`agent_cost/rates.json`) は履歴型カタログで、値上げは新しい期間として追加します。
|
|
@@ -1,29 +1,158 @@
|
|
|
1
1
|
# agent-cost
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
> command (`agent-cost`) and import name (`agent_cost`) are unchanged. The name `agent-cost`
|
|
5
|
-
> itself is blocked by PyPI's name-similarity rule against `agentcost`, an unrelated project
|
|
6
|
-
> by a different author; this tool is not affiliated with it.
|
|
7
|
-
|
|
8
|
-
Estimate how many tokens Claude Code and Codex CLI actually used, and roughly
|
|
9
|
-
what that cost, by reading the local logs those tools already write to your
|
|
3
|
+
See Claude Code and Codex CLI token usage and estimated costs from the logs already on your
|
|
10
4
|
machine.
|
|
11
5
|
|
|
12
|
-
|
|
6
|
+
Keep pricing gaps visible: unknown models are marked `unpriced`, and cache-write estimates
|
|
7
|
+
with missing TTL information are marked `lower_bound`. JSON reports include the rate catalog
|
|
8
|
+
version and SHA-256 used for the calculation; the catalog records its pricing sources.
|
|
9
|
+
|
|
10
|
+
**These are estimates based on the selected rate catalog, not your actual bill.** The CLI makes
|
|
11
|
+
no runtime network calls and has zero runtime dependencies. On macOS and Linux with IANA
|
|
12
|
+
timezone data, no account, service, or project configuration is required. See the
|
|
13
|
+
[platform note](#report-and-export) for minimal Windows Python environments.
|
|
14
|
+
|
|
15
|
+
Need the result in another program? [`agent-cost measure`](#machine-consumption-agent-cost-measure)
|
|
16
|
+
returns versioned `measure/v1` JSON for session IDs you supply. Task and PR attribution remain
|
|
17
|
+
the caller's responsibility.
|
|
18
|
+
|
|
19
|
+
[日本語サマリ](#日本語サマリ) · [Synthetic output example](#synthetic-output-example)
|
|
20
|
+
|
|
21
|
+
## Try it on your machine
|
|
22
|
+
|
|
23
|
+
With [`uvx`](https://docs.astral.sh/uv/guides/tools/), no persistent install is needed:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uvx --from coding-agent-cost agent-cost doctor
|
|
27
|
+
uvx --from coding-agent-cost agent-cost report
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The package runner may need network access to download the tool. The CLI itself does not upload
|
|
31
|
+
your logs.
|
|
32
|
+
|
|
33
|
+
The first command checks the expected local paths, the Codex database, and the bundled rate
|
|
34
|
+
catalog. It does not open every Claude JSONL file. The second command performs the real scan,
|
|
35
|
+
prints the result, and exposes unreadable inputs in `data_quality.skipped_files`. This path was
|
|
36
|
+
exercised on macOS from a clean temporary directory against the published `0.1.0` package on
|
|
37
|
+
2026-08-23.
|
|
38
|
+
|
|
39
|
+
Prefer a persistent command? Install the PyPI distribution, then run the same two commands:
|
|
13
40
|
|
|
14
41
|
```bash
|
|
15
|
-
pip install coding-agent-cost
|
|
16
|
-
agent-cost doctor
|
|
42
|
+
pip install coding-agent-cost
|
|
43
|
+
agent-cost doctor
|
|
17
44
|
agent-cost report
|
|
18
45
|
```
|
|
19
46
|
|
|
20
|
-
`agent-cost
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
47
|
+
The PyPI distribution is named [`coding-agent-cost`](https://pypi.org/project/coding-agent-cost/),
|
|
48
|
+
while the command remains `agent-cost` and the import remains `agent_cost`. The shorter PyPI
|
|
49
|
+
name is unavailable because of PyPI's similarity rule; this project is not affiliated with the
|
|
50
|
+
unrelated `agentcost` distribution.
|
|
51
|
+
|
|
52
|
+
## Synthetic output example
|
|
53
|
+
|
|
54
|
+
This is **synthetic Claude data**, not observed usage, a bill, or evidence of savings. The
|
|
55
|
+
CLI output below was reproduced with PyPI package `coding-agent-cost==0.1.0` and source
|
|
56
|
+
commit `d170ea301ed0c46351749214bd299e75ae8a7786` (only trailing space padding is omitted).
|
|
57
|
+
The [two-event fixture](examples/synthetic-claude.jsonl) contains known-model input, cache
|
|
58
|
+
writes without a TTL breakdown, and unknown-model input.
|
|
25
59
|
|
|
60
|
+
```text
|
|
61
|
+
Month Agent Model Token Kind Tokens Priced Unpriced Est. Cost (USD) Credits Status
|
|
62
|
+
------- ------ -------------------- ------------------- ------- ------- -------- --------------- ------- -----------
|
|
63
|
+
2026-06 claude claude-opus-4-8 cache_write_unknown 1000000 1000000 0 6.2500 - lower_bound
|
|
64
|
+
2026-06 claude claude-opus-4-8 input_nocache 1000000 1000000 0 5.0000 - priced
|
|
65
|
+
2026-06 claude model-not-in-catalog input_nocache 500 0 500 0.0000 - unpriced
|
|
66
|
+
|
|
67
|
+
Total tokens: 2,000,500 Total estimated cost: $11.2500
|
|
68
|
+
Rates catalog: 2026-07-29 (sha256=5d86e11b3c95...)
|
|
69
|
+
Data quality: malformed_events=0 skipped_files=0 negative_deltas=0 unpriced_tokens=500
|
|
26
70
|
```
|
|
71
|
+
|
|
72
|
+
- `priced`: $5.0000 is a catalog-based estimate for 1,000,000 input tokens, not a confirmed charge.
|
|
73
|
+
- `lower_bound`: $6.2500 uses the 5-minute cache-write rate because the TTL is missing. This is
|
|
74
|
+
a lower bound under the catalog and observed token data, not a lower bound on your actual bill.
|
|
75
|
+
- `unpriced`: `0.0000` does not mean free. Read `pricing_status` (the `Status` column) together
|
|
76
|
+
with `unpriced_tokens` (`Unpriced`): 500 tokens have no price and are excluded from the dollar
|
|
77
|
+
total. The $11.2500 total also includes the cache-write lower-bound estimate.
|
|
78
|
+
|
|
79
|
+
<details>
|
|
80
|
+
<summary>Reproduce with synthetic data only (Python 3.9+ and uvx)</summary>
|
|
81
|
+
|
|
82
|
+
Run from this repository's root. Both log locations and the config file are explicitly set
|
|
83
|
+
inside a temporary directory. Inherited log-location overrides are removed for the child
|
|
84
|
+
process, so it cannot fall back to your real Claude or Codex logs. The temporary data is
|
|
85
|
+
removed when the command exits. The package runner may download the pinned package.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
python3 - <<'PY'
|
|
89
|
+
import json
|
|
90
|
+
import os
|
|
91
|
+
from pathlib import Path
|
|
92
|
+
import shutil
|
|
93
|
+
import subprocess
|
|
94
|
+
import tempfile
|
|
95
|
+
|
|
96
|
+
fixture = Path("examples/synthetic-claude.jsonl").resolve()
|
|
97
|
+
with tempfile.TemporaryDirectory(prefix="agent-cost-example-") as directory:
|
|
98
|
+
root = Path(directory)
|
|
99
|
+
project = root / "claude" / "projects" / "synthetic"
|
|
100
|
+
project.mkdir(parents=True)
|
|
101
|
+
(root / "codex").mkdir()
|
|
102
|
+
shutil.copyfile(fixture, project / "session.jsonl")
|
|
103
|
+
config = root / "config.json"
|
|
104
|
+
config.write_text(json.dumps({
|
|
105
|
+
"claude_home": str(root / "claude"),
|
|
106
|
+
"codex_home": str(root / "codex"),
|
|
107
|
+
}))
|
|
108
|
+
env = dict(os.environ)
|
|
109
|
+
for key in ("CLAUDE_HOME", "CODEX_HOME", "PYTHONPATH"):
|
|
110
|
+
env.pop(key, None)
|
|
111
|
+
env["AGENT_COST_CONFIG"] = str(config)
|
|
112
|
+
subprocess.run([
|
|
113
|
+
"uvx", "--from", "coding-agent-cost==0.1.0", "agent-cost",
|
|
114
|
+
"report", "--agent", "claude", "--since", "2026-06-01",
|
|
115
|
+
"--until", "2026-06-02", "--format", "table",
|
|
116
|
+
], cwd=root, env=env, check=True)
|
|
117
|
+
PY
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Use `--format json` in the same command to see the full catalog SHA-256 and field names.
|
|
121
|
+
|
|
122
|
+
</details>
|
|
123
|
+
|
|
124
|
+
## Why this exists
|
|
125
|
+
|
|
126
|
+
Many usage trackers are designed as rich, convenient dashboards. That can be the right choice
|
|
127
|
+
when broad agent coverage and interactive exploration matter most. `agent-cost` is for a
|
|
128
|
+
different trust model:
|
|
129
|
+
|
|
130
|
+
- **Local-first and zero-network:** source logs stay on disk; the package has zero runtime
|
|
131
|
+
dependencies.
|
|
132
|
+
- **Auditable:** token facts, the versioned rate catalog, its digest, and data-quality counters
|
|
133
|
+
are available for inspection and machine consumption.
|
|
134
|
+
- **Fail-closed pricing:** unknown models remain `unpriced`; ambiguous cache-write TTLs are
|
|
135
|
+
labeled `lower_bound` instead of silently receiving a best-guess price.
|
|
136
|
+
- **Explicit attribution boundary:** `measure` accepts named session ids, but agent-cost does
|
|
137
|
+
not infer a task from a branch or PR. A workflow such as
|
|
138
|
+
[`spec-lane`](https://github.com/shiki-yusuke/spec-lane) can own the session-to-task binding
|
|
139
|
+
and consume the versioned JSON result.
|
|
140
|
+
|
|
141
|
+
This is not a claim that local CLI accounting is universally better than a dashboard. It is a
|
|
142
|
+
smaller primitive for environments where data egress, dependency surface, custom metrics, or
|
|
143
|
+
task attribution need to remain under the operator's control.
|
|
144
|
+
|
|
145
|
+
See [Choosing by use case and trust model](https://github.com/shiki-yusuke/agent-cost/blob/main/docs/comparison.md)
|
|
146
|
+
for a dated, source-linked comparison with broader CLI trackers, local dashboards, and
|
|
147
|
+
observability stacks.
|
|
148
|
+
|
|
149
|
+
## Report and export
|
|
150
|
+
|
|
151
|
+
`agent-cost report` turns each local usage event into a canonical fact (one model, one token
|
|
152
|
+
kind, one timestamp, one count), prices each fact against the bundled rate catalog, and prints
|
|
153
|
+
an aggregated table:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
27
156
|
agent-cost report --since 2026-06-01 --until 2026-07-01 --format table
|
|
28
157
|
agent-cost report --group-by month,agent --format csv
|
|
29
158
|
agent-cost report --format json > usage.json
|
|
@@ -35,6 +164,11 @@ interpreted in `--timezone`, default UTC), `--agent claude,codex`,
|
|
|
35
164
|
`--group-by month,agent,model,token-kind`, `--rates PATH` (use a different
|
|
36
165
|
catalog entirely, see below), `--exclude-archived` (Codex threads).
|
|
37
166
|
|
|
167
|
+
**Platform note:** `report`, `export`, and `measure` use Python's IANA timezone database even
|
|
168
|
+
when the timezone is `UTC`. macOS and typical Linux installations provide it through the
|
|
169
|
+
operating system. A minimal Windows Python environment may require `pip install tzdata` first;
|
|
170
|
+
`tzdata` is not currently a declared package dependency.
|
|
171
|
+
|
|
38
172
|
If another program wants to parse agent-cost's output for one or more
|
|
39
173
|
specific session ids, see `agent-cost measure` below rather than
|
|
40
174
|
scraping `report`.
|
|
@@ -52,10 +186,12 @@ network, never calls `gh`, and never resolves branches or PRs.
|
|
|
52
186
|
at the 5-minute rate as an explicit **lower bound** and flagged
|
|
53
187
|
`lower_bound` rather than guessed at the (more expensive) 1-hour rate.
|
|
54
188
|
- **Codex CLI**: rollout files record a *cumulative* token count after each
|
|
55
|
-
turn; agent-cost turns that into per-turn deltas.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
189
|
+
turn; agent-cost turns that into per-turn deltas. Under the Codex token-rate
|
|
190
|
+
tariff used here, cache writes are not added as a separate charge. The current
|
|
191
|
+
reader does not emit independent cache-write facts; newer logs can include
|
|
192
|
+
`cache_write_input_tokens`, but this field is not used to add a cache-write
|
|
193
|
+
charge. This differs from older logs where that signal was unavailable.
|
|
194
|
+
Codex's `output` fact is `output_tokens` alone: cross-checking
|
|
59
195
|
real rollout files confirms `total_tokens == input_tokens + output_tokens`
|
|
60
196
|
in every sample, which means `reasoning_output_tokens` is a breakdown of
|
|
61
197
|
output tokens already counted, not an additional charge -- adding it in
|
|
@@ -92,6 +228,15 @@ network, never calls `gh`, and never resolves branches or PRs.
|
|
|
92
228
|
|
|
93
229
|
## Updating the rate catalog
|
|
94
230
|
|
|
231
|
+
**GPT-6 Astra:** Codex Standard/Fast estimates use exact ID `gpt-6-astra` and
|
|
232
|
+
owned settings matched to turn/model context in the public Codex 0.153.4 JSONL
|
|
233
|
+
format. Explicit `default` uses Standard; `priority` uses 2.5x. Missing/ambiguous
|
|
234
|
+
tier or model attribution stays `unpriced`, with tokens preserved. These are
|
|
235
|
+
request-setting estimates, not confirmed processing tiers or actual bills.
|
|
236
|
+
The catalog observation cutoff is not an official launch time; earlier usage
|
|
237
|
+
is `unpriced`. See [evidence, synthetic tests and model-switch limits](docs/astra-pricing.md).
|
|
238
|
+
API pricing and legacy message billing are outside this entry.
|
|
239
|
+
|
|
95
240
|
Prices live in `agent_cost/rates.json`, not in code. It's a historical
|
|
96
241
|
catalog: each model can have several time-bounded rate periods, so a price
|
|
97
242
|
change is recorded as a new period rather than overwriting the old one (see
|
|
@@ -201,8 +346,10 @@ MIT. See [LICENSE](LICENSE).
|
|
|
201
346
|
|
|
202
347
|
- 集計の最小単位は「1 イベント = 1 モデル × 1 token 種別」の fact であり、session 単位でモデルを
|
|
203
348
|
丸めません。Claude の prompt cache は TTL 内訳(5分/1時間)が取れればそれを使い、取れない場合は
|
|
204
|
-
5分単価で **下限推計**(`lower_bound
|
|
205
|
-
|
|
349
|
+
5分単価で **下限推計**(`lower_bound`)として明示します。対象の Codex トークン料金体系では
|
|
350
|
+
cache write を別料金として加算せず、現行 reader は独立した cache-write fact を出力しません。
|
|
351
|
+
新しいログに `cache_write_input_tokens` が含まれていても追加料金の計算には使用しません。
|
|
352
|
+
これは、旧ログでその情報を観測できないこととは区別します。
|
|
206
353
|
- 出力フィールドは `estimated_cost_usd`(推計であることを明示)。Codex は `credits` も併記します。
|
|
207
354
|
未知のモデル・単価表にない token 種別は `unpriced` として扱い、憶測の価格を出しません。
|
|
208
355
|
- 単価表 (`agent_cost/rates.json`) は履歴型カタログで、値上げは新しい期間として追加します。
|
|
@@ -33,6 +33,14 @@ def price_fact(catalog: RateCatalog, fact: Fact) -> Tuple[Optional[Decimal], str
|
|
|
33
33
|
if resolved_key is None or period is None:
|
|
34
34
|
return None, "unpriced", None
|
|
35
35
|
|
|
36
|
+
# Astra's verified rates cover only the exact Codex model ID. Generic
|
|
37
|
+
# suffix normalization must not implicitly price unverified snapshots,
|
|
38
|
+
# speed variants or usage from a different agent with this new entry.
|
|
39
|
+
if resolved_key == "gpt-6-astra" and (
|
|
40
|
+
fact.agent != "codex" or fact.model_raw != "gpt-6-astra" or fact.mode == "unknown"
|
|
41
|
+
):
|
|
42
|
+
return None, "unpriced", None
|
|
43
|
+
|
|
36
44
|
rate_field = fact.token_kind
|
|
37
45
|
lower_bound = False
|
|
38
46
|
if fact.token_kind == "cache_write_unknown":
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1",
|
|
3
|
-
"catalog_version": "2026-
|
|
3
|
+
"catalog_version": "2026-09-06",
|
|
4
4
|
"currency": "USD",
|
|
5
5
|
"unit": "per_mtok",
|
|
6
6
|
"usd_per_credit": "0.04",
|
|
7
7
|
"notes": [
|
|
8
8
|
"All Claude rates are standard (non-batch, non-priority) API prices. Batch API is roughly 50% off, but agent-cost's logs have no signal for whether a given request went through Batch, so batch usage is priced at standard rates and will overstate cost for anyone using Batch.",
|
|
9
9
|
"claude-opus-5's launch date could not be confirmed from an authoritative source as of this catalog_version; its rate period's effective_from (2026-07-01) is a placeholder -- update it once confirmed.",
|
|
10
|
-
"gpt-5.6 (sol/terra/luna) credits could not be confirmed from the primary source (help.openai.com's Codex rate card returned HTTP 403 to automated fetches). The values here were cross-checked across several independent secondary sources that agreed with each other and are internally consistent (Sol's $5/$30 per-MTok API price x 25 = 125/750 credits, matching usd_per_credit=0.04); see the gpt-5.6-* sources entries below. Treat effective_from (2026-07-01) as a placeholder and re-verify against the primary rate card when it becomes reachable."
|
|
10
|
+
"gpt-5.6 (sol/terra/luna) credits could not be confirmed from the primary source (help.openai.com's Codex rate card returned HTTP 403 to automated fetches). The values here were cross-checked across several independent secondary sources that agreed with each other and are internally consistent (Sol's $5/$30 per-MTok API price x 25 = 125/750 credits, matching usd_per_credit=0.04); see the gpt-5.6-* sources entries below. Treat effective_from (2026-07-01) as a placeholder and re-verify against the primary rate card when it becomes reachable.",
|
|
11
|
+
"gpt-6-astra: Codex standard token-based rates only; not API pricing, legacy message metering, or actual contractual charges. Confirmed 2026-09-06 JST (2026-09-05T17:18:23Z). effective_from is this observation cutoff, NOT an official launch or price-start time; earlier events remain unpriced. No Codex long-context surcharge or cache-write charge is applied. Fast multiplier 2.5 applies to explicit priority request settings with matching owned turn/model context; explicit default uses Standard. Missing or ambiguous Astra modes remain unpriced. These settings do not confirm the backend processing tier. See docs/astra-pricing.md for compatibility limits and the separate GPT-5.6 discrepancy report."
|
|
11
12
|
],
|
|
12
13
|
"sources": [
|
|
13
14
|
{
|
|
@@ -32,6 +33,21 @@
|
|
|
32
33
|
"url": "https://rohitai.com/blog/openai-gpt-5-6-codex-rate-card-agentic-credit-pool",
|
|
33
34
|
"retrieved_at": "2026-07-29",
|
|
34
35
|
"note": "secondary source, used only for gpt-5.6 (sol/terra/luna) credits pending primary confirmation"
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"url": "https://help.openai.com/en/articles/11481834-chatgpt-rate-card",
|
|
39
|
+
"retrieved_at": "2026-09-05T17:18:23Z",
|
|
40
|
+
"note": "Primary source: ChatGPT Work / Codex token credits and Astra Fast 2.5x. Existing GPT-5.6 values are preserved pending historical-period review; see docs/astra-pricing.md."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"url": "https://help.openai.com/en/articles/20001415-chatgpt-rate-card-enterprise-token-based-pricing",
|
|
44
|
+
"retrieved_at": "2026-09-05T17:18:23Z",
|
|
45
|
+
"note": "Primary source: Work / Codex standard USD token rates, Astra Fast 2.5x, no Codex Astra long-context surcharge and no Codex cache-write charge. Individual agreements may differ."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"url": "https://developers.openai.com/api/docs/models/gpt-6-astra",
|
|
49
|
+
"retrieved_at": "2026-09-05T17:18:23Z",
|
|
50
|
+
"note": "Boundary check only: API cache writes, long context and API Fast rates are NOT applied to this Codex entry."
|
|
35
51
|
}
|
|
36
52
|
],
|
|
37
53
|
"models": [
|
|
@@ -485,6 +501,30 @@
|
|
|
485
501
|
"output": "10.0"
|
|
486
502
|
}
|
|
487
503
|
]
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
"model_key": "gpt-6-astra",
|
|
507
|
+
"aliases": [],
|
|
508
|
+
"fast_multiplier": "2.5",
|
|
509
|
+
"credits_per_mtok": {
|
|
510
|
+
"input_nocache": "250.0",
|
|
511
|
+
"cache_read": "25.0",
|
|
512
|
+
"cache_write_5m": null,
|
|
513
|
+
"cache_write_1h": null,
|
|
514
|
+
"output": "1250.0"
|
|
515
|
+
},
|
|
516
|
+
"rates": [
|
|
517
|
+
{
|
|
518
|
+
"rate_id": "gpt-6-astra-codex-observed-2026-09-05",
|
|
519
|
+
"effective_from": "2026-09-05T17:18:23+00:00",
|
|
520
|
+
"effective_until": null,
|
|
521
|
+
"input_nocache": "10.0",
|
|
522
|
+
"cache_read": "1.0",
|
|
523
|
+
"cache_write_5m": null,
|
|
524
|
+
"cache_write_1h": null,
|
|
525
|
+
"output": "50.0"
|
|
526
|
+
}
|
|
527
|
+
]
|
|
488
528
|
}
|
|
489
529
|
]
|
|
490
530
|
}
|