Prompt Receipts
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.
Browse the prompts · Browse receipts · Make a receipt for your own run · What's new
$ python3 receipt.py --prompt
Receipt v5.0 · Claude Code 2.1.292 · 6 Oct 2026, 8:16 PM EDT · no. 5631-4887
model claude-opus-5-5 · effort medium
time 4 min (model working 4 min) · 1 prompt from me
cost $0.83 (Claude Code's own total at API prices; the lines below add up to it)
claude-opus-5-5
input 18 × $4.00/M <$0.01
cache read 273k × $0.20/M $0.05
cache write (1 h) 33k × $8.00/M $0.27
output 25k × $20.00/M $0.51
extras thinking 2 min · waiting on retries <1 s
prices API list prices per million tokens ($/M), from LiteLLM 05166e2, 9 Oct 2026
billing Max plan: a flat fee, not charged per run (your account today)
tokens in 306k (273k cached) · out 25k
work 13 tool calls, 6 shell commands · web 0 · lines +537 -0
files 2 files written or edited (.html, .js)
add-ons skills none (of 14 available) · MCP none (of 0 connected) · plugins none · subagents 0
hooks none logged
memory none loaded
settings bypassPermissions
id 680b62f5e76e (prompt fingerprint)
prompt A mascot for my habit-tracker app: a round blob that breathes, blinks and
giggles when you poke it. I'd like it in four moods: idle, happy, sleepy and
surprised.
That's plain Opus 5.5 making this blob mascot from one of the site's prompts. See the other models' versions, or this receipt on the site, made with --link.
Make a receipt for your own run
In the folder where you ran Claude Code:
curl -sO https://musharna.github.io/prompt-receipts/tools/receipt.py && python3 receipt.py
On Windows, in PowerShell:
curl.exe -sO https://musharna.github.io/prompt-receipts/tools/receipt.py; py receipt.py
Or install it as a command, receipt (also prompt-receipts):
uvx prompt-receipts # run it without installing
pipx install prompt-receipts # or keep it installed
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:
| Tool | Add | Logs it reads |
|---|---|---|
| Claude Code | nothing | ~/.claude/projects/, or under $CLAUDE_CONFIG_DIR |
| Codex | --codex |
~/.codex/sessions/, or under $CODEX_HOME |
| OpenCode | --opencode |
~/.local/share/opencode/opencode.db, or under $XDG_DATA_HOME |
| Qwen Code | --qwen |
~/.qwen/projects/, or under $QWEN_HOME |
| Gemini CLI | --gemini |
~/.gemini/tmp/, or under $GEMINI_CLI_HOME |
| GitHub Copilot CLI | --copilot |
~/.copilot/session-state/, or under $COPILOT_HOME |
Run it somewhere else and it tells you where your sessions are; --list --all lists them from every folder.
A run with claude -p in a script or CI can be saved with --output-format stream-json --verbose > run.jsonl, and receipt run.jsonl reads it like a session log. That output has no prompt, effort, hooks or memory files, so the receipt says they aren't in it. If you still have the prompt, --asked prompt.txt puts it on the receipt, with a line saying it is your words and not the log's.
codex exec --json > run.jsonl saves a Codex run the same way. Its output has the replies, commands, files and tokens, but no prompt, model, version or times. --asked gives the prompt, and --model NAME names the model, so its tokens are priced; the receipt says both are your word. Codex logs only the run's total tokens, not each call's, so the price is at the model's standard rate.
Common uses
python3 receipt.py --list # this folder's recent sessions, numbered
python3 receipt.py --pick 2 --prompt # a receipt for one of them, with your prompts
python3 receipt.py --hide cost --link # leave out the cost and print a link to share
python3 receipt.py --turns --recipe # a line per prompt, and the commands to rerun them
python3 receipt.py --replay LINK --run # run someone's receipt again, in a new empty folder
python3 receipt.py --replay LINK --picture shot.png --run # ...with a picture of what it made
python3 receipt.py --out receipt.png # a picture, for posting where text gets mangled
python3 receipt.py --totals week --all # cost, prompts and time by week, every folder
python3 receipt.py --json --prompt-id --out opus.json # save one receipt per model,
python3 receipt.py --compare opus.json sonnet.json # then set them side by side
What it shares
receipt.pyitself never connects to the internet. It reads local files and prints text.- 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. --linkputs the receipt after the#in the link, which browsers never send, so nothing is uploaded.--bundlepacks the files a run wrote, and--pageputs 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.--output-urlonly names where you'll put the page;receipt.pyuploads nothing. The receipt site fetches it from there when someone opens the receipt.- Read the receipt before you share it. Prompts, tool names and times can say more than you mean to.
Choosing what it covers
| Option | What it does |
|---|---|
--codex, --opencode, --qwen, --gemini, --copilot |
Use that tool's sessions instead of Claude Code ones |
--list, then --pick N |
List this folder's recent sessions, then make a receipt for one of them |
--all |
With --list or --pick: sessions from every folder |
--last N |
Cover only your last N prompts, when one session held several tasks |
--turns A-B |
Cover only prompts A to B (3, 3-5, 3- or -5). Its cost is worked out from those prompts' calls |
SESSION.jsonl or ses_… |
Make a receipt for a log file, or an OpenCode session id, directly |
Leaving things out
| Option | What it does |
|---|---|
--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 |
--counts |
Show numbers instead of the names of skills, MCP servers, plugins, subagent types and memory files |
--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 |
--prompt |
Add your prompts, each one numbered. Home folders become ~, and it stops if a prompt holds an email address or a key |
--asked FILE |
For a log that doesn't hold its prompt (claude -p output): put the prompt from FILE (or - for what you pipe in) on the receipt, checked like --prompt. The receipt says it is your words, not the log's, and a --record still vouches only for the log. It stops if the log holds its own prompt |
--model NAME |
For a log that doesn't name its model (codex exec --json output): the model it ran on, so its tokens can be priced. The receipt says it is your word |
--redact |
With --prompt, --asked, --reply, --recipe, --outcome or --reported: print the text with [email] and [key] in their place instead of stopping |
--file-names |
Name the files the run wrote. Off by default: the receipt shows only how many and their types |
Prompt by prompt
| Option | What it does |
|---|---|
--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 |
--reply |
Add the model's last reply, checked for email addresses and keys like a prompt |
--outcome TEXT |
Add your own word on how it went, marked as yours |
--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 |
--replay RECEIPT |
Show the rerun commands in a receipt link or saved receipt made with --recipe. With --run, run them one by one in a new empty folder (replay-<receipt no.>), with the model, effort and permission mode the receipt names, then print the new run's receipt. It runs only claude, codex, opencode, qwen, gemini or copilot, never through a shell, and says when the original ran with permission checks off. With --picture FILE (a .png, .jpg, .webp or .gif of what the original made), the picture goes into the new folder as look.png and the first prompt gets a line saying it's a picture of what this should look like. In a test of 5 gallery prompts, 3 runs each, the receipt with a picture made the same thing 15 times of 15, the receipt alone 10 and a picture alone 9 (the test) |
Saving and sharing
| Option | What it does |
|---|---|
--md, --json |
Wrap it for GitHub or Discord, or print it as JSON (hidden parts stay out) |
--out FILE |
Save it to a .txt, .md, .json or .png file, or into a folder. A .png is a picture of a paper receipt, for posting where text gets mangled. It reads like one from a shop: what was asked for (with --prompt), what the run made, what it took, the total, and a barcode of the receipt's number. It prints alt text for the picture (1,000 characters at most) to paste in with it, and keeps a copy inside the PNG |
--picture FILE |
With a .png: put a picture of what the run made on the receipt, under what was asked for. A .png goes on as it is, made smaller if it's wider or taller than the receipt is wide. A sound goes on as its spectrogram (time across, pitch up, louder brighter), and a video as 4 of its frames, each with a line saying how long it is. PNGs and WAVs need nothing else; other pictures, sounds (.mp3, .ogg, .flac…) and videos need ffmpeg (or set RECEIPT_FFMPEG to where it is) |
--look LOOK |
With a .png: strip (the whole receipt, the default), card (cut down for a feed: the prompt large, the picture, the model, time, tool calls and the total; 1080 pixels wide and at most 1350 tall, so X, Bluesky and LinkedIn show it whole) or print (the strip set in a real font, drawn by Chrome, Edge or Chromium) |
--theme THEME |
With a .png: the paper and ink, paper (the default), night, terminal, blueprint or pink. The barcode stays dark on light, so it scans on dark paper too |
--report |
Also print a link to the report form with this receipt filled in |
--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 |
--share |
--link, and a link that sends the receipt to the gallery: a GitHub issue with the link filled in |
--bundle FILE.zip |
Save one zip with the receipt, its JSON, a record, and the files the run wrote, plus RO-Crate metadata and a page that shows the receipt |
--shot |
With --bundle or a .png: add a screenshot of the web page the run made (on a .png, it goes where --picture would), 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. On a .png, a run that made no page but a video or a sound gets its frames or its spectrogram instead, with no browser |
What the run made
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.
A run often makes its sounds, videos and pictures with a program it runs (a script, ffmpeg) rather than writing them itself. Those are counted on a line of their own: made 3 files changed in its folder while it ran (.mp4 ×3) · 76 MB · 3 videos, 0:16 in all. It is every file in the run's folder that changed while it ran and that its own tools didn't write, so a file you changed there at the same time counts too. Folders whose names start with ., node_modules, __pycache__ and virtual environments aren't looked in, nor is your home folder. They go in the record, the bundle and the page like the files it wrote.
| Option | What it does |
|---|---|
--page FILE.html |
Save one page with the receipt, every prompt and the model's full replies, and each file the run made. A web page the run made runs inside it, in a sandboxed frame, with the .js, .css, pictures, sounds and videos it uses from the run put inside, so the one file works anywhere. Pictures show, and sounds and videos play, up to 16 MB in all; past that, with ffmpeg installed, a sound or video is shown as a smaller copy (the same bytes each time it's made), and without it, by its size. 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 |
--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, raw.githubusercontent.com and gists do |
python3 receipt.py --page run.html --output-url https://you.github.io/runs/run.html --link
To post the run as a picture, with the prompt, a screenshot of what it made and the cost on one receipt:
python3 receipt.py --prompt --shot --out receipt.png
For a feed, the card shows the same run in one screen, in the night theme here:
python3 receipt.py --prompt --shot --look card --theme night --out card.png
For a run that made a sound, put its spectrogram there instead:
python3 receipt.py --prompt --picture song.wav --out receipt.png
No site of your own? A public GitHub gist works, and --page prints these steps:
receipt --page run.html # make the page
gh gist create --public run.html # put it in a gist
gh api gists/ID --jq '.files[].raw_url' # ID ends the gist's address
receipt --page run.html --output-url RAW_ADDRESS --link
Making the page again gives the same bytes, so the uploaded copy matches; if it doesn't (the run went on, or you hid something else), receipt.py says so and you upload the new one. The raw address names that version of the gist, so a later edit to the gist can't change what the receipt points at.
From someone's post
Found a post that shares a prompt, what it cost and what it made? --reported FILE makes a receipt of what the post says. FILE holds key: value lines: post (its address, needed), and any of by, date, tool, model, effort, time, cost, tokens in, tokens cached, tokens out, made and prompt (put it last; it can run over several lines).
$ receipt --reported post.txt
Reported v7.13 · Claude Code · 7 Oct 2026
REPORTED from a post, not read from a log: what it says, unchecked; no receipt number or
record
post https://musharna.github.io/prompt-receipts/#p1 · by Prompt Receipts
model claude-opus-5-5 · effort medium
time 4 min
cost $0.80 (the post's own figure)
$0.65 at API prices for the model and tokens it states; more if some were cache
writes
tokens in 439k (402k cached) · out 21k
made a full page with captions and speech bubbles
prompt A three-panel comic page, drawn as a finished image file, about a pigeon who's
convinced he's the town postman, for the kids' corner of our local newsletter.
Every look carries a REPORTED stamp, and anything the post leaves out reads "not stated". With a model and tokens, they are priced next to the post's own figure. That price is the least the run could have cost, since posts rarely say which tokens were cache writes. The receipt has no number, barcode or record, because there's no log to vouch for. It goes with --out, --look, --theme, --picture, --link, --share and --redact.
More than one run
| Option | What it does |
|---|---|
--compare A.json B.json |
Set receipts side by side, for one prompt run on several models or efforts |
--prompt-id |
Add a short fingerprint of the prompt (not the prompt itself), so --compare can tell runs of one prompt |
--combine A.json B.json |
Add up receipts for one task spread over several sessions |
Totals over time
--totals adds up every prompt in this folder's sessions (every folder's with --all), by day, week, month, folder or model:
$ python3 receipt.py --gemini --totals
Totals v6.0 · Gemini CLI · folder gwork · 9 Oct 2026 · by day
day cost sessions prompts time tokens in / out
Fri 9 Oct 2026 $0.01 1 2 <1 s 62k / 312
---------------------------------------------------------------
total $0.01 1 2 <1 s 62k / 312
| Option | What it does |
|---|---|
--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 |
--since DATE, --until DATE |
Count only prompts sent on or after, or on or before, a date (2026-10-01) |
--json, --md, --out and --link work on totals too.
A record of what went in and came out
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.
| Option | What it does |
|---|---|
--record FILE |
Save a record of the run. Its fingerprint goes on the receipt. --hide, --counts, --rename and --file-names apply to it too |
--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 |
--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 |
--verify FILE |
Check the signature next to a receipt or record. Add --signers allowed_signers to check whose key signed it |
--prices FILE |
Price with a newer copy of LiteLLM's model_prices_and_context_window.json instead of the one built in |
A record is in-toto's Statement 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.
A receipt after every Claude Code session
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:
{
"hooks": {
"SessionEnd": [
{ "hooks": [{ "type": "command", "command": "python3 ~/receipt.py --hook --out ~/receipts/" }] }
]
}
}
Keep receipt.py in your home folder for this, or change the path. Sessions with no prompts leave no receipt.
Plan use on the status line
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:
{ "statusLine": { "type": "command", "command": "python3 ~/receipt.py --statusline" } }
Opus 5.5 · $0.28 · 3 s · 5-hour 2% · weekly 51%
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:
#!/bin/sh
input=$(cat)
echo "$(echo "$input" | ~/.claude/my-statusline.sh) · $(echo "$input" | python3 ~/receipt.py --statusline)"
Good to know
- Claude Code deletes session logs after 30 days unless you raise
cleanupPeriodDaysin~/.claude/settings.json. Logs can be large, so check your free disk space before raising it a lot. - If you moved a tool's folder with
CLAUDE_CONFIG_DIR,CODEX_HOME,XDG_DATA_HOME,QWEN_HOME,GEMINI_CLI_HOMEorCOPILOT_HOME, the receipt looks there. - 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. - A Claude Code session resumed into a new log file gets its own receipt;
--combineadds them up. - 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. Open models, which many providers sell (MiMo, Nemotron, DeepSeek, GLM, Kimi, MiniMax, Mistral, Llama, gpt-oss), are priced at OpenRouter's list price, and the receipt says so. The built-in prices are LiteLLM's, dated on the receipt;
python3 tools/update_prices.pyrefreshes them. - 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.
- Qwen Code's background helpers (its memory extractor) make API calls of their own. They are counted, since Qwen Code logs them.
--recordand--bundlecover all six tools. Files made by shell commands aren't in a bundle or on a page.- 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.
- Files count what the edit tools wrote, subagents' included. A file the run changed again with a shell command counts as the run left it on disk. Files made only by shell commands aren't counted, and what subagents read isn't in a record.
- 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. - 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.
- 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.
- Checked on Linux, macOS and Windows (Python 3.9 and 3.13) on every change, and by hand on WSL and Windows 11.
- A receipt is text you can edit. It shows what someone reports, not proof, unless it's signed by a key you trust.
The prompts
Each prompt on the site 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, and links to its receipt.
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.
The gallery
The gallery shows every run on the site and ones people send in: what each made, whether it worked, what it cost and how long it took, grouped by prompt, with a summary for each model. Play it opens what a run made when it's something a browser opens (66 of the 308): a page, a toy or a 3D scene, as the run left it, from play/ (play/runs.json gives each page's run by its receipt number).
To add yours, run receipt.py --prompt --turns --recipe --redact --share in the folder you worked in. That shows how you made it: each prompt you sent, with its time, cost and what it did, and the commands to run them again (--turns 3-5 covers only prompts 3 to 5). Or paste your --link into the gallery's Add yours box, or open the link and press Add to the gallery. Each opens a GitHub issue with the link filled in, where you can say whether it worked and what it made. A bot replies with the receipt as the gallery will show it (a run of several prompts shows the first and how many), or says why it can't go in, and it goes in when the site's owner adds the gallery label. Everything in it is public, so leave out anything private first (--redact, --hide prompt).
The gallery can't check a receipt against the log it came from, since a link can be edited, so receipts sent in are marked as sent. Reported ones keep their REPORTED badge. tools/gallery.py does the checking.
License
The code (tools/receipt.py, the tests and the site's scripts) is MIT: see LICENSE. Prompts and page text are CC BY 4.0: see LICENSE-prompts. The outputs were made by the models named on each card.
Metadata
Release files for prompt-receipts 7.13
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| prompt_receipts-7.13.tar.gz | 163.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| prompt_receipts-7.13-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 268.7 kB
Release files / prompt_receipts-7.13.tar.gz
| Download URL | prompt_receipts-7.13.tar.gz |
|---|---|
| Size | 163.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f4b7436bd91525f1ca7279a7067e30d72eef718da39076ca646b7a5ae88fc55c
|
|
BLAKE2b-256 checksum How to use checksums |
14d7f576707a22c0b8d31c280735d8d69d3d6ff07db0ad350d691f9ef05ff785
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|
Release files / prompt_receipts-7.13-py3-none-any.whl
| Download URL | prompt_receipts-7.13-py3-none-any.whl |
|---|---|
| Size | 105.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
71c8172c9674dbbd11a1fb9d6f9f12f3916ce4de58348c015db04e739ea262c4
|
|
BLAKE2b-256 checksum How to use checksums |
d955c4b51772386f32fdcae66fd5c49a4f31820c4d91c62b389ae3f956a81a9f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.2
|