Nodes/Macro Nodes/Save Image (Macro)
ComfyUI Node

Save Image (Macro)

Filenames that follow the model, and a workflow you can share without the prompt

By the-Macro-Man·Created 2 months ago·Updated 15 days ago· 1
Save Image (Macro)
  • images
    ◄folder_prefix►
    ◄file_prefix►
    ◄create_foldertrue►
    ◄embed_workflowtrue►
    ◄save_workflow_jsonfalse►
    ◄save_summary_txtfalse►
    ◄shorten_if_neededtrue►
    ◄model_name►
    ◄text—►

    Every ComfyUI install produces a folder full of ComfyUI_00047_.png and no memory of which checkpoint made which. Cycle between three models in a week and the default save node hands you a pile of files named after nothing, with your prompt welded into them as PNG text chunks.

    Save Image (Macro) is a drop-in replacement that names files after the model that made them, with per-node control over what travels with the image.

    The mechanism, and why it needs its own save node

    ComfyUI writes two PNG text chunks by default: workflow (the full UI graph - positions, wires, muted branches) and prompt (the API-format execution graph). That's what makes a PNG drag back onto the canvas as a reloadable project, and it's also why posting a raw ComfyUI PNG announces your prompt, negative, seed, checkpoint and LoRA list to anyone who opens it in a text editor. The metadata is the payload.

    The global escape hatch is the --disable-metadata launch flag or the "Disable saving prompt metadata" server setting. Both are all-or-nothing: they kill the chunks for every save node in the install, including the ones you wanted to keep.

    This node does the saving itself rather than handing a filename to core SaveImage, and the consequences are the whole feature list:

    The numbers match. Because this node does the saving, it knows which counter it landed on. draft_krea2_turbo_00007_.png gets a draft_krea2_turbo_00007_.json and a .txt with the same number. A node that only hands SaveImage a filename string can't know that - it has no idea what number SaveImage will land on.

    embed_workflow is per-node. Off means this one node writes a clean PNG with no prompt and no graph inside while everything else in your install behaves normally.

    It can measure the path. Only the saver knows the real output directory and final filename, so only the saver can shorten a name only when it would actually break.

    Model detection is a backwards walk of the execution graph until it hits a loader carrying a filename widget - ckpt_name, unet_name, model_name, model_path, gguf_name or name - which covers Load Checkpoint, Load Diffusion Model, the GGUF loaders and most custom ones without hardcoding any of them. The name is sanitised for both Windows and Linux (illegal characters to underscores, reserved device names like CON prefixed), so folders stay portable. Find nothing and you get unknown_model rather than a crash.

    The inputs that matter

    images is the only required input - wire your decode in and it works on defaults.

    • folder_prefix / file_prefix - prepended to the folder (art_ → art_krea2_turbo/) and the file (draft_). The folder one needs create_folder on.
    • create_folder (default on) - one subfolder per model. Makes a month of output navigable, and doubles the model name's contribution to path length.
    • embed_workflow (default on) - the privacy switch. Off for clean files.
    • save_workflow_json (default off) - the matching .json sidecar.
    • save_summary_txt (default off) - a one-screen text file with model, LoRAs, sampler, steps, CFG, seed and prompt. Greppable from a shell without opening ComfyUI - the entire point.
    • model_name - leave blank to detect; type into it to force a name.
    • text - a connect-only STRING input. The interesting one: wire the prompt you actually used and it's written to the numbered .txt whether or not save_summary_txt is on. The auto-summary is a best-effort guess reassembled from graph widgets; this is the real string. With both on, the summary is appended below a --- workflow summary --- rule.

    The node has no outputs - it's an output node, so it always runs and the cache works backward from it.

    Installing it

    cd ComfyUI/custom_nodes
    git clone https://github.com/the-Macro-Man/ComfyUI-MacroNodes
    

    Restart. Or through ComfyUI Manager, search Macro Nodes, or comfy node install macronodes. Found under MacroNodes/image. Nothing to pip install: the pack ships no requirements file, and PIL and numpy are already hard requirements of ComfyUI itself.

    Where people get burned

    Long paths on Windows. shorten_if_needed (default on) measures the finished path against the 260-character limit and does nothing below it. When it must act it first drops suffixes describing the packaging rather than the model (_fp8_scaled, _pruned_emaonly), and only truncates if that isn't enough. Note the create_folder interaction: the model name appears in the folder and the filename, so it counts twice. Without a limiter an over-long path fails mid-batch instead of at the start, which is how you lose an overnight run.

    Two loaders in one graph. The name comes from whichever loader the walk reaches first, so with a refiner or a second checkpoint it can pick the one you didn't mean. That's what model_name is for.

    If you post to CivitAI, read this part. Stripping the embedded workflow is great for privacy, but it doesn't make this a metadata-optimised upload node. CivitAI's auto-detection keys on an A1111-style parameters chunk plus matchable resource hashes, which ComfyUI's save code - including this one - doesn't write. If auto-linking your checkpoint and LoRAs on upload matters, that's a different node. This one keeps your archive legible and your public images clean.

    Getting the graph back. Drag the .json into ComfyUI and the graph reloads just as a PNG would - change the seed and you're iterating on the same pipeline.

    CategoryMacroNodes/image

    Inputs (10)

    NameTypeDefaultDescription
    imagesIMAGEThe images to save.
    folder_prefixoptSTRINGText prepended to the FOLDER name, e.g. 'art_' gives art_krea2_turbo/. Only used when create_folder is on.
    file_prefixoptSTRINGText prepended to the FILE name, e.g. 'draft_'.
    create_folderoptBOOLEANtrueON: save into a subfolder named after the model.
    embed_workflowoptBOOLEANtrueOFF writes a clean PNG with no prompt or workflow inside - safe to post publicly. Combine with save_workflow_json to keep the workflow beside the file instead.
    save_workflow_jsonoptBOOLEANfalseWrites the workflow next to each image, with a matching number. Drag the .json into ComfyUI to reload the graph.
    save_summary_txtoptBOOLEANfalseA short readable summary - model, LoRAs, sampler, steps, CFG, seed, prompt. Greppable without opening ComfyUI.
    shorten_if_neededoptBOOLEANtrueOnly acts when the finished path would exceed the Windows 260-character limit. Drops _fp8_scaled and similar first, then truncates. Short names are never touched.
    model_nameoptSTRINGLeave blank to detect from the graph. Type a name to force one.
    textoptSTRINGText to save beside each image, numbered to match. Connect the prompt you actually used - the auto summary is a guess assembled from the graph, this is the real thing. Writes the .txt even when save_summary_txt is off.

    Outputs (0)

    No outputs