prompt-receipts 7.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jaret Arnold
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,278 @@
1
+ Metadata-Version: 2.4
2
+ Name: prompt-receipts
3
+ Version: 7.0
4
+ Summary: Receipts for AI coding runs: what a Claude Code, Codex, OpenCode, Qwen Code, Gemini CLI or Copilot CLI session cost, took and did
5
+ Author: Jaret Arnold
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://musharna.github.io/prompt-receipts/
8
+ Project-URL: Source, https://github.com/musharna/prompt-receipts
9
+ Project-URL: Changelog, https://github.com/musharna/prompt-receipts/blob/main/CHANGELOG.md
10
+ Keywords: claude-code,codex,opencode,qwen-code,gemini-cli,copilot-cli,llm-cost,ai-coding
11
+ Classifier: Environment :: Console
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Software Development
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Dynamic: license-file
18
+
19
+ # Prompt Receipts
20
+
21
+ [![tests](https://github.com/musharna/prompt-receipts/actions/workflows/test.yml/badge.svg)](https://github.com/musharna/prompt-receipts/actions/workflows/test.yml) [![license: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
22
+
23
+ Prompts for making things with Claude Code and Codex, each shown with a receipt: what it cost, how long it took and what was switched on. Plus a script that prints the same receipt for your own runs in Claude Code, Codex, OpenCode, Qwen Code, Gemini CLI or GitHub Copilot CLI.
24
+
25
+ **[Browse the prompts](https://musharna.github.io/prompt-receipts/)** · **[Make a receipt for your own run](#make-a-receipt-for-your-own-run)** · [What's new](CHANGELOG.md)
26
+
27
+ ```
28
+ $ python3 receipt.py --prompt
29
+ Receipt v5.0 · Claude Code 2.1.292 · 6 Oct 2026, 8:16 PM EDT · no. 5631-4887
30
+ model claude-opus-5-5 · effort medium
31
+ time 4 min (model working 4 min) · 1 prompt from me
32
+ cost $0.83 (Claude Code's own total at API prices; the lines below add up to it)
33
+ claude-opus-5-5
34
+ input 18 × $4.00/M <$0.01
35
+ cache read 273k × $0.20/M $0.05
36
+ cache write (1 h) 33k × $8.00/M $0.27
37
+ output 25k × $20.00/M $0.51
38
+ extras thinking 2 min · waiting on retries <1 s
39
+ prices API list prices per million tokens ($/M), from LiteLLM 05166e2, 9 Oct 2026
40
+ billing Max plan: a flat fee, not charged per run (your account today)
41
+ tokens in 306k (273k cached) · out 25k
42
+ work 13 tool calls, 6 shell commands · web 0 · lines +537 -0
43
+ files 2 files written or edited (.html, .js)
44
+ add-ons skills none (of 14 available) · MCP none (of 0 connected) · plugins none · subagents 0
45
+ hooks none logged
46
+ memory none loaded
47
+ settings bypassPermissions
48
+ id 680b62f5e76e (prompt fingerprint)
49
+ prompt A mascot for my habit-tracker app: a round blob that breathes, blinks and
50
+ giggles when you poke it. I'd like it in four moods: idle, happy, sleepy and
51
+ surprised.
52
+ ```
53
+
54
+ <a href="https://musharna.github.io/prompt-receipts/play/1bfe1ef0-9a8/index.html"><img src="m/1bfe1ef0-9a8_opus_0.webp" width="300" align="right" alt="A round green blob mascot, with smaller versions in four moods: idle, happy, sleepy and surprised"></a>
55
+
56
+ That's plain Opus 5.5 making [this blob mascot](https://musharna.github.io/prompt-receipts/play/1bfe1ef0-9a8/index.html) from one of the site's prompts. See [the other models' versions](https://musharna.github.io/prompt-receipts/#1bfe1ef0-9a8), or [this receipt on the site](https://musharna.github.io/prompt-receipts/r/#r1.ZVNBbtswELzrFXsIEBu1FUmOZCfNpUh7KBCjQdEPUNLKYk2RgkjF8Uv6lN7bj3VIOY3b6GCLS452ODP7lSuWvaOnPE7o10-6V2Ksme4NfrI4jbObzJcL-lI5ypKsWNDmNi3ocUufPn7zW9rElBerdHm92ayjDkBFeKrwoaXpR7vMl7k_yU1jBkcd13LsIic79gfpmjqpaTYhD2bYS72binOPSqkfTAeKDf4AjipjXQBeJPFmRbMzypeWzEGTM04oEo4-PH4GWlZs35NrmZTUbKlkZQ4k6prGHmdJunlEL89_vF83iKTuR0dvnnRDv3_QxXWcJFdbrO_AK0nPgZWo0HxgUZ8Vs_VqH4BJnE1A_5rkb4GHQTqmWUrtPFRXJ-DmpWP4xvocaEb3lmuWT7gsOQfmacTPbhAWS9dKHeTPgidQ_yCk8wWjwd8NEvLdpWSjSVVAvMRKwpFTpecBWKWk8T7sWVuaXVxt54vJvwdc5eFhS0meFgVnC7r5m6yo9DD0oq14pl4JfUuCGgUfG-YFguaoasWw4zp0GUak5mjGgURVmVE79KvFcR6d2nrDaJUUe5oFrYOYdcgU5PFqRD5tk4crgI3CGaXsAnG3LSssTdcJXdugBJcURmQK0bt8taZlEjVSBR0g2fTq3XKsyQyEoDuQncWt69SC4u92HiF2S-PZ2T2ua3ErDW9NQ-k1iSchlSgVB5Lb-8fX3QRctObKnW7Qq3En9QmOtR1LsWPtLCVRa8w-UAqbyuygWNRxZ4bja1HUKFp23l2MxLEX1j7y0ElrYZ2N5EtWi01SFlmT87oAlZdZBIoHWK4xO6caskCdsBVswpxTd6RWlNItka1qD79E33tDB1hVU6lMibjB2xJzgdmE6iWUBXEI_hrlndztgqotJIXZ1MNcTGxMny9rWBEW3ujGB6Ezpra3JGuFvLRoeFyQVcz98d-v2tFzt1zHfwA), made with `--link`.
57
+
58
+ <br clear="right">
59
+
60
+ ## Make a receipt for your own run
61
+
62
+ In the folder where you ran Claude Code:
63
+
64
+ ```
65
+ curl -sO https://musharna.github.io/prompt-receipts/tools/receipt.py && python3 receipt.py
66
+ ```
67
+
68
+ On Windows, in PowerShell:
69
+
70
+ ```
71
+ curl.exe -sO https://musharna.github.io/prompt-receipts/tools/receipt.py; py receipt.py
72
+ ```
73
+
74
+ Or install it as a command, `receipt` (also `prompt-receipts`):
75
+
76
+ ```
77
+ uvx --from git+https://github.com/musharna/prompt-receipts receipt # run it without installing
78
+ pipx install git+https://github.com/musharna/prompt-receipts # or keep it installed
79
+ ```
80
+
81
+ It needs only Python 3.9 or later. It reads the logs these tools already keep, so it works on runs you've already finished:
82
+
83
+ | Tool | Add | Logs it reads |
84
+ |---|---|---|
85
+ | Claude Code | nothing | `~/.claude/projects/`, or under `$CLAUDE_CONFIG_DIR` |
86
+ | Codex | `--codex` | `~/.codex/sessions/`, or under `$CODEX_HOME` |
87
+ | OpenCode | `--opencode` | `~/.local/share/opencode/opencode.db`, or under `$XDG_DATA_HOME` |
88
+ | Qwen Code | `--qwen` | `~/.qwen/projects/`, or under `$QWEN_HOME` |
89
+ | Gemini CLI | `--gemini` | `~/.gemini/tmp/`, or under `$GEMINI_CLI_HOME` |
90
+ | GitHub Copilot CLI | `--copilot` | `~/.copilot/session-state/`, or under `$COPILOT_HOME` |
91
+
92
+ Run it somewhere else and it tells you where your sessions are; `--list --all` lists them from every folder.
93
+
94
+ ### Common uses
95
+
96
+ ```
97
+ python3 receipt.py --list # this folder's recent sessions, numbered
98
+ python3 receipt.py --pick 2 --prompt # a receipt for one of them, with your prompts
99
+ python3 receipt.py --hide cost --link # leave out the cost and print a link to share
100
+ python3 receipt.py --turns --recipe # a line per prompt, and the commands to rerun them
101
+ python3 receipt.py --out receipt.png # a picture, for posting where text gets mangled
102
+ python3 receipt.py --totals week --all # cost, prompts and time by week, every folder
103
+
104
+ python3 receipt.py --json --prompt-id --out opus.json # save one receipt per model,
105
+ python3 receipt.py --compare opus.json sonnet.json # then set them side by side
106
+ ```
107
+
108
+ ### What it shares
109
+
110
+ - `receipt.py` itself never connects to the internet. It reads local files and prints text.
111
+ - It never prints paths, your email, account ids or file contents. Your prompts and the model's reply appear only when you ask (`--prompt`, `--reply`, `--recipe`), and it stops if one holds an email address or a key.
112
+ - `--link` puts the receipt after the `#` in the link, which browsers never send, so nothing is uploaded.
113
+ - `--bundle` packs the files a run wrote, and `--page` puts your prompts, the model's replies and those files on one page, only when you ask. Their text is checked for email addresses and keys like `--prompt`.
114
+ - `--output-url` only names where you'll put the page; `receipt.py` uploads nothing. The receipt site fetches it from there when someone opens the receipt.
115
+ - Read the receipt before you share it. Prompts, tool names and times can say more than you mean to.
116
+
117
+ ### Choosing what it covers
118
+
119
+ | Option | What it does |
120
+ |---|---|
121
+ | `--codex`, `--opencode`, `--qwen`, `--gemini`, `--copilot` | Use that tool's sessions instead of Claude Code ones |
122
+ | `--list`, then `--pick N` | List this folder's recent sessions, then make a receipt for one of them |
123
+ | `--all` | With `--list` or `--pick`: sessions from every folder |
124
+ | `--last N` | Cover only your last N prompts, when one session held several tasks |
125
+ | `--turns A-B` | Cover only prompts A to B (`3`, `3-5`, `3-` or `-5`). Its cost is worked out from those prompts' calls |
126
+ | `SESSION.jsonl` or `ses_…` | Make a receipt for a log file, or an OpenCode session id, directly |
127
+
128
+ ### Leaving things out
129
+
130
+ | Option | What it does |
131
+ |---|---|
132
+ | `--hide cost,date` | Drop parts: version, date, model, time, cost, items (the priced lines), billing, tokens, work, files, output (the size of what it wrote and the replies), addons, hooks, memory, settings. Hiding the model or the cost hides the priced lines too, since they name both |
133
+ | `--counts` | Show numbers instead of the names of skills, MCP servers, plugins, subagent types and memory files |
134
+ | `--rename old=new` | Show one name as another. Stops with an error if the name isn't on the receipt, so a typo can't leave the real one in |
135
+ | `--prompt` | Add your prompts, each one numbered. Home folders become `~`, and it stops if a prompt holds an email address or a key |
136
+ | `--redact` | With `--prompt`, `--reply`, `--recipe` or `--outcome`: print the text with `[email]` and `[key]` in their place instead of stopping |
137
+ | `--file-names` | Name the files the run wrote. Off by default: the receipt shows only how many and their types |
138
+
139
+ ### Prompt by prompt
140
+
141
+ | Option | What it does |
142
+ |---|---|
143
+ | `--turns` | Add a line per prompt: when you sent it, how long it ran, its cost (subagents included), tool calls and files. The receipt says whether the lines add up to the cost above |
144
+ | `--reply` | Add the model's last reply, checked for email addresses and keys like a prompt |
145
+ | `--outcome TEXT` | Add your own word on how it went, marked as yours |
146
+ | `--recipe` | Add the commands that send the same prompts again, each with the model and effort it ran on (`claude -p`, `codex exec`, `opencode run`, `qwen`, `gemini -p`, `copilot -p`). Models give a different answer each time, so it reruns the run, not its output |
147
+
148
+ ### Saving and sharing
149
+
150
+ | Option | What it does |
151
+ |---|---|
152
+ | `--md`, `--json` | Wrap it for GitHub or Discord, or print it as JSON (hidden parts stay out) |
153
+ | `--out FILE` | Save it to a `.txt`, `.md`, `.json` or `.png` file, or into a folder. A `.png` is a picture, for posting where text gets mangled |
154
+ | `--report` | Also print a link to [the report form](https://musharna.github.io/prompt-receipts/) with this receipt filled in |
155
+ | `--link` | Also print a link that shows this receipt on the site. The receipt rides in the part after `#`, which your browser never sends, so nothing is uploaded. Long receipts make links too long for some chats; it warns over 2,000 characters |
156
+ | `--bundle FILE.zip` | Save one zip with the receipt, its JSON, a record, and the files the run wrote, plus [RO-Crate](https://www.researchobject.org/ro-crate/) metadata and a page that shows the receipt |
157
+ | `--shot` | With `--bundle`: add a screenshot of the web page the run made, taken with Chrome, Edge or Chromium if one is installed. It shows the files in the bundle, served to the browser from your own computer only while the picture is taken; pictures the run didn't make aren't in it |
158
+
159
+ ### What the run made
160
+
161
+ Every receipt says how much the run wrote: `files 3 files written or edited (.html, .js ×2) · 612 lines, 24 KB · a web page`, and `replies 4 replies, 1,180 words`. No names or text.
162
+
163
+ | Option | What it does |
164
+ |---|---|
165
+ | `--page FILE.html` | Save one page with the receipt, every prompt and the model's full replies, and each file the run wrote. A web page the run made runs inside it, in a sandboxed frame, with the .js, .css and pictures it uses from the run put inside, so the one file works anywhere. Text files are shown as the run wrote them, or as they are on disk now when only edited. With `--redact`, emails and keys are replaced instead of stopping |
166
+ | `--output-url URL` | With `--page`: say where you'll put the page (an `https://` address, such as a GitHub Pages site). The receipt gets a `page` line with the address and the start of the page's SHA-256. When someone opens the receipt's `--link`, the site fetches the page, checks it, and shows it only if it matches byte for byte. Upload the file unchanged; the site where it lives must let other sites read it, as GitHub Pages and raw.githubusercontent.com do |
167
+
168
+ ```sh
169
+ python3 receipt.py --page run.html --output-url https://you.github.io/runs/run.html --link
170
+ ```
171
+
172
+ ### More than one run
173
+
174
+ | Option | What it does |
175
+ |---|---|
176
+ | `--compare A.json B.json` | Set receipts side by side, for one prompt run on several models or efforts |
177
+ | `--prompt-id` | Add a short fingerprint of the prompt (not the prompt itself), so `--compare` can tell runs of one prompt |
178
+ | `--combine A.json B.json` | Add up receipts for one task spread over several sessions |
179
+
180
+ ### Totals over time
181
+
182
+ `--totals` adds up every prompt in this folder's sessions (every folder's with `--all`), by `day`, `week`, `month`, `folder` or `model`:
183
+
184
+ ```
185
+ $ python3 receipt.py --gemini --totals
186
+ Totals v6.0 · Gemini CLI · folder gwork · 9 Oct 2026 · by day
187
+ day cost sessions prompts time tokens in / out
188
+ Fri 9 Oct 2026 $0.01 1 2 <1 s 62k / 312
189
+ ---------------------------------------------------------------
190
+ total $0.01 1 2 <1 s 62k / 312
191
+ ```
192
+
193
+ | Option | What it does |
194
+ |---|---|
195
+ | `--totals [BY]` | Add up cost, sessions, prompts, time and tokens by day (the default), week, month, folder or model. Each prompt's cost is worked out from its own calls at API list prices |
196
+ | `--since DATE`, `--until DATE` | Count only prompts sent on or after, or on or before, a date (`2026-10-01`) |
197
+
198
+ `--json`, `--md`, `--out` and `--link` work on totals too.
199
+
200
+ ### A record of what went in and came out
201
+
202
+ A receipt says what a run cost. A record says which files it made and what it was given, as SHA-256 fingerprints, so anyone holding a file can check whether it came out of that run. It holds no prompts, file contents or paths: only fingerprints of your prompts, the system prompt, the instruction files as they were loaded (`CLAUDE.md`, `AGENTS.md`), every tool result the model saw, and the files it wrote, plus the model, effort, settings and, for Codex, the git commit.
203
+
204
+ | Option | What it does |
205
+ |---|---|
206
+ | `--record FILE` | Save a record of the run. Its fingerprint goes on the receipt. `--hide`, `--counts`, `--rename` and `--file-names` apply to it too |
207
+ | `--verify RECORD FILES…` | Say for each file whether it came out of the run, went into it, or isn't in the record. One changed byte and it isn't |
208
+ | `--sign KEY` | Sign the receipt (`--out`) and the record with an SSH key (`ssh-keygen -Y sign`); the signature goes next to each as `.sig` |
209
+ | `--verify FILE` | Check the signature next to a receipt or record. Add `--signers allowed_signers` to check whose key signed it |
210
+ | `--prices FILE` | Price with a newer copy of LiteLLM's `model_prices_and_context_window.json` instead of the one built in |
211
+
212
+ A record is in-toto's [Statement](https://github.com/in-toto/attestation/blob/main/spec/v1/statement.md) format, written in one byte form (sorted keys, no spaces), so its fingerprint is the same wherever it's made. It makes a run checkable, not repeatable: neither tool lets you fix the model's randomness. Records of short prompts can be guessed by trying likely prompts, and a signature made after the run proves only what the log said when it was signed.
213
+
214
+ ### A receipt after every Claude Code session
215
+
216
+ Put this in `~/.claude/settings.json` (merge it with any `hooks` you already have) and every session leaves a receipt in `~/receipts` when it ends:
217
+
218
+ ```json
219
+ {
220
+ "hooks": {
221
+ "SessionEnd": [
222
+ { "hooks": [{ "type": "command", "command": "python3 ~/receipt.py --hook --out ~/receipts/" }] }
223
+ ]
224
+ }
225
+ }
226
+ ```
227
+
228
+ Keep `receipt.py` in your home folder for this, or change the path. Sessions with no prompts leave no receipt.
229
+
230
+ ### Plan use on the status line
231
+
232
+ On a Pro or Max plan, Claude Code tells the status line how much of your 5-hour and weekly limits you've used. `--statusline` shows that, and keeps the readings so a receipt made later can say how much of your plan a run took:
233
+
234
+ ```json
235
+ { "statusLine": { "type": "command", "command": "python3 ~/receipt.py --statusline" } }
236
+ ```
237
+
238
+ ```
239
+ Opus 5.5 · $0.28 · 3 s · 5-hour 2% · weekly 51%
240
+ ```
241
+
242
+ Receipts for sessions that ran with it get a `limits` line, such as `5-hour +7%, weekly +2% while this ran`. Other sessions running at the same time count toward the same limits, so the receipt says so. The readings are kept in `~/.cache/prompt-receipts/limits/` (under `$XDG_CACHE_HOME` if set, `%LOCALAPPDATA%` on Windows), only when a number changes. To keep the status line you have, call both from one script, passing each the same input:
243
+
244
+ ```sh
245
+ #!/bin/sh
246
+ input=$(cat)
247
+ echo "$(echo "$input" | ~/.claude/my-statusline.sh) · $(echo "$input" | python3 ~/receipt.py --statusline)"
248
+ ```
249
+
250
+ ### Good to know
251
+
252
+ - Claude Code deletes session logs after 30 days unless you raise `cleanupPeriodDays` in `~/.claude/settings.json`. Logs can be large, so check your free disk space before raising it a lot.
253
+ - If you moved a tool's folder with `CLAUDE_CONFIG_DIR`, `CODEX_HOME`, `XDG_DATA_HOME`, `QWEN_HOME`, `GEMINI_CLI_HOME` or `COPILOT_HOME`, the receipt looks there.
254
+ - For a whole Claude Code session, the cost and tokens are Claude Code's own totals and include subagents, added up over every time the session was opened. The lines under the cost price each call at API list prices, and the receipt says whether they add up to Claude Code's total or by how much they miss; long sessions that were compacted many times can miss. With `--last`, the cost is worked out from that part's calls.
255
+ - A Claude Code session resumed into a new log file gets its own receipt; `--combine` adds them up.
256
+ - Codex, Qwen Code, Gemini CLI and Copilot CLI don't log a price, so their cost is worked out from their token counts at API list prices (Alibaba Cloud's for Qwen models, Google's for Gemini). OpenCode's own figure is used when it has one. The built-in prices are LiteLLM's, dated on the receipt; `python3 tools/update_prices.py` refreshes them.
257
+ - What you pay can differ from list prices. Qwen OAuth's free allowance isn't charged; Copilot bills a plan's premium requests or AI credits, and the receipt shows the AI credits when the log has them; a key for a service like OpenRouter is charged at that service's prices.
258
+ - Qwen Code's background helpers (its memory extractor) make API calls of their own. They are counted, since Qwen Code logs them.
259
+ - `--record` and `--bundle` cover all six tools. Files made by shell commands aren't in a bundle or on a page.
260
+ - The billing line reads your account as it is today, so it shows your plan now, not necessarily when the run happened. A run on a local model (Ollama, LM Studio) says so on the model line.
261
+ - Files count what the edit tools wrote, subagents' included. Files made by shell commands aren't counted, and what subagents read isn't in a record.
262
+ - With `--turns`, some background work Claude Code prices itself (titles, summaries) logs no calls, so no prompt can hold it; the receipt says how much it is. A session that's still running keeps writing its log, so its numbers can move a little between runs.
263
+ - Codex logs don't record hooks, and OpenCode's, Qwen Code's, Gemini CLI's and Copilot CLI's record neither hooks nor memory files. Gemini CLI logs no version, effort or approval setting either. Claude Code logs a hook run only when the hook prints something, so hook counts are a floor.
264
+ - If a log has your prompts but no replies or token counts, the receipt says so: the tool may have changed how it writes logs. Please [open an issue](https://github.com/musharna/prompt-receipts/issues).
265
+ - Checked on Linux, macOS and Windows (Python 3.9 and 3.13) on every change, and by hand on WSL and Windows 11.
266
+ - A receipt is text you can edit. It shows what someone reports, not proof, unless it's signed by a key you trust.
267
+
268
+ ## The prompts
269
+
270
+ [![One prompt, run once on each model: Opus, Sonnet and Haiku 5.5 in Claude Code, and GPT-5.6 Sol, Terra and Luna in Codex](og.png)](https://musharna.github.io/prompt-receipts/)
271
+
272
+ Each prompt on [the site](https://musharna.github.io/prompt-receipts/) was run once on plain Claude Code (Opus, Sonnet and Haiku 5.5) and on GPT-5.6 Sol, Terra and Luna in Codex, all at medium effort, plus GPT-6-Astra, Codex's default model. Every run shows what came out, what it cost and how long it took.
273
+
274
+ Tried one? Use the "Tell us how it went" button on its card. Runs that didn't work are as useful as ones that did.
275
+
276
+ ## License
277
+
278
+ The code (`tools/receipt.py`, the tests and the site's scripts) is MIT: see [LICENSE](LICENSE). Prompts and page text are CC BY 4.0: see [LICENSE-prompts](LICENSE-prompts). The outputs were made by the models named on each card.
@@ -0,0 +1,260 @@
1
+ # Prompt Receipts
2
+
3
+ [![tests](https://github.com/musharna/prompt-receipts/actions/workflows/test.yml/badge.svg)](https://github.com/musharna/prompt-receipts/actions/workflows/test.yml) [![license: MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
4
+
5
+ Prompts for making things with Claude Code and Codex, each shown with a receipt: what it cost, how long it took and what was switched on. Plus a script that prints the same receipt for your own runs in Claude Code, Codex, OpenCode, Qwen Code, Gemini CLI or GitHub Copilot CLI.
6
+
7
+ **[Browse the prompts](https://musharna.github.io/prompt-receipts/)** · **[Make a receipt for your own run](#make-a-receipt-for-your-own-run)** · [What's new](CHANGELOG.md)
8
+
9
+ ```
10
+ $ python3 receipt.py --prompt
11
+ Receipt v5.0 · Claude Code 2.1.292 · 6 Oct 2026, 8:16 PM EDT · no. 5631-4887
12
+ model claude-opus-5-5 · effort medium
13
+ time 4 min (model working 4 min) · 1 prompt from me
14
+ cost $0.83 (Claude Code's own total at API prices; the lines below add up to it)
15
+ claude-opus-5-5
16
+ input 18 × $4.00/M <$0.01
17
+ cache read 273k × $0.20/M $0.05
18
+ cache write (1 h) 33k × $8.00/M $0.27
19
+ output 25k × $20.00/M $0.51
20
+ extras thinking 2 min · waiting on retries <1 s
21
+ prices API list prices per million tokens ($/M), from LiteLLM 05166e2, 9 Oct 2026
22
+ billing Max plan: a flat fee, not charged per run (your account today)
23
+ tokens in 306k (273k cached) · out 25k
24
+ work 13 tool calls, 6 shell commands · web 0 · lines +537 -0
25
+ files 2 files written or edited (.html, .js)
26
+ add-ons skills none (of 14 available) · MCP none (of 0 connected) · plugins none · subagents 0
27
+ hooks none logged
28
+ memory none loaded
29
+ settings bypassPermissions
30
+ id 680b62f5e76e (prompt fingerprint)
31
+ prompt A mascot for my habit-tracker app: a round blob that breathes, blinks and
32
+ giggles when you poke it. I'd like it in four moods: idle, happy, sleepy and
33
+ surprised.
34
+ ```
35
+
36
+ <a href="https://musharna.github.io/prompt-receipts/play/1bfe1ef0-9a8/index.html"><img src="m/1bfe1ef0-9a8_opus_0.webp" width="300" align="right" alt="A round green blob mascot, with smaller versions in four moods: idle, happy, sleepy and surprised"></a>
37
+
38
+ That's plain Opus 5.5 making [this blob mascot](https://musharna.github.io/prompt-receipts/play/1bfe1ef0-9a8/index.html) from one of the site's prompts. See [the other models' versions](https://musharna.github.io/prompt-receipts/#1bfe1ef0-9a8), or [this receipt on the site](https://musharna.github.io/prompt-receipts/r/#r1.ZVNBbtswELzrFXsIEBu1FUmOZCfNpUh7KBCjQdEPUNLKYk2RgkjF8Uv6lN7bj3VIOY3b6GCLS452ODP7lSuWvaOnPE7o10-6V2Ksme4NfrI4jbObzJcL-lI5ypKsWNDmNi3ocUufPn7zW9rElBerdHm92ayjDkBFeKrwoaXpR7vMl7k_yU1jBkcd13LsIic79gfpmjqpaTYhD2bYS72binOPSqkfTAeKDf4AjipjXQBeJPFmRbMzypeWzEGTM04oEo4-PH4GWlZs35NrmZTUbKlkZQ4k6prGHmdJunlEL89_vF83iKTuR0dvnnRDv3_QxXWcJFdbrO_AK0nPgZWo0HxgUZ8Vs_VqH4BJnE1A_5rkb4GHQTqmWUrtPFRXJ-DmpWP4xvocaEb3lmuWT7gsOQfmacTPbhAWS9dKHeTPgidQ_yCk8wWjwd8NEvLdpWSjSVVAvMRKwpFTpecBWKWk8T7sWVuaXVxt54vJvwdc5eFhS0meFgVnC7r5m6yo9DD0oq14pl4JfUuCGgUfG-YFguaoasWw4zp0GUak5mjGgURVmVE79KvFcR6d2nrDaJUUe5oFrYOYdcgU5PFqRD5tk4crgI3CGaXsAnG3LSssTdcJXdugBJcURmQK0bt8taZlEjVSBR0g2fTq3XKsyQyEoDuQncWt69SC4u92HiF2S-PZ2T2ua3ErDW9NQ-k1iSchlSgVB5Lb-8fX3QRctObKnW7Qq3En9QmOtR1LsWPtLCVRa8w-UAqbyuygWNRxZ4bja1HUKFp23l2MxLEX1j7y0ElrYZ2N5EtWi01SFlmT87oAlZdZBIoHWK4xO6caskCdsBVswpxTd6RWlNItka1qD79E33tDB1hVU6lMibjB2xJzgdmE6iWUBXEI_hrlndztgqotJIXZ1MNcTGxMny9rWBEW3ujGB6Ezpra3JGuFvLRoeFyQVcz98d-v2tFzt1zHfwA), made with `--link`.
39
+
40
+ <br clear="right">
41
+
42
+ ## Make a receipt for your own run
43
+
44
+ In the folder where you ran Claude Code:
45
+
46
+ ```
47
+ curl -sO https://musharna.github.io/prompt-receipts/tools/receipt.py && python3 receipt.py
48
+ ```
49
+
50
+ On Windows, in PowerShell:
51
+
52
+ ```
53
+ curl.exe -sO https://musharna.github.io/prompt-receipts/tools/receipt.py; py receipt.py
54
+ ```
55
+
56
+ Or install it as a command, `receipt` (also `prompt-receipts`):
57
+
58
+ ```
59
+ uvx --from git+https://github.com/musharna/prompt-receipts receipt # run it without installing
60
+ pipx install git+https://github.com/musharna/prompt-receipts # or keep it installed
61
+ ```
62
+
63
+ It needs only Python 3.9 or later. It reads the logs these tools already keep, so it works on runs you've already finished:
64
+
65
+ | Tool | Add | Logs it reads |
66
+ |---|---|---|
67
+ | Claude Code | nothing | `~/.claude/projects/`, or under `$CLAUDE_CONFIG_DIR` |
68
+ | Codex | `--codex` | `~/.codex/sessions/`, or under `$CODEX_HOME` |
69
+ | OpenCode | `--opencode` | `~/.local/share/opencode/opencode.db`, or under `$XDG_DATA_HOME` |
70
+ | Qwen Code | `--qwen` | `~/.qwen/projects/`, or under `$QWEN_HOME` |
71
+ | Gemini CLI | `--gemini` | `~/.gemini/tmp/`, or under `$GEMINI_CLI_HOME` |
72
+ | GitHub Copilot CLI | `--copilot` | `~/.copilot/session-state/`, or under `$COPILOT_HOME` |
73
+
74
+ Run it somewhere else and it tells you where your sessions are; `--list --all` lists them from every folder.
75
+
76
+ ### Common uses
77
+
78
+ ```
79
+ python3 receipt.py --list # this folder's recent sessions, numbered
80
+ python3 receipt.py --pick 2 --prompt # a receipt for one of them, with your prompts
81
+ python3 receipt.py --hide cost --link # leave out the cost and print a link to share
82
+ python3 receipt.py --turns --recipe # a line per prompt, and the commands to rerun them
83
+ python3 receipt.py --out receipt.png # a picture, for posting where text gets mangled
84
+ python3 receipt.py --totals week --all # cost, prompts and time by week, every folder
85
+
86
+ python3 receipt.py --json --prompt-id --out opus.json # save one receipt per model,
87
+ python3 receipt.py --compare opus.json sonnet.json # then set them side by side
88
+ ```
89
+
90
+ ### What it shares
91
+
92
+ - `receipt.py` itself never connects to the internet. It reads local files and prints text.
93
+ - It never prints paths, your email, account ids or file contents. Your prompts and the model's reply appear only when you ask (`--prompt`, `--reply`, `--recipe`), and it stops if one holds an email address or a key.
94
+ - `--link` puts the receipt after the `#` in the link, which browsers never send, so nothing is uploaded.
95
+ - `--bundle` packs the files a run wrote, and `--page` puts your prompts, the model's replies and those files on one page, only when you ask. Their text is checked for email addresses and keys like `--prompt`.
96
+ - `--output-url` only names where you'll put the page; `receipt.py` uploads nothing. The receipt site fetches it from there when someone opens the receipt.
97
+ - Read the receipt before you share it. Prompts, tool names and times can say more than you mean to.
98
+
99
+ ### Choosing what it covers
100
+
101
+ | Option | What it does |
102
+ |---|---|
103
+ | `--codex`, `--opencode`, `--qwen`, `--gemini`, `--copilot` | Use that tool's sessions instead of Claude Code ones |
104
+ | `--list`, then `--pick N` | List this folder's recent sessions, then make a receipt for one of them |
105
+ | `--all` | With `--list` or `--pick`: sessions from every folder |
106
+ | `--last N` | Cover only your last N prompts, when one session held several tasks |
107
+ | `--turns A-B` | Cover only prompts A to B (`3`, `3-5`, `3-` or `-5`). Its cost is worked out from those prompts' calls |
108
+ | `SESSION.jsonl` or `ses_…` | Make a receipt for a log file, or an OpenCode session id, directly |
109
+
110
+ ### Leaving things out
111
+
112
+ | Option | What it does |
113
+ |---|---|
114
+ | `--hide cost,date` | Drop parts: version, date, model, time, cost, items (the priced lines), billing, tokens, work, files, output (the size of what it wrote and the replies), addons, hooks, memory, settings. Hiding the model or the cost hides the priced lines too, since they name both |
115
+ | `--counts` | Show numbers instead of the names of skills, MCP servers, plugins, subagent types and memory files |
116
+ | `--rename old=new` | Show one name as another. Stops with an error if the name isn't on the receipt, so a typo can't leave the real one in |
117
+ | `--prompt` | Add your prompts, each one numbered. Home folders become `~`, and it stops if a prompt holds an email address or a key |
118
+ | `--redact` | With `--prompt`, `--reply`, `--recipe` or `--outcome`: print the text with `[email]` and `[key]` in their place instead of stopping |
119
+ | `--file-names` | Name the files the run wrote. Off by default: the receipt shows only how many and their types |
120
+
121
+ ### Prompt by prompt
122
+
123
+ | Option | What it does |
124
+ |---|---|
125
+ | `--turns` | Add a line per prompt: when you sent it, how long it ran, its cost (subagents included), tool calls and files. The receipt says whether the lines add up to the cost above |
126
+ | `--reply` | Add the model's last reply, checked for email addresses and keys like a prompt |
127
+ | `--outcome TEXT` | Add your own word on how it went, marked as yours |
128
+ | `--recipe` | Add the commands that send the same prompts again, each with the model and effort it ran on (`claude -p`, `codex exec`, `opencode run`, `qwen`, `gemini -p`, `copilot -p`). Models give a different answer each time, so it reruns the run, not its output |
129
+
130
+ ### Saving and sharing
131
+
132
+ | Option | What it does |
133
+ |---|---|
134
+ | `--md`, `--json` | Wrap it for GitHub or Discord, or print it as JSON (hidden parts stay out) |
135
+ | `--out FILE` | Save it to a `.txt`, `.md`, `.json` or `.png` file, or into a folder. A `.png` is a picture, for posting where text gets mangled |
136
+ | `--report` | Also print a link to [the report form](https://musharna.github.io/prompt-receipts/) with this receipt filled in |
137
+ | `--link` | Also print a link that shows this receipt on the site. The receipt rides in the part after `#`, which your browser never sends, so nothing is uploaded. Long receipts make links too long for some chats; it warns over 2,000 characters |
138
+ | `--bundle FILE.zip` | Save one zip with the receipt, its JSON, a record, and the files the run wrote, plus [RO-Crate](https://www.researchobject.org/ro-crate/) metadata and a page that shows the receipt |
139
+ | `--shot` | With `--bundle`: add a screenshot of the web page the run made, taken with Chrome, Edge or Chromium if one is installed. It shows the files in the bundle, served to the browser from your own computer only while the picture is taken; pictures the run didn't make aren't in it |
140
+
141
+ ### What the run made
142
+
143
+ Every receipt says how much the run wrote: `files 3 files written or edited (.html, .js ×2) · 612 lines, 24 KB · a web page`, and `replies 4 replies, 1,180 words`. No names or text.
144
+
145
+ | Option | What it does |
146
+ |---|---|
147
+ | `--page FILE.html` | Save one page with the receipt, every prompt and the model's full replies, and each file the run wrote. A web page the run made runs inside it, in a sandboxed frame, with the .js, .css and pictures it uses from the run put inside, so the one file works anywhere. Text files are shown as the run wrote them, or as they are on disk now when only edited. With `--redact`, emails and keys are replaced instead of stopping |
148
+ | `--output-url URL` | With `--page`: say where you'll put the page (an `https://` address, such as a GitHub Pages site). The receipt gets a `page` line with the address and the start of the page's SHA-256. When someone opens the receipt's `--link`, the site fetches the page, checks it, and shows it only if it matches byte for byte. Upload the file unchanged; the site where it lives must let other sites read it, as GitHub Pages and raw.githubusercontent.com do |
149
+
150
+ ```sh
151
+ python3 receipt.py --page run.html --output-url https://you.github.io/runs/run.html --link
152
+ ```
153
+
154
+ ### More than one run
155
+
156
+ | Option | What it does |
157
+ |---|---|
158
+ | `--compare A.json B.json` | Set receipts side by side, for one prompt run on several models or efforts |
159
+ | `--prompt-id` | Add a short fingerprint of the prompt (not the prompt itself), so `--compare` can tell runs of one prompt |
160
+ | `--combine A.json B.json` | Add up receipts for one task spread over several sessions |
161
+
162
+ ### Totals over time
163
+
164
+ `--totals` adds up every prompt in this folder's sessions (every folder's with `--all`), by `day`, `week`, `month`, `folder` or `model`:
165
+
166
+ ```
167
+ $ python3 receipt.py --gemini --totals
168
+ Totals v6.0 · Gemini CLI · folder gwork · 9 Oct 2026 · by day
169
+ day cost sessions prompts time tokens in / out
170
+ Fri 9 Oct 2026 $0.01 1 2 <1 s 62k / 312
171
+ ---------------------------------------------------------------
172
+ total $0.01 1 2 <1 s 62k / 312
173
+ ```
174
+
175
+ | Option | What it does |
176
+ |---|---|
177
+ | `--totals [BY]` | Add up cost, sessions, prompts, time and tokens by day (the default), week, month, folder or model. Each prompt's cost is worked out from its own calls at API list prices |
178
+ | `--since DATE`, `--until DATE` | Count only prompts sent on or after, or on or before, a date (`2026-10-01`) |
179
+
180
+ `--json`, `--md`, `--out` and `--link` work on totals too.
181
+
182
+ ### A record of what went in and came out
183
+
184
+ A receipt says what a run cost. A record says which files it made and what it was given, as SHA-256 fingerprints, so anyone holding a file can check whether it came out of that run. It holds no prompts, file contents or paths: only fingerprints of your prompts, the system prompt, the instruction files as they were loaded (`CLAUDE.md`, `AGENTS.md`), every tool result the model saw, and the files it wrote, plus the model, effort, settings and, for Codex, the git commit.
185
+
186
+ | Option | What it does |
187
+ |---|---|
188
+ | `--record FILE` | Save a record of the run. Its fingerprint goes on the receipt. `--hide`, `--counts`, `--rename` and `--file-names` apply to it too |
189
+ | `--verify RECORD FILES…` | Say for each file whether it came out of the run, went into it, or isn't in the record. One changed byte and it isn't |
190
+ | `--sign KEY` | Sign the receipt (`--out`) and the record with an SSH key (`ssh-keygen -Y sign`); the signature goes next to each as `.sig` |
191
+ | `--verify FILE` | Check the signature next to a receipt or record. Add `--signers allowed_signers` to check whose key signed it |
192
+ | `--prices FILE` | Price with a newer copy of LiteLLM's `model_prices_and_context_window.json` instead of the one built in |
193
+
194
+ A record is in-toto's [Statement](https://github.com/in-toto/attestation/blob/main/spec/v1/statement.md) format, written in one byte form (sorted keys, no spaces), so its fingerprint is the same wherever it's made. It makes a run checkable, not repeatable: neither tool lets you fix the model's randomness. Records of short prompts can be guessed by trying likely prompts, and a signature made after the run proves only what the log said when it was signed.
195
+
196
+ ### A receipt after every Claude Code session
197
+
198
+ Put this in `~/.claude/settings.json` (merge it with any `hooks` you already have) and every session leaves a receipt in `~/receipts` when it ends:
199
+
200
+ ```json
201
+ {
202
+ "hooks": {
203
+ "SessionEnd": [
204
+ { "hooks": [{ "type": "command", "command": "python3 ~/receipt.py --hook --out ~/receipts/" }] }
205
+ ]
206
+ }
207
+ }
208
+ ```
209
+
210
+ Keep `receipt.py` in your home folder for this, or change the path. Sessions with no prompts leave no receipt.
211
+
212
+ ### Plan use on the status line
213
+
214
+ On a Pro or Max plan, Claude Code tells the status line how much of your 5-hour and weekly limits you've used. `--statusline` shows that, and keeps the readings so a receipt made later can say how much of your plan a run took:
215
+
216
+ ```json
217
+ { "statusLine": { "type": "command", "command": "python3 ~/receipt.py --statusline" } }
218
+ ```
219
+
220
+ ```
221
+ Opus 5.5 · $0.28 · 3 s · 5-hour 2% · weekly 51%
222
+ ```
223
+
224
+ Receipts for sessions that ran with it get a `limits` line, such as `5-hour +7%, weekly +2% while this ran`. Other sessions running at the same time count toward the same limits, so the receipt says so. The readings are kept in `~/.cache/prompt-receipts/limits/` (under `$XDG_CACHE_HOME` if set, `%LOCALAPPDATA%` on Windows), only when a number changes. To keep the status line you have, call both from one script, passing each the same input:
225
+
226
+ ```sh
227
+ #!/bin/sh
228
+ input=$(cat)
229
+ echo "$(echo "$input" | ~/.claude/my-statusline.sh) · $(echo "$input" | python3 ~/receipt.py --statusline)"
230
+ ```
231
+
232
+ ### Good to know
233
+
234
+ - Claude Code deletes session logs after 30 days unless you raise `cleanupPeriodDays` in `~/.claude/settings.json`. Logs can be large, so check your free disk space before raising it a lot.
235
+ - If you moved a tool's folder with `CLAUDE_CONFIG_DIR`, `CODEX_HOME`, `XDG_DATA_HOME`, `QWEN_HOME`, `GEMINI_CLI_HOME` or `COPILOT_HOME`, the receipt looks there.
236
+ - For a whole Claude Code session, the cost and tokens are Claude Code's own totals and include subagents, added up over every time the session was opened. The lines under the cost price each call at API list prices, and the receipt says whether they add up to Claude Code's total or by how much they miss; long sessions that were compacted many times can miss. With `--last`, the cost is worked out from that part's calls.
237
+ - A Claude Code session resumed into a new log file gets its own receipt; `--combine` adds them up.
238
+ - Codex, Qwen Code, Gemini CLI and Copilot CLI don't log a price, so their cost is worked out from their token counts at API list prices (Alibaba Cloud's for Qwen models, Google's for Gemini). OpenCode's own figure is used when it has one. The built-in prices are LiteLLM's, dated on the receipt; `python3 tools/update_prices.py` refreshes them.
239
+ - What you pay can differ from list prices. Qwen OAuth's free allowance isn't charged; Copilot bills a plan's premium requests or AI credits, and the receipt shows the AI credits when the log has them; a key for a service like OpenRouter is charged at that service's prices.
240
+ - Qwen Code's background helpers (its memory extractor) make API calls of their own. They are counted, since Qwen Code logs them.
241
+ - `--record` and `--bundle` cover all six tools. Files made by shell commands aren't in a bundle or on a page.
242
+ - The billing line reads your account as it is today, so it shows your plan now, not necessarily when the run happened. A run on a local model (Ollama, LM Studio) says so on the model line.
243
+ - Files count what the edit tools wrote, subagents' included. Files made by shell commands aren't counted, and what subagents read isn't in a record.
244
+ - With `--turns`, some background work Claude Code prices itself (titles, summaries) logs no calls, so no prompt can hold it; the receipt says how much it is. A session that's still running keeps writing its log, so its numbers can move a little between runs.
245
+ - Codex logs don't record hooks, and OpenCode's, Qwen Code's, Gemini CLI's and Copilot CLI's record neither hooks nor memory files. Gemini CLI logs no version, effort or approval setting either. Claude Code logs a hook run only when the hook prints something, so hook counts are a floor.
246
+ - If a log has your prompts but no replies or token counts, the receipt says so: the tool may have changed how it writes logs. Please [open an issue](https://github.com/musharna/prompt-receipts/issues).
247
+ - Checked on Linux, macOS and Windows (Python 3.9 and 3.13) on every change, and by hand on WSL and Windows 11.
248
+ - A receipt is text you can edit. It shows what someone reports, not proof, unless it's signed by a key you trust.
249
+
250
+ ## The prompts
251
+
252
+ [![One prompt, run once on each model: Opus, Sonnet and Haiku 5.5 in Claude Code, and GPT-5.6 Sol, Terra and Luna in Codex](og.png)](https://musharna.github.io/prompt-receipts/)
253
+
254
+ Each prompt on [the site](https://musharna.github.io/prompt-receipts/) was run once on plain Claude Code (Opus, Sonnet and Haiku 5.5) and on GPT-5.6 Sol, Terra and Luna in Codex, all at medium effort, plus GPT-6-Astra, Codex's default model. Every run shows what came out, what it cost and how long it took.
255
+
256
+ Tried one? Use the "Tell us how it went" button on its card. Runs that didn't work are as useful as ones that did.
257
+
258
+ ## License
259
+
260
+ The code (`tools/receipt.py`, the tests and the site's scripts) is MIT: see [LICENSE](LICENSE). Prompts and page text are CC BY 4.0: see [LICENSE-prompts](LICENSE-prompts). The outputs were made by the models named on each card.
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "prompt-receipts"
7
+ dynamic = ["version"]
8
+ description = "Receipts for AI coding runs: what a Claude Code, Codex, OpenCode, Qwen Code, Gemini CLI or Copilot CLI session cost, took and did"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE"]
12
+ requires-python = ">=3.9"
13
+ authors = [{ name = "Jaret Arnold" }]
14
+ keywords = ["claude-code", "codex", "opencode", "qwen-code", "gemini-cli", "copilot-cli", "llm-cost", "ai-coding"]
15
+ classifiers = [
16
+ "Environment :: Console",
17
+ "Programming Language :: Python :: 3",
18
+ "Topic :: Software Development",
19
+ ]
20
+
21
+ [project.urls]
22
+ Homepage = "https://musharna.github.io/prompt-receipts/"
23
+ Source = "https://github.com/musharna/prompt-receipts"
24
+ Changelog = "https://github.com/musharna/prompt-receipts/blob/main/CHANGELOG.md"
25
+
26
+ [project.scripts]
27
+ prompt-receipts = "receipt:main"
28
+ receipt = "receipt:main"
29
+
30
+ [tool.setuptools]
31
+ package-dir = { "" = "tools" }
32
+ py-modules = ["receipt"]
33
+
34
+ [tool.setuptools.dynamic]
35
+ version = { attr = "receipt.VERSION" }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+