_.rest
Everything after the first item, without the ceremony
- py_list
- LIST
_.rest is a tiny list-slicing node: feed it a list, get back a list of everything except the first element. If you've used the JS library Underscore.js, you already know the semantics - this is that exact function, wrapped up as a ComfyUI node by the comfy-ovum pack.
Let me be straight about the context before the details. This is one of a family of auto-generated _.something nodes in the pack, and the author's own README says, almost verbatim: these are "an absolute disaster to use in production," a work in progress, and "not recommended for use in workflows." That's not modesty - the wrapper generator has rough edges, which I'll get to. If you just want to drop the head of a list, this node works. If you're building something you'll depend on, the pack's own ListSlice node (same menu area) is the saner pick.
How it works
Every underscore node in this pack wraps underscore3, a Python port of Underscore.js that ships inside the repo - no separate install. The wrapper deep-copies whatever you feed in, so _.rest never mutates your source list; you always get a fresh slice. That's a genuinely nice property for graph debugging, where shared list objects cause half the confusing bugs.
The implementation is just self.obj[index:], aliased from Underscore's tail/rest. It expects an array, but the py_list input is typed *, so the node won't stop you from passing a dict or a number - it just returns whatever slicing does to it.
The inputs that matter
There's really one input you touch:
- py_list (
*) - the source. Anything list-like works; tuples and sets get sliced too. - index (BOOLEAN, default true) - this is where the "disaster" shows up. In real Underscore,
rest(list, index)lets you say "start from position 3." The auto-generator here saw the default of1and, because Python's1 == True, classified the widget as a boolean. So in practice you get the default slice-from-1 and no meaningful control over the start position. Set it tofalseand you slice from position 0 - i.e., the whole list. Don't lose sleep over it.
Output is a single LIST - everything from the cut point onward. Wire it into any node that eats a list.
One more trick worth knowing: _.rest (like all these nodes) accepts a _.CHAIN in its py_list input. If you feed it a chain from _.chain or another underscore node, it keeps the chain alive and returns a chain, which you unwrap later with _.value. That's the intended power move for multi-step list pipelines.
Install
# via ComfyUI Manager: search "comfy-ovum"
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
# restart ComfyUI
No models to download. The pack's dependencies (aiohttp, pillow, numpy, requests, and a few more) are declared in requirements.txt and installed by Manager for you; underscore3 is bundled in the repo.
If a list node misbehaves, check that you're feeding it a list, not a string or a dict. And if you find yourself needing real head/tail control for anything important, use ListSlice from the same pack instead - it has proper integer start/end and clamps its bounds like a grown-up.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| py_listopt | * | Primary input object (expected array). You can still pass any JSON-serializable value. Also accepts _.CHAIN to continue chaining. | |
| indexopt | BOOLEAN | true | index (boolean) |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LIST | LIST | — |