$_ bashkit

jq builtin

Bashkit ships an embedded jq JSON processor backed by jaq with a thin compatibility shim layered on top. This guide documents which jq features are supported so callers (and LLM agents that generate jq filters against bashkit) can avoid surprises.

Reported version

jq --version prints jq-1.8. Filters generated for stedfan/jq 1.7 and 1.8 are the intended target.

Command-line flags

Implemented:

FlagDescription
-r, --raw-outputStrings are written without quotes
-R, --raw-inputEach line of input becomes a JSON string
-s, --slurpRead every input value into one array
-n, --null-inputUse null as the (single) input value
-c, --compact-outputOne JSON value per line, no pretty-printing
-S, --sort-keysSort object keys recursively
-e, --exit-statusSet exit code based on the output
-jLike -r but suppresses trailing newlines
--tabUse tabs for indentation
--arg name valueBind $name to a string
--argjson name jsonBind $name to a parsed JSON value
-V, --versionPrint the version
-h, --helpPrint help
Combined flags like -snrTreated as the union of the individual flags

Variables

VariableBehaviour
$ENVBound to the shell environment as an object — same map as the env filter. (#1486)
$nameVariables defined with --arg / --argjson are passed through.

Notable filters

The full jq stdlib is mostly available via jaq-std. The compatibility shim adds or overrides:

FilterNotes
envReads from the shell env map (not the host process env), avoiding the unsafe std::env::set_var path.
setpath(p; v)Bashkit ships a recursive definition because jaq’s stdlib doesn’t expose one.
leaf_pathsDefined as paths(scalars) since jaq’s stdlib lacks it.
match(re; flags) / match(re)Overridden to add "name": null to unnamed captures, matching jq output.
scan(re; flags) / scan(re)Overridden so scan defaults to global (“g”) matching, matching jq.
input_filenameStub returning null (#1486). Bashkit reads inputs as a single concatenated stream via shell redirection, so per-input filenames are not tracked.
input_line_numberStub returning 0 (#1486). Per-line input tracking is not implemented.
input / inputsReal jaq implementations — pull from the shared input iterator.
Most other 1.7/1.8 stdlib filtersForwarded from jaq-std (getpath, paths, to_entries, group_by, ltrimstr/rtrimstr, splits, test, now, debug, limit, etc.).

Errors

Filter parse failures and runtime errors return exit code 3 and 5 respectively, matching jq. Long error operands are summarised so failures do not blow up an LLM context window — see #1485.

Known gaps

Bashkit’s jq is intentionally minimal in places where the host model differs from upstream jq:

  • File inputs are concatenated into a single stream by the shell, so per-file metadata (input_filename, input_line_number) is stubbed.
  • Exotic numeric formatting modes (@base32, @base64d, etc.) follow whatever jaq-json ships.

If you hit a missing builtin, please open an issue with the failing filter.

See also