Local Run Receipts: Build Run Key
A Stable ID for Every ComfyUI Run (Built From What You Declare)
- run_key
- canonical_record
Give every run a name it can't forget
Local Run Receipts: Build Run Key is the front half of a two-node pair, and it does exactly one job: it turns values you type into a stable identifier for a run - a canonical JSON record plus a key like lrr1_3f9a... (a SHA-256 hash of that record). No models get loaded, no files get written, nothing gets uploaded. It builds a key; its partner node, Commit Image Run, is the one that actually saves your images under it.
Why bother? Without a stable key, "did I already run this?" is a guess. With one, the commit node can give you a definitive answer: CREATED if this is new, ALREADY_IDENTICAL if the same declared values already produced these exact pixels, or a hard stop if the same key somehow produced different pixels. That turns retries and parameter sweeps from a trust-me exercise into something the workflow itself can verify.
How it works
The node normalizes your declared values (trims and length-checks text, requires a non-negative integer seed), canonicalizes them into JSON with sorted keys and no whitespace, and hashes it. Deterministic: same declared values in, same lrr1_ key out, every time, on any machine. That's what makes the key worth anything - a fingerprint of the run as you described it.
The catch, and it's a real one, is the phrase "as you described it." The node never inspects your model weights, sampler, LoRAs, or CUDA kernels - it hashes exactly what you type in and nothing more. Two runs that declare identical values but use different models will share a key, and the commit node will flag byte-different images as a conflict instead of starting a fresh run. So this key detects changed runs and accidental retries; it's not a claim of bit-for-bit reproducibility. The README is blunt about this: it does not prove the same weights, custom nodes, or machine settings were used later.
The inputs that matter
namespace(defaultlocal) - your scope. Think of it as a tenant or project name; use something more specific thanlocalonce you have more than one experiment going, or all your runs compete for the same bucket.label(defaultSD 1.5 image) - a human-readable description of the run. Cosmetic, but it lands in the receipt and makes a folder tree legible later.seed- the seed you intend to use. It's just a declared integer up to 2^53−1 (the largest integer ComfyUI's frontend handles cleanly); the node doesn't verify the sampler actually used it.parameters_json(default{"sampler":"euler","steps":20}) - the real payload. This must be a valid JSON object. Declare whatever makes a run distinct here: sampler, steps, CFG, model name, resolution. This is the field that actually differentiates runs.parent_run_key(default empty) - optional chaining. Feed it a validlrr1_key to mark this run as a child or retry of an earlier one; it gets recorded in the receipt.
Outputs: run_key (the lrr1_... string) and canonical_record (the normalized JSON). Wire both into Commit Image Run - the commit node re-derives the expected hash from the record and errors if it doesn't match the key, so you can't silently mix records.
Install
The pack is new and the Registry listing is pending, so until it's live, clone and restart:
cd ComfyUI/custom_nodes
git clone https://github.com/nawnie/ComfyUI-Local-Run-Receipts
Restart ComfyUI after. Once the listing publishes you can install "Local Run Receipts" from ComfyUI Manager instead. There are no models to download and no dependencies beyond Pillow and NumPy (already part of ComfyUI), though it needs ComfyUI 0.28.0+.
Troubleshooting
parameters_jsonmust be valid JSON - the most common beginner trip. Paste a prompt instead of an object, or leave a trailing comma, and you get a clean error before anything runs. It must parse to a JSON object specifically, not a list or a number.- Same key, different images, conflict error - you forgot to declare something that actually changed (a model, a LoRA, a step count). The fix is to add it to
parameters_jsonor bump the seed so the run gets its own identity. - A quick smoke test - the pack ships a no-model starter that makes a 128px empty image and commits it with a receipt, no GPU involved. Run it twice to see
CREATEDthenALREADY_IDENTICAL, and change a declared value to watch the key change. It talks only to127.0.0.1:8188by default (--portif yours is elsewhere).
Use this node the way you'd use a commit hash: as an identity for the values you decided to save, declared honestly and checked automatically. It won't do the honesty part for you.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| namespace | STRING | local | — |
| label | STRING | SD 1.5 image | — |
| seed | INT | 00–9007199254740991 | — |
| parameters_json | STRING | {"sampler":"euler","steps":20} | — |
| parent_run_key | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| run_key | STRING | — |
| canonical_record | STRING | — |