LoRA Stack Auto Triggers
Forget the trigger words — this LoRA stack fetches them for you
- lora_stack
- LORA_STACK
- LORA_PROMPT
- LORA_MetaData
The one-line pitch
Every LoRA user has the same story: you download a character or style LoRA, crank the weight, run, and get nothing - because you forgot the trigger word. This node kills that loop. Pick a LoRA from its dropdown and it looks up the trigger words, from Civitai by file hash and from the safetensors training metadata, then puts the ones you want straight into the prompt. Oh, and it's also a perfectly usable four-slot LoRA stacker.
It's a merged build rather than original work, and the README says so plainly: the stacking half comes from jakechai/ComfyUI-JakeUpgrade's CR_LoRAStack_JK, and the trigger extraction is a port of idrirap/ComfyUI-Lora-Auto-Trigger-Words (itself a fork of Extraltodeus/LoadLoraWithTags). The author wrote the code fresh and did improve things along the way - request timeouts, atomic cache writes, no crash when the hash is missing. But set expectations: this is a small hobby pack with zero community footprint, not an rgthree-scale institution. The idea is genuinely handy; the reputation just isn't there yet.
How it works
Each of the four slots has a LoRA dropdown and a trigger-preview box that fills itself - no Run button required. When you select a LoRA, frontend JS calls a backend route the plugin registers (/lorastack/trigger_words), and the backend does two lookups:
- Civitai: hashes the whole file (SHA256) and hits
civitai.com/api/v1/model-versions/by-hash/<hash>for thetrainedWordslist. No API key. - safetensors metadata: reads
__metadata__from the file header, parsesss_tag_frequency, and sorts the tags by how often they appeared in training.
The two merge, Civitai first, deduped, and every tag is labelled in the preview with its source (civitai vs meta). Results are cached in loras_tags.json inside the plugin folder, so the network only happens on first use - or whenever you flip force_fetch.
The inputs that matter
You'll set a handful of these and forget the rest:
trigger_selector(per slot) - slice syntax for which tags go in the prompt. Default:means all of them;0, 3grabs specific ones,5:8a range,-1the last,-8:everything from the eighth-to-last on. The preview's[selected]line updates live as you type.trigger_weight(per slot) - anything other than1.0wraps the selected tags as(tag:weight).model_weightandclip_weight- independent, which is the real upgrade over older stackers:clip_weight = 0no longer disables the LoRA, it just means "no text-encoder effect." Both at zero and the slot is skipped.fallback_to_filename- when no trigger words are found, the node outputs<lora:name:weight>so the LoRA still applies. Turn it off and a wordless LoRA silently drops out of the prompt.
The three outputs are the standard stacker trio: LORA_STACK (triples for an Apply-style node), LORA_PROMPT (trigger words ready to drop into a CLIP Text Encode), and LORA_MetaData (names, plus the first 12 chars of the hash if you tick save_hash). Optional lora_stack / lora_prompt / lora_metadata inputs let you chain several nodes when four slots isn't enough.
Installing it
ComfyUI Manager, search the pack title - or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/opaiopaio/ComfyUI-LoRAStackAutoTriggers
Then restart ComfyUI. The only dependency is requests, which ComfyUI almost always ships already, and there are no model downloads or heavy extras. It's about as lightweight as a custom node gets.
Where people get burned
- First fetch needs the network. No connection, no tags. And because it's whole-file SHA256, a pruned or re-uploaded LoRA hashes differently from the version on Civitai and won't match - a limitation the author calls out directly. You still get training-metadata tags when the file has them, and the filename fallback when it doesn't.
- The stack needs a matching Apply node. This pack ships only this one node, and
LORA_STACKis a custom type - a plain LoraLoader won't accept it. Pair the output with an Apply-LoRA-Stack-style node from a compatible pack. - The cache is sticky. Once a LoRA's tags land in
loras_tags.json, they don't refresh on their own; flipforce_fetchwhen a model page updates.
Honest sizing: if you already run rgthree's Power Lora Loader, which has read trigger words off files and fetched them from Civitai for ages, this is a sideways move rather than an upgrade. Where it wins is the live, pre-run preview and visible prompt injection. If you stack LoRAs daily and hate juggling trigger words, that's worth the install.
Inputs (34)
| Name | Type | Default | Description |
|---|---|---|---|
| lora_1 | BOOLEAN | false | Enable/disable LoRA 1 |
| lora_name_1 | COMBO | Select LoRA model 1 | |
| model_weight_1 | FLOAT | 1.00-10–10 | Model (U-Net) weight for LoRA 1; 0 = no model effect |
| clip_weight_1 | FLOAT | 1.00-10–10 | CLIP (text encoder) weight for LoRA 1; 0 = no CLIP effect (model still applies) |
| trigger_selector_1 | STRING | : | Trigger selector 1. ATW slice syntax: 0, 3, 5:8, -8:, : (empty part = open end, : = all) |
| trigger_weight_1 | FLOAT | 1.00-10–10 | Trigger word weight 1 (1.0 = no wrapping) |
| trigger_preview_1 | STRING | Trigger preview 1 (auto-filled by UI) | |
| lora_2 | BOOLEAN | false | Enable/disable LoRA 2 |
| lora_name_2 | COMBO | Select LoRA model 2 | |
| model_weight_2 | FLOAT | 1.00-10–10 | Model (U-Net) weight for LoRA 2; 0 = no model effect |
| clip_weight_2 | FLOAT | 1.00-10–10 | CLIP (text encoder) weight for LoRA 2; 0 = no CLIP effect (model still applies) |
| trigger_selector_2 | STRING | : | Trigger selector 2. ATW slice syntax: 0, 3, 5:8, -8:, : (empty part = open end, : = all) |
| trigger_weight_2 | FLOAT | 1.00-10–10 | Trigger word weight 2 (1.0 = no wrapping) |
| trigger_preview_2 | STRING | Trigger preview 2 (auto-filled by UI) | |
| lora_3 | BOOLEAN | false | Enable/disable LoRA 3 |
| lora_name_3 | COMBO | Select LoRA model 3 | |
| model_weight_3 | FLOAT | 1.00-10–10 | Model (U-Net) weight for LoRA 3; 0 = no model effect |
| clip_weight_3 | FLOAT | 1.00-10–10 | CLIP (text encoder) weight for LoRA 3; 0 = no CLIP effect (model still applies) |
| trigger_selector_3 | STRING | : | Trigger selector 3. ATW slice syntax: 0, 3, 5:8, -8:, : (empty part = open end, : = all) |
| trigger_weight_3 | FLOAT | 1.00-10–10 | Trigger word weight 3 (1.0 = no wrapping) |
| trigger_preview_3 | STRING | Trigger preview 3 (auto-filled by UI) | |
| lora_4 | BOOLEAN | false | Enable/disable LoRA 4 |
| lora_name_4 | COMBO | Select LoRA model 4 | |
| model_weight_4 | FLOAT | 1.00-10–10 | Model (U-Net) weight for LoRA 4; 0 = no model effect |
| clip_weight_4 | FLOAT | 1.00-10–10 | CLIP (text encoder) weight for LoRA 4; 0 = no CLIP effect (model still applies) |
| trigger_selector_4 | STRING | : | Trigger selector 4. ATW slice syntax: 0, 3, 5:8, -8:, : (empty part = open end, : = all) |
| trigger_weight_4 | FLOAT | 1.00-10–10 | Trigger word weight 4 (1.0 = no wrapping) |
| trigger_preview_4 | STRING | Trigger preview 4 (auto-filled by UI) | |
| save_hash | BOOLEAN | false | Include SHA256[:12] in metadata |
| force_fetch | BOOLEAN | false | Force re-fetch from civitai |
| fallback_to_filename | BOOLEAN | true | No trigger words found -> output <lora:name:weight> as fallback; OFF -> skip that lora from the prompt |
| lora_stackopt | LORA_STACK | Existing LoRA stack to extend (chain more nodes here) | |
| lora_promptopt | STRING | Existing LoRA prompt to extend | |
| lora_metadataopt | STRING | Existing LoRA metadata to extend |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| LORA_STACK | LORA_STACK | — |
| LORA_PROMPT | STRING | — |
| LORA_MetaData | STRING | — |