🔧 jq

JSON processing at the command line — and why AI makes it much easier

aider curl fabric fzf gh Copilot jq ollama ripgrep sgpt tmux

What Is jq?

jq is a lightweight, powerful command-line JSON processor. Think of it as sed and awk for JSON — it lets you slice, filter, transform, and format JSON data directly in the shell, with no need for Python scripts or a full programming environment.

For a Linux SysAdmin in 2026, jq is no longer optional. API responses, container logs, Kubernetes output, cloud CLI tools, systemd journal exports, Ansible facts — everything outputs JSON. If you can't process JSON at the command line, you're copy-pasting into a browser or writing throw-away Python for every one-off query.

jq's filter syntax is its own small language, and that's where AI becomes a genuine force multiplier. Describing what you want in plain English and having AI write the jq filter is dramatically faster than consulting the manual for every query.

"jq is the tool that turns JSON from a wall of text into data you can actually work with. AI is the tool that turns your intent into jq filters you don't have to memorize."

💰 Cost & Licensing

jq is free and open source (MIT license). It is available in the package repositories of every major Linux distribution.

# RHEL/Rocky/CentOS sudo dnf install jq # Debian/Ubuntu sudo apt install jq # Verify jq --version

💻 Basic Usage

Pretty-print JSON

The most common use — take compressed or ugly JSON and make it readable:

curl -s https://api.example.com/status | jq . # Or from a file jq . response.json

Extract a field

# Get a single top-level field echo '{"name":"bambustudio","status":"active"}' | jq '.name' # Get a nested field jq '.server.hostname' config.json

Extract from an array

# First element jq '.[0]' array.json # All elements — iterate jq '.[]' array.json # Specific field from each element jq '.[].name' array.json

Filter array elements

# Select elements where status is "running" jq '.[] | select(.status == "running")' containers.json # Select and extract just the name field jq '.[] | select(.status == "running") | .name' containers.json

Format output for shell use

# Raw output (no quotes) for use in scripts jq -r '.[] | .name' containers.json # Tab-separated columns jq -r '.[] | [.name, .status, .ip] | @tsv' containers.json # CSV output jq -r '.[] | [.name, .status] | @csv' containers.json

🤖 AI + jq — The Real Workflow

jq's filter language is expressive but not intuitive. The learning curve is steep enough that most SysAdmins use it occasionally but never feel fluent. AI changes that equation completely.

The pattern: describe, generate, verify, use

1. Paste your JSON sample and describe what you want:

# Tell the AI: "Here's a sample of the JSON I'm working with: [paste 10-20 lines of representative JSON] I need a jq filter that: - Selects only containers where status is 'running' - Returns name, image, and created_at fields - Formats as tab-separated for piping into awk - Uses raw output (-r flag)"

2. Test the generated filter on your real data:

jq -r '.[] | select(.status=="running") | [.name, .image, .created_at] | @tsv' \ containers.json | head -5

3. Refine if needed:

# Tell the AI: "Close — but created_at is a Unix timestamp, I need it converted to human-readable ISO format. Also sort by created_at descending."
Tip: Always give the AI a real sample of your JSON, not just a description of it. The field names, nesting depth, and data types in the actual output matter for getting a correct filter on the first try.

Real SysAdmin examples

Docker / Podman container inspection:

# List all running containers with name and IP podman ps --format json | jq -r \ '.[] | select(.State=="running") | [.Names[0], .Networks[].IPAddress] | @tsv' # Find containers using more than 1GB memory docker stats --no-stream --format '{{json .}}' | \ jq -r 'select(.MemUsage | split("/")[0] | rtrimstr("GiB") | tonumber > 1) | .Name'

systemd journal in JSON mode:

# Extract error messages from journal JSON output journalctl -o json --since "1 hour ago" | \ jq -r 'select(.PRIORITY <= "3") | [.__REALTIME_TIMESTAMP, .MESSAGE] | @tsv'

AWS CLI output:

# List EC2 instances: name tag, instance ID, state aws ec2 describe-instances | jq -r \ '.Reservations[].Instances[] | [(.Tags[]? | select(.Key=="Name") | .Value), .InstanceId, .State.Name] | @tsv'

Kubernetes:

# List pods not in Running state kubectl get pods -A -o json | jq -r \ '.items[] | select(.status.phase != "Running") | [.metadata.namespace, .metadata.name, .status.phase] | @tsv'

📝 Useful jq Patterns to Know

keys and values

# List all keys in an object jq 'keys' object.json # List all values jq '[to_entries[] | .value]' object.json

Building new objects

# Reshape output into a new structure jq '.[] | {host: .hostname, ip: .network.ip, role: .tags.role}' servers.json

Counting and aggregating

# Count elements matching a condition jq '[.[] | select(.status=="running")] | length' containers.json # Group by a field and count jq 'group_by(.status) | map({status: .[0].status, count: length})' containers.json

Working with null values

# Provide a default when field is null jq '.[] | .description // "no description"' items.json # Filter out null values jq '[.[] | select(.name != null)]' items.json

Combining jq with other tools

# jq output into a while loop jq -r '.[].hostname' servers.json | while read host; do echo "Checking $host..." ssh "$host" uptime done # jq into sort and uniq jq -r '.[].status' containers.json | sort | uniq -c | sort -rn

✅ Strengths & Limitations

Works Well

  • Filters, transforms, and extracts JSON cleanly
  • Pipes naturally with all Unix tools
  • Raw output mode for scripting
  • CSV and TSV export built in
  • Available everywhere, no dependencies
  • AI generates filters quickly from descriptions
  • Fast even on large JSON files

Watch Out For

  • Filter syntax has a steep learning curve
  • Complex filters become hard to read
  • Not suitable for streaming very large files
  • Error messages can be cryptic
  • No in-place file editing (use sponge or temp files)
  • Numeric precision issues with large integers

📊 Craig's Take

jq is one of those tools I knew existed for years before I actually learned it — because every time I needed it, the filter syntax sent me back to grep and Python. AI changed that completely. Now I describe what I want, get a filter, test it, and refine it in under two minutes.

The combination of jq and AI is genuinely greater than the sum of its parts. jq is the right tool for JSON processing but has a difficult interface. AI is good at translating intent into jq syntax but can't run commands. Together they cover each other's weaknesses.

The workflow I use: paste a sample of the JSON into the chat, describe what I want, get the filter, test it. If it's wrong, paste the error or wrong output back and ask for a fix. Three iterations gets the right answer faster than reading the jq manual ever did.

"jq without AI is a tool I used occasionally. jq with AI is a tool I use daily."

🔗 Resources