Set Metadata For A1111
Write A1111-compatible generation info into your image
- images_passthrough
- IMAGE
ComfyUI stores its generation record as an embedded workflow graph - great for reopening the exact same node setup, useless if you or anyone downstream wants to read "steps: 20, cfg: 7, sampler: euler" the way AUTOMATIC1111's WebUI writes it. A huge amount of tooling around Stable Diffusion - CivitAI's own metadata reader among it - still expects that older, flatter A1111-style text block in the PNG info. This node bridges the gap: it writes that A1111-compatible block into your image alongside (not instead of) ComfyUI's own workflow metadata.
The node's own description carries a real warning worth repeating: it runs on every generation to make sure the metadata always gets written, which means placement matters. Put it as close to your actual save node as possible - last thing before the file hits disk - so you're not paying for extra node execution downstream of something that's meant to be a final step.
How it works
images_passthrough is required and returned unchanged; everything else is optional, and each field maps to a specific line in the A1111 metadata block: positive_prompt/negative_prompt, steps, cfg, model_name, sampler_name, scheduler_name, vae_name, seed_number, clip_skip, and image_width/image_height. Leave any of them unset and that field just doesn't get written - nothing's forced.
clip_skip is worth understanding specifically, because ComfyUI and A1111 don't count it the same way. A1111 counts CLIP skip 1 to 12 (1 = default, no skip); ComfyUI's own CLIPSetLastLayer node counts -1 to -24 in the opposite direction (-1 = default). This node's clip_skip defaults to -1 with a max of -1, matching ComfyUI's own convention rather than A1111's - so if you're hand-copying a value from an A1111 setting of "2," the ComfyUI-side equivalent is -2, not 2. Get that backward and the number written into the metadata won't mean what a reader expects.
The inputs and outputs
images_passthrough(IMAGE, required) - the image; returned unchanged.positive_prompt/negative_prompt(STRING, multiline, optional)seed_number(INT, optional)steps(INT, default 20, optional)cfg(FLOAT, default 8, optional)model_name/sampler_name/scheduler_name/vae_name(STRING, optional)clip_skip(INT, default -1, optional) - ComfyUI's -1-to-negative convention, not A1111's 1-to-12.image_width/image_height(INT, optional)IMAGEoutput - the same image, now carrying A1111-style metadata.
How to install it
Via ComfyUI Manager: Install Custom Nodes, search "JNodes", install, restart. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/JaredTherriault/ComfyUI-JNodes
pip install -r ComfyUI-JNodes/requirements.txt
then restart ComfyUI. No model downloads.
Common issues & troubleshooting
Extra nodes executing after this one for no reason. Because this node runs on every single generation by design, anything wired downstream of it also runs every time. The pack's own guidance is explicit: put it last, immediately before your save node, not somewhere in the middle of a longer chain.
Metadata reader showing a CLIP skip value that seems "backwards" or off by a sign. That's the ComfyUI-vs-A1111 counting difference, not a bug - ComfyUI's own -1 is A1111's 1 (no skip), and ComfyUI's -2 is A1111's 2. If you're deliberately trying to match an A1111 setting, negate and check the direction, don't just copy the number across.
Fields silently missing from the metadata. Every field except images_passthrough is optional, and an unset field is simply omitted, not written as blank or zero. If a metadata reader downstream expects a full set of fields and something's missing, check that you actually wired that specific value in rather than leaving the widget at its default.
CFG or steps not matching what actually ran. This node writes whatever values you feed it - it doesn't introspect your actual sampler node to confirm they match. If you change your KSampler's settings but forget to update the matching values feeding this node, the metadata will describe a generation that didn't actually happen that way. Wire these from the same source values your sampler uses, not separate hardcoded widgets, if you want them to stay honest.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| images_passthrough | IMAGE | — | |
| positive_promptopt | STRING | — | |
| negative_promptopt | STRING | — | |
| seed_numberopt | INT | 0 | — |
| stepsopt | INT | 201–10000 | — |
| cfgopt | FLOAT | 8.000–100 | — |
| model_nameopt | STRING | — | |
| sampler_nameopt | STRING | — | |
| scheduler_nameopt | STRING | — | |
| vae_nameopt | STRING | — | |
| clip_skipopt | INT | -1 | — |
| image_widthopt | INT | 0 | — |
| image_heightopt | INT | 0 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |