Hook Recenter
A conditioning wire that switches recentering on
- prompt
- CONDITIONING
The recentering idea keeps coming back in this pack, and each version finds a different way to wire it into the graph. Hook Recenter is the version that rides the conditioning path: instead of replacing your KSampler or sitting on the latent wire, it takes a CONDITIONING in and hands the same CONDITIONING back - while quietly installing the recenter hook that your sampler will use. It's the most explicit of the pack's "switch" nodes, and the custom_sampler toggle makes it the one you'd reach for when your workflow uses a custom sampler.
How it works
The node stores your target channel means and strength, then monkey-patches ComfyUI's sampling functions - but which function depends on the custom_sampler boolean:
custom_sampleroff (default): it wrapscomfy.sample.sample, which is what the standard KSampler calls.custom_sampleron: it wrapscomfy.sample.sample_custominstead, which is the path ComfyUI's advanced/custom sampling nodes use.
From then on, each sampling step recenters the 4 latent channels toward your targets: x[channel] += (target[channel] - x[channel].mean()) * strength. The CONDITIONING it outputs is literally the same tensor you put in - the node's graph position is what matters, not its data flow.
Why the conditioning input matters
The input being CONDITIONING rather than LATENT is a deliberate ordering trick. Because of how ComfyUI executes the graph, a node that takes conditioning is evaluated in the run when your prompt encoding runs - so putting Hook Recenter in the conditioning path (e.g. inline after your positive text encode) means the hook is installed before any KSampler that depends on that conditioning. You get ordering you can reason about, which is precisely what the pack's other global-state nodes don't give you.
The inputs that matter
- prompt -
CONDITIONING. Wire it through (positive or negative path; it passes through unchanged). - custom_sampler - boolean, default off. Set it on if your sampler goes through
sample_custom(advanced sampler nodes). - strength - 0 to 1, default 0. Effect volume.
- C (default 0.01), M (default 0.5), Y (-0.13), K (0) - target means for the 4 SD 1.5 channels, mapped internally as
[-K, -M, C, Y].
Output: CONDITIONING - wire it to your KSampler's positive/negative input as you normally would.
A note on versions and the off switch
Hook Recenter comes from the "complete rewrite" era of the pack, which also shipped Unhook Recenter - the node that restores the original sampling functions to turn the hook off mid-graph. The current v2 release replaced this whole family with Diffusion CG + Disable CG. If you install today and only find those two nodes, that's the redesign; use Diffusion CG for the same recenter effect.
Also note the hook is still effectively global for the duration of the run - it patches module-level functions, so every sampler that runs after it is affected, not just the one you wired. That's exactly what Unhook Recenter (or Disable CG in v2) exists to clean up.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Haoming02/comfyui-diffusion-cg
Restart ComfyUI. Zero dependencies, no model downloads. And same caveat as the whole pack: not every sampler cooperates - the README's known issue ("does not work with certain samplers") still applies, especially to low-step/distilled samplers.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | CONDITIONING | — | |
| custom_sampler | BOOLEAN | false | — |
| strength | FLOAT | 0.00–1 | — |
| C | FLOAT | 0.01-1–1 | — |
| M | FLOAT | 0.50-1–1 | — |
| Y | FLOAT | -0.13-1–1 | — |
| K | FLOAT | 0.00-1–1 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| CONDITIONING | CONDITIONING | — |