The Autoheal CLI
autoheal (also installed as ah) drives the Autoheal platform from the command line. It is built for coding agents first: start an investigation, wait for the result, answer the agent's questions, read the RCA — all with stable JSON output and meaningful exit codes. Humans get readable text output on a TTY automatically.
Install
macOS / Linux
curl -fsSL https://raw.githubusercontent.com/accelos/autoheal-cli/main/install.sh | sh
Homebrew (recommended on macOS):
brew install accelos/tap/autoheal
# or, if you'd rather type a bare name afterward:
brew tap accelos/tap && brew install autoheal
Windows
irm https://raw.githubusercontent.com/accelos/autoheal-cli/main/install.ps1 | iex
Or with Scoop:
scoop bucket add autoheal https://github.com/accelos/scoop-autoheal; scoop install autoheal
Direct downloads
Prebuilt binaries, .deb/.rpm packages, and checksums.txt for every release are on the releases page. Install a specific version (including a release candidate) with the installer's version flag:
curl -fsSL https://raw.githubusercontent.com/accelos/autoheal-cli/main/install.sh | sh -s -- --version v0.1.0
# Windows: & ([scriptblock]::Create((irm .../install.ps1))) -Version v0.1.0
First launch on an unsigned build
The binaries are not yet code-signed, so the OS may warn on first run. This is a one-time step (Homebrew avoids it on macOS, which is why it's recommended there):
- macOS:
xattr -d com.apple.quarantine "$(command -v autoheal)"(and once more forah), or approve it under System Settings → Privacy & Security. - Windows: on the SmartScreen prompt choose More info → Run anyway.
Signing and notarization are landing shortly, after which these steps go away.
Use with your coding agent (Claude Code / Codex / Cursor / GitHub Copilot)
Installing the CLI offers to set up the Autoheal agent skill. The skill teaches your coding agent to route any production/observability question through autoheal — starting a real investigation on Autoheal's connected data sources instead of guessing from local logs. It ships embedded in the binary, so it always matches your CLI version.
autoheal skill install # prompts for scope (global/project) and which agents
autoheal skill status # where it's installed + installed vs. embedded version
autoheal skill update # re-materialize after a CLI upgrade
autoheal skill uninstall # remove it
The curl … | sh and install.ps1 installers run autoheal skill install for you (it prompts on a terminal, and skips silently when there is none — CI never gets surprise files). Opt out with:
--no-skillon the shell installer, or-NoSkillvia the PowerShell script-block form (& ([scriptblock]::Create((irm …))) -NoSkill)AUTOHEAL_SKIP_SKILL=1in the environment (works for a plainirm … | iextoo)
Package-manager installs (brew/scoop) have no install script, so the CLI offers the skill once on your first interactive run instead.
Per-agent notes:
- Claude Code / Codex — installed under
~/.claude/skills/autohealand~/.codex/skills/autoheal(or./.claude/./.codexfor a project install). - Cursor — reads the open-standard
~/.agents/skillstree (and also loads~/.claude/~/.codex), so a Claude Code + Codex install already covers it;autoheal skill installwrites~/.agents/skills/autohealas the canonical target too. - GitHub Copilot — has no global skills directory; its customization is per-repository.
autoheal skill install --project --agents copilotwrites a self-contained.github/instructions/autoheal.instructions.md(withapplyTo: "**") into the current repo without touching any existing instructions. Copilot is skipped for a global install.
Log in
autoheal login
It asks where to log in, then takes one browser approval (OAuth device flow):
? Where do you want to log in?
1) autoheal.ai — the managed service (default)
2) Other — a dev, BYOC, or self-hosted host you'll type
> 1
On autoheal.ai the CLI discovers your organization from the login, writes a default profile to ~/.autoheal/, and silently renews tokens afterwards. Choosing Other asks for your host — and, for a self-hosted instance whose identity provider the CLI can't know, for its auth host and client id too.
The profile it writes is just the target host plus any of those overrides, so ~/.autoheal/config stays readable and hand-editable. If your organization is renamed, update domain there.
For a second org, add explicit profiles with autoheal auth login --org NAME or --domain HOST and switch with --profile / AUTOHEAL_PROFILE. Any of --org, --domain or --yes skips the question, as does running without a terminal — so scripts and coding agents keep the flag-free zero-config behaviour against autoheal.ai.
Headless / CI environments skip the browser: set AUTOHEAL_TOKEN and AUTOHEAL_DOMAIN (e.g. acme.autoheal.ai).
AUTOHEAL_TOKEN takes an Autoheal API credential — either a service account key (ahsa_…) for shared automation, or your personal access token (ahpat_…) for your own CI. Both are long-lived and revocable; see API Credentials for how to create one and which to pick.
export AUTOHEAL_DOMAIN=acme.autoheal.ai
export AUTOHEAL_TOKEN="$AUTOHEAL_SERVICE_ACCOUNT_KEY" # from your CI secret store
autoheal whoami
Prefer a service account for anything shared: a personal access token carries your access and stops working the day you lose a role or leave, which will break the pipeline at the worst possible moment.
BYOC: each self-hosted deployment has its own identity provider. Answer Other and the CLI asks for the same three values interactively, or pass them up front with values from your install's .env.zitadel:
autoheal auth login --profile acme \
--domain autoheal.example.com \
--issuer https://auth.example.com \
--client-id <ZITADEL_CLI_CLIENT_ID>
The agent workflow
# Start an investigation and block until there's an answer (or a question for you)
autoheal inv create "checkout error rate spiked at 14:00 UTC" --wait
# The run paused to ask something? List, answer, and re-enter the wait loop:
autoheal inv hitl <id>
autoheal inv hitl answer <id> --ref <ref> --text "us-east-1 production"
autoheal inv hitl approve <id> --ref <ref> --session
autoheal inv wait <id>
# Heading the wrong way? Stop it and re-steer
autoheal inv stop <id>
autoheal inv resume <id> "ignore the CDN — the DB pool saturated at 14:02"
# Read the result
autoheal inv rca <id>
autoheal inv evidence <id>
--wait/wait return as soon as a human must act, printing what the run is blocked on. Exit codes tell an agent exactly what happened:
| Code | Meaning |
|---|---|
| 0 | success — root cause available/accepted, or resolved |
| 1 | error — CLI/API failure, or the run ended in error/stopped |
| 2 | usage error |
| 3 | authentication required |
| 4 | not found |
| 5 | wait timeout |
| 6 | awaiting human — answer/approve, then wait again |
autoheal inv follow <id> streams the live agent events instead of polling — the full transcript, including every tool call with its arguments and result, so you can see exactly what the agent looked at. autoheal inv stop <id> cancels a running investigation (safe to call even if it already finished) and keeps the hypotheses and evidence gathered so far. autoheal chat ... offers the same verbs for chat sessions.
Everything else
Beyond the investigation/chat workflow, a small allowlist of API domains ships as generated command groups — alerts, integrations, and skills:
autoheal alerts list
autoheal alerts get <alert-id>
autoheal integrations list
autoheal skills list
And autoheal api is the raw escape hatch to any endpoint not in that allowlist:
autoheal api GET /api/v1/incidents
autoheal api GET /api/v1/alerts --query page=1
autoheal api POST /api/investigations/create --field query="db latency" --field mode=fast
Output auto-detects: human text on a TTY, JSON when piped (--json to force). Data goes to stdout, progress to stderr — pipe away.
Updating
autoheal update # update to the latest release
autoheal update --check # report whether an update is available, without acting
A standalone install (from curl … | sh or a direct download) is replaced in place after a checksum-verified download, and its agent skill is refreshed in the same step. Installed via a package manager, autoheal update prints the matching command instead:
| Installed via | Update command |
|---|---|
| Homebrew | brew upgrade autoheal |
| Scoop | scoop update autoheal |
.deb / .rpm | download the latest package from the releases page |
When run interactively, the CLI checks for a newer release at most once a day and prints a one-line hint. Set AUTOHEAL_NO_UPDATE_CHECK=1 to disable that check. The check never runs for agents or CI (any of --json, non-TTY, CI, or a preset AUTOHEAL_TOKEN suppresses it).