SD Prompt Saver
Make ComfyUI outputs readable by Civitai again — hashes and all
- images
- lora_name
- FILENAME
- FILE_PATH
- METADATA
SDPromptReader is the pack's best-known node, but SDPromptSaver is the one you actually want in your workflow. ComfyUI's native save writes its workflow JSON into the PNG, and that's fine for sharing with other ComfyUI users - but post that same image to Civitai and the site shrugs, because it wants A1111-style parameters text. This node writes that text. It's the write-side of the same coin, and the two halves are meant to live together.
What it does
When you save through SDPromptSaver, it builds an A1111-format comment - positive prompt, Negative prompt:, Steps:, Sampler:, CFG scale:, Seed:, Size:, Model: - and embeds it in the file. For PNG it also keeps the ComfyUI workflow JSON in the same file, so you get Civitai compatibility and drag-and-drop workflow reconstruction. JPEG and WebP only get the metadata (via piexif, the pack's one dependency), because those formats can't hold the workflow chunk at all.
The killer feature is calculate_hash. With it on, the node computes a truncated SHA-256 of your checkpoint, VAE, and any LoRA and embedding, then writes them as Hashes: in the metadata. Flip on resource_hash as well and those hashes drive Civitai's auto-detection, so the site shows exactly which model and LoRA made the image. This is the detail that separates "someone posted the image" from "someone posted the image and the card's resource tab fills itself in."
The trade-off: the first save after a restart, or after you swap in a new model, is noticeably slower while it hashes. The results are cached in memory for the session, so it's a one-time hit per model.
The inputs that matter
The images input is required; everything else is optional, and most of it you'll hand over from the SD Parameter Generator node rather than typing by hand. The few worth setting yourself:
filenameandpathsupport placeholders like%time,%seed,%counter,%date,%model,%sampler.%countercounts every image file in the target path and auto-increments so you never overwrite - duplicate filenames get_1,_2suffixes anyway.extension-png,jpg,jpeg, orwebp. PNG is the default and the only one that keeps the workflow embed.calculate_hashandresource_hash- described above; both default on, which is the right call.lora_nameis a wildcard input you feed from the pack's SD Lora Loader or Lora Selector chains, so LoRA hashes actually make it into the file.save_metadata_filealso drops a.txtalongside the image, andextra_infoappends whatever arbitrary note you want to the metadata.
It's an output node, so the three outputs are mostly bookkeeping - but FILENAME and FILE_PATH are handy if you have downstream nodes that need to know where the file landed, and METADATA is the exact comment string it wrote, useful for logging or feeding back into a reader.
Installing it
Same story as the whole pack - ComfyUI Manager, search "SD Prompt Reader," or:
cd ComfyUI/custom_nodes
git clone --recursive https://github.com/receyuki/comfyui-prompt-reader-node.git
cd comfyui-prompt-reader-node
pip install -r requirements.txt
Restart, done. The --recursive matters because the pack's metadata engine ships as a submodule, and the README explicitly tells you to avoid the ZIP install. Only piexif gets installed, so no heavy dependencies.
Gotchas
First save after a model swap being slow isn't a bug, it's the hash. Don't disable calculate_hash out of impatience - you lose the Civitai auto-detection that's the whole point. And remember that only PNG carries both the metadata and the workflow; if you save JPEG for file size, you're giving up the workflow-embed and the hashes go into EXIF, which Civitai reads but ComfyUI's own image drag-in won't reconstruct.
Inputs (24)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| filenameopt | STRING | ComfyUI_%time_%seed_%counter | — |
| pathopt | STRING | %date/ | — |
| model_nameopt | COMBO | 0 options: | |
| vae_nameopt | COMBO | 0 options: | |
| seedopt | INT | 00–18446744073709550000 | — |
| stepsopt | INT | 201–10000 | — |
| cfgopt | FLOAT | 8.00–100 | — |
| sampler_nameopt | COMBO | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 | |
| scheduleropt | COMBO | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 | |
| lora_nameopt | * | — | |
| widthopt | INT | 11–16384 | — |
| heightopt | INT | 11–16384 | — |
| positiveopt | STRING | — | |
| negativeopt | STRING | — | |
| extensionopt | COMBO | 4 options: png, jpg, jpeg, webp | |
| calculate_hashopt | BOOLEAN | true | — |
| resource_hashopt | BOOLEAN | true | — |
| lossless_webpopt | BOOLEAN | true | — |
| jpg_webp_qualityopt | INT | 1001–100 | — |
| date_formatopt | STRING | %Y-%m-%d | — |
| time_formatopt | STRING | %H%M%S | — |
| save_metadata_fileopt | BOOLEAN | false | — |
| extra_infoopt | STRING | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| FILENAME | STRING | — |
| FILE_PATH | STRING | — |
| METADATA | STRING | — |