TF Save Images
The pictures that survive the cache clear
- images
- levels
- path
PreviewImage writes to ComfyUI's temp directory, so everything you looked at is gone the moment a cache clear happens. TF Save Images is the node that puts pictures somewhere permanent: it writes any IMAGE to output/trajectory_forcing/<name>.png, right beside the trajectory .npz and report .md from the same run. For most workflows that's a nicety; for a TF Sweep Edit it's the whole ballgame - a sweep's contact sheet shows every arm, but only the arm that leaves on a socket exists as latents, so every other arm exists nowhere unless you save the sheet. This node is how an experiment leaves evidence.
Inputs are refreshingly generic. images accepts any IMAGE - a batch is written as one file per frame, a stitched contact sheet is one file, so what you saw is what lands on disk. name (default images) sets the filename, and overwrite (off by default) means repeated saves append -001, -002, ... instead of silently replacing an earlier result. The path output tells you the exact file, which plays nicely with the pack's report and provenance story.
The optional levels input is where this pack's provenance obsession shows up, and it's worth using. Wire the trajectory in and each PNG's metadata carries the class, seed, and full edit history - so a picture can be traced back to the run that produced it without you maintaining a separate ledger. Months later, when you're looking at a folder of images trying to remember which edit this was, the metadata answers. If you're coming from a workflow where image files are anonymous, this feels like overkill right up until it saves a writeup.
Why does this node exist at all when ComfyUI ships SaveImage? Two reasons, and the README makes both concrete. The first is the sweep problem above: SaveImage writes a batch as one file per frame, but the thing you actually want to keep - the contact sheet where all arms are visible side by side - is a single stitched image, and this node treats it as one file. The second is provenance: stock SaveImage doesn't know a trajectory exists, so it can't stamp the class and seed into the file. Same folder, same run, one consistent naming scheme.
Where people get caught: filename collisions. With overwrite off (the default), saving the same name twice gives you name.png and name-001.png rather than an error or a silent replacement - which is the safe behavior, but it does mean re-running a workflow with an unchanged name accumulates files rather than refreshing one. If you want each run to clobber the previous result, that's what overwrite is for, deliberately opt-in. And remember the output folder is the same one TF Save Levels and TF Save Report use, so a well-named run leaves three sibling files - .npz, .md, .png - that read like a coherent experiment record rather than scattered artifacts.
Install
Pack-standard: Manager → search Trajectory Forcing, or git clone https://github.com/korayulusan/ComfyUI-TrajectoryForcing into custom_nodes/. Pure image IO, but the pack runs JAX inside ComfyUI and needs its own Python 3.11 environment on CUDA 12; requirements.txt is empty on purpose, install.py adds the JAX stack or declines with a reason (normal), and README's env/setup.sh is the fallback. Health check:
cd ComfyUI/custom_nodes/ComfyUI-TrajectoryForcing
python -m tf_nodes.doctor
Pair it with TFSaveReport on the same run and you get the two halves an experiment needs to survive: the numbers in the .md, the pictures next to them in the .png.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Any IMAGE. A batch is written as one file per frame; a stitched contact sheet is one file. | |
| name | STRING | images | — |
| overwrite | BOOLEAN | false | Off appends -001, -002, ... rather than replacing existing files. |
| levelsopt | TF_LEVELS | Optional provenance: class, seed and edit history are written into each PNG's metadata so a picture can be traced back to its run. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| path | STRING | — |