Nodes/ComfyUI-CFG-Ctrl/SMC-CFG (CFG-Ctrl)
ComfyUI Node

SMC-CFG (CFG-Ctrl)

The node that puts your CFG scale on rails

By flyghtxmz·Created 6 months ago·Updated 6 months ago· 1
SMC-CFG (CFG-Ctrl)
  • model
  • model
smc_lambda0.05
smc_k0.10
warmup_steps2
adaptive_scaletrue
max_correction_ratio0.25

If you've ever pushed CFG past ~7 on SDXL and watched faces melt into oversaturation, you already know the failure this node is built to fix. Plain CFG is a proportional controller with a fixed gain - the bigger the scale, the harder it yanks the image toward your prompt, and past a point it overshoots and burns. SMC-CFG treats guidance like a control-theory problem and adds a correction term that damps exactly that overshoot. It comes from the CFG-Ctrl paper (arXiv 2603.03281, CVPR 2026), and this pack by flyghtxmz is a clean reimplementation for ComfyUI.

What it actually is

A one-wire model patch. You slot it between your checkpoint loader and the KSampler, and it doesn't call any API or need any extra model files. It lives in the model wire, same family as CFGNorm or PerturbedAttentionGuidance, and it rewrites how guidance is computed at sampling time. Important: it does not replace your CFG scale. The CFG value on the KSampler is still the proportional gain w; the node layers the sliding-mode correction on top.

How it works

Every denoising step, the sampler computes two predictions: v_cond (with your prompt) and v_uncond (without). Their gap is the guidance error e_t = v_cond - v_uncond, and vanilla CFG is just v_uncond + w * e_t. SMC-CFG builds an "exponential sliding surface" out of the current and previous error - s_t = (e_t - e_prev) + λ * e_prev - then applies a switching term u_sw = -K * φ(s) that shoves the error back toward the manifold instead of letting it fly past. Final output is v_uncond + w * (e_t + u_sw). The node tracks e_prev across steps and resets it when it detects a new generation (sigma jump) or a new latent shape, so it doesn't leak state between runs.

The inputs that matter

  • smc_lambda (default 0.05) - how much of the previous step's error carries into the sliding surface. Here's a trap: the paper and the README's settings table recommend 5.0 for FLUX/SD3/Wan, but the shipped default is 0.05, which is a much weaker carry-over. Start at the default; set it to 5.0 if you want the paper's behavior.
  • smc_k (default 0.1) - the switching gain. With adaptive_scale on, this is a dimensionless ratio: 0.1 means the correction never exceeds ~10% of the error signal, and the tooltip's safe range is 0.05–0.3. This is the dial to reach for when output gets crunchy.
  • warmup_steps (default 2) - the first N steps run with no guidance at all (conditional prediction only) before SMC activates. The README calls this "vanilla CFG" warmup, but the code actually returns the raw cond prediction; either way, it's a sensible way to avoid over-correcting the noisy early steps.
  • adaptive_scale (default on) - normalizes the sliding surface by ||e_t|| so the same K works across FLUX, SD3, SDXL, SD1.5 and Pony without per-model tuning. Leave it on; turning it off means re-tuning K per model.
  • max_correction_ratio (default 0.25) - the safety clamp. The correction is capped at 25% of the error signal, which is why you can't really break anything with this node. Set 0 to disable.

One output: a model (MODEL), wired straight into the KSampler's model input.

Install

ComfyUI Manager, search "CFG-Ctrl", install, restart. Or the manual route:

cd ComfyUI/custom_nodes
git clone https://github.com/flyghtxmz/ComfyUI-CFG-Ctrl

then restart ComfyUI. That's it - no requirements.txt, no pip deps beyond torch (which ComfyUI already ships), no model downloads. The whole pack is a single ~500-line nodes.py, MIT-licensed.

Common issues

  • Looks identical to without the node - you're at CFG 1, or there's no negative prompt creating an error signal. No gap, no correction. Check that CFG > 1.
  • Oversaturation / crunchy edges - lower smc_k to 0.05–0.1, or use the Advanced node's smooth mode to soften the switching.
  • Output drifting toward the negative - raise smc_lambda.
  • Distilled models (Schnell, Turbo, etc.) at CFG 1 - there's nothing to correct. Skip the node.

One honest caveat: the CFG-Ctrl method is brand new (the paper landed March 2026, this repo days later), and the community's standing objection to every CFG demo applies here - one nicer image can just be luckier RNG. Test on a fixed seed across a handful of generations before you declare it a win.

CategoryCFG-Ctrl

Inputs (6)

NameTypeDefaultDescription
modelMODEL
smc_lambdaFLOAT0.050–50Exponential decay coefficient λ of the sliding surface. Recommended by paper: 5.0 for FLUX / SD3 / Wan.
smc_kFLOAT0.100–1Switching gain K. With adaptive_scale ON this is a ratio of ||e_t||: K=0.1 means correction ≤ 10% of the error signal. Safe range: 0.05–0.3 for any model.
warmup_stepsINT20–50Steps at the start where NO CFG is applied (only cond prediction). SMC state initialises at the first active step.
adaptive_scaleBOOLEANtrueNormalise s_t by ||e_t|| before applying gain K. Makes K a dimensionless ratio — same value works across FLUX, SD3, SDXL, SD1.5, Pony and any other model. Disable to use the raw paper formulation (requires per-model K tuning).
max_correction_ratioFLOAT0.250–1Hard safety clamp: ||u_sw|| is limited to this fraction of ||e_t||. 0.25 = correction never exceeds 25% of the error signal. Set 0.0 to disable. Prevents runaway correction on any model.

Outputs (1)

NameTypeDescription
modelMODEL