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#