CircleCI のジョブログを取得する Rust製CLI ツール circleci-logs を作りました

tl;dr

  • CircleCI のジョブログ・ワークフロー情報・テスト結果をコマンドラインから取得できる Rust 製 CLI ツールを作りました
  • ジョブ番号や CircleCI の URL を渡すだけでログが取れます
  • Claude Code のスキルとして登録すると CI 失敗の調査を雑に頼めます
  • crates.io に公開済み、MIT ライセンス

https://crates.io/crates/circleci-logs

github.com

背景

諸事情でCircleCIがCIとして使われているレポジトリを使うことになりました。 で、結構CIが失敗してて、ログを見ながら調整するみたいなことが必要になったのでした。

意外なことにCircleCI CLIにもログを見る機能がなかったりします。 CircleCI CLIはローカル環境で動作確認などを行うためのものだし、JSON返すAPIはあるのでそっちを使えってことなんだとは思うのですが。実際CircleCI MCPはあって、こちらはログが取れる模様。

とはいえ、Webの画面で細かいログ見たくないし、JSONだと見づらいし、Bearer tokenと長いURL使ってcurl叩くのもなんか面倒だし…、みたいな感じ。

ひとまずcircleci-logsというnpmがあったのでそれを使っていたのですが、Claude Codeがいろいろ再試行したりするしちょっと微妙に気持ちではありました(実用はできたので直近の問題は解決しましたが)。

ので、もうちょっとぼくが使いやすいやつを作ってみました。

なにこれ

circleci-logs は、ジョブ番号やワークフロー UUID を渡すだけでログが取れる CLI ツールです。CircleCI の URL をそのまま貼り付けてもいけます。

前提として、CircleCIの実行ログはこんな感じの構造です。

Pipeline (123001)         1回のgit pushや定期実行で起動される単位
 └─ Workflow (uuid)    ジョブの実行順序・依存関係を定義
     └─ Job (456003)      個々の実行環境で動くステップの集まり
         └─ Step       実際のコマンド実行。ログはここに残る

それぞれを、ID(Number)を指定するだけで取得できます。

できること

  • 3階層対応: パイプライン → ワークフロー → ジョブ のドリルダウン
  • ログフィルタ: --errors-only で失敗ステップだけ、--grep で正規表現フィルタ
  • テスト結果: --tests で store_test_results のテスト結果を取得、--failed-only で失敗分のみ
  • JSON出力: --json で機械処理しやすい形式に
  • 対話モード: -i で TUI のドリルダウン。番号や UUID を調べなくても選ぶだけでログにたどり着けます
  • URL直接入力: CircleCI の Web UI の URL をそのまま引数に渡せます
  • プロジェクト自動検出: git remote から GitHub/Bitbucket のプロジェクトを自動判定

できないこと

  • ログのストリーミング取得: tail -f みたいなことはできません
  • 実行中のジョブのログの参照: 今は実行済みのジョブしか取得できません
    • 現状 v1.1 の output_url はジョブ完了後にしか生成されないので、実行中のジョブのログが見れません。後述の非公開 APIを使用すると上記2件に対応できるんだけど、今はやってません。

事前準備

CircleCI の API トークンは https://app.circleci.com/settings/user/tokens から発行できます。名前をつけて「Create New Token」するだけです。取得したトークンは export CIRCLE_TOKEN="xxx" で環境変数にセットしておけば、circleci-logs がそのまま使います。

つかいかた

詳しくは、--helpとかREADME.ja.mdを読んでください。

# ジョブログを取得
circleci-logs -j 4301

# ジョブログを取得(失敗ステップのみ)
circleci-logs -j 4504 --errors-only

# CircleCI の URL をそのまま貼れる
circleci-logs "https://app.circleci.com/pipelines/github/org/repo/123/workflows/UUID/jobs/456" --errors-only

# ワークフローのジョブ一覧
circleci-logs -w UUID

# パイプラインのワークフロー一覧
circleci-logs -p 142

git リポジトリ内で実行すれば remote URL からプロジェクトを自動検出するので、設定ファイルなしで使えます。 認証に必要となる CIRCLE_TOKEN 環境変数に設定したり、tomlファイルに書いたりできます。 なので、IDを引数に実行するだけ。 あと、コーディングエージェント向けにJSONで取得することもできます(出力や実行ログにトークンが記録されません)。

対話モード

circleci-logs -i で起動すると、パイプライン → ワークフロー → ジョブ → ノード → ステップ → ログ を TUI で階層的にたどれます。CircleCI の Web UI と同じ階層構造で、並列ジョブのノード選択にも対応しています。

? Select a job
  .. (back to workflows)
  #5678     rspec                success      2025-03-08 14:32:10
  #5679     lint                 success      2025-03-08 14:32:08
> #5680     e2e                  failed       2025-03-08 14:33:01
  .. (back to workflows)

番号や UUID を調べる手間なく、選ぶだけで目的のログにたどり着けるので、わざわざWebの管理画面に移動する必要はありません。

AI エージェント連携

せっかくなのでClaude Code のスキルとして登録できるようにしてあります。--help-skill で SKILL.md を出力できるので、以下のコマンドで登録可能です。

mkdir -p ~/.claude/skills/circleci-logs && circleci-logs --help-skill > ~/.claude/skills/circleci-logs/SKILL.md

登録すると、Claude Code に「CI 落ちてるから見て」と言えば勝手にログを取ってきて分析してくれると思います。--errors-only や --json を適切に使い分けてくれるように SKILL.md を書いてあるので、コンテキストウィンドウを溢れさせることもない、はず。

ちなみに、細かい点としては「ソースファイル群からSKILL.mdをコピー」とかではなく、オプションで出力するのでシングルバイナリ単体でスキルの登録ができます。ちょっとした工夫をした気がする(npmなら不要なんだろうけど)。

「バイナリ自身が自身のドキュメントを持つ」というのは有用だと思ってて、人間がmanとか--helpとかを読んで使い方を理解する、みたいのと同じ簡易jにしたかったわけです。npm パッケージであれば npx でファイルを同梱・実行できるので別途気にする必要はないのですが、シングルバイナリの CLI でスキル登録まで完結させられるのでなかなか良いのではないかと思ってます。

インストール

cargo install circleci-logs

ビルド済みバイナリも GitHub Releases に置いてあります(Linux, macOS Intel/Apple Silicon, Windows)。

技術的なこと

  • Rust 製、MSRV 1.85(edition 2024)
  • CircleCI API v1.1(ジョブ詳細・ログ)と v2(ワークフロー・パイプライン)を使い分け
  • ログの並列取得に futures の buffer_unordered を使用
    • ステップログを並列フェッチしてレイテンシを削減
  • テスト 175 個、wiremock で API のモックテスト
    • 行カバレッジ83%(ロジック部分は96〜100%、TUI/CLI部分は60〜71%)
  • GitHub Actions で CI(fmt, clippy, audit, MSRV, test)とクロスプラットフォームリリース

CLIでCircleCIのログを見る方法についてちょっと調べた件

CircleCI の公式 CLI(circleci コマンド)は「ローカル CLI」という位置付けになっており、config のバリデーションやローカル実行が主な用途で、リモートのジョブログを取得する機能がありません。ターミナルからログを見る手段が公式には提供されていない状態です(MCP サーバはあります)。

API としても、ログ取得は v1.1 にしか存在せず、v2 API には移行されていません。 Discuss でも 2017 年頃から繰り返し要望が上がっていますが、対応される気配はなさそうです。

なお、Ruby 製の非公式 CLI(https://github.com/unhappychoice/circleci-cli)は watch コマンドで tailっぽいログストリーミングを実現しています。

ただしこれは api/private/output/raw という非公開エンドポイントに対して HTTP Rangeヘッダ付きで1秒間隔のポーリングをかける力技です。さらにビルド状態の変更通知には CircleCI 内部のPusher(WebSocket)チャンネルを使っていて、ログのポーリングと Pusher の通知を組み合わせることで擬似的なリアルタイム監視を実現しています。 どちらも非公開 APIを使っている感じですね。

なお、CircleCI の公式 MCPサーバーも、ソースを見ると同じ非公開 API (api/private/output/raw)を使ってログを取得している雰囲気です。この辺→ mcp-server-circleci/src/clients/circleci-private/jobsPrivate.ts at main · CircleCI-Public/mcp-server-circleci · GitHub

なので、 v2 APIにログ取得を入れる予定は当面なさそう。

標準的に提供してくれても良さそうなのになあ。(特に実行済みログの取得すらv2にないのが謎)

かんそう

今回も開発の大部分は Claude Code の支援で作成しました。ありがとう Claude Code。

そもそもCLIベースでログが取得できないのが謎なんですが、そういう方針なら仕方ない。 とはいえ、そのためにMCP サーバでトークン消費するのも嫌だなという感じでした。

npm 版を置き換えて自作ツールを使えるかと思うとちょっと気分がいい。

なお所要時間としては、だいたい 約5-6時間くらいで期間としては2日半くらいでした。


リンク