Skip to content
Latchkey

jq --arg and --argjson : Pass Shell Values In

jq --arg name value binds a string variable; --argjson name value binds a value parsed as JSON.

Injecting a branch name, a number, or a JSON array from the shell into a jq filter safely is what --arg and --argjson are for in CI.

What it does

--arg name value binds $name to the value as a string, never interpreted as JSON, which avoids injection. --argjson name value parses the value as JSON first, so use it for numbers, booleans, arrays, and objects. Both are safer than interpolating into the program text.

Common usage

Terminal
# filter by a shell-provided string safely
jq --arg branch "$BRANCH" '.[] | select(.name == $branch)' branches.json
# pass a number as JSON, not a string
jq --argjson min 100 '.[] | select(.size > $min)' files.json
# pass an array
jq --argjson tags '["a","b"]' '.[] | select(.tag | IN($tags[]))' items.json

Flags

FlagWhat it does
--arg n vBind $n to v as a string
--argjson n vBind $n to v parsed as JSON
--slurpfile n fBind $n to an array of values from file f
--rawfile n fBind $n to the raw contents of file f

In CI

Always pass user or environment data through --arg/--argjson rather than splicing it into the program string; this prevents a value with quotes or special characters from breaking or hijacking the filter. Use --argjson for anything that should stay a number, boolean, or array.

Common errors in CI

"jq: Invalid JSON text passed to --argjson" means the value is not valid JSON, often an unquoted string that needed --arg instead. "jq: error: $x is not defined" means the program uses $x but no matching --arg was given. A numeric comparison that always fails usually means a number was passed with --arg (as a string) rather than --argjson.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →