Skip to main content
Claude Code is Anthropic’s terminal coding agent. These two commands take the work you did in it and record that work in Receipt, so a session you ran in your own terminal becomes a replayable run beside the ones Receipt did itself. receipt import reads a log of Claude Code activity once. receipt observe does the same thing and keeps following the file. Both turn each line into receipts. The ones that are uploaded land on the Sessions page as replayable runs; a local-only import stays on your machine and never appears there. Read the warning on this page before you run either command against real work.

Read this first

Metadata mode does not redact your prompts.The --mode metadata default redacts a fixed list of sensitive keys from the raw captured payload only. The normalized receipt — the one the Sessions page reads — still contains prompt text, assistant replies, tool inputs such as the bash commands that were run, tool output such as stdout and stderr, along with the working directory and the git branch.Receipt’s own repository documentation claims the opposite. The code and its tests do not. Do not run receipt import or receipt observe against sessions containing data you are not willing to store in Receipt.
Captured activity is uploaded by default. Once you have signed in with receipt setup, imports and observations go to the hosted store in your Receipt workspace, not to your machine. Pass --local-only (or --no-cloud, or --no-upload) to keep them local.

The two sources

A source is where the record of the session comes from. clauden is a companion proxy that sits in front of Claude Code and writes its own event log; claude-code reads the transcript files Claude Code writes for itself. Both sources are implemented, but only the second needs nothing extra: the current release does not ship the companion binary, so clauden works only if you supply one (see receipt setup and the observer). For clauden, the default becomes the legacy text log ~/.claudeN/clauden.log only when you also launch the companion and the resolved binary is named clauden. Without --launch, the default is always ~/.claudeN/events.ndjson. For claude-code, Receipt scans ~/.claude/projects and takes the newest .jsonl file by modification time, falling back to ~/.claude/projects/latest.jsonl when it finds none. The stream project name comes from the parent directory, and the source id is the file name with .jsonl stripped, which is the session UUID.
claude-code appears in no help text. receipt --help and the usage strings list only clauden. The source is fully implemented and validated — it is only reachable by typing it.
Omitting the source, or naming another one, fails with the same message either way:

Commands

receipt import <source> [<path>] runs once over the file. receipt observe <source> is the same import with follow mode forced on.

Flags

--launch without --follow fails with --launch requires --follow or receipt observe clauden. Any other failure exits 1, like every other command in this CLI; see Environment and exit codes. Both commands always emit JSON, so --json does nothing here:
When receipts were uploaded, the envelope also carries cloud with the gateway URL and the organization id. Read storage to confirm where the receipts actually went.
With --output-file, the result JSON goes to the file and stdout gets a pointer object instead — ok, the absolute outputFile and its bytes. Unlike receipt tools and receipt mcp config, import and observe write that file with a plain write at your default umask, not atomically and not at mode 0600.

Where receipts go

There are two destinations, and the CLI picks between them for you:
  1. A saved CLI session exists — receipts go to the hosted store in your workspace, storage: "cloud".
  2. Otherwise — receipts go to a file-backed store under RECEIPT_DATA_DIR, or ~/.receipt/data when that is unset, storage: "local".
Any of --local-only, --no-cloud or --no-upload disables the cloud path, so a signed-in machine can still keep an import to itself.
ZERO_UPSTREAM_DB is read on this path but has no effect. The released binary always forces the local store, so the third destination you may see referenced, storage: "postgres", is unreachable from it — only the developer CLI built from source can produce it.
Uploads go to <gatewayUrl>/api/receipt-ingest/receipts with your session bearer token, which must carry connect:write. The endpoint caps a request at 2 MiB and 100 receipts, and accepts only the imports/clauden/ and imports/claude-code/ stream prefixes. A custom --stream outside those prefixes is rejected:

What is captured

Each transcript line produces two receipts: import.raw_object.captured for the raw object and import.object.normalized for the normalized one, or import.object.rejected when the line cannot be parsed. The run is bracketed by import.batch.started and import.batch.completed. Duplicates are collapsed on an event id built from the source, source id, object id and event type. The normalized receipt carries the model, whether the call was streamed, the HTTP status, the session key, request and response byte counts, rate-limit and cooldown state, method and path, cwd, gitBranch, entrypoint, user type, prompt and request ids, version, stop reason, any error, and a timeline. The timeline is the part that matters for the warning above. Each entry has a role — user, assistant, system, tool use, tool result, attachment, metadata or error — plus its text, content, token usage, tool name, tool result, and metadata including the last prompt and the permission mode. Token counts are copied through from the transcript. Receipt does not compute a cost.

Running it in the background

install accepts --mode, --event-log, --proxy-bin, --poll-ms, --stream, --receipt-bin and --no-start. This is a clauden-only feature. Asking for it on the other source is refused:
To follow claude-code transcripts continuously, run receipt observe claude-code yourself and keep it running. Only macOS and Linux are supported. Anywhere else: Background Claude observation is currently supported on macOS and Linux.

Service paths

These are visible on your machine, so they are worth knowing exactly.
The launchd label is run.beetle.clauden-observer, at:
Logs are written to <dataDir>/logs/clauden-observer.out.log and <dataDir>/logs/clauden-observer.err.log, where the data directory is RECEIPT_DATA_DIR or ~/.receipt/data. The installed command is:
The service runs that command and nothing else, so it uploads to the cloud store whenever a saved session exists. install has no --local-only, and the flag would not survive into the installed command: if you do not want the service uploading, do not install it.
The service label and unit filename use the string beetle, not receipt; Beetle is the assistant’s name in the interface. Search for that string when you are looking for the service on disk.

receipt setup and the observer

receipt setup installs this background observer as part of signing you in. Decline it with --no-observer (also spelled --no-claude, --no-background or --skip-claude). The install only happens when the companion binary is on the machine, and the current release archive does not contain one, so on a stock install the step reports itself as not installed with the resolution error rather than failing the sign-in:
The CLI looks for the companion in order: --proxy-bin, --clauden-bin, RECEIPT_CLAUDE_PROXY_BIN, CLAUDEN_BIN, then receipt-claude-proxy next to the CLI entrypoint and next to the executable, then clauden in those same two places, and finally receipt-claude-proxy and then clauden on PATH.

Seeing what you imported

Uploaded runs appear at /sessions, which reads exactly the two stream prefixes the ingest endpoint accepts. That page is not in the sidebar — it is reachable by direct URL only. With nothing imported it reads No imported sessions yet. A --local-only import never reaches it. Next step: look up every command, flag and exit code.