> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anomalyarmor.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Overview

> Install and use the armor CLI for scripting, automation, and CI/CD integration

<div aria-hidden="true" style={{position:"absolute",width:"1px",height:"1px",overflow:"hidden",clip:"rect(0,0,0,0)",whiteSpace:"nowrap"}}>For LLM agents: documentation index at <a href="/llms.txt" tabIndex={-1}>/llms.txt</a>, full text at <a href="/llms-full.txt" tabIndex={-1}>/llms-full.txt</a>. Append .md to any page URL for plain markdown.</div>
Stop bad data before it reaches production. The `armor` CLI lets you gate deployments on data freshness, check quality in CI/CD pipelines, and automate monitoring setup.

```bash theme={null}
# Gate your pipeline on data freshness
armor freshness check snowflake.prod.warehouse.orders || exit 1
```

## Installation

```bash theme={null}
pip install anomalyarmor-cli
```

This installs both the Python SDK and the `armor` CLI command.

## Authentication

### Login with API Key

```bash theme={null}
# Interactive prompt
armor auth login

# Non-interactive (for CI/CD)
armor auth login --key aa_live_your_key_here
```

Credentials are stored in `~/.armor/config.yaml`.

### Check Auth Status

```bash theme={null}
armor auth status
```

Output:

```
Authenticated as: your-email@company.com
API Key: aa_live_k8jd...9z4f
Organization: Acme Corp
```

### Logout

```bash theme={null}
armor auth logout
```

## Commands

### Assets

```bash theme={null}
# List all assets
armor assets list

# Filter by source
armor assets list --source snowflake

# Filter by type
armor assets list --type table

# Get single asset
armor assets get snowflake.prod.warehouse.orders
```

### Freshness

```bash theme={null}
# Get freshness summary
armor freshness summary

# List all freshness statuses
armor freshness list

# Get freshness for specific asset
armor freshness get snowflake.prod.warehouse.orders

# Check freshness (exit 0 if fresh, exit 1 if stale)
armor freshness check snowflake.prod.warehouse.orders

# Trigger refresh
armor freshness refresh snowflake.prod.warehouse.orders

# Trigger and wait for completion
armor freshness refresh snowflake.prod.warehouse.orders --wait
```

### Schema

```bash theme={null}
# Get schema drift summary
armor schema summary

# List recent schema changes
armor schema changes

# Trigger schema check
armor schema refresh snowflake.prod.warehouse.orders --wait
```

### Lineage

```bash theme={null}
# List assets with lineage
armor lineage list

# Get lineage for asset
armor lineage get snowflake.prod.warehouse.orders

# Get only upstream
armor lineage get snowflake.prod.warehouse.orders --direction upstream

# Get only downstream
armor lineage get snowflake.prod.warehouse.orders --direction downstream
```

### Alerts

```bash theme={null}
# Get alerts summary
armor alerts summary

# List all alerts
armor alerts list

# Filter by status
armor alerts list --status triggered

# Filter by asset
armor alerts list --asset snowflake.prod.warehouse.orders
```

### Metrics

```bash theme={null}
# Get metrics summary for an asset
armor metrics summary <asset-id>

# List all metrics for an asset
armor metrics list <asset-id>

# Filter by type
armor metrics list <asset-id> --type null_percent

# Get specific metric details
armor metrics get <asset-id> <metric-id>

# Create a row count metric
armor metrics create <asset-id> --type row_count --table snowflake.prod.warehouse.orders

# Create a null percentage metric
armor metrics create <asset-id> --type null_percent --table snowflake.prod.warehouse.orders --column email

# Trigger manual capture
armor metrics capture <asset-id> <metric-id>

# Delete a metric
armor metrics delete <asset-id> <metric-id> --yes
```

### API Keys (Admin)

```bash theme={null}
# List your API keys
armor api-keys list

# Create new key
armor api-keys create --name "airflow-prod" --scope read-only

# Revoke key
armor api-keys revoke <key-id>
```

## Exit Codes

| Code | Meaning                            |
| ---- | ---------------------------------- |
| 0    | Success                            |
| 1    | Check failed (e.g., data is stale) |
| 2    | Authentication error               |
| 3    | Resource not found                 |
| 4    | Rate limited                       |

### Using in Scripts

```bash theme={null}
#!/bin/bash

# Gate pipeline on freshness
if armor freshness check snowflake.prod.warehouse.orders; then
    echo "Data is fresh, running pipeline..."
    dbt run
else
    echo "Data is stale, aborting"
    exit 1
fi
```

## Output Formats

### Table (Default)

```bash theme={null}
armor assets list
```

```
QUALIFIED NAME                        TYPE    SOURCE     ROWS
snowflake.prod.warehouse.orders       table   snowflake  1.5M
snowflake.prod.warehouse.customers    table   snowflake  250K
snowflake.prod.warehouse.products     table   snowflake  10K
```

### JSON

```bash theme={null}
armor assets list --format json
```

```json theme={null}
[
  {
    "qualified_name": "snowflake.prod.warehouse.orders",
    "asset_type": "table",
    "source": "snowflake",
    "row_count": 1500000
  }
]
```

## Configuration File

The CLI stores configuration in `~/.armor/config.yaml`:

```yaml theme={null}
api_key: aa_live_your_key_here
api_url: https://api.anomalyarmor.ai
```

### Environment Variables

Override config file with environment variables:

```bash theme={null}
export ARMOR_API_KEY="aa_live_xxx"
export ARMOR_API_URL="https://api.anomalyarmor.ai"
```

## CI/CD Examples

### GitHub Actions

```yaml theme={null}
- name: Check data freshness
  env:
    ARMOR_API_KEY: ${{ secrets.ARMOR_API_KEY }}
  run: |
    pip install anomalyarmor-cli
    armor freshness check snowflake.prod.warehouse.orders
```

### GitLab CI

```yaml theme={null}
check_freshness:
  script:
    - pip install anomalyarmor-cli
    - armor freshness check snowflake.prod.warehouse.orders
  variables:
    ARMOR_API_KEY: $ARMOR_API_KEY
```

## Next Steps

<CardGroup cols={2}>
  <Card title="CLI Reference" icon="book" href="/cli/reference">
    Complete command reference
  </Card>

  <Card title="Python SDK" icon="python" href="/sdk/overview">
    Use programmatically in Python
  </Card>

  <Card title="Airflow Integration" icon="wind" href="/integrations/airflow">
    Use in Airflow DAGs
  </Card>

  <Card title="API Reference" icon="code" href="/api/overview">
    REST API documentation
  </Card>
</CardGroup>

## Common Questions

### How do I use the CLI in GitHub Actions or GitLab CI?

Install it with `pip install anomalyarmor-cli`, set `ARMOR_API_KEY` from your secrets store, and run `armor freshness check <asset>`. The non-zero exit code on stale data fails the step cleanly. The "CI/CD Examples" section above has copy-paste snippets for both runners.

### What does each exit code mean in scripts?

`0` is success, `1` is a check failure (stale data, validity fail), `2` is auth, `3` is not-found, and `4` is rate-limited. Write shell guards against the specific codes you care about (`if [ $? -eq 1 ]; then ...`) rather than treating any non-zero as the same error.

### How do I get machine-readable output from the CLI?

Pass `--format json` on any list or get command. The output is a raw JSON array (or object) suitable for piping into `jq`, other CLIs, or uploading as a CI artifact. The default table format is optimized for terminal reading only.

### Where does the CLI store credentials and how do I override them?

`armor auth login` writes `api_key` and `api_url` to `~/.armor/config.yaml`. The `ARMOR_API_KEY` and `ARMOR_API_URL` environment variables override the config file, which is what you want in CI where you shouldn't write secrets to disk.

### Can I use the CLI non-interactively for CI?

Yes. `armor auth login --key aa_live_...` skips the interactive prompt, and every command reads `ARMOR_API_KEY` directly if you prefer not to persist a config file at all. Most CI pipelines just set the env var and run commands without ever calling `auth login`.
