Skip to content

ht-cli: the HostTracker command line

View as Markdown

ht-cli is HostTracker’s official command-line client. Every operation of the REST API v2 is a command - monitors, incidents, contacts, alerts, reports, maintenance windows, status pages, webhooks and instant checks - generated from the same published OpenAPI document the API serves, so it cannot drift behind the API. It is built on the Go SDK, which gives it bearer auth, automatic idempotency keys on writes, retries that honour Retry-After and the RFC 9457 problem-document errors. Current release: 0.1.1, MIT licensed, source at github.com/HostTracker/cli.

Every channel installs the same binary.

Platform Command
Homebrew (macOS and Linux, shell completion included) brew install HostTracker/tap/ht-cli
curl installer (Linux or macOS, installs into ~/.local/bin) curl -fsSL https://raw.githubusercontent.com/HostTracker/cli/main/install.sh | sh
Windows (Scoop) scoop bucket add hosttracker https://github.com/HostTracker/scoop-bucket then scoop install ht-cli
Docker (for a CI job, nothing to install) docker run --rm -e HT_TOKEN ghcr.io/hosttracker/ht-cli:latest monitors list
Go 1.24 or newer go install github.com/HostTracker/cli/cmd/ht-cli@latest

Debian and Ubuntu (signed apt repository):

Terminal window
curl -fsSL https://hosttracker.github.io/apt/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/hosttracker.gpg
echo "deb [signed-by=/usr/share/keyrings/hosttracker.gpg] https://hosttracker.github.io/apt stable main" \
| sudo tee /etc/apt/sources.list.d/hosttracker.list
sudo apt update && sudo apt install ht-cli

Fedora and RHEL (dnf repository):

Terminal window
sudo curl -fsSL -o /etc/yum.repos.d/hosttracker.repo https://hosttracker.github.io/apt/rpm/hosttracker.repo
sudo dnf install ht-cli

Release binaries for Linux, macOS and Windows (amd64 and arm64), plus .deb, .rpm and .apk packages for a one-off install, are on the releases page. Verify the archive against checksums.txt and put ht-cli on your PATH. A winget package is waiting for review in the community repository and is not available yet.

Check the install with ht-cli version. Outside Homebrew, ht-cli completion bash|zsh|fish|powershell prints a completion script.

Update through the channel you installed with: sudo apt upgrade, sudo dnf upgrade, brew upgrade ht-cli, scoop update ht-cli, or docker pull ghcr.io/hosttracker/ht-cli. The curl installer and release binaries are reinstalls - run the installer again or replace the binary.

  1. Mint a token under Integrations -> API (/integrations/api) with the scopes the commands you plan to run need - see API authentication, tokens and scopes.

  2. Run:

    Terminal window
    ht-cli auth login

    It prompts for the token, verifies it against the API and stores it in a YAML file under your OS configuration directory, written with 0600 permissions. ht-cli config path prints where.

Other ways to supply the token:

  • --token <token> on a single command.
  • The HT_TOKEN environment variable - the usual choice in CI; no config file is needed.
  • Named profiles for several accounts: ht-cli auth login --profile staging stores a second token, and --profile staging selects it per command.

ht-cli auth status shows what is configured and ht-cli auth logout removes it. ht-cli config get|set reads and changes base-url and the default output.

Commands are grouped by API resource (monitors, contacts, status-pages, webhooks, jobs and so on). The command name follows the API operation: listMonitor becomes ht-cli monitors list, getMonitor becomes ht-cli monitors get <id>, bulkCreateMonitor becomes ht-cli monitors bulk-create.

  • Path parameters are positional arguments.
  • Query parameters are flags. --limit, --cursor, --sort, --expand and --fields work wherever the operation takes them.
  • A request body is --json '<inline>', --json @file.json or --json - (stdin); --set key=value builds a simple body without writing JSON.
  • --idempotency-key sets the header explicitly; otherwise the SDK adds one to every write.

A quick tour:

Terminal window
ht-cli monitors list # a table on a terminal, JSON when piped
ht-cli monitors get <monitor-id>
ht-cli check run https://example.com --type http --wait
ht-cli monitors create --json @monitor.json
ht-cli monitors bulk-update --json @edit.json # answers with a job id
ht-cli jobs wait <job-id>
ht-cli monitors list --output json | jq -r '.data[].url'

Hand-written convenience commands on top of the generated ones:

Command What it does
ht-cli check run <url> [--type http] [--pool ...] [--wait] Runs an instant check; --wait follows it to the result.
ht-cli jobs wait <job-id> Polls an asynchronous job until it finishes.
ht-cli webhooks verify --secret <s> --headers-file <file> < body Verifies a webhook delivery’s signature.
ht-cli api GET /monitor --query limit=5 --query state=down Calls any API path directly - the escape hatch for anything without a named command.
ht-cli docs Generates the command reference.
ht-cli version, ht-cli completion <shell> Version and shell completion.

Global flags: --output json|yaml|table (or -o), --all (follow nextCursor through every page), --base-url, --timeout, --no-retry, --verbose (prints each request, its status, request id and rate-limit budget to stderr, retries included).

The default is a table on a terminal and JSON when the output is piped, so ht-cli monitors list | jq needs no flag. The table view shows scalar fields, folds nested objects into a short marker and renders Unix-second timestamps as readable times. Anything a script depends on should ask for --output json explicitly.

Code Meaning
0 The command did what it was asked.
1 A failure with no more specific code.
2 The command line was wrong: an unknown flag, a missing argument, a bad value.
3 The credential is missing, rejected or under-scoped (invalid_token, missing_scope).
4 The address names nothing (not_found).
5 The API refused the request: validation, a conflict, a precondition.
6 Throttled, or the quota is exhausted.
7 The API could not be reached, or faulted.

A failure prints the problem document’s code, detail, the offending members and the request id to stderr; with -o json the whole problem document is printed. Exit code 6 covers two different causes: rate_limited is worth retrying, quota_exceeded is not - only the printed code tells them apart. See Error codes.

Store the token as a secret, export it as HT_TOKEN, and call ht-cli like any other tool. A deploy gate:

Terminal window
export HT_TOKEN="$HT_TOKEN_SECRET"
ht-cli check run https://staging.example.com --type http --wait

Pausing a monitor around a deploy:

Terminal window
ht-cli monitors update <monitor-id> --json '{"enabled":false}'
# ... deploy ...
ht-cli monitors update <monitor-id> --json '{"enabled":true}'

For a planned change that should not alert or count as downtime, a maintenance window is usually the better tool than pausing.

Monitors as code:

Terminal window
ht-cli monitors list --output json --all > monitors.json # export what you have
ht-cli monitors bulk-create --json @monitors.json # create from a file (answers with a job)

A monitor is unique per (url, type), so re-running a create for an address you already monitor answers 409 duplicate_monitor naming the existing id instead of creating a duplicate.

On GitHub Actions, the HostTracker Check action wraps the CLI for the common cases.