vrk assert
Try it in your browser
# Exits 0 when the condition holds and 1 when it does not. Change 0 to 50 to see it fail.
Press RUN. Nothing leaves your browser.files you can cat:
Edit the command and press RUN. Open the full playground for more recipes, or install vrk to run it on your own files.
vrk assert evaluates conditions mid-pipeline and stops the flow if a check fails.
The problem
Schema validation catches missing fields and wrong types. It does not catch wrong values. An LLM returns {“status”:“error”,“message”:“rate limited”} and the schema passes because status is a string. The garbage ends up in your database. You find out when a user reports it.
The solution
vrk assert evaluates conditions on pipeline data and stops the flow if a check fails. In JSON mode it runs gojq expressions. In text mode it checks substrings or regex patterns. Data passes through on success, so you can put it between any two pipeline stages as a gate.
Before and after
Before
echo "$RESPONSE" | jq -e '.status == "ok"' > /dev/null
if [ $? -ne 0 ]; then exit 1; fi
echo "$RESPONSE" | next-step
# data doesn't pass through, must re-read
After
echo $RESPONSE | vrk assert '.status == "ok"' | next-step
Example
echo '{"status":"ok","count":42}' | vrk assert '.count > 0'
Exit codes
| Code | Meaning |
|---|---|
| 0 | All conditions passed; input passed through to stdout |
| 1 | Assertion failed, or runtime error |
| 2 | No condition specified, mixed modes, invalid regex, interactive TTY |
Flags
| Flag | Short | Type | Description |
|---|---|---|---|
--contains | string | Assert stdin contains this literal substring | |
--matches | string | Assert stdin matches this regular expression. Complex patterns with many alternations reduce throughput on large streams. | |
--message | -m | string | Custom message on failure |
--json | -j | bool | Emit errors as JSON to stdout |
--quiet | -q | bool | Suppress stderr output on failure |
JSON mode
vrk assert checks JSON input against gojq expressions and exits 1 if a condition is false. If every condition passes, the input goes to stdout unchanged.
Basic conditions
$ echo '{"status":"ok","count":42}' | vrk assert '.status == "ok"'
{"status":"ok","count":42}
$ echo $?
0
$ echo '{"status":"error"}' | vrk assert '.status == "ok"'
assert: assertion failed: .status == "ok"
$ echo $?
1
The message goes to stderr. Stdout is empty.
Common gojq expressions
# Check a field exists and has a value
echo "$JSON" | vrk assert '.items | length > 0'
# Check a numeric threshold
echo "$JSON" | vrk assert '.confidence >= 0.8'
# Check for null/absence
echo "$JSON" | vrk assert '.error == null'
# Multiple conditions (all must pass)
echo "$JSON" | vrk assert '.status == "ok"' '.items | length > 0'
Custom failure message
$ echo '{"score":0.3}' | vrk assert '.score >= 0.8' -m 'Confidence too low for production'
assert: assertion failed: Confidence too low for production (.score >= 0.8)
$ echo $?
1
The error shows your message first, then the failed condition in parentheses.
Text mode
vrk assert also checks plain text for a substring or a regex pattern.
–contains (substring check)
$ echo 'deployment successful' | vrk assert --contains 'successful'
deployment successful
$ echo $?
0
$ echo 'deployment failed' | vrk assert --contains 'successful'
assert: assertion failed: input does not contain "successful"
$ echo $?
1
–matches (regex check)
$ echo 'v2.3.1' | vrk assert --matches '^v[0-9]+\.[0-9]+\.[0-9]+$'
v2.3.1
$ echo $?
0
$ echo 'not-a-version' | vrk assert --matches '^v[0-9]+\.[0-9]+\.[0-9]+$'
assert: assertion failed: input does not match "^v[0-9]+\\.[0-9]+\\.[0-9]+$"
$ echo $?
1
The pattern is printed as a Go-quoted string, so each backslash is printed twice.
Pipeline integration
Guard between prompt and database
# Only store the result if it looks correct
echo "$INPUT" | \
vrk prompt --schema '{"answer":"string","confidence":"number"}' | \
vrk assert '.confidence >= 0.8' | \
vrk kv set --ns results latest
If confidence is below 0.8, assert exits 1 and the pipeline stops before writing to kv.
Validate API responses in a script
# Check that an API returned the expected shape
RESPONSE=$(curl -s https://api.example.com/health)
echo "$RESPONSE" | vrk assert '.status == "healthy"' '.uptime > 0' --quiet
if [ $? -ne 0 ]; then
echo "Health check failed" | vrk emit --level error --tag monitoring
exit 1
fi
Check LLM output before piping to emit
# Ensure the LLM returned real content, not an error
echo "$DOCUMENT" | \
vrk prompt --system 'Summarize this' | \
vrk assert --contains 'Summary' -m 'LLM did not return a summary' | \
vrk emit --tag summaries --level info
When it fails
Assertion failed (JSON mode):
$ echo '{"status":"error"}' | vrk assert '.status == "ok"'
assert: assertion failed: .status == "ok"
$ echo $?
1
Assertion failed (text mode):
$ echo 'hello' | vrk assert --contains 'goodbye'
assert: assertion failed: input does not contain "goodbye"
$ echo $?
1
No condition specified:
$ echo '{}' | vrk assert
usage error: assert: a condition expression is required
$ echo $?
2
If the input is empty and the condition is a JSON expression, assert exits 1. A check with nothing to test does not pass:
$ printf '' | vrk assert '.ok == true'
error: assert: no JSON records on stdin
$ echo $?
1
Each line must hold exactly one JSON value. A second value on the same line is a parse error, not a pass on the first:
$ echo '{"a":1} {"a":2}' | vrk assert '.a == 1'
assert: input is not valid JSON
$ echo $?
1
If a condition runs longer than 5 seconds, assert stops it and the assertion fails with condition timed out after 5s.