CLI reference
Ember CLI
Drive Ember from your terminal. Connect alert sources, run a full incident analysis from an alarm and a log file, watch a service live, and export postmortems to your wiki.
Install and authenticate
The CLI requires Node.js 18 or later. Install it globally with npm or any package manager that reads the npm registry.
ember login opens a browser page to complete OAuth and stores a scoped API key in ~/.ember/credentials.json. Pass --token to skip the browser and supply a key directly (useful in CI).
npm i -g @ember/cli
$ ember login Opening browser to complete authentication... Logged in as nadia@acmecorp.com (team: acmecorp) API key written to ~/.ember/credentials.json
# headless / CI ember login --token em_live_xxxxxxxxxxxxxxxxxxxx
ember connect <source>
Connect an alert source, a log source, or a deploy feed. Ember uses what you connect; you do not need all of them to start.
Supported sources: pagerduty, datadog, grafana, opsgenie, cloudwatch, sentry. Run ember connect --help for the full list, including log (Loki, Honeycomb) and deploy (GitHub, GitLab, Terraform) sources.
# PagerDuty (API token from Settings > API Access > Create New API User Token) ember connect pagerduty --token $PD_TOKEN # Datadog (API key + application key) ember connect datadog \ --api-key $DD_API_KEY \ --app-key $DD_APP_KEY \ --site us5.datadoghq.com # Grafana (service account token, requires Viewer role at minimum) ember connect grafana \ --url https://grafana.acmecorp.com \ --token $GRAFANA_SA_TOKEN # Opsgenie ember connect opsgenie --api-key $OG_API_KEY # CloudWatch (reads from current AWS_PROFILE / instance role) ember connect cloudwatch --region us-east-1 # Sentry (org auth token from Settings > Auth Tokens) ember connect sentry --token $SENTRY_TOKEN --org acmecorp
$ ember connect pagerduty --token $PD_TOKEN Verifying token... Connected source=pagerduty account=Acme Corp services=47 Webhook URL → copy this into PagerDuty > Extensions > Generic Webhooks (V3): https://app.emberoncall.com/hooks/pd/h_01j9kx8m
All source credentials are encrypted at rest. See the security page for the data handling policy.
ember incident run
Read an alarm and telemetry, return a ranked root cause, a drafted fix, a timeline, and a first-draft postmortem.
ember incident run \ --alarm "PagerDuty [SEV2] checkout-api 5xx rate 8.4% for 4m, p95 2.9s" \ --logs ./checkout-api.log \ --changes ./deploy-log.txt \ --service checkout-api
--alarm and --logs are required. All other flags are optional. Pass --json to write structured JSON to stdout, which you can pipe to jq or post to a webhook.
When --changes is omitted, Ember skips deploy correlation. When --service is omitted, it infers the service name from the alarm text.
Ember incident run service=checkout-api started=15:04:02 Reading alarm... [SEV2] checkout-api 5xx rate 8.4% (threshold 1%) p95 2.9s pagerduty Reading logs... 2 918 lines t=15:01:58–15:04:01 pulled 14 signal lines from 2 918 total Reading changes... 14:58 deploy checkout-api v2025.7.3 (PR #4821 swap Redis client, pool -> 200) 14:31 flag promo_engine_v2 enabled at 25% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ CAUSE Redis connection pool exhausted after deploy v2025.7.3 CONFIDENCE 78% EVIDENCE 15:02:11 pool timeout acquiring connection after 5000ms (redis) 15:02:12 redis connected_clients=200 blocked_clients=147 maxclients=200 14:58 deploy v2025.7.3 raised pool from 80 -> 200, landed 4m before alarm FIX rollback 1. kubectl rollout undo deploy/checkout-api 2. kubectl rollout status deploy/checkout-api --timeout=5m 3. confirm 5xx rate drops below 1% in Datadog before closing TIMELINE 14:58:00 deploy checkout-api v2025.7.3 rolled out (9/9 pods) 15:01:58 first pool timeout errors appear 15:02:00 PagerDuty alarm fires, SEV2 declared 15:02:12 redis maxclients=200 saturated, 147 connections blocked 15:04:02 Ember analysis complete Incident ID inc_01j9kxbp Postmortem draft ready → ember postmortem export inc_01j9kxbp --to markdown
Flags for incident run
--alarm <text|file>Alert body or path to a file containing the alert. Supports PagerDuty webhook JSON, plain text, and CloudWatch SNS payloads.
--logs <file|glob>Log file, glob, or "-" for stdin. Multiple --logs flags are accepted; outputs are merged and deduplicated by timestamp.
--changes <file>Deploy log, git log, or flag-change list to correlate against the alarm. Plain text or JSON.
--service <name>Explicit service name. Ember infers from the alert when omitted, but setting this speeds up ownership and runbook lookup.
--jsonWrite structured JSON to stdout instead of the default human-readable output. Pipe to jq or a webhook.
ember incident watch <service>
Tail a service and re-run analysis every 30 seconds. Alerts on severity changes and updates the running timeline. Press q to stand down.
ember incident watch checkout-api \ --tail 500 \ --interval 30
Watching service=checkout-api interval=30s tail=500 15:04:30 poll 1 5xx rate 8.2% cause unchanged confidence 78% 15:05:00 poll 2 5xx rate 6.1% confidence unchanged 15:05:30 poll 3 5xx rate 1.8% → recovering 15:06:00 poll 4 5xx rate 0.4% below threshold SEVERITY CHANGE SEV2 → resolved Timeline updated. Press q to exit or enter to export postmortem.
--tail <n>Number of recent log lines to pull on each poll cycle. Default 500.
--interval <s>Poll interval in seconds. Default 30.
ember postmortem export <incident-id>
Push the first-draft postmortem to Confluence, Notion, or a Markdown file. The timeline and ranked cause are attached automatically.
# export to Confluence (workspace must be connected via ember connect) ember postmortem export inc_01j9kxbp \ --to confluence \ --page-id 823746 # export to Notion ember postmortem export inc_01j9kxbp \ --to notion \ --page-id 1a2b3c4d5e6f # write a local Markdown file ember postmortem export inc_01j9kxbp \ --to markdown \ --out ./postmortems/inc_01j9kxbp.md
$ ember postmortem export inc_01j9kxbp --to confluence --page-id 823746 Exporting postmortem inc_01j9kxbp... title Postmortem: checkout-api SEV2 (July 15, 2026) sections Impact, Root cause, Timeline (14 events), Action items (3) Created Confluence page https://acmecorp.atlassian.net/wiki/spaces/ENG/pages/823746/children/823899
--to confluence|notion|markdownExport destination. Confluence and Notion require a connected workspace (ember connect).
--page-id <id>Target Confluence page ID or Notion page ID. Ember creates a child page when omitted.
--out <file>Write to this path when --to markdown is set. Default: <incident-id>.md in the current directory.
ember models ls and ember models set
Ember routes each task to a provider and model automatically. Use these commands to inspect the current routing table or override it.
ember models ls
Task Provider Model Fallback ───────────────── ────────── ─────────────────────── ───────────────────────── cause-ranking anthropic claude-opus-4 openai/gpt-4.1 fix-drafting openai gpt-4.1 anthropic/claude-sonnet-4 log-extraction openai gpt-4.1-mini anthropic/claude-haiku-3-5 timeline-gen anthropic claude-haiku-3-5 openai/gpt-4.1-mini postmortem-draft anthropic claude-sonnet-4 openai/gpt-4.1 Routing mode auto (Scale: override per-task or bring your own endpoint)
# pin cause-ranking to a specific model ember models set cause-ranking \ --provider openai \ --model gpt-4.1 # point all tasks at your own endpoint (Scale plan) ember models set --all \ --endpoint https://llm.internal.acmecorp.com/v1 \ --model your-model-name \ --api-key $INTERNAL_LLM_KEY # reset to automatic routing ember models set --reset
$ ember models set cause-ranking --provider openai --model gpt-4.1 Updated task=cause-ranking provider=openai model=gpt-4.1 Fallback unchanged (anthropic/claude-opus-4) Changes take effect on the next ember incident run
Custom endpoints require a Scale plan. See pricing or how the AI works for the routing design.
Structured output shape
Pass --json to incident run to get a structured response. The shape matches the REST API response exactly.
{
"incident_id": "inc_01j9kxbp",
"service": "checkout-api",
"severity": "SEV2",
"analyzed_at": "2026-07-15T15:04:02Z",
"causes": [
{
"rank": 1,
"summary": "Redis connection pool exhausted after deploy v2025.7.3",
"confidence": 0.78,
"evidence": [
{
"ts": "2026-07-15T15:02:11Z",
"source": "logs",
"line": "pool timeout acquiring connection after 5000ms (redis)"
},
{
"ts": "2026-07-15T15:02:12Z",
"source": "logs",
"line": "redis connected_clients=200 blocked_clients=147 maxclients=200"
},
{
"ts": "2026-07-15T14:58:00Z",
"source": "changes",
"line": "deploy checkout-api v2025.7.3 raised pool from 80 -> 200"
}
]
},
{
"rank": 2,
"summary": "promo_engine_v2 flag at 25% may have amplified checkout throughput",
"confidence": 0.31,
"evidence": [
{
"ts": "2026-07-15T14:31:00Z",
"source": "changes",
"line": "flag promo_engine_v2 enabled at 25%"
}
]
}
],
"fix": {
"type": "rollback",
"steps": [
"kubectl rollout undo deploy/checkout-api",
"kubectl rollout status deploy/checkout-api --timeout=5m",
"confirm 5xx rate drops below 1% in Datadog before closing"
]
},
"timeline": [
{ "ts": "2026-07-15T14:58:00Z", "event": "deploy checkout-api v2025.7.3 rolled out (9/9 pods)" },
{ "ts": "2026-07-15T15:01:58Z", "event": "first pool timeout errors appear in logs" },
{ "ts": "2026-07-15T15:02:00Z", "event": "PagerDuty alarm fires, SEV2 declared" },
{ "ts": "2026-07-15T15:02:12Z", "event": "redis maxclients=200 saturated, 147 blocked" },
{ "ts": "2026-07-15T15:04:02Z", "event": "Ember analysis complete, postmortem draft ready" }
],
"postmortem": {
"title": "Postmortem: checkout-api SEV2 (July 15, 2026)",
"impact": "8.4% 5xx error rate on POST /charge for 4m04s. Estimated 1 200 failed checkout attempts.",
"root_cause": "Deploy v2025.7.3 raised the Redis connection pool limit from 80 to 200. The pool grew faster than Redis could serve connections, exhausting maxclients=200 and blocking 147 concurrent requests.",
"action_items": [
"Add pool size to deploy checklist and require a load-test before increasing above current redis maxclients",
"Set pool high-watermark alert at 80% of maxclients",
"Stagger pool increases with a canary stage before full rollout"
]
},
"model": "claude-opus-4",
"provider": "anthropic"
}Command reference
Run your first incident from the terminal.
Install the CLI, connect a source, and analyze a real alarm in under ten minutes.