# CLI Automation

{% hint style="success" %}
**Prerequisites:** Install the SDK (`pip install clore-ai`) and configure your API key. See the [Python Quickstart](https://docs.clore.ai/guides/getting-started/python-quickstart) if you haven't yet.
{% endhint %}

## Basic Workflow

The core loop: **search → deploy → connect → cancel**.

```bash
# 1. Find a GPU
clore search --gpu "RTX 4090" --max-price 2.0 --sort price --limit 5

# 2. Deploy (use a server ID from step 1)
clore deploy 142 \
  --image cloreai/ubuntu22.04-cuda12 \
  --type on-demand \
  --currency bitcoin \
  --ssh-password MySecurePass \
  --port 22:tcp \
  --port 8888:http

# 3. Check your orders
clore orders

# 4. SSH into the server
clore ssh 38

# 5. Cancel when done
clore cancel 38

# 6. Check wallet balance
clore wallets
```

***

## CLI Command Reference

| Command                               | Description                         |
| ------------------------------------- | ----------------------------------- |
| `clore search`                        | Search GPU marketplace              |
| `clore deploy <server_id>`            | Create a new order                  |
| `clore orders`                        | List active orders                  |
| `clore orders --completed`            | List all orders including completed |
| `clore ssh <order_id>`                | SSH into an active order            |
| `clore cancel <order_id>`             | Cancel an order                     |
| `clore wallets`                       | Show wallet balances                |
| `clore servers`                       | List your hosted servers            |
| `clore server-config <name>`          | Show server configuration           |
| `clore spot <server_id>`              | View spot market for a server       |
| `clore spot-price <order_id> <price>` | Set spot price for an order         |
| `clore config set <key> <value>`      | Set config value                    |
| `clore config get <key>`              | Get config value                    |
| `clore config show`                   | Show all config                     |

***

## Scripting with CLI

### Deploy and Wait for SSH

```bash
#!/bin/bash
# deploy-and-connect.sh — Deploy a server and SSH in when ready

set -euo pipefail

SERVER_ID=${1:?Usage: $0 <server_id>}
IMAGE=${2:-cloreai/ubuntu22.04-cuda12}
PASSWORD="AutoDeploy$(date +%s)"

echo "🚀 Deploying server $SERVER_ID..."
clore deploy "$SERVER_ID" \
  --image "$IMAGE" \
  --type on-demand \
  --currency bitcoin \
  --ssh-password "$PASSWORD" \
  --port 22:tcp

echo "⏳ Waiting for order to be ready..."
sleep 15

echo "📦 Active orders:"
clore orders

echo ""
echo "🔑 SSH password: $PASSWORD"
echo "💡 Connect with: clore ssh <order_id>"
```

### Find Cheapest GPU and Deploy

```bash
#!/bin/bash
# cheapest-gpu.sh — Find and deploy the cheapest GPU matching criteria

GPU_MODEL=${1:-"RTX 4090"}
MAX_PRICE=${2:-5.0}

echo "🔍 Searching for cheapest $GPU_MODEL under \$$MAX_PRICE/h..."
clore search --gpu "$GPU_MODEL" --max-price "$MAX_PRICE" --sort price --limit 5

echo ""
read -p "Enter server ID to deploy (or 'q' to quit): " SERVER_ID

if [ "$SERVER_ID" = "q" ]; then
    echo "Cancelled."
    exit 0
fi

read -sp "SSH password: " SSH_PASS
echo ""

clore deploy "$SERVER_ID" \
  --image cloreai/ubuntu22.04-cuda12 \
  --type on-demand \
  --currency bitcoin \
  --ssh-password "$SSH_PASS" \
  --port 22:tcp \
  --port 8888:http

echo "✅ Deployed! Check 'clore orders' for status."
```

### Cancel All Orders

```bash
#!/bin/bash
# cancel-all.sh — Cancel all active orders

echo "📦 Current orders:"
clore orders

echo ""
read -p "Cancel ALL active orders? (yes/no): " CONFIRM

if [ "$CONFIRM" = "yes" ]; then
    # Use Python one-liner since CLI cancels one at a time
    python3 -c "
from clore_ai import CloreAI
client = CloreAI()
orders = client.my_orders()
for o in orders:
    client.cancel_order(o.id, issue='Batch cleanup')
    print(f'Cancelled order {o.id}')
print(f'Done. Cancelled {len(orders)} orders.')
"
else
    echo "Cancelled."
fi
```

***

## CI/CD Integration

### GitHub Actions: Deploy GPU for Training

```yaml
# .github/workflows/train.yml
name: GPU Training

on:
  workflow_dispatch:
    inputs:
      gpu_model:
        description: 'GPU model'
        default: 'RTX 4090'
      max_price:
        description: 'Max price USD/h'
        default: '2.0'

env:
  CLORE_API_KEY: ${{ secrets.CLORE_API_KEY }}

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

      - name: Install clore-ai
        run: pip install clore-ai

      - name: Find and deploy GPU
        run: |
          python3 << 'EOF'
          import time, os
          from clore_ai import CloreAI

          client = CloreAI()

          # Find cheapest matching GPU
          servers = client.marketplace(
              gpu="${{ github.event.inputs.gpu_model }}",
              max_price_usd=float("${{ github.event.inputs.max_price }}")
          )
          servers.sort(key=lambda s: s.price_usd or float("inf"))

          if not servers:
              print("No servers available!")
              exit(1)

          best = servers[0]
          print(f"Deploying on server {best.id}: {best.gpu_model} @ ${best.price_usd:.4f}/h")

          order = client.create_order(
              server_id=best.id,
              image="cloreai/ubuntu22.04-cuda12",
              type="on-demand",
              currency="bitcoin",
              ssh_password=os.environ.get("SSH_PASSWORD", "CITraining123"),
              ports={"22": "tcp"},
              command="bash /workspace/train.sh"
          )

          print(f"Order {order.id} created")

          # Wait for ready
          for _ in range(30):
              orders = client.my_orders()
              o = next((x for x in orders if x.id == order.id), None)
              if o and o.pub_cluster:
                  print(f"Ready: {o.pub_cluster}")
                  break
              time.sleep(10)

          # Save order ID for cleanup
          with open(os.environ["GITHUB_ENV"], "a") as f:
              f.write(f"ORDER_ID={order.id}\n")
          EOF

      - name: Wait for training to complete
        run: |
          echo "Training in progress..."
          # Add your monitoring logic here
          sleep 60

      - name: Cleanup GPU
        if: always()
        run: |
          python3 -c "
          from clore_ai import CloreAI
          import os
          client = CloreAI()
          order_id = int(os.environ.get('ORDER_ID', 0))
          if order_id:
              client.cancel_order(order_id, issue='CI job complete')
              print(f'Cancelled order {order_id}')
          "
```

### GitLab CI: Batch Processing

```yaml
# .gitlab-ci.yml
gpu-batch-job:
  stage: process
  image: python:3.11
  variables:
    CLORE_API_KEY: $CLORE_API_KEY
  before_script:
    - pip install clore-ai
  script:
    - |
      python3 << 'EOF'
      from clore_ai import CloreAI
      import time

      client = CloreAI()

      servers = client.marketplace(gpu="RTX 4090", max_price_usd=3.0)
      if not servers:
          print("No GPUs available")
          exit(1)

      servers.sort(key=lambda s: s.price_usd or float("inf"))
      order = client.create_order(
          server_id=servers[0].id,
          image="cloreai/ubuntu22.04-cuda12",
          type="spot",
          currency="bitcoin",
          spot_price=0.00005,
          ports={"22": "tcp"}
      )
      print(f"Deployed: order {order.id}")

      # ... do work ...

      client.cancel_order(order.id)
      print("Done and cleaned up")
      EOF
  after_script:
    - |
      python3 -c "
      from clore_ai import CloreAI
      client = CloreAI()
      for o in client.my_orders():
          client.cancel_order(o.id, issue='CI cleanup')
      "
```

***

## Monitoring

### Check Orders Periodically

```bash
#!/bin/bash
# monitor.sh — Check orders every 60 seconds

while true; do
    echo "=== $(date) ==="
    clore orders
    clore wallets
    echo ""
    sleep 60
done
```

### Python Monitoring Script

```python
#!/usr/bin/env python3
"""monitor-orders.py — Monitor active orders and alert on issues."""

import time
from clore_ai import CloreAI

POLL_INTERVAL = 60  # seconds
LOW_BALANCE_THRESHOLD = 0.001  # BTC

def monitor():
    client = CloreAI()

    while True:
        try:
            # Check orders
            orders = client.my_orders()
            print(f"[{time.strftime('%H:%M:%S')}] Active orders: {len(orders)}")
            for o in orders:
                print(f"  Order {o.id}: type={o.type}, IP={o.pub_cluster or 'pending'}")

            # Check balance
            wallets = client.wallets()
            for w in wallets:
                if w.name.lower() == "bitcoin" and w.balance < LOW_BALANCE_THRESHOLD:
                    print(f"  ⚠️  Low BTC balance: {w.balance:.8f}")

        except Exception as e:
            print(f"  ❌ Error: {e}")

        time.sleep(POLL_INTERVAL)

if __name__ == "__main__":
    monitor()
```

***

## Batch Operations

### Deploy on Multiple Servers

```bash
#!/bin/bash
# batch-deploy.sh — Deploy on multiple servers

SERVER_IDS=(142 305 891 450)
IMAGE="cloreai/ubuntu22.04-cuda12"
PASSWORD="BatchRun$(date +%s)"

for SID in "${SERVER_IDS[@]}"; do
    echo "🚀 Deploying on server $SID..."
    clore deploy "$SID" \
      --image "$IMAGE" \
      --type on-demand \
      --currency bitcoin \
      --ssh-password "$PASSWORD" \
      --port 22:tcp \
      || echo "⚠️  Failed to deploy on $SID"
    sleep 6  # Respect rate limits
done

echo ""
echo "📦 All orders:"
clore orders
echo "🔑 Password: $PASSWORD"
```

### Batch Deploy with Python (Async)

```python
#!/usr/bin/env python3
"""batch-deploy.py — Deploy on multiple servers concurrently."""

import asyncio
from clore_ai import AsyncCloreAI
from clore_ai.exceptions import CloreAPIError

async def batch_deploy(server_ids, image="cloreai/ubuntu22.04-cuda12"):
    async with AsyncCloreAI() as client:
        tasks = [
            client.create_order(
                server_id=sid,
                image=image,
                type="on-demand",
                currency="bitcoin",
                ssh_password="BatchPass123",
                ports={"22": "tcp"}
            )
            for sid in server_ids
        ]

        results = await asyncio.gather(*tasks, return_exceptions=True)

        for sid, result in zip(server_ids, results):
            if isinstance(result, CloreAPIError):
                print(f"❌ Server {sid}: {result}")
            elif isinstance(result, Exception):
                print(f"❌ Server {sid}: {result}")
            else:
                print(f"✅ Server {sid}: Order {result.id}")

if __name__ == "__main__":
    import sys
    server_ids = [int(x) for x in sys.argv[1:]]
    if not server_ids:
        print("Usage: python batch-deploy.py 142 305 891")
        exit(1)
    asyncio.run(batch_deploy(server_ids))
```

Usage:

```bash
python batch-deploy.py 142 305 891
```

### Spot Market Scanner

```bash
#!/bin/bash
# spot-scanner.sh — Scan spot prices for a list of servers

SERVERS=(6 12 42 100)

echo "📊 Spot Market Scan — $(date)"
echo "---"

for SID in "${SERVERS[@]}"; do
    echo "Server $SID:"
    clore spot "$SID"
    echo ""
done
```

***

## Cron Jobs

### Daily GPU Price Check

```bash
# Add to crontab: crontab -e
# Run every day at 9 AM
0 9 * * * CLORE_API_KEY=your_key /usr/local/bin/clore search --gpu "RTX 4090" --sort price --limit 5 >> /var/log/clore-prices.log 2>&1
```

### Hourly Balance Check

```bash
# Check balance every hour
0 * * * * CLORE_API_KEY=your_key /usr/local/bin/clore wallets >> /var/log/clore-balance.log 2>&1
```

***

## Tips

1. **Always set `CLORE_API_KEY`** as an environment variable in scripts and CI
2. **Add `sleep 6`** between deploy commands in bash loops to respect rate limits
3. **Use `--type spot`** for batch/CI jobs — cheaper and interruptible is fine
4. **Cancel orders in `after_script`** / `if: always()` to avoid forgotten billing
5. **Store SSH passwords in secrets** (GitHub Secrets, GitLab CI Variables, etc.)
6. **Use `clore orders --completed`** to audit past usage

***

## Next Steps

* [Python SDK Guide](https://docs.clore.ai/guides/advanced/python-sdk) — Full SDK reference with async patterns
* [Batch Processing](https://docs.clore.ai/guides/advanced/batch-processing) — Process large AI workloads
* [API Integration](https://docs.clore.ai/guides/advanced/api-integration) — Connect AI services to your apps
