ValiTools
ValiTools node collection: VSmartPrompt (Dynamic Prompts with rich-text editor, reusable variables, switcher conditions, chaining inputs and post-run selection highlighting), VFileRandom (no-repeat random image loader) and VRandomSelector (lazy random passthrough of N same-type inputs).
ValiTools
A collection of ComfyUI custom nodes. More tools will be added over time.
Nodes
VSmartPrompt
A Dynamic Prompts node with a rich-text (syntax-highlighted) prompt editor.
- Combinations:
{a|b}with optionalN::weights, nested at will, per-level coloring - Wildcards:
__file__pulls a random line from a.txtinwildcard_directory(subfolders supported); typing__opens an autocomplete dropdown of the existing wildcard files; CTRL+Click opens or creates the file in a built-in editor (works on remote installs too) - Variables:
{a|b}==<name>,__file__==<name>orword==<name>store the resolved value - rolled ONCE, constant everywhere you reuse<name>; assignments inside combination branches only fire for the selected branch; typing<opens an autocomplete dropdown of all assigned variables. Silent variant==!<name>stores the value but outputs nothing at the definition site - only the<name>references emit it (references work even before the assignment) - Comments:
#to end of line, inline#comment#,##/###headline styles - Find & replace + undo/redo: hovering or focusing the editor shows a small toolbar (undo / redo / find).
CTRL+Fopens find,CTRL+Hjumps straight to the replace field;ENTER/SHIFT+ENTERstep through matches,Aatoggles case sensitivity,⧉restricts find & replace to the selected text (a multi-line selection sets this automatically),ESCcloses. The⎘button copies the whole prompt as plain text. Undo/redo works via the buttons orCTRL+Z/CTRL+SHIFT+Z/CTRL+Y(typing bursts collapse into one step) - Post-run feedback: the branches actually selected during execution are marked in the editor; resolved wildcards show their pulled line on hover; variables (assignments, references and switcher conditions) show their rolled value on hover
- String inputs: four optional input sockets
in1-in4; connected text is available in the prompt as<in1>-<in4>(inserted as-is, not re-resolved) - chain VSmartPrompt nodes by wiring one's output into another's socket - Variable hand-over: wire a node's
variablesoutput into the next node'svars_ininput and every<name>it assigned works there too - references, switcher conditions and all. Inherited variables travel on down the chain; a local assignment to the same name wins - Switcher: glue
<name>==value::directly in front of a{...}block or__wildcard__to gate it on a variable's value (case-insensitive) - match resolves normally, mismatch outputs nothing.<name>!=value::is the NOT form (fires for every other value). Tag the state with silent branch assignments ({... cake==!<act>|... glass==!<act>}), then later<act>==cake::{...}/<act>!=cake::{...}. Works within1-in4too; assign the tag before the switch - Outputs:
prompt(resolved),original_prompt,variables(forvars_inof another VSmartPrompt)
Example - every feature at a glance

## EXAMPLE - every feature in one prompt
a {photo|{oil|water} painting} of a {0.7::cute|scary} __animal__==<pet>
# {a|b} picks one option (nesting ok), '0.7::' sets its chance to 70%
# __animal__ pulls a random line from animal.txt, '==<pet>' remembers the result
the <pet> naps in a (cozy:1.2) {garden|kitchen}. {day|night}==!<time> #the same <pet> again!#
# '<pet>' outputs the SAME value everywhere. '==!<time>' remembers silently (outputs nothing)
<time>==day::{sunlight warms the <pet>|birds sing}
<time>!=day::{the <pet> sleeps in the dark}
# switcher: a gated block only appears when its condition matches the remembered value
With the picks shown above (white marks), the output is:
a photo of a cute fox the fox naps in a (cozy:1.2) kitchen. the fox sleeps in the dark
Colors: green/blue = combination options per nesting level, gold = wildcards, violet = variables, orange = switcher conditions, green italics = comments, white marks = what the last run actually picked.
Based on ComfyUI-RichText_BasicDynamicPrompts (heavily modified fork).
VFileRandom
Loads a random image from a folder — like a shuffled deck: no image repeats until every image in the folder has been drawn once, then the deck reshuffles.
- The cycle is remembered per folder in
vfile_random_state.json(survives ComfyUI restarts) - Images added mid-cycle join the current cycle; deleted ones are dropped
include_subfoldersscans recursively;reset_cyclestarts a fresh shuffled cycle- Keep
seedon randomize — it only triggers a new draw each queue; fix it to pause drawing - Outputs:
image,mask(from alpha),filename(relative to folder),remaining_in_cycle,filename_noext - After each run the node displays the cycle progress (e.g.
45 / 235) so you can see when the deck reshuffles
VRandomSelector
Passes one of its connected inputs through at random. Accepts any input type — all inputs must share one type; the first connection locks it.
- Variable input count: a new empty slot appears as you connect (up to 30)
- Lazy evaluation: only the selected input's upstream branch executes — unselected branches stay cold
from_input/to_inputrestrict the pick to a slot range (0 = no limit)- Keep
seedon randomize — same seed + same connections = same pick - Outputs:
selected(typed like the inputs),selected_index(1-based)
Changelog
- v1.12.1
- VSmartPrompt: copying is guaranteed plain text - the handler no longer falls through to the browser's default (which would copy the highlighting HTML) when the selection cannot be mapped, and it explicitly clears the rich-text flavour. New
⎘toolbar button copies the entire prompt as plain text
- VSmartPrompt: copying is guaranteed plain text - the handler no longer falls through to the browser's default (which would copy the highlighting HTML) when the selection cannot be mapped, and it explicitly clears the rich-text flavour. New
- v1.12.0
- VSmartPrompt: typing
__opens a dropdown of the existing wildcard files, just like<does for variables - filters as you type (substring match, prefix matches first), UP/DOWN + ENTER/TAB or click inserts__name__. Only offered while a__is actually open, so a finished__wildcard__no longer triggers it
- VSmartPrompt: typing
- v1.11.0
- VSmartPrompt: variables can be handed from node to node - new
variablesoutput andvars_ininput. Everything a prompt assigned (including what it inherited itself) is available in the next node as a normal<name>, works with switcher conditions, and a local assignment to the same name still wins. Thein1-in4socket names are deliberately not passed on. Changed inherited values re-roll the downstream picks even with a fixed seed
- VSmartPrompt: variables can be handed from node to node - new
- v1.10.0
- VSmartPrompt: CTRL+Click on a wildcard now opens its
.txtin a built-in editor overlay (load, edit, save) instead of handing the path to the operating system's file handler. This removes the last system call from the package - the old behaviour never worked on remote ComfyUI installs and got the package flagged by the registry's security scan - Packaging: registry metadata completed (
[project.urls]table,requires-python, classifiers, emptyIconremoved),.comfyignoreadded, build artifacts (node.zip,.codex,.tracking) removed from git, and a GitHub Action publishes automatically whenpyproject.tomlchanges
- VSmartPrompt: CTRL+Click on a wildcard now opens its
- v1.9.3
- VSmartPrompt: find & replace can be restricted to the selected text - selecting several lines and pressing
CTRL+Fscopes it automatically, the⧉button toggles it, and the scoped region is tinted in the editor
- VSmartPrompt: find & replace can be restricted to the selected text - selecting several lines and pressing
- v1.9.2
- VSmartPrompt: fixed undo/redo staying greyed out - ComfyUI's widget setter fires
callback()on every assignment, so the node's own edits looked like external changes and reset the history on each keystroke. Own writes are now recognised; typed words group into one undo step, everything else (paste, cut, Enter, Tab, autocomplete, weighting, find & replace, external changes) is its own step, 500 steps deep
- VSmartPrompt: fixed undo/redo staying greyed out - ComfyUI's widget setter fires
- v1.9.1
- VSmartPrompt: the editor toolbar is easier to reach - it shows while the mouse is anywhere over the editor area, stays visible while the cursor travels to it, and dims to 55% opacity until hovered
- v1.9.0
- VSmartPrompt: find & replace in the editor (
CTRL+F/CTRL+H, plain text, case toggle, match counter, replace / replace all) and a real undo/redo history with toolbar buttons andCTRL+Z/CTRL+SHIFT+Z/CTRL+Y- the browser's own undo was dead because every edit rewrites the highlighted markup. Matches are painted with the CSS Custom Highlight API, so the syntax highlighting stays untouched
- VSmartPrompt: find & replace in the editor (
- v1.8.1
- VSmartPrompt: hovering a variable after a run shows its rolled value - works on assignments (
==<name>), references (<name>) and switcher conditions; resolved variables get a subtle violet underline like resolved wildcards
- VSmartPrompt: hovering a variable after a run shows its rolled value - works on assignments (
- v1.8.0
- VFileRandom: cycle progress counter shown on the node after each run (
45 / 235= 45th image drawn of a 235-image cycle)
- VFileRandom: cycle progress counter shown on the node after each run (
- v1.7.2
- VSmartPrompt: comments are now stripped BEFORE resolution - text inside comments can no longer trigger variable assignments, switcher guards, wildcard pulls or combination rolls (previously a comment like
'==<pet>' rememberssilently overwrote the variable) - README: visual all-features example with editor coloring
- VSmartPrompt: comments are now stripped BEFORE resolution - text inside comments can no longer trigger variable assignments, switcher guards, wildcard pulls or combination rolls (previously a comment like
- v1.7.1
- VSmartPrompt: copying/cutting from the editor now puts plain text on the clipboard - previously the syntax-highlighting HTML came along and markdown-aware paste targets rendered the bold styling as
**...**
- VSmartPrompt: copying/cutting from the editor now puts plain text on the clipboard - previously the syntax-highlighting HTML came along and markdown-aware paste targets rendered the bold styling as
- v1.7.0
- VSmartPrompt: switcher NOT guards -
<name>!=value::fires for every value except the given one; never-assigned variables remove the construct like with==
- VSmartPrompt: switcher NOT guards -
- v1.6.4
- VSmartPrompt: the white mark for a chosen zero-length branch (
{text|}) now actually renders - it marks the|delimiter (the mark's HTML previously misnested across the branch split and was dropped by the browser)
- VSmartPrompt: the white mark for a chosen zero-length branch (
- v1.6.3
- VSmartPrompt: guard against the prompt editor collapsing to a narrow strip - editor asserts full node width (100% + border-box), node keeps a 360px minimum width, re-checked on resize and workflow load
- v1.6.2
- VSmartPrompt: selection marks survive on branches whose stored value differs from the branch text (e.g.
{large chest chest==!<part>|stomach}==<part>); silent==!<name>blocks now also white-mark their chosen branch
- VSmartPrompt: selection marks survive on branches whose stored value differs from the branch text (e.g.
- v1.6.1
- VSmartPrompt:
in1-in4are lazy - an upstream node chain only executes when its<inN>actually appears in the prompt text; nodes skipped this way get their stale white selection marks cleared after the run (cached nodes keep theirs)
- VSmartPrompt:
- v1.6.0
- VSmartPrompt: switcher guards -
<name>==value::glued before a{...}block or__wildcard__gates it on a variable's value; false or never-assigned guards remove the construct (and skip its assignments); guards render orange in the editor (red when the variable is unassigned)
- VSmartPrompt: switcher guards -
- v1.5.1
- VSmartPrompt: fixed a serious RNG bias - the resolver reseeded the random generator with the same seed on every resolution pass, replaying the identical draw stream and locking picks of different passes together (worst case: a nested wildcard's line pick was 100% correlated with its parent's - half of the combinations could never occur). One RNG stream per run now; note: the same seed produces a different (unbiased) result than in older versions
- v1.5.0
- VSmartPrompt: connected
in1-in4texts are mixed into the effective seed - when an upstream node re-rolls, this node's combination/wildcard picks re-roll too, even with a fixed seed. Same seed + same prompt + same input texts stays fully reproducible
- VSmartPrompt: connected
- v1.4.3
- VSmartPrompt: post-run selection marking now survives variable substitution - a chosen branch consisting of references (e.g.
{0.4::<in1>|<in2>}) marks the<name>chars in the editor
- VSmartPrompt: post-run selection marking now survives variable substitution - a chosen branch consisting of references (e.g.
- v1.4.2
- VSmartPrompt: post-run selection marking now also shows picks of empty / whitespace-only branches - the branch's spaces are marked, or for zero-length branches the preceding
|delimiter
- VSmartPrompt: post-run selection marking now also shows picks of empty / whitespace-only branches - the branch's spaces are marked, or for zero-length branches the preceding
- v1.4.1
- VSmartPrompt: fixed CTRL+Left/Right word jump (and CTRL+SHIFT word selection) inside the editor - was swallowed by the global CTRL+arrow listener
- v1.4.0
- VSmartPrompt: four optional string input sockets
in1-in4, referenced in the prompt as<in1>-<in4>for chaining VSmartPrompt nodes; connected sockets show in the autocomplete dropdown and validate the references violet
- VSmartPrompt: four optional string input sockets
- v1.3.0
- VSmartPrompt: silent variable assignment
==!<name>- assigns without emitting the value at the definition site; works on all three forms ({a|b}==!<name>,__file__==!<name>,word==!<name>); silent assignments render dimmed/italic in the editor
- VSmartPrompt: silent variable assignment
- v1.2.1
- VFileRandom: new
filename_noextoutput (filename without extension)
- VFileRandom: new
- v1.2.0
- New node: VRandomSelector — random passthrough of one of N connected same-type inputs, lazy-evaluated, with optional slot-range restriction
- v1.1.0
- New node: VFileRandom — random image loader with no-repeat shuffle-bag cycling
- v1.0.0
- Initial release: VSmartPrompt (renamed from the SILVER_BasicDynamicPrompts fork v4.1.0, new node identifier and
/valitools/API routes so it can coexist with the original)
- Initial release: VSmartPrompt (renamed from the SILVER_BasicDynamicPrompts fork v4.1.0, new node identifier and