# 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


---

# Agent Instructions: 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:

```
GET https://docs.clore.ai/guides/advanced/cli-automation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
