Nodes/CRT-Nodes/Text Rows Crawl (CRT)
ComfyUI Node

Text Rows Crawl (CRT)

Walk a list one item per run with ComfyUI's own seed widget

By PGCRT·Created 2 years ago·Updated 6 days ago· 138
Text Rows Crawl (CRT)
    • selected_row
    text
    seed0

    Text Rows Crawl (CRT) answers a deceptively common question in ComfyUI: how do I process a whole list of things, one per run, without building twenty copies of the same subgraph? Its answer is to let the seed do the work. You paste a multiline block of text, and the node picks exactly one row, where the row is chosen as seed % number_of_rows. Change the seed, change the row.

    This is the "crawl" pattern, and CRT-Nodes uses it everywhere - Image Loader Crawl, Text Loader Crawl, the batch variants - because it's the neatest way to iterate without a batch loop. For the text version, the obvious use is a list of JSON Q/A pairs: feed them in, and each run of your workflow processes a different pair, then hands it to Extract Q/A (CRT) and onward through the LLM pipeline. It also does boring jobs like cycling through a list of prompts, style tags, or LoRA names.

    Only two inputs, and one is the point:

    • text - the multiline block. Rows are split on line breaks, stripped, and blank lines dropped entirely, so a trailing newline doesn't create an empty phantom row.
    • seed - an INT with control_after_generate wired in, which is where the magic lives. Because the selected row is seed % row_count, a huge seed still lands safely in range; you're never dealing with an index-out-of-bounds.

    The single output, selected_row, is the text of that one row, ready to feed any string input downstream.

    Here's the part that trips people up, and it's the exact trap the ComfyUI community keeps hitting with seed widgets: control_after_generate fires after the run. The four settings - fixed, increment, decrement, randomize - decide what the seed becomes when the run finishes, so the number you see in the box is the row used next, not the one that just ran. If you set it to increment to walk through your list one row at a time, the box ticking up by one after each run is correct behavior, and the first row you actually see is the one after your starting seed. There's a global setting, "widget control mode," that switches this to fire before the run so the number in the box is the one used - worth changing once if you want to reason directly about what's about to execute. randomize is the lazy man's "shuffle through the list," and fixed plus a manual seed is the precise picker.

    Two small behaviors to know about, both visible in the source:

    • The node guards against a NaN seed. That can appear after a frontend refresh when a huge seed overflowed JS's safe integer range - the node just falls back to 0 rather than crashing. If your crawl suddenly always returns the first row after a refresh, this is why.
    • Empty input prints a [WARN] to the console and returns "". It won't error out your graph, but an empty string flowing downstream can silently corrupt a prompt, so check your text box.

    Installation is just the pack:

    cd ComfyUI/custom_nodes
    git clone https://github.com/PGCRT/CRT-Nodes
    

    then restart ComfyUI, or search "CRT-Nodes" in ComfyUI Manager. This node is pure stdlib - no imports beyond what Python ships with - so ignore the pack's heavy requirements.txt if the text nodes are all you want; it exists for the audio and model nodes.

    It's a tiny node with one trick, but the trick composes. Combine it with the seed widget you already understand, and you've turned "iterate over a list one item per run" into a solved problem instead of a copy-paste exercise. That's a fair trade for a utility you'll reach for more than you expect.

    CategoryCRT/Text

    Inputs (2)

    NameTypeDefaultDescription
    textSTRINGMultiline text to select a row from.
    seedINT00–18446744073709550000Selects the row as seed % number_of_rows. Use ComfyUI's seed control (fixed / increment / decrement / randomize) to crawl.

    Outputs (1)

    NameTypeDescription
    selected_rowSTRING