- pipe_a
- opt_pipe_b
- STRING
Every convenience abstraction in ComfyUI makes the same trade. You bundle eight wires into one and the graph becomes readable - and the moment something's wrong, you can no longer see anything. CMK's pipes are exactly this: CMK_PIPE, CMK_MODEL_PIPE, CMK_DETAILER_PIPE and friends hide a dict full of tensors behind one socket.
CMK Pipe Inspect is the node that cracks the box open. It takes one pipe, or two, and prints you a table: what keys are inside, what type each value is, what shape it has, and - this is the useful part - which keys differ between two pipes.
Inputs
pipe_a- required, wildcard socket.label_a,label_b- strings to name the two sides. DefaultAandB, which is exactly as exciting as it sounds.opt_pipe_b- optional; the second pipe to compare against.
That wildcard on pipe_a is worth a note, because it's the pack being pragmatic at the cost of some politeness. A comment in the source spells out the reasoning: ComfyUI's frontend only supports exact type matching, so a Python-side pseudo-union of all the CMK pipe types would produce a socket you can't actually connect anything to. So CMK Pipe Inspect declares *, accepts anything, and validates at runtime. The practical consequence is that you can plug a CMK_PIPE, a CMK_PROCESS_SDXL, a CMK_FACE_PIPE - any of them - into the same node.
It will also let you plug in something that isn't a pipe at all. It just won't do anything useful with it: a non-dict gets reported as not a CMK pipe dict with its type name, and that's your answer.
Outputs and what you get
One output, STRING - the full report as text, so you can feed it to a note node, a save-text node, or CMK Summary-style consumers. The node is marked OUTPUT_NODE, so it always executes.
Alongside the text, it renders a summary panel as a PNG and pushes it into ComfyUI's ui.images, which means you get a readable visual table in the node's preview area, not just a wall of monospace. For each pipe you get the key count, an identified image_source, a curated table of the interesting keys with type and shape, and then a complete alphabetical all_keys listing.
With two pipes connected, you get both summaries plus a comparison block: keys only in A, keys only in B, and a different row listing every common key whose value changed. Values are compared by identity first (a is b), then by type name, shape and a 48-character preview - so it catches a swapped tensor without dumping a megabyte of floats at you, and it won't cry wolf over two distinct objects holding equal data.
What it's for
Diagnosing "why is my module producing garbage" in three specific shapes:
- A key is missing. Compare a pipe from a working workflow against one from yours.
only A/only Bnames the offender immediately. - A value is the wrong shape. A
LATENTthat should carry[1, 4, 128, 128]and carries something else tells you the problem is upstream of the sampler, not in it. - Two branches diverged. Place an Inspect after each parallel branch and diff. The CMK branch-cache machinery is built around dependency manifests, and inspecting is how you find out which manifest entry actually changed.
Cost: essentially nothing. It's dict walking and one PNG render.
Install
Part of CMKFlow/cmk_nodes. ComfyUI Manager → search CMK Flow → install the CMKFlow entry → restart. Manual, ComfyUI closed:
git clone https://github.com/CMKFlow/cmk_nodes.git custom_nodes/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py
CMK dependency check: OK or the install didn't finish.
Notes and traps
It's a diagnostics node in a Developer category (CMK/Developer/Diagnostics). Not something you leave in the finished workflow - it forces execution and writes preview PNGs. Strip it before you share, or you'll be adding CMK_pipe_inspect files to your output folder forever.
Passing a value that isn't a dict throws a type error, not a warning: "PROCESS PIPE A must be a CMK process/function pipe dictionary." That message is oddly literal, since the socket says *. It's the runtime validation catching what the socket can't.
Nothing here substitutes for reading the source. When the pipe contents surprise you, the pack's ARCHITECTURE.md is the contract document that says what should be in each pipe - and the node's output is the fastest way to find out where reality diverged from it.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| pipe_a | * | — | |
| label_a | STRING | A | — |
| label_b | STRING | B | — |
| opt_pipe_bopt | * | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |