jpx - JMESPath CLI with Extended Functions
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 - The query language specification created by James Saryerwinnie
- jmespath.rs - The Rust implementation by @mtdowling that provides our parsing, evaluation, and standard functions
- 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 or the jmespath crate directly.
jpx vs jq
Coming from jq? Here's a quick comparison:
| jq | jpx | |
|---|---|---|
| Language | Custom DSL | JMESPath (standardized) |
| Functions | ~70 built-in | 400+ extensions |
| Ecosystem | Standalone | Works with AWS CLI, Ansible |
| Streaming | ✅ | ❌ |
# jq # jpx
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.
Quick Start (Docker)
Try jpx instantly without installing anything:
# Fetch a Hacker News story and extract fields
| \
# {"by": "pg", "score": 57, "title": "Y Combinator"}
# Basic query
|
# "Alice"
# Calculate average
|
# 85.0
# String manipulation
|
# "HELLO WORLD"
# Filter and transform
|
# ["alice"]
Installation
# Docker (no install needed)
# Homebrew (macOS/Linux)
# Pre-built binaries (macOS, Linux, Windows)
# Download from https://github.com/joshrotenberg/jmespath-extensions/releases
# From crates.io
# From source
# Without MCP server support (smaller binary)
MCP Server (AI Assistant Integration)
jpx can run as an MCP (Model Context Protocol) server, allowing AI assistants like Claude to use JMESPath for JSON querying and transformation.
Building with MCP Support
MCP support is included by default. Simply build:
To build without MCP support (smaller binary):
Running the Server
MCP Tools (17 total)
Discovery - Find and explore functionality:
| Tool | Description |
|---|---|
search |
Fuzzy search functions by name, description, category, or signature |
similar |
Find functions related to a specified function |
functions |
List available functions (with optional category filter) |
describe |
Get detailed info for a specific function |
categories |
List all function categories |
Data Analysis - Understand JSON structure:
| Tool | Description |
|---|---|
stats |
Analyze JSON structure (type, size, depth, field analysis) |
paths |
Extract all paths in dot notation (e.g., users[0].name) |
keys |
Extract object keys (optionally recursive with dot notation) |
Querying - Evaluate expressions:
| Tool | Description |
|---|---|
evaluate |
Run JMESPath expressions against JSON input |
evaluate_file |
Query JSON files directly from disk (with security checks) |
batch_evaluate |
Run multiple expressions against the same input |
validate |
Check expression syntax without executing |
JSON Utilities - Transform and manipulate:
| Tool | Description |
|---|---|
format |
Pretty-print JSON with configurable indentation |
diff |
Generate RFC 6902 JSON Patch between two documents |
patch |
Apply RFC 6902 JSON Patch operations |
merge |
Apply RFC 7396 JSON Merge Patch |
Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
Or use Docker with the dedicated server image (no installation required):
You can also use the CLI image with the mcp subcommand:
Example Usage
Once configured, Claude can use jpx to query JSON data:
User: I have this JSON: {"users": [{"name": "alice", "age": 30}, {"name": "bob", "age": 25}]}
Get the names of users over 28.
Claude: [Uses jpx.evaluate with expression "users[?age > `28`].name"]
Result: ["alice"]
More MCP Examples
Query a file directly:
Claude: [Uses jpx.evaluate_file with file_path="/data/users.json", expression="users[*].email"]
Batch multiple queries:
Claude: [Uses jpx.batch_evaluate with input and expressions=["length(users)", "users[0].name", "max(users[*].age)"]]
Result: {results: [{expression: "length(users)", result: 10}, ...]}
Compare JSON documents (RFC 6902):
Claude: [Uses jpx.diff with source and target documents]
Result: [{"op": "replace", "path": "/name", "value": "bob"}, {"op": "add", "path": "/age", "value": 30}]
Explore JSON structure:
Claude: [Uses jpx.keys with input and recursive=true]
Result: ["user", "user.name", "user.profile", "user.profile.settings"]
Usage
) )
) )
)
)
Environment Variables
Configure jpx defaults via environment variables (CLI flags take precedence):
| Variable | Description |
|---|---|
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) |
# Set defaults in your shell profile
# Always output raw strings
# Temporarily use strict mode
JPX_STRICT=1
# Unset to use extensions again
Function Discovery
# List all available functions grouped by category
# Shows 26 standard JMESPath functions and 400+ extension functions
# List functions in a specific category
# Get detailed info about a specific function
# Shows type (standard JMESPath or extension), category, signature, and example
Examples
Basic Queries
# Simple field access
|
# "Alice"
# Array operations
|
# 15.0
# Nested access
|
# "alice@example.com"
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.
# Basic streaming - each line is processed independently
|
# With raw output for piping to other tools
| |
# From a file
# 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
-qto suppress)
Comparison with --slurp:
--slurploads all lines into memory as an array, then queries--streamprocesses each line independently with constant memory- Use
--slurpwhen you need to aggregate across lines (e.g.,sum([*].value)) - Use
--streamfor large files or when lines are independent
String Functions
# Case conversion
|
# "HELLO WORLD"
|
# "hello_world"
# String manipulation
|
# trim me
|
# hello, world
Array Functions
# Get unique values
|
# [1, 2, 3]
# Chunk arrays
|
# [[1, 2], [3, 4], [5, 6]]
# Array statistics
|
# 30.0
|
# 14.142135623730951
Date/Time Functions
# Current Unix timestamp
|
# 1705312200.0
# Format a Unix timestamp
|
# 2024-01-15
# Date arithmetic (add 7 days to timestamp)
|
# 1705881600.0
Duration Functions
# Parse human-readable durations
|
# 5400.0
|
# 60.0
# Format seconds as duration
|
# 1h2m5s
Color Functions
# Convert colors
|
# {"r": 255, "g": 85, "b": 0}
|
# #ff8000
# Color manipulation
|
# #5c85d6
|
# #00ffff
Computing Functions
# Parse byte sizes
|
# 1500000000.0
# Format bytes
|
# 1.00 GiB
# Bitwise operations
|
# 8
|
# 16
Hash and Encoding Functions
# Hash functions
|
# 5d41402abc4b2a76b9719d911017c592
|
# 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
# Base64 encoding
|
# aGVsbG8gd29ybGQ=
# URL encoding
|
# hello%20world%20%26%20more
Geo Functions
# Calculate distance between coordinates (km)
|
# 3935.746...
# Calculate bearing
|
# 273.687...
Network Functions
# IP address operations
|
# 3232235777
|
# true
|
# true
Semver Functions
# Parse semantic versions
|
# {"major": 1, "minor": 2, "patch": 3, "prerelease": "beta.1", "build": null}
# Compare versions
|
# -1
# Check version constraints
|
# true
Text Analysis Functions
# Word and character counts
|
# 6
|
# 12
# Reading time estimation
|
# "1 min read"
# Word frequencies
|
# {"the": 3, "quick": 1, "brown": 1, ...}
Phonetic Functions
# Soundex encoding
|
# R163
# Check if names sound alike
|
# true
# Double Metaphone
|
# {"primary": "SM0", "secondary": "XMT"}
Fuzzy Matching Functions
# Levenshtein distance
|
# 3
# Jaro-Winkler similarity
|
# 0.961...
# Sorensen-Dice coefficient
|
# 0.25
ID Generation Functions
# Generate UUIDs
|
# 550e8400-e29b-41d4-a716-446655440000
# Generate nanoids
|
# V1StGXR8_Z5jdHi6B-myT
# Generate ULIDs
|
# 01ARZ3NDEKTSV4RRFFQ69G5FAV
Validation Functions
# Email validation
|
# true
# URL validation
|
# true
# UUID validation
|
# true
# IP address validation
|
# true
Expression Functions (Higher-Order)
# Filter with expression (expression string first, then array)
|
# [{"age": 25}, {"age": 30}]
# Map with expression (extract field from each object)
|
# ["Alice", "Bob"]
# Group by expression
|
# {"a": [{"type": "a", "v": 1}, {"type": "a", "v": 3}], "b": [{"type": "b", "v": 2}]}
Using Test Data Files
The testdata/ directory contains sample JSON files for experimenting:
# Users data
# Server logs
# E-commerce orders
# Geo locations
# Versions
Using Query Files
For complex queries, you can store the JMESPath expression in a file and use -Q / --query-file:
# Create a query file
# Run the query
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-functionsto 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