jq – Other skill for AI agents
Expert jq usage for JSON querying, filtering, transformation, and pipeline integration. Practical patterns for real shell workflows.
Install the jq skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/jq-fc71f.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /jq – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/jq-fc71f.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $jq – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/jq-fc71f.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /jq – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/jq-fc71f.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /jq – then describe the task you want done.
SKILL.md content
jq — JSON Querying and Transformation
Overview
jq is the standard CLI tool for querying and reshaping JSON. This skill covers practical, expert-level usage: filtering deeply nested data, transforming structures, aggregating values, and composing jq into shell pipelines. Every example is copy-paste ready for real workflows.
When to Use This Skill
- Use when parsing JSON output from APIs, CLI tools (AWS, GitHub, kubectl, docker), or log files
- Use when transforming JSON structure (rename keys, flatten arrays, group records)
- Use when the user needs
jqinside a bash script or one-liner - Use when explaining what a complex
jqexpression does
How It Works
jq takes a filter expression and applies it to JSON input. Filters compose with pipes (|), and jq handles arrays, objects, strings, numbers, booleans, and null natively.
Basic Selection
# Extract a field
echo '{"name":"alice","age":30}' | jq '.name'
# "alice"
# Nested access
echo '{"user":{"email":"[email protected]"}}' | jq '.user.email'
# Array index
echo '[10, 20, 30]' | jq '.[1]'
# 20
# Array slice
echo '[1,2,3,4,5]' | jq '.[2:4]'
# [3, 4]
# All array elements
echo '[{"id":1},{"id":2}]' | jq '.[]'Filtering with select
# Keep only matching elements
echo '[{"role":"admin"},{"role":"user"},{"role":"admin"}]' \
| jq '[.[] | select(.role == "admin")]'
# Numeric comparison
curl -s https://api.github.com/repos/owner/repo/issues \
| jq '[.[] | select(.comments > 5)]'
# Test a field exists and is non-null
jq '[.[] | select(.email != null)]'
# Combine conditions
jq '[.[] | select(.active == true and .score >= 80)]'Mapping and Transformation
# Extract a field from every array element
echo '[{"name":"alice","age":30},{"name":"bob","age":25}]' \
| jq '[.[] | .name]'
# ["alice", "bob"]
# Shorthand: map()
jq 'map(.name)'
# Build a new object per element
jq '[.[] | {user: .name, years: .age}]'
# Add a computed field
jq '[.[] | . + {senior: (.age > 28)}]'
# Rename keys
jq '[.[] | {username: .name, email_address: .email}]'Aggregation and Reduce
# Sum all values
echo '[1, 2, 3, 4, 5]' | jq 'add'
# 15
# Sum a field across objects
jq '[.[].price] | add'
# Count elements
jq 'length'
# Max / min
jq 'max_by(.score)'
jq 'min_by(.created_at)'
# reduce: custom accumulator
echo '[1,2,3,4,5]' | jq 'reduce .[] as $x (0; . + $x)'
# 15
# Group by field
jq 'group_by(.department)'
# Count per group
jq 'group_by(.status) | map({status: .[0].status, count: length})'String Interpolation and Formatting
# String interpolation
jq -r '.[] | "\(.name) is \(.age) years old"'
# Format as CSV (no header)
jq -r '.[] | [.name, .age, .email] | @csv'
# Format as TSV
jq -r '.[] | [.name, .score] | @tsv'
# URL-encode a value
jq -r '.query | @uri'
# Base64 encode
jq -r '.data | @base64'Working with Keys and Paths
# List all top-level keys
jq 'keys'
# Check if key exists
jq 'has("email")'
# Delete a key
jq 'del(.password)'
# Delete nested keys from every element
jq '[.[] | del(.internal_id, .raw_payload)]'
# Recursive descent: find all values for a key anywhere in tree
jq '.. | .id? // empty'
# Get all leaf paths
jq '[paths(scalars)]'Conditionals and Error Handling
# if-then-else
jq 'if .score >= 90 then "A" elif .score >= 80 then "B" else "C" end'
# Alternative operator: use fallback if null or false
jq '.nickname // .name'
# try-catch: skip errors instead of halting
jq '[.[] | try .nested.value catch null]'
# Suppress null output with // empty
jq '.[] | .optional_field // empty'Practical Shell Integration
# Read from file
jq '.users' data.json
# Compact output (no whitespace) for further piping
jq -c '.[]' records.json | while IFS= read -r record; do
echo "Processing: $record"
done
# Pass a shell variable into jq
STATUS="active"
jq --arg s "$STATUS" '[.[] | select(.status == $s)]'
# Pass a number
jq --argjson threshold 42 '[.[] | select(.value > $threshold)]'
# Slurp multiple JSON lines into an array
jq -s '.' records.ndjson
# Multiple files: slurp all into one array
jq -s 'add' file1.json file2.json
# Null-safe pipeline from a command
kubectl get pods -o json | jq '.items[] | {name: .metadata.name, status: .status.phase}'
# GitHub CLI: extract PR numbers
gh pr list --json number,title | jq -r '.[] | "\(.number)\t\(.title)"'
# AWS CLI: list running instance IDs
aws ec2 describe-instances \
| jq -r '.Reservations[].Instances[] | select(.State.Name=="running") | .InstanceId'
# Docker: show container names and images
docker inspect $(docker ps -q) | jq -r '.[] | "\(.Name)\t\(.Config.Image)"'Advanced Patterns
# Transpose an object of arrays to an array of objects
# Input: {"names":["a","b"],"scores":[10,20]}
jq '[.names, .scores] | transpose | map({name: .[0], score: .[1]})'
# Flatten one level
jq 'flatten(1)'
# Unique by field
jq 'unique_by(.email)'
# Sort, deduplicate and re-index
jq '[.[] | .name] | unique | sort'
# Walk: apply transformation to every node recursively
jq 'walk(if type == "string" then ascii_downcase else . end)'
# env: read environment variables inside jq
export DISPLAY_REGION=eu-west
jq -n 'env.DISPLAY_REGION' # use a non-sensitive example; do not print secretsBest Practices
- Always use
-r(raw output) when passingjqresults to shell variables or other commands to strip JSON string quotes - Use
--arg/--argjsonto inject shell variables safely — never interpolate shell variables directly into filter strings - Prefer
map(f)over[.[] | f]for readability - Use
-c(compact) for newline-delimited JSON pipelines; omit it for human-readable debugging - Test filters interactively with
jq -nand literal input before embedding in scripts - Use
emptyto drop unwanted elements rather than filtering tonull
Security & Safety Notes
jqfilters do not normally execute shell commands, but invocation flags can read files and shell redirection writes output. Never usejq ... input.json > input.json: the shell truncates the input first. Write to a separate file, verify it and replace only the intended target- Avoid embedding untrusted JSON field values directly into shell commands; always quote or use
--arg
Common Pitfalls
- Problem:
jqoutputsnullinstead of the expected value
Solution: Check for typos in key names; use keys to inspect actual field names. Remember JSON is case-sensitive.
- Problem: Numbers are quoted as strings in the output
Solution: Use --argjson instead of --arg when injecting numeric values.
- Problem: Filter works in the terminal but fails in a script
Solution: Ensure the filter string uses single quotes in the shell to prevent variable expansion. Example: jq '.field' not jq ".field".
- Problem:
addreturnsnullon an empty array
Solution: Use add // 0 or add // "" to provide a fallback default.
- Problem: Streaming large files is slow
Solution: Use jq --stream or switch to jstream/gron for very large files.
Related Skills
@bash-pro— Wrapping jq calls in robust shell scripts@bash-linux— General shell pipeline patterns@github-automation— Using jq with GitHub CLI JSON output
Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
Related skills
- julia-pro – Master Julia 1.10+ with modern features, performance optimization, multiple dispatch…
- keyword-clustering-tool – Keyword Clustering Tool. Use when working with keyword list.
- keyword-comparison-tool – Keyword Comparison Tool. Use when working with two or more keywords and optional metrics.
- keyword-difficulty-estimator – Keyword Difficulty Estimator. Use when working with keyword plus supplied SERP or…
- keyword-expansion-tool – Keyword Expansion Tool. Use when working with seed terms and optional industry.
- keyword-gap-finder – Keyword Gap Finder. Use when working with your keyword set and competitor keyword sets.
- keyword-intent-identifier – Keyword Intent Identifier. Use when working with keyword or query list.
- keyword-placement-highlighter – Keyword Placement Highlighter. Use when working with text and target keywords.