> For the complete documentation index, see [llms.txt](https://developer.celigo.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.celigo.com/cli/using-the-cli/scripting.md).

# Scripting patterns

The CLI is designed to compose with standard Unix tooling. A few patterns cover 90% of what you'll want to do in bash, PowerShell, or CI.

## Get a single field

```bash
celigo integrations get 5f83a9b2c7d3e8f1a2b3c4d5 --jq '.name'
```

Or pipe to jq:

```bash
celigo integrations get 5f83a9b2c7d3e8f1a2b3c4d5 --format json | jq -r '.name'
```

## Filter a listing client-side

Resource `list` commands don't take server-side filters (unlike `jobs list` and `audit list`). Filter in jq:

```bash
# All disabled flows
celigo flows list --jq '[.[] | select(.disabled) | ._id]'

# All flows in one integration
celigo flows list \
  --jq '[.[] | select(._integrationId == "5f83a9b2c7d3e8f1a2b3c4d5") | {_id, name, disabled}]'
```

`--jq` takes a single expression argument — it doesn't accept jq's own flags like `-r` or `--arg`. Inline any values directly into the expression. Plain-string results are emitted raw (no surrounding quotes) automatically, so you rarely need `-r`. When you do need jq flags, pipe `--format json` to a standalone `jq` instead.

## Bulk enable or disable

```bash
# Disable every flow whose name matches a pattern
celigo flows list --jq '.[] | select(.name | test("prod-v1-.*")) | ._id' \
  | xargs -I {} celigo flows set {} disabled=true
```

## Diff two accounts

```bash
celigo --profile prod integrations list --jq '.[] | .name' | sort > prod.txt
celigo --profile eu   integrations list --jq '.[] | .name' | sort > eu.txt

diff prod.txt eu.txt
```

## Per-file JSON dump (for Git diffs)

`celigo pull` is the built-in way: it writes the account (or one integration) as a tree of per-resource JSON files — one folder per integration, one file per flow, export, import, connection, script, and so on — with a manifest that lets `celigo status`, `celigo diff`, and `celigo push` work against it. Commit the tree and the diffs are Git diffs. See [The local tree](/cli/local-tree.md) and [pull](/cli/local-tree/pull.md).

```bash
# --no-symlinks writes links as pointer files, so the tree survives every platform's checkout
celigo pull --dir ./envs/prod --no-symlinks
git add envs/prod && git commit -m "Account snapshot $(date +%F)"
```

The manual alternative — one `get` per resource — still works when you want a flat dump of one resource type and nothing else:

```bash
mkdir -p snapshot/flows
celigo flows list --jq '.[]._id' | while read id; do
  celigo flows get "$id" --format json > "snapshot/flows/$id.json"
done
git add snapshot/ && git commit -m "Flow snapshot $(date +%F)"
```

For a live local index (fast search + dependency graph) use `celigo account snapshot` instead — it writes to `~/.celigo/indexes/<profile>.json`.

## CI: fail on lint

```bash
celigo account lint --format json \
  | jq -e '[.[] | select(.severity == "error")] | length == 0' \
  || { echo "Lint errors; see above."; exit 1; }
```

## CI gates for a pulled tree

A committed `celigo pull` tree gives a pipeline four gates, each an exit code. See [Workflow](/cli/local-tree/workflow.md) for the team workflow around the tree and [push](/cli/local-tree/push.md) for what a push refuses.

```bash
# The checkout matches its manifest (no edits committed without a push, no deploy left behind).
# Informational by default, like `git status`; --exit-code turns it into a gate.
celigo status --exit-code --dir envs/prod

# The files this change touched differ from the live account (exit 1 when anything differs).
celigo diff --exit-code --dir envs/prod

# Plan the push without writing anything: exit 1 when any planned item is refused —
# a half-merged file, invalid JSON, a document outside the tree's scope. Gated like push.
celigo push --dry-run --dir envs/prod

# Validate the tree against the platform's published API schemas, offline (no token needed).
celigo lint --dir envs/prod
```

`celigo lint` is a usable gate as it stands: its errors (a shape nothing on the account backs, the response-mapping object wrapper, an unparseable file) fail the run, and its warnings do not. `celigo lint --strict` — every warning an error — is **not** yet a usable gate: the published schemas are stricter than the API on real data, so a pristine pull of a real account produces warnings and `--strict` fails everything until the specs catch up.

Set `CELIGO_MODE=read` on the `diff` step and `CELIGO_MODE=full` on the `push --dry-run` step, so the dry run is gated exactly like the push it plans.

### Promote on merge: two tokens

`celigo promote --to <name>` writes a committed tree into ANOTHER account or environment, so the job holds two identities and the CLI keeps them apart by variable name: `CELIGO_API_TOKEN` (+ `CELIGO_BASE_URL`) is the source session's, and `CELIGO_TARGET_API_TOKEN` (+ `CELIGO_TARGET_BASE_URL`) is the target the `--to` profile names on a machine that has no such profile. The source token never stands in for the target: a job that sets only `CELIGO_API_TOKEN` is refused rather than writing the tree back into the source account. See [Promote](/cli/local-tree/promote.md).

```yaml
name: celigo-promote
on:
  push:
    branches: [main]
permissions:
  contents: write                                   # the target-file write-back commit
concurrency: celigo-promote-production            # one writer per target at a time
jobs:
  promote:
    runs-on: ubuntu-latest
    env:
      CELIGO_TARGET_API_TOKEN: ${{ secrets.CELIGO_PRODUCTION_TOKEN }}   # the TARGET's full-mode token
      CELIGO_TARGET_BASE_URL: ${{ secrets.CELIGO_PRODUCTION_BASE_URL }} # omit for https://api.integrator.io
      CELIGO_FORMAT: table
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      - run: npm install -g @celigo/celigo-cli
      - run: celigo promote --to production --dry-run      # exit 1 on any refusal: stop here
      - run: celigo promote --to production -y
      - name: Commit the target file write-back
        run: |
          git config user.name celigo-ci
          git config user.email celigo-ci@users.noreply.github.com
          git add .celigo/targets/production.json
          git diff --cached --quiet || git commit -m "Promote to production [skip ci]" && git push
```

The job needs no source token at all. Commit `.celigo/targets/production.json` after every promote — it holds the target's id map and the optimistic-lock tokens the next promote checks.

## Handling rate limits

The HTTP client retries a `429 Too Many Requests` automatically, up to 3 times. Since celigo-cli 2026.9.1 it honors the server's `Retry-After` header (delay-seconds or an HTTP-date), capped at 60 seconds; without the header it backs off exponentially. If you're still hitting the limit, you're sending requests too aggressively — reduce parallelism or add `sleep` between loops. For `pull`, `diff`, `push`, and `promote`, lower `--concurrency` (or `CELIGO_CONCURRENCY`; default 8).

## Idempotent upsert by name

```bash
ID=$(celigo connections list --jq '.[] | select(.name == "my-conn") | ._id' | head -n1)

if [ -z "$ID" ]; then
  ID=$(celigo connections create --file conn.json --format json | jq -r '._id')
fi

# Update specific fields; `set` is GET-modify-PUT so it's safe
celigo connections set "$ID" 'name=my-conn' 'http.baseURI=https://api.example.com'
```

## Exit codes

See [Exit codes](/cli/using-the-cli/exit-codes.md). The CLI returns `0` on success and `1` on any error; `push` and `promote` return `130` when interrupted with Ctrl-C.

```bash
if ! celigo flows get "$FLOW_ID" >/dev/null 2>&1; then
  echo "flow missing or fetch failed"
fi
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developer.celigo.com/cli/using-the-cli/scripting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
