Extensions/Breeze
ComfyUI Extension

Breeze

Frontend extensions that make a ComfyUI graph easier to read and work in. They draw over the canvas; the workflow that runs is never changed.

By pytraveler·Created about 21 hours ago·Updated about 19 hours ago· 0
pytraveler/ComfyUI-Breeze
Nodes—
On cloudLocal install
Stars0
Updatedabout 19 hours ago
Readme

Breeze for ComfyUI

Frontend extensions that make a ComfyUI graph easier to read and to work in. They answer the questions a graph raises while you look at it: what feeds this node, what this wire carries, where the nodes went when the screen is empty, what the next run will compute again.

Russian version | Changelog

<p align="center"> <a href="LICENSE"><img alt="License: Apache-2.0" src="https://img.shields.io/badge/License-Apache--2.0-blue"></a> <img alt="Python 3.10+" src="https://img.shields.io/badge/Python-3.10%2B-3776AB?logo=python&logoColor=white"> </p>

A ComfyUI graph in Russian with KSampler selected. ModelSamplingAuraFlow and two CLIP Text Encode prompts, which feed it, are outlined in blue with a soft blue glow; VAE Decode, which it feeds, in amber. The pointer rests on the MODEL wire into KSampler: two violet arrows stand on the wire, one back up towards ModelSamplingAuraFlow and one ahead towards KSampler, and the tooltip reads MODEL, ModelSamplingAuraFlow #69 MODEL, to KSampler #70 model. On the right the blue IMAGE wires from VAE Decode run as one trunk to a small dot and split there

KSampler is selected: what feeds it is outlined in blue, what it feeds in amber. The pointer rests on a wire, which names its ends and shows the two arrows that carry the view to them. On the right, one output's wires share a trunk.

What it does

  • What feeds a node, and what it feeds. Select a node and everything it depends on is outlined in blue, everything that depends on it in amber, each with a soft glow of its colour, and the rest of the graph fades, wires and prompt boxes included. Select several and they light up together; a node between two of them is outlined in violet. Frontend reroutes and Reroute nodes are followed like any other link.
  • What a wire is. Rest the pointer on a wire for a moment and a tooltip names its type, the output it leaves and the inputs it reaches, and what went along it in the last run: 1x1536x1024x3 float32 for an image, the head of the text for a string, latent 1x16x128x128 float32, ModelPatcher: Flux. Where wires overlap, each one is described.
  • Where a wire leads. Two arrows in the wire's colour appear on the wire beside the resting pointer, one pointing back along it to the output it leaves, one ahead to the input it reaches, and a click on one carries the view there, slowly enough to follow. They stand wherever the pointer is, so a wire too long to see either end of can be followed from the middle; when several of the wires under the pointer leave one output, the arrow ahead frames every input they reach. Where the view lands, the node flashes in the wire's colour, twice, and fades. Zoomed in, the arrows grow with the wire. The wire itself stays drawn.
  • One trunk for a fan of wires. Wires that leave one output for inputs standing in a column, a CLIP into both prompts or a VAE into several decoders, run as one trunk that splits just before the column, at a small dot, instead of each crossing the graph on its own. It is drawn as a reroute in front of the column would draw it, in every link render mode, but nothing is added to the graph: the links stay as they are. A click, the tooltip and the arrows find the trunk like any wire, and the arrow ahead on it frames every input it splits to. A wire through a reroute of yours keeps its own line.
  • What the next run computes again. Rest the pointer on Run and every node the run needs is outlined: green where its result comes from the cache, orange where it is computed again, yellow where it is computed on every run, dashed orange where only a lazy input asks for it, which the node may or may not do. Above each node computed again stands the time it took the last time it was computed, and a note under the button sums it up: computed again 2, from the cache 3, about 40 s. The answer comes from ComfyUI's own cache, so a run from another tab, an entry the cache let go and a seed that changes after every run all count. Under Settings > Breeze > Forecast the marks can stay on the nodes all the time instead, renewed after every edit and every run.

The forecast with the pointer resting on Run, in a YuE2 workflow with ComfyUI in Russian. Write the song, whose badge says it took 18.85 s last time, and The score it sang are outlined in green: both come from the cache. The song, a SaveAudioAdvanced node whose format has just been switched to mp3, is outlined in orange, with a tag beside its badges saying it took under a second. The note under the Run button reads Next run: computed again 1, from the cache 2, under a second

Only the format of the save node has changed, so the next run saves the song again and takes the 19 seconds of singing from the cache.

Each can be switched off under Settings > Breeze, which is also where the fade, the glow's radius and the three outline colours are set; a radius of 0 turns the glow off. A colour given in eight hex digits carries an alpha as well. With ComfyUI set to Russian the settings and the tooltip are in Russian; in any other language they read in English.

Next on the list: a compass to the nodes off screen.

Where the values on a wire come from

ComfyUI tells the browser about a node's result only when the node displays it. For everything else the pack's server side writes a line about each output while the prompt runs -- the shape and dtype of a tensor, the head of a string, a number -- and keeps that line, never the value, under the workflow the prompt was queued from. Nodes taken from the cache are described too, so a run in which nothing had to be computed again still fills every wire in.

The tooltip asks the server for those lines, so they survive a reload of the page and show in every tab with the same workflow open; they last until ComfyUI restarts. A line is shown only while the node it describes is still of the same type, and only on the top level of a workflow: inside a subgraph the tooltip gives the type and the ends, not yet the value. A prompt queued through the HTTP API carries no workflow and leaves nothing behind.

To read the outputs the pack wraps PromptExecutor.execute_async, to learn which workflow is running, and three methods of ExecutionList, one of them to time each node. The originals run first and unchanged; a description that fails is dropped, never raised into the run. If an update of ComfyUI moves any of them, the pack wraps none, logs a warning at startup, and the tooltip shows no values and Run no forecast; everything else keeps working.

How the forecast is made

ComfyUI takes a node from its cache when the node's key is there: its class, its inputs, what its IS_CHANGED says, and the same for everything upstream. The browser cannot see that cache, so it sends the server the prompt Run would queue, and the server builds the keys for it the way a run does and looks them up in the cache the last run left. The prompt goes through what ComfyUI does to a queued prompt first, node replacements and validation, so a prompt ComfyUI would refuse gets the reason instead of a forecast. Handlers other packs register for queued prompts are not called.

The cache is only read. IS_CHANGED does run, as it does when a prompt is queued, so a LoadImage hashes its file; that happens on a thread of its own, one forecast at a time. The cache can still change before the prompt runs, which is why it is a forecast. The seconds are those of the node's last computation in the same workflow, and a node no run has computed yet has none.

Not yet supported

  • With "Modern Node Design (Nodes 2.0)" turned on under Settings > Comfy > Nodes 2.0, the lineage fades the wires but not the nodes, and the forecast marks no nodes; the note under Run still sums it up.
  • Inside a subgraph the forecast marks nothing; on the top level a subgraph's node takes the mark of what is inside it.
  • A trunk only forms for inputs ahead of the output, on the left of their nodes; wires that run backwards, or into inputs too close to the output to gain anything, are drawn as before.

How it changes a workflow

It does not. Everything is drawn over the canvas, and anything an extension has to remember is kept in the workflow's extra field. No node is added and no link is rewired, so a workflow saved with these extensions loads and runs the same without them. The principle is borrowed from Zip Ties.

Install

The pack is in the Comfy Registry as comfyui-breeze: find Breeze in ComfyUI-Manager's Custom Nodes Manager, or install it with comfy-cli:

comfy node install comfyui-breeze

Or clone the repository into ComfyUI's custom_nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/pytraveler/ComfyUI-Breeze

Either way, restart ComfyUI afterwards. The pack needs nothing beyond ComfyUI itself: no Python packages, no models.

Development

The suite runs without ComfyUI, torch or a browser:

python -m pip install pytest
python -m pytest tests -q

With Node.js 22 or later on PATH it also parses every script under web/js and runs the browser-free parts of them against tests/js; without Node those tests skip. CI installs Node and sets BREEZE_REQUIRE_NODE, so there they fail instead.

The suite also carries the house rules, so CI and the release archive enforce them as well:

  • ASCII only, outside the translations.
  • Both changelogs describe every release, and the version in pyproject.toml, the git tag and the GitHub release always agree. The release workflow refuses a tag that breaks either rule.

Licence

Apache-2.0. See LICENSE and NOTICE.md.