# jpx - JMESPath CLI with Extended Functions
[](https://crates.io/crates/jpx)
[](https://crates.io/crates/jpx)
[](https://github.com/joshrotenberg/jmespath-extensions#license)
A command-line tool for querying JSON data using JMESPath expressions with 400+ additional functions beyond the standard JMESPath specification.
## Acknowledgments
jpx builds on the excellent work of the JMESPath community:
- **[JMESPath](https://jmespath.org/)** - The query language specification created by [James Saryerwinnie](https://github.com/jamesls)
- **[jmespath.rs](https://crates.io/crates/jmespath)** - The Rust implementation by [@mtdowling](https://github.com/mtdowling) that provides our parsing, evaluation, and standard functions
- **[jp](https://github.com/jmespath/jp)** - The official JMESPath CLI (Go) - a minimal, focused tool that inspired jpx's design
If you only need standard JMESPath without extensions, consider using [jp](https://github.com/jmespath/jp) or the [`jmespath`](https://crates.io/crates/jmespath) crate directly.
## jpx vs jq
Coming from [jq](https://jqlang.org/)? Here's a quick comparison:
| **Language** | Custom DSL | JMESPath (standardized) |
| **Functions** | ~70 built-in | 400+ extensions |
| **Ecosystem** | Standalone | Works with AWS CLI, Ansible |
| **Streaming** | ✅ | ❌ |
```bash
# jq # jpx
jq '[.[] | select(.age > 30)]' jpx '[?age > `30`]'
jq '.[].name' jpx '[*].name'
**Choose jpx** for: extended functions (geo, hash, fuzzy, semver), multiple output formats, AI/MCP integration, JMESPath ecosystem compatibility.
**Choose jq** for: streaming large files, custom function definitions, complex recursive transformations.
**[Full comparison →](https://joshrotenberg.github.io/jmespath-extensions/examples/jq-comparison.html)**
## Quick Start (Docker)
Try jpx instantly without installing anything:
```bash
# Fetch a Hacker News story and extract fields
# {"by": "pg", "score": 57, "title": "Y Combinator"}
# Basic query
# Calculate average
# String manipulation
# Filter and transform
```
## Installation
```bash
# Docker (no install needed)
docker pull ghcr.io/joshrotenberg/jpx
# Homebrew (macOS/Linux)
brew tap joshrotenberg/brew
brew install jpx
# Pre-built binaries (macOS, Linux, Windows)
# Download from https://github.com/joshrotenberg/jmespath-extensions/releases
# From crates.io
cargo install jpx
# From source
git clone https://github.com/joshrotenberg/jmespath-extensions
cd jmespath-extensions/jpx
cargo install --path .
# Without MCP server support (smaller binary)
cargo install --path . --no-default-features
```
## MCP Server (AI Assistant Integration)
For MCP (Model Context Protocol) support, use the dedicated [`jpx-server`](https://crates.io/crates/jpx-server) package:
```bash
# Install
cargo install jpx-server
# Or use Docker
docker run -i --rm ghcr.io/joshrotenberg/jpx-server
```
See the [MCP documentation](https://joshrotenberg.github.io/jmespath-extensions/server/mcp/overview.html) for setup instructions with Claude Desktop.
## Usage
```bash
jpx [OPTIONS] [EXPRESSIONS]...
Arguments:
[EXPRESSIONS]... JMESPath expression(s) to evaluate (multiple are chained as a pipeline)
Options:
-e, --expression <EXPR> Expression(s) to evaluate (can be chained)
-Q, --query-file <FILE> Read JMESPath expression from file
-f, --file <FILE> Input file (reads from stdin if not provided)
-o, --output <FILE> Output file (writes to stdout if not provided)
-n, --null-input Don't read input, use null as input value
-s, --slurp Read all inputs into an array
--stream, --each Process input line by line (NDJSON/JSON Lines)
Output Formats:
-r, --raw Output raw strings without quotes
-c, --compact Compact output (no pretty printing)
-y, --yaml Output as YAML
--toml Output as TOML
--csv Output as CSV (for arrays of objects)
--tsv Output as TSV (for arrays of objects)
-l, --lines Output one JSON value per line (for arrays)
-t, --table Output as a formatted table (for arrays of objects)
--table-style <STYLE> Table style: unicode, ascii, markdown, plain
--color <MODE> Colorize output (auto, always, never)
JSON Patch Operations:
--diff <SRC> <TGT> Generate JSON Patch (RFC 6902) from two files
--patch <FILE> Apply JSON Patch (RFC 6902) to input
--merge <FILE> Apply JSON Merge Patch (RFC 7396) to input
Data Analysis:
--stats Show statistics about the input data
--paths List all paths in the input JSON
--types Show types alongside paths (use with --paths)
--values Show values alongside paths (use with --paths)
Function Discovery:
--list-functions List all available extension functions
--list-category <NAME> List functions in a specific category
--describe <FUNCTION> Show detailed info for a specific function
--search <QUERY> Search functions by name, description, or category
--similar <FUNCTION> Find functions similar to the specified function
Debugging:
--explain Show how an expression is parsed (AST)
--debug Show diagnostic information
--bench [N] Benchmark expression performance
--warmup <N> Warmup iterations before benchmarking
Modes:
-q, --quiet Suppress errors and warnings
-v, --verbose Show expression details and timing
--strict Strict mode - only standard JMESPath (no extensions)
--repl Start interactive REPL mode
--demo <NAME> Load a demo dataset (use with --repl)
Other:
--completions <SHELL> Generate shell completions (bash, zsh, fish, powershell, elvish)
-h, --help Print help
-V, --version Print version
```
## Environment Variables
Configure jpx defaults via environment variables (CLI flags take precedence):
| `JPX_VERBOSE=1` | Enable verbose mode |
| `JPX_QUIET=1` | Enable quiet mode |
| `JPX_STRICT=1` | Enable strict mode (standard JMESPath only) |
| `JPX_RAW=1` | Output raw strings without quotes |
| `JPX_COMPACT=1` | Compact output (no pretty printing) |
```bash
# Set defaults in your shell profile
export JPX_RAW=1 # Always output raw strings
# Temporarily use strict mode
JPX_STRICT=1 jpx 'length(@)' data.json
# Unset to use extensions again
unset JPX_STRICT
jpx 'upper(name)' data.json # Extension functions work
```
## Function Discovery
```bash
# List all available functions grouped by category
# Shows 26 standard JMESPath functions and 400+ extension functions
jpx --list-functions
# List functions in a specific category
jpx --list-category string
jpx --list-category math
jpx --list-category geo
jpx --list-category standard # List all 26 standard JMESPath functions
# Get detailed info about a specific function
# Shows type (standard JMESPath or extension), category, signature, and example
jpx --describe upper
jpx --describe haversine_km
jpx --describe abs # Standard JMESPath function
```
## Examples
### Basic Queries
```bash
# Simple field access
# Array operations
# Nested access
```
### Streaming (NDJSON/JSON Lines)
Process newline-delimited JSON one line at a time with constant memory usage. Perfect for large log files, event streams, and data pipelines.
```bash
# Basic streaming - each line is processed independently
# With raw output for piping to other tools
# From a file
jpx --stream 'id' -f huge_dataset.jsonl
# Using the --each alias
# With expression functions
**Performance**: ~1.25 million lines/second (processes 100k lines in ~80ms)
**How it works**:
- Each line is parsed as a complete JSON object
- Expression is compiled once, reused for all lines
- Results output immediately (no accumulation)
- Empty lines and null results are skipped
- Errors on individual lines don't stop processing (use `-q` to suppress)
**Comparison with `--slurp`**:
- `--slurp` loads all lines into memory as an array, then queries
- `--stream` processes each line independently with constant memory
- Use `--slurp` when you need to aggregate across lines (e.g., `sum([*].value)`)
- Use `--stream` for large files or when lines are independent
### String Functions
```bash
# Case conversion
# String manipulation
```
### Array Functions
```bash
# Get unique values
# Chunk arrays
# Array statistics
```
### Date/Time Functions
```bash
# Current Unix timestamp
# Format a Unix timestamp
# Date arithmetic (add 7 days to timestamp)
```
### Duration Functions
```bash
# Parse human-readable durations
# Format seconds as duration
```
### Color Functions
```bash
# Convert colors
# Color manipulation
```
### Computing Functions
```bash
# Parse byte sizes
# Format bytes
# Bitwise operations
```
### Hash and Encoding Functions
```bash
# Hash functions
# Base64 encoding
# URL encoding
```
### Geo Functions
```bash
# Calculate distance between coordinates (km)
# Calculate bearing
```
### Network Functions
```bash
# IP address operations
```
### Semver Functions
```bash
# Parse semantic versions
# Compare versions
# Check version constraints
```
### Text Analysis Functions
```bash
# Word and character counts
# Reading time estimation
# Word frequencies
```
### Phonetic Functions
```bash
# Soundex encoding
# Check if names sound alike
# Double Metaphone
```
### Fuzzy Matching Functions
```bash
# Levenshtein distance
# Jaro-Winkler similarity
# Sorensen-Dice coefficient
```
### ID Generation Functions
```bash
# Generate UUIDs
# Generate nanoids
# Generate ULIDs
```
### Validation Functions
```bash
# Email validation
# URL validation
# UUID validation
# IP address validation
```
### Expression Functions (Higher-Order)
```bash
# Filter with expression (expression string first, then array)
echo '[{"name": "Alice"}, {"name": "Bob"}]' | jpx 'map_expr(`"name"`, @)'
# ["Alice", "Bob"]
# Group by expression
```
## Using Test Data Files
The `testdata/` directory contains sample JSON files for experimenting:
```bash
# Users data
jpx -f testdata/users.json '[].name'
jpx -f testdata/users.json 'filter_expr(@, &age > `25`) | [].name'
# Server logs
jpx -f testdata/servers.json 'filter_expr(@, &status == `active`) | length(@)'
jpx -f testdata/servers.json '[].{name: name, uptime: format_duration(uptime_seconds)}'
# E-commerce orders
jpx -f testdata/orders.json 'sum([].total)'
jpx -f testdata/orders.json 'group_by_expr(@, &status)'
# Geo locations
jpx -f testdata/locations.json 'haversine_km([0].lat, [0].lon, [1].lat, [1].lon)'
# Versions
jpx -f testdata/packages.json 'sort_by_expr(@, &semver_parse(version).major)'
```
## Using Query Files
For complex queries, you can store the JMESPath expression in a file and use `-Q` / `--query-file`:
```bash
# Create a query file
cat > transform.jmespath << 'EOF'
{
users: @[?active].{
name: name,
email: contact.email,
joined: format_date(created_at, '%Y-%m-%d')
},
total: length(@[?active]),
generated: now()
}
EOF
# Run the query
jpx -Q transform.jmespath -f users.json
```
Benefits of query files:
- Easier to write and edit complex expressions
- Can be version controlled
- Reusable across different data files
- No shell escaping issues
See the `queries/` directory for example query files.
## Tips
- Use `-r` (raw) when piping string output to other commands
- Use `-c` (compact) for single-line JSON output
- Use `--list-functions` to see all available functions
- Backticks create literal values: `` `5` `` is number 5, `` `"hello"` `` is string
- Use `&` prefix for expression references in higher-order functions
## License
MIT OR Apache-2.0