mcpField
I
incidentio-cli

incidentio-cli

github.com/paymogクラウド・DevOps09.2k 回インストール14 週間前に更新
リポジトリ

incidentio-cli について

incidentio-cliは、incident.ioのコマンドラインインターフェースです。JSONコマンドでインシデント、アラート、スケジュール、カタログを管理でき、公式OpenAPI仕様からコマンドを生成します。公開APIとブラウザーセッションが必要な内部APIを区別します。

主な機能

  1. 01公式OpenAPI仕様からコマンドを生成
  2. 02インシデント、アラート、エスカレーションの管理
  3. 03スケジュール、カタログ、設定リソースの照会
  4. 04Bearer APIキーによる認証
  5. 05ブラウザーセッションによる内部APIへの任意アクセス

活用シーン

  1. 01インシデントの一覧表示や作成
  2. 02アラートの解決とエスカレーション状況の確認
  3. 03スケジュールやサービスカタログ項目の管理
  4. 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 はブラウザーや Cookie を使わず、API に直接アクセスします。コマンドはincident.io の公式 OpenAPI 仕様から生成されます(リソースタグごとに 1 つ)。そのため、ドキュメントに記載されたすべてのエンドポイントを利用できます。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]

コマンドは 2 つのトークンで構成されます:<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ボディのフィールドを設定します。繰り返し指定可能
--rawJSON 整形なしで生のレスポンスを出力
--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 リソースにわたるパブリック Bearer API コマンド約 179 個、🍪 マーク付きの内部/ダッシュボードコマンド約 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 プランで作成できる公開ページは1 つです(2 つ目の create は 422 exceeded your allowance を返します)。ロゴ、ファビコン、ブランドカラーはダッシュボードからアップロードします。

カタログに基づく親ページの場合、split_by_catalog_type_id はサブページの基になるカタログタイプを、split_by_component_attribute_id はそのタイプのうちコンポーネントを指す属性を指定します。各 sub_pages エントリは、カタログエントリをサブページのスラッグに対応付けます。

ユーザー、チーム、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 '{...}'

ダッシュボード/内部 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 の置換を行いません)。

新しいエンドポイントをコード化する手順:

  1. 空または一部のみの本文で調査します:incidentio raw POST /api/<thing> --body-json '{}'。
  2. 422 validation_error を確認します。source.field/メッセージに必須フィールドが記載されています。許可される値を調べるには、意図的に無効な列挙値を指定して再試行します。
  3. 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 を実行してください。

リソースが対応する HTTP メソッドを確認する
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}]}
    }]
  }}'
カタログのナビゲーション式を使って、アラートのサービスから影響を受けるコンポーネントを導出する(🍪)

ナビゲーション式を使うと、アラートルートはアラート属性(例:サービス)からカタログの関係(例:コンポーネント)をたどり、カタログ連携のカスタムフィールドに値を自動入力できます。

# 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 は、サービスのカタログエントリを保持するアラートソース属性を指します。
  • operations[0].navigate.reference は、コンポーネントエントリを保持するサービス型のカタログ属性名です(incidentio catalog-types show --id <service-type-id> で確認してください)。
  • 式の reference 値は、expressions["<reference>"] バインディングのキーになります。
  • 「影響を受けるコンポーネント」カスタムフィールドは、コンポーネントのカタログ型を対象に custom-fields create-catalog-backed(ダッシュボード内部 API)で作成した、カタログ連携の multi_select である必要があります。
シークレット、署名付き 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)。

ダッシュボード/内部コマンドは、記録したブラウザー HAR から bun run codegen:har <a.har> [b.har ...] で生成します。GET および 書き込みエンドポイント(POST→create、PUT/PATCH→update、 DELETE→delete)を抽出し、ULID/Slack ID を :param にテンプレート化し、公開 Bearer API ですでに 対応しているものを除外して、generated-internal.ts を上書きします。そのため、反映させたい HAR をすべて1回の実行で渡してください(例:app.incident.io.har app.incident.io2.har app.incident.io3.har)。 HAR に含まれない、手動で検証済みの内部エンドポイント(例:ステータスページの作成/更新/コンポーネント/構造)は、 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)。

エンドポイントが見つからない

そのエンドポイントは生成済みカタログにありません。新たに公開された incident.io のエンドポイントを取り込むには、bun run codegen を再実行してから、再ビルドしてください。

コメント