Save Checkpoint with Metadata
Write a checkpoint header you actually chose
- model
- clip
- vae
- clip_vision
- ckpt_path
- saved_metadata
- saved_prompt
- saved_extra_pnginfo
So you merged two checkpoints, dragged the result into a Save node, and got a file whose header ComfyUI decided for you and a filename with a counter you didn't ask for. This node is the antidote to both. Save Checkpoint with Metadata serializes your MODEL wire into a .safetensors file - optionally bundling CLIP, VAE, and CLIP_VISION in with it - while letting you write exactly the metadata header you want and pick how the file gets named.
It sits in advanced/model_merging as an output node, which tells you the intended audience: people who merge, test, and ship checkpoints. If you've ever uploaded a model somewhere and then had to re-save it because the header looked like junk, this is the node that fixes your next run.
How it works
A safetensors file is just a JSON header followed by raw tensor bytes - no executable code, which is the whole reason .ckpt (pickle) is dead. The header carries an optional __metadata__ string map, and that's the part this node puts you in charge of. Under the hood it calls ComfyUI's own comfy.sd.save_checkpoint, passing your final metadata dict and no extra keys. Because safetensors requires dict[str, str], the node JSON-encodes any non-string value for you - so {"training":{"epochs":80}} becomes a string instead of blowing up.
The two metadata_mode options are where the control lives. replace writes only what's in metadata_json - the prompt, the workflow, everything ComfyUI normally adds, all gone. merge_minimal builds a small base header from the hidden PROMPT input (your workflow JSON, the same thing ComfyUI embeds in generated images) plus the hidden EXTRA_PNGINFO, then overlays your metadata_json so your keys win. That hidden prompt embedding is ComfyUI culture - "workflow included" is the norm - so merge_minimal is the mode that keeps that behavior on the saved checkpoint without letting it run away with the whole header.
The inputs that actually matter
metadata_json- the whole point. A JSON object of header keys; this is your{"author":"you","modelspec.architecture":"sdxl","training":{"epochs":80}}.metadata_mode-replacefor a clean header,merge_minimalto keep the prompt/workflow then override.filename_prefix- subfolder and base name under ComfyUI's output directory, e.g.checkpoints/MyModel.filename_mode-smart_counterwritesMyModel.safetensorsif it's free, thenMyModel_00001_.safetensorsonward without ever overwriting.no_counter_overwritealways writes the plain name and clobbers whatever's there. The smart counter is genuinely nice: first save is a clean filename, later saves never silently destroy earlier work.prompt_overrideandinclude_extra_pnginfo- only do anything inmerge_minimal, and only if you care what goes into the base header.
The optional clip, vae, and clip_vision inputs embed those objects into the file, so you can ship a real checkpoint-style file, not just weights.
Outputs
Four string outputs for inspection, not for wiring into anything clever: ckpt_path (the full saved path), saved_metadata (final header as JSON), saved_prompt, and saved_extra_pnginfo. Handy for logging or a quick sanity check that your header landed.
Installing it
ComfyUI Manager → Install via Git URL → paste https://github.com/a-l-e-x-d-s-9/ComfyUI-SaveCheckpointWithMetadata.git, then restart. It's not in the default Manager catalog yet, so if Manager throws a security-level error, either install manually or drop your security level to middle/weak in config.ini. Manual is one command either way:
cd ComfyUI/custom_nodes
git clone https://github.com/a-l-e-x-d-s-9/ComfyUI-SaveCheckpointWithMetadata.git
Then restart ComfyUI. There are no dependencies - requirements.txt is explicitly empty, no model files, nothing heavy. This is about as low-friction as a custom node gets.
Troubleshooting
- You get
prefix_00001_.safetensorseven on the first save - something namedprefix.safetensorsalready exists in that output folder, so the smart counter correctly skipped it. - You expected
modelspec.*keys like the stock node adds - stock ComfyUI injects those automatically; this node doesn't, by design. Add them tometadata_jsonyourself. - It ignores
--disable-metadata- that launch flag stops ComfyUI from embedding prompt metadata in images, and people genuinely hit it. This node bypasses it entirely and writes what you specify. Which, honestly, is the point: if you want a header with no prompt, setreplaceand leave the prompt out.
One caveat before you ship your merge: a checkpoint that's all weights and no modelspec info will still load fine in ComfyUI - it's CivitAI-style galleries and other tools that expect those keys. Know your destination.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | MODEL to serialize into a .safetensors checkpoint. Wire your merged/trained model here. | |
| filename_prefix | STRING | checkpoints/CustomMeta | Subfolder/prefix under output directory. Example: checkpoints/MyModel. |
| filename_mode | COMBO | smart_counter | smart_counter: first save uses prefix.safetensors if free, later saves use prefix_00001_.safetensors. no_counter_overwrite: always write to prefix.safetensors and overwrite if it exists. |
| metadata_json | STRING | {} | JSON object of header keys to write. Values must be strings; non-strings are JSON-encoded for you. Example: {"author":"Alex","training":{"epochs":80}} |
| metadata_mode | COMBO | replace | replace: write only metadata_json. merge_minimal: start with prompt and optional EXTRA_PNGINFO, then apply metadata_json. |
| include_extra_pnginfo | BOOLEAN | true | Merge mode only. When ON, copy keys from hidden EXTRA_PNGINFO into the header before applying metadata_json. |
| prompt_override | STRING | Optional override for the hidden PROMPT. Ignored in replace mode. In merge_minimal mode, becomes the base prompt unless metadata_json also contains prompt. | |
| clipopt | CLIP | Optional CLIP to embed into the saved checkpoint. | |
| vaeopt | VAE | Optional VAE to embed into the saved checkpoint. | |
| clip_visionopt | CLIP_VISION | Optional CLIP_VISION to embed into the saved checkpoint. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| ckpt_path | STRING | — |
| saved_metadata | STRING | — |
| saved_prompt | STRING | — |
| saved_extra_pnginfo | STRING | — |