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
| Flag | Short | Description |
|---|
--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. |
--cloud | | Select the Anthropic cloud backend; equivalent to --backend anthropic. |
--compact-output | -c | Emit compact JSON output. |
--exit-status | -e | Set the exit status based on the last output value. |
--explain | | Print 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-cache | | Disable persistent on-disk judgement cache reads and writes for this run. |
--null-input | -n | Use a single null input value instead of reading stdin. |
--raw-input | -R | Read each input line as a string. |
--raw-output | -r | Emit strings without JSON quoting. |
--stats | | Print run statistics to stderr after a successful run. |
--stream | | Run 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 | -v | Print the version and exit. |
--help | -h | Print 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
| Command | Description |
|---|
ajq cache status [--json] | Print persistent judgement cache status, or its versioned machine-readable probe. |
ajq cache clear | Delete 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 status | Print the warm local daemon status. |
ajq examples [topic] | Print categorized safe examples; semantic examples explicitly use --backend mock. |
ajq daemon stop | Stop 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 provision | Download 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
| Code | Meaning |
|---|
0 | Success. With --exit-status, also means the last output value was truthy. |
1 | With --exit-status: the last output value was false or null. Otherwise a general error. |
4 | With --exit-status: the query produced no output. |
| non-zero | A 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.
ajq selects an input framing based on flags and the shape of stdin.
| Mode | Flag | Behavior |
|---|
| Auto (default) | — | Auto-detects a single JSON value or a stream of top-level / NDJSON JSON values. |
| Null input | -n, --null-input | Ignores stdin; supplies one null input frame. |
| Raw input | -R, --raw-input | Reads 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.
| Mode | Flag | Behavior |
|---|
| Pretty JSON (default) | — | Indented, human-readable JSON. |
| Compact JSON | -c, --compact-output | Single-line JSON, no extra whitespace. |
| Raw output | -r, --raw-output | String 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
| Function | Form | Kind | Returns | Execution status |
|---|
sem_match | sem_match(value; "spec") | predicate | boolean | Shipped |
sem_classify | sem_classify(value; "a"; "b"; …) | bounded value | one label from the given labels | Shipped |
sem_extract | sem_extract(value; "what") | unbounded value | string | Limited: supported only in gated/interleaved fallback contexts |
sem_score | sem_score(value; "spec") | unbounded value | number | Limited: supported in sort_by(...) three-phase placeholder mode and in gated/interleaved fallback contexts |
sem_norm | sem_norm(value; "canonicalization spec") | unbounded value | string | Limited: supported in group_by(...) three-phase placeholder mode and in gated/interleaved fallback contexts |
sem_redact | sem_redact(value; "redaction spec") | unbounded value | string | Limited: 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
| Kind | Meaning |
|---|
| Predicate | Returns true or false; typically used in select or if. |
| Bounded value | Returns one of a finite set declared at the call site. |
| Unbounded value | Returns 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
| Surface | Desugars 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
| Scenario | Invocation | Status |
|---|
| Fuzzy filter | select(.msg =~ "auth failure") | Shipped |
| Raw-line fuzzy filter | select(. =~ "stack trace") with -R | Shipped |
| Routing / labeling | {route: sem_classify(.text; "billing"; "bug"; "feature")} | Shipped |
| Semantic sort key | sort_by(sem_score(.review; "positivity")) | Limited, supported three-phase placeholder mode |
| Semantic grouping key | group_by(sem_norm(.company; "canonical name")) | Limited, supported three-phase placeholder mode |
| Gated semantic score | select(sem_score(.review; "positivity") > 0.8) | Limited, uses interleaved fallback |
| Gated typed extraction | select(sem_extract(.raw; "years") != "") | Limited, uses interleaved fallback |
| Gated semantic redaction | select(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
| Field | Meaning |
|---|
query | The query as parsed. |
execution | pure-jq deterministic — no semantic call sites. |
deterministic | yes. |
model_calls / backend_calls | 0. |
byte_reproducible | yes. |
stdin | ignored — 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
| Field | Meaning |
|---|
execution | semantic split plan — the query has semantic call sites. |
deterministic | no. |
model_calls / backend_calls | input-dependent. |
byte_reproducible | cache-dependent — deterministic phases are byte-reproducible; semantic answers depend on backend/cache state. |
stdin | harvested 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_sites | Total semantic call sites found in the static plan. |
semantic_predicates / semantic_values | Counts of predicate-kind and value-kind ops. |
estimates block
Present when valid stdin was supplied and the mock harvest path can estimate the query.
| Field | Unit / meaning |
|---|
estimate_status | available, or unavailable with a stable reason. |
static_call_sites | Semantic call sites in the static plan; not input cardinality. |
input_frames | Number of input frames read for the estimate. |
harvested_judgements | Pre-dedup semantic judgements collected by the mock harvest pass. |
post_dedup_judgements | Distinct judgements after deduplication — the estimated backend-call count before considering persistent-cache hits in a later real run. |
mock_judge_batches | Backend.Judge batch invocations in the deterministic mock path. |
over_harvest_bound | Notes that post-dedup judgements may be a safe superset of execute-needed judgements; it never underestimates needed decisions. |
semantic_plan entries
| Field | Meaning |
|---|
call_id | Deterministic planner call-site ID. |
op | The sem_* operator. |
kind | predicate or value. |
value_expr | The jq expression producing the judged value. |
specs | Ordered literal spec arguments. |
source_range | Byte offsets into the desugared query for the call site, or unavailable. |
gated | For value ops: whether the result flows into a pruning gate; n/a for predicates. |
execution | Execution mode: 3-phase, planner-required interleaved, or user-stream-inline when --stream selects inline execution for a supported plan. |
subgraph | semantic. |
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
| Rank | Source | Notes |
|---|
| 1 | Command-line flags | --backend, --model, --base-url, --backend-concurrency, --max-calls, --window-bytes, and --no-cache. |
| 2 | Environment variables | AJQ_BACKEND, AJQ_MODEL, AJQ_BASE_URL, AJQ_BACKEND_CONCURRENCY, AJQ_MAX_CALLS, AJQ_WINDOW_BYTES. |
| 3 | TOML config | Default path or AJQ_CONFIG. |
| 4 | Backend defaults | For 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
| Setting | Behavior |
|---|
AJQ_CONFIG=/path/to/config.toml | Read this exact file. If it is set and the file is missing or invalid, ajq errors. |
${XDG_CONFIG_HOME}/ajq/config.toml | Default path when XDG_CONFIG_HOME is set and AJQ_CONFIG is not. |
~/.config/ajq/config.toml | Default 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
| Key | Type | Example | Meaning |
|---|
backend | string | "local" | Semantic backend: mock, local, ollama, openai, openrouter, or anthropic. |
model | string | "qwen2.5-3b" | Model id or shipped alias for the selected backend. |
base_url | string | "http://127.0.0.1:11434" | HTTP base URL for backends that accept one. |
backend_concurrency | positive integer | 1 | Maximum in-flight requests in one provider batch. The selected OpenAI-compatible or Anthropic backend permits at most 2; Ollama permits at most 4. |
max_calls | integer | 100 | Maximum post-dedup backend judgements; 0 means unlimited. Must be non-negative. |
window_bytes | positive integer | 262144 | Maximum 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_cache | boolean | true | Disable 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
| Variable | Type | Meaning |
|---|
AJQ_BACKEND | string | Same values as backend. |
AJQ_MODEL | string | Same meaning as model. |
AJQ_BASE_URL | string | Same meaning as base_url. |
AJQ_BACKEND_CONCURRENCY | positive integer | Same meaning as backend_concurrency. |
AJQ_MAX_CALLS | non-negative integer | Same meaning as max_calls. |
AJQ_WINDOW_BYTES | positive integer | Same meaning as window_bytes; defaults to 262144 when unset. |
AJQ_CONFIG | path | Explicit config file path. |
AJQ_CACHE_DIR | path | Cache root for provisioning assets, daemon state, local models, and judgement cache files. |
OLLAMA_HOST | URL or host[:port] | Used by the Ollama backend when no ajq base URL is set. |
ANTHROPIC_API_KEY | secret | Anthropic credential. |
OPENAI_API_KEY | secret | OpenAI credential. |
OPENROUTER_API_KEY | secret | OpenRouter 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
| Data | Location 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 files | Cache-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
| Backend | Select with | Model default / requirement | Base URL | Credentials | Default max_calls |
|---|
mock | --backend mock | Built-in ajq-default-model identity | none | none | 0 (unlimited) |
local | --backend local | qwen2.5-1.5b unless overridden | Managed loopback http://127.0.0.1:8081; explicit --base-url for user-trusted servers | managed bearer key (internal) | 0 (unlimited) |
ollama | --backend ollama | Required --model / config / env | OLLAMA_HOST or http://127.0.0.1:11434 | none | 0 (unlimited) |
openai | --backend openai | Required --model / config / env | https://api.openai.com/v1 | OPENAI_API_KEY | 100 |
openrouter | --backend openrouter | Required --model / config / env | https://openrouter.ai/api/v1 | OPENROUTER_API_KEY | 100 |
anthropic | --backend anthropic or --cloud | claude-haiku-4-5; aliases haiku, sonnet, opus | provider default; no user base URL | ANTHROPIC_API_KEY | 100 |
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.
| Backend | Default root | API-key env var |
|---|
openai | https://api.openai.com/v1 | OPENAI_API_KEY |
openrouter | https://openrouter.ai/api/v1 | OPENROUTER_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:
| Alias | Model id |
|---|
haiku | claude-haiku-4-5 |
sonnet | claude-sonnet-5 |
opus | claude-opus-4-8 |
Anthropic credentials come only from ANTHROPIC_API_KEY.
Paid backend defaults
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:
| Provider | Default | Maximum | Why |
|---|
OpenAI-compatible (openai, openrouter) | 1 | 2 | A conservative opt-in ceiling for paid requests and their retries. |
| Anthropic | 1 | 2 | Bounds concurrent SDK-retried paid Messages API requests. |
| Ollama | 1 | 4 | A 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.