h4 : The Engine (Simple Sampler+Plot) v1.3.0
A sampler, an XY grid, and a LoRA watchdog in one node
- model_in
- clip_in
- vae_in
- conditioning_in
- conditioning_positive_in
- conditioning_negative_in
- latent_in
- image_in
- Images
- Grid_Image
- Model
- CLIP
- VAE
- Latent
- Positive
- Negative
XY plot grids are the classic way to answer "which sampler and CFG actually work for this prompt?" Most packs make you bolt a grid plotters onto a normal sampler. The h4 Toolkit's "Engine" (h4 : The Engine (Simple Sampler+Plot)) skips the bolt-on entirely: it is the sampler, and the grid is built into its output list. One node, an annotated comparison panel, and the model handles you'd otherwise have to re-route out of a KSampler.
It's also the flagship of a genuinely obscure pack - zero search impressions, essentially no community footprint, and the README flat-out announces it's a shelved project (the author points you at h4_Live instead). So set expectations: this is an enthusiast's tool, documented to an almost absurd degree by its author, and supported by exactly one person. The good news is the docs are unusually honest, and there's no heavy machinery under the hood - no model downloads, just plumbing over ComfyUI's own sampler infrastructure.
How it works
Give it a checkpoint (or wire model_in/clip_in/vae_in), a base prompt, and up to two axes. Each axis has a mode - prompt, checkpoint, sampler, scheduler, cfg, steps, denoise, seed, lora, or none - plus a newline-separated list of values. It builds a plan matrix, runs every combination through the sampler, and stitches the results into one labelled grid with the plan name written on each tile. Along the way it layers LoRAs, encodes images you feed it, clones incoming latents when you're refining, and keeps the final Model/CLIP/VAE/Latent/conditioning handles on its outputs so downstream nodes keep working without rebuilding state.
The touches you'll notice: it auto-cleans the CUDA cache between grid cells, it gracefully skips clip-skip when the model has no hook, and it tries to publish live previews mid-run (falling back to direct VAE decode if latent_preview isn't available). It also has a signature-aware sampler shim that renames or drops kwargs to match whatever ComfyUI version you're on - a nod to how often upstream breaks node packs, a theme the ecosystem knows all too well.
The inputs that matter
seed,steps,cfg,denoise- the baseline sampler settings. Axis plans can override per cell.sampler_name/scheduler_name- defaults for the whole grid.positive_prompt/negative_prompt- base text; apromptaxis appends its values to the base prompt.x_axis_mode/x_axis_valuesandy_axis_mode/y_axis_values- the actual grid. Keep these small at first; a 6×6 grid is 36 full generations.bypass_engine- handy during wiring: passes through without generating anything.
Outputs: Images (every render stacked), Grid_Image (the annotated panel - this is the one you save), plus Model, CLIP, VAE, Latent, Positive, Negative for chaining.
Install
ComfyUI Manager, search "h4 ToolKit", or:
cd ComfyUI/custom_nodes
git clone https://github.com/m3rr/h4_ToolKit
Restart and watch for the neon status banner. The only deps are colorama and numpy in requirements.txt, and the package auto-installs them (plus a torch version check) on startup - nothing to download by hand. One gotcha: the README talks about h4_Plot/nodes.py and h4_Plot/js/, but the shipped tree keeps nodes.py and js/ at the repo root. The code is what installs, not the prose.
Common issues
- Sampler rejects kwargs on bleeding-edge ComfyUI. The compatibility shim adapts known signatures, but brand-new sampler changes can outrun it. Update the pack, and the author notes recent ComfyUI builds generally fix this.
- Big grids eat VRAM. Start 2×3 before 8×8. The Engine clears cache per cell, but 36 images is 36 images.
- The seed trap. Put
seedon an axis and every cell rolls its own seed - great for txt2img exploration, disastrous for img2img. If you're refining an existing image with denoise < 1, keep the seed out of the grid and reuse the original seed, or every cell comes back completely different and your careful denoise value quietly stops meaning what you think it means.
Inputs (32)
| Name | Type | Default | Description |
|---|---|---|---|
| seed | INT | 00–4294967295 | — |
| steps | INT | 201–150 | — |
| cfg | FLOAT | 7.51–30 | — |
| denoise | FLOAT | 1.000–1 | — |
| clip_skip | INT | 21–12 | — |
| sampler_name | COMBO | euler | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 |
| scheduler_name | COMBO | normal | 6 options: normal, simple, karras, exponential, sgm_uniform, lognormal |
| width | INT | 51264–2048 | — |
| height | INT | 51264–2048 | — |
| checkpoint | COMBO | NONE | 1 options: NONE |
| vae_name | COMBO | <checkpoint> | 2 options: NONE, <checkpoint> |
| clip_text_name | COMBO | <checkpoint> | 2 options: NONE, <checkpoint> |
| clip_vision_name | COMBO | <checkpoint> | 2 options: NONE, <checkpoint> |
| positive_prompt | STRING | — | |
| negative_prompt | STRING | — | |
| x_axis_mode | COMBO | prompt | 10 options: prompt, checkpoint, sampler, scheduler, cfg, steps, +4 |
| x_axis_values | STRING | — | |
| y_axis_mode | COMBO | none | 10 options: prompt, checkpoint, sampler, scheduler, cfg, steps, +4 |
| y_axis_values | STRING | — | |
| bypass_engine | BOOLEAN | false | — |
| axis_xopt | STRING | — | |
| axis_yopt | STRING | — | |
| axis_zopt | STRING | — | |
| legacy_summaryopt | STRING | — | |
| model_inopt | MODEL | — | |
| clip_inopt | CLIP | — | |
| vae_inopt | VAE | — | |
| conditioning_inopt | CONDITIONING | — | |
| conditioning_positive_inopt | CONDITIONING | — | |
| conditioning_negative_inopt | CONDITIONING | — | |
| latent_inopt | LATENT | — | |
| image_inopt | IMAGE | — |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| Images | IMAGE | — |
| Grid_Image | IMAGE | — |
| Model | MODEL | — |
| CLIP | CLIP | — |
| VAE | VAE | — |
| Latent | LATENT | — |
| Positive | CONDITIONING | — |
| Negative | CONDITIONING | — |