jpath-cli
v0.1.0
Published
Query and extract data from JSON with a simple, powerful path syntax. A focused zero-dependency CLI — jq's little sibling for the 90% case.
Maintainers
Readme
jpath-cli
Query and extract data from JSON with a simple, powerful path syntax. A focused, zero-dependency CLI — jq's little sibling for the 90% case.
Why?
jq is brilliant but its filter language is its own dialect with a steep learning curve. For the vast majority of real work — "give me the name field of every user over 30" — you shouldn't need to reach for a manual. jpath uses an intuitive dot/bracket path you already know from JavaScript, adds a tiny filter syntax, and stays zero-dependency so it installs instantly and audits clean.
Install
npm install -g jpath-cliOr run it directly with npx jpath ... — no install needed.
Quickstart
# Extract a single value
echo '{"user":{"name":"Ada","age":36}}' | jpath .user.name
# "Ada"
# All names from an array
cat users.json | jpath 'users[*].name'
# Filter + extract
cat users.json | jpath 'users[?(@.age >= 18)].name'
# Every "id" at any depth
cat data.json | jpath '..id'
# Pretty table
cat items.json | jpath '[*]' -o table -k id,name,pricePath syntax
| Syntax | Meaning | Example |
|---|---|---|
| .foo | object key foo | .user.name |
| ['foo.bar'] | bracket key (supports dots/spaces) | ['weird.key'] |
| [0] | array index | arr[0] |
| [-1] | last element | arr[-1] |
| [*] | wildcard — all elements / all values | users[*] |
| [1:4] | slice (start inclusive, end exclusive) | arr[1:4] |
| ..key | recursive descent — key at any depth | ..id |
| [?(expr)] | filter — keep matching elements | [?(@.price > 10)] |
A leading $ (root) is accepted and ignored: $.user.name ≡ .user.name.
Filter expressions
Inside [?(...)], use @ to refer to the current element:
| Expression | Matches when… |
|---|---|
| @.active | active is truthy |
| [email protected] | deleted is falsy |
| @.age > 30 | numeric comparison (>=, <, <=, ==, !=) |
| @.name == 'Ada' | equality (loose: "10" == 10) |
| @.tags contains 'go' | array/string contains |
| @.name startsWith 'A' | string prefix |
| @.name =~ /^A/i | regex match (/pattern/flags) |
| @.id in [1,2,3] | membership |
Combine with the element path to pull a field: users[?(@.age > 30)].name.
Output formats (-o, --output)
| Format | Description |
|---|---|
| json | Pretty JSON (default) |
| compact | Minified JSON |
| jsonl | Newline-delimited (one JSON per array item) |
| raw | Raw scalar (no quotes) |
| table | Aligned columns (-k id,name to choose) |
| keys | List object keys / array indices |
| count | Length of the result |
Options
-o, --output <fmt> output format
-k, --keys <a,b> columns for table output
-i, --indent <n> JSON indent (default 2)
-r, --raw shortcut for -o raw
--null-as <str> emit this string when the result is null/undefined
-v, --version print version
-h, --help show help
--demo run a built-in demoRecipes
# Names of active users, one per line
jpath 'users[?(@.active)].name' data.json -o jsonl
# In-stock products, tabular
jpath 'products[?(@.stock > 0)]' data.json -o table -k sku,name,price
# Count comments on a post
jpath 'post.comments[*]' data.json -o count
# Pull every URL out of a deeply-nested config
jpath '..url' config.json -o jsonl
# Last 3 log entries
jpath 'logs[-3:]' app.json
# Raw scalar for scripting
PRICE=$(jpath '.price' quote.json -r)As a library
const { evaluate } = require('jpath');
const data = { users: [{ age: 30 }, { age: 40 }] };
const over30 = evaluate('users[?(@.age > 30)]', data);
// [{ age: 40 }]Design notes
- Zero dependencies. Pure Node.js, no install-time risk, fast cold start.
- Safe by construction. Filter expressions are parsed by a small hand-written evaluator — no
eval(), ever. Untrusted JSON is safe to query. - Predictable missing values. A missing key or out-of-range index yields
undefinedand a silent exit — ideal for pipelines.
License
MIT © venture
