Skip to content
Docs/CLI

Agents & API

CLI

Manage monitors, wrap cron jobs with heartbeats, report incidents and mark deploys from a terminal, CI job or agent. Every command takes --json.

Install

npm install -g upbutler   # Node 18+
upbutler --help

The CLI has no runtime dependencies. It can also be compiled to a single binary with bun build --compile.

Log in

upbutler login --key ub_live_...       # verifies the key and saves it
echo "$KEY" | upbutler login --key -   # read the key from stdin
upbutler whoami
upbutler logout

The key is saved to ~/.config/upbutler/config.json (or $XDG_CONFIG_HOME/upbutler/config.json) with mode 0600. Flags win over environment variables, which win over the saved login:

FlagEnvironmentMeaning
--api-keyUPBUTLER_API_KEYAPI key
--base-urlUPBUTLER_BASE_URLAPI origin, default https://upbutler.com
wrap --heartbeatUPBUTLER_HEARTBEATHeartbeat URL, token or monitor id for wrap

Monitors

upbutler monitors ls
upbutler monitors add https://api.example.com/health --name "Search API" --page acme --group APIs
upbutler monitors add db.internal:5432 --name Postgres
upbutler monitors add --name "Nightly backup" --period 86400 --grace 1800   # prints the ping URL
upbutler monitors get mon_...
upbutler monitors check mon_...    # runs it now, exits 1 if down
upbutler monitors rm mon_...

The target decides the kind: an https:// URL is an HTTP check, host:port is TCP, and --period without a target creates a heartbeat. --page also publishes the monitor on a status page, creating the page if needed. Run upbutler monitors add --help for all options.

Status pages

$ upbutler status upbutler
UpButler: All systems operational

COMPONENT                       STATUS       UPTIME
Platform / Website & dashboard  operational  100%
Platform / REST API             operational  100%
Platform / MCP server           operational  100%

upbutler status <slug> shows any public status page and needs no API key.

Incidents

upbutler incidents ls --open
upbutler incidents report "Elevated API errors" -m "Investigating 5xx on search" \
  --impact minor --component cmp_123=partial_outage
upbutler incidents update inc_... -m "Fix deployed, monitoring" --status monitoring
upbutler incidents resolve inc_... -m "Error rates are back to normal"

Heartbeats

upbutler heartbeat https://upbutler.com/hb/hb_Xf3kq9LmR2vT8wYzN4bC1dE7 -m "backup ok"
upbutler heartbeat hb_Xf3kq9LmR2vT8wYzN4bC1dE7 --fail -m "pg_dump exited 1"
upbutler heartbeat mon_... --duration 48210   # monitor ids are resolved with your API key

Pass a ping URL, an hb_… token or a mon_… monitor id. URLs and tokens need no API key.

Wrap a command

upbutler wrap --heartbeat "$UPBUTLER_HB_URL" -- ./backup.sh --full

# crontab: the heartbeat can also come from UPBUTLER_HEARTBEAT
0 2 * * * UPBUTLER_HEARTBEAT=hb_Xf3kq9LmR2vT8wYzN4bC1dE7 upbutler wrap -- /usr/local/bin/backup.sh

wrap runs the command with its output streamed as usual, then reports success with the duration, or failure with the exit code and the last lines of stderr. It exits with the command's exit code, and a failed ping never changes it. Everything after -- is passed to the command untouched.

Deploys

upbutler deploy mark --service api --version v1.42.0 --env production
# --commit defaults to $GITHUB_SHA or $CI_COMMIT_SHA

MCP setup

$ upbutler mcp config --client claude-code
# Claude Code
claude mcp add --transport http upbutler https://upbutler.com/mcp --header "Authorization: Bearer $UPBUTLER_API_KEY"

upbutler mcp config prints ready-to-paste config for Claude Code, Cursor (~/.cursor/mcp.json) and generic MCP clients. It references $UPBUTLER_API_KEY by default. Pass --with-key to inline your saved key. See MCP server.

Any API operation

upbutler api                                   # list every operation
upbutler api monitors.get --input '{"id":"mon_..."}'
upbutler api pages.push --input @statuses.json
echo '{"slug":"acme"}' | upbutler api public.status --input -

upbutler api is the escape hatch: it calls any operation from the API reference by id and prints the JSON result.

Scripts and agents

$ upbutler monitors ls --json | jq -r '.[] | select(.state=="down") | .name'
Search API

$ upbutler monitors get mon_nope --json
# stderr:
{"error":{"code":"not_found","message":"Monitor not found","status":404}}
$ echo $?
1

For programmatic use from code, see the SDKs.