This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Reference

CLI flags, configuration, backends, functions, and output formats.

Lookup pages for ajq behavior and interfaces.

For procedures, see the how-to guides. For design rationale, see explanation.

1 - Command-line interface

ajq invocation, global flags, subcommands, and exit codes.

Synopsis

ajq [query] [flags]
ajq [command]

ajq reads input from standard input, applies one jq/semantic query, and writes results to standard output. Errors are written to standard error and produce a non-zero exit code.

query is a single argument. ajq desugars =~/!~ to sem_match(...), parses with gojq, and executes through the selected backend only when semantic operators require one.

Global flags

FlagShortDescription
--backend <name>Select the semantic backend: anthropic, local, mock, ollama, openai, or openrouter.
--base-url <url>Set the HTTP base URL for backends that use one (local, ollama, openai, openrouter). For openai/openrouter, custom URLs must use HTTPS unless the host is loopback (127.0.0.1, localhost, or [::1]).
--backend-concurrency <N>Maximum in-flight semantic requests in one provider batch. Default 1; maximum 2 for OpenAI-compatible/Anthropic and 4 for Ollama. Must be positive when set.
--cloudSelect the Anthropic cloud backend; equivalent to --backend anthropic.
--compact-output-cEmit compact JSON output.
--exit-status-eSet the exit status based on the last output value.
--explainPrint the deterministic/semantic execution plan and exit without executing the query.
--max-calls <N>Maximum post-dedup backend judgements before aborting; 0 means unlimited. Paid backends default to 100; local/Ollama/mock default to unlimited.
--model <id-or-alias>Semantic model id or alias for the selected backend.
--no-cacheDisable persistent on-disk judgement cache reads and writes for this run.
--null-input-nUse a single null input value instead of reading stdin.
--raw-input-RRead each input line as a string.
--raw-output-rEmit strings without JSON quoting.
--statsPrint run statistics to stderr after a successful run.
--streamRun supported semantic queries inline for low-latency frame output instead of window batching. Does not change backend, model, cache identity, or --max-calls; pure-jq and planner-required inline queries retain their existing behavior.
--window-bytes <N>Maximum source bytes per supported three-phase semantic window; positive integer, default 262144. Has no execution effect for pure-jq or inline queries, including --stream.
--version-vPrint the version and exit.
--help-hPrint usage and exit.

See Input and output modes for framing and formatting details, Backends for backend-specific defaults, and Configuration for env/config precedence.

Help-first agent probe

For machine consumers, begin with ajq capabilities --json, before examples or query execution. It is static introspection: it does not load config or credentials, construct a backend, start a daemon, inspect/provision assets, or contact the network. Its versioned schema_version: "1" document is the stable contract for input/output modes, semantic-function availability, backend defaults, cost/cache/provisioning notes, safety guarantees, and discovery commands. The plain ajq capabilities summary, ajq_version, and human backend descriptions are informational build text; all other documented v1 fields and enum values are stable. Consumers must use schema_version as the contract discriminator and ignore unknown fields and future enum values for compatible v1 builds.

After capabilities discovery, run ajq examples for categorized, copy-pasteable safe workflows. ajq examples [topic] can show one of pure-jq, semantic-filter, explain, classification, or ndjson; its semantic commands explicitly use --backend mock and therefore need no model, network, or API key. It is the source of the detailed snippets; this reference keeps only the workflow overview. The root help shows the same three safe first workflows:

# Pure jq remains deterministic and does not construct a backend.
printf '{"users":[{"name":"Ada"}]}' | ajq -r '.users[].name'

# --backend mock is the safe semantic-agent probe: deterministic, no model,
# no network access, and no API key.
printf '[{"id":1,"msg":"please keep this"}]' \
  | ajq --backend mock -c '.[] | select(.msg =~ "keep") | .id'

# Review the semantic plan and estimated backend calls before execution.
printf '[{"msg":"refund demanded"}]' \
  | ajq --backend mock --explain '.[] | select(.msg =~ "angry/frustrated") | .msg'

The mock backend is appropriate for checking query shape and split-execution behavior; it is not a substitute for evaluating a query’s semantic quality on a production model. --explain exits before query execution and does not contact a model backend.

Discovery command help also includes safe inspection examples: ajq provision --check reports missing local assets without downloading them, ajq models list shows local model availability, ajq cache status inspects the local judgement cache, and ajq daemon status checks daemon state without starting a model.

JSON state probes

Coding agents can request versioned local-state documents with command-local --json flags. Every document has schema_version: "1", is one JSON document on stdout, and has a trailing newline. Consumers should use the schema version, ignore unknown future fields/enums, and keep stdout even when a readiness check has a non-zero exit status.

  • ajq models list --json returns active and ordered models. active.state is catalog, path_like, or unknown; name occurs only for catalog and path only for path_like. Each catalog row contains name, active, installed, filename, path, size_bytes, and ram.
  • ajq cache status --json returns availability (available or unavailable), path, entries, and bytes. An unavailable local cache also has error: "status_unavailable" and exits non-zero; it never exposes a raw filesystem error.
  • ajq provision --check --json returns platform, ready, engine, model, and ordered actions. Assets contain identity, present, path, and source when present; sources include override, bundle, legacy_cache, path, cache, and unknown. Missing readiness produces a complete document then exits 1. Actions are engine-first: provision runs ajq provision, and a selected non-default model can add models_pull with ajq models pull <name>. --json requires --check; ajq provision --json is rejected and never starts provisioning.

These probes only read local configuration, filesystem, and PATH state. They do not construct a backend, contact a provider, download assets, or start a daemon. They intentionally omit credentials, prompts, provider responses, catalog URLs, and checksums.

Subcommands

CommandDescription
ajq cache status [--json]Print persistent judgement cache status, or its versioned machine-readable probe.
ajq cache clearDelete persistent judgement cache entries and report what was freed.
ajq capabilities [--json]Print informational static metadata, or the versioned machine-readable capability contract for agents.
ajq daemon statusPrint the warm local daemon status.
ajq examples [topic]Print categorized safe examples; semantic examples explicitly use --backend mock.
ajq daemon stopStop the local daemon if running; idempotent.
ajq models list [--json]Print the pinned local model catalog, or its versioned machine-readable probe.
ajq models pull <name>Download a checksum-pinned catalog model into the ajq cache.
ajq models use <name>Persist model = "<name>" to config after verifying the model is installed.
ajq provisionDownload or locate the local llama-server engine and default GGUF model.
ajq provision --check [--json]Report provisioning status (or its versioned JSON) and exit non-zero if assets are missing, without downloading.

The root help also includes Cobra’s generated completion and help commands.

Exit codes

CodeMeaning
0Success. With --exit-status, also means the last output value was truthy.
1With --exit-status: the last output value was false or null. Otherwise a general error.
4With --exit-status: the query produced no output.
non-zeroA parse, runtime, configuration, backend, provisioning, or I/O error occurred.

The --exit-status codes match jq’s convention.

Behavior notes

  • If no semantic operators are present, ajq constructs no backend, makes no network calls, and spawns no daemon.
  • The managed local backend starts llama-server on loopback with a per-daemon --api-key; ajq stores the bearer key beside the daemon PID file in the cache directory with 0600 permissions and sends it only to the managed daemon.
  • A healthy process already listening on the default managed local address is treated as a port conflict unless it has ajq’s managed PID/key files. To use a server you started yourself, pass --base-url (or set AJQ_BASE_URL/base_url); that explicit server is trusted by user intent and is not given ajq’s managed daemon key.
  • --cloud with a conflicting explicit --backend is a CLI error.
  • --backend openai and --backend openrouter send API keys on each request, so custom --base-url values must be https://; http:// is accepted only for loopback OpenAI-compatible proxies such as 127.0.0.1, localhost, or [::1].
  • --explain on a pure-jq query validates the query and prints a byte-stable pure-jq report without reading stdin.
  • --explain on a semantic query prints the static plan and, when valid stdin is supplied, mock-path estimates without contacting a real backend. With --explain --stream on a supported semantic plan, it instead identifies user-selected inline execution, does not consume stdin, and reports the harvest/batching/dedup estimate as unavailable.
  • --stats writes only the summary to stderr; query output remains on stdout. Its execution_mode is pure-jq, three-phase-windowed, planner-interleaved, or user-stream; batching_dedup states the matching windowed or inline trade-off. The numeric window_bytes, window_count, and oversized_window_count fields are zero outside three-phase-windowed mode.
  • --stream selects inline, input-order semantic execution only for supported semantic plans that would otherwise be windowed. It gives first-frame latency but disables cross-frame pre-resolve deduplication and window batching. Cache identity, cache hits, schema validation, and the run-global --max-calls cap are unchanged.
  • --window-bytes applies only to supported three-phase semantic execution. It forms complete-frame windows, never buffers the entire input, and accepts a record larger than the budget as a one-frame oversized window.

2 - Input and output modes

How ajq frames input and formats output.

Input framing

ajq selects an input framing based on flags and the shape of stdin.

ModeFlagBehavior
Auto (default)Auto-detects a single JSON value or a stream of top-level / NDJSON JSON values.
Null input-n, --null-inputIgnores stdin; supplies one null input frame.
Raw input-R, --raw-inputReads each stdin line as a string, excluding the line terminator. . is the line.

In the default mode, a stream of multiple top-level JSON values (whitespace- or newline-separated, i.e. NDJSON/JSON Lines) is framed independently, with no whole-stream buffering. Pure-jq and planner-required interleaved semantic queries execute and emit one frame at a time. Supported three-phase semantic queries instead group complete frames into configured byte-budgeted windows, resolve each window once, then emit their frames in original order. The window retains only its frames plus bounded framing lookahead; a record larger than the budget forms one oversized window and is never split. This still allows inputs larger than available memory.

For a supported semantic query, --stream selects that same per-frame inline behavior instead of default windows so a result need not wait for a later frame. It trades window-wide batching and cross-frame pre-resolve deduplication for low latency, without changing cache identity or the run-global --max-calls cap. See Process NDJSON for selection guidance and examples.

Output formatting

ModeFlagBehavior
Pretty JSON (default)Indented, human-readable JSON.
Compact JSON-c, --compact-outputSingle-line JSON, no extra whitespace.
Raw output-r, --raw-outputString results are written without surrounding quotes; non-string results are unaffected.

-c and -r can be combined, and both may be combined with any input mode.

Examples

# Single JSON value
printf '{"a":1}\n' | ajq -c '.a + 1'
# 2

# NDJSON, processed independently per frame
printf '{"a":1}\n{"a":2}\n' | ajq -c '.a, (.a + 10)'
# 1
# 11
# 2
# 12

# Null input — build output from scratch
printf '{"ignored":true}\n' | ajq -n -c '{generated: true}'
# {"generated":true}

# Raw input + raw output
printf 'error: disk full\n' | ajq -R -r 'ascii_upcase'
# ERROR: DISK FULL

3 - Semantic functions

The shipped semantic vocabulary, =/! sugar, arities, return types, and current limits.

Semantic operators are registered as jq functions, so gojq parses them inside ordinary jq constructs. ajq adds only the =~ and !~ surface sugar before parsing.

Function vocabulary

FunctionFormKindReturnsExecution status
sem_matchsem_match(value; "spec")predicatebooleanShipped
sem_classifysem_classify(value; "a"; "b"; …)bounded valueone label from the given labelsShipped
sem_extractsem_extract(value; "what")unbounded valuestringLimited: supported only in gated/interleaved fallback contexts
sem_scoresem_score(value; "spec")unbounded valuenumberLimited: supported in sort_by(...) three-phase placeholder mode and in gated/interleaved fallback contexts
sem_normsem_norm(value; "canonicalization spec")unbounded valuestringLimited: supported in group_by(...) three-phase placeholder mode and in gated/interleaved fallback contexts
sem_redactsem_redact(value; "redaction spec")unbounded valuestringLimited: supported only in gated/interleaved fallback contexts

The spec is a literal string in the query. Stream data is structurally fenced by the selected backend’s output constraints.

Kinds

KindMeaning
PredicateReturns true or false; typically used in select or if.
Bounded valueReturns one of a finite set declared at the call site.
Unbounded valueReturns a string or number with no finite output set. These shapes need bounded executor contexts or interleaved fallback; unsupported forms fail loudly.

Variadic implicit .

Every operator accepts both an explicit value and an implicit one. When the value argument is omitted, it defaults to .:

sem_match(.field; "spec")   # explicit value
sem_match("spec")           # value defaults to .

The implicit form is what makes raw-line mode ergonomic.

The =~ and !~ sugar

SurfaceDesugars to
X =~ "spec"sem_match(X; "spec")
X !~ "spec"`sem_match(X; “spec”)

The desugaring is performed by a jq-aware lexer, not a regular expression.

.users[] | select(.feedback =~ "angry/frustrated") | .id
# ≡
.users[] | select(sem_match(.feedback; "angry/frustrated")) | .id

Return-type discipline

Each semantic operator has a fixed output type: boolean, enum label, string, or number. Backends constrain model output with GBNF grammar or provider structured-output/schema features, so downstream jq receives a value of the expected shape when execution succeeds.

For sem_classify, the enum is exactly the label arguments at the call site:

sem_classify(.text; "billing"; "bug"; "feature")

That expression returns one of "billing", "bug", or "feature".

Scenario matrix

ScenarioInvocationStatus
Fuzzy filterselect(.msg =~ "auth failure")Shipped
Raw-line fuzzy filterselect(. =~ "stack trace") with -RShipped
Routing / labeling{route: sem_classify(.text; "billing"; "bug"; "feature")}Shipped
Semantic sort keysort_by(sem_score(.review; "positivity"))Limited, supported three-phase placeholder mode
Semantic grouping keygroup_by(sem_norm(.company; "canonical name"))Limited, supported three-phase placeholder mode
Gated semantic scoreselect(sem_score(.review; "positivity") > 0.8)Limited, uses interleaved fallback
Gated typed extractionselect(sem_extract(.raw; "years") != "")Limited, uses interleaved fallback
Gated semantic redactionselect(sem_redact(.notes; "PII") != .notes)Limited, uses interleaved fallback

sem_score and sem_norm are not general-purpose enrichment operators in 0.0.1. Use sem_score as a sort_by(...) key and sem_norm as a group_by(...) key when you want the three-phase executor. sem_extract and sem_redact have no supported three-phase context; use them only in a gated control-flow context. When an unbounded value result is used to prune control flow, such as a score comparison inside select or if, ajq may choose an interleaved fallback instead of the harvest/resolve/execute path. That fallback is bounded by the same backend, cache, and --max-calls controls, but its call count is not available as a three-phase harvest estimate.

Current grammar scope

There is no custom jq grammar. @classify(...)-style @ forms and infix transform operators such as ~> do not parse in gojq and are not shipped. Use the function-core forms above.

4 - --explain output

Every field in the ajq explain v1 report.

--explain prints a stable plan report and exits without executing the query. It does not contact a provider or local model.

Pure-jq report

ajq explain v1
query: ".users[] | select(.active) | .name"
execution: pure-jq deterministic
deterministic: yes
model_calls: 0
backend_calls: 0
byte_reproducible: yes
stdin: ignored
FieldMeaning
queryThe query as parsed.
executionpure-jq deterministic — no semantic call sites.
deterministicyes.
model_calls / backend_calls0.
byte_reproducibleyes.
stdinignored — pure-jq explain does not read input.

Semantic report

ajq explain v1
query: ".[] | select(sem_match(.msg; \"urgent\")) | .msg"
execution: semantic split plan
deterministic: no
model_calls: input-dependent
backend_calls: input-dependent
byte_reproducible: cache-dependent
stdin: harvested for estimates
planned_call_sites: 1
semantic_predicates: 1
semantic_values: 0
estimates:
  estimate_status: available
  static_call_sites: 1
  input_frames: 1
  harvested_judgements: 3
  post_dedup_judgements: 2
  mock_judge_batches: 1
  over_harvest_bound: post_dedup_judgements == mock distinct judgements; may be a safe superset of execute-needed judgements
subgraphs:
  deterministic: jq outside semantic call sites
  semantic: 1 planned call site(s)
semantic_plan:
  - call_id: 1
    op: "sem_match"
    kind: "predicate"
    value_expr: ".msg"
    specs: ["urgent"]
    source_range: 13:38
    gated: n/a
    execution: 3-phase
    subgraph: semantic

Header fields

FieldMeaning
executionsemantic split plan — the query has semantic call sites.
deterministicno.
model_calls / backend_callsinput-dependent.
byte_reproduciblecache-dependent — deterministic phases are byte-reproducible; semantic answers depend on backend/cache state.
stdinharvested for estimates when valid stdin is used for an estimate. With --stream on a supported plan, not harvested: inline execution has no cross-frame harvest estimate and explain leaves stdin untouched.
planned_call_sitesTotal semantic call sites found in the static plan.
semantic_predicates / semantic_valuesCounts of predicate-kind and value-kind ops.

estimates block

Present when valid stdin was supplied and the mock harvest path can estimate the query.

FieldUnit / meaning
estimate_statusavailable, or unavailable with a stable reason.
static_call_sitesSemantic call sites in the static plan; not input cardinality.
input_framesNumber of input frames read for the estimate.
harvested_judgementsPre-dedup semantic judgements collected by the mock harvest pass.
post_dedup_judgementsDistinct judgements after deduplication — the estimated backend-call count before considering persistent-cache hits in a later real run.
mock_judge_batchesBackend.Judge batch invocations in the deterministic mock path.
over_harvest_boundNotes that post-dedup judgements may be a safe superset of execute-needed judgements; it never underestimates needed decisions.

semantic_plan entries

FieldMeaning
call_idDeterministic planner call-site ID.
opThe sem_* operator.
kindpredicate or value.
value_exprThe jq expression producing the judged value.
specsOrdered literal spec arguments.
source_rangeByte offsets into the desugared query for the call site, or unavailable.
gatedFor value ops: whether the result flows into a pruning gate; n/a for predicates.
executionExecution mode: 3-phase, planner-required interleaved, or user-stream-inline when --stream selects inline execution for a supported plan.
subgraphsemantic.

When estimates are unavailable

If stdin is empty or invalid, or the query uses a semantic execution shape the current executor cannot safely estimate/execute, the static plan is still printed and estimate_status is marked unavailable with a reason.

--explain --stream is intentionally unavailable without reading stdin. Its report names semantic user-stream inline, says stdin: not harvested, and includes execution_selection: user-selected --stream interleaving, inline per-uncached-judgement batching, and disabled cross-frame pre-resolve deduplication. This is a mode choice, not a change to backend/model/cache identity or the run-global call cap.

The important distinction is execution mode. sem_score in sort_by(...) and sem_norm in group_by(...) can use the three-phase placeholder path. Gated unbounded value shapes, such as select(sem_score(.review; "positivity") > 0.8), can use interleaved fallback; their estimate status is unavailable because ajq resolves values as execution reaches them rather than harvesting a complete up-front set. Standalone sem_extract and sem_redact are registered but currently fail as unsupported in three-phase execution.

5 - Configuration

Config files, environment variables, precedence, and credential policy.

ajq resolves semantic-backend settings from flags, environment variables, a TOML config file, and backend defaults.

Precedence

RankSourceNotes
1Command-line flags--backend, --model, --base-url, --backend-concurrency, --max-calls, --window-bytes, and --no-cache.
2Environment variablesAJQ_BACKEND, AJQ_MODEL, AJQ_BASE_URL, AJQ_BACKEND_CONCURRENCY, AJQ_MAX_CALLS, AJQ_WINDOW_BYTES.
3TOML configDefault path or AJQ_CONFIG.
4Backend defaultsFor example, Anthropic’s default model and paid-backend call cap.

Flags override environment variables; environment variables override config values; config values override backend defaults.

Config file path

SettingBehavior
AJQ_CONFIG=/path/to/config.tomlRead this exact file. If it is set and the file is missing or invalid, ajq errors.
${XDG_CONFIG_HOME}/ajq/config.tomlDefault path when XDG_CONFIG_HOME is set and AJQ_CONFIG is not.
~/.config/ajq/config.tomlDefault fallback path when neither AJQ_CONFIG nor XDG_CONFIG_HOME is set.

A missing default config file is ignored. A missing explicit AJQ_CONFIG file is an error.

TOML keys

KeyTypeExampleMeaning
backendstring"local"Semantic backend: mock, local, ollama, openai, openrouter, or anthropic.
modelstring"qwen2.5-3b"Model id or shipped alias for the selected backend.
base_urlstring"http://127.0.0.1:11434"HTTP base URL for backends that accept one.
backend_concurrencypositive integer1Maximum in-flight requests in one provider batch. The selected OpenAI-compatible or Anthropic backend permits at most 2; Ollama permits at most 4.
max_callsinteger100Maximum post-dedup backend judgements; 0 means unlimited. Must be non-negative.
window_bytespositive integer262144Maximum source bytes in a supported three-phase semantic window. A larger value can deduplicate more nearby records but delays output until the window resolves. It has no execution effect for pure-jq or interleaved queries.
no_cachebooleantrueDisable persistent judgement cache reads/writes when true.

Example:

backend = "local"
model = "qwen2.5-3b"
backend_concurrency = 1
max_calls = 50
window_bytes = 262144
no_cache = false

ajq models use <name> writes model = "<name>" after verifying the model is installed. It preserves unrelated keys but not comments or original formatting.

Environment variables

VariableTypeMeaning
AJQ_BACKENDstringSame values as backend.
AJQ_MODELstringSame meaning as model.
AJQ_BASE_URLstringSame meaning as base_url.
AJQ_BACKEND_CONCURRENCYpositive integerSame meaning as backend_concurrency.
AJQ_MAX_CALLSnon-negative integerSame meaning as max_calls.
AJQ_WINDOW_BYTESpositive integerSame meaning as window_bytes; defaults to 262144 when unset.
AJQ_CONFIGpathExplicit config file path.
AJQ_CACHE_DIRpathCache root for provisioning assets, daemon state, local models, and judgement cache files.
OLLAMA_HOSTURL or host[:port]Used by the Ollama backend when no ajq base URL is set.
ANTHROPIC_API_KEYsecretAnthropic credential.
OPENAI_API_KEYsecretOpenAI credential.
OPENROUTER_API_KEYsecretOpenRouter credential.

Provider API keys are not part of the generic AJQ_* config merge. Each provider backend reads only its own credential environment variable. backend_concurrency and window_bytes follow normal flag > environment > TOML > backend-default precedence. An explicit concurrency value must be positive and within the selected provider’s maximum (2 for OpenAI-compatible and Anthropic; 4 for Ollama); invalid flag, environment, or TOML values are rejected when a semantic backend is resolved. Pure-jq execution does not resolve a semantic backend, so its streaming behavior is unchanged by environment or TOML backend settings.

API-key policy

API keys are environment-only. The TOML config rejects credential-looking keys including api_key, apikey, and token:

config key "api_key" looks like a credential; API keys are env-only (use ANTHROPIC_API_KEY, OPENAI_API_KEY, or OPENROUTER_API_KEY)

Cache paths

DataLocation under cache root
Persistent semantic judgements<cache>/judgements/
Local model files<cache>/models/
Engine bundles / legacy binary cache<cache>/engine/ and legacy <cache>/bin/
Daemon PID/activity filesCache-root daemon state files.

The cache root is AJQ_CACHE_DIR when set; otherwise it is the OS user cache directory joined with ajq (for example ~/Library/Caches/ajq on macOS or ~/.cache/ajq on Linux, with ~/.cache/ajq as a fallback).

6 - Backends

Semantic backend names, defaults, required settings, and paid-call caps.

Semantic operators require a backend. Pure jq queries do not construct a backend, spawn a daemon, or make network calls unless a semantic operator is present and a backend is selected by flags, environment, or config.

Backend summary

BackendSelect withModel default / requirementBase URLCredentialsDefault max_calls
mock--backend mockBuilt-in ajq-default-model identitynonenone0 (unlimited)
local--backend localqwen2.5-1.5b unless overriddenManaged loopback http://127.0.0.1:8081; explicit --base-url for user-trusted serversmanaged bearer key (internal)0 (unlimited)
ollama--backend ollamaRequired --model / config / envOLLAMA_HOST or http://127.0.0.1:11434none0 (unlimited)
openai--backend openaiRequired --model / config / envhttps://api.openai.com/v1OPENAI_API_KEY100
openrouter--backend openrouterRequired --model / config / envhttps://openrouter.ai/api/v1OPENROUTER_API_KEY100
anthropic--backend anthropic or --cloudclaude-haiku-4-5; aliases haiku, sonnet, opusprovider default; no user base URLANTHROPIC_API_KEY100

max_calls counts post-dedup backend judgements. 0 means unlimited. For a machine-readable static projection of these registered backends, use ajq capabilities --json; it does not resolve configured credentials or runtime asset state. In that projection Ollama has no default_base_url, because its runtime URL may come from OLLAMA_HOST before the documented loopback fallback.

Mock

The mock backend is deterministic and in-process. It is for examples, tests, fixtures, and --explain estimates. It never contacts a model provider.

Local

The local backend uses a managed llama-server daemon and a GGUF model from the ajq model catalog. ajq provision installs or locates the engine and default model. ajq models list|pull|use manages larger catalog models. Managed daemons are started with --api-key; ajq keeps the generated bearer key beside the PID file in the cache directory with 0600 permissions and sends it on /completion requests.

When ajq owns the managed daemon config, the base URL is an HTTP loopback URL with no path, query, fragment, or userinfo; bracketed IPv6 loopback is accepted, for example http://[::1]:8081. A health-only listener on the default managed address is a port conflict, not silent adoption. An explicit --base-url, AJQ_BASE_URL, or config base_url means you trust that external server; ajq bypasses managed provisioning/daemon startup and does not send its managed daemon key to that server.

Model identity for cache keys is local/<catalog-name> for catalog models, such as local/qwen2.5-3b. Path-like local model overrides use a stable hashed path identity.

Ollama

The Ollama backend uses Ollama’s native structured /api/chat endpoint. --model is required unless supplied by AJQ_MODEL or config. If no ajq base URL is configured, OLLAMA_HOST is honored before falling back to http://127.0.0.1:11434. Host-only forms such as 127.0.0.1:11434 are accepted and normalized.

OpenAI and OpenRouter

OpenAI and OpenRouter use OpenAI-compatible /v1/chat/completions transport with structured output. --model is required unless supplied by config or AJQ_MODEL.

BackendDefault rootAPI-key env var
openaihttps://api.openai.com/v1OPENAI_API_KEY
openrouterhttps://openrouter.ai/api/v1OPENROUTER_API_KEY

A custom --base-url is treated as an OpenAI-compatible API root.

Anthropic

--cloud selects the Anthropic backend and is equivalent to --backend anthropic. The default model is claude-haiku-4-5. Model aliases resolve as follows:

AliasModel id
haikuclaude-haiku-4-5
sonnetclaude-sonnet-5
opusclaude-opus-4-8

Anthropic credentials come only from ANTHROPIC_API_KEY.

The paid/remote backends (anthropic, openai, and openrouter) default to max_calls = 100 unless a flag, env var, or config value overrides it. Local, Ollama, and mock default to unlimited.

Bounded batch concurrency

--backend-concurrency, AJQ_BACKEND_CONCURRENCY, and TOML backend_concurrency set the maximum number of simultaneous requests while one provider resolves a batch of distinct cache misses. The default is 1, which keeps the established sequential path. Explicit values must be positive and are validated for the selected provider before backend construction or a request:

ProviderDefaultMaximumWhy
OpenAI-compatible (openai, openrouter)12A conservative opt-in ceiling for paid requests and their retries.
Anthropic12Bounds concurrent SDK-retried paid Messages API requests.
Ollama14A bounded local-service limit matching the managed local daemon’s default slot count.

A higher value can reduce latency for a multi-judgement batch, but it does not increase a batch’s judgement count, relax max_calls, change deduplication or cache keys, or alter per-request retry policy. For paid providers, start at 1 and increase only after checking the provider’s account rate limits; retries also consume request capacity. Managed-local and mock backend scheduling are unchanged by this setting.

Results always retain their input-batch order even when requests complete out of order. A per-item schema/coercion error stays attached to that item. In contrast, a transport or system failure cancels queued and admitted sibling work, waits for cleanup, and returns no partial batch results.