DevLogTechnical writing
Tutorials

jq: Slice, Filter, and Transform Any JSON from the Terminal

October 24, 2026

JSON is the common tongue of APIs, configs, and logs, and every developer has stood in front of a wall of it wondering: what's actually in this response? jq answers that in one command. Its README calls it "sed, awk, grep and friends for JSON" — a purpose-built tool that slices, filters, maps, and reshapes structured data. It first appeared in 2012, designed by Stephen Dolan (the original implementation was in Haskell, later ported to C). It is written in portable C, has zero runtime dependencies, and is MIT-licensed, which means one small binary that runs anywhere.

Here's the part that surprises people: the tool many assumed was dead is quietly thriving. After jq 1.6 shipped in November 2018, the project went silent for five years. Then, in September 2023, it came back — a revitalized jqlang GitHub organization, new maintainers, and the long-awaited 1.7 release. The new pace has held: 1.7.1 in December 2023 (fixing CVE-2023-50246 and CVE-2023-50268), 1.8.0 in June 2025, 1.8.1 in July 2025, and 1.8.2 in June 2026, which added Windows arm64 builds. The repo passes roughly 35,000 stars.

Getting it takes seconds. Debian/Ubuntu: sudo apt-get install jq. Fedora: sudo dnf install jq. macOS: brew install jq. Windows: winget install jqlang.jq. Or download a standalone prebuilt binary for Linux, macOS, or Windows and just run it.

The mental model is one idea: filters. jq reads a stream of whitespace-separated JSON values and runs your program once per value, so newline-delimited JSON (JSON Lines) works with zero setup. . is the identity filter. .field plucks a key. .[] fans an array out into a stream. | composes. That's most of the language:

$ echo '{"repo":"jq","issues":[{"title":"Slow startup","labels":["bug"]},
  {"title":"Docs typo","labels":["docs"]}]}' | jq '.issues[].title'
"Slow startup"
"Docs typo"

$ echo '<same input>' | jq '.issues | map(.title)'
["Slow startup","Docs typo"]

map(f) is just shorthand for [.[] | f], and select(cond) keeps only the items that pass — .issues[] | select(.title | contains("typo")) returns the Docs typo object. Now point it at a real API. GitHub's REST endpoint for a repository returns full_name, language, stargazers_count, and forks_count, so this is all it takes:

$ curl -s https://api.github.com/repos/jqlang/jq | \
    jq '{full_name, language, stargazers_count, forks_count}'

Four flags cover most everyday needs: -r prints strings without quotes, -c keeps each result on one line (pairs beautifully with grep), -s slurps the whole stream into one array, and -n builds JSON from nothing — handy for generating config. Add --arg to inject shell variables and "\(.field)" interpolation inside strings, and you can assemble almost any shape.

If you're learning now, you're catching the tool at a good moment. The 1.8 line added genuinely useful functions: trim, ltrim, rtrim, and trimstr for whitespace (the release notes demo "foobarfoo" | trimstr("foo") returning "bar"), plus add/1 and skip/2. Error messages now point at the exact offending column, and the maximum parse depth jumped to 10,000. The series also switched to 1.X.Y versioning, which says something about the project's confidence.

Want to play before installing? The official playground at play.jqlang.org runs jq in your browser via WebAssembly, processes your JSON locally, and lets you share snippets. The tutorial at jqlang.org/tutorial walks through a real session, and the manual at jqlang.org/manual is exhaustive. Ten minutes now will pay off in every pipeline you write from here on.

← More Tutorials