From efc73a58b1d7283ff5b7d69643d0dad8634badbe Mon Sep 17 00:00:00 2001 From: ysyneu Date: Thu, 8 Oct 2026 22:24:42 -0700 Subject: [PATCH] docs(readme): rewrite README for the current CLI - Drop the removed flashduty-sdk dependency; list go-flashduty, cobra, toon-go, yaml.v3 and x/term. - Replace the hand-maintained command list (which covered about ten of the 37 groups and used outdated names) with a group overview by product area and the path-to-command rule, and point to --help and the docs for the long tail. - Link the website, CLI docs, API reference, console, blog post and related projects; use the flashduty.com and docs.flashduty.com domains. - Document whoami, update, the environment variables the CLI reads, and the Go 1.26 requirement; refresh the version example to v1.5.12. - Keep README.md and README_zh.md in step. --- README.md | 390 ++++++++++++--------------------------------------- README_zh.md | 381 +++++++++++++------------------------------------ 2 files changed, 189 insertions(+), 582 deletions(-) diff --git a/README.md b/README.md index 91b0514..a809fef 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,16 @@ English | [中文](README_zh.md) [![CI](https://img.shields.io/github/actions/workflow/status/flashcatcloud/flashduty-cli/ci.yml?style=flat-square&branch=main&label=CI)](https://github.com/flashcatcloud/flashduty-cli/actions) [![Go Report Card](https://goreportcard.com/badge/github.com/flashcatcloud/flashduty-cli?style=flat-square)](https://goreportcard.com/report/github.com/flashcatcloud/flashduty-cli) -A command-line interface for the [Flashduty](https://flashcat.cloud) platform. Manage incidents, on-call schedules, status pages, and more from your terminal. +**Flashduty CLI** (`flashduty`) is the official open-source command-line tool for [Flashduty](https://www.flashduty.com), the incident management and on-call platform. From a terminal, a shell script, or an AI coding agent you can triage incidents and alerts, query on-call schedules, publish status page updates, manage monitors and RUM, and drive the AI SRE. + +[Website](https://www.flashduty.com) · [CLI documentation](https://docs.flashduty.com/en/developer/cli) · [API reference](https://docs.flashduty.com/en/openapi/introduction) · [Console](https://console.flashcat.cloud) · [Blog: a CLI for humans and agents](https://www.flashduty.com/en/now/blog/flashduty-cli) · [Releases](https://github.com/flashcatcloud/flashduty-cli/releases) + +## Highlights + +- **The whole public API.** Every public Flashduty API operation has a command, generated from the OpenAPI spec through the [go-flashduty](https://github.com/flashcatcloud/go-flashduty) SDK. Common workflows (incidents, alerts, on-call, status pages) also get hand-tuned commands with shorter flags and readable tables. +- **Predictable names.** An API path maps directly to a command: `POST /incident/merge` is `flashduty incident merge`, and `POST /status-page/change/create` is `flashduty status-page change-create`. +- **Built for scripts and agents.** Output as `table`, `json`, or `toon` (compact, fewer tokens). List pages are size-bounded and say so when reduced. `--fields` projects rows to the fields you need. +- **One binary.** macOS, Linux, and Windows on amd64 and arm64. `flashduty update` upgrades in place. ## Installation @@ -23,365 +32,152 @@ curl -sSL https://static.flashcat.cloud/flashduty-cli/install.sh | sh irm https://static.flashcat.cloud/flashduty-cli/install.ps1 | iex ``` -### Manual Download +### Manual download -Download the latest release for your platform from [GitHub Releases](https://github.com/flashcatcloud/flashduty-cli/releases). +Download the archive for your platform from [GitHub Releases](https://github.com/flashcatcloud/flashduty-cli/releases), extract it, and put the binary on your `PATH`. -### Options +### Installer options | Variable | Description | Default | |----------|-------------|---------| -| `FLASHDUTY_VERSION` | Install a specific version (e.g. `v0.1.2`) | latest | -| `FLASHDUTY_INSTALL_DIR` | Custom install directory | `/usr/local/bin` (shell), `~\.flashduty\bin` (PowerShell) | -| `MIRROR_URL` | Override installer release asset mirror | `https://static.flashcat.cloud/flashduty-cli` | -| `FLASHDUTY_UPDATE_BASE_URL` | Override `flashduty update` and auto update-check base URL | `https://static.flashcat.cloud/flashduty-cli` | - -## Quick Start +| `FLASHDUTY_VERSION` | Install a specific version (e.g. `v1.5.12`) | latest | +| `FLASHDUTY_INSTALL_DIR` | Install directory | `/usr/local/bin` (shell), `~\.flashduty\bin` (PowerShell) | +| `MIRROR_URL` | Release asset mirror (must be `https://`) | `https://static.flashcat.cloud/flashduty-cli` | -### 1. Authenticate +## Quick start ```bash +# 1. Authenticate with an APP key (console: My → APP Key) flashduty login -``` +flashduty whoami -You will be prompted for your Flashduty APP key. To obtain one, log into the [Flashduty console](https://console.flashcat.cloud) and navigate to **Account Settings > APP Key**. +# 2. Work with incidents +flashduty incident list --since 24h --severity Critical +flashduty incident info +flashduty incident ack +flashduty incident merge --source , # sources are closed and kept +flashduty incident close -Alternatively, set the key via environment variable: +# 3. Who is on call, and what changed? +flashduty oncall who +flashduty change list --since 2h -```bash -export FLASHDUTY_APP_KEY=your_app_key +# 4. Explore any area +flashduty status-page --help ``` -### 2. Use +How to create an APP key is described in the [API reference](https://docs.flashduty.com/en/openapi/introduction). -```bash -# List recent incidents -flashduty incident list +## Command groups -# Get incident details -flashduty incident get +Run `flashduty --help` for the commands in a group, and `flashduty --help` for flags and examples. The [CLI documentation](https://docs.flashduty.com/en/developer/cli) walks through the common workflows. -# List team members -flashduty member list +| Area | Groups | +|------|--------| +| On-call | `incident`, `alert`, `alert-event`, `change`, `channel`, `route`, `oncall`, `schedule`, `calendar`, `integration`, `webhook`, `enrichment`, `field`, `template`, `insight`, `status-page` | +| Monitors | `monit`, `monit-query`, `datasource` | +| RUM | `rum`, `sourcemap` | +| AI SRE | `safari`, `session`, `automation` | +| Platform | `account`, `member`, `person`, `team`, `role`, `audit` | +| CLI | `login`, `whoami`, `config`, `update`, `version`, `completion` | -# View channels -flashduty channel list -``` +### Request bodies ---- +Generated commands expose each top-level request field as a typed flag, and take the full JSON body through `--data` (`--data -` reads stdin). Positional arguments and typed flags override the matching keys in `--data`, so nested objects and arrays go in `--data` while scalars stay readable: -## Authentication +```bash +flashduty status-page change-create --type incident \ + --title "API latency elevated" --status investigating \ + --data '{"updates":[{"status":"investigating","description":"Investigating.","component_changes":[{"component_id":"","status":"degraded"}]}]}' +``` + +## Authentication and configuration -The CLI resolves credentials in this order (highest priority first): +Credentials are resolved in this order: 1. `--app-key` flag (hidden, for scripting) 2. `FLASHDUTY_APP_KEY` environment variable -3. `~/.flashduty/config.yaml` (written by `flashduty login`) - -### Configuration File - -Stored at `~/.flashduty/config.yaml` with `0600` permissions: +3. `~/.flashduty/config.yaml`, written by `flashduty login` with `0600` permissions ```yaml app_key: your_app_key base_url: https://api.flashcat.cloud ``` -### Configuration Commands - ```bash flashduty config show # Print current config (key masked) -flashduty config set app_key KEY # Set app key -flashduty config set base_url URL # Override API endpoint +flashduty config set app_key KEY # Set the APP key +flashduty config set base_url URL # Override the API endpoint ``` ---- +| Environment variable | Purpose | +|----------------------|---------| +| `FLASHDUTY_APP_KEY` | APP key | +| `FLASHDUTY_BASE_URL` | API endpoint (default `https://api.flashcat.cloud`) | +| `FLASHDUTY_NO_UPDATE_CHECK=1` | Disable the daily background update check | +| `FLASHDUTY_UPDATE_BASE_URL` | Mirror used by `flashduty update` and the update check | -## Global Flags +## Global flags | Flag | Description | |------|-------------| -| `--output-format` | Output format: `table` (default), `json`, or `toon` (compact, fewer tokens) | -| `--json` | Output as JSON (alias for `--output-format json`) | +| `--output-format` | `table` (default), `json`, or `toon` | +| `--json` | Alias for `--output-format json` | | `--no-trunc` | Do not truncate long fields in table output | | `--base-url` | Override the API base URL | ---- +## Output formats -## Available Commands +- **Table** (default): aligned columns for people; long fields are truncated unless `--no-trunc` is set. +- **JSON** (`--json`): for `jq` and scripts, e.g. `flashduty incident list --json | jq '.[].title'`. +- **TOON** (`--output-format toon`): [Token-Oriented Object Notation](https://github.com/toon-format/toon-go). It drops the keys JSON repeats on every row, so lists cost far fewer tokens. Use it when an LLM or agent reads the output. -### `incident` - Incident Lifecycle Management (9 commands) +Every structured list page is capped at 16 KiB. A page that had to be reduced is reported on stderr, and list envelopes also carry `"truncated": true` in the payload. With `"emitted_rows": N`, only the first N rows were returned: re-request with a smaller `--limit` until the rows you hold reach `total`. Without it, every row is present but long values were clipped: narrow `--fields`. -```bash -flashduty incident list [flags] # List incidents (default: last 24h) -flashduty incident get [] # Get incident details (vertical view for single ID) -flashduty incident create [flags] # Create a new incident (interactive if flags missing) -flashduty incident update [flags] # Update incident fields -flashduty incident ack [] # Acknowledge incidents -flashduty incident close [] # Close (resolve) incidents -flashduty incident timeline # View incident timeline -flashduty incident alerts # View incident alerts -flashduty incident similar # Find similar historical incidents -``` - -**List flags:** - -| Flag | Description | Default | -|------|-------------|---------| -| `--progress` | Filter: Triggered, Processing, Closed | all | -| `--severity` | Filter: Critical, Warning, Info | all | -| `--channel` | Filter by channel ID | - | -| `--title` | Search by title keyword | - | -| `--since` | Start time (duration, date, datetime, or unix) | `24h` | -| `--until` | End time | `now` | -| `--limit` | Max results | `20` | -| `--page` | Page number | `1` | - -**Time format examples:** `5m`, `1h`, `24h`, `168h`, `2026-04-01`, `2026-04-01 10:00:00`, `1712000000` - -### `change` - Change Record Query (1 command) +## Updating ```bash -flashduty change list [flags] # List changes (deployments, configs) +flashduty update # Install the latest release in place +flashduty update --check # Only report whether a newer release exists ``` -Supports `--channel`, `--since`, `--until`, `--type`, `--limit`, `--page`. - -### `member` - Member Query (1 command) - -```bash -flashduty member list [flags] # List members -``` - -Supports `--name`, `--email`, `--page`. - -### `team` - Team Query (1 command) - -```bash -flashduty team list [flags] # List teams with members -``` - -Supports `--name`, `--page`. - -### `channel` - Channel Query (1 command) - -```bash -flashduty channel list [flags] # List collaboration spaces -``` - -Supports `--name`. - -### `escalation-rule` - Escalation Rule Query (1 command) - -```bash -flashduty escalation-rule list --channel # By channel ID -flashduty escalation-rule list --channel-name # By channel name (auto-resolved) -``` - -### `field` - Custom Field Query (1 command) - -```bash -flashduty field list [flags] # List custom field definitions -``` - -Supports `--name`. - -### `status-page` - Status Page Management (28 commands) - -The group is `status-page` (hyphenated), not `statuspage`. Nested object/array -fields carry no typed flag and must be supplied as JSON through `--data`; -`--data -` reads the entire request body from stdin. Positional arguments and -explicitly-set typed flags override the matching keys inside `--data`. - -**Pages, components, sections** - -```bash -flashduty status-page list # List status pages (JSON: {"items":[...]}) -flashduty status-page info # Page detail, incl. component and section IDs -flashduty status-page create --name --url-name --type \ - --date-view --display-uptime-mode -flashduty status-page update [--name ] [--url-name ] ... # Update a page -flashduty status-page delete # Delete a page -flashduty status-page component-upsert --data '{"components":[{"name":"API","section_id":""}]}' -flashduty status-page component-delete [...] --page-id -flashduty status-page section-upsert --data '{"sections":[{"name":"Core"}]}' -flashduty status-page section-delete [...] --page-id -``` - -**Events (incident / maintenance) and their timeline** - -```bash -flashduty status-page change-active-list --type # Only in-progress events -flashduty status-page change-list --type --status -flashduty status-page change-info --page-id --change-id -flashduty status-page change-create --type --title \ - --status <status> --description <text> --data '{"updates":[...]}' -flashduty status-page change-update --page-id <page-id> --change-id <change-id> [--title <title>] -flashduty status-page change-delete --page-id <page-id> --change-id <change-id> -flashduty status-page change-timeline-create --page-id <page-id> --change-id <change-id> \ - --status <status> --description <text> [--data '{"component_changes":[...]}'] -flashduty status-page change-timeline-update --page-id <page-id> --change-id <change-id> --update-id <update-id> [--description <text>] -flashduty status-page change-timeline-delete --page-id <page-id> --change-id <change-id> --update-id <update-id> -``` - -`change-create` takes `<page-id>` as a **required positional argument**, and its -required `updates` array (with the nested `component_changes`) has no flag — so a -real `change-create` call always carries a `--data` payload: - -```bash -flashduty status-page change-create 5750613685214 --type incident \ - --title "API latency elevated" --status investigating \ - --description "Investigating elevated latency." \ - --data '{"updates":[{"status":"investigating","description":"Team is investigating.","component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"degraded"}]}]}' -``` - -The whole body can also come from stdin with `--data -`: - -```bash -cat change.json | flashduty status-page change-create 5750613685214 --data - -``` - -Resolving an incident goes through `change-timeline-create`; every component the -event touched must be moved back to `operational`: - -```bash -flashduty status-page change-timeline-create --page-id 5750613685214 --change-id 5821693893131 \ - --status resolved --description "Recovered." \ - --data '{"component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"operational"}]}' -``` - -**Subscribers and templates** - -```bash -flashduty status-page subscriber-list <page-id> [--component-ids <ids>] [--page <n>] [--limit <n>] -flashduty status-page subscriber-import <page-id> --method <email|im> --data '{"subscribers":[...]}' -flashduty status-page subscriber-export <page-id> [--component-ids <ids>] -flashduty status-page template-list <page-id> --type <pre_defined|message> -flashduty status-page template-upsert <page-id> --type <pre_defined|message> --data '{"template":{...}}' -flashduty status-page template-delete --page-id <page-id> --template-id <template-id> --type <pre_defined|message> -``` - -**Migration from Atlassian Statuspage** - -```bash -flashduty status-page migrate-structure <source-page-id> --api-key <key> [--url-name <slug>] # Structure + history -flashduty status-page migrate-email-subscribers --source-page-id <id> --target-page-id <id> --api-key <key> -flashduty status-page migration-status <job-id> # Check migration job status -flashduty status-page migration-cancel <job-id> # Cancel a running migration job -``` - -Migration jobs are asynchronous. After starting `migrate-structure` or -`migrate-email-subscribers`, poll the returned `job_id`: - -```bash -flashduty status-page migration-status <job-id> -``` - -Typical flow: - -```bash -flashduty status-page migrate-structure page_123 --api-key $ATLASSIAN_STATUSPAGE_API_KEY -flashduty status-page migration-status <structure_job_id> -flashduty status-page migrate-email-subscribers --source-page-id page_123 \ - --target-page-id <target_page_id> --api-key $ATLASSIAN_STATUSPAGE_API_KEY -flashduty status-page migration-status <subscriber_job_id> -``` - -### `template` - Notification Template Management (4 commands) - -```bash -flashduty template get-preset --channel <channel> # Get preset template code -flashduty template validate --channel <channel> --file <path> # Validate and preview template -flashduty template variables [--category <category>] # List template variables -flashduty template functions [--type custom|sprig|all] # List template functions -``` - -Supported channels: `dingtalk`, `dingtalk_app`, `feishu`, `feishu_app`, `wecom`, `wecom_app`, `slack`, `slack_app`, `telegram`, `teams_app`, `email`, `sms`, `zoom`. - -### Utility Commands - -```bash -flashduty login # Authenticate interactively -flashduty config show # Show current configuration -flashduty config set # Set a configuration value -flashduty version # Print version information -flashduty completion # Generate shell completions (bash/zsh/fish/powershell) -``` - ---- - -## Output Formats - -**Table (default):** Human-readable, aligned columns, long fields truncated. - -``` -ID TITLE SEVERITY PROGRESS CHANNEL CREATED -inc_abc123 DB connection timeout Critical Triggered Production 2026-04-10 10:23 -inc_def456 High memory usage Warning Processing Staging 2026-04-10 09:15 -Showing 2 results (page 1, total 2). -``` - -**JSON (`--json` / `--output-format json`):** Machine-parseable output for `jq` and scripts. - -```bash -flashduty incident list --json | jq '.[].title' -``` - -**TOON (`--output-format toon`):** Token-Oriented Object Notation — drops the per-row repeated keys that JSON emits for uniform arrays, so list output costs materially fewer tokens. Preferred for LLM/agent consumption. Not directly `jq`-able; use `--json` when you need to pipe into `jq`. - -```bash -flashduty incident list --output-format toon -``` - -**Bounded list pages.** Every structured list page is capped at 16 KiB: an oversize page is emitted as the leading rows that fit, and the reduction is announced on stderr. A reduced **list envelope says so in the payload** too — scripts routinely discard stderr — and the marker's shape tells you which reduction happened: - -- `"truncated": true` **with** `"emitted_rows": N` — the page carries its first N rows and withheld the rest. The envelope's `total` / `has_next_page` / `search_after_ctx` still describe the page as the server returned it, so a page cut to 7 of 100 rows reads as complete. To collect everything, re-request with a `--limit` no larger than the rows you received (or, where the command documents its cursor as a row id, pass the last received row's id back as `--search-after-ctx`) and repeat until the rows you hold reach `total`; stopping on `has_next_page=false` alone silently drops the withheld rows. -- `"truncated": true` **alone** — every row was emitted, but long values inside them were clipped (stderr names the fields). Paging cannot restore them; narrow `--fields` and re-request. - -A bare top-level array has nowhere to carry the marker, so it announces a reduction only on stderr — page it with a lower `--limit`, or switch to a page-envelope command (`alert event-list`, `insight incident-list`) when a script needs completeness. - -**No truncation (`--no-trunc`):** Table with full field content. - ---- - ## Development -### Prerequisites - -- Go 1.24+ -- golangci-lint (auto-installed by Makefile) - -### Build +Requires Go 1.26+ (see `go.mod`). golangci-lint is installed by the Makefile. ```bash -make build # Build binary to bin/flashduty -make test # Run tests with race detection -make lint # Run linter -make check # Run all checks (fmt, lint, test, build) -make help # Show all available targets +make build # Build bin/flashduty +make test # Run tests with the race detector +make check # fmt, lint, test, build +make gen-cards # Regenerate the command fences in skills/flashduty/reference +make check-cards # Check those fences against the real command tree +make help # All targets ``` -### Dependencies +Generated commands live in `internal/cli/zz_generated_*.go` and are produced by `go run ./internal/cmd/cligen` from the OpenAPI spec bundled with go-flashduty. Hand-written commands live next to them. When a hand-written command takes a generated command's name, `TestCuratedCommandsCoverRequestFields` requires it to still expose every request field of that API. + +| Dependency | Purpose | +|------------|---------| +| [go-flashduty](https://github.com/flashcatcloud/go-flashduty) | Flashduty API client, generated from the OpenAPI spec | +| [cobra](https://github.com/spf13/cobra) | Command framework | +| [toon-go](https://github.com/toon-format/toon-go) | TOON output | +| [yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) | Config file | +| [x/term](https://pkg.go.dev/golang.org/x/term) | Masked APP key input | -| Package | Purpose | -|---------|---------| -| [flashduty-sdk](https://github.com/flashcatcloud/flashduty-sdk) | Flashduty API client | -| [cobra](https://github.com/spf13/cobra) | CLI framework | -| [yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) | Config file parsing | -| [x/term](https://pkg.go.dev/golang.org/x/term) | Masked password input | +## Related projects ---- +- [go-flashduty](https://github.com/flashcatcloud/go-flashduty): Go SDK for the Flashduty API +- [flashduty-mcp-server](https://github.com/flashcatcloud/flashduty-mcp-server): MCP server for Flashduty +- [terraform-provider-flashduty](https://github.com/flashcatcloud/terraform-provider-flashduty): Terraform provider for Flashduty resources ## Contributing -Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request, and note our [Code of Conduct](CODE_OF_CONDUCT.md). +Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request, and note our [Code of Conduct](CODE_OF_CONDUCT.md). - [Report a bug or request a feature](https://github.com/flashcatcloud/flashduty-cli/issues/new/choose) - [Get help and support](SUPPORT.md) - [Report a security vulnerability](SECURITY.md) ---- - ## License -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. +MIT. See [LICENSE](LICENSE). diff --git a/README_zh.md b/README_zh.md index b4f736d..59e2b34 100644 --- a/README_zh.md +++ b/README_zh.md @@ -7,7 +7,16 @@ [![CI](https://img.shields.io/github/actions/workflow/status/flashcatcloud/flashduty-cli/ci.yml?style=flat-square&branch=main&label=CI)](https://github.com/flashcatcloud/flashduty-cli/actions) [![Go Report Card](https://goreportcard.com/badge/github.com/flashcatcloud/flashduty-cli?style=flat-square)](https://goreportcard.com/report/github.com/flashcatcloud/flashduty-cli) -[Flashduty](https://flashcat.cloud) 平台的命令行工具。在终端中管理故障、值班、状态页等。 +**Flashduty CLI**(`flashduty`)是 [Flashduty](https://www.flashduty.com) 故障管理与值班平台的官方开源命令行工具。在终端、Shell 脚本或 AI 编程助手里,都可以用它处理故障和告警、查询值班、发布状态页更新、管理监控和 RUM,以及调用 AI SRE。 + +[官网](https://www.flashduty.com) · [CLI 文档](https://docs.flashduty.com/zh/developer/cli) · [API 参考](https://docs.flashduty.com/zh/openapi/introduction) · [控制台](https://console.flashcat.cloud) · [博客:写给人和 Agent 的 CLI](https://www.flashduty.com/zh/now/blog/flashduty-cli) · [版本发布](https://github.com/flashcatcloud/flashduty-cli/releases) + +## 特点 + +- **覆盖全部公开 API。** 每个公开的 Flashduty API 都有对应命令,由 OpenAPI 规范经 [go-flashduty](https://github.com/flashcatcloud/go-flashduty) SDK 生成。故障、告警、值班、状态页等常用流程另有手写命令,flag 更短,表格更易读。 +- **命令名可预测。** API 路径直接对应命令:`POST /incident/merge` 是 `flashduty incident merge`,`POST /status-page/change/create` 是 `flashduty status-page change-create`。 +- **适合脚本和 Agent。** 输出支持 `table`、`json`、`toon`(紧凑格式,更省 token)。列表分页有大小上限,被裁剪时会明确标出。`--fields` 只返回需要的字段。 +- **单个二进制。** 支持 macOS、Linux、Windows 的 amd64 和 arm64。`flashduty update` 原地升级。 ## 安装 @@ -25,348 +34,150 @@ irm https://static.flashcat.cloud/flashduty-cli/install.ps1 | iex ### 手动下载 -从 [GitHub Releases](https://github.com/flashcatcloud/flashduty-cli/releases) 下载适合您平台的最新版本。 +从 [GitHub Releases](https://github.com/flashcatcloud/flashduty-cli/releases) 下载对应平台的压缩包,解压后把二进制放到 `PATH` 中。 -### 选项 +### 安装选项 | 变量 | 说明 | 默认值 | |------|------|--------| -| `FLASHDUTY_VERSION` | 安装指定版本(如 `v0.1.2`) | 最新版 | -| `FLASHDUTY_INSTALL_DIR` | 自定义安装目录 | `/usr/local/bin`(Shell)、`~\.flashduty\bin`(PowerShell) | -| `MIRROR_URL` | 覆盖安装脚本使用的 release 资源镜像 | `https://static.flashcat.cloud/flashduty-cli` | -| `FLASHDUTY_UPDATE_BASE_URL` | 覆盖 `flashduty update` 和自动更新检查的 base URL | `https://static.flashcat.cloud/flashduty-cli` | - -## 快速开始 +| `FLASHDUTY_VERSION` | 安装指定版本(如 `v1.5.12`) | 最新版 | +| `FLASHDUTY_INSTALL_DIR` | 安装目录 | `/usr/local/bin`(shell),`~\.flashduty\bin`(PowerShell) | +| `MIRROR_URL` | 下载镜像地址(必须是 `https://`) | `https://static.flashcat.cloud/flashduty-cli` | -### 1. 认证 +## 快速上手 ```bash +# 1. 用 APP Key 登录(控制台:我的 → APP Key) flashduty login -``` +flashduty whoami -系统会提示输入 Flashduty APP Key。获取方式:登录 [Flashduty 控制台](https://console.flashcat.cloud),进入 **账户设置 > APP Key**。 +# 2. 处理故障 +flashduty incident list --since 24h --severity Critical +flashduty incident info <incident_id> +flashduty incident ack <incident_id> +flashduty incident merge <target_id> --source <id1>,<id2> # 源故障默认关闭并保留 +flashduty incident close <incident_id> -也可以通过环境变量设置: +# 3. 谁在值班,最近有什么变更 +flashduty oncall who +flashduty change list --since 2h -```bash -export FLASHDUTY_APP_KEY=your_app_key +# 4. 浏览任意模块 +flashduty status-page --help ``` -### 2. 使用 - -```bash -# 列出最近的故障 -flashduty incident list +APP Key 的创建方法见 [API 参考](https://docs.flashduty.com/zh/openapi/introduction)。 -# 查看故障详情 -flashduty incident get <incident_id> +## 命令分组 -# 列出团队成员 -flashduty member list +`flashduty <分组> --help` 列出分组内的命令,`flashduty <分组> <命令> --help` 查看 flag 和示例。常用流程见 [CLI 文档](https://docs.flashduty.com/zh/developer/cli)。 -# 查看协作空间 -flashduty channel list -``` +| 模块 | 分组 | +|------|------| +| On-call | `incident`、`alert`、`alert-event`、`change`、`channel`、`route`、`oncall`、`schedule`、`calendar`、`integration`、`webhook`、`enrichment`、`field`、`template`、`insight`、`status-page` | +| 监控 | `monit`、`monit-query`、`datasource` | +| RUM | `rum`、`sourcemap` | +| AI SRE | `safari`、`session`、`automation` | +| 平台 | `account`、`member`、`person`、`team`、`role`、`audit` | +| CLI 自身 | `login`、`whoami`、`config`、`update`、`version`、`completion` | ---- +### 请求体 -## 认证方式 +生成的命令把请求的每个顶层字段做成带类型的 flag,完整 JSON 请求体通过 `--data` 传入(`--data -` 从 stdin 读取)。位置参数和 flag 会覆盖 `--data` 中的同名字段,所以嵌套对象和数组放进 `--data`,标量字段用 flag: -CLI 按以下优先级解析凭证(优先级从高到低): +```bash +flashduty status-page change-create <page_id> --type incident \ + --title "API latency elevated" --status investigating \ + --data '{"updates":[{"status":"investigating","description":"Investigating.","component_changes":[{"component_id":"<component_id>","status":"degraded"}]}]}' +``` -1. `--app-key` 参数(隐藏参数,用于脚本) -2. `FLASHDUTY_APP_KEY` 环境变量 -3. `~/.flashduty/config.yaml`(由 `flashduty login` 写入) +## 认证与配置 -### 配置文件 +凭据按以下顺序读取: -存储在 `~/.flashduty/config.yaml`,权限为 `0600`: +1. `--app-key` flag(隐藏,供脚本使用) +2. `FLASHDUTY_APP_KEY` 环境变量 +3. `~/.flashduty/config.yaml`,由 `flashduty login` 写入,权限 `0600` ```yaml app_key: your_app_key base_url: https://api.flashcat.cloud ``` -### 配置命令 - ```bash -flashduty config show # 查看当前配置(密钥已脱敏) +flashduty config show # 打印当前配置(key 已脱敏) flashduty config set app_key KEY # 设置 APP Key -flashduty config set base_url URL # 覆盖 API 地址 +flashduty config set base_url URL # 修改 API 地址 ``` ---- +| 环境变量 | 用途 | +|----------|------| +| `FLASHDUTY_APP_KEY` | APP Key | +| `FLASHDUTY_BASE_URL` | API 地址(默认 `https://api.flashcat.cloud`) | +| `FLASHDUTY_NO_UPDATE_CHECK=1` | 关闭每天一次的后台更新检查 | +| `FLASHDUTY_UPDATE_BASE_URL` | `flashduty update` 和更新检查使用的镜像地址 | -## 全局参数 +## 全局 flag -| 参数 | 说明 | +| Flag | 说明 | |------|------| -| `--json` | 以 JSON 格式输出 | -| `--no-trunc` | 表格输出时不截断长字段 | +| `--output-format` | `table`(默认)、`json` 或 `toon` | +| `--json` | 等同 `--output-format json` | +| `--no-trunc` | 表格输出不截断长字段 | | `--base-url` | 覆盖 API 地址 | ---- - -## 可用命令 - -### `incident` - 故障生命周期管理(9 个命令) - -```bash -flashduty incident list [flags] # 列出故障(默认最近 24 小时) -flashduty incident get <id> [<id2>] # 查看故障详情(单个 ID 时显示详细视图) -flashduty incident create [flags] # 创建故障(缺少参数时进入交互模式) -flashduty incident update <id> [flags] # 更新故障字段 -flashduty incident ack <id> [<id2>] # 认领故障 -flashduty incident close <id> [<id2>] # 关闭故障 -flashduty incident timeline <id> # 查看故障时间线 -flashduty incident alerts <id> # 查看故障告警 -flashduty incident similar <id> # 查找相似故障 -``` - -**列表参数:** - -| 参数 | 说明 | 默认值 | -|------|------|--------| -| `--progress` | 筛选:Triggered、Processing、Closed | 全部 | -| `--severity` | 筛选:Critical、Warning、Info | 全部 | -| `--channel` | 按协作空间 ID 筛选 | - | -| `--title` | 按标题关键字搜索 | - | -| `--since` | 开始时间(时长、日期、日期时间或 Unix 时间戳) | `24h` | -| `--until` | 结束时间 | `now` | -| `--limit` | 最大结果数 | `20` | -| `--page` | 页码 | `1` | - -**时间格式示例:** `5m`、`1h`、`24h`、`168h`、`2026-04-01`、`2026-04-01 10:00:00`、`1712000000` - -### `change` - 变更记录查询(1 个命令) - -```bash -flashduty change list [flags] # 列出变更记录(部署、配置等) -``` - -支持 `--channel`、`--since`、`--until`、`--type`、`--limit`、`--page`。 - -### `member` - 成员查询(1 个命令) - -```bash -flashduty member list [flags] # 列出成员 -``` - -支持 `--name`、`--email`、`--page`。 - -### `team` - 团队查询(1 个命令) - -```bash -flashduty team list [flags] # 列出团队及成员 -``` - -支持 `--name`、`--page`。 - -### `channel` - 协作空间查询(1 个命令) - -```bash -flashduty channel list [flags] # 列出协作空间 -``` - -支持 `--name`。 - -### `escalation-rule` - 分派策略查询(1 个命令) - -```bash -flashduty escalation-rule list --channel <id> # 按协作空间 ID 查询 -flashduty escalation-rule list --channel-name <name> # 按协作空间名称查询(自动解析) -``` - -### `field` - 自定义字段查询(1 个命令) - -```bash -flashduty field list [flags] # 列出自定义字段定义 -``` - -支持 `--name`。 - -### `status-page` - 状态页管理(28 个命令) - -命令组名是 `status-page`(带连字符),不是 `statuspage`。嵌套对象、数组类字段没有 -对应的 flag,必须通过 `--data` 传 JSON;`--data -` 表示整个请求体从 stdin 读取。 -位置参数和显式设置的 flag 会覆盖 `--data` 里的同名字段。 - -**状态页、组件、分组** - -```bash -flashduty status-page list # 列出状态页(JSON 形如 {"items":[...]}) -flashduty status-page info <page-id> # 状态页详情,含组件 ID 和分组 ID -flashduty status-page create --name <name> --url-name <slug> --type <public|internal> \ - --date-view <calendar|list> --display-uptime-mode <chart_and_percentage|chart|none> -flashduty status-page update <page-id> [--name <name>] [--url-name <slug>] ... # 更新状态页 -flashduty status-page delete <page-id> # 删除状态页 -flashduty status-page component-upsert <page-id> --data '{"components":[{"name":"API","section_id":"<section-id>"}]}' -flashduty status-page component-delete <component-id> [<id2>...] --page-id <page-id> -flashduty status-page section-upsert <page-id> --data '{"sections":[{"name":"核心服务"}]}' -flashduty status-page section-delete <section-id> [<id2>...] --page-id <page-id> -``` - -**事件(故障 / 维护)与时间线** - -```bash -flashduty status-page change-active-list <page-id> --type <incident|maintenance> # 只列进行中的事件 -flashduty status-page change-list <page-id> --type <incident|maintenance> --status <status> -flashduty status-page change-info --page-id <page-id> --change-id <change-id> -flashduty status-page change-create <page-id> --type <incident|maintenance> --title <title> \ - --status <status> --description <text> --data '{"updates":[...]}' -flashduty status-page change-update --page-id <page-id> --change-id <change-id> [--title <title>] -flashduty status-page change-delete --page-id <page-id> --change-id <change-id> -flashduty status-page change-timeline-create --page-id <page-id> --change-id <change-id> \ - --status <status> --description <text> [--data '{"component_changes":[...]}'] -flashduty status-page change-timeline-update --page-id <page-id> --change-id <change-id> --update-id <update-id> [--description <text>] -flashduty status-page change-timeline-delete --page-id <page-id> --change-id <change-id> --update-id <update-id> -``` - -`change-create` 的 `<page-id>` 是**必填位置参数**;必填的 `updates` 数组(以及嵌套在里面的 -`component_changes`)没有对应的 flag,所以真实的 `change-create` 调用一定带 `--data`: - -```bash -flashduty status-page change-create 5750613685214 --type incident \ - --title "API 延迟升高" --status investigating \ - --description "正在排查延迟升高问题。" \ - --data '{"updates":[{"status":"investigating","description":"团队正在排查。","component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"degraded"}]}]}' -``` - -整个请求体也可以用 `--data -` 从 stdin 读: - -```bash -cat change.json | flashduty status-page change-create 5750613685214 --data - -``` - -关闭事件走 `change-timeline-create`,并且事件涉及的每个组件都要改回 `operational`: - -```bash -flashduty status-page change-timeline-create --page-id 5750613685214 --change-id 5821693893131 \ - --status resolved --description "已恢复。" \ - --data '{"component_changes":[{"component_id":"01KC3GAZ6ZJE40H55GM31RPWZE","status":"operational"}]}' -``` - -**订阅者与模板** - -```bash -flashduty status-page subscriber-list <page-id> [--component-ids <ids>] [--page <n>] [--limit <n>] -flashduty status-page subscriber-import <page-id> --method <email|im> --data '{"subscribers":[...]}' -flashduty status-page subscriber-export <page-id> [--component-ids <ids>] -flashduty status-page template-list <page-id> --type <pre_defined|message> -flashduty status-page template-upsert <page-id> --type <pre_defined|message> --data '{"template":{...}}' -flashduty status-page template-delete --page-id <page-id> --template-id <template-id> --type <pre_defined|message> -``` - -**从 Atlassian Statuspage 迁移** - -```bash -flashduty status-page migrate-structure <source-page-id> --api-key <key> [--url-name <slug>] # 迁移结构与历史 -flashduty status-page migrate-email-subscribers --source-page-id <id> --target-page-id <id> --api-key <key> -flashduty status-page migration-status <job-id> # 查询迁移任务状态 -flashduty status-page migration-cancel <job-id> # 取消正在跑的迁移任务 -``` - -迁移任务是异步的。启动 `migrate-structure` 或 `migrate-email-subscribers` 之后, -用返回的 `job_id` 轮询: - -```bash -flashduty status-page migration-status <job-id> -``` - -典型流程: - -```bash -flashduty status-page migrate-structure page_123 --api-key $ATLASSIAN_STATUSPAGE_API_KEY -flashduty status-page migration-status <structure_job_id> -flashduty status-page migrate-email-subscribers --source-page-id page_123 \ - --target-page-id <target_page_id> --api-key $ATLASSIAN_STATUSPAGE_API_KEY -flashduty status-page migration-status <subscriber_job_id> -``` - -### `template` - 通知模板管理(4 个命令) - -```bash -flashduty template get-preset --channel <channel> # 获取预设模板代码 -flashduty template validate --channel <channel> --file <path> # 验证并预览模板 -flashduty template variables [--category <category>] # 列出模板变量 -flashduty template functions [--type custom|sprig|all] # 列出模板函数 -``` - -支持的通知渠道:`dingtalk`、`dingtalk_app`、`feishu`、`feishu_app`、`wecom`、`wecom_app`、`slack`、`slack_app`、`telegram`、`teams_app`、`email`、`sms`、`zoom`。 - -### 工具命令 - -```bash -flashduty login # 交互式认证 -flashduty config show # 查看当前配置 -flashduty config set # 设置配置项 -flashduty version # 打印版本信息 -flashduty completion # 生成 Shell 自动补全(bash/zsh/fish/powershell) -``` - ---- - ## 输出格式 -**表格(默认):** 人类可读,列对齐,长字段自动截断。 +- **Table**(默认):对齐的列,给人看;长字段会截断,加 `--no-trunc` 不截断。 +- **JSON**(`--json`):给 `jq` 和脚本用,例如 `flashduty incident list --json | jq '.[].title'`。 +- **TOON**(`--output-format toon`):[Token-Oriented Object Notation](https://github.com/toon-format/toon-go)。JSON 每行都重复字段名,TOON 不重复,列表输出的 token 少得多。LLM 或 Agent 读取输出时用它。 -``` -ID TITLE SEVERITY PROGRESS CHANNEL CREATED -inc_abc123 DB connection timeout Critical Triggered Production 2026-04-10 10:23 -inc_def456 High memory usage Warning Processing Staging 2026-04-10 09:15 -Showing 2 results (page 1, total 2). -``` +每一页结构化列表最大 16 KiB。被裁剪的页会在 stderr 上提示,列表的返回体里也会带 `"truncated": true`。同时带 `"emitted_rows": N` 表示只返回了前 N 行:用更小的 `--limit` 重新请求,直到拿到的行数达到 `total`。不带 `emitted_rows` 表示行都在,但长字段被截断:用 `--fields` 缩小字段范围。 -**JSON(`--json`):** 机器可解析,可直接管道给 `jq`。 +## 升级 ```bash -flashduty incident list --json | jq '.[].title' +flashduty update # 原地安装最新版 +flashduty update --check # 只检查是否有新版本 ``` -**列表页有 16 KiB 上限。** 结构化列表的一页超出上限时,只输出能装下的前若干行,并在 stderr 说明。如果该页是分页信封(形如 `{items, total, has_next_page, …}`),载荷内也会带上标记:`"truncated": true` 与 `"emitted_rows": N`(保留了前 N 行,其余被丢弃)。`total` / `has_next_page` / `search_after_ctx` 仍是服务端原值,因此一页被裁到"100 行里只发 7 行"时,看起来与完整页无异。脚本要完整翻页时,请从**实际收到的最后一行**之后继续(用不大于已收到行数的 `--limit` 重新请求,再跟随该响应的游标),不要只依赖 `has_next_page`;若只有 `"truncated": true` 而没有 `emitted_rows`,说明行内长值被裁剪——翻页无法恢复,应收窄 `--fields` 后重新请求。 - -**不截断(`--no-trunc`):** 表格显示完整字段内容。 - ---- - ## 开发 -### 前置条件 - -- Go 1.24+ -- golangci-lint(Makefile 自动安装) - -### 构建 +需要 Go 1.26+(见 `go.mod`)。golangci-lint 由 Makefile 自动安装。 ```bash -make build # 构建二进制文件到 bin/flashduty -make test # 运行测试(启用竞态检测) -make lint # 运行代码检查 -make check # 运行所有检查(格式化、检查、测试、构建) -make help # 显示所有可用目标 +make build # 构建 bin/flashduty +make test # 运行测试(带 race 检测) +make check # fmt、lint、test、build +make gen-cards # 重新生成 skills/flashduty/reference 中的命令片段 +make check-cards # 用真实命令树校验这些片段 +make help # 全部目标 ``` -### 依赖 +生成的命令在 `internal/cli/zz_generated_*.go`,由 `go run ./internal/cmd/cligen` 根据 go-flashduty 自带的 OpenAPI 规范生成;手写命令放在同一目录。手写命令占用了生成命令的名字时,`TestCuratedCommandsCoverRequestFields` 要求它仍然能设置该 API 的每个请求字段。 -| 包 | 用途 | -|----|------| -| [flashduty-sdk](https://github.com/flashcatcloud/flashduty-sdk) | Flashduty API 客户端 | -| [cobra](https://github.com/spf13/cobra) | CLI 框架 | -| [yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) | 配置文件解析 | -| [x/term](https://pkg.go.dev/golang.org/x/term) | 密码输入脱敏 | +| 依赖 | 用途 | +|------|------| +| [go-flashduty](https://github.com/flashcatcloud/go-flashduty) | Flashduty API 客户端,由 OpenAPI 规范生成 | +| [cobra](https://github.com/spf13/cobra) | 命令框架 | +| [toon-go](https://github.com/toon-format/toon-go) | TOON 输出 | +| [yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) | 配置文件 | +| [x/term](https://pkg.go.dev/golang.org/x/term) | APP Key 隐藏输入 | + +## 相关项目 ---- +- [go-flashduty](https://github.com/flashcatcloud/go-flashduty):Flashduty API 的 Go SDK +- [flashduty-mcp-server](https://github.com/flashcatcloud/flashduty-mcp-server):Flashduty 的 MCP Server +- [terraform-provider-flashduty](https://github.com/flashcatcloud/terraform-provider-flashduty):管理 Flashduty 资源的 Terraform Provider ## 参与贡献 -欢迎贡献代码!提交 Pull Request 前请阅读 [CONTRIBUTING.md](CONTRIBUTING.md),并遵守我们的[行为准则](CODE_OF_CONDUCT.md)。 +欢迎贡献。提交 PR 前请阅读 [CONTRIBUTING.md](CONTRIBUTING.md),并遵守[行为准则](CODE_OF_CONDUCT.md)。 -- [报告缺陷或提交需求](https://github.com/flashcatcloud/flashduty-cli/issues/new/choose) -- [获取帮助与支持](SUPPORT.md) +- [报告问题或提需求](https://github.com/flashcatcloud/flashduty-cli/issues/new/choose) +- [获取帮助](SUPPORT.md) - [报告安全漏洞](SECURITY.md) ---- - ## 许可证 -本项目基于 MIT 许可证开源 - 详见 [LICENSE](LICENSE) 文件。 +MIT,详见 [LICENSE](LICENSE)。