Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    lanej

    jq

    lanej/jq
    Data & Analytics
    34
    2 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    JSON processing, parsing, and manipulation. STRONGLY PREFERRED for all JSON formatting, filtering, transformations, and analysis. Use instead of Python/Node.js scripts for JSON operations.

    SKILL.md

    jq - JSON Processing

    IMPORTANT: jq is the STRONGLY PREFERRED tool for ALL JSON formatting, parsing, manipulation, and analysis tasks. Use jq instead of Python/Node.js scripts, grep, awk, or other text processing tools when working with JSON data.

    Core Philosophy

    • Always use jq for JSON: If the data is JSON or can be converted to JSON, use jq
    • Streaming-friendly: jq processes JSON as a stream, making it memory-efficient for large files
    • Composable: jq filters can be chained with pipes, just like shell commands
    • Pure and functional: jq transformations are predictable and side-effect-free

    Basic Usage Patterns

    Pretty-Printing and Formatting

    # Pretty-print JSON (most common use case)
    cat file.json | jq '.'
    jq '.' file.json
    
    # Compact output (remove whitespace)
    jq -c '.' file.json
    
    # Sort keys alphabetically
    jq -S '.' file.json
    
    # Raw output (no quotes for strings)
    jq -r '.field' file.json
    
    # Null input (construct JSON from scratch)
    jq -n '{name: "value", count: 42}'
    

    Selecting and Filtering

    # Select a single field
    jq '.field' file.json
    
    # Select nested field
    jq '.user.email' file.json
    
    # Select array element by index
    jq '.[0]' array.json
    jq '.[2:5]' array.json  # Array slice
    
    # Select multiple fields (create new object)
    jq '{name: .name, email: .email}' file.json
    
    # Filter array elements
    jq '.[] | select(.age > 21)' users.json
    
    # Filter with multiple conditions
    jq '.[] | select(.active == true and .role == "admin")' users.json
    
    # Filter and select fields
    jq '.[] | select(.price < 100) | {name, price}' products.json
    

    Array Operations

    # Map over array (transform each element)
    jq 'map(.name)' users.json
    jq '[.[] | .email]' users.json  # Alternative syntax
    
    # Filter then map
    jq 'map(select(.active)) | map(.name)' users.json
    
    # Get array length
    jq 'length' array.json
    jq '.items | length' file.json
    
    # Sort array
    jq 'sort' numbers.json
    jq 'sort_by(.created_at)' items.json
    
    # Reverse array
    jq 'reverse' array.json
    
    # Unique values
    jq 'unique' array.json
    jq 'unique_by(.category)' items.json
    
    # Group by field
    jq 'group_by(.category)' items.json
    
    # Flatten nested arrays
    jq 'flatten' nested.json
    jq 'flatten(2)' deeply_nested.json  # Flatten 2 levels
    

    Aggregations and Statistics

    # Sum values
    jq 'map(.price) | add' items.json
    jq '[.[] | .count] | add' data.json
    
    # Average
    jq 'map(.score) | add / length' scores.json
    
    # Min/max
    jq 'map(.price) | min' products.json
    jq 'map(.price) | max' products.json
    jq 'min_by(.created_at)' items.json
    jq 'max_by(.score)' results.json
    
    # Count occurrences
    jq 'group_by(.status) | map({status: .[0].status, count: length})' items.json
    

    Transforming Data

    # Add field
    jq '. + {new_field: "value"}' file.json
    
    # Update field
    jq '.price = .price * 1.1' product.json
    jq '.updated_at = now' record.json
    
    # Rename field
    jq '{name: .old_name, other: .other}' file.json
    
    # Delete field
    jq 'del(.sensitive_data)' file.json
    
    # Conditional updates
    jq 'if .price > 100 then .category = "premium" else . end' product.json
    
    # Map with transformation
    jq 'map(. + {full_name: "\(.first_name) \(.last_name)"})' users.json
    

    Combining and Merging

    # Merge objects
    jq '. + {extra: "data"}' file.json
    jq '. * {override: "value"}' file.json  # Recursive merge
    
    # Combine arrays
    jq '. + [1,2,3]' array.json
    
    # Merge multiple files
    jq -s '.[0] + .[1]' file1.json file2.json
    
    # Slurp mode (combine into array)
    jq -s '.' file1.json file2.json file3.json
    jq -s 'map(.items) | flatten' *.json
    

    Working with Keys

    # Get all keys
    jq 'keys' object.json
    jq 'keys_unsorted' object.json
    
    # Check if key exists
    jq 'has("field")' file.json
    
    # Get values
    jq 'values' object.json
    jq '.[] | values' array.json  # Filter out nulls
    
    # Convert object to array of key-value pairs
    jq 'to_entries' object.json
    jq 'to_entries | map({key: .key, value: .value})' object.json
    
    # Convert array of pairs back to object
    jq 'from_entries' pairs.json
    

    String Operations

    # String interpolation
    jq '"\(.first_name) \(.last_name)"' user.json
    
    # String functions
    jq '.name | ascii_downcase' file.json
    jq '.email | ascii_upcase' file.json
    jq '.text | ltrimstr("prefix:")' file.json
    jq '.url | rtrimstr(".html")' file.json
    
    # Split and join
    jq '.tags | split(",")' file.json
    jq '.words | join(" ")' file.json
    
    # Regular expressions
    jq '.email | test("@example\\.com$")' user.json
    jq '.text | match("\\b\\w+@\\w+\\.\\w+\\b")' content.json
    jq '.name | sub("old"; "new")' file.json
    jq '.text | gsub("\\s+"; " ")' file.json  # Replace all
    

    Conditional Logic

    # Simple if-then-else
    jq 'if .age >= 18 then "adult" else "minor" end' user.json
    
    # Multiple conditions
    jq 'if .score > 90 then "A" elif .score > 80 then "B" else "C" end' result.json
    
    # Alternative operator (handle null/false)
    jq '.optional_field // "default"' file.json
    
    # Try-catch (handle errors gracefully)
    jq 'try .field.nested catch "not found"' file.json
    

    Type Conversions

    # Convert to string
    jq 'tostring' number.json
    
    # Convert to number
    jq 'tonumber' string.json
    
    # Type checking
    jq 'type' value.json
    jq '.[] | select(type == "number")' mixed.json
    
    # Array/object detection
    jq 'if type == "array" then length else 1 end' value.json
    

    Output Formatting

    # Tab-separated values
    jq -r '.[] | [.name, .email, .age] | @tsv' users.json
    
    # CSV output
    jq -r '.[] | [.name, .email, .age] | @csv' users.json
    
    # URL encoding
    jq -r '@uri' string.json
    
    # Base64 encoding/decoding
    jq -r '@base64' string.json
    jq -r '@base64d' encoded.json
    
    # HTML encoding
    jq -r '@html' string.json
    
    # Shell escaping
    jq -r '@sh' command.json
    

    Advanced Patterns

    # Recursive descent (search all levels)
    jq '.. | .id? | select(. != null)' nested.json
    
    # Walk (apply transformation recursively)
    jq 'walk(if type == "string" then ascii_downcase else . end)' file.json
    
    # Path queries
    jq 'path(.items[].name)' file.json
    jq 'getpath(["items", 0, "name"])' file.json
    
    # Limit output
    jq 'limit(5; .[] | select(.active))' items.json
    
    # Until condition
    jq 'until(. > 100; . * 2)' number.json
    
    # Reduce (fold)
    jq 'reduce .[] as $item (0; . + $item.count)' items.json
    jq 'reduce .[] as $item ({}; . + {($item.key): $item.value})' pairs.json
    

    Working with API Responses

    # Pretty-print API response
    curl -s api.example.com/data | jq '.'
    
    # Extract specific fields from API
    curl -s api.example.com/users | jq '.[] | {id, name, email}'
    
    # Filter and transform
    curl -s api.example.com/items | jq 'map(select(.active)) | sort_by(.created_at) | reverse | .[0:10]'
    
    # Pagination handling
    for page in {1..5}; do
      curl -s "api.example.com/items?page=$page" | jq '.items[]'
    done | jq -s '.'
    
    # Error handling
    curl -s api.example.com/data | jq 'if .error then .error.message else .data end'
    

    Log Analysis

    # Parse JSON logs
    cat app.log | jq -R 'fromjson? | select(.level == "error")'
    
    # Group errors by type
    cat app.log | jq -R 'fromjson? | select(.level == "error")' | jq -s 'group_by(.error_type) | map({type: .[0].error_type, count: length})'
    
    # Time-based filtering
    cat app.log | jq -R 'fromjson? | select(.timestamp > "2024-01-01")'
    
    # Extract stack traces
    cat app.log | jq -R 'fromjson? | select(.stack_trace) | .stack_trace'
    

    Multi-File Processing

    # Merge multiple JSON files
    jq -s 'add' file1.json file2.json file3.json
    
    # Process each file separately, collect results
    jq -s 'map(.)' *.json
    
    # Cross-file analysis
    jq -s 'map(.items) | flatten | group_by(.category)' *.json
    
    # Join files (like SQL join)
    jq -s '.[0].users as $users | .[1].orders | map(. + {user: ($users[] | select(.id == .user_id))})' users.json orders.json
    

    Performance Optimization

    # Streaming mode for large files (don't load entire file)
    jq --stream 'select(length == 2)' huge.json
    
    # Process line-by-line for NDJSON (newline-delimited JSON)
    cat data.ndjson | jq -c '.'
    
    # Use compact output to reduce size
    jq -c '.' file.json > compressed.json
    
    # Limit memory by processing incrementally
    cat stream.json | jq -c 'select(.important)' >> filtered.json
    

    Debugging

    # Debug mode (show intermediate values)
    jq --debug '.field' file.json
    
    # Print to stderr while continuing
    jq 'debug | .field' file.json
    
    # Add debugging output
    jq '. as $orig | .field | debug | $orig' file.json
    
    # Validate JSON
    jq empty file.json  # No output = valid JSON
    
    # Check for null fields
    jq 'paths(. == null)' file.json
    

    Common Patterns for Claude Code Tasks

    Extract Configuration Values

    # Get specific config value
    jq -r '.database.host' config.json
    
    # Get all environment variables
    jq -r '.env | to_entries | .[] | "\(.key)=\(.value)"' config.json
    

    Process API Responses

    # Extract IDs from response
    gh api /repos/owner/repo/issues | jq '.[].number'
    
    # Format for display
    gh api /repos/owner/repo/pulls | jq -r '.[] | "\(.number): \(.title)"'
    

    Transform Test Results

    # Parse test output
    cat test-results.json | jq '{total: .stats.tests, passed: .stats.passes, failed: .stats.failures}'
    
    # Find failed tests
    cat test-results.json | jq '.tests[] | select(.state == "failed") | .title'
    

    Modify Package Files

    # Update package.json version
    jq '.version = "2.0.0"' package.json > package.json.tmp && mv package.json.tmp package.json
    
    # Add dependency
    jq '.dependencies["new-package"] = "^1.0.0"' package.json > package.json.tmp && mv package.json.tmp package.json
    
    # Remove dev dependency
    jq 'del(.devDependencies["old-package"])' package.json > package.json.tmp && mv package.json.tmp package.json
    

    When NOT to Use jq

    • Binary data: jq is for text-based JSON only
    • Very simple extraction: For trivial field access where grep would suffice
    • Modifying files in place: jq doesn't support in-place editing (use temp files)
    • Non-JSON data: Use appropriate tools (xsv for CSV, yq for YAML, etc.)

    Error Messages and Troubleshooting

    Common Errors

    # "parse error: Invalid numeric literal"
    # → JSON has invalid syntax, validate with: jq empty file.json
    
    # "jq: error: Cannot index string with string"
    # → Trying to access field on non-object, check types first
    
    # "jq: error: null cannot be parsed as JSON"
    # → Input is null or empty, use: jq -R 'fromjson?'
    
    # "Cannot iterate over null"
    # → Field doesn't exist, use: jq '.field // []'
    

    Validation

    # Validate JSON syntax
    jq empty file.json && echo "Valid JSON" || echo "Invalid JSON"
    
    # Pretty-print to find errors
    jq '.' file.json
    

    Performance Considerations

    1. Use -c for compact output when piping to other commands
    2. Stream large files with --stream or process line-by-line for NDJSON
    3. Filter early to reduce data size before complex transformations
    4. Avoid unnecessary array creation - use streaming operations when possible
    5. Use built-in functions like map, select, group_by instead of manual loops

    Integration with Other Tools

    # With curl
    curl -s api.example.com/data | jq '.results[]'
    
    # With grep (for NDJSON)
    cat logs.ndjson | grep "error" | jq '.'
    
    # With awk
    cat data.json | jq -r '.[] | @tsv' | awk -F'\t' '{print $1, $3}'
    
    # With xargs
    jq -r '.files[]' list.json | xargs -I {} cp {} dest/
    
    # With parallel processing
    cat items.json | jq -c '.[]' | parallel -j4 'echo {} | jq ".id"'
    

    Resources

    • Official manual: https://stedolan.github.io/jq/manual/
    • jq play (online tester): https://jqplay.org/
    • Cookbook: https://github.com/stedolan/jq/wiki/Cookbook
    Recommended Servers
    Parallel Tasks
    Parallel Tasks
    Browser tool
    Browser tool
    Repository
    lanej/dotfiles
    Files