Programming
The Programming node is a pocket Python
- values
- data
- string
- int
- float
- bool
- list
- dict
- any
The Programming node is the heavyweight of Utility-MegaPack, and the reason most people install the pack at all. Its mode dropdown holds 61 operations: control flow (for/while/if/switch), data structures (dict, list, JSON Path extraction), text and parsing (regex, sandboxed Jinja, YAML), math and stats, logic and bitwise, crypto (SHA/HMAC/AES-GCM), and encoding (base64, URL, slug). If you've ever stared at a workflow and wished you could just write a line of Python, this is the node that gets you most of the way there without leaving the canvas.
It earns its place in real graphs, not just show-off ones. Compute a step count or CFG value with eval_expr instead of hardcoding it. Pull the seed out of a saved filename with regex_extract. Build a save path or a prompt with template_render. Merge two DICTs from earlier nodes with dict_merge. These are the glue operations that turn a one-off workflow into something you can hand to someone else without a lecture.
How it works
Same architecture as every node in the pack: the mode dropdown picks a registered operation, that operation declares its own inputs, and one process method dispatches. There are seven typed outputs - string, int, float, bool, list, dict, and a wildcard any - and only the ones the active mode fills are live; the rest pad to empty defaults. So for_loop lands in list, hashes land in string, compare and the boolean ops land in bool, and eval_expr spits into any so it can return whatever type your expression produces.
The two inputs that carry most of the weight are expr (the expression or while-loop condition) and the *_json family - vars_json for expression bindings, data_json for dict ops, cases_json for switch/case. All expressions run through simpleeval, not eval(): no imports, no attribute poking, and any __ substring is rejected outright. The Jinja template renderer runs inside a sandboxed environment too. That's not paranoia - this pack had a full security audit in v0.3.0 specifically to close escape hatches, and given how custom-node malware has spread via shared workflows, it's the right instinct.
Installing it
It's one node out of the pack, so install the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/IxMxAMAR/ComfyUI-Utility-MegaPack
Restart ComfyUI (or use ComfyUI Manager → search "Utility-MegaPack"). No model downloads. Dependencies are numpy, Pillow, requests, simpleeval, Jinja2, PyYAML, cryptography - simpleeval and Jinja2 are the ones this node actually leans on, and both are lightweight.
Where people get tripped up
The sandbox is the thing people fight first. eval_expr will cheerfully do 2 + 2, but it will refuse to import os or touch anything dunder-related, and that's a feature. The while_loop is hard-capped at 100,000 iterations, so if your expression never becomes false you get a bounded list, not a frozen machine. Regex modes use Python's re syntax - the same patterns you already know from everywhere else. And the crypto ops are the pack's own implementation (AES-GCM with HKDF-derived keys, constant-time HMAC compare), not a shell-out to a system tool, so they behave consistently everywhere. One aside: it's easy to forget which typed output an op uses, so glance at the node's socket names before wiring - that's the single most common "why is my node red?" moment with this one.
Inputs (43)
| Name | Type | Default | Description |
|---|---|---|---|
| mode | COMBO | aes_decrypt | 61 options: aes_decrypt, aes_encrypt, base64_decode, base64_encode, bitwise_and, bitwise_or, +55 |
| theme | COMBO | (use pack default) | 17 options: (use pack default), (use ComfyUI default), cyberpunk, minimalist, glassmorphic, retro_terminal, +11 |
| textopt | STRING | — | |
| max_lengthopt | INT | 801–1024 | — |
| aopt | BOOLEAN | false | — |
| bopt | BOOLEAN | false | — |
| placesopt | INT | 0-64–64 | — |
| valueopt | FLOAT | 0.00 | — |
| loopt | FLOAT | 0.00 | — |
| hiopt | FLOAT | 1.00 | — |
| topt | FLOAT | 0.500–1 | — |
| valuesopt | LIST | — | |
| seedopt | INT | -1-1–4294967295 | — |
| patternopt | STRING | — | |
| groupopt | INT | 00–99 | — |
| replacementopt | STRING | — | |
| max_splitsopt | INT | 00–1024 | — |
| templateopt | STRING | — | |
| vars_jsonopt | STRING | {} | — |
| sepopt | STRING | — | |
| data_jsonopt | STRING | {} | — |
| dataopt | DICT | [object Object] | — |
| keyopt | STRING | — | |
| defaultopt | STRING | — | |
| indexopt | INT | 0 | — |
| startopt | INT | 0 | — |
| stopopt | INT | 0 | — |
| reverseopt | BOOLEAN | false | — |
| pathopt | STRING | — | |
| default_on_missopt | STRING | — | |
| endopt | INT | 10 | — |
| stepopt | INT | 11–1000000 | — |
| expropt | STRING | i<10 | — |
| max_itersopt | INT | 10001–100000 | — |
| conditionopt | BOOLEAN | false | — |
| when_trueopt | STRING | — | |
| when_falseopt | STRING | — | |
| opopt | COMBO | == | 6 options: <, >, <=, >=, ==, != |
| copt | STRING | — | |
| cases_jsonopt | STRING | {"_": ""} | — |
| expected_hexopt | STRING | — | |
| plaintextopt | STRING | — | |
| ciphertext_b64opt | STRING | — |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| string | STRING | — |
| int | INT | — |
| float | FLOAT | — |
| bool | BOOLEAN | — |
| list | LIST | — |
| dict | DICT | — |
| any | * | — |