关于 incidentio-cli
incidentio-cli 是 incident.io 的命令行接口,适合通过 JSON 命令管理事故、告警、排班和服务目录。它依据官方 OpenAPI 规范生成命令,同时区分公开 API 与需要浏览器会话的内部接口。
主要功能
- 01按官方 OpenAPI 规范生成命令
- 02管理事故、告警和升级流程
- 03查询排班、目录及配置资源
- 04支持 Bearer API 密钥认证
- 05可选浏览器会话调用内部 API
适用场景
- 01查询或创建事故
- 02处理告警并查看升级状态
- 03维护排班和服务目录条目
- 04通过内部接口查询仪表板与策略
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ paymog/ incidentio-cli --skill incidentio-cli安装后在 Claude Code 中输入/incidentio-cli确认已加载。
详细介绍
incident.io CLI
调用 incidentio 二进制文件。权威来源:paymog/incidentio-cli。
与 blacksmith 的 cookie-replay 不同,incident.io 有一个由 Bearer 令牌认证的真正的公共 API。incidentio 直接调用该 API——无需浏览器,也无需 Cookie。命令根据 incident.io 官方 OpenAPI 规范生成(每个资源标签对应一份规范),因此所有有文档记录的端点都可用。API 基础 URL 为 https://api.incident.io。
身份验证(执行任何命令前都必须完成)
需要一个 Bearer API 密钥。在 Settings → API keys (app.incident.io/settings/api-keys) 中创建;创建时可以选择其作用域(例如 incidents.create),创建后作用域集合将固定不变。
incidentio auth set <api-key> # store it (chmod 600, ~/.config/incidentio/creds.json)
incidentio auth status # show masked key + last-updated
incidentio auth logout # clear stored credentials
解析顺序:--api-key <key> 标志 → $INCIDENT_API_KEY → 已存储的凭据。对于一次性使用或 CI,导出 INCIDENT_API_KEY 即可跳过 auth set。
401/403 表示密钥无效、已撤销,或缺少端点所需的作用域(例如,使用只读密钥调用 incidents create)。请在控制面板中重新检查密钥的作用域。
用法
incidentio list [filter] # every command (optionally filtered by substring)
incidentio list incidents # all verbs for the `incidents` resource
incidentio <resource> <verb> [flags]
命令由两个词元组成:<resource> <verb>。输出为格式化的 JSON——可以通过管道传给 jq,或传入 --raw 获取未格式化的响应。
标志
| 标志 | 含义 |
|---|---|
--api-key <key> | 此次调用使用的 API 密钥(否则使用 $INCIDENT_API_KEY 或已存储的密钥) |
--<param> <value> | 路径参数:--id、--user-id、--schedule-id、--alert-source-config-id |
--query key=value | 查询参数,可重复使用(包括方括号过滤器——见下文) |
--body-file <path> | 从文件读取 JSON 请求正文(用于 POST/PUT) |
--body-json '<json>' | 内联 JSON 请求正文 |
--set a.b=value | 设置正文中的字段,可重复使用 |
--raw | 输出原始响应,不进行 JSON 格式化 |
--auth cookie|bearer | (仅限 raw)强制指定身份验证模式;否则根据路径推断 |
方括号查询过滤器
列表端点使用方括号键(Rails 风格)。将其原样传给 --query;多值过滤器可重复传入。incident.io 的列表过滤器功能强大,但有文档记录的参数名称会显示在 incidentio list <resource> 输出中。
# incidents in the "live" status category, severity rank >= a given severity
incidentio incidents list --query 'status_category[one_of]=live' --query 'severity[gte]=<sev-id>'
# created within a date range (tilde-separated)
incidentio incidents list --query 'created_at[date_range]=2026-06-01~2026-06-30'
# any-of multiple modes
incidentio incidents list --query 'mode[one_of]=standard' --query 'mode[one_of]=retrospective'
日期使用 ISO-8601 UTC 格式(2026-06-04T00:00:00.000Z)。要获取“现在”的时间,请计算:date -u +%FT%T.000Z(macOS)或 date -u -d '30 days ago' +%FT%T.000Z(GNU)。
命令范围
运行 incidentio list 可查看权威命令列表(约 324 个命令:涵盖 53 个资源的约 179 个公共 Bearer API 命令,另有约 145 个标记为 🍪 的内部/控制面板命令,以及 raw 备用入口)。以下为分类重点命令(除非另有说明,均为 GET):
事件
incidentio incidents list [--query status[one_of]=<id>] [--query page_size=50]
incidentio incidents show --id <id>
incidentio incidents create --body-json '{"name":"...","severity_id":"...","visibility":"public"}'
incidentio incidents edit --id <id> # edit fields/status of an incident
incidentio incidents import-postmortem-document --id <id>
操作、后续跟进、附件
incidentio actions list --query incident_id=<id>
incidentio follow-ups list --query incident_id=<id>
incidentio follow-ups create --body-json '{"incident_id":"...","content":"..."}'
incidentio follow-ups connect-external-issue --id <id> --body-json '{...}'
incidentio incident-attachments list --query incident_id=<id>
告警与告警来源
incidentio alerts list
incidentio alerts show --id <id>
incidentio alerts resolve --id <id>
incidentio alert-sources list
incidentio alert-routes list
incidentio alert-routes show --id <id>
incidentio alert-routes update --id <id> --body-json '{...}' # public API, no version field
incidentio alert-events create-http --alert-source-config-id <id> --body-json '{...}'
incidentio heartbeat ping --alert-source-config-id <id> # GET ping
# Alert route with incident-template custom-field binding (🍪 dashboard API)
# Rules:
# 1. version = current_version + 1 (optimistic concurrency — GET it first).
# 2. OMIT the `users` key from every escalation_config.escalation_targets entry;
# the GET payload carries an invalid users binding that PUT rejects. API restores it.
# 3. Custom-field bindings: static option OR navigation-expression reference.
# Static: array_value:[{reference:"",value:"<opt-id>",label:"<label>",sort_key:0}]
# Expression: array_value:[{reference:"expressions[\"<expr-ref>\"]"}]
# 4. Navigation expressions (derive component array from Service catalog attribute):
# Declare in top-level `expressions` array; bind by reference in custom_fields.
# merge_strategy: "first-wins" | "last-wins" | "append"
incidentio alert-routes show-route --id <route-id>
incidentio alert-routes update-route --id <route-id> --body-json '{
"version":4,
"escalation_config":{"escalation_targets":[
{"type":"schedule","id":"<sched-id>"}
]},
"incident_template":{
"custom_fields":[{
"custom_field_id":"<field-id>",
"merge_strategy":"first-wins",
"binding":{"array_value":[{"reference":"","value":"<option-id>","label":"<label>","sort_key":0}]}
}]
}}'
# With a catalog navigation expression (auto-derive Affected Components from alert Service):
incidentio alert-routes update-route-expr --id <route-id> --body-json '{
"version":5,
"expressions":[{
"id":"01EXPR001","label":"Affected Components","reference":"affected_components",
"returns":{"type":"CatalogEntry[\"<component-type-id>\"]","array":true},
"root_reference":"alert.attributes.<service-alert-attr-id>",
"operations":[{"operation_type":"navigate",
"returns":{"type":"CatalogEntry[\"<component-type-id>\"]","array":true},
"navigate":{"reference":"catalog_attribute[\"components\"]","reference_label":"Components"}}]
}],
"incident_template":{
"custom_fields":[{
"custom_field_id":"<affected-components-field-id>",
"merge_strategy":"first-wins",
"binding":{"array_value":[{"reference":"expressions[\"affected_components\"]"}]}
}]
}}'
升级与值班安排
incidentio escalations list [--query status=active]
incidentio escalations create --body-json '{...}'
incidentio escalations cancel-escalation --id <id>
incidentio escalation-paths list
incidentio schedules list
incidentio schedules show --id <id>
incidentio schedule-entries list --schedule-id <id>
incidentio schedule-overrides list --schedule-id <id>
incidentio schedule-replicas list --schedule-id <id>
目录(以代码形式管理服务目录)
# Public API (Bearer)
incidentio catalog-types list
incidentio catalog-types show --id <type-id> # includes .schema.attributes[].id
incidentio catalog-types create --body-json '{...}'
incidentio catalog-types update-type-schema --id <id> --body-json '{...}'
incidentio catalog-entries list --query catalog_type_id=<id>
incidentio catalog-entries create --body-json '{...}' # simple entries
incidentio catalog-entries update --id <id> --body-json '{...}'
incidentio catalog-entries bulk-update-entries --body-json '{...}'
incidentio catalog-resources list
# Catalog entries with attribute_values (🍪 dashboard API — verified contract)
# Required body: catalog_type_id, name, external_id, attribute_values (pass {} when none)
# Attribute shapes:
# plain text: {"<attr-id>":{"value":"some text"}}
# catalog-relation: {"<attr-id>":{"array_value":["<entry-id>",...]}}
# intentional clear (create only): {"<attr-id>":{"value":null}}
# Get attribute IDs: incidentio catalog-types show --id <type-id> | jq '.catalog_type.schema.attributes[].id'
incidentio catalog-entries create-entry --body-json '{
"catalog_type_id":"<type-id>",
"name":"My Service",
"external_id":"my-service",
"attribute_values":{
"<attr-id>":{"value":"production"},
"<rel-attr-id>":{"array_value":["<related-entry-id>"]}
}}'
incidentio catalog-entries update-entry --id <entry-id> --body-json '{
"name":"My Service",
"attribute_values":{"<attr-id>":{"value":"staging"}}}'
配置(自定义字段、严重级别、类型、角色、状态、时间戳)
# Public API (Bearer)
incidentio custom-fields list
incidentio custom-fields create --body-json '{...}' # basic fields
incidentio custom-field-options list --query custom_field_id=<id>
incidentio severities list
incidentio incident-types list
incidentio incident-roles list
incidentio incident-statuses list
incidentio incident-timestamps list
# Catalog-backed multi-select custom field (🍪 dashboard API — supports catalog_type_id,
# field_mode, condition_groups not available in the public API)
# Required body: name, description, field_type:"multi_select", catalog_type_id, field_mode,
# dynamic_options, cannot_be_unset, options, condition_groups
incidentio custom-fields create-catalog-backed --body-json '{
"name":"Affected Services",
"description":"Which services are affected by this incident",
"field_type":"multi_select",
"catalog_type_id":"<catalog-type-id>",
"field_mode":"dashboard",
"dynamic_options":true,
"cannot_be_unset":false,
"options":[],
"condition_groups":[]}'
状态页面
# Read (Bearer public API)
incidentio status-pages list
incidentio status-pages show --status-page-id <id> # includes current_structure
incidentio status-page-incidents list --query status_page_id=<id>
incidentio status-page-maintenances list --query status_page_id=<id>
# Manage the page itself (🍪 internal — the public API cannot create pages/components)
# Simple page:
incidentio status-pages create --body-json '{"name":"Acme","subpath":"acme","theme":"light"}'
# Catalog-backed parent page with auto-generated sub-pages per catalog entry:
incidentio status-pages create --body-json '{
"name":"Acme","subpath":"acme","theme":"light",
"parent_page_options":{
"page_type":"parent",
"split_by_catalog_type_id":"<catalog-type-id>",
"split_by_component_attribute_id":"<component-attr-id>",
"sub_pages":[
{"defined_by_catalog_entry_id":"<entry-id>","name":"Team A","subpath":"team-a"}
]
}}'
# Update — name, subpath, support_label are ALL required even for a single-field change:
incidentio status-pages update --status-page-id <id> --body-json '{"name":"Acme","subpath":"acme","support_label":"Report a problem","allow_search_engine_indexing":false}'
incidentio status-page-components create --body-json '{"name":"API","status_page_id":"<id>"}'
incidentio status-page-components delete --id <component-id>
incidentio status-page-structures create --body-json '{"status_page_id":"<id>","items":[
{"group":{"name":"Core","display_aggregated_uptime":true,"hidden":false,"components":[
{"component_id":"<id>","display_uptime":true,"hidden":false}]}},
{"component":{"component_id":"<id>","display_uptime":true,"hidden":false}}]}'
# Audit subscribers / templates (🍪)
incidentio status-page-subscriptions --query status_page_id=<id>
incidentio status-page-templates --query status_page_id=<id>
# Retrospective status-page incident (Bearer) — bulk-import historical incidents
incidentio status-page-incidents create-status-page-retrospective-incident --body-json '{
"status_page_id":"<id>",
"name":"Elevated API latency",
"idempotency_key":"historical-2021-08-17",
"updates":[
{"incident_status":"investigating","message":"Looking into it.","published_at":"2021-08-17T13:28:57Z"},
{"incident_status":"resolved","message":"Fixed.","published_at":"2021-08-17T14:00:00Z",
"component_statuses":[{"component_id":"<id>","component_status":"operational"}]}
]}'
说明:创建页面、设置品牌样式以及定义页面组件/布局仅限内部使用(需要 Cookie 会话);公共 Bearer API 仅支持列出/显示页面,以及发布事件/维护信息。公共页面的组件是页面原生对象(先创建组件,再使用 status-page-structures 放置),并非自定义字段(该模型用于内部页面)。theme 的值为 light|dark。Team 套餐仅允许创建一个公共页面(第二次调用 create 会返回 422 exceeded your allowance)。Logo、favicon 和品牌颜色需在控制面板中上传。
对于基于目录的父页面:split_by_catalog_type_id 和 split_by_component_attribute_id 用于标识子页面所基于的目录类型,以及该类型中指向组件的属性;每个 sub_pages 条目都将一个目录条目映射到一个子页面 slug。
用户、团队、API 密钥、工作流、密钥
incidentio users list --query email=<email>
incidentio users show --id <id>
incidentio teams list
incidentio api-keys list
incidentio api-keys rotate --id <id>
# api-keys create/update accept optional `comments` string
# Workflows (public Bearer CRUD)
incidentio workflows list
incidentio workflows show --id <id>
incidentio workflows create --body-json '{...}' # public shape — see OpenAPI
incidentio workflows update --id <id> --body-json '{...}'
# Secrets store (public Bearer — prefer this for scripting)
# Create: {name, value, description?, owning_team_ids?}
# Rotate: {value} — bumps version; value never returned (only last_four_chars)
incidentio secrets list [--query team_ids=<id>]
incidentio secrets show --id <id> # includes versions[] history
incidentio secrets create --body-json '{"name":"pagerduty_token","value":"..."}'
incidentio secrets rotate --id <id> --body-json '{"value":"new-secret"}'
incidentio secrets update --id <id> --body-json '{"name":"pagerduty_token"}'
incidentio secrets delete --id <id>
日常维护
incidentio utilities identity # validate the key + show the identity
incidentio maintenancewindows list
incidentio ipallowlists show
incidentio telemetry update --id <id> --body-json '{...}'
Dashboard / 内部 API(🍪 — 需要浏览器会话)
这些命令会访问 app.incident.io/api/*,该接口拒绝 API 密钥(“Cannot use API keys to
authenticate to internal APIs”)。它们会重放已登录的浏览器会话。请先导入一个会话:
# devtools → Network → right-click any /api/ request → Copy as cURL
incidentio auth import '<paste curl>' # or: pbpaste | incidentio auth import
incidentio auth set-org 01G9XY4BZ7YGBPJ3K50NB30YXS # x-incident-organisation-id (auto-captured from the curl if present)
然后,list 中标记为 🍪 的命令即可使用。以下是一些亮点——公共 API 无法实现的功能:
incidentio saved-views --query context=incidents # saved filter views
incidentio insights trends --query start_date=2026-06-01 --query end_date=2026-06-30
incidentio insights custom-dashboards
incidentio policies # policy list
incidentio policies update --id <id> --body-json '{...}' # flip run_on_private_incidents etc.
incidentio secrets list-internal # cookie twin of public secrets.*
incidentio workflows triggers # alert.updated|attached, scheduled, ...
incidentio workflows show-internal --id <id> # expands webhook.send signing params
incidentio workflows create-internal --body-json '{
"trigger":"alert.updated",
"workflow":{"name":"...","once_for":["alert"],"condition_groups":[],"steps":[],"expressions":[],
"runs_on_incident_modes":["standard"],"continue_on_step_error":false,
"runs_on_incidents":"newly_created","state":"draft","private_incident_scope":"none"}}'
incidentio policy-violations
incidentio incident-timelines timeline --incident-timeline <id> # full timeline
incidentio incident-timelines activity-log --incident-timeline <id> # activity log
incidentio debriefs incident-debriefs --query incident_id=<id>
incidentio incident-suggestions for-incident --query incident_id=<id> # AI suggestions
incidentio postmortems templates --query incident_id=<id>
incidentio schedule-reports
incidentio user-preferences
incidentio identity self # who am I + scopes (dashboard identity)
🍪 命令返回 401 "No authorization material",表示会话 Cookie 未被识别(错误或已过期)——请重新导入一份最新的 Copy-as-CURL。组织 ID 的解析顺序为 --org → $INCIDENT_ORG_ID → 已存储的值。
原始请求和新端点的逆向工程
并非每个端点都已编入代码。incidentio raw <METHOD> </path> 使用已存储的凭据访问任意端点,是探测和逆向工程内部路由的快捷方式:
incidentio raw GET /api/status_pages # cookie inferred (/api/*)
incidentio raw GET /v2/incidents --query page_size=1 # bearer inferred (else)
incidentio raw POST /api/status_pages --body-json '{}' # probe: 422 names required fields
incidentio raw PUT /api/settings/self --body-json '{...}' # tune a setting
incidentio raw DELETE /api/status_pages/<id> --auth cookie
身份验证方式会自动推断(/api/* → Cookie,否则使用 bearer);可通过 --auth cookie|bearer 覆盖。可直接在路径中内联任意 ID(raw 不会替换 :param)。
将新端点编入代码(步骤):
- 使用空请求体或部分请求体进行探测:
incidentio raw POST /api/<thing> --body-json '{}'。 - 阅读
422 validation_error——source.field/ 消息会指出必填字段;使用故意无效的枚举值重试,以了解允许的值。 - 在
src/commands/manual-internal.ts中添加一个Command(加载时会合并该文件中的命令,且 HAR 重新生成后仍会保留),然后运行bun run build。
操作指南
验证 API 密钥
incidentio utilities identity | jq '.identity'
按最新顺序列出未关闭的事件
incidentio incidents list --query 'status_category[one_of]=live' \
| jq '.incidents[] | {id, name, severity: .severity.name, status: .incident_status.name}'
分页浏览列表(游标分页)
list 响应包含 pagination_meta.after 游标;将其作为 --query after=<cursor> 传回:
incidentio incidents list --query page_size=250 > first.json
AFTER=$(jq -r '.pagination_meta.after // empty' first.json)
[ -n "$AFTER" ] && incidentio incidents list --query page_size=250 --query "after=$AFTER" > second.json
声明事件
incidentio incidents create --body-json '{
"name": "API 5xx spike",
"severity_id": "<sev-id>",
"summary": "Elevated 5xx from the edge.",
"visibility": "public"
}' | jq '.incident.id'
需要先获取严重性 / 状态 ID?请运行 incidentio severities list / incidentio incident-statuses list。
资源支持哪些动词?
incidentio list schedules # shows list/create/show/update/delete + nested schedule-entries/overrides/replicas
incidentio list catalog-entries # shows create/create-entry (🍪)/update/update-entry (🍪)/...
创建带有组件关系的目录条目(🍪)
# 1. Get the catalog type's attribute IDs
incidentio catalog-types show --id <type-id> | jq '.catalog_type.schema.attributes[] | {id, name}'
# 2. Create an entry with attribute values
incidentio catalog-entries create-entry --body-json '{
"catalog_type_id":"<type-id>",
"name":"payments-service",
"external_id":"payments-service",
"attribute_values":{
"<team-attr-id>":{"array_value":["<team-catalog-entry-id>"]},
"<tier-attr-id>":{"value":"tier-1"}
}}'
更新告警路由以绑定自定义字段(🍪)
# 1. GET current route — capture version and escalation_targets (you'll need to strip `users`)
VERSION=$(incidentio alert-routes show-route --id <route-id> | jq '.version')
# 2. PUT with version+1. Two critical rules:
# a) version = $VERSION + 1 (optimistic concurrency)
# b) omit `users` from every escalation_config.escalation_targets entry
# (the GET payload has an invalid users binding the PUT rejects; API restores it after PUT)
incidentio alert-routes update-route --id <route-id> --body-json '{
"version":'$((VERSION+1))',
"name":"My Route",
"escalation_config":{"escalation_targets":[
{"type":"schedule","id":"<sched-id>"}
]},
"incident_template":{
"custom_fields":[{
"custom_field_id":"<field-id>",
"merge_strategy":"first-wins",
"binding":{"array_value":[{"reference":"","value":"<option-id>","label":"P1 - Critical","sort_key":0}]}
}]
}}'
通过目录导航表达式,从告警 Service 派生受影响的组件(🍪)
导航表达式可让告警路由通过目录关系(例如 Components),从告警属性(例如 Service)导航,从而自动填充目录关联的自定义字段。
# 1. Find the IDs you need:
# - service-alert-attr-id: the alert source attribute ID for the Service field
# - component-type-id: catalog type ID for Components (incidentio catalog-types list)
# - affected-components-field-id: the incident custom field ID (incidentio custom-fields list)
VERSION=$(incidentio alert-routes show-route --id <route-id> | jq '.version')
# 2. PUT the route with an expression + expression-reference binding.
# Same rules: version+1, omit users from escalation_targets.
incidentio alert-routes update-route-expr --id <route-id> --body-json '{
"version":'$((VERSION+1))',
"escalation_config":{"escalation_targets":[{"type":"schedule","id":"<sched-id>"}]},
"expressions":[{
"id":"<expr-id>",
"label":"Affected Components",
"reference":"affected_components",
"returns":{"type":"CatalogEntry[\"<component-type-id>\"]","array":true},
"root_reference":"alert.attributes.<service-alert-attr-id>",
"operations":[{
"operation_type":"navigate",
"returns":{"type":"CatalogEntry[\"<component-type-id>\"]","array":true},
"navigate":{"reference":"catalog_attribute[\"components\"]","reference_label":"Components"}
}]
}],
"incident_template":{
"custom_fields":[{
"custom_field_id":"<affected-components-field-id>",
"merge_strategy":"first-wins",
"binding":{"array_value":[{"reference":"expressions[\"affected_components\"]"}]}
}]
}}'
# After a successful PUT the API echoes the expressions array back intact.
注意:
root_reference指向存有 Service 目录条目的告警来源属性。operations[0].navigate.reference是 Service 类型上存有其组件条目的目录属性名称(可通过incidentio catalog-types show --id <service-type-id>验证)。- 表达式的
reference值会成为expressions["<reference>"]绑定中的键。 - Affected Components 自定义字段必须是通过
custom-fields create-catalog-backed(Dashboard 内部 API)创建的目录关联multi_select,并以 Component 目录类型为目标。
密钥、签名 Webhook、由告警触发的工作流
# List triggers (🍪) — includes alert.updated, alert.attached, scheduled
incidentio workflows triggers | jq '.triggers[] | select(.name|test("alert|scheduled"))'
# Create an alert-triggered workflow (🍪). NOTE the split body: top-level `trigger`
# string + nested `workflow` object. Public `workflows create` uses a flatter shape.
incidentio workflows create-internal --body-json '{
"trigger":"alert.updated",
"workflow":{
"name":"Alert resolved webhook",
"once_for":["alert"],
"condition_groups":[],
"steps":[{
"id":"step1",
"name":"webhook.send",
"param_bindings":[
{"value":{"literal":"https://example.com/hook"}},
{"value":{"literal":"POST"}},
{"array_value":[{"literal":"Authorization: Bearer {{secrets.my_token}}"}]},
{"value":{"literal":"{\"ok\":true}"}},
{"value":{"literal":"<secret-id>"}},
{"value":{"literal":""}},
{"value":{"literal":"X-Signature"}}
]
}],
"expressions":[],
"runs_on_incident_modes":["standard"],
"continue_on_step_error":false,
"runs_on_incidents":"newly_created",
"state":"draft",
"private_incident_scope":"none"
}}'
# webhook.send param order (from show-internal): endpoint, method, headers
# (TemplatedText plain_single_line_with_secrets), body, signing_secret (type Secret),
# generated_signing_secret, signature_header_name (HMAC-SHA256).
# Prefer public `secrets create` for the signing secret when you have a Bearer key.
将策略设为允许私人事件(🍪)
# GET first — subjects/operations come back as expanded objects
incidentio policies | jq '.policies[] | {id,name,run_on_private_incidents}'
# PUT write shape differs: subject/operation are bare strings; follow_up needs due_date_config
incidentio policies update --id <id> --body-json '{
"enabled":true,
"name":"...",
"description":"...",
"policy_type":"follow_up",
"conditions":[{"conditions":[{"subject":"incident.severity","operation":"gte",
"param_bindings":[{"value":{"literal":"<sev-id>"}}]}]}],
"requirements":{"conditions":[{"conditions":[{"subject":"follow_up.status","operation":"not_one_of",
"param_bindings":[{"array_value":[{"literal":"outstanding"}]}]}]}]},
"run_on_private_incidents":true,
"due_date_config":{"incident_timestamp_id":"<ts-id>","days":{"value":{"literal":"30"}},
"calculation_type":"seven_days"}
}'
重新生成命令目录
命令位于 src/commands/generated.ts,由 incident.io 按标签划分的 OpenAPI 规范生成(实时从 docs.incident.io 获取):
bun run codegen
生成器会从 docs.incident.io/llms.txt 中发现 REST 标签集,获取每个 /openapi/tags/<tag>.json,为每个操作生成 <resource> <verb> 名称,并解决名称冲突(例如 catalog-types update-type 与 update-type-schema;heartbeat ping 与 ping-post)。重新生成后,运行构建(bun run build)。
通过 bun run codegen:har <a.har> [b.har ...],从捕获的浏览器 HAR 文件生成仪表板/内部命令。它会收集 GET 和写入端点(POST→create、PUT/PATCH→update、DELETE→delete),将 ULID/Slack ID 替换为 :param,剔除公共 Bearer API 已涵盖的端点,并覆盖 generated-internal.ts——因此,请在一次调用中传入所有想要纳入的 HAR 文件(例如 app.incident.io.har app.incident.io2.har app.incident.io3.har)。未出现在任何 HAR 中、经人工核验的内部端点(例如状态页的 create/update/components/structures)位于 src/commands/manual-internal.ts,并在加载时合并,因此重新生成不会影响它们。
常见问题
not authenticated
未通过标志、环境变量或存储找到密钥。运行 incidentio auth set <key> 或 export INCIDENT_API_KEY=<key>。
HTTP 401 / HTTP 403(公共/Bearer 命令)
密钥无效/已过期,或缺少端点所需的权限范围(例如,只读密钥调用写入动词)。在 Settings → API keys 中检查密钥的权限范围;权限范围在创建时固定——如需更多权限,请轮换密钥或创建新密钥。
needs a browser session / 401 "No authorization material"(🍪 仪表板命令)
仪表板命令(app.incident.io/api/*)不接受 API 密钥。它们需要已登录的浏览器会话:通过 incidentio auth import <curl> 重新导入(在 app.incident.io 中使用 Copy-as-cURL),并确保已设置组织 ID(使用 auth set-org 或 --org)。Chrome/Brave 导出的 HAR 通常会去掉 Cookie——请使用 Copy-as-cURL。
HTTP 422,并显示验证消息
请求体/查询参数格式错误(缺少必填字段、枚举值无效或类型错误)。错误正文会指出有问题的 source.field——请修正 --body-json/--query/--set 的值。
HTTP 429
触发速率限制(默认每个密钥每分钟 1200 个请求)。错误正文包含 rate_limit.retry_after。请稍后重试,不要持续发送请求。
unknown command
命令格式为 <resource> <verb>。运行 incidentio list <resource> 查看确切的动词。如果只输入资源,CLI 会提示其动词。CRUD 动词会合并显示(incidents list/create/show/update/delete);非 CRUD 操作保留其名称(incidents edit、escalations cancel-escalation、catalog-entries bulk-update-entries)。
缺少端点
该端点不在生成的目录中。重新运行 bun run codegen 以纳入新发布的 incident.io 端点,然后重新构建。