MoonLoRA Loader
LoRAs and their trigger words, kept together so they never drift
- model
- clip
- MODEL
- CLIP
- trigger_text
A LoRA is only half a tool. The other half is its trigger phrase - the token you trained it on (or the one the author tells you to use), the thing you have to type into the prompt or the LoRA does close to nothing. Run more than one LoRA and you're juggling a handful of LoraLoader nodes and a prompt string that has to stay in sync with all of them. Forget one phrase and your output quietly degrades, and nothing tells you why.
MoonLoRA Loader is the node that makes that impossible to do wrong. Every row on the node carries a LoRA and the trigger text that belongs with it - the two physically live in the same row, so they can't drift apart. Toggle a row off and both the LoRA and its words disappear from the output together.
How it works
The rows are frontend widgets; the backend resolves each row's filename against your loras folder and then calls the stock ComfyUI LoraLoader under the hood - same code path as the built-in node, so behavior is what you already know. The filename lookup is forgiving in the right way: exact match first, then case-insensitive, then basename, so a LoRA you moved between subfolders still resolves. If a file is genuinely gone, the row is skipped with a warning and its trigger text is dropped too - you never get prompt words for a LoRA that wasn't applied, which is a nicer failure than the alternative.
Trigger texts of the enabled rows get joined with the separator (default ". ") and handed out on the trigger_text output, ready to wire into your positive prompt.
The inputs that matter
model- required. This is the MODEL output of your checkpoint loader.separator- what goes between trigger texts, verbatim.". "default is fine.clip- optional. Leave it unconnected for a model-only patch (the node warns and applies model strengths only).trigger_text- an optional string input that's always prepended, in case you want text from elsewhere in the graph.
Outputs: patched MODEL, patched CLIP, and trigger_text (STRING).
The details that make it worth it
Row order is both the application order and the concatenation order - reorder with the right-click menu and both follow. There's a Show Strengths property that switches between one strength per row and separate model/clip strengths. And one behavior to know about: a row set to strength 0 is a no-op on the model but still emits its trigger text - the author reasoned that if you asked for the words, you get the words. It's a judgment call, and now it's yours.
The honest trade-off
Everything is local. There's no Civitai lookup and no trigger-word scraping - the text is whatever you type, stored in the workflow. So the first time you add a LoRA you still have to know (or find) its trigger phrase yourself; that's a two-minute lookup, and it buys you never having to manage the two separately again.
Installing it
MoonLoRA Loader ships in MoonPack (comfyui-moonpack). Install via ComfyUI Manager (search MoonPack) or:
cd ComfyUI/custom_nodes
git clone https://github.com/moonwhaler/comfyui-moonpack.git
Restart ComfyUI. Your LoRAs live in ComfyUI/models/loras as usual - the node reads that folder for the ➕ Add LoRA picker. No models to download and no extra dependencies.
One thing to check
If you're stacking LoRAs on a two-pass model like Wan 2.2, remember the trigger words still have to reach the prompt encoder on the pass that matters. This node gets the words into the string - what you do with the string is on you.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| separator | STRING | . | Inserted verbatim between the trigger texts of enabled LoRAs. |
| clipopt | CLIP | — | |
| trigger_textopt | STRING | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |
| CLIP | CLIP | — |
| trigger_text | STRING | — |