Readme
toonq — jq for TOON
CLI tool for querying, filtering, inspecting, and converting TOON (Token-Oriented Object Notation) files — the equivalent of jq for TOON data. Built on jaq , a Rust reimplementation of jq — see Differences from jq for limitations.
toonq - f ' . [ ] | select ( . close > 10000 ) | { date, close} ' data. toon
toonq - - extract close data. toon
toonq - - slurp - - count session. jsonl
toonq - n - f ' [ range ( 5 ) ] ' # generate without input
toonq - f ' . [ ] | select ( . age > $min ) ' - - argjson min 21 data. toon
Installation
cargo install toonq
No external dependencies. Everything (jaq engine, TOON parser, JSONL support) is compiled into the binary.
Quick start
# Inspect
toonq --head 5 data.toon # First 5 records
toonq --count data.toon # How many records?
toonq --schema data.toon # What fields and types?
toonq --stats data.toon # TOON vs JSON size comparison
# Query with jq syntax (via jaq engine)
toonq -f '.[] | select(.close > 100)' data.toon
toonq -f 'sort_by(-.sharpe) | .[0:5]' metrics.toon
# Extract fields (one call for all records)
toonq --extract text chat.json # All messages
toonq --extract "0,2,8" chat.json # Specific indices
# JSONL support
toonq --slurp --count data.jsonl # Parse line-delimited JSON
toonq --slurp --truncate 80 --head 3 data.jsonl # With truncation
# Convert
toonq --to json data.toon
toonq --from json data.json
# Pipeline
cat data.toon | toonq -f '.[0:10]' | toonq --stats
Features
Inspection
Flag
Description
--head N
First N records
--tail N
Last N records
--count
Record count
--schema
Field names and types
--stats
Token statistics (TOON vs JSON savings)
--truncate N
Truncate string fields to N chars
Queries
- f / - - filter accepts jq syntax via the jaq engine (not 100% jq — see differences ):
toonq - f ' .[] | select(.close > 100)' data.toon
toonq - f ' sort_by(-.date) | .[0:5] | {date, close}' data.toon
toonq - f ' group_by(.currency) | .[] | {currency: .[0].currency, count: length}' portfolio.toon
Variables (--arg , --argjson )
Pass values into filters via named variables:
# --arg: string value
toonq -f '.[] | select(.name == $target)' --arg target alice data.toon
# --argjson: parsed JSON (numbers, arrays, objects)
toonq -f '.[] | select(.age > $min)' --argjson min 21 data.toon
toonq -f '. + $extra' --argjson extra '[4,5,6]' data.toon
# Multiple variables
toonq -f '.[] | select(.age > $min and .role == $role)' \
--argjson min 21 --arg role admin data.toon
Run the filter once with null as input — no file needed. Useful for generating data:
toonq - n - f ' [range(5)]' # [0,1,2,3,4]
toonq -n -f '$greeting + ", world!"' --arg greeting Hello -r
Raw output (- r)
Print string results without quotes, one per line. Non-string values stay compact JSON:
toonq - f ' .[].name' - r data.toon # alice
# bob
toonq -f '.[].price' -r data.toon # 100.5
With multiple files, the first is the filter input (. ), the rest are available via input /inputs :
toonq - f ' . + inputs' a.json b.json # concatenate arrays
toonq -f '[inputs]' a.json b.json # collect extras into array
--extract pulls values by field name or array index:
toonq -- extract close data.toon # All close prices
toonq --extract role chat.json # All roles
toonq --extract 0 chat.json # First record
toonq --extract "0,2,8" chat.json # Multiple records by index
JSONL support
--slurp reads line-delimited JSON as an array. Auto-detected when JSON parsing fails:
toonq -- slurp -- count data.jsonl
toonq -- from json -- count data.jsonl # Auto-detect
Flag
Description
--to json
Output as pretty-printed JSON
--to toon
Output as TOON (default)
--to raw
Compact JSON for pipelines
--from json
Read JSON input
--from auto
Auto-detect by file extension
Pipelines
toonq - f ' filter' data.toon | toonq -- head 3
toonq -- to json data.toon | jq ' . | length'
cat data.toon | toonq -- count
Differences from jq
toonq uses jaq , not the original jq (C). Modern jaq (3.x) implements nearly all of the jq language:
Feature
jq
jaq / toonq
Basic syntax (pipe, select, map, sort_by, group_by)
✅
✅
Object/array indexing and slicing
✅
✅
Variable binding (as $x )
✅
✅
External variables (--arg , --argjson )
✅
✅
Null input (- n)
✅
✅
Raw output (- r)
✅
✅
Multiple inputs (input , inputs )
✅
✅
try / catch
✅
✅
foreach
✅
✅
walk
✅
✅
transpose
✅
✅
@ csv, @ tsv, @ json format strings
✅
✅
Format strings (" \(.x)" )
❌
✅ (jaq extension)
Modules (include , import from file)
✅
❌
input_filename
✅
❌
The only notable gaps are module loading from external files and input_filename (jaq implements the latter only in its CLI, not in the embedded library).
Full list: jaq differences from jq .
How it works
TOON → serde_toon → jaq- all ( native lib) → serde_toon → TOON
TOON parser jq- compatible engine TOON encoder
toonq uses jaq-all — the same engine that powers the jaq binary — directly in-process. No subprocess, no JSON roundtrip, no runtime dependencies. See docs/serde-research.md for the architectural deep-dive.
Documentation
License
ISC