Scripting and CI¶
Global flags¶
--json and --quiet are declared once on the root canviq program and inherited by every command; they are not repeated per subcommand. This is the single authoritative reference for their behavior; other pages link back here rather than re-explain it.
canviq auth login and canviq mcp configure accept both flags without erroring (the parser never rejects them), but their action handlers ignore them. This is a documented no-op, not a bug. auth login always prompts interactively for your API key regardless of --quiet; since there's no non-interactive equivalent, use the CANVIQ_API_KEY environment variable instead (see Authentication). mcp configure always prints its normal output; use its own --print flag to change what it writes, not --json.
Every other command reads the merged flags and behaves as described below.
JSON output¶
Pass --json to get machine-readable output from any command.
When stdout is not a TTY (piped, redirected, or running in CI), the CLI switches to JSON output automatically. You do not need --json in most CI environments.
Quiet mode¶
Pass --quiet to suppress all stdout output except errors. The command still exits with the appropriate code, so scripts can check $? without parsing any output.
Piping with jq¶
canviq survey list --json prints a bare JSON array, not an object wrapping one, so index directly with .[] rather than .surveys[].
# List all survey IDs
canviq survey list --json | jq '.[].id'
# Get the PMF score as a plain number
canviq survey pmf-score srv_abc123 --json | jq '.score'
# Find surveys below 40% PMF
canviq survey list --json \
| jq -r '.[].id' \
| while read -r id; do
SCORE=$(canviq survey pmf-score "$id" --json | jq '.score // 0')
echo "$id: $SCORE%"
done
Exit codes¶
| Code | Name | When it fires |
|---|---|---|
0 | SUCCESS | Command completed |
1 | GENERAL | Unclassified runtime failure |
2 | BAD_ARGS | Invalid arguments or usage |
3 | AUTH | Missing or invalid credentials (401/403) |
4 | NOT_FOUND | Requested resource not found (404) |
5 | RATE_LIMITED | API rate limit hit (429) |
Scripts can branch on these codes:
canviq survey pmf-score srv_abc123 --json
case $? in
0) echo "Score retrieved" ;;
3) echo "Auth failed. Check CANVIQ_API_KEY" ;;
5) echo "Rate limited. Retry later" ;;
*) echo "Unexpected error" ;;
esac
CI/CD pattern¶
Set CANVIQ_API_KEY as a repository secret. The CLI auto-detects the non-TTY environment and outputs JSON.
# .github/workflows/pmf-check.yml
name: PMF Score Gate
on:
schedule:
- cron: '0 9 * * 1'
jobs:
pmf-check:
runs-on: ubuntu-latest
env:
CANVIQ_API_KEY: ${{ secrets.CANVIQ_API_KEY }}
SURVEY_ID: srv_abc123
steps:
# This step assumes canviq has been published to npm. Until that
# happens (tracked in issue #5721), replace it with the source-checkout
# steps from index.md's "Pre-launch: run from source" section.
- name: Install Canviq CLI
run: npm install -g @canviq/cli
- name: Check PMF score
run: |
RESULT=$(canviq survey pmf-score "$SURVEY_ID" --json)
INSUFFICIENT=$(echo "$RESULT" | jq -r '.insufficient_responses')
if [ "$INSUFFICIENT" = "true" ]; then
echo "Not enough responses yet. Skipping gate."
exit 0
fi
SCORE=$(echo "$RESULT" | jq '.score // 0')
echo "PMF score: ${SCORE}%"
if [ "$(echo "$SCORE < 40" | bc -l)" = "1" ]; then
echo "PMF score ${SCORE}% is below the 40% benchmark"
exit 1
fi
echo "PMF score ${SCORE}% meets the 40% benchmark"
Handling rate limits¶
The API rate limits vary by endpoint. When a request is rate limited, the CLI exits with code 5 and prints a retry hint if the Retry-After header is present.
until canviq audit-logs --json > audit.json; do
CODE=$?
if [ "$CODE" -eq 5 ]; then
echo "Rate limited. Waiting 60 seconds."
sleep 60
else
echo "Command failed with exit code $CODE"
exit "$CODE"
fi
done
See Troubleshooting for what triggers each exit code in practice (401 vs 403, the 422 unrecognized-key error, NO_COLOR, and rate limit specifics per command group).