---
title: 'CLI'
description: 'Complete reference for the Yorker CLI: all commands, flags, and environment variables.'
section: 'Reference'
canonical_url: 'https://yorkermonitoring.com/docs/reference/cli'
---

# CLI

The Yorker CLI manages monitors, alerts, SLOs, notification channels, and private locations. Use it for infrastructure-as-code deployments from `yorker.config.yaml`, or manage resources imperatively with CRUD commands.

---

## Installation

Install globally with npm:

```bash
npm install -g @yorker/cli
```

On macOS or Linux you can also install with Homebrew:

```bash
brew install reverse-sweep-ltd/tap/yorker
```

Or locally in a project:

```bash
npm install --save-dev @yorker/cli
```

---

## Authentication

For interactive use, run `yorker login`. The CLI prints a short `XXXX-XXXX` confirmation code, opens your browser, and waits for you to click Authorize. On success it stores a fresh API key at `~/.yorker/credentials` (mode 0600).

```bash
yorker login
```

For CI, Docker, and other headless contexts, set `YORKER_API_KEY` instead. Generate a key from **Settings > API Keys** in the dashboard:

```bash
export YORKER_API_KEY=sk_your_key_here
```

The CLI resolves auth in this order on every invocation:

1. `YORKER_API_KEY` environment variable
2. `~/.yorker/credentials` (written by `yorker login`)
3. Otherwise, the command exits with code `2` (authentication failure).

The same precedence applies to the API URL via `--api-url`, `YORKER_API_URL`, the persisted file, then the default `https://yorkermonitoring.com`.

---

## Global Flags

These flags are available on every command:

| Flag | Description |
|---|---|
| `--json` | Output in structured JSON format. |
| `--quiet` | Suppress non-essential output. |
| `--no-color` | Disable colored output. |
| `--verbose` | Enable verbose/debug output. |
| `--api-url <url>` | Control plane URL (default: `https://yorkermonitoring.com`). Also settable via `YORKER_API_URL`. |
| `--help`, `-h` | Show help. |
| `--version`, `-V` | Show version. |

---

## Output safety

The CLI prints text it did not write: monitor and project names from your config, names and messages from the API, response bodies from `yorker test`. So that a name cannot take over a terminal or a CI job, everything written to stdout and stderr is cleaned, in every command:

| What | What happens to it |
|---|---|
| Terminal escape sequences other than plain colours (cursor movement, clear screen, window title, clipboard, terminal queries) | Each control character is replaced with a space. |
| Other control characters, and the characters that reorder text on screen | Replaced with a space. Tabs and line breaks are kept. |
| CI log commands: `::error::` and the like at the start of a line (GitHub Actions), and `##[`, `##vso[`, `##teamcity[` and other `##word[` service messages anywhere (GitHub, Azure Pipelines, TeamCity) | Broken up (`: :error::`, `# #[`) so the runner does not act on them. |

In `--json` output the same characters are written as `\uXXXX` escapes instead, so a JSON parser gives you back exactly the original value.

In the plan that `yorker deploy` and `yorker diff` print, each name and field value is also kept to a single line, so a name cannot add a line that looks like part of the plan. Elsewhere a name can still contain a line break or a colour code; nothing more.

---

## Environment Variables

| Variable | Required | Default | Description |
|---|---|---|---|
| `YORKER_API_KEY` | Yes, unless logged in via `yorker login` | - | API key for authentication. Keys start with `sk_`. |
| `YORKER_API_URL` | No | `https://yorkermonitoring.com` | Control plane base URL. Override for self-hosted or development. |

---

## Exit Codes

| Code | Meaning |
|---|---|
| `0` | Success. |
| `1` | General error (validation failure, API error, missing config). |
| `2` | Authentication failure (invalid or missing API key). |
| `3` | Plan/quota limit exceeded. |
| `4` | Partial failure (some operations succeeded, others failed). |
| `5` | Drift detected: remote resources were modified outside the CLI. |
| `10` | `yorker status` reports one or more unhealthy monitors. |

---

## Commands

### `yorker login`

Authenticate the CLI by approving access in your browser.

```bash
yorker login [--force]
```

The CLI uses a device-code flow:

1. The CLI calls the server to get a fresh `XXXX-XXXX` confirmation code that expires in 10 minutes.
2. It prints the code in your terminal and opens your browser to the consent page.
3. You sign in (if you weren't already), confirm the code in the browser matches the one in your terminal, then click **Authorize**.
4. The CLI polls every 2 seconds for the result. On success it picks up a fresh API key labelled `CLI <hostname>` and writes it to `~/.yorker/credentials` with mode `0600`.

Confirming the code is the phishing protection. If the code in the browser doesn't match the one in your terminal, you are on a different device's consent page; cancel and run `yorker login` again. You can revoke the key any time from **Settings > API Keys**, or with `yorker logout --revoke`.

If `~/.yorker/credentials` already exists, `yorker login` exits without re-authenticating. Pass `--force` to mint a new key and overwrite the file.

| Flag | Description |
|---|---|
| `--force` | Re-authenticate and overwrite existing credentials. |

The standard global flags `--api-url`, `--json`, and `--quiet` work here too. Use `--api-url` to authenticate against a non-default control plane (e.g. self-hosted or staging).

#### Auth resolution order

The CLI looks up auth in this order on every invocation, including immediately after `yorker login`:

1. `YORKER_API_KEY` environment variable
2. `~/.yorker/credentials`
3. Otherwise, the command exits with code `2` (authentication failure).

This means a `YORKER_API_KEY` set in your shell wins over a stored credential. If you want to switch teams temporarily, set the env var; to switch permanently, run `yorker logout` then `yorker login` again.

#### Example output

TTY success path:

```
  Yorker login

  Open this URL in your browser:
    https://yorkermonitoring.com/cli/auth?code=ABCD-EFGH

  Confirm this code matches the one shown there:

    ┌─────────────┐
    │  ABCD-EFGH  │
    └─────────────┘

  Waiting for authorization...

  ✓ Logged in
    Saved credentials to /Users/you/.yorker/credentials

  Next steps:
    1. yorker init    scaffold a yorker.config.yaml
    2. yorker deploy  push monitors to https://yorkermonitoring.com
```

#### `--json` output

```json
{
  "ok": true,
  "data": {
    "apiUrl": "https://yorkermonitoring.com",
    "credentialsPath": "/Users/you/.yorker/credentials",
    "createdAt": "2026-05-09T14:23:00.000Z"
  }
}
```

When credentials already exist and `--force` is not set, the JSON envelope is `{ "ok": true, "data": { "alreadyLoggedIn": true, "credentialsPath": "..." } }`.

Stdout receives exactly one JSON envelope per invocation (the success or error result). After the device code is minted, a one-line progress event is written to **stderr** so CI scripts that want the verification URL can read it without affecting the parseable stdout payload:

```
{"event":"awaiting_consent","code":"ABCD-EFGH","verification_url":"https://yorkermonitoring.com/cli/auth?code=ABCD-EFGH"}
```

Subsequent commands use the persisted credential unless `YORKER_API_KEY` is set in the env, which always wins (see [Auth resolution order](#auth-resolution-order)).

#### Error envelope

When login fails (the 10-minute code TTL was reached without authorization, a network error during init, etc.), the JSON envelope is:

```json
{
  "ok": false,
  "error": {
    "code": "general_error",
    "message": "Login session expired. Run `yorker login` again.",
    "details": {
      "exitCode": 1
    }
  }
}
```

The same envelope shape is used for every CLI command in `--json` mode. The `code` field uses the strings from the [exit code table](#exit-codes) (`auth_failure` for code 2, `plan_limit` for code 3, etc.).

#### Stale-tab safety

The consent page only mints a key when you click Authorize, so closing the tab before clicking does not produce an orphaned key. The code expires after 10 minutes, after which the CLI prints a clean error and you can run `yorker login` again. Each run mints a fresh code, so an old verification URL pulled from your browser history will simply land on a "Code expired" page instead of authorizing access.

---

### `yorker logout`

Sign out by deleting local credentials.

```bash
yorker logout [--revoke]
```

Removes `~/.yorker/credentials`. The API key remains valid on the server unless you also pass `--revoke`, which calls `DELETE /api/api-keys/self` to delete the key on the server. The endpoint identifies the key from the Authorization header, so no key ID has to be supplied; the row whose hash matches the bearer token is removed. Revoke is best-effort: if the network call fails, the local file is still removed so you do not get stuck holding a credential the CLI considers active. After `--revoke` succeeds, the key cannot be reused.

| Flag | Description |
|---|---|
| `--revoke` | Also delete the API key on the server (via `/api/api-keys/self`). Best-effort; the local file is removed even if the server call fails. |

`--json` and `--quiet` work as on every other command.

#### `--json` output

```json
{
  "ok": true,
  "data": {
    "removed": true,
    "revoked": true,
    "revokeError": null,
    "credentialsPath": "/Users/you/.yorker/credentials"
  }
}
```

`alreadyLoggedOut: true` is added when the local file did not exist. When `--revoke` is set and the server call fails, `revoked` is `false` and `revokeError` is a string describing the failure (the local file is still removed).

#### Error envelope

```json
{
  "ok": false,
  "error": {
    "code": "general_error",
    "message": "...",
    "details": { "exitCode": 1 }
  }
}
```

---

### `yorker init`

Scaffold a new monitoring config in the current directory. Interactive prompts guide you through project name, first monitor URL, type, and frequency. In non-interactive contexts (CI, `--json`, or a non-TTY shell) you must pass `--url` (and optionally the other fields) as flags or the command errors out.

```bash
yorker init [--name <name>] [--url <url>] [--type <type>] [--frequency <freq>] [--format file|directory] [--force]
```

| Flag | Description |
|---|---|
| `--name <name>` | Project name (skips prompt). |
| `--url <url>` | First monitor URL (skips prompt). Required in non-interactive contexts. |
| `--type <type>` | Monitor type: `http`, `browser`, or `mcp` (skips prompt). Default: `http`. |
| `--frequency <freq>` | Check frequency, e.g. `30s`, `5m`, `1h` (skips prompt). Default: `5m`. |
| `--format <format>` | Output layout: `file` (a single `yorker.config.yaml`, the default) or `directory` (a `.yorker/` directory with one YAML file per resource). |
| `--force` | Overwrite existing config without asking. |

The generated config uses a single default location (`loc_us_east`) and the frequency you choose. Free-tier accounts support one location per check; edit the file to add more locations on a paid plan. HTTP monitors get a starter `status_code: 200` assertion; browser monitors get a `./monitors/<name>.ts` script stub placeholder; MCP monitors just get the endpoint URL.

---

### `yorker deploy`

Push your local `yorker.config.yaml` to the control plane. Computes a diff against remote state, displays a Terraform-style plan, and applies changes.

```bash
yorker deploy [--dry-run] [--prune] [--force] [--accept-remote] [--wait]
```

| Flag | Description |
|---|---|
| `--dry-run` | Show the deploy plan without applying changes. |
| `--prune` | Delete remote resources not defined in the local config. |
| `--force` | Overwrite remote changes (ignore drift). Local config wins. |
| `--accept-remote` | Skip drifted resources, keeping their remote changes. |
| `--wait` | After a successful create, poll for the first check result from each new monitor (3-minute overall timeout). Exits with code `4` (`PARTIAL_FAILURE`) if any new check's first result is a failure, or if waiting for a first result times out. Useful in CI to catch broken monitors before merging. |

> `--force` and `--accept-remote` are mutually exclusive: pass one or the other, not both.

#### Deploy pipeline

1. **Load**: reads `yorker.config.yaml` from the current directory.
2. **Interpolate**: resolves `{{secrets.NAME}}`, `{{env.NAME}}`, and `${NAME}` placeholders from environment variables.
3. **Validate**: parses every resource through shared Zod schemas. Fails with all errors collected.
4. **Resolve**: applies cascading defaults (defaults to group to monitor), reads browser script files, builds API payloads.
5. **Fetch remote state**: gets all checks, alerts, SLOs, channels, and maintenance windows from the API.
6. **Detect drift**: compares remote `updatedAt` timestamps against the stored deploy state. See [Drift detection](#drift-detection) below.
7. **Compute plan**: field-level diffs between local and remote state.
8. **Display plan**: Terraform-style plan output.
9. **Apply**: if not `--dry-run`, applies changes in ordered phases.
10. **Save state**: writes `.yorker/.deploy-state.json` with config hashes and remote timestamps.

#### Deploy phases

Changes are applied in dependency order:

| Phase | Action | Why |
|---|---|---|
| 0 | Create/update notification channels | Channels must exist before alerts or SLOs reference them. |
| A | Delete SLOs | Must be deleted before their parent checks. |
| B | Delete alerts | Must be deleted before their parent checks. |
| C | Delete checks | Safe after dependent resources removed. |
| D+E | Create and update checks | New checks get server-assigned IDs needed by alerts and SLOs. |
| E2 | Sync check labels | Labels are a separate API, applied after checks exist so new check IDs are known. |
| F | Create/update alerts | Alerts reference check IDs and channel IDs. |
| G | Create/update SLOs | SLOs reference check IDs and channel IDs. |
| H | Create/update maintenance windows | Maintenance windows reference check IDs, so they run after checks exist. |
| I | Delete maintenance windows (only with `--prune`) | Stale maintenance windows are only removed when you opt in via `--prune`. |
| Z | Delete channels | Runs last so alerts/SLOs referring to channels are gone first. Delete only runs when `--prune` is set, or when a channel's `type` changed in YAML (type changes require delete-and-recreate). |

#### Plan output

```
Yorker deploy plan for "my-project"

  Channels:
    + CREATE  "ops-slack"
    = UNCHANGED  "team-email"

  Checks:
    + CREATE  http  "Users API"  (60s, 3 locations)
    ~ UPDATE  http  "Homepage"
        ~ configJson.timeoutMs  30000 -> 15000
    - DELETE  http  "Old Endpoint"
    = UNCHANGED  http  "Orders API"

  Alerts:
    + CREATE  "api-down" (Users API)

  SLOs:
    ~ UPDATE  "Homepage SLO"
        ~ targetBasisPoints  9990 -> 9995

  Summary: 2 to create, 2 to update, 1 to delete, 2 unchanged
```

| Symbol | Meaning |
|---|---|
| `+` CREATE | Resource will be created. |
| `~` UPDATE | Resource will be updated. Field-level diffs shown below. |
| `-` DELETE | Resource will be deleted (requires `--prune` or type change). |
| `=` UNCHANGED | No action needed. |

#### Secrets in the plan

The plan shows what would change, not the credentials involved. This applies to the printed plan and to `--json` output from both `yorker deploy` and `yorker diff`.

- Values that came from your `secrets:` list are replaced with `***REDACTED***` wherever they appear, including in resource names and in errors the API returns while applying.
- Fields that hold credentials are masked whatever their value, which covers a token that was rotated and is no longer in your environment. These are `auth` user names, tokens, passwords and API key values, a ServiceNow channel's user name and password, request, webhook and OTLP header values (apart from ordinary ones such as `Content-Type` and `User-Agent`), Slack webhook URLs, PagerDuty routing keys, and the user name, password and credential-style query parameters of a URL. A webhook channel's URL is shown as its origin only.

- A request `body` and a browser `script` are free text that can hold a credential anywhere, so a change to either is reported without its content.

When a masked value changes, both sides are masked, so the plan says so instead of showing two identical masks:

```
    ~ UPDATE  http  "Orders API"
        ~ configJson.auth.token  (changed, value hidden)
```

> **Breaking in CLI 0.11.0.** Before 0.11.0, every entry in the `changes` array of `yorker deploy --json` and `yorker diff --json` had a `local` and a `remote` object holding the whole resource, credentials included. Both are removed. A script that read `changes[].local.type` should read `changes[].checkType`. Nothing replaces the rest of the two objects.

In `--json` output the same change has `"oldValue"` and `"newValue"` set to `***REDACTED***` and `"redacted": true`. Each entry in `changes` carries `type`, `kind`, `name`, `remoteId` and `fieldChanges`. Checks also carry `checkType`, and checks being created carry `frequencySeconds` and `locationCount`. An entry does not carry the full local or remote resource.

The path of a monitor URL or MCP endpoint is shown as written, because the CLI cannot tell a token in a path from an ordinary path segment. If a URL has a credential in its path, such as `https://api.example.com/hooks/<token>`, write it as `{{secrets.NAME}}` so the current value is masked. A previous value that has since been rotated is not masked in that case, so treat a plan that changes such a URL as sensitive.

Field masking goes by where a value sits. A credential written into a field that is not named like one, such as an assertion's expected value, is masked only when it comes from your `secrets:` list, so keep credentials in `auth`, in headers, or behind `{{secrets.NAME}}`.

#### Drift detection

The CLI tracks the state of each resource after every deploy in `.yorker/.deploy-state.json`. On the next deploy, it compares remote `updatedAt` timestamps against the stored state to detect resources modified outside the CLI (e.g., via the web UI).

| Local changed? | Remote changed? | Result |
|---|---|---|
| No | No | Unchanged; skip. |
| Yes | No | Normal update; proceed. |
| No | Yes | **Drift**: remote was edited outside the CLI. |
| Yes | Yes | **Conflict**: both local config and remote were changed. |

If drift or conflicts are detected, the deploy aborts with a report:

```
  Warning: 1 drifted, 1 conflicting resource(s) modified outside config

  Checks:
    ! DRIFT     "api-health"  (remote changed since last deploy)

  Alerts:
    ! CONFLICT  "api-health:latency"  (both local and remote changed)

  Use --force to overwrite remote changes, or --accept-remote to keep them.
```

Resolution options:

| Flag | Behavior |
|---|---|
| *(default)* | Abort with drift/conflict report. |
| `--force` | Local config wins; overwrite remote changes. |
| `--accept-remote` | Skip drifted/conflicting resources; keep remote as-is. |

The deploy state file `.yorker/.deploy-state.json` is per-machine state. Add it to your `.gitignore` to avoid committing it. Every successful `yorker pull` rewrites this file with a fresh snapshot of remote state, so the next deploy treats everything as a clean baseline.

---

### `yorker diff`

Show changes between local config and remote state without applying them.

```bash
yorker diff
```

Displays the same Terraform-style plan as `yorker deploy --dry-run`. Designed for CI pipelines and quick checks. See [CI/CD Integration](/docs/guides/ci-cd) for full workflow examples.

---

### `yorker pull`

Export remote monitors, alerts, SLOs, and notification channels to a local config. The reverse of `yorker deploy`.

```bash
yorker pull [--output <path>] [--format file|directory] [--monitor <name>] [--force]
```

| Flag | Description |
|---|---|
| `-o, --output <path>` | Output path. Default: `yorker.config.yaml` in file format, or `.yorker/` in directory format. |
| `--format <format>` | Output layout: `file` (single `yorker.config.yaml`, default) or `directory` (a `.yorker/` tree with one YAML file per resource). |
| `--monitor <name>` | Pull a single monitor by name or ID. |
| `--force` | Overwrite existing config file and scripts. |

Fetches all monitors, alerts, SLOs, and notification channels and writes a config file that `yorker deploy` can consume. Browser monitor scripts are extracted to `./monitors/<slug>.ts`, where `<slug>` is the monitor name lowercased with non-alphanumeric characters replaced by hyphens (e.g., `Login Flow` becomes `login-flow.ts`).

> **`yorker pull` does not export maintenance windows and overwrites your entire config file.** If you manage maintenance windows through YAML, running `pull` will erase them from your local file (remote maintenance windows are not touched, but they will not reappear in the re-pulled YAML). If you need to round-trip safely, either avoid `pull` on projects that use `maintenanceWindows`, or re-add them to the YAML after each pull. A subsequent `yorker deploy` without `--prune` leaves remote maintenance windows alone; `yorker deploy --prune` will delete any remote maintenance windows that are not in the (now empty) local YAML.

---

### `yorker import`

> **Coming soon.** The `import` command is a scaffold today: running it reports the selected source, the source and output paths, and a link to the changelog where the release will land, then exits with code `1`. The importers themselves ship in a follow-up release.

Import existing monitors from another synthetic monitoring tool into a Yorker config. The resulting YAML is ready to deploy with `yorker deploy`, with inline `TODO` comments on anything that doesn't translate cleanly.

```bash
yorker import --from <source> [--output <path>] [path]
```

| Flag / Argument | Description |
|---|---|
| `--from <source>` | **Required.** Source tool to import from. See supported sources below. |
| `--output <path>` | Directory to write the generated Yorker YAML into. Default: `.` (current directory). |
| `[path]` | Path to the source repo or config file (e.g. `./src/__checks__` for Checkly, `./tests` for a Playwright project). |

**Supported sources** (planned):

| Source | `--from` value |
|---|---|
| Checkly | `checkly` |
| Datadog Synthetics | `datadog-synthetics` |
| Better Stack | `better-stack` |
| Pingdom | `pingdom` |
| Grafana Synthetic Monitoring | `grafana-synthetic-monitoring` |
| Playwright | `playwright` |

Example (once available):

```bash
# Import a Checkly project
yorker import --from checkly ./src/__checks__

# Import a Playwright test suite as browser monitors
yorker import --from playwright ./tests --output ./yorker/
```

Watch the [changelog](/changelog) for release dates. Until the importers land, the [comparison pages](/compare) document the migration story for each source.

---

### `yorker validate`

Validate your config without deploying. Runs the full load, interpolate, and validate pipeline without contacting the API.

```bash
yorker validate
```

Validation includes YAML syntax, Zod schema validation, secret interpolation, browser script file existence, frequency range checks, name uniqueness, SLO/alert cross-references, channel resolution, and maintenance-window time ranges.

```
  Config is valid: 5 monitor(s), 2 SLO(s)
```

On failure, all errors are collected:

```
3 config error(s):

  monitors[Homepage].httpConfig.url: Invalid url
  monitors[Login Flow]: cannot read script file "./monitors/missing.ts"
  slos[API SLO]: references monitor "Nonexistent" which does not exist
```

---

### `yorker status`

Show a status overview of all monitors.

```bash
yorker status [--watch] [--interval <duration>]
```

| Flag | Description |
|---|---|
| `--watch` | Continuously refresh. In an interactive TTY the screen is cleared and redrawn in place. In `--json` mode each cycle emits a single newline-delimited JSON object. When stdout is piped (non-TTY, non-JSON), each snapshot is appended with a `--- Status @ <ISO-timestamp> ---` header. Press `Ctrl+C` to exit. |
| `--interval <duration>` | Refresh interval for `--watch` (default: `30s`, range: `5s` to `1h`). Ignored without `--watch`. |

Displays each monitor with its enabled/paused state, type, frequency, health, and recent-result sparkline. Exits with code `10` when any monitor is unhealthy.

---

### `yorker dashboard`

Open an interactive full-screen status dashboard in your terminal. Polls the API on a configurable interval and renders monitor health, recent results, and sparklines.

```bash
yorker dashboard [--interval <duration>]
```

| Flag | Description |
|---|---|
| `--interval <duration>` | Refresh interval (default: `30s`, range: `5s` to `1h`). |

**Keybindings** (list view):

| Key | Action |
|---|---|
| `↑` / `k` | Move selection up |
| `↓` / `j` | Move selection down |
| `Enter` | Open detail view for the selected monitor |
| `/` | Filter monitors by name |
| `r` | Refresh now (outside the polling interval) |
| `q` / `Ctrl+C` | Quit |

In the detail view, press `Esc` to return to the list, `q` to quit, or `r` to refresh.

This is the interactive TUI (singular `dashboard`). For installing HyperDX / ClickStack dashboard packs, see `yorker dashboards install` below.

> **`yorker dashboard` has no `--json` mode.** It is the one command that always draws a full-screen interface and needs an interactive terminal, so do not run it from a script, a CI job or an agent. The same data is available as JSON from other commands:
>
> | You want | Use |
> |---|---|
> | The health of every monitor, once | `yorker status --json` |
> | The same, refreshed on an interval (one JSON object per line) | `yorker status --watch --json` |
> | One monitor's configuration and state | `yorker monitors get <name-or-id> --json` |
> | Recent results for a monitor | `yorker results list <monitor> --json` |
> | Results as they arrive (one JSON object per line) | `yorker results tail <monitor> --json` |

---

### `yorker dashboards install`

Install pre-built Yorker dashboards into HyperDX (self-hosted) or ClickStack Cloud. See [Install Dashboards](/docs/guides/install-dashboards) for full setup.

```bash
# Self-hosted HyperDX
yorker dashboards install --hyperdx-api-key <your-key>

# ClickStack Cloud
yorker dashboards install --mode clickstack_cloud \
  --clickstack-org-id <org-uuid> \
  --clickstack-service-id <service-uuid> \
  --clickstack-api-key-id <key-id> \
  --clickstack-api-secret <key-secret>
```

| Flag | Description |
|---|---|
| `--mode <mode>` | `self_hosted` (default) or `clickstack_cloud` (env: `HYPERDX_MODE`) |
| `--hyperdx-api-key <key>` | HyperDX Personal API Access Key for self-hosted mode, not the Ingestion API Key (env: `HYPERDX_API_KEY`) |
| `--hyperdx-url <url>` | Override HyperDX API URL for self-hosted (default: `https://www.hyperdx.io`) |
| `--clickstack-org-id <id>` | ClickHouse Cloud organization ID (env: `CLICKSTACK_ORG_ID`) |
| `--clickstack-service-id <id>` | ClickHouse Cloud service ID (env: `CLICKSTACK_SERVICE_ID`) |
| `--clickstack-api-key-id <id>` | ClickHouse Cloud API key ID (env: `CLICKSTACK_API_KEY_ID`) |
| `--clickstack-api-secret <secret>` | ClickHouse Cloud API key secret (env: `CLICKSTACK_API_SECRET`) |
| `--packs <list>` | Comma-separated subset: `overview`, `deep-dive`, `slo`, `events`, `performance-forensics`, `third-party`, `anomaly-insights`, `tls-health` |
| `--force` | Skip duplicate check (may create additional copies) |

---

### `yorker log`

View config change history. Shows what changed, when, and how.

```bash
yorker log [--type <type>] [--name <name>] [--source <source>] [--limit <n>] [--offset <n>]
```

| Flag | Description |
|---|---|
| `--type <type>` | Filter by resource type (`check`, `alert`, `slo`, `channel`). |
| `--name <name>` | Filter by resource name (case-insensitive substring match). |
| `--source <source>` | Filter by change source (`ui`, `yaml`, `api`). |
| `--limit <n>` | Number of changes to show (default: 20, max: 200). |
| `--offset <n>` | Skip first N changes for pagination (cannot be used together with `--name`). |

```
  Config changes (showing 5):

  Time     Action  Type     Name             Source
  2m ago   create  check    api-health       yaml
  5m ago   update  alert    api-health:p95   ui
  1h ago   delete  channel  old-slack        yaml
  2h ago   update  slo      availability     api
  3h ago   create  check    login-flow       yaml
```

Use `--json` for machine-readable output in CI pipelines.

---

### `yorker test`

Run HTTP monitors locally against their configured URLs and evaluate their assertions. Uses the same config pipeline as deploy, so all defaults, auth, and secrets are applied identically, and the same assertion logic as the hosted runners, so a monitor that passes here is judged the same way in production.

```bash
yorker test [--allow-private-network]
```

| Flag | Description |
|---|---|
| `--allow-private-network` | Allow requests to private, loopback, and link-local addresses, such as `localhost` or a staging host on your own network. |

```
Running monitors locally...

  HTTP Homepage ... 200 (142ms)  2/2 assertions passed
  HTTP Users API ... 200 (89ms)  1/3 assertions failed
    ✗ body_json_path: JSONPath $.data.total: expected equals 10, got undefined
  Browser Login Flow (4 steps)
    1. Navigate
    2. Log in
    3. Dashboard loads
    4. Check account
    Browser monitors require remote execution: use `yorker deploy` then check results
  MCP Docs Server
    MCP monitors require remote execution: use `yorker deploy` then check results

  1 passed, 1 failed
```

The command exits with code `1` when any HTTP monitor fails, either because the request itself failed or because an assertion did not hold, so it can gate a deploy in a script or CI job.

> **Changed in 0.9.0.** Earlier versions did not evaluate assertions and always exited `0`. If a script runs `yorker test` for information only, use `yorker test || true`. See the [changelog](/changelog/2026-10-08-yorker-test-assertions).

What a local run covers:

| | Behavior |
|---|---|
| HTTP monitors | Request sent from your machine; `status_code`, `response_time`, `body_contains`, `body_matches`, `body_json_path`, `header_value`, and `ssl_expiry` assertions evaluated. |
| `openapi_conformance` assertions | Reported as skipped. They need the stored API spec and run on hosted checks only. |
| A monitor with no assertions | Passes on any response, as it does when hosted. The output says so when the status is 4xx or 5xx. |
| Browser and MCP monitors | Listed (browser monitors with their step markers) but not executed. Deploy them and view results remotely. |

`response_time` is measured from your machine, so it can differ from what a hosted location sees.

#### Private addresses

By default `yorker test` refuses to send a request to a private, loopback, or link-local address, on the first URL and on every redirect. This is the same policy hosted locations enforce, and it matters in CI: without it, a config change in a pull request could point the command at a cloud metadata endpoint or an internal service and read the response back from a failed assertion.

To test against `localhost` or a host on your own network, pass `--allow-private-network`. Remember that a hosted location cannot reach that address either; monitor it from a [private location](/docs/guides/private-locations).

#### Redirects

Redirects are followed by the hosted runner's rules: `followRedirects` and `maxRedirects` are honoured, a `303` becomes a `GET`, and credentials are dropped when a redirect crosses origins. The response body is read exactly as sent, without decompression. A local run is stricter than a hosted one in two ways when a redirect crosses origins, because it has your secrets in its environment: it removes any request header whose value contains a secret from your config's `secrets:` list, and it will not resend a request body, failing with an explanation instead. Hosted runs send both. See [Redirects and credentials](/docs/reference/configuration#yorker-test-is-stricter) for the comparison.

Values from your config's `secrets:` list are redacted from the output, and long strings quoted from a response are truncated, since this output usually ends up in a CI log.

In `--json` mode, each HTTP result carries `passed`, `status`, `responseTimeMs`, an `assertions` array (`type`, `passed`, `expected`, `actual`, `message`, and `actualTruncated: true` when `actual` is a shortened preview of a large value), a `skipped` array, and `error` when the request failed. A top-level `summary` gives `passed`, `failed`, and `notRun` counts.

---

### `yorker completions [shell]`

Generate shell completion scripts. Auto-detects your shell if the argument is omitted.

```bash
yorker completions        # auto-detect
yorker completions bash
yorker completions zsh
yorker completions fish
```

Pipe the output to the appropriate file for your shell. For example:

```bash
yorker completions zsh > ~/.zfunc/_yorker
```

---

### `yorker skills install`

Install the [Yorker agent skill](/docs/ai/skills) so coding agents such as Claude Code know how to write, deploy, and debug monitors. Does not require authentication.

```bash
yorker skills install [--target claude|agents] [--dir <path>] [--global] [--force]
```

| Flag | Description |
|---|---|
| `--target <agent>` | `claude` (default) installs to `.claude/skills/yorker/`. `agents` installs to `.agents/skills/yorker/`. |
| `--dir <path>` | Install into a specific skills directory. Overrides `--target`. |
| `--global` | Install into your home directory instead of the current project. Cannot be combined with `--dir`. |
| `--force` | Replace an existing install. |

In `--json` mode, returns `{ installed, path, files }`.

---

### `yorker skills show [reference]`

Print the skill to stdout, for agents without skill support. Pass a reference name (`config`, `browser-scripts`, `investigate`) to print that file instead.

```bash
yorker skills show >> AGENTS.md
yorker skills show config
```

In `--json` mode, returns `{ file, content, references }`.

---

## Monitor Commands

### `yorker monitors list`

List all monitors. The output includes each monitor's name, type, frequency, location count, and any labels attached to the check.

```bash
yorker monitors list [--type <type>] [--status <status>]
```

| Flag | Description |
|---|---|
| `--type <type>` | Filter by type: `http`, `browser`, or `mcp`. |
| `--status <status>` | Filter by status: `enabled` or `paused`. |

In `--json` mode, each monitor entry includes a `labels` array (omitted when label lookup failed, e.g. due to permissions or a transient API error).

---

### `yorker monitors get <name-or-id>`

Show detailed information about a monitor, including recent results.

```bash
yorker monitors get "Homepage"
yorker monitors get chk_abc123
```

Displays monitor details (ID, type, status, frequency, locations, URL or endpoint) and a table of recent results with response times and status codes.

---

### `yorker monitors create`

Create a new HTTP monitor imperatively. Browser and MCP monitors must be created via `yorker deploy` from YAML.

```bash
yorker monitors create --name "API Health" --type http --url https://api.example.com/health [--method GET] [--frequency 5m] [--locations loc_us_east,loc_eu_central]
```

| Flag | Required | Description |
|---|---|---|
| `--name <name>` | Yes | Monitor name. |
| `--type <type>` | Yes | Must be `http`. |
| `--url <url>` | Yes | URL to monitor. |
| `--method <method>` | No | HTTP method (default: `GET`). |
| `--frequency <freq>` | No | Check frequency (default: `5m`). |
| `--locations <ids>` | No | Comma-separated location IDs (default: all active hosted locations). |

---

### `yorker monitors edit <name-or-id>`

Edit an existing monitor.

```bash
yorker monitors edit "Homepage" --frequency 1m --add-location loc_eu_central
```

| Flag | Description |
|---|---|
| `--name <name>` | New monitor name. |
| `--frequency <freq>` | New frequency. |
| `--add-location <id>` | Add a location. |
| `--remove-location <id>` | Remove a location. |
| `--yes` | Skip confirmation prompt. |

---

### `yorker monitors delete <name-or-id>`

Delete a monitor and all its results and alert rules.

```bash
yorker monitors delete "Old Endpoint" [--yes]
```

Requires confirmation unless `--yes` is passed.

---

### `yorker monitors pause <name-or-id>`

Pause a running monitor.

```bash
yorker monitors pause "Homepage"
```

---

### `yorker monitors resume <name-or-id>`

Resume a paused monitor.

```bash
yorker monitors resume "Homepage"
```

---

### `yorker monitors analyze <name-or-id>`

Run a deep insights analysis on a monitor. Sends recent results and context to the Yorker insights engine and returns a classified summary (type, severity, confidence, summary text).

```bash
yorker monitors analyze "Homepage"
yorker monitors analyze chk_abc123
yorker monitors analyze chk_abc123 --json
```

Output in human mode:

```
  Type        degradation
  Severity    warning
  Confidence  0.87
  Summary     Response times increased 3x over the last hour across US-East,
              correlated with an upstream dependency slowdown.
  Model       claude-sonnet-5-5
  Generated   Apr 9, 2026, 3:23:04 PM UTC

  Deep analysis usage: 2/5 used for this resource.
```

In `--json` mode, emits the full validated response envelope (`insight`, `stale`, `deepAnalysisCount`, `deepAnalysisLimit`) under the standard `{ ok: true, data: ... }` envelope.

Deep analysis is rate-limited per monitor (5-minute cooldown between runs) and per team (100 per month). When rate-limited, the command exits with code `3` and prints a message explaining how long to wait or when the monthly quota resets.

---

## Results Commands

### `yorker results list <monitor>`

List check results for a monitor.

```bash
yorker results list "Homepage" [--limit 20] [--status success] [--since 24h]
```

| Flag | Description |
|---|---|
| `--limit <n>` | Number of results (default: `20`, max: `200`). |
| `--offset <n>` | Skip first N results for pagination. Cannot be combined with `--status` or `--since`. |
| `--status <status>` | Filter: `success`, `failure`, `error`, `timeout`. Applied client-side. |
| `--since <duration>` | Only show results from this period (e.g. `1h`, `24h`, `7d`). Applied client-side. |

> `--offset` is server-side pagination; `--status` and `--since` are client-side filters. Mixing them would produce inconsistent page sizes, so the CLI rejects the combination. Use `--limit` + re-run with a later `--since` if you need to page through filtered results.

---

### `yorker results get <monitor> <result-id>`

Show full details for a specific check result.

```bash
yorker results get "Homepage" res_abc123
```

Includes timing breakdown (DNS, TLS, TTFB, content transfer), assertions (pass/fail), screenshots, Web Vitals (browser monitors), tool-call results (MCP monitors), network requests, and console errors.

---

### `yorker results tail <monitor>`

Live-stream new results as they arrive. Long-running command that polls at a configurable interval.

```bash
yorker results tail "Homepage" [--interval 30s]
```

| Flag | Description |
|---|---|
| `--interval <duration>` | Poll interval (default: `30s`, range: `5s` to `1h`). |

```
  Tailing Homepage (every 30s, Ctrl+C to stop)

  Apr 9, 2026, 12:34:56 PM UTC  ✓ 200      US East Coast   142ms
  Apr 9, 2026, 12:35:26 PM UTC  ✓ 200      EU Central      89ms
  Apr 9, 2026, 12:36:56 PM UTC  ✗ timeout  US East Coast   30000ms  connection timeout
```

Timestamps are formatted as localized US English strings using the team's configured timezone (defaults to UTC). In `--json` mode, outputs one JSON object per result (newline-delimited).

---

## Alert Commands

### `yorker alerts list`

List alert instances.

```bash
yorker alerts list [--all] [--monitor "Homepage"] [--state active,acknowledged]
```

| Flag | Description |
|---|---|
| `--all` | Include resolved and recovered alerts (default: active and acknowledged only). |
| `--monitor <name-or-id>` | Filter by monitor. |
| `--state <states>` | Comma-separated states: `active`, `acknowledged`, `recovered`, `resolved`. |

The command returns at most 100 alert instances per invocation (the most recent by start time). For larger historical windows, use `yorker alerts history` or the REST API with pagination.

---

### `yorker alerts ack <instance-id>`

Acknowledge an active alert.

```bash
yorker alerts ack ainst_abc123
```

---

### `yorker alerts resolve <instance-id>`

Manually resolve an alert.

```bash
yorker alerts resolve ainst_abc123
```

---

### `yorker alerts analyze <instance-id>`

Run a deep insights analysis on an alert instance. Sends context about the alert (monitor, recent results, correlations) to the Yorker insights engine and returns a classified summary with a type, severity, confidence score, and summary text.

```bash
yorker alerts analyze ainst_abc123
yorker alerts analyze ainst_abc123 --json
```

Output in human mode matches `yorker monitors analyze`: labeled fields for `Type`, `Severity`, `Confidence`, `Summary`, `Model`, and `Generated`, followed by a usage footer.

In `--json` mode, emits the full validated response envelope (`insight`, `stale`, `deepAnalysisCount`, `deepAnalysisLimit`) under the standard `{ ok: true, data: ... }` envelope.

Deep analysis is rate-limited per alert instance (5-minute cooldown between runs) and per team (100 per month). When rate-limited, the command exits with code `3` and prints a message explaining how long to wait or when the monthly quota resets.

---

### `yorker alerts history`

Show alert history.

```bash
yorker alerts history [--monitor "Homepage"] [--since 7d] [--limit 20]
```

| Flag | Description |
|---|---|
| `--monitor <name-or-id>` | Filter by monitor. |
| `--since <duration>` | Time window (e.g. `30m`, `24h`, `7d`). |
| `--limit <n>` | Number of alerts (default: `20`, max: `200`). |

---

### `yorker alerts rules list`

List alert rules across monitors.

```bash
yorker alerts rules list [--monitor "Homepage"]
```

---

### `yorker alerts rules create`

Create a new alert rule with a single condition. For multi-condition rules, use `yorker.config.yaml` and `yorker deploy`.

```bash
yorker alerts rules create --monitor "Homepage" --condition "consecutive_failures >= 3" --channel nch_abc123 [--name "homepage-down"] [--severity critical]
```

| Flag | Required | Description |
|---|---|---|
| `--monitor <name-or-id>` | Yes | Monitor to attach the rule to. |
| `--condition <condition>` | Yes | Alert condition (see formats below). |
| `--channel <id>` | Yes | Notification channel ID (`nch_...`). |
| `--name <name>` | No | Optional rule name. |
| `--severity <level>` | No | Severity for SSL/certificate conditions: `critical`, `warning`, or `info`. Ignored for non-certificate conditions. |

#### Condition formats

| Syntax | Type |
|---|---|
| `consecutive_failures >= 3` | Trigger after N consecutive failures. |
| `response_time > 5000` | Trigger if response time exceeds N ms. |
| `multi_location >= 2` | Trigger if N+ locations fail simultaneously. |
| `ssl_expiry < 14` | Trigger if SSL cert expires within N days. |
| `ssl_certificate_changed` | Trigger when the leaf certificate fingerprint changes between runs. |
| `ssl_self_signed` | Trigger when a self-signed or untrusted-root certificate is detected. |
| `ssl_protocol < TLSv1.3` | Trigger when the TLS handshake negotiates a protocol older than the minimum. Allowed minimums: `TLSv1.2`, `TLSv1.3`. |

---

## Incident Commands

An incident groups correlated alerts. See [Incidents](/docs/concepts/incidents) for the lifecycle.

### `yorker incidents list`

```bash
yorker incidents list [--state <states>] [--severity <severities>] [--search <query>] [--page <n>] [--limit <n>]
```

| Flag | Description |
|---|---|
| `--state <states>` | Comma-separated: `active`, `open`, `acknowledged`, `auto_resolved`, `closed`, `reopened`. Default: `active` (open and acknowledged). |
| `--severity <severities>` | Comma-separated: `critical`, `warning`, `info`. |
| `--search <query>` | Free-text search on the incident title. |
| `--page <n>` | Page number (default: `1`). |
| `--limit <n>` | Page size (default: `50`, max: `100`). |

### `yorker incidents get <id>`

Show an incident's full detail: timeline, member alerts, and observations.

```bash
yorker incidents get inc_abc123
```

### `yorker incidents ack <id>`, `close <id>`, `reopen <id>`

```bash
yorker incidents ack inc_abc123
yorker incidents close inc_abc123 [--reason "Rolled back deploy"]
yorker incidents reopen inc_abc123 [--reason "Recurred"]
```

`--reason` is free text, up to 500 characters.

### `yorker incidents note <id>`

Append a note to the incident timeline.

```bash
yorker incidents note inc_abc123 --body "Suspect the 14:05 deploy"
```

### `yorker incidents analyze <id>`

Run a deep analysis on an incident: suspects, ruled-out causes, and next steps.

```bash
yorker incidents analyze inc_abc123 [--json]
```

### `yorker incidents watch`

Stream incident lifecycle events as newline-delimited JSON until interrupted.

```bash
yorker incidents watch [--interval <duration>] [--from <iso>] [--state <states>] [--severity <severities>] [--events <types>]
```

| Flag | Description |
|---|---|
| `--interval <duration>` | Poll interval (default: `10s`, range: `5s` to `1h`). |
| `--from <iso>` | ISO-8601 start instant. Only used on the first poll. |
| `--state <states>` | Filter by incident state. |
| `--severity <severities>` | Filter by incident severity. |
| `--events <types>` | Filter by event type. |

---

## Location Commands

The `yorker locations` command group manages private locations and runner keys.

### `yorker locations list`

List your private locations. By default only private locations are shown; pass `--all` to include the 14 hosted locations as well.

```bash
yorker locations list          # private locations only
yorker locations list --all    # private + hosted
```

| Flag | Description |
|---|---|
| `--all` | Include hosted locations in the output. |

Shows each location's ID, type (`hosted` / `private`), display name, region, health status, and (for private locations) the agent's version and last heartbeat. The Agent column says when a newer agent release is available, and any assigned monitors the agent cannot run are listed under the table with the reason.

---

### `yorker locations create`

Create a private location and auto-provision an initial runner key.

```bash
yorker locations create --name <slug> --display-name "<name>" [--region <id>]
```

| Flag | Required | Description |
|---|---|---|
| `--name <slug>` | Yes | Unique lowercase slug (e.g. `staging-eu`). |
| `--display-name <name>` | Yes | Human-readable display name. |
| `--region <id>` | No | Region identifier (default: `private`). |

The runner key secret is printed **once**; save it immediately. The command also prints a ready-to-run Docker snippet for starting the runner.

---

### `yorker locations delete <location-id>`

Delete a private location. Fails if any monitors still reference it. Also revokes every runner key associated with the location. The argument is the location ID (`loc_...`).

```bash
yorker locations delete loc_staging_eu [--yes]
```

---

### `yorker locations keys list <location-id>`

List runner keys for a private location. Only the key ID, name, prefix, and last-used time are returned; the secret is never exposed again after creation.

```bash
yorker locations keys list loc_staging_eu
```

---

### `yorker locations keys create <location-id>`

Provision a new runner key for a private location. The secret is printed **once**, followed by a ready-to-run Docker snippet.

```bash
yorker locations keys create loc_staging_eu [--name "<label>"]
```

| Flag | Description |
|---|---|
| `--name <label>` | Optional label for the key (useful when a location has multiple runners). |

---

### `yorker locations keys revoke <location-id> <key-id>`

Revoke a runner key by its ID (`rkey_...`). Any runners using the revoked key lose access immediately.

```bash
yorker locations keys revoke loc_staging_eu rkey_abc123 [--yes]
```

---

## CI/CD Integration

Validate on push, preview changes on PRs, deploy on merge. See the full [CI/CD Integration guide](/docs/guides/ci-cd) for complete GitHub Actions and GitLab CI workflows with PR commenting and JSON output parsing.

```yaml
# GitHub Actions: quick start
- run: npm install -g @yorker/cli
- run: yorker validate                          # every push
- run: yorker diff                              # PR preview
- run: yorker deploy --force                    # merge to main (CI owns the config)
  if: github.ref == 'refs/heads/main'
```

Use `--force` in automated pipelines where the config file is the source of truth. Use `--accept-remote` if you want CI to skip resources that were edited manually.

Set `YORKER_API_KEY` and any `YORKER_SECRET_*` variables at the job or workflow level so all steps (including `validate`) can resolve `{{secrets.*}}` placeholders.

---

## Command Tree

```
yorker
├── login [--force]
├── logout [--revoke]
├── init [--name] [--url] [--type] [--frequency] [--format file|directory] [--force]
├── deploy [--dry-run] [--prune] [--force] [--accept-remote] [--wait]
├── diff
├── pull [--output] [--format file|directory] [--monitor] [--force]
├── validate
├── status [--watch] [--interval]
├── test [--allow-private-network]
├── dashboard [--interval]               # interactive TUI
├── dashboards
│   └── install [--mode] [--hyperdx-api-key] [--clickstack-*] [--packs]
├── log [--type] [--name] [--source] [--limit] [--offset]
├── completions [bash|zsh|fish]
├── import --from <source> [--output] [path]  # coming soon
├── skills
│   ├── install [--target] [--dir] [--global] [--force]
│   └── show [reference]
├── monitors
│   ├── list [--type] [--status]
│   ├── get <name-or-id>
│   ├── create --name --type [--url] [--method] [--frequency] [--locations]
│   ├── edit <name-or-id> [--name] [--frequency] [--add-location] [--remove-location] [--yes]
│   ├── delete <name-or-id> [--yes]
│   ├── pause <name-or-id>
│   ├── resume <name-or-id>
│   └── analyze <name-or-id>
├── results
│   ├── list <monitor> [--limit] [--offset] [--status] [--since]
│   ├── get <monitor> <result-id>
│   └── tail <monitor> [--interval]
├── alerts
│   ├── list [--all] [--monitor] [--state]
│   ├── ack <instance-id>
│   ├── resolve <instance-id>
│   ├── history [--monitor] [--since] [--limit]
│   ├── analyze <instance-id>
│   └── rules
│       ├── list [--monitor]
│       └── create --monitor --condition --channel [--name] [--severity]
├── incidents
│   ├── list [--state] [--severity] [--search] [--page] [--limit]
│   ├── get <id>
│   ├── ack <id>
│   ├── close <id> [--reason]
│   ├── reopen <id> [--reason]
│   ├── note <id> --body
│   ├── analyze <id>
│   └── watch [--interval] [--from] [--state] [--severity] [--events]
└── locations
    ├── list [--all]
    ├── create --name --display-name [--region]
    ├── delete <location-id> [--yes]
    └── keys
        ├── list <location-id>
        ├── create <location-id> [--name]
        └── revoke <location-id> <key-id> [--yes]
```
