Fixed Seed Controller
Let This Node Hold One For You
- seed
- seed_info
You know the drill: you queue a prompt, don't like it, tweak one word, queue again - and the seed rolled over, so you're not actually comparing anything. The single most repeated piece of advice in the SD community is "change one variable at a time with a fixed seed," and the reason people ignore it is that ComfyUI makes locking a seed annoying. Its KSampler randomizes the seed widget on every queue unless you stop and type a value back in. Fixed Seed Controller is a one-trick node that automates the boring part: it holds a seed, hands it to your sampler, and only rolls a new one when you explicitly say so.
The scenario it's built for is the SaveImage-on-bypass trap. You preview by queuing with SaveImage bypassed, finally get a frame you like, un-bypass and save - and the seed changed in between, so what gets written to disk isn't what you fell for. Wire this node's seed into your sampler and that whole failure mode disappears.
How it works
Mechanically it's embarrassingly simple, which is the point. The node keeps one integer in memory and mirrors it to a last_seed.json file inside its own folder, so the value survives ComfyUI restarts. On its very first run it has nothing stored, so it generates regardless of the toggle. After that it only rolls random.randint(seed_min, seed_max) when generate_new_seed is flipped to Generate New; set it back to Keep Current and it returns the same value forever.
One thing worth knowing before you trust it: every instance of this node in your workflow reads and writes the same last_seed.json. The README claims each node has its own seed store - the code says otherwise. That's fine as long as you only use one instance per workflow. Use two and they'll clobber each other's values, which is exactly the crossed-wires bug the README warns about (even if its stated reason is wrong).
Inputs and outputs
Only the few that matter:
generate_new_seed(boolean, default off) - the whole point. The widget even labels itself "Generate New" / "Keep Current" so you don't have to remember which way is which.manual_seed(optional int, default -1) - the tooltip is the spec: "Set to -1 to use random generation, or enter a specific seed." A value ≥ 0 wins over everything, toggle included. This is how you say "give me exactly 8675309."seed_min/seed_max- bounds for random generation, defaulting to the full 0 to 2^64−1 range. Leave them unless you're deliberately farming seeds inside a narrow window.
Outputs are a seed (INT) that wires into any sampler's seed input, and a seed_info (STRING) that tells you what it just did - "New Random Seed: X", "Fixed Seed: X", "Manual Seed: X". Feed seed_info into a ShowText node if you want it visible in the graph; the node itself doesn't display anything.
Installing it
Zero dependencies - it's pure Python standard library, no pip install, no model files, nothing to download but the repo. In ComfyUI Manager, search "ComfyUI-FixedSeedController" and hit install. Or clone it yourself:
cd ComfyUI/custom_nodes
git clone https://github.com/Slartibart23/ComfyUI-FixedSeedController.git
Then restart ComfyUI and you'll find "Fixed Seed Controller" under the utils category.
Gotchas
- The README is in German. If you don't read German, the instructions here are the translation.
- Reinstalling the pack resets your seed -
last_seed.jsonlives inside the repo folder, so a fresh clone or a destructivegit pullwipes your remembered value. - Node not appearing after install? Full restart, then check the folder is named exactly
custom_nodes/ComfyUI-FixedSeedController/. - If you're already on rgthree, its Seed node does something similar for giant workflows. This one is the minimal single-purpose alternative - no pack baggage, no frontend compatibility drama, just a seed that holds still.
Is this node changing anyone's life? No, and with 2 search impressions a month nobody's arguing about it. But if you've spent an evening squinting at two images wondering which parameter did that, it's three minutes of install to never do that again.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| generate_new_seed | BOOLEAN | false | — |
| seed_min | INT | 00–18446744073709550000 | — |
| seed_max | INT | 184467440737095500000–18446744073709550000 | — |
| manual_seedopt | INT | -1-1–18446744073709550000 | Set to -1 to use random generation, or enter a specific seed |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| seed | INT | — |
| seed_info | STRING | — |