| name | jq |
| description | This skill should be used when the user asks to "parse JSON", "filter JSON", "transform JSON", "extract fields from JSON", "query JSON data", "format JSON output", "convert JSON to CSV", "reshape JSON", "merge JSON files", or when working with JSON data on the command line. Covers jq filters, built-in functions, and advanced patterns. |
jq — Command-Line JSON Processor
jq (v1.8.1) is installed at /opt/homebrew/bin/jq. It reads JSON from stdin
or files, applies filters, and outputs transformed JSON. Prefer jq over
writing custom scripts for JSON manipulation in shell pipelines.
Core Concepts
Filters and Pipes
Every jq program is a filter. Filters connect with | (pipe) and produce
zero or more outputs. The . filter is identity (passes input through).
echo '{"name":"Ada"}' | jq '.name'
echo '{"user":{"id":1}}' | jq '.user.id'
echo '{"items":[1,2,3]}' | jq '.items | add'
Array Operations
echo '[10,20,30]' | jq '.[1]'
echo '[10,20,30]' | jq '.[1:3]'
echo '[1,2,3]' | jq '.[]'
echo '[1,2,3,4]' | jq 'map(select(. > 2))'
Object Construction
echo '{"first":"Ada","last":"Lovelace","age":36}' | jq '{name: .first, surname: .last}'
echo '{"name":"Ada","age":36}' | jq '{name, age}'
echo '{"key":"color","val":"blue"}' | jq '{(.key): .val}'
Essential Command-Line Flags
| Flag | Purpose |
|---|
-r | Raw string output (no quotes) |
-R | Raw input (treat each line as string) |
-s | Slurp all inputs into one array |
-n | Null input (use with input/inputs) |
-c | Compact output (one line) |
-S | Sort object keys |
-e | Set exit status based on output (false/null = 1) |
--arg k v | Bind string variable $k |
--argjson k v | Bind JSON variable $k |
--slurpfile k f | Load file into $k as array |
--rawfile k f | Load file into $k as string |
--tab | Indent with tabs |
--indent n | Set indentation level |
Common Patterns
Extract and reshape
cat data.json | jq '.[].user.email'
cat data.json | jq '[.[] | {id: .id, name: .name}]'
cat data.json | jq '[.[][] ]'
cat data.json | jq 'flatten'
Filter and search
jq '[.[] | select(.status == "active")]' users.json
jq '[.[] | select(.name | test("^A"))]' users.json
jq '[.[] | select(has("email"))]' users.json
Aggregate and summarize
jq 'length' data.json
jq '[.[].price] | add' orders.json
jq 'group_by(.category) | map({key: .[0].category, count: length})' items.json
jq 'min_by(.age)' people.json
Transform and update
jq '.version = "2.0"' package.json
jq '.config.timeout |= . + 10' settings.json
jq '[.[] | . + {processed: true}]' items.json
jq 'del(.metadata)' data.json
Format conversion
jq -r '.[] | [.name, .age, .email] | @csv' users.json
jq -r '.[] | [.id, .status] | @tsv' records.json
jq -r '.query | @uri' params.json
jq -r '.filename | @sh' config.json
jq -r '.data | @base64' payload.json
jq -r '.encoded | @base64d' payload.json
Multi-file and variable operations
jq --arg name "$USER" '.users[] | select(.name == $name)' db.json
jq --argjson threshold 100 '[.[] | select(.count > $threshold)]' data.json
jq -s '.[0] * .[1]' defaults.json overrides.json
jq -n '[inputs]' file1.json file2.json
String operations
jq -r '"User: \(.name) (age \(.age))"' user.json
jq '.path | split("/") | last' config.json
jq '.text | gsub("old"; "new")' doc.json
jq '.value | trim' data.json
Quick Reference — Key Built-in Functions
| Category | Functions |
|---|
| Array | map, select, empty, add, sort_by, group_by, unique_by, flatten, reverse, first, last, range, limit, nth, transpose, combinations |
| Object | keys, values, has, in, to_entries, from_entries, with_entries, del, pick |
| String | test, match, capture, scan, split, join, sub, gsub, ltrimstr, rtrimstr, trim, ascii_downcase, ascii_upcase, startswith, endswith, explode, implode |
| Type | type, length, utf8bytelength, tostring, tonumber, arrays, objects, strings, numbers, booleans, nulls, scalars, iterables, values |
| Math | floor, ceil, round, sqrt, pow, log, exp, fabs, abs, sin, cos, atan, nan, infinite, isinfinite, isnan |
| Date | now, todate, fromdate, todateiso8601, fromdateiso8601, strftime, strptime, gmtime, mktime |
| Path | path, paths, leaf_paths, getpath, setpath, delpaths |
| Format | @csv, @tsv, @json, @html, @uri, @urid, @sh, @base64, @base64d, @text |
| I/O | input, inputs, debug, stderr, halt, halt_error, error, env, $ENV |
| SQL-style | INDEX, IN, GROUP_BY, UNIQUE_BY, JOIN |
Operator Reference
| Operator | Purpose |
|---|
| | Pipe (chain filters) |
, | Multiple outputs |
? | Suppress errors (try) |
// | Alternative (default for null/false) |
|= | Update in place |
+= -= *= /= %= //= | Arithmetic update |
as $var | Variable binding |
.. | Recursive descent |
Error Handling
jq '.foo.bar?' data.json
jq 'try .foo.bar catch "default"' data.json
if jq -e '.enabled' config.json > /dev/null 2>&1; then
echo "Feature is enabled"
fi
Agent-Specific Notes
- Always use
-r when output feeds into other shell commands (avoids quoted strings)
- Use
-e in conditionals to leverage jq's exit status
- Use
--arg / --argjson to pass shell variables — never interpolate variables into jq programs directly (injection risk)
- Use
-c for compact output when piping JSON between commands
- Use
-s (slurp) to process multiple JSON objects as a single array
- Combine with
curl -s for API response processing: curl -s url | jq '.data'
Additional Resources
Reference Files
For detailed function signatures and advanced patterns, consult:
references/filters.md — Complete built-in function reference organized by category with signatures and examples
references/advanced.md — Advanced patterns: reduce, foreach, streaming, recursive processing, custom functions, and complex data transformations