π§© jq for JSONC β query, view, and edit JSON-with-Comments files without losing your comments.
jq is the standard tool for JSON on the command line. But many config files β VS Code settings.json, tsconfig.json, deno.jsonc, biome.jsonc β use JSONC, which extends JSON with // and /* */ comments. Piping these through jq silently strips every comment.
Homebrew
brew install muleyuck/tap/jqcShell script (macOS / Linux)
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/muleyuck/jqc/releases/latest/download/jqc-installer.sh | shCargo
cargo install --git https://github.com/muleyuck/jqcjqc accepts the same filter expressions as jq. If you already know jq, you already know how to query with jqc.
jqc '.port' config.jsonc
# 3000
jqc '.compilerOptions.target' tsconfig.json
# "ES2022"
jqc '.plugins[]' config.jsonc
# "core"
# "auth"
jqc '.plugins[0]' config.jsonc
# "core"
cat config.jsonc | jqc '.host'
# "localhost"Output flags (same as jq)
| Flag | Behavior |
|---|---|
-r |
Raw output β strips surrounding quotes from strings |
-c |
Compact output β no newlines |
jqcuses jaq as its filter engine. The vast majority ofjqfilters work without modification. For known differences, see the jaq compatibility notes.
Running jqc without a filter, or using fmt, outputs JSONC with syntax highlighting. Comments are colorized alongside the JSON tokens β something jq cannot do because it cannot parse JSONC at all.
# Colorized output β comments are preserved
jqc fmt config.jsonc
# Identity filter β pretty-prints with color, but comments are stripped
# (the filter engine processes pure JSON values and does not carry comments through)
jqc '.' config.jsoncOutput when writing to a terminal is colorized automatically. When piped, output is plain. Override with:
jqc -C fmt config.jsonc # force color (e.g. when piping to less -R)
jqc -M fmt config.jsonc # disable color
NO_COLOR=1 jqc fmt config.jsonc # disable color (https://no-color.org/)Token colors are customizable via JQC_COLORS β a colon-separated list of 9 ANSI SGR codes:
null : false : true : number : string : array : object : key : comment
Leave a field empty to keep the default. Example β bold cyan numbers:
export JQC_COLORS="::::1;36::::"
jqc fmt config.jsoncfmt also validates JSONC syntax and exits non-zero on invalid input, making it usable as a pre-commit check:
jqc fmt tsconfig.json > /dev/null && echo "valid"set, del, and push rewrite the JSONC source text directly. Only the targeted value changes β all comments, including inline comments on the same line as the edited value, are left untouched.
Before After: jqc set '.port' 8080 -i config.jsonc
ββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββββββββ
{ {
// Server settings // Server settings
"host": "localhost", "host": "localhost",
"port": 3000, // default port β "port": 8080, // default port
/* Feature flags */ /* Feature flags */
"debug": false "debug": false
} }
Without -i, the result is printed to stdout. Add -i to overwrite the file atomically.
jqc set '.port' 8080 config.jsonc # print to stdout
jqc set '.port' 8080 -i config.jsonc # edit in-place
jqc set '.host' '"production.example.com"' config.jsonc # string value
jqc set '.compilerOptions.strict' 'false' tsconfig.json # boolean
jqc set '.compilerOptions.target' '"ES2022"' tsconfig.jsonjqc del '.debug' config.jsonc
jqc del '.compilerOptions.noImplicitAny' -i tsconfig.jsonjqc push '.plugins' '"logging"' config.jsonc
jqc push '.lint.rules.tags' '"strict"' -i deno.jsonc| jq | jqc | |
|---|---|---|
| Filter syntax | yes | yes β same syntax |
| Reads JSONC | no β parse error | yes |
| Colorized output with comments | no | yes |
| Comment-preserving edits | no | yes |
| In-place editing | no | yes (-i) |
| Custom colors | JQ_COLORS (8 fields) |
JQC_COLORS (9 fields, adds comment color) |
MIT
