Aidelly Docs
CLI

CI/CD Integration

Use the Aidelly CLI in GitHub Actions and other CI/CD pipelines.

Post release announcements, changelogs, and other automated content directly from your CI/CD pipeline.

GitHub Actions

Announce on release

name: Announce release

on:
  release:
    types: [published]

jobs:
  announce:
    runs-on: ubuntu-latest
    steps:
      - name: Post release announcement
        env:
          AIDELLY_API_KEY: ${{ secrets.AIDELLY_API_KEY }}
          AIDELLY_WORKSPACE_ID: ${{ secrets.AIDELLY_WORKSPACE_ID }}
          AIDELLY_BRAND_ID: ${{ secrets.AIDELLY_BRAND_ID }}
        run: |
          npx @aidelly/cli post \
            --content "🚀 ${{ github.event.release.name }} just shipped! ${{ github.event.release.body }}" \
            --platforms linkedin,x \
            --publish-now

Schedule weekly digest

name: Weekly digest

on:
  schedule:
    - cron: '0 9 * * MON' # Every Monday at 9am UTC

jobs:
  digest:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Generate and post digest
        env:
          AIDELLY_API_KEY: ${{ secrets.AIDELLY_API_KEY }}
          AIDELLY_BRAND_ID: ${{ secrets.AIDELLY_BRAND_ID }}
        run: |
          CONTENT=$(cat scripts/weekly-digest.txt)
          npx @aidelly/cli post \
            --content "$CONTENT" \
            --platforms linkedin \
            --publish-now

Setting up secrets

In your GitHub repository:

  1. Go to Settings → Secrets and variables → Actions
  2. Add:
    • AIDELLY_API_KEY — your API key (starts with aidelly_live_)
    • AIDELLY_WORKSPACE_ID — your workspace UUID
    • AIDELLY_BRAND_ID — your brand UUID

Idempotency in CI/CD

Each CI run should use a stable idempotency key based on the run identifier. The CLI generates keys automatically, but if you're calling the API directly in scripts:

# Stable key for this specific release
IDEM_KEY="release-${{ github.run_id }}-${{ github.sha }}"

This ensures that if a step retries due to a transient failure, the post won't be created twice.

Error handling

set -e   # Exit on first error

npx @aidelly/cli post \
  --content "$ANNOUNCEMENT" \
  --platforms linkedin \
  --publish-now || {
    echo "Failed to post announcement"
    exit 1
  }

For non-blocking announcements (don't fail the pipeline if the post fails):

npx @aidelly/cli post \
  --content "$ANNOUNCEMENT" \
  --platforms linkedin \
  --publish-now || echo "Post failed (non-blocking)"

Machine-readable output (--json)

Use --json to get structured output suitable for parsing by scripts and CI systems.

npx @aidelly/cli post \
  --content "Release shipped!" \
  --platforms linkedin \
  --publish-now \
  --json

Success response:

{
  "success": true,
  "data": {
    "post_id": "abc123",
    "platform": "linkedin",
    "status": "scheduled",
    "scheduled_at": "2026-02-25T10:00:00Z"
  }
}

Error response:

{
  "success": false,
  "error": {
    "code": "PUBLIC_API_BODY_INVALID",
    "message": "Post content is required",
    "hint": "Pass --content with non-empty text"
  }
}

Parsing in bash:

RESULT=$(npx @aidelly/cli post --content "..." --publish-now --json)
STATUS=$(echo "$RESULT" | jq -r '.success')
POST_ID=$(echo "$RESULT" | jq -r '.data.post_id // empty')

if [ "$STATUS" = "true" ]; then
  echo "Posted: $POST_ID"
else
  ERROR=$(echo "$RESULT" | jq -r '.error.message')
  echo "Error: $ERROR"
  exit 1
fi

Breaking change (0.2.0)

As of CLI v0.2.0-beta.1, the --json format changed from raw output to a structured envelope. If you have existing scripts, update them to use .data or .error:

# Old (pre-0.2.0) — no longer works
RESULT=$(npx @aidelly/cli post ... --json)
POST_ID=$RESULT.post_id

# New (0.2.0+) — use .data wrapper
RESULT=$(npx @aidelly/cli post ... --json)
POST_ID=$(echo "$RESULT" | jq -r '.data.post_id')

Exit codes

The CLI returns standardized exit codes:

CodeMeaningExample
0SuccessPost created/scheduled successfully
1Command failedInvalid input, API error
2Non-interactive error (TTY mismatch)Prompt required but running in CI
3Auth errorInvalid API key, key expired

Handle in scripts:

npx @aidelly/cli post --content "..." --publish-now

case $? in
  0) echo "Success" ;;
  2) echo "Non-interactive environment; use --api-key" ;;
  3) echo "Auth failed; check AIDELLY_API_KEY" ;;
  *) echo "Error" ;;
esac

Non-TTY / Non-interactive behavior

When running in CI/CD (non-TTY environment), the CLI never hangs waiting for input. If a prompt is required and no flag is provided, it exits with code 2 (NonInteractiveError):

# This hangs in interactive terminal; exits with code 2 in CI
npx @aidelly/cli post

# In CI, must explicitly provide flags
npx @aidelly/cli post \
  --content "..." \
  --platforms linkedin \
  --publish-now

Other CI systems

The CLI works in any environment that has Node.js available. Set the same environment variables (AIDELLY_API_KEY, AIDELLY_WORKSPACE_ID, AIDELLY_BRAND_ID) and use npx @aidelly/cli or install globally first.

CircleCI:

- run:
    name: Post release announcement
    command: npx @aidelly/cli post --content "$ANNOUNCEMENT" --platforms x --publish-now

GitLab CI:

announce:
  script:
    - npx @aidelly/cli post --content "$ANNOUNCEMENT" --platforms linkedin --publish-now