View as Markdown

Command-line tool

upheron lists your monitors and their status, checks a website on the spot, and keeps your workspace in a file: export it, change it, review the difference and apply it, by hand or from CI. It works on every plan, Free included, and uses only the public API, within your plan and the rate limits.

It is one JavaScript file with no dependencies, for Node.js 20 or later or Bun, downloaded from this site. The current version is 1.0.0, and its SHA-256 is:

830ff4d31b8c008d53eb93229f7f03790bfe29615921c54cb7a840826c5da5cb

Install

On macOS and Linux, download it, check it against the SHA-256 above and put it on your PATH:

curl -fsSLO https://upheron.com/downloads/upheron \
  && echo "830ff4d31b8c008d53eb93229f7f03790bfe29615921c54cb7a840826c5da5cb  upheron" | shasum -a 256 -c \
  && chmod +x upheron && mkdir -p ~/.local/bin && mv upheron ~/.local/bin/

Linux without shasum has sha256sum -c instead. On Windows, download upheron, compare Get-FileHash upheron with the SHA-256 above, and run it as node upheron. The checksum is also at /downloads/upheron.sha256. To update, download it again; upheron version says which version you have.

Sign in

Create a token in Settings → API tokens (see Authentication): read is enough to list, check, export and diff; apply needs write. Give it to upheron in the UPHERON_API_KEY environment variable, or save it once:

upheron login

login reads the token without showing it, checks it, and saves it in ~/.config/upheron/config.json (%APPDATA%\upheron\config.json on Windows) readable only by you. upheron refuses a config file that others can read. UPHERON_API_KEY wins over the file; upheron logout deletes it.

Commands

Command What it does
upheron monitors Every monitor with its status, kind, target and last check.
upheron monitor <name or id> One monitor: status, uptime over 24 hours, 7 and 30 days, certificate and domain expiry, open incidents and vulnerability findings.
upheron check <url> Checks a public website (or pings a public IPv4 address) now, from UpHeron's server: ten a minute.
upheron export [-o file] Writes the workspace's contacts, monitors, status pages and maintenance windows as YAML, or JSON with -o file.json or --format json.
upheron diff <file> Shows what apply would change.
upheron apply <file> Creates and updates what the file describes.

Every command takes --json for machine-readable output. Exit codes:

Code Meaning
0 Done: no changes (diff), the website is up (check), applied (apply).
1 diff found changes, or check found the website down or unreachable.
2 A mistake in the command or the file, such as an unknown field or a name used twice.
3 The API refused the request (its message is shown) or could not be reached.

Monitoring as code

Start from your workspace as it is:

upheron export -o upheron.yaml
version: 1
contacts:
  - name: Ops email
    kind: email
    destination: [email protected]
monitors:
  - name: Shop
    kind: http
    url: https://shop.example.com
    interval_seconds: 60
    locations: [fra-1, nyc-1]
    keyword: Add to cart
    contacts: [Ops email]
  - name: Nightly backup
    kind: heartbeat
    heartbeat_grace_seconds: 600
    contacts: [Ops email]
status_pages:
  - name: Example status
    slug: example-status
    components: [Shop, { monitor: Nightly backup, display_name: Backups }]
    appearance: { theme: dark }
maintenance_windows:
  - name: Database upgrade
    monitor: Shop
    starts_at: "2026-12-01T02:00:00Z"
    ends_at: "2026-12-01T03:00:00Z"
  - name: Backup window
    starts_at: "2026-12-01T02:00:00+01:00"
    ends_at: "2026-12-01T02:30:00+01:00"
    recurrence: { frequency: daily }

Change it, then upheron diff upheron.yaml and upheron apply upheron.yaml. How the file is read:

  • Names are the keys. Each item is matched with the one of the same name in the workspace, so names must be unique within a section, in the file and among what the file lists in the workspace. Renaming an item in the file creates a new one. Contacts, monitors and tabs are named in references too: a monitor's contacts, tab and escalation_policy, a status page's components, a maintenance window's monitor (left out, the window covers every monitor).
  • What is left out is left alone. A section the file does not have is not managed, and neither is a field an item does not give: export leaves out fields at their default, so if you want a default kept, write it. The fields are those of the API (paused: true pauses a monitor).
  • Deleting needs --delete. Items of a managed section that the file does not list are shown as deletions but kept; upheron apply --delete deletes them. --dry-run shows what apply would do. Maintenance windows that have ended are never exported, changed or deleted; a repeating one has ended once it has no occurrences left.
  • Write-only fields are those the API never returns: a contact's destination, token and options, a monitor's request_headers, request_body and repository_token, and check options such as transaction steps. They are sent when the item is created; --write-secrets sends them again. Keep secrets out of the file in the repository; the export shows a contact's destination only as a destination_hint. A contact's kind and destination, and a monitor's kind, cannot change: give the new one another name.
  • A maintenance window's recurrence (repeating windows) is compared by the keys the file gives, so { frequency: daily } matches a rule the API filled in with its interval and time zone; a change sends the file's rule, and the API fills in the rest again. Occurrences skipped or moved in the dashboard are not in the file and stay as they are.
  • check_options are sent whole. Changing one option sends all the options in the file, and options it does not give are removed, so list every option of a check you change, write-only ones included.
  • When the file manages status pages, monitors it creates get no status page of their own. New monitors are created with an Idempotency-Key, so a retry never makes a second one; upheron waits out rate limits and retries what is safe to retry.

JSON files work the same way, and YAML may use the usual block and flow styles, quotes, comments and | blocks; anchors and tags are not supported.

In CI

Review changes to the file in pull requests and apply them when they are merged. In GitHub Actions, with a write token saved as the secret UPHERON_API_KEY:

name: Monitoring
on:
  pull_request:
    paths: [upheron.yaml]
  push:
    branches: [main]
    paths: [upheron.yaml]
jobs:
  upheron:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - name: Install upheron
        run: |
          curl -fsSLO https://upheron.com/downloads/upheron
          curl -fsSL https://upheron.com/downloads/upheron.sha256 | sha256sum -c
          chmod +x upheron
      - name: Show the changes
        if: github.event_name == 'pull_request'
        run: ./upheron diff upheron.yaml || [ $? -eq 1 ]
        env:
          UPHERON_API_KEY: ${{ secrets.UPHERON_API_KEY }}
      - name: Apply
        if: github.event_name == 'push'
        run: ./upheron apply upheron.yaml
        env:
          UPHERON_API_KEY: ${{ secrets.UPHERON_API_KEY }}

To fail a scheduled job when someone changed the workspace by hand, run upheron diff upheron.yaml: it exits 1 when the workspace and the file differ. Runners have Node.js; elsewhere, install Node.js 20 or later or Bun first. To pin a version, check the download against its SHA-256 from this page instead of the .sha256 file: an update then stops the job until you take it.

Command-line tool · UpHeron