add-command について
Coralogix の `cx` CLI にコマンドを追加する開発スキルです。方式の選定から実装、テスト、検証までの手順を案内します。
主な機能
- 01DataPrime または REST 方式の選択
- 02API とコマンドモジュールの追加
- 03CLI へのコマンド登録
- 04単体・統合・E2E テスト
- 05ビルド・Lint・フォーマット確認
活用シーン
- 01ログやスパンのクエリコマンド追加
- 02Coralogix REST API のラップ
- 03CLI のコマンドグループ拡張
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ coralogix/ cx-cli --skill add-commandインストール後、Claude Code で/add-commandを入力して読み込まれたか確認します。
詳細
CLI コマンドの追加
cx に新しいコマンドを追加するためのエンドツーエンドのワークフローです。すべてのコマンドは、2 つのアーキタイプのいずれかに該当します。まずどちらに該当するかを判断してから、対応する手順に従ってください。
docs/adding-a-command.md には、以下の各手順で使えるコピー&ペースト可能なコードテンプレートがあります。このワークフローと併せてお読みください。
ステップ 0:作成するものを把握する
コードを書く前に、対象となるドメインを明確にします。
- どの Coralogix API をラップしますか? API ドキュメントやレスポンスの例を探します。データモデルを把握し、どのようなエンティティがあり、それぞれにどのフィールドがあり、どのような操作がサポートされているかを確認します。
- ユーザーが何をできるようにするべきですか? サブコマンド(例:
list、get、create)と、適切なフラグを列挙します。 - ラッパーグループの配下に置くべきですか? CLI では、関連するコマンドをラッパーグループにまとめています。トップレベルコマンドを作成する前に、既存のグループにコマンドを追加できるか確認してください。
cx alerts- アラート定義とschedulerscx notifications-connectors、routers、presets、testcx webhooks- 送信 Webhook とactionscx enrichments- エンリッチメントルールとcustomエンリッチメントテーブルcx integrations- インテグレーションとextensions、contextual-datacx iam-api-keys、roles、scopes、users、groups、ip-accesscx schemaを実行すると、コマンドツリー全体を JSON 形式で確認できます。
- どのアーキタイプが適していますか?
| アーキタイプ | 用途 | 参照実装 |
|---|---|---|
| A:DataPrime ベース | ログ、スパン、または任意の DataPrime ソースをクエリする場合 | src/commands/logs/mod.rs |
| B:REST ベース | Coralogix REST API をラップする場合(新しいコマンドの大半はこちら) | src/commands/alerts/api.rs + src/commands/alerts/mod.rs |
DataPrime コマンドは共有パイプラインに処理を委譲するため、必要なコードは最小限(約 130 行)です。REST コマンドでは、API クライアント、ファンアウト、マージ、レンダリングからなる完全なパイプラインを構築します。コード量は増えますが、より細かく制御できます。
重要: すべての API 連携では REST(HTTP)を使用する必要があります。CLI は設計上 HTTP のみをサポートしているため、gRPC は使用しないでください。
ステップ 1:参照実装を読む
コードを書く前に、既存のパターンを把握するため、以下のファイルを読んでください。このステップは非常に重要です。既存コードを先に読むエージェントは新しいパターンを独自に作り出すのではなく、コードベースに一貫した実装を作成できます。
必ず読むファイル:
src/main.rs-Commandsenum を調べてバリアントの構造を確認し、match cli.commandのディスパッチブロックを見て、新しいバリアントをどこに追加するか確認します。早期終了するコマンド(認証情報が不要)と、完全な設定解決フローを通るコマンドを確認してください。ラッパーグループ(例:Notifications、Iam、Webhooks、Integrations)にも注意してください。これらは、関連するドメインをまとめるため、ネストされたサブコマンド enum を持つトップレベルコマンドです。コマンドが既存のグループに属する場合は、トップレベルコマンドを作成するのではなく、そのグループのサブコマンド enum に新しいバリアントを追加します。src/commands/mod.rs- 既存のモジュール登録を確認し、適切な場所に新しいモジュールを追加します。docs/adding-a-command.md- 両方のアーキタイプのコードテンプレートを含む完全なガイドです。
DataPrime アーキタイプの場合は、以下も読む:
src/commands/logs/mod.rs- 完全な DataPrime コマンドです。共有パイプラインが大部分の処理を担うため、必要なコードがいかに少ないかに注目してください。src/commands/dataprime/mod.rs- コマンドが処理を委譲する共有パイプラインです。run_query()のシグネチャと、その処理内容(ファンアウト、マージ、スピリング、エージェント出力)を確認してください。
REST アーキタイプの場合は、以下も読む:
src/commands/alerts/api.rs- レスポンス型の構成、API 構造体が&CxClientを借用する方法、デシリアライズテストの書き方を確認してください。src/commands/alerts/mod.rs- ハンドラーでpub mod api;を宣言する方法と、use api::{...};で型をインポートする方法を確認してください。src/commands/dashboards/mod.rs-render::*ヘルパーを使ったファンアウト/マージ/レンダリングのパターンと、3 つすべての出力形式への対応方法を確認してください。
ステップ 2:API レイヤーを作成する(REST のみ)
DataPrime コマンドではこのステップをスキップしてください。共有の DataPrime パイプラインを使用します。
src/commands/<domain>/api.rs を作成します。完全なテンプレートについては、docs/adding-a-command.md の「Archetype B, Step 1」を参照してください。
主な規約とその理由:
- レスポンス型に
#[serde(rename_all = "camelCase")]を指定する — Coralogix API は camelCase の JSON キーを使用します Vecフィールドに#[serde(default)]を指定する — API は空の配列を[]として送信せず、省略することがあります。これによりデシリアライズの失敗を防げます- 存在しない可能性のあるフィールドには
Option<T>を使用する — API は変更され、フィールドはプランによって異なるため、予防的に対応します - API 構造体は
&CxClientを借用する(所有しない)— クライアントはファンアウト全体で共有され、個々の API 呼び出しより長く存続する必要があります - エンドポイントのプレフィックスには
const BASE_PATHを使用する — URL の重複を避けられます - デシリアライズテストは必須です — 本番環境で問題になるケースなので、正常系とエッジケース(空のリスト、省略可能なフィールドの欠落)の両方をテストします
ステップ 3:コマンドモジュールを作成する
src/commands/<domain>/mod.rs を作成します。REST コマンドでは、先頭に pub mod api; を宣言して、ハンドラーから兄弟ファイルの api.rs にある型を use api::{...}; で使用できるようにします。両方のアーキタイプの完全なテンプレートについては、docs/adding-a-command.md を参照してください。
DataPrime アーキタイプ
次の 2 つを用意します。
- テキストレンダラー:
pub fn render_<domain>_text(merged: &MergedResults) -> Result<()>—OutputFormat::Textの場合のみ呼び出されます。JSON と Agents の出力は共有パイプラインで処理されます - 薄い
run()ラッパー:DataPrime のソース名を指定してsuper::dataprime::run_query()を呼び出します
REST アーキタイプ
ファンアウト/マージ/レンダリングのパイプライン全体を構築します。理解しておくべき主なパターン:
- テキスト出力には
render::render_tableを使用する — 列ヘッダー(「Profile」を除く)と、最初の要素がプロファイル名である行を渡します。このヘルパーはinclude_profileに応じて Profile 列を含めます。構造体を重複して定義する必要はありません - JSON 出力には
render::render_jsonを使用する —&[Value]配列を整形して出力します let include_profile = targets.len() > 1;— この 1 つのブール値で、プロファイルが複数ある場合のすべての動作(テキストの Profile 列、JSON の"profile"キー)を制御します- ファンアウトのエラーは致命的ではありません — 標準エラー出力に表示して続行します。設定に問題のあるプロファイルが 1 つあっても、ほかのプロファイルの結果を妨げないためです
- ステータスメッセージは標準エラー出力(
eprintln!)に送ります — パイプ出力にデータ以外が混ざらないよう、標準出力はデータ用に確保します - Agents 出力はコマンド側で処理します — コマンドによってエンコード前のデータ変換が異なるため、後処理の後に各コマンドから直接
toon_encodeを呼び出します
src/commands/mod.rs にモジュールを登録します。
ステップ 4:CLI に接続する
src/main.rs に 3 つ追加します。テンプレートについては、docs/adding-a-command.md の「CLI Wiring」を参照してください。
Commandsenum のバリアント — DataPrime コマンドではインライン引数を使用し、REST コマンドではサブコマンドの enum を参照します- サブコマンドの enum(REST のみ)—
List、Getなどを定義します - ディスパッチの match アーム —
match cli.commandブロック内に追加します。ほとんどのコマンドは設定解決の全フローを通ります。認証情報が不要なコマンド(profiles、cleanupなど)のみ早期終了します
ステップ 5:テストを追加する
新しいコマンドを追加する場合は、3 つのレイヤーすべてにテストを追加する必要があります。それぞれのコードテンプレートと例については、
docs/adding-a-command.md § 「Testing」を参照してください。
| レイヤー | 場所 | 検証内容 |
|---|---|---|
| ユニット | src/**/<file>.rs #[cfg(test)] | 純粋なロジック:デシリアライズ(REST の場合は必須)、ヘルパー、変換 |
| インテグレーション | tests/<command>/main.rs(wiremock) | HTTP をモックしたコマンドランナーのエンドツーエンドテスト |
| E2E | tests/e2e/<command>/mod.rs(assert_cmd、#[ignore] 付き) | Coralogix のテストチームに対する実際の cx バイナリのテスト |
ドキュメントで強調されていない、このワークフロー固有の注意点:
- 変更を伴うコマンド(create/delete/enable/disable)には E2E テストを追加しないでください。対応する取り消し手順がある場合を除きます。共有のテストチームの状態に影響するためです。
tests/e2e/alerts/mod.rsのように、コメントで意図的にテスト対象外としていることを明記してください。 - サブコマンドでテストチームの ID が必要な場合(例:
get <id>)は、tests/e2e/alerts/mod.rsのdiscover_alert_idを参考にして、E2E テストモジュールにローカルのdiscover_*関数を追加してください。OnceLockを使ってキャッシュし、テストチームにデータがない場合はパニックせずにスキップしてください。 #[path = "e2e/your_domain/mod.rs"] mod your_domain;を使って、tests/e2e.rsで新しい E2E モジュールを宣言するのを忘れないでください。
ステップ 6:ユーザー向けスキルを作成する
すべてのコマンドには、AI エージェントが使い方を理解できるように、skills/ に対応するスキルが必要です。add-skill ワークフローを使って作成してください。参照実装の確認、効果的なトリガー説明の作成、検証を含む全工程を案内します。
ステップ 7:検証する
cargo build、cargo test(ユニットテスト+インテグレーションテスト)、cargo clippy、
cargo fmt --check を実行してください。コミットする前に、問題をすべて修正してください。
テストチームの認証情報を設定している場合は、E2E テストスイートも実行してください:
cargo test --test e2e -- --ignored --test-threads=1
3 つすべての出力形式(text、json、agents)と、
複数のプロファイル(-p profile1 -p profile2)でスモークテストを実行してください。
PR の説明に記載するチェックリスト全体については、docs/adding-a-command.md § 「PR Checklist」を参照してください。