Custom Functions and Modules

def name: body; defines a function. Parameters come in two kinds: f is a filter argument, evaluated against whatever input the function gives it (a closure, so revenue_by(.channel) and revenue_by(month) both work), while $min is an ordinary value. Functions you reuse belong in a module file, loaded with import from the directories given by -L.

booknest.jq: a jq module for the sample ordersPython
# booknest.jq: reusable filters for BookNest's sample orders
def money: . * 100 | round / 100;
def month: .order_ts[0:7];
def revenue_by(f): reduce .[] as $o ({}; .[$o | f | tostring] += $o.total) | map_values(money);
def big_orders($min): .[] | select(.total >= $min) | .order_id;
Importing the module, and an inline definition
jq -n -c -L . 'import "booknest" as bn;
  [limit(12000; inputs)] | bn::revenue_by(bn::month), [bn::big_orders(180)]' data/orders.jsonl
jq -n -c 'def sq: . * .; [range(1; 5) | sq]'
Output
{"2025-01":198449.25,"2025-02":174781.43,"2025-03":44856.34}
[1301,6922]
[1,4,9,16]

import "booknest" as bn; namespaces the functions as bn::money; include "booknest"; would merge them into the program instead. Keep shared modules in version control next to the pipelines that use them, and test them with jq 133,477 's --run-tests, which reads cases of program, input and expected output.