Scripting + CI
Turn common store operations into reliable CI jobs and repeatable runbooks.
Exit codes, idempotency, GitHub Actions example, polling vs webhooks, error handling, concurrency.
Patterns for using the CLI from shell scripts, CI pipelines, and local automation. Stay --json-first, pipe to jq, and treat exit codes seriously.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success. |
| 1 | Unknown / generic error. |
| 2 | Invalid arguments. |
| 3 | Authentication failure (401). |
| 4 | Authorization failure (403, scope mismatch). |
| 5 | Not found (404). |
| 6 | Conflict / state guard (409, 422). |
| 7 | Rate limited (429). |
| 8 | Network / transport. |
Idempotent operations
Always set --idempotency-key on state-changing commands in CI. A retried script run with the same key replays cleanly:
KEY="ci-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" aly-store-cli orders fulfill ord_72...4b \ --carrier USPS --tracking 940011... \ --idempotency-key "$KEY"GitHub Actions example
name: Import productson: workflow_dispatch: jobs: run: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v1 - run: bun install - name: Import env: ALY_API_KEY: ${{ secrets.ALY_API_KEY_PROD }} run: | jq -c '.[]' products.json | while read row; do slug=$(echo "$row" | jq -r .slug) name=$(echo "$row" | jq -r .name) price=$(echo "$row" | jq -r .price_cents) bun tools/aly-store-cli.ts products create \ --site-slug acme \ --slug "$slug" \ --name "$name" \ --price "$price" \ --idempotency-key "import-$slug" \ --direct --json donePolling vs webhooks
For event-driven work, prefer webhooks — register an endpoint, let Aly push. Polling is fine for one-shot scripts but never for a long-running loop; you'll hit the rate limit.
Error handling
set -euo pipefail # Fail fast on auth issues, but absorb a transient rate limitif ! out=$(aly-store-cli orders list --status pending --json); then case $? in 3|4) echo "Auth problem — fix the key"; exit 1;; 7) echo "Rate limited — retrying in 30s"; sleep 30; out=$(aly-store-cli orders list --status pending --json);; *) echo "Unknown failure"; exit 1;; esacfiecho "$out" | jq '.[].id'--direct in CI scripts. The MCP transport is useful for human + agent parity but adds latency and JSON-RPC framing overhead. Direct mode is consistently faster and easier to debug.Concurrency
The per-principal rate limit applies to the bearer, not the process. Parallel xargs with high concurrency will hit it fast. Cap at 5 concurrent calls in CI; back off on a 429.
Was this page helpful?