The Autoheal CLI
autoheal (also installed as ah) drives the Autoheal agent platform from the command line. Find the agents in your project and run them, create and improve your own agents, start them automatically with triggers, and chat with Autoheal. It works the same for people and for coding agents. People get readable text on a terminal. Scripts and coding agents get stable JSON and meaningful exit codes.
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.
Code signing and notarization are planned (coming soon). Once they ship, you no longer need these steps.
Use with your coding agent (Claude Code / Codex / Cursor / GitHub Copilot)
Installing the CLI offers to install two Autoheal skills for your coding agent. They ship embedded in the binary, so they always match your CLI version:
- run-agent: find the right agent in your project and run it, wait for the result, answer its questions, and send follow-ups. When no agent fits, it asks Autoheal in a chat instead. Use it for production questions too: "why is checkout slow?", "what changed before the 14:00 alert?".
- build-agent: create or change an agent (its
agent.yaml, instructions, tools and skills), check it, publish it, try it, and wire it to triggers.
In Claude Code they arrive as the autoheal plugin, so you invoke them as /autoheal:run-agent and /autoheal:build-agent (or just ask, and Claude picks the right one).
autoheal skill install # prompts for scope (global/project) and which agents
autoheal skill status # where they're installed + installed vs. embedded version
autoheal skill update # refresh after a CLI upgrade
autoheal skill uninstall # remove them
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, so 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 skills once on your first interactive run instead.
Per-agent notes:
- Claude Code: installed as a plugin from a local plugin marketplace the CLI keeps in
~/.autoheal/claude-marketplace(or./.autoheal/claude-marketplacefor a project install). The CLI registers it withclaude plugin marketplace addandclaude plugin install autoheal@autoheal. If theclaudecommand isn't on your PATH, it prints those two commands for you to run. - Codex:
~/.codex/skills/autoheal-run-agentand~/.codex/skills/autoheal-build-agent(or./.codex/…for a project install). - Cursor: reads the open-standard
~/.agents/skillstree, whereautoheal skill installwrites the same two skills. - GitHub Copilot: has no global skills directory. Its customization is per-repository.
autoheal skill install --project --agents copilotwrites.github/instructions/autoheal-run-agent.instructions.mdandautoheal-build-agent.instructions.mdinto the current repo without touching any existing instructions. Copilot is skipped for a global install.
Upgrading from a CLI that installed the older single autoheal skill? autoheal update (or autoheal skill update) replaces it with the two new skills, and keeps any file you edited by hand.
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?
Press Enter for autoheal.ai — your organization is found when you sign in.
Otherwise type your Autoheal URL, for example:
acme.autoheal.ai an autoheal.ai organization
autoheal.example.com a BYOC or self-hosted install
>
Press Enter for autoheal.ai. The CLI discovers your organization from the login, writes a default CLI profile to ~/.autoheal/, and silently renews tokens afterwards. On a BYOC or self-hosted install, type the URL you open Autoheal at (pasting it from the browser works). The CLI then also asks for the auth issuer URL and CLI client id. It can't know these for your install.
After the approval it connects you to a project. Agents, runs and triggers all live in a project, so the CLI always works in one. If you can open just one project, the CLI picks it for you. Otherwise the CLI lists your projects and asks. Pass --project <id> to skip the question.
The CLI profile it writes is just the target host, your project, and any of those overrides, so ~/.autoheal/config stays readable and hand-editable. If your organization is renamed, update domain there.
Most people only ever need that one CLI profile. For a second organization or a dev/BYOC host, add another with autoheal login --cli-profile NAME --org NAME (or --domain HOST). autoheal cli-profile list shows them. autoheal cli-profile use NAME changes the default. --cli-profile / AUTOHEAL_CLI_PROFILE pick one for a single command. (A CLI profile is just where and how the CLI logs in. It has nothing to do with agent profiles.) 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). API credentials can't reach projects, agents, runs or triggers yet, so those commands need autoheal login for now.
AUTOHEAL_TOKEN takes an Autoheal API credential. It accepts 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. It stops working the day you lose a role or leave, and that will break the pipeline at the worst possible moment.
BYOC (connected or airgapped): each deployment has its own identity provider. Type your install's URL at the question, and the CLI asks for the issuer and client id (ZITADEL_ISSUER and ZITADEL_CLI_CLIENT_ID in your install's .env.zitadel). Or pass all three up front:
autoheal login --cli-profile acme \
--domain autoheal.example.com \
--issuer https://auth.example.com \
--client-id <ZITADEL_CLI_CLIENT_ID>
Projects
autoheal project # the project you're working in
autoheal project list # every project you can open, with your roles
autoheal project use payments # switch (no id: pick from a list)
autoheal project create "Payments" # organization admins: create one and switch to it
The project is saved on your CLI profile. To use another project for a single command, pass --project <id> or set AUTOHEAL_PROJECT.
Run an agent
autoheal agents list --search triage
autoheal run alert-triage "Triage the checkout 5xx alert from 14:00 UTC" --wait
autoheal run starts the agent and prints the run id and a link to the run in the web app. --wait blocks until the run finishes or needs you. --follow prints the agent's messages as they arrive. Pass structured input with --arg key=value (repeatable, and values that parse as JSON keep their type).
autoheal runs list --agent alert-triage # recent runs of an agent
autoheal runs view <run> # result and full transcript
autoheal runs send <run> "Now check the payments DB too" --wait # follow-up
autoheal runs cancel <run>
When a run stops to ask you something or needs an approval, --wait returns with exit code 6:
autoheal runs hitl <run> # what it's waiting on
autoheal runs answer <run> --ref <ref> --text "us-east-1"
autoheal runs approve <run> --ref <ref>
autoheal runs wait <run>
Build an agent
An agent is a folder in your project's repository: agents/<slug>/agent.yaml plus any files it refers to, such as an instructions.md. You edit it locally and publish it with push.
autoheal agents create checkout-triage --name "Checkout triage"
# edit ./agents/checkout-triage/agent.yaml and instructions.md
autoheal agents validate agents/checkout-triage
autoheal agents push agents/checkout-triage -m "Look at the payments DB first"
autoheal run checkout-triage "Why did checkout fail at 14:00?" --commit <sha> --wait
push saves your changes, commits them, and waits until Autoheal reads the new version. It prints any problems it found and the commit to run (--commit runs exactly what you just pushed). To change an agent someone else made, start with autoheal agents pull <agent>. If someone commits a change to the agent after you pull, push stops rather than undo it. Pull again to get their change (your own edits are kept), then push. autoheal agents show <agent> and autoheal agents history <agent> show the current version and its commits. autoheal agents schema prints every field agent.yaml accepts.
A minimal agent.yaml:
apiVersion: agents.autoheal.ai/v1
name: Checkout triage
description: Triages checkout errors and points at the likely cause.
instructions: ./instructions.md
tools:
- integration_type: datadog
inputs:
prompt:
type: string
required: true
description: What the agent should do on this run.
with:
prompt: "${{ inputs.prompt }}"
Omit tools to give the agent every tool your connected integrations offer, or list rules (by integration_type, operation_type or tool name) to narrow them.
inputs.prompt receives the text you pass to autoheal run <agent> "…" (or a trigger's with.prompt). with.prompt hands it to the model. agents create writes both. Keep them when you add another input. Also add that input to with.prompt (for example a line Dry run: ${{ inputs.dry_run }}), or the model won't see it.
Start agents automatically
Triggers run an agent when something happens: an alert group opens, or a GitHub event arrives.
autoheal triggers catalog # events you can trigger on
autoheal triggers catalog --event alertgroup.created # its fields and a sample event
autoheal triggers dry-run -f critical-alerts.yaml --event sample.json # would it match?
autoheal triggers create -f critical-alerts.yaml
autoheal triggers list --agent alert-triage
autoheal triggers disable <trigger>
# critical-alerts.yaml
name: Triage critical alert groups
on:
alertgroup.created:
- severity: critical
- status: firing
run:
agent: alert-triage
with:
prompt: "Triage alert group ${{ event.data.title }} (${{ event.data.alert_count }} alerts)"
on names one event and lists conditions that must all hold. Each condition is a field and the value it must have, or a comparison such as {greater_than: 5}. anyOf groups alternatives. with.prompt is what the agent is asked, with values from the event. autoheal triggers fire <trigger> --event sample.json runs it once for real. autoheal triggers runs <trigger> shows the runs it started.
Chat with Autoheal
autoheal chat create -m "What changed in checkout before 14:00?" --wait
autoheal chat send <session> "Show me the deploys" --wait
autoheal chat view <session>
Exit codes
| Code | Meaning |
|---|---|
| 0 | success: the run or chat finished |
| 1 | error: CLI/API failure, or the run failed or was canceled |
| 2 | usage error, including "no project selected" |
| 3 | authentication required |
| 4 | not found |
| 5 | wait timeout: the run is still going. Wait again |
| 6 | awaiting a person: answer or approve, then wait again |
Everything else
A few more API domains ship 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 GET /api/v1/projects
Output auto-detects: human text on a TTY, JSON when piped (--json to force). Data goes to stdout and progress to stderr, so pipe away.
Updating
autoheal update # update to the latest release
autoheal update --check # report whether an update is available, without acting
autoheal update replaces a standalone install (from curl … | sh or a direct download) in place after a checksum-verified download. It refreshes the agent skills in the same step. For an install from 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).