TrainyThing Review
Swipe your batch on your phone, then let the graph carry on
- images
- latent
- images_b
- accepted
- rejected
- accepted_latent
- images
- labels
- summary
- notes
- accepted_meta
- accepted_indices
- link
- slug
What it is
TrainyThing Review is the flagship of this pack: wire it after VAE Decode, press Queue, and the batch becomes a review queue on your phone. A link and QR appear on the node, the run waits, you swipe each image keep-or-reject with a note on why, and the graph carries on - keepers on one socket, rejects on another, reasons attached as text.
Why use it instead of clicking keepers on the canvas? Because you'd rather review away from the desk; because a note on why you rejected something beats "meh"; or because someone else is picking and you want names on the verdicts. If none of that applies, an on-canvas chooser like cg-image-picker is simpler.
It's an output node, so it runs with nothing wired downstream. The pack is brand new (v0.2.0, barely a Reddit thread to its name), so everything below comes from the source, not folklore.
How it works
Review is TrainyThing Send and TrainyThing Wait welded together: each image becomes a card, the PNGs go to a local daemon, the node polls /status while the reviewer works, then splits the batch you still have in memory. That's the point of the combined node - the batch and its latent stay resident across the wait, so accepted_latent needs no re-encoding.
The uploaded PNGs carry the prompt and workflow chunks Save Image would have written, unless ComfyUI runs with --disable-metadata. The node also walks your graph backwards from images - VAE Decode, sampler, text encoders, LoRA loaders, checkpoint - and attaches what it found to each card. That's how a keeper's seed and prompt come back to you.
Connection details are deliberately not widgets - TRAINYTHING_URL/TRAINYTHING_TOKEN, then ~/.trainything/config.json, then 127.0.0.1:4747. No token field, on purpose: ComfyUI writes widget values into every PNG and shared workflow, so a token in a node leaks with the first image.
The inputs that matter
A fresh node shows five - images, title, prompt, mode, public. The rest is folded behind a more settings switch, which unfolds itself if a loaded workflow changed one of them.
images- any batch size, one card per image.mode-single(keep or reject),pair(A vs B, wireimages_b),choose(pick one of youroptions),select(tick any).public- off, the link only works on that machine. On, the daemon opens a tunnel (fetchingcloudflaredon first use) so your phone off the home Wi-Fi can reach it; if it fails you get a console line and the local link.min_reviews- how many people must judge each card before the queue is done. Set 2+ and ties becomecontested, which is in neither set - that's what Filter's rule is for.feedback/identity- when a reason is demanded (on_reject,optional,required,off), and whether reviewers leave a name and email.timeout_minutes(45) andon_timeout-partialgoes on with what got judged,blockstops the run. The queue stays open either way.
Optional: latent (needed for accepted_latent), images_b (pair mode), labels (a caption per card), meta (your own JSON, which overrides the graph walk), and slug - empty derives one from the title, random makes an unguessable one.
The outputs
accepted and rejected are the obvious two. images plus labels is the pair you wire into TrainyThing Filter when you need a rule more interesting than keep/reject. summary into any preview-text node is the fastest way to read the reasons, and notes is the bare list of them. accepted_meta is JSON with each keeper's seed, position, prompt, checkpoint, LoRAs and sampler settings; accepted_indices is an INT list, so a downstream node runs once per keeper. link and slug are for you and for Load.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/ryanrinkel/comfyui-trainything
cd comfyui-trainything
python -m pip install -r requirements.txt # ComfyUI's own python, or python_embeded\python.exe
# restart ComfyUI, then once:
npx -y trainything dashboard
Or Manager → search "TrainyThing" (comfy node install trainything). The Python side is tiny - segno, pillow, numpy, no models - but the daemon needs Node ≥ 22.5 and the pack wants ComfyUI ≥ 0.39.0 for its V3 node API. You can test it with no checkpoint: copy tests/fixtures/sprites/*.png into ComfyUI's input/, drag examples/gate.json onto the canvas, press Run.
Where people get burned
It holds ComfyUI's whole queue - nothing else runs while you're swiping. Inherent to any on-canvas chooser, and the reason Send-then-Load exists.
ComfyUI caches an unchanged Review. The same graph with the same inputs is skipped - those images are already on the phone. Change a seed if you want a fresh send.
accepted_latent is always blocked in pair mode - the wired latent is the A side's, and a winning B has none. VAE Encode accepted.
In choose and select, accepted and rejected are empty on purpose - those modes produce a tally, not a binary. Get the images with TrainyThing Filter, rule option.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | The pictures to review. Each one becomes a card on the phone. | |
| title | STRING | ComfyUI batch | A name for this batch. Shown at the top of the phone page and on the dashboard. |
| prompt | STRING | Keep this one? | The question written on every card, e.g. Keep this one? |
| mode | COMBO | single | How the reviewer answers. single: keep or reject each picture. pair: pick A or B (wire the B pictures into images_b). choose: pick one of your options per picture. select: tick any of your options per picture. |
| public | BOOLEAN | false | On: make a link that works away from this computer (your phone off the home Wi-Fi), through a tunnel. Off: the link only works on this machine. |
| slug | STRING | The short name in the link, like a folder name. Leave empty to make one from the title. Use the name of a batch that is still open to add these pictures to it. Type random for a name nobody can guess. | |
| intro | STRING | A short message the reviewer reads before the first card. Leave empty for an automatic one that quotes your positive prompt and says what to do. | |
| options | STRING | Only for choose and select: the buttons the reviewer sees, as id:Label pairs separated by commas, e.g. hair:Hair colour, hands:Hands, ok:Fine. An id is lowercase letters, digits, - or _. Ignored in single and pair. | |
| feedback | COMBO | on_reject | When the reviewer is asked to type a reason. on_reject: only when they reject (single mode; a note box on every card in the other modes). optional: a note box on every card. required: they must write something. off: never. |
| identity | COMBO | name_email | name_email: the phone asks for a name and email before the first card, so you know who said what. anonymous: it asks nothing. |
| order | COMBO | coverage | The order the cards are shown in. coverage: the pictures with the fewest reviews first, so several reviewers spread out. fixed: the batch order. |
| min_reviews | INT | 11–50 | How many people must judge each picture before the batch counts as done. 1 when it is just you. |
| project | STRING | comfyui | A tag that groups batches on the dashboard. |
| timeout_minutes | FLOAT | 45.00.1–10080 | How long to wait for the phone before the run moves on. The batch stays open on the dashboard either way. |
| on_timeout | COMBO | partial | What happens when the time runs out. partial: carry on with what was judged, the rest counts as unjudged. block: stop here; nothing after this node runs. |
| latentopt | LATENT | Optional: the latent from the KSampler that made these pictures. accepted_latent then carries the keepers' latents to a next step. | |
| images_bopt | IMAGE | pair mode only: the B pictures, one for each A picture, same count. | |
| labelsopt | STRING | Optional: a caption above each card. One line per picture, in batch order. | |
| metaopt | STRING | Optional: extra details to attach to every card as JSON, e.g. {"lora": "witch-v2"}. One object for all pictures, or one per line. It comes back with the verdicts and overrides what the node reads from the graph. |
Outputs (11)
| Name | Type | Description |
|---|---|---|
| accepted | IMAGE | The pictures the reviewer kept. |
| rejected | IMAGE | The pictures the reviewer rejected. |
| accepted_latent | LATENT | The keepers' latents, cut from the latent you wired in. Nothing flows here if no latent was wired. |
| images | IMAGE | All the pictures, unchanged, in batch order. Wire with labels into TrainyThing Filter. |
| labels | STRING | One line per picture: its verdict, the votes and the notes. Made for TrainyThing Filter. |
| summary | STRING | A short readable report: how many were kept, rejected or contested, and the notes. Wire to a Preview Any node. |
| notes | STRING | The reasons the reviewer typed, one per line, with the picture each one was about. |
| accepted_meta | STRING | For each keeper: its seed, batch position, prompt, checkpoint, LoRAs and sampler settings, as JSON. For reproducing or refining. |
| accepted_indices | INT | The batch positions of the keepers, counting from 0. |
| link | STRING | The review link the phone was sent to. |
| slug | STRING | This batch's short name, for TrainyThing Load in a later run. |