Overview
Flashduty CLI (flashduty) is a command-line tool for managing the incident lifecycle, querying on-call schedules, publishing status page updates, and debugging notification templates from your terminal. It fits naturally into operations scripts, local troubleshooting, and AI coding-agent workflows.
The tool is open source at flashcatcloud/flashduty-cli and supports macOS, Linux, and Windows.
Installation
- macOS / Linux
- Windows (PowerShell)
- Manual download
/usr/local/bin by default. Override with the FLASHDUTY_INSTALL_DIR environment variable.Installer options
Authentication
Log in
Credential resolution order
The CLI resolves credentials in the following order (highest priority first):--app-keycommand-line flag (hidden, for scripting)FLASHDUTY_APP_KEYenvironment variable- Config file
~/.flashduty/config.yaml(written byflashduty login)
Config file
Stored at~/.flashduty/config.yaml with 0600 permissions:
Config commands
Global flags
All subcommands accept these flags:Command catalog
incident — Incident lifecycle
incident list:
Time format examples:
5m, 1h, 24h, 168h, 2026-04-01, 2026-04-01 10:00:00, 1712000000.
Work items and follow-ups (work-item-*)
incident work-item-* manages work items anchored to an incident or a post-mortem. --item-type distinguishes two kinds: action (an action item anchored to an active incident) and follow_up (a post-mortem follow-up, which must be bound to a post-mortem ID).
work-item-create: --item-type (required, action or follow_up), --title (required, up to 512 characters), --idempotency-key (required idempotency key, up to 128 characters), --post-mortem-id (required for follow_up, forbidden for action), --assignee-ids (initial assignees). Mutating verbs (update/complete/convert/delete/assignees-reset) require --version (optimistic locking — it must match the stored version).
Post-mortem reports (post-mortem-*)
Post-mortem verbs live under theincident command group (there is no standalone post-mortem group):
post-mortem-template-list, post-mortem-template-info <template-id>, post-mortem-template-upsert (creates when --template-id is omitted; --team-id is required when creating), post-mortem-template-delete <template-id> (irreversible).
Comment types (comment-type-*)
change — Change records
--channel, --since, --until, --type, --limit, --page.
member — Member queries
member list supports --query (free-text search by name or email), --role-id, --page, --limit, --orderby, --asc.
member info-reset identifies the member by exactly one of --member-id, --member-name, --email, --phone, or --ref-id; the fields to change go into the required body via --data '{"updates":{...}}'. With --from api, an updated email or phone is marked verified directly when the account has member invites disabled.
member invite takes the member list via --data '{"members":[...]}'. When the account has member invites disabled and --from api is set, members are created directly in the enabled state with email/phone marked verified — no invitation is sent.
team — Team management
team list supports --query (team name substring match), --page, --limit, --orderby (created_at/updated_at/team_name), --asc, --person-id (filter to teams the given member belongs to).
team info accepts --ref-id, --team-name, or --team-id to identify the team (exactly one required). When several are provided, the precedence is --ref-id > --team-name > --team-id.
team upsert creates or updates a team:
--team-name(required, 1–39 characters)--team-id(set to update an existing team; omit to create)--description(up to 500 characters)--person-ids(member ID list; replaces the entire member list — runteam infofirst to see current members before updating)--emails(add existing members by email; addresses that match no existing member are silently ignored — no invitation is sent)--phones(add existing members by phone number; non-matching numbers are silently ignored, and non-E.164 numbers are parsed with--country-code)--country-code(default country code applied to--phonesentries that are not in E.164 format)--ref-id(external reference ID for HR system integration)
team upsert’s --emails / --phones only match and attach existing members — no invitation is ever sent. To invite new members into the organization, use flashduty member invite.team delete accepts --team-id, --team-name, or --ref-id to identify the team. This action is permanent and cannot be undone.
channel — Channel queries
--name.
channel escalate-rule-list — Escalation rule queries
Escalation rule management has moved into thechannel command group. Pass the channel ID as a positional argument:
channel group: escalate-rule-create, escalate-rule-update, escalate-rule-delete (all require --channel-id).
channel silence/inhibit/drop rules — Noise rule management
Channel-level noise rules are managed through thechannel command group; see Noise Reduction for rule semantics and configuration. The three families — silence-rule-* (silence), inhibit-rule-* (inhibit), unsubscribe-rule-* (drop) — share the same shape, each with list/create/update/enable/disable/delete verbs:
inhibit-rule-* and unsubscribe-rule-* work the same way; inhibit-rule-create requires --equals (the label keys pairing source and target alerts). Silence and inhibit rules accept --is-directly-discard to drop suppressed alerts instead of merging them. Note that channel-id is positional on *-rule-create and *-rule-list but a flag (--channel-id) on *-rule-update/delete/enable/disable; --rule-id is a MongoDB ObjectID string.
field — Custom field queries
--name.
status-page — Status page management
Event drafts (draft-create)
draft-create stores a status page event draft (incident or maintenance) so a human can review and publish it from the console — the draft itself is never published publicly:
--source: opaque marker of the drafting origin (e.g.ai_sre:sess_xxx), up to 64 characters.- The
draftobject in--data(required, stored verbatim, up to 64 KB serialized). Required fields:page_id,type(incidentormaintenance),name,message; optionalchange_id(append an update to an existing event when > 0),status,affected_components, andstart_time/end_time(Unix epoch seconds, new maintenance only). - The response returns
draft_id(matchingdraft_[A-Za-z0-9]{22}) andcreated_at; the console review link carriesdraft_id.
Migrate from Atlassian Statuspage
Migration jobs run asynchronously. Poll progress withmigration-status after kicking off a job:
draft-create, change-delete, change-info, change-list, change-timeline-delete, change-timeline-update, change-update, component-upsert, component-delete, section-upsert, section-delete, info, subscriber-list, subscriber-import, subscriber-export, template-list, template-upsert, template-delete.
rum — RUM applications and session replay
Use these commands to manage RUM applications and export session replay data. The application commands cover detail, batch reads, listing, webhook testing, and create/update/delete operations.application-list:
Core fields for
application-create / application-update:
application-webhook-test returns ok, status_code, and message, which makes it suitable for verifying that a RUM alert webhook really accepts a sample delivery from Flashduty.Session replay
session-replay-metadata, use --ts to supply the session-start Unix timestamp in milliseconds when you need to disambiguate a reused session ID from different time windows.
Common session-replay-segments flags:
Error ingestion rules (error-ingestion-rules-*)
Error ingestion rules filter or rewrite the error events an application reports:--description is capped at 512 characters. create/list/history-list/history-revert take application-id as a positional argument; update/enable/disable/delete target rules via the --application-id and --rule-id flags.
Preset severity rules (issue-preset-severity-rules-*)
Preset severity rules assign a preset severity to errors matching a condition, used for issue grading:Resource info (resource-info)
oncall — On-call licenses
fixed is explicitly assigned, while temporary is active for the current temporary-license window.
template — Notification templates
dingtalk, dingtalk_app, feishu, feishu_app, wecom, wecom_app, slack, slack_app, telegram, teams_app, email, sms, zoom.
session — AI SRE sessions
Inspect AI SRE (and other Flashduty agent) sessions:session list lists the sessions visible to the caller, and session export streams a single session’s full event log for offline analysis.
session list:
The server endpoint
/safari/session/list caps each page at 100 rows; when --limit exceeds that, the CLI paginates automatically — no manual paging required. The API has no time-window filter, so --since is applied client-side against each session’s updated_at after fetching.session export streams session events as newline-delimited JSON (NDJSON) to stdout: the first line is always a session_meta envelope, and each subsequent line is one event (user_message, llm_call, tool_call, subagent_dispatch, final_answer, agent_text, error). Exports can be large, so redirect to a file instead of printing to the terminal:
monit-query — Unified datasource tool invocation
monit-query executes a single named tool against a configured datasource — the unified entry for both query tools (<type>.query, covering prometheus, mysql, postgres, oracle, clickhouse, elasticsearch, loki, victorialogs, sls, tencent_cls) and diagnostic tools (e.g. mysql.overview, redis_node.slowlog), bypassing the alert-rule layer. The legacy monit-query data subcommand is retired. Get the datasource ID from the id field of monit datasource-list:
Query tools return a complete
explore_result.v1 structured result: format is always explore_result.v1, and result.kind is one of samples (instant samples with complete label sets), frames (typed table/time-series frames), or logs (raw logs with applied_limit and has_more). For the diagnostic tool response shape, see monit datasource-tools-invoke below.
monit datasource-tools-invoke — Datasource diagnostics
monit datasource-tools-invoke executes one deterministic read-only tool against a configured datasource — the current path for structured datasource diagnostics (replacing monit-query diagnose). It is equivalent to the monit-query command above, which is the recommended path. Get the datasource ID from the id field of monit datasource-list:
Semantics and limits:
- No tool catalog, no auto-replay, no fallback: one call runs exactly one named tool; fill parameters according to the datasource tool’s contract rather than guessing from the command list. Alongside diagnostic tools, the entry also supports
<type>.queryquery tools (prometheus,mysql,postgres,oracle,clickhouse,elasticsearch,loki,victorialogs,sls,tencent_cls). - Requires all currently online routable Edge sessions in the cluster to support the v0.71.0 base invoke protocol (individual tools may require a newer implementation); normal datasource queries retain their existing version compatibility.
- Request body limit 128 KiB; complete success response limit 10 MiB; tool timeout at most 25 seconds.
- The datasource must have
enabled=true;alerting_enabled=falsedoes not block diagnostics. - Response:
data(tool-specific JSON evidence, preserved without conversion, never null, no legacy diagnose envelope),tool,datasource_id, optionalsummary, and atruncatedobject (withreason; its presence indicates truncation).
edge_upgrade_required (Edge too old), mixed_edge_versions (mixed Edge versions in the cluster), no_active_edge (no routable online Edge), tool_not_supported (tool unavailable), invalid_request (fix the parameters), source_too_large / result_too_large (narrow the request). On Edge version issues, do not rotate Edges or fall back to the legacy diagnose.
monit — Datasource and alert-expression preview
If you want to validate a datasource expression before saving a rule, usepreview-sync to execute a synchronous preview request and inspect the raw result.
Datasource management (datasource-*)
Themonit datasource-* command family manages monitoring datasources (provided by the OpenAPI-generated commands):
datasource-create / datasource-update:
enabled and alerting_enabled are independent: alert evaluation requires both enabled=true and an alerting-capable type; alerting_enabled=false does not block non-alerting queries or tools, and monit datasource-list always reports alerting_enabled=false for diagnostic-only types.
Diagnostic-type payloads and secret handling:
redis_node:database(Redis database number, default 0),username/password,timeout_ms(default 3000, range 1000–10000).redis_sentinel:username/password,timeout_ms(default 3000).mongodb_mongod/mongodb_mongos:auth_source(authentication database, defaults toadmin; username and password must be configured together),username/password,timeout_ms(default 3000), TLS fields; client certificates are unsupported.kafka:sasl_mechanism(nonedefault /plain/scram-sha-256/scram-sha-512, the latter three require username and password),username/password,timeout_ms(default 5000), TLS fields (tls_min_versiondefaults to 1.2, max 1.3).- Passwords and
kafka.tls_keysupport${env:NAME}references (resolved on the edge); literal values are omitted from responses, only${env:...}references are echoed. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear.
alert — Alert and alert-event queries
list commands: --severity (Critical,Warning,Info), --channel (comma-separated channel IDs), --integration (comma-separated integration IDs), --since/--until, --limit (max 100), --page. alert-event list also takes --integration-type, which filters by comma-separated plugin keys (e.g. AliCloud,Prometheus) — note these are plugin keys, not integration IDs; use --integration to filter by integration ID.
automation — AI SRE automation rules
Theautomation command group manages AI SRE automation rules — create, query, update, delete, run history, and triggering. See Automations for the console workflow.
create flags:
update accepts --name, --prompt/--prompt-file, --schedule/--at/--weekday/--cron-expr, --enable/--disable, --enable-schedule/--disable-schedule, --enable-http-post-trigger/--disable-http-post-trigger, --rotate-http-post-token, and --environment-kind/--environment-id. The personal/team scope is immutable after creation, so update exposes no scope flag.
runs supports --status (queued/running/retrying/succeeded/partial/failed/skipped/abandoned), --trigger-kind (schedule/debug/http_post), --since/--until, --page, and --limit. fire authenticates with the trigger’s token (--token, or the FLASHDUTY_AUTOMATION_TRIGGER_TOKEN environment variable); --text passes context for the run, and --data passes a full JSON request body (inline JSON or - to read stdin).
insight — Insight queries
Theinsight command family queries aggregated incident metrics over a time window (response times, notification counts, and so on):
insight incidents:
In
json/toon mode the rows default to the compact fields incident_id, title, severity, channel_name, seconds_to_ack, seconds_to_close, notifications (a stderr note announces the default projection and that --fields can change it); output is bounded at 16 KiB — overflowing rows are dropped or shortened, with all notes on stderr (see “Field projections for structured output” under “Output formats” below).
insight top-alerts: --label is required (check or resource), --since/--until as above, --limit defaults to 10 (top-K), returning the alert count and event count per label value.
insight incident-export: writes the filtered incident list as a CSV of header row plus data rows (redirect to a file; --start-time/--end-time take Unix seconds). The export endpoint returns a one-shot CSV and caps its row count server-side, so the command verifies the CSV data-row count against the incident-list total for the same filter after writing: on a shortfall the CSV is still written (a rows=N line goes to stderr) and the command exits non-zero stating written vs total — narrow the time window and retry.
Full command coverage
Beyond the curated commands above, the CLI now provides full coverage of the Flashduty OpenAPI through a spec-driven code generator. The current OpenAPI contains 340 API operations, and the CLI generates resource-organized commands for 337 of them; the remaining operations (e.g.session-read-export) are provided by hand-written commands (session export / safari session-export). In addition to the On-call domain (incident, incident-trigger-subscription, change, channel, field, status-page, template, and more), it also covers:
- AI SRE (
safari): a2a-agents, artifacts, automations, knowledge, mcp-servers, sessions, skills, and more - Alerting & noise reduction: alert, alert-event, enrichment (alert-rules, rule-sets), route
- On-call & scheduling: calendar, schedule
- Platform administration: account, member, person, team, role (roles-permissions), audit (audit-logs)
- Monitoring & RUM: monit, rum, sourcemap
- Integrations & webhooks: datasource (IM integrations), webhook (integrations)
resource-action naming form (e.g. flashduty safari a2a-agent-get, flashduty safari session-list); their inputs and response fields map directly to the corresponding API. Explore them level by level with flashduty <resource> --help:
--start-time / --end-time) accept the same human-friendly formats as the curated commands: relative durations (7d, 24h — interpreted as “now minus duration”), +7d (“now plus duration”, i.e. a future time), now, dates and datetimes (such as 2026-05-01 or 2026-05-01 10:00:00), and unix timestamps in seconds. In addition, --since and --until are aliases for --start-time and --end-time respectively and can be used interchangeably; passing both spellings with different values is an error.
knowledge — AI SRE knowledge base
Thesafari knowledge-* command family manages AI SRE Knowledge Packs — versioned, account/team-scoped file trees (DUTY.md plus runbooks, FAQs, service catalogs, and similar files) staged into every AI SRE sandbox at session start. See Manage Knowledge for the full feature model (DUTY.md structure, @references, account/team scope, file constraints).
knowledge-file-put requires --content-b64 to be the Base64 encoding of valid UTF-8 text; --content-type is inferred from the file extension when omitted. knowledge-file-delete refuses to remove a file still referenced by other pack files unless --force is passed, in which case the referrers are returned as warnings.
artifacts — AI SRE artifact gallery
Thesafari artifact-* command family manages artifacts produced by AI SRE sessions — publishing to the gallery, sharing, and signed downloads. See Artifacts for the console workflow:
public_urlis a console/share/artifact/<artifact-id>page served entirely from the CDN; it exists only while sharing is on, and anyone with the link can view the content without logging in.- The public snapshot is materialized from the artifact’s current
file_id: whenshare_enabled=trueand the response’sshare_file_iddiffers fromfile_id, the public snapshot is stale — callartifact-gallery-share-syncto refresh it before referencing it externally. - The
artifact-signtoken is bound to the calling account and person and is valid for 5 minutes (responseexpires_in);download_url/preview_urlare relative paths (/safari/artifact/stream?...) — prepend the API base (https://api.flashcat.cloud). - An artifact’s initial scope inherits from its source session (personal-session artifacts belong to the creator; team-bound session artifacts belong to the team);
can_edittells whether the caller may rename/transfer/delete/share it (the creator, any member of the owning team, or a manager of the source session).
Utility commands
flashduty update downloads and runs the platform installer, replacing the current binary with the latest release. --check only prints the available version without modifying any local files. After any non-update command runs in a terminal, if a newer version is available the CLI automatically emits an update notice banner to stderr.Output formats
Select the output shape with--output-format (--json is an alias for --output-format json) to fit different consumers:
- Table (default)
- JSON (--json / --output-format json)
- TOON (--output-format toon)
- Full table (--no-trunc)
Human-readable, aligned columns, long fields truncated.
Generated-command output bound
Generated commands (the ones covering the OpenAPI through the code generator, such assafari session-list, monit datasource-list, safari a2a-agent-list) apply the same 16 KiB bound to list-shaped responses in json/toon mode, mirroring the curated commands’ behavior, with every note going only to stderr and stdout left untouched:
- The whole page overflows: only the leading rows that fit are emitted, with every value intact, and a stderr note reports how many of the N/M rows were emitted.
- A single row alone overflows the budget: that row’s string values are shortened and end with
...; a stderr note names the clipped fields. Identifier fields (keys ending in_idor_key) are never shortened. - A row cannot be reduced enough to fit: the command fails and names the largest fields (up to 3, with their byte sizes); lower
--limitor reduce the output fields and retry.
safari session-get) are never bounded or shortened — a shortened id or status would pass for a real value, so these responses print untouched. Generated commands mostly have no --fields; for complete JSON lower --limit and page through with --page (e.g. flashduty safari session-list --limit 20 --page 2), or narrow the filter.
Field projections for structured output
The following commands support--fields with json or toon output. Supply comma-separated top-level response fields; an unknown field fails immediately, and table output ignores this flag.
For example, export only an incident ID, title, and progress:
incident list, incident similar, alert-event list, channel escalate-rule-list, insight incidents) exceeds its 16 KiB limit, the CLI handles it in three tiers, with every note going to stderr and stdout left untouched:
- Whole page overflows: only the leading rows that fit are emitted, with every value left intact (no truncation), and a stderr note reports how many of the rows were emitted while the rest were not; narrow
--fieldsor lower--limitto fit more rows per page. - A single row alone overflows the budget: that row’s string values are shortened and end with
..., and a stderr note names the clipped fields — matching or filtering on a shortened field will miss, so narrow--fieldsor--limitfor untruncated values. Identifier fields (keys ending in_idor_key) are never shortened at any tier. - A row cannot be reduced enough to fit: the command fails with an error naming the largest fields (up to 3, with their byte sizes); reduce the fields in
--fieldsor lower--limitand retry.
incident detail behaves differently when its projection overflows: the detail is a single object, and a truncated value is indistinguishable from a genuinely short one, so silently shortening it would hand you wrong data. A projection over 8 KiB therefore fails the command outright, and the error names the largest fields (up to 3, with their byte sizes). Reduce the fields in --fields, or omit --fields entirely to get the full detail, which is not subject to the projection limit.
When --fields is omitted and the default compact projection is used, the CLI prints a one-line note to stderr stating which fields the projection uses and that --fields can select others. The note goes only to stderr and never touches stdout, so piping into jq or similar tools is unaffected.
Agent skills
Flashduty CLI ships with a single agent skill namedflashduty that teaches AI coding agents — Claude Code, Cursor, Codex, Gemini CLI, Windsurf, and 40+ others — how to operate Flashduty from your terminal.
Install it to every detected agent on your machine in one shot:
SKILL.md carries the shared conventions (authentication, global flags, safety rules) and indexes per-domain reference cards — incidents, alerts, changes, on-call and schedules, channels and escalations, status pages, insights, monitors, RUM and sourcemaps, automations, notification templates, members and teams, and more. Before running a task, the agent reads the card for that domain to get every command, flag, and workflow for it — no --help trial-and-error.
Common workflows
Attach a CLI link to notifications
Attach a CLI link to notifications
Use
flashduty incident get <id> to fetch incident details from the terminal. Embed the snippet into notification templates so responders can copy-paste it.Bulk acknowledge or close incidents
Bulk acknowledge or close incidents
Export incident data to BI tools
Export incident data to BI tools
jq or load it into your warehouse.Validate notification templates in CI/CD
Validate notification templates in CI/CD