Skip to content

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.

canviq survey list --json
canviq survey pmf-score srv_abc123 --json

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.

canviq survey publish srv_abc123 --quiet && echo "published"

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).