Reshape
The reshape step: every list manipulation in one tile — filter, sort, remove duplicates, limit, split out, aggregate — no code.
Every list manipulation in one step. Point it at a list, pick a task:
| task | what it does |
|---|---|
| filter | keep the items matching a condition |
| sort | order by a per-item key |
| remove duplicates | drop repeats by a compare key (first one wins) |
| limit | keep the first or last N |
| split out | lift a nested array up to the top-level items list |
| aggregate | collapse a list into one value |
Config
The task picker decides which fields show; every task starts from the same List expression.
- List — an expression picking the list off the upstream
output:
payload["items"]. Bracket access, same dialect as loop's over. - Per-task fields — filter's Keep when, sort's Sort by + order, remove-duplicates' compare key, limit's max + first/last, aggregate's mode.
Per-item expressions see three bindings: item (the element),
index (0-based), and payload (the whole upstream output) — so
item["score"] > payload["threshold"] works.
Output
filter / sort / remove duplicates / limit / split out share one envelope:
{ "items": [ … ], "count": 12 }
(filter adds "dropped".) Feed payload.items straight into a
loop or the next reshape. Aggregate emits per
its mode: all_items nests the whole list under one key;
fields collects named fields across items into parallel lists
({"emails": […], "count": 3}).
Patterns
- Top 5 digest — filter (
item["score"] > 50) → sort desc → limit 5 → summarize. - Dedupe then act — remove duplicates by
item["email"]→ loop → send. - Chain them — each reshape outputs
items, so the next one's List is justpayload["items"].