| name | query |
| description | Query structured data (JSON, JSONL, TOML, YAML, XML, CSV, Markdown) using jq, mdq, and yq. Use instead of grep/cat/sed for structured files. |
Structured Query Tools
Query structured data instead of dumping it into context. Three tools, one per format family.
jq — JSON and JSONL
jq '.field' file.json
jq '.parent.child' file.json
jq -r '.[] | .name' file.json
cat log.jsonl | jq 'select(.level == "ERROR")'
jq '{name: .name, cost: .cost_usd}' file.json
cat log.jsonl | jq -s 'length'
jq -s 'sort_by(.cost_usd) | reverse | .[:5]' file.jsonl
Never grep JSONL — lines are multi-KB JSON blobs. Always use jq.
mdq — Markdown
mdq '# Section Name' file.md
mdq '## Parent > ### Child' file.md
mdq '# Section > list' file.md
mdq '# Section > code' file.md
mdq '# Section > table' file.md
Use instead of cat for large markdown files. Extract just the section you need.
mdq selects sections, not headings. mdq '# Foo' returns the heading AND all its content.
yq — TOML, YAML, XML, CSV, and more
yq auto-detects format from file extensions. No -p flag needed for .toml, .yaml, .yml, .xml, .csv files.
yq '.section.key' file.toml
yq -oy '.' file.toml
yq -oj '.' file.toml
yq '.key' file.yaml
yq '.items[0].name' file.yaml
yq '.root.element' file.xml
yq '.[0]' file.csv
yq 'keys' file.toml
yq '.section | keys' file.toml
yq '.agents[] | select(.id == "myagent")' file.toml
yq -o json file.toml
yq -o toml file.yaml
cat something | yq -p toml '.key'
Supported formats: YAML, JSON, TOML, XML, CSV, TSV, HCL, properties, base64, URI, shell, Lua, INI.
Output format flag: -oy (YAML), -oj (JSON), -ot (TOML), -ox (XML).
Input format flag (-p): Only needed when piping or reading files with non-standard extensions.
When to use what
| Data format | Tool | Notes |
|---|
.json, .jsonl | jq | Pipe JSONL, don't load whole file |
.md | mdq | Query by heading structure |
.toml | yq | Config files, foci.toml |
.yaml, .yml | yq | Docker compose, k8s, etc. |
.xml | yq | |
.csv | yq | |
Philosophy
Structured queries beat line numbers. Line numbers change on edits; section titles and keys usually don't. You can guess or fuzzy-match headings and keys when you can't guess line numbers.
Optimistic pattern: Try the key you expect, fall back to listing keys:
yq '.agents[0].thinking' file.toml || yq '.agents[0] | keys' file.toml