Pick from List
Actionrectangle.and.text.magnifyingglass
action.palette — appears as Pick from List in the Actions palette
Pauses a running flow and floats a Spotlight-shaped chooser — so you can pick one row out of the list the node before it produced. Type to filter, arrow to move, ↵ to pick. The flow continues carrying the row you chose.
It is the mid-flow “which one?” step. User Input asks a question; the Mid-Flow Form asks several; Pick from List asks which of these. Query 40 customers, pick one, act on it — without writing the list into the flow.
The panel is the same surface the app summons everywhere else: always on top, follows you to the active Space, works over full-screen apps, and takes no keyboard focus from the app underneath until you type into it. Only the branch that reached this node waits; the rest of the flow is untouched.
It chooses from the node before it
The node has no data source of its own. It reads records from the incoming payload — the same real array of rows a Find in Database, a Linear: Query Issues, or any node that emits a list already produces. Whatever fills records decides what there is to pick from, which is why the node has no query, no table picker, and no file field.
- No
recordsat all — or an empty list — still opens the chooser, showing that the flow ran and found nothing. Dismissing it is the normal way out. - Rows of plain values (a list of strings or numbers) are shown under a single
valuecolumn, and the row you pick arrives as{ "value": … }. recordsas JSON text is refused before anything opens. Rows serialized into a string is what a hand-built upstream step produces by accident; parsing it on the node's own initiative is how a flow ends up letting you choose between characters. Fix the node above it to emit a real array.
An upstream columns array (and columnTypes, if there is one) is honoured as the display order. With none declared, every column the rows carry is discovered automatically.
Ports
Two ways out, and only one of them ever fires. Work you wire behind Selected cannot run on a row nobody chose.
| Direction | Name | Data Type | Description |
|---|---|---|---|
| Input | Input | Any | Incoming payload — records is the list to choose from; columns sets the display order |
| Output | Selected | Any | The user picked a row. Carries the incoming payload plus selected and selectedIndex |
| Output | Dismissed | Any | The user walked away. Carries the incoming payload unchanged — neither selection key exists on this path |
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
| Layout | Dropdown | List | List — one launcher row per record, glyph plus two lines. Table — a sortable grid, for when the columns themselves are what you are comparing. |
| Primary Column | Text | — | The big line on a list row. A column the rows don't actually carry falls back to the first text column — a mislabelled row is never a reason to fail the run. |
| Secondary Column | Text | — | The dim second line. Leave it blank for single-line rows. |
| Thumbnail Column | Text | — | List layout only. A column holding image paths (imagePath, filePath…). Each row whose path points at a readable image shows it as a small rounded thumbnail where the glyph would be; every other row keeps its glyph. A path that has moved or been deleted costs you the picture, never the row — it stays fully pickable. Only the rows on screen are read from disk, so a long list opens just as fast. |
| Search Columns | Text | — | Comma-separated column names the search box matches against (name, email). Blank searches every text column. |
| Prompt | Text | Search… | The search field's placeholder. The chooser has no title bar, so this is the question — phrase it as one: “Pick a customer…”. |
Output Variables
Both keys exist only on the Selected path. The variable picker offers them to anything downstream of either outlet, so read them behind Selected — on the Dismissed path they are genuinely absent, and {{selected}} there resolves to nothing rather than to a stale row.
| Variable | Type | Description |
|---|---|---|
| selected | JSON | The whole row you picked, as real structure — every column, not just the two on screen, and each cell still the type it arrived as. Navigate it with {{selected.email}}, {{selected.meta.owner}}. |
| selectedIndex | Number | Zero-based position of that row in records. records[selectedIndex] is selected, no matter what you filtered or sorted on screen. |
Both keys are merged over the incoming payload, so everything upstream — including the records list itself — still flows through underneath. An upstream key literally named selected is overwritten by the choice.
Keyboard
| Key | Does |
|---|---|
| type | Filters the rows live. The count in the footer reads “N of M” as you narrow. |
| ↑ ↓ | Moves the highlight, wrapping at the ends. |
| ↵ | Picks the highlighted row — the flow leaves by Selected. |
| esc | Dismisses — the flow leaves by Dismissed and keeps running. Clicking outside the panel does the same. |
Walking away is not a failure
Dismissing takes the Dismissed wire, not the Failure wire. Escaping a chooser is a normal outcome with its own path — the run finishes as completed, and a wired Failure outlet does not receive it. Leave Dismissed unwired and the flow simply ends there; wire it to say “nothing picked” out loud.
The fork is real. Whichever outlet is not taken is skipped in full — the canvas greys that branch out for the run, and nothing behind it executes. That is the whole point of two outlets: a Move to Trash wired behind Selected can never fire on a row nobody picked.
Stopping the flow closes the chooser — but as a cancellation, not a dismissal. Stop, quitting the app, or switching the flow off, takes the panel down and cancels the run outright; neither outlet fires, so a Dismissed wire never sees it — a cancelled run just never leaves a chooser floating over your screen.
One chooser at a time, and losing the slot fails the node. A second summon while one is open replaces it: the open one fails — nobody ever answered it, so neither outlet is honest — rather than queueing a surprise second panel behind the one you thought you were done with.
Nobody home fails the node too, after 15 minutes. An unattended chooser — a 3 am Schedule fire, an MCP agent run with nobody watching — gives up rather than holding the flow's run slot indefinitely. That also fails the node; it does not take the Dismissed wire.
A disabled Pick from List continues via Dismissed. Nothing was picked, so the payload carries no selected and the Selected branch stays untaken — the same shape as walking away.
Example
A shortcut you press when someone asks for a contact: query the customers table, pick one from the list, and the email lands on your clipboard ready to paste.