Bash JSON Viewer β€” jless & JQ_COLORS Guide

Β·Platform EngineerΒ·Reviewed byNadia OkonkwoΒ·Published

Use the free online JSON Pretty Print directly in your browser β€” no install required.

Try JSON Pretty Print Online β†’

When you need a bash JSON viewer for interactive exploration rather than scripting, the standard jq . pipe falls short β€” output scrolls past the top of the terminal and you have no way to navigate back through a 300-line API response. This guide covers tools built specifically for viewing JSON interactively in the terminal: jless (collapsible tree with vim-key navigation), JQ_COLORS custom color themes, jq -C | less -R colorized paging, shell aliases for daily use, and fx as a Node.js alternative. For scripting, CI/CD, and validation workflows, see the companion Format JSON in Bash guide. For a zero-install browser viewer, the JSON Pretty Print tool works instantly. Examples are tested on Bash 5.x (macOS via Homebrew, Ubuntu 22.04+) and are compatible with Bash 3.2+ (macOS system shell).

Key Takeaways
  • β€’ jless β€” the best interactive JSON viewer for the terminal: collapsible tree, vim-keys, incremental search
  • β€’ jq -C . | less -R β€” colorized scrollable pager with no extra install beyond jq
  • β€’ JQ_COLORS β€” env variable that customizes jq's ANSI color scheme for every JSON type
  • β€’ fx β€” interactive Node.js JSON viewer with mouse support and JavaScript filter expressions
  • β€’ alias jv='jless' β€” a one-word command makes interactive viewing a muscle memory habit

Interactive vs. Scripted JSON Viewing

Piping JSON to jq . is the right choice when you want formatted output for a small payload, or when the result feeds into another command. It is the wrong choice when you need to explore a 200-field API response β€” the output flies past the terminal window and leaves you with no way to navigate, collapse sections, or search for a specific field without re-running the command with a filter. Interactive JSON viewers render the same formatted, colorized output inside a persistent pager where you control navigation. The data is identical; the difference is the interface.

Before Β· Bash
After Β· Bash
# jq . β€” output scrolls off screen for large responses
curl -s https://api.github.com/users/torvalds | jq .
# 300+ lines scroll past β€” you lose context immediately
# jless β€” opens an interactive pager, nothing scrolls off
curl -s https://api.github.com/users/torvalds | jless
# Full document visible, collapsible, searchable with j/k/h/l
Note:Interactive viewers are for human inspection only β€” they should never appear in scripts, CI pipelines, or automation. For programmatic JSON processing, use jq with explicit filters and exit code handling. The Format JSON in Bash guide covers those scripting patterns.

jless β€” Interactive JSON Viewer

jless is a purpose-built terminal JSON viewer. Unlike a plain jq pipe, it renders the document as a persistent collapsible tree: every object and array can be expanded or collapsed independently with l and h, navigation uses vim-style keys, and incremental search finds any key or value instantly. It streams input incrementally, so it opens large files and API responses in under a second regardless of size β€” where jq buffers the entire document before displaying anything. I reach for jless as the first tool whenever an API response is too large to scan at a glance.

Installation

Bash
# macOS
brew install jless

# Linux β€” prebuilt binary from GitHub Releases
curl -sL https://github.com/PaulJuliusMartinez/jless/releases/latest/download/jless-x86_64-unknown-linux-gnu.tar.gz \
  | tar xz
sudo mv jless /usr/local/bin/

# Verify
jless --version

Basic usage

Bash
# Open a local file β€” interactive tree viewer launches immediately
jless api-response.json

# Pipe any JSON stream directly into jless
curl -s https://api.github.com/users/torvalds | jless

# Open with all nodes collapsed to top level (useful starting point for large documents)
jless --mode line api-response.json

# Load a specific array element and view it in isolation
jq '.[0]' deployments.json | jless

Navigation and search in practice

Bash
# Inside jless:
#
#   j / ↓        move down
#   k / ↑        move up
#   l / β†’        expand node (or Enter)
#   h / ←        collapse node
#   H            collapse current + all siblings β†’ high-level overview
#   L            expand everything recursively
#
#   /            start forward search β€” type a key name and press Enter
#   n / N        next / previous search match
#
#   g / gg       jump to start
#   G            jump to end
#   q            quit

jless Keyboard Shortcuts Reference

All shortcuts are available immediately after opening jless β€” no configuration required. The navigation model is intentionally identical to vim so existing muscle memory transfers.

Key
Action
When to Use
j / ↓
Move cursor down one line
Scanning through object keys or array items
k / ↑
Move cursor up one line
Moving back to a previous field
J
Move down 5 lines
Faster scrolling through long arrays
K
Move up 5 lines
Faster upward navigation
h / ← / -
Collapse the current node
Hiding a large nested object to reduce noise
l / β†’ / +
Expand the current node
Opening a collapsed object or array
H
Collapse current node and all siblings
Getting a top-level overview of the structure
L
Expand all nodes recursively
Revealing the full depth of a nested structure
g
Jump to the start of the document
Returning to the root quickly
G
Jump to the end of the document
Jumping to the last element in a large array
/
Start a forward search
Finding a specific key or value in the document
?
Start a backward search
Searching upward from the current position
n
Jump to next search match
Cycling through all occurrences of a search term
N
Jump to previous search match
Stepping backward through search results
q
Quit jless
Exiting after inspection is complete

jq -C | less -R β€” Colorized Paging Without Extra Tools

If jless is not installed and you need a scrollable, colorized view of a JSON response, jq -C . | less -R is a capable fallback. The -C flag forces ANSI color codes even when stdout is a pipe (normally jq strips them), and -R tells less to render those codes instead of printing them as literal text. The result is a fully colorized, scrollable document β€” without the interactive tree structure of jless. Navigation inside less uses arrow keys or vim-style j/k, and /triggers less's built-in text search.

Bash
# Basic colorized pager
jq -C . response.json | less -R

# From a curl response β€” -s prevents progress bar from corrupting the JSON stream
curl -s https://api.github.com/repos/jqlang/jq | jq -C . | less -R

# Sort keys for easier visual scanning, then page
jq -CS . config.json | less -R
# -C = force color, -S = sort keys (both flags combined)

# Add an alias so you never have to type the full pipe again
alias jqv='jq -C . | less -R'
# Usage: cat response.json | jqv
#    or: curl -s https://api.example.com/status | jqv
Note:jq -C | less -R buffers the entire formatted output before less can display it. On a 200 MB file this means waiting several seconds and consuming significant memory β€” the same limitation as plain jq .. For large files, use jless instead, which streams incrementally.

JQ_COLORS β€” Custom Color Themes

JQ_COLORSis an environment variable that overrides jq's default ANSI color scheme. It takes a colon-separated string of seven ANSI attribute;color codes, one per JSON type in this fixed order: null : false : true : numbers : strings : arrays : objects. Each code is in the format attribute;color where attribute is 0 (normal), 1 (bold), 2 (dim), or 4 (underline), and color is a standard ANSI color number (30–37 = standard, 90–97 = bright).

Bash
# ANSI color reference for building JQ_COLORS:
#   Attributes:  0=normal  1=bold  2=dim  4=underline
#   Colors:      30=black  31=red  32=green  33=yellow
#                34=blue   35=magenta  36=cyan  37=white
#   Bright:      90=bright-black  91=bright-red  92=bright-green  93=bright-yellow
#                94=bright-blue  95=bright-magenta  96=bright-cyan  97=bright-white
#
# Order: null : false : true : numbers : strings : arrays : objects

# High-contrast theme for dark terminals (recommended)
export JQ_COLORS="1;30:0;91:0;92:0;93:0;32:1;96:1;96"
# null=dim-gray, false=bright-red, true=bright-green,
# numbers=bright-yellow, strings=green, arrays=bold-cyan, objects=bold-cyan

# Solarized-style theme
export JQ_COLORS="2;37:0;35:0;35:0;36:0;33:1;34:1;34"
# null=dim-white, false=magenta, true=magenta,
# numbers=cyan, strings=yellow, arrays=bold-blue, objects=bold-blue

# Minimal (bold keys only, everything else plain)
export JQ_COLORS="0;90:0;39:0;39:0;39:0;39:1;39:1;39"
Bash
# Add your chosen theme to ~/.bashrc or ~/.zshrc so it applies to every jq call
echo 'export JQ_COLORS="1;30:0;91:0;92:0;93:0;32:1;96:1;96"' >> ~/.bashrc
source ~/.bashrc

# Test the theme
echo '{"active":true,"errors":null,"count":42,"tags":["api","v2"],"meta":{"version":"1.0"}}' | jq .
Warning:JQ_COLORS must have exactly seven colon-separated values. If the string has fewer segments, jq silently falls back to its built-in defaults without any error message β€” making misconfiguration hard to diagnose. Always test a new color string on a short JSON payload before adding it to your shell profile.

Shell Aliases for Daily JSON Viewing

The commands for interactive JSON viewing are verbose by default. A small set of aliases in ~/.bashrc or ~/.zshrc makes jless and colorized paging single-word commands that integrate naturally into any workflow. The aliases below compose β€” jv and jvp both accept piped input or a filename as the first argument.

Bash
# Add to ~/.bashrc or ~/.zshrc

# jv β€” interactive viewer (jless if available, colorized pager fallback)
jv() {
  if command -v jless &>/dev/null; then
    jless "$@"
  else
    jq -C . "$@" | less -R
  fi
}

# jvp β€” view with keys sorted alphabetically (useful for comparing responses)
alias jvp='jq -CS . | less -R'

# jvc β€” view from clipboard (macOS)
alias jvc='pbpaste | jless'

# jvf β€” view and filter: jvf '.users[0]' response.json
jvf() {
  local filter="$1"; shift
  jq -C "$filter" "$@" | less -R
}

# Reload without restarting terminal
source ~/.bashrc
Bash
# Usage examples after adding aliases above

# View any file or piped response
jv deployment-config.json
curl -s https://api.github.com/users/torvalds | jv

# View sorted (easy to scan alphabetically)
cat feature-flags.json | jvp

# Drill into a sub-document interactively
jvf '.database' infra/app-config.json
jvf '.users[] | select(.role == "admin")' users.json

bat β€” Syntax-Highlighted JSON File Viewing

bat is a cat replacement with syntax highlighting, line numbers, and a built-in pager. For JSON files on disk it provides a clean, editor-style reading experience without opening a full text editor. Unlike jless, bat renders the file as static text β€” no collapse, no search, no navigation beyond scrolling. Its strength is visual clarity for medium-sized static files (configs, fixtures, test payloads) where you want syntax color and line numbers but do not need interactive tree navigation.

Bash
# macOS
brew install bat

# Debian / Ubuntu (binary may be named batcat)
apt-get install -y bat
# alias bat=batcat   # add to ~/.bashrc if needed on Ubuntu

# View a JSON file with syntax highlighting and line numbers
bat config/feature-flags.json

# Disable pager β€” print directly to terminal (useful in scripts)
bat --paging=never api-response.json

# Combine with jq: format with jq, view with bat (preserves bat's JSON highlighting)
jq '.' response.json | bat --language=json --paging=never
Note:Use bat for reading static config files and test fixtures where line numbers matter (e.g., when a test failure references line 47 of a fixture file). For API responses and dynamic JSON from curl, jless is faster to open and more practical to navigate. If you need to view in the browser and share with a colleague, paste directly into the JSON Pretty Print tool β€” no terminal required.

fx β€” Interactive Node.js JSON Explorer

fx is an interactive JSON viewer built on Node.js. Its interface is similar to jless β€” collapsible tree, keyboard navigation, search β€” but it adds two features jless lacks: mouse support (click to expand/collapse nodes) and the ability to type a JavaScript expression in the bottom bar to filter the document in real time. For teams already running Node.js, fx is a natural fit and requires no separate binary. For pure terminal environments without Node, jless is the leaner choice.

Bash
# Install globally via npm
npm install -g fx

# Or run without installing (npx caches the package)
curl -s https://api.github.com/users/torvalds | npx fx

# Basic interactive use
fx api-response.json
curl -s https://api.github.com/repos/jqlang/jq | fx

# In fx: arrow keys navigate, Enter expands/collapses, / searches
# Bottom bar accepts JavaScript expressions for live filtering:
#   .name           β†’ show only the "name" field
#   .repos.slice(0,5) β†’ first 5 repos
Bash
# fx also works as a non-interactive formatter (like jq . but with JS syntax)
# Pass a JavaScript expression as argument β€” no interactive mode
echo '{"users":[{"id":1,"name":"Sarah Chen"},{"id":2,"name":"Marcus Osei"}]}' \
  | fx '.users[0].name'
# Sarah Chen

# Chain with map for array transformations
cat deployments.json | fx '.items.map(d => ({id: d.deploy_id, status: d.state}))'

Common Mistakes

These four mistakes come up repeatedly when developers first start using terminal JSON viewers β€” each one has a clear fix once you understand why it happens.

❌ Using jq . to view large responses (output scrolls off screen)

Problem: jq . dumps all output to stdout at once. For responses longer than your terminal height, everything above the last screenful is gone β€” you cannot scroll back to the beginning or navigate to a specific field.

Fix: Pipe to jless for interactive navigation, or use jq -C . | less -R as a fallback. Both keep the full document accessible regardless of its size.

Before Β· Bash
After Β· Bash
# 300-line API response β€” top 280 lines immediately scroll off
curl -s https://api.github.com/users/torvalds | jq .
# Only the bottom of the output is visible β€” cannot navigate back
# Full document stays accessible in jless β€” nothing is lost
curl -s https://api.github.com/users/torvalds | jless
# j/k to scroll, h/l to collapse/expand, / to search
❌ Setting JQ_COLORS with the wrong number of segments

Problem: JQ_COLORS requires exactly seven colon-separated values. If the string has six or eight values, jq silently ignores the entire variable and falls back to its compiled-in defaults β€” no warning, no error, just the wrong colors.

Fix: Count the colons: a valid JQ_COLORS string has exactly six colons and seven values. Echo the variable and pipe to tr to count.

Before Β· Bash
After Β· Bash
# Only 6 values β€” jq silently uses defaults, no indication of why
export JQ_COLORS="1;30:0;91:0;92:0;93:0;32:1;96"
echo '{"ok":true}' | jq .  # colors unchanged β€” no error shown
# Exactly 7 values β€” 6 colons
export JQ_COLORS="1;30:0;91:0;92:0;93:0;32:1;96:1;96"

# Verify the count before adding to shell profile
echo "$JQ_COLORS" | tr -cd ':' | wc -c   # must output 6
❌ Piping jless or fx output into another command

Problem: jless and fx render their interactive interface to the terminal (a TTY), not to stdout. Piping them into grep, tee, or any other command produces garbled ANSI escape codes or empty output β€” the viewer's interactive output is not designed to be consumed by other programs.

Fix: Use jq with an explicit filter to extract data programmatically. Use jless and fx only as the final step in a pipeline when a human is reading the output.

Before Β· Bash
After Β· Bash
# jless output is for human eyes β€” piping it produces garbage
jless response.json | grep "request_id"
# Output: ANSI escape codes and cursor sequences, not clean text
# Use jq for programmatic extraction β€” clean, composable
jq -r '.request_id' response.json | grep "req_"

# Use jless only as the terminal endpoint β€” nothing after it
jless response.json
❌ Using jq -C without less -R (color codes print as literal text)

Problem: -C forces ANSI color codes into the output stream. When that stream is printed directly to a terminal that is not in raw mode β€” or piped to a tool that does not interpret ANSI β€” the escape sequences appear as literal characters like ^[[1;34m cluttering the output.

Fix: Always pair jq -C with less -R. The -R flag puts less into raw-input mode, telling it to render ANSI sequences as colors instead of printing them as text.

Before Β· Bash
After Β· Bash
# -C without -R: escape sequences print as raw text
jq -C . response.json | less
# Output: ^[[1;34m"status"^[[0m: ^[[0;32m"ok"^[[0m ...
# -C with -R: ANSI codes are rendered as actual colors
jq -C . response.json | less -R
# Output: colorized JSON, clean and readable

jless vs jq vs bat vs fx β€” Interactive Viewer Comparison

All four tools render colorized JSON, but their interactive capabilities differ significantly. Choose based on whether you need collapsible navigation, search, or mouse support β€” and whether Node.js is already in your environment.

Tool
Interactive Nav
Search
Collapsible
Color
Large Files
Install
jless
βœ… vim-keys
βœ… (/, n, N)
βœ… (h/l keys)
βœ… (built-in)
βœ… (streaming)
brew / binary
jq -C | less -R
⚠️ (less only)
βœ… (/ in less)
❌
βœ… (ANSI)
⚠️ (buffers all)
jq only
fx
βœ… arrow keys
βœ… (/)
βœ…
βœ…
⚠️ (JS load)
npm install -g fx
bat
⚠️ (pager only)
❌ (in bat)
❌
βœ… (theme)
⚠️ (reads all)
brew / apt
jq . (plain)
❌ (scrolls off)
❌
❌
βœ… (tty only)
❌
brew / apt

For most situations: install jless once and use it as the default interactive viewer. Keep jq -C . | less -R as a fallback for environments where you cannot install additional binaries. Add fx if your team is Node.js-first and values mouse navigation or live JavaScript filtering.

Frequently Asked Questions

How do I search for a specific key inside a JSON file in the terminal?

In jless, press / to open an incremental search prompt, type the key name, and press Enter. Use n to jump forward through matches and N to jump backward. Searching is case-sensitive by default. In jq -C | less -R, / triggers less's built-in search, which matches raw text including ANSI color codes β€” jless search is more reliable for structured JSON.

Bash
# Open file in jless, then press / to search
jless api-response.json
# In jless: type /  β†’  "request_id"  β†’  Enter  β†’  n for next match

# jq alternative: extract and print all matching keys to stdout
jq '.. | objects | with_entries(select(.key == "request_id"))' api-response.json

How do I navigate a deeply nested JSON structure with keyboard shortcuts?

jless mirrors vim navigation: j/k for up/down, h to collapse a node, l to expand it. Press H to collapse the current node and all its siblings at once β€” useful for getting a high-level overview before drilling into a specific branch. L expands everything recursively. Once you have collapsed everything to the top level, expand only the path you care about with l.

Bash
# Open the response in jless
curl -s https://api.github.com/repos/jqlang/jq | jless
# In jless:
#   H            β†’ collapse all top-level keys
#   j/k          β†’ navigate to the key you want
#   l            β†’ expand only that branch
#   gg           β†’ return to root
#   G            β†’ jump to last element

How do I make jq color output easier to read on a dark terminal?

Set the JQ_COLORS environment variable with ANSI attribute;color codes for each JSON type. The seven positions are, in order: null, false, true, numbers, strings, arrays, objects. Put the export in ~/.bashrc or ~/.zshrc to apply it to every jq call. Bold bright colors work best on dark backgrounds.

Bash
# High-contrast theme for dark terminals β€” add to ~/.bashrc or ~/.zshrc
export JQ_COLORS="1;30:0;91:0;92:0;93:0;32:1;96:1;96"
# null=gray, false=bright-red, true=bright-green,
# numbers=bright-yellow, strings=green, arrays/objects=bright-cyan

# Test immediately without reloading shell
echo '{"active":true,"errors":0,"tags":["api","v2"]}' | jq .

What is the difference between jless and jq . for viewing JSON?

jq . scrolls output past the top of the terminal and gives you no way to navigate back β€” useful for small responses, but impractical for anything over 50 lines. jless renders the entire document in an interactive pager where you can scroll, search, collapse nodes, and navigate with keyboard shortcuts without losing context. Use jq . when you want to glance at a small payload; use jless when you need to explore.

Bash
# Small payload β€” jq . is fine
echo '{"status":"ok","version":"2.4.1"}' | jq .

# Large or nested response β€” jless is better
curl -s https://api.github.com/repos/jqlang/jq | jless
# β†’ interactive tree, no output scrolled off screen

How do I view JSON from a curl response interactively in the terminal?

Pipe curl directly into jless. Always include -s (silent) to prevent curl's progress bar from appearing in the output. jless will open the interactive viewer with the full response rendered as a collapsible tree. If jless is not installed, jq -C . | less -R gives a colorized pager as a fallback.

Bash
# Interactive exploration with jless
curl -s https://api.github.com/users/torvalds | jless

# Colorized pager fallback (no collapse, but still scrollable with color)
curl -s https://api.github.com/users/torvalds | jq -C . | less -R

Can I view multiple JSON files side by side in the terminal?

jless opens one file at a time. For side-by-side comparison, use a terminal multiplexer: tmux split-window -h opens a vertical split, then run jless in each pane with a different file. Alternatively, use the browser-based JSON Diff tool if you need to compare two documents structurally.

Bash
# tmux side-by-side: split horizontally, then run jless in each pane
tmux split-window -h
# Left pane:  jless response-v1.json
# Right pane: jless response-v2.json

# Or use diff on jq-normalized output for a text diff
diff <(jq -S . response-v1.json) <(jq -S . response-v2.json)

The JSON Pretty Print tool gives you the same collapsible, colorized view as jless β€” directly in the browser, with no installation and no terminal required.

CM
Cora MatsumotoPlatform Engineer

Cora is a platform engineer who builds developer tooling and internal platforms, using Bash as the glue that connects components written in different languages and runtimes. She writes about cross-platform shell scripting, Bash utility functions, environment management, configuration templating, and the practical shell techniques that platform engineers use to build self-service tooling for development teams.

NO
Nadia OkonkwoTechnical Reviewer

Nadia is a site reliability engineer who lives in the terminal. She writes Bash scripts that process logs, transform data, and orchestrate infrastructure across fleets of servers. She is a heavy user of jq, awk, and sed and writes about shell one-liners, text processing pipelines, data serialisation from the command line, and the practical Bash patterns that SREs reach for when speed matters more than elegance.