Skip to content

Scripting with JSON

Every vabc command follows the same output contract: data goes to stdout, human notes and errors go to stderr. This split makes shell pipelines safe — you can pipe stdout into jq without worrying about progress notes polluting the JSON.

Requesting JSON output

Two equivalent ways to get JSON:

Terminal window
vabc --json product search bourbon
vabc --format json product search bourbon

Both produce 2-space indented JSON with HTML escaping disabled (so URLs survive intact). Plain text and TSV are the other options:

Terminal window
vabc --format tsv store near 22182

For scripting, always use --json or --format json. The plain and TSV renderers are for human-readable terminal output and their column selection is not guaranteed to be stable across versions.

Field projection with —select

--select takes a comma-separated list of dot-path fields and keeps only those keys in each object. Nested paths use dot notation.

Terminal window
# Keep only storeNumber and distance from nearby-store results
vabc --json store near 22182 --select storeNumber,distance
# Pull name and retailPrice from a product search
vabc --json product search bourbon --select name,retailPrice

Projection happens before output, so it works with any command. If a path does not exist in an object it is silently omitted (no error).

Limiting results with —limit

All list operations default to 50 results. Override with --limit:

Terminal window
# The three nearest stores to ZIP 22182
vabc --json store near 22182 --limit 3
# Top 10 bourbon results
vabc --json product search bourbon --limit 10

When the output is truncated a note is written to stderr:

note: output truncated to 10 of 94 items (use --limit to change)

That note never lands on stdout, so your jq pipeline is unaffected.

The structured error envelope

When a command fails, vabc writes a JSON object to stderr (when --json is active) and exits with a non-zero code:

{
"error": "product 999999 not found",
"code": "NOT_FOUND",
"remediation": "list available products to find a valid id"
}

Fields:

FieldTypeDescription
errorstringHuman-readable message
codestringMachine-readable symbol, stable across versions
remediationstringSuggested fix, may be empty

Exit codes

Exit codes are stable and documented. The ones you’ll encounter most in scripts:

CodeValueMeaning
ok0Success
generic_error1Unexpected error
usage2Bad flag or argument
empty_results3Query succeeded but returned nothing
not_found5Specific resource (product, store) not found
rate_limited7Throttle block — retry after a moment
retryable8Transient backend error — safe to retry
config_error10Environment or state-file problem
input_required13Interactive prompt needed but --no-input is set
cancelled130SIGINT

Check codes in shell with $? immediately after the command:

Terminal window
vabc --json inventory check 010807 --near 22182
rc=$?
case $rc in
0) echo "got results" ;;
3) echo "product not found in inventory (but query worked)" ;;
7) echo "rate limited — wait and retry" ;;
*) echo "unexpected error ($rc)" ;;
esac

For non-interactive scripts, pass --no-input so prompts become a clean exit 13 instead of hanging:

Terminal window
vabc --json --no-input inventory check 010807 --store 219

jq recipes

The recipes below assume jq is installed. All commands are real, runnable invocations — adjust product codes and locations for your own use.

Cheapest in-stock product near a ZIP

Search for bourbon, get inventory near ZIP 22182 for each result, keep only products where the anchor store has stock, then sort by retail price:

Terminal window
vabc --json product search bourbon --limit 20 \
| jq -r '.[].productCode' \
| while read code; do
vabc --json inventory check "$code" --near 22182 2>/dev/null \
| jq --arg c "$code" '
select(.store.quantity > 0)
| {productCode: $c, quantity: .store.quantity, storeNumber: .store.storeNumber}
'
done \
| jq -s 'sort_by(.quantity) | reverse'

All nearby stores that stock a product, sorted by distance

inventory check returns the anchor store plus nearbyStores ranked by distance. Merge them and filter for stock > 0:

Terminal window
vabc --json inventory check 953714 --near 22182 \
| jq '[.store, .nearbyStores[]] | map(select(.quantity > 0)) | sort_by(.distance)'

The --allocated flag filters on the server side, but you can also post-filter in jq to be explicit:

Terminal window
vabc --json product search --allocated \
| jq '[.[] | select(.allocated == true) | {productCode, name, retailPrice}]'

Or combine it with --select to skip the jq projection entirely:

Terminal window
vabc --json product search --allocated --select productCode,name,retailPrice,allocated

Store numbers nearest a location

Terminal window
vabc --json store near 22182 --limit 5 \
| jq -r '.[].storeNumber'

Extract warehouse stock for a product

Terminal window
vabc --json inventory warehouse 953714 \
| jq '{code: .productCode, warehouse: .warehouseInventory}'

Check if a lottery product is allocated and has active events

Terminal window
vabc --json lottery check 953714 \
| jq '{allocated: .allocated, active: .active, events: (.eventLinks | length)}'

The allocated field comes from the live product catalog record; active and eventLinks come from the live limited-availability hook. Both are present in the same response object.

Handle errors in a pipeline

Redirect stderr to capture the structured error, check the exit code:

Terminal window
result=$(vabc --json inventory check 010807 --store 219 2>/tmp/vabc_err)
rc=$?
if [ $rc -ne 0 ]; then
code=$(jq -r '.code' /tmp/vabc_err 2>/dev/null)
echo "failed: $code (exit $rc)"
exit $rc
fi
echo "$result" | jq '.store.quantity'

Throttle and retry

vabc maintains a persistent cross-process throttle. If a call is blocked, the default behavior is to fail fast with exit 7 rather than wait. For scripts that can afford to wait, use --wait:

Terminal window
vabc --json --wait inventory check 010807 --near 22182

--max-wait sets the ceiling (default 30 seconds):

Terminal window
vabc --json --wait --max-wait 60s inventory check 010807 --near 22182

In a loop, check for exit 7 and sleep before retrying rather than hammering the endpoint:

Terminal window
for code in 010807 953714; do
while true; do
vabc --json inventory check "$code" --store 219
rc=$?
[ $rc -ne 7 ] && break
echo "rate limited, sleeping 5s" >&2
sleep 5
done
done

Or simply pass --wait and let vabc handle the backoff for you.

Machine-readable schema

vabc schema --json prints the full command tree, all flags, the exit-code table, and the live throttle state. Useful for programmatic introspection:

Terminal window
vabc schema --json | jq '.exitCodes'

See Commands reference and Flags and environment variables for the full reference. For agent-oriented usage (tool definitions, prompt-injection fencing), see For agents.