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
# 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.jsonFlags
| Flag | What it does |
|---|---|
| --arg n v | Bind $n to v as a string |
| --argjson n v | Bind $n to v parsed as JSON |
| --slurpfile n f | Bind $n to an array of values from file f |
| --rawfile n f | Bind $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.