π Model Directory (dropdown)
One picker for all your model roots
- directory
Plenty of ComfyUI nodes - especially in 3D and custom pipelines - take a directory as a hand-typed STRING. ckpt_root, model_root, weights_dir. It's the worst kind of widget: absolute, long, and different on every machine, so shared workflows ship with someone else's /mnt/data/... path baked in. TypedModelDir turns that into a name you pick and an environment variable you set once.
What it does
You choose a root key - anigen, trellis, somax, or custom - and the node resolves that to an actual directory on your disk and emits it as a STRING. Wire the output into whatever node wants a root path. The point is that the workflow no longer contains a machine-specific path: it contains the word anigen, and your install decides what that means.
How it works
Resolution is a two-step fallback. For a non-custom key, the node reads the environment variable MODEL_ROOT_<KEY> in uppercase - MODEL_ROOT_ANIGEN, MODEL_ROOT_TRELLIS, MODEL_ROOT_SOMAX. If it's set and non-empty, that's your root. If it isn't, the node falls back to whatever you put in the custom_root field. If the resolved path doesn't exist or isn't a directory, it raises rather than handing a broken path downstream - an error at this node is much better than a confusing failure five nodes later.
Set the variables wherever ComfyUI gets its environment - in the launcher script, the systemd unit, the Docker -e flags, or the ENV block of your container build. One line each and you're done for every workflow you'll ever load. This is the pattern ComfyUI itself uses for HF_HOME and friends, and it's the one worth adopting: machine-specific config lives in the environment, not in the graph.
Inputs and output
root_key - the dropdown: anigen, trellis, somax, custom. "Which model root am I browsing." There's no filesystem scan behind this one, so there's no placeholder row and no refresh needed; the choices are baked into the node.
custom_root - an explicit path, used when root_key is custom or when the matching env var isn't set. It's declared as a forced input in the source, meaning it's a socket, not a text box: you wire a string into it (a Primitive/string node, or another node's output). That's slightly awkward if all you wanted was to type a path - see below.
directory - a STRING, the resolved root. Wire it into the downstream node's path input.
One clarification the pack's own blurb gets wrong: the module docstring describes this node as listing subdirectories as a dropdown. It doesn't - the shipped code resolves a root and returns the root itself, and the only dropdown is the four root keys. Read the schema, not the prose.
Installing it
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/JayDataEngineer/melite-utility-nodes.git
Restart ComfyUI, then search Melite Utility Nodes in ComfyUI Manager if you'd rather not clone. The pack's dependencies (matplotlib, av) are for its plot and media-decode nodes; this picker needs neither.
No models are downloaded by this pack, ever. It's a path resolver - you install the models yourself and tell it where they live.
Where it bites
customwith nothing wired resolves to an empty string, and you get "model root not found or not a directory: ". Becausecustom_rootis a forced input, you can't just click and type - drop a string primitive on it (or use one of the fixed keys plus an env var, which is the cleaner habit anyway).- The env var wins over
custom_root. IfMODEL_ROOT_TRELLISis set, whatever you wire intocustom_rootis ignored for that key. That's the intended precedence, but it surprises people who set an env var months ago and forgot. - It returns the root, not a subdirectory. If your downstream node wants
<root>/variant-aspecifically, this node alone doesn't get you there. That's what the pack's per-family pickers (Kimodo, HY-Motion, See-Through) are for - they enumerate the subdirectories of their own root and hand back the one you picked. - It changes when the root's mtime changes. Adding or removing a directory under the root invalidates the node, which is right for a directory selector - but it also means a busy scratch root keeps the node dirty.
- Nothing here validates what's in the directory. You'll get a path to an empty folder just as happily. The failure surfaces at the loader that actually reads it.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| root_key | COMBO | custom | Which model root to browse. Selects the env var MODEL_ROOT_<KEY>. Use 'custom' to type an explicit root path. |
| custom_root | STRING | Explicit root path (used when root_key='custom' or when the env var is not set). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| directory | STRING | β |