Extensions/scorpiov-nodes
ComfyUI Extension

scorpiov-nodes

A collection of ComfyUI nodes including an all-in-one wildcard processor with LoRA loading and aspect ratio node for image sizing.

By scorpiov·Created 3 months ago·Updated 7 days ago· 2
vikramudyawar/scorpiov-nodes
Nodes
On cloudLocal install
Stars2
Updated7 days ago
Readme

scorpiov-nodes

<img width="3523" height="1477" alt="workflow(1)" src="https://github.com/user-attachments/assets/1a45cb30-7633-44a3-a65e-d0c8af0acdbd" />

A collection of custom ComfyUI nodes I use in my own workflows — wildcard prompting, LoRA tag loading, Civitai-ready image saving with automatic metadata, graph-wide broadcast connections, and weighted prompt/conditioning merging.

Installation

  1. Download or clone this repo into ComfyUI/custom_nodes/scorpiov-nodes/
  2. Restart ComfyUI

No extra Python dependencies beyond what ComfyUI already ships with.

Nodes

| Node | Category | What it does | | ----------------------- | ---------------- | -------------------------------------------------------------------------------------------- | | Wildcard Processor 🎲 | Scorpiov/Prompt | Resolves wildcards + inline {a\|b\|c} groups, loads <lora:...> tags, outputs CONDITIONING | | Wildcard Prompter 📝 | Scorpiov/Prompt | Text-only version — no model/clip needed, just resolves wildcards to a string | | Lora Tag Loader 🏷️ | Scorpiov/Loaders | Reads <lora:name:weight> tags out of any text, loads them onto model/clip, strips the tags | | Width Height | Scorpiov/Latent | Aspect ratio picker for empty latents | | Image Meta Reader 🔍 | Scorpiov/Image | Reads A1111 and ComfyUI-native PNG metadata back out of an image | | Image Loader 🖼️ | Scorpiov/Image | Loads an image, also outputs its filename and full path | | Save Image 💾 | Scorpiov/Image | Saves images with full Civitai-compatible metadata, auto-detected from your workflow | | Scorpiov Anywhere 📡 | Scorpiov/Routing | Broadcasts a connection to every matching, unconnected input in the graph — no wires needed | | Prompt Combiner/Router 🔀 | Scorpiov/Routing | Merges multiple STRING and/or CONDITIONING inputs into one output each, with per-input weight and enable/disable |


Wildcard Processor 🎲

<img width="1050" height="728" alt="Screenshot 2026-07-31 214155" src="https://github.com/user-attachments/assets/0c4b9fa2-a349-40a1-811e-403151acd593" />

All-in-one wildcard processor with LoRA loading, serial/random modes, and prompt preview.

  • Put your wildcard .txt files into the wildcards/ folder in the node folder — any subfolder depth, just reference by filename with __filename__ (no path needed)
  • Supports inline {option_a|option_b|option_c} groups, including nested
  • Random or Serial selection mode; Serial remembers position and loops
  • Parses and loads <lora:name:weight> tags found in the resolved text directly onto the model/clip
  • Outputs CONDITIONING, MODEL, CLIP, and the resolved STRING
  • Comments are supported both in wildcard .txt files and typed directly into the node's own text box — see Comments below
  • A live 🎨 Highlighted Preview box sits under the text field, color-coding { } groups, ( ) weights, :weight numbers, and comments as you type — read-only, just a visual aidc

Wildcard Prompter 📝

<img width="1347" height="827" alt="image" src="https://github.com/user-attachments/assets/d56cb04b-f154-4961-9fad-cf498366fd85" />

Text-only variant of the Wildcard Processor — no model/clip inputs, no LoRA loading. Just resolves wildcards and outputs the string, so you can feed it into a Lora Tag Loader or CLIPTextEncode. Useful when you want to build your prompt text before deciding what to do with it. Same comment support and Highlighted Preview as the Wildcard Processor.

Comments

Both wildcard nodes, and the .txt files they load from wildcards/, support two comment styles:

  • # comment — everything from a # to the end of that line is dropped. Works on its own line, or trailing after real text (blonde hair # my favorite).
  • /* comment */ — block comments, C-style. Can span multiple lines, and the markers don't need to sit alone on their own line — /* this on one line and is a comment */ two lines later works exactly like you'd expect from any C-style comment.

Comments are stripped before wildcards or {a|b|c} groups are resolved, so they never reach the resolved prompt, Save Image, or embedded PNG metadata.

Lora Tag Loader 🏷️

<img width="1260" height="800" alt="Screenshot 2026-07-31 211411" src="https://github.com/user-attachments/assets/203cd9fb-9688-419d-9d63-e4c828ceef19" />

Reads <lora:name:weight> or <lora:name:weight:clip_weight> tags out of a text prompt (e.g. from Wildcard Prompter), loads each named LoRA onto the given model/clip, and strips the tags out of the text so it's safe to feed into a standard CLIPTextEncode node.

  • <lora:name:0.8> → same weight applied to both the model and CLIP
  • <lora:name:0.8:0.6> → separate model weight (0.8) and CLIP weight (0.6), matching how comfyui_lora_tag_loader handles it (Shoutout and thanks to badjeff for an amazing node).
  • Searches every folder registered under ComfyUI's loras path, matched by filename — subfolders in your LoRA library "just work," and a subfolder prefix inside the tag itself (e.g. <lora:MyFolder\mylora:0.8>) is handled too
  • Outputs: model, clip, text (tags stripped, ready for CLIPTextEncode), and loras_info — a formatted string with each LoRA's name, weight, and content hash, meant to be wired straight into Save Image's loras input for Civitai-compatible metadata

Typical chain: Wildcard PrompterLora Tag Loader → two CLIPTextEncode nodes (positive/negative) → KSampler, with loras_info also wired to Save Image.

Width Height

<img width="1189" height="646" alt="workflow(4)" src="https://github.com/user-attachments/assets/3a13e3a2-5feb-4fe0-80fa-2d6ac39b7713" />

Aspect Ratio Node, set width/height for empty latents or choose from a list

  • Add to the list by updating the ratios.txt file in the node folder
    • Eg: My Custom Ratio (2:1) | 2048 | 1024

Image Meta Reader 🔍

<img width="2213" height="1326" alt="workflow(5)" src="https://github.com/user-attachments/assets/b919038d-1ce0-4813-a9ca-802f8687d917" />

Reads PNG metadata in both A1111 and ComfyUI-native JSON formats — model, VAE, LoRAs, prompts, and the full raw metadata — into a single scrollable textarea. Has a "Read Metadata Now" button so you can inspect an image without running the whole workflow.

Image Loader 🖼️

<img width="1808" height="786" alt="Screenshot 2026-07-19 132754" src="https://github.com/user-attachments/assets/f9f223ce-6997-4b8c-88c6-625b38b445a1" />

Loads an image and outputs the tensor, the bare filename, and the full file path — handy when a downstream node needs to know exactly which file it's working with.

Save Image 💾

<img width="581" height="798" alt="Screenshot 2026-07-31 211015" src="https://github.com/user-attachments/assets/83ec6dc6-711c-4b0d-b6c5-1fe399c08f52" />

Saves images with full A1111/Civitai-compatible metadata embedded in the PNG.

  • Required wires: images, positive_prompt, negative_prompt
  • loras is also a wire-only input (no typed-text fallback) — connect it from Lora Tag Loader's loras_info output, or Image Meta Reader's loras output. Leave it unconnected to skip LoRA metadata entirely.
  • Everything else is auto-detected from your workflow graph — steps, CFG, sampler, scheduler, seed, checkpoint name, and VAE name are all read automatically. Typing a value into any of those fields overrides the auto-detected one.
  • ⚙ Advanced Settings collapses model_name, vae_name, steps, cfg, sampler_name, and scheduler behind a toggle button, collapsed by default, since these usually only matter when overriding auto-detection. seed, control_after_generate, save_metadata, and model_hash stay visible.
  • LoRA + Civitai badges: wire Lora Tag Loader's loras_info output into the loras input, and Save Image will embed the <lora:name:weight> tag and a proper Lora hashes: line so Civitai can recognize and badge the LoRAs used.
  • Model hash: the checkpoint file is automatically hashed (SHA256 → Civitai's "AutoV2" short hash) and embedded as Model hash:, same as the model_hash field can be typed manually to override.
  • Hashing is cached, keyed by file content (not filename or path), so a given checkpoint or LoRA is only ever hashed once — after that, saves reuse the cached hash instantly. The cache lives at scorpiov-nodes/.scorpiov_hash_cache.json; delete it any time to force a clean re-hash of everything.
  • filename_prefix supports subfolders via / and date tokens like %date:yyyy-MM-dd%

Scorpiov Anywhere 📡

<img width="1641" height="606" alt="image" src="https://github.com/user-attachments/assets/6819ceba-bf2d-4731-bd98-ae2144a0c92f" /> <img width="1336" height="611" alt="image" src="https://github.com/user-attachments/assets/d1f720c4-1abe-4a27-8cca-d63139eb7971" />

A broadcast/connector node — plug something in once, and it becomes available to every other matching, unconnected input in the graph, without drawing a wire to each one by hand. Inspired by cg-use-everywhere's "Anything Everywhere," rebuilt independently for reliability on newer Vue-based ComfyUI frontends. Shoutout and thanks to chrisgoringe

  • Dynamic inputs — connect one thing or ten; a fresh empty anything_N slot appears automatically as each one fills.
  • Auto-labeling — each connected slot is labeled from its source (MODEL, CLIP, VAE, ...) automatically, for readability.
  • Any-node broadcasting — right-click any node → "Add Scorpiov Broadcasting" to broadcast its outputs directly, without routing through a dedicated node.
  • Type + name matching with priority — an unconnected input is filled by the best-scoring match (exact name match beats type-only match). Genuine ties — e.g. two same-typed sources with nothing to disambiguate them (two CONDITIONING outputs, or several STRING fields) — are skipped and logged rather than guessed.
  • Manual disambiguation — right-click any input dot on a Scorpiov Anywhere node → "Rename for Scorpiov matching..." to give it a specific name (e.g. positive / negative) so it matches the right target when more than one source shares a type. This persists with the saved workflow.
  • Cycle-safe — before accepting a match, the engine checks whether it would create a dependency loop through the graph's existing connections, and skips it (with a log message) rather than producing an unrunnable prompt.
  • Selection-based wire visualizer — select a Scorpiov Anywhere (or broadcast-flagged) node to see faint dashed lines to everything it feeds; select any fed node to see a line back to its broadcaster. Nothing is drawn unless something is selected.
  • Resolves entirely at prompt-submission time by rewriting the serialized graph before it's sent for execution — the node itself never reaches the backend, so there's no runtime cost, but it also means broadcast connections never appear as real wires on the canvas. Use the visualizer, or check the browser console for skipped-match warnings, to confirm what actually got connected.

Prompt Combiner/Router 🔀

Merges multiple STRING and/or CONDITIONING inputs into one merged STRING output and one merged CONDITIONING output, with per-input weight and enabled/disabled control. Sits naturally between Wildcard Prompter and Lora Tag Loader when plain concatenation isn't giving you enough control over how prompt fragments combine.

  • Dynamic inputs — same anything_N growth pattern as Scorpiov Anywhere; wire in as many STRING and/or CONDITIONING sources as you want, in any mix.
  • Auto-routing by type — no need to tell it what's connected. STRING inputs feed merged_string, CONDITIONING inputs feed merged_conditioning, automatically, per connection.
  • Per-input weight and enable/disable — right-click any connected slot → "Set weight..." or "Enable/Disable this input". Settings persist with the saved workflow.
    • For STRING inputs, weight is expressed using ComfyUI's own prompt-emphasis syntax ((fragment:0.60)), so it directly affects generation strength through a standard CLIPTextEncode — text itself has no numeric "blend," so this is how weight actually does something for the STRING path.
    • For CONDITIONING inputs, weight drives a genuine weighted average across every connected input's tensor and pooled_output (matching how ComfyUI's own ConditioningAverage node treats its strength parameter, generalized here to N inputs instead of 2).
  • separator controls how merged STRING fragments are joined (default , ).

A note on merged_conditioning: averaging conditioning tensors works well for gently nudging between similar prompts, but has a real ceiling for very different scenes — at equal weight, one prompt's content can dominate almost entirely, with barely a trace of the other. This is confirmed against ComfyUI's own built-in ConditioningAverage node behaving identically, not a limitation specific to this node. For blending two very different scenes, merging as STRING and running the combined text through a single CLIPTextEncode is usually the more reliable route to an actual blend.

Typical chain: Wildcard PrompterCombiner/RouterLora Tag LoaderCLIPTextEncode.


Notes

  • All LoRA-aware nodes search every folder registered under ComfyUI's loras path — you don't need to configure anything, just drop LoRA files anywhere under your usual loras directory (subfolders included).
  • Metadata written by Save Image is readable by Automatic1111, Civitai, and this package's own Image Meta Reader.
  • Built and tested against ComfyUI's newer Vue-based frontend. If you're on the older classic frontend, the JS-side UI extras (Highlighted Preview, Advanced Settings toggle, Scorpiov Anywhere's visualizer and rename menu) should still work, but haven't been explicitly tested there.
  • Scorpiov Anywhere's Image Meta Reader compatibility: since broadcast connections aren't real graph wires, Image Meta Reader's graph-walking (which follows real links) currently won't see prompts/LoRAs delivered via a broadcast — wire those directly if you need them to show up in embedded metadata.