TECH PLAY

GraphQL

イベント

該当するコンテンツが見つかりませんでした

マガジン

該当するコンテンツが見つかりませんでした

技術ブログ

はじめに こんにちは、Insight Edge の日下です。 ここ最近のコーディングAIエージェントの進化は目覚ましく、以下のような光景が当たり前になってきました。 プロダクトオーナーやUXデザイナがAIツールでプロトタイプを作る 議事録・仕様書・設計メモといったドキュメント系の成果物もAIで作成しgitで管理する 特にバイブコーディングの広がりで、エンジニア以外もソースコードの形で成果物を作ることが増えました。弊社では AIが文脈を理解しやすいように、プロダクトのソースコードだけでなくデザイン成果物や設計ドキュメント、意思決定の経緯などもGitやGitHubに集約しています 。こうしてソースコードとドキュメントの両面から、 Gitリポジトリを触るエンジニア以外のメンバー が増えてきています。 このとき、従来からGit/GitHubを使うエンジニア側と、新たに使い始めた側のそれぞれに悩みが生まれます。 エンジニア側 — 開発フローの説明や救援作業(作業支援、誤コミットの修正)など、エンジニア以外のメンバーが慣れるまでサポート負荷が高くなる 開発に参加するメンバー側 — Git/GitHubの作法や開発フローを学ぶ負担と、それを意識することによるアイデア具現化スピードの鈍化 「AIに任せればベストプラクティスが守られるのでは?」と思いきや、そうでもありません。最近のAIモデルはGitやGitHubの良い作法を知っていますし、インターネットを探せば素晴らしいスキルも多々あります。しかし、開発するプロダクトの特徴やフェーズ、チームの大きさなどに応じて、現場に適した開発フローは様々であり、そこに開発チームの工夫が表れます。だからこそ、 自分のチームに適した開発手順を言語化してスキルに固める 必要がありました。 本記事では、エンジニア以外のメンバーも含む開発チームで、バイブコーディングの速さや気軽さも尊重しつつ、GitやGitHubをお行儀よく活用した開発フローを実現するために私が作り育てたClaudeスキルを題材に、その設計思想と中身、実際の使い勝手を ニールセンのユーザビリティ10原則 に照らし合わせて紹介します。 ※本記事は Claude Code の Skill 機能 を前提としています。また、 /d の動作には git コマンドと GitHub CLI ( gh コマンド)がセットアップ済みであることが必要です。 目次 はじめに 設計の3本柱 /d スキルの構造 動かしてみる:2つの典型シナリオ スキル改善の経緯と考え方 おわりに 設計の3本柱 /d の d は develop からとっています。 このスキルの設計には3つの軸があります。共通するのは、 作業者が意識して開発フローに合わせるのではなく、スキルを使っているだけで自然にルールを守れる という発想です。 A. バイブコーディングの手を止めない アイデアを高速に具現化する人の手を、複雑な開発プロセスで遅くしない。 お行儀のためのチェックリストや規約を増やすほど、利用者は「考える前に手順を思い出す」モードに入ります。これは思いつきを高速に形にするUXデザイナやプロダクトオーナーには致命的です。 /d スキルは 思考のリズムを止めない ことを最優先にします。 具体的には、手順を覚えてもらうのではなく スキル側がすべて代行する 設計にしました。たとえば、利用者が /d issue 42 と打つことでIssueに着手するときの定型作業を実行し、作業ブランチ作成・push・方針コメント投稿まで自動で走ります。 B. 使いながらGit/GitHubの作法に慣れる 細かい作法を習ってから使うのではなく、使いながら徐々に作法を体得する。 ブランチ・コミット・PR・rebase…とGitの概念を最初に全部説明されると、それだけで利用者は挫折します。一方で「教えなくていい」とすると、利用者はずっと作法を知らないまま、エンジニアの救援が必要な状態が続きます。 /d スキルは 「必要最低限のコマンドを使うだけで、結果としてお行儀よく作業できていた」 状態を作りつつ、 裏で何が起こったかは可視化する 設計にしました。 /d issue 実行時に「ブランチを作りました」「PRを作成しました」とログが出るので、利用者は使い続けるうちに「これはブランチを切っていたのか」「これがDraft PRか」と自然に理解していきます。また、issueやcommitなど重要な用語はGit/GitHubのエコシステムに合わせることで、エンジニアと同じ言語で開発に参加できるようにしています。 C. 覚えなければならない知識を減らす 使う側が頭の中に抱える「知識量」をできる限り減らす。 利用者の負担は 「次に何のコマンドを打つか」「どのスキルを呼ぶか」を毎回思い出すこと にあります。これを減らすために2つの仕掛けを入れました。 個別スキルではなくサブコマンド方式 — /d todo /d issue /d commit …といった操作を /d 1つのスキルに統合することで、利用者は最低限 /d だけ覚えればよく、 /d 42番のIssueに着手 のように自然言語で意図を伝えるだけでも適切なサブコマンドが実行されます 次のアクションは選択肢で提示 — スキル実行の終わりには必ず次の候補を出すことで、利用者は「次に何をすればよかったっけ」と考えずに済みます(後述する「再生より再認」) 結果として、利用者が頭に抱える「Git作法 + コマンド体系 + チーム運用ルール」の知識セットが大幅に圧縮されます。 覚えるべきは /d という入口だけ という状態が、参加ハードルを最小化します。 /d スキルの構造 スキル本体は ~/.claude/skills/d/SKILL.md 1ファイルです。フロントマター + サブコマンドごとの手順記述で構成されます。全文は以下に折りたたんで載せておきます。 SKILL.md 全文(クリックで展開) --- name: d description: GitHub Issue・Pull Request・ブランチ操作・コミット等の作法を定義した開発ワークフロースキル argument-hint: " < todo |new|issue|commit|pr|review|improve|help> [args...]" allowed-tools: Bash, Agent, Read --- GitHub を起点とした開発ワークフローをサブコマンドを指定して実行する。引数なしで ` /d ` と実行された場合は ` /d help ` として動作した上で、次の行動を提案する。 サブコマンドが指定されずに文が続く場合(例: ` /d 42番のIssueに着手して ` )は、テキスト内容から利用者の意図を解釈し、適切なサブコマンドにマッピングして実行する。利用者は厳密なサブコマンド名を覚えていなくてもよい。 ## 出力ルール ### yes/no 質問 AIによる「〜してよいですか?」「〜しますか?」のような closed questionや許可確認の末尾には ` (y/n) ` を付け、ユーザの回答負荷を軽減する。「他に修正はありますか?」のような実質的Open Questionには付けない。 ### 表・箇条書きへの識別子付与 表・箇条書き・選択肢など、複数項目が並ぶ出力には必ず連番や記号の識別子を振る。Issue番号やPR番号など既存の識別子がある場合はそれを使い、無い場合は左端に ` No ` 列を追加する。これにより、後の会話でユーザが番号で行を指定できるようにする。 ### 次のアクションの提示 サブコマンドの終わりには、可能な限り次のアクションの候補を選択肢として提示する。利用者に「次に何をすればよいか」を思い出させるのではなく、提示された選択肢から選ばせる(再生より再認)。 ## 不満・改善提案の案内 利用者が ` /d ` スキルの挙動に不満を表明した場合: ` /d improve <内容> ` でスキル改善Issueを起票する。 ## 共通ルール ### 並列実行 依存関係のない複数のコマンド・API呼び出しは常に並列実行する。逐次実行しない。独立したコマンドを見つけたら積極的に並列化する。 ### ブランチ切り替え前の確認 ` git checkout ` の前に ` git status --porcelain ` で未コミット変更を確認する。変更がある場合は選択肢を提示: 1. **コミットして続行** 2. **worktree で並列作業** — ` git worktree add ../<リポ名>-<新ブランチ> -b <新ブランチ> origin/main ` → 別セッションを案内 3. **中断** ### main 最新取り込み 作業ブランチで ` /d issue ` (既存ブランチ checkout 時)または ` /d commit ` (push 前)に実行する。originのmainブランチに対する遅れを確認し、遅れがあれば ` git merge origin/main ` を提案する。 ### ブランチ命名規則 ` CLAUDE.md ` に命名規則の定義があればそれに従う。なければデフォルトとして ` <prefix>/<issue番号>-<英語kebab-case 5語以内> ` を使用する。prefix はIssueのラベル・内容から判断: - ` feat/ ` — 新機能 - ` fix/ ` — バグ修正 - ` nf/ ` — 非機能(インフラ等) - ` doc/ ` — ドキュメント - ` process/ ` — 開発プロセス関連(CI、Claudeスキル等) - ` misc/ ` — その他 Issue 番号がない場合は ` <prefix>/<英語kebab-case 5語以内> ` とする。 ### PR マージ確認 PR が Ready かつ最新コミットに対するレビューでマージ可能と判定されている場合、 ` gh pr merge <PR番号> --merge --delete-branch ` を提案する。適用タイミング: ` /d commit ` で Ready PR 作成後、 ` /d review ` で Ready 化後、 ` /d pr ` で Ready 化後。 ### レビュー実行 レビューは **Claude のレビュー用サブエージェント** で実行する。実装したコンテキストとは別のサブエージェントで実行することで、客観的な指摘を得る。 他人の PR をレビューする場合は先に対象ブランチを取得する。 チェックアウト前に元ブランチ名を退避し、ダーティーツリーでないことを確認する: ```bash ORIG_BRANCH=$(git branch --show-current) git status --porcelain # 出力ありなら未コミット変更あり ``` 未コミット変更がある場合は「ブランチ切り替え前の確認」を適用する。クリーンな状態を確認したら既存ローカルブランチを破壊しない方法で取得する: #### レビュー手順 1. ` COMMIT_SHA=$(git rev-parse HEAD) ` で SHA を取得。 ` git fetch origin main ` 後、 ` git diff origin/main...HEAD ` + ` git log origin/main..HEAD --oneline ` を取得。 ` OWNER_REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner) ` で owner/repo も取得 2. Agent ツールでレビュー用サブエージェントを起動する( ` run_in_background: true ` )。プロジェクトの設計基準やレビューガイドライン( ` CLAUDE.md ` 、レビュー用エージェント定義、 ` docs/ ` 配下のガイドライン等があれば参照)に従ってレビューさせる。プロンプトに ` diff ` , ` commits ` , ` commit_sha ` , ` owner_repo ` , ` pr_number ` , ` pr_author ` , ` is_own_pr ` , ` is_draft ` , ` post_to_pr=false ` , ` defer_ready=true ` を渡す 3. 完了を待ち、結果を会話に表示(指摘一覧 + 総合判定) 4. 自分の PR の場合は各指摘の妥当性を評価する 5. ` post_to_pr=true ` の場合は次の「PR への投稿」を実行 #### PR への投稿 ( ` post_to_pr=true ` ) skill 側で投稿する(レビュー用サブエージェントは二重投稿回避のため ` post_to_pr=false ` ): - **総評コメント**: ` gh pr review <PR番号> --comment --body "<本文>" ` (自分の PR)/ ` --approve ` / ` --request-changes ` (他人の PR) - **インラインコメント**: ` gh api repos/{owner}/{repo}/pulls/<PR番号>/comments ` を使用。各コメントに ` commit_id ` (= ` COMMIT_SHA ` ), ` path ` , ` line ` , ` side ` が必須 投稿後、自分の Draft PR でマージ可能(高指摘なし)なら Ready 化: 1. PR タイトルから ` WIP: ` 削除 2. 本文を ` Summary / Related Issue / Test plan ` テンプレートに更新( ` Closes ` / ` Refs ` は「Related Issue とクローズ判定」に従う) 3. ` gh pr ready <番号> ` ### 変更確認 ` git status --porcelain ` 、 ` git diff ` 、 ` git diff --cached ` を3つ並列実行する。変更がなければエラー。 ### ステージング判断 以下の懸念がないか確認する: - ` .env ` 、クレデンシャル系( ` credentials.json ` 、 ` cred-* ` 、 ` *.pem ` 、 ` *.key ` 等) - ` .gitignore ` すべきファイル( ` node_modules/ ` 、 ` dist/ ` 、 ` __pycache__/ ` 、 ` .venv/ ` 等) - ブランチ名から推測される作業内容と無関係なファイル 懸念がなければ全ファイルを自動ステージング(確認不要)。懸念があれば明示してユーザーに確認する。 ### コミットメッセージ生成 変更内容から日本語で簡潔に自動生成する(確認不要)。ブランチ名に Issue 番号があれば ` #<番号> ` を含める。 ## サブコマンド ### ` /d todo ` 自分が対応すべきものを表示する。 現在作業中のタスクがあるかどうかと、GitHub上でアサインされたIssue、メンション、レビュー依頼を確認する。 1. **2つを並列実行**: - (A) gitコマンドで現在の作業状況を確認 ` git fetch origin && git branch --show-current && git status --porcelain ` - (B) ghコマンドでGitHubを確認。GraphQL で一括取得: ```bash OWNER_REPO=$(gh repo view --json nameWithOwner --jq .nameWithOwner) gh api graphql -f query="{ assignedIssues: search(query: \"repo:${OWNER_REPO} assignee:@me is:open is:issue\", type: ISSUE, first: 20) { nodes { ... on Issue { number title labels(first: 5) { nodes { name } } updatedAt } } } reviewRequested: search(query: \"repo:${OWNER_REPO} review-requested:@me is:open is:pr\", type: ISSUE, first: 20) { nodes { ... on PullRequest { number title author { login } updatedAt } } } mentions: search(query: \"repo:${OWNER_REPO} mentions:@me is:open\", type: ISSUE, first: 20) { nodes { ... on Issue { number title updatedAt } } } myOpenPRs: search(query: \"repo:${OWNER_REPO} is:open is:pr author:@me\", type: ISSUE, first: 20) { nodes { ... on PullRequest { number headRefName isDraft } } } }" ``` 2. **fetch 完了後の確認**: - 現在のブランチが main なら ` git rev-list HEAD..origin/main --count ` で同期状態を確認。作業ブランチなら ` gh pr view --json number,title,state,mergedAt,url ` で PR 状態を確認 - アサイン済み Issue について ` git branch -r ` を1回実行し、各 Issue 番号に対して ` origin/*/<issue番号>-* ` のパターンでブランチを探す → ` myOpenPRs ` から PR 有無を判定 → 未着手 / ブランチあり / PR #番号 (Draft|Ready) 3. **出力フォーマット**: ``` ## 現在のブランチ - ⚠️/✓/🔧 の状態表示 ## アサイン済み Issue | # | タイトル | 状態 | ラベル | 更新日 | ## レビュー依頼 | # | タイトル | 作成者 | 更新日 | ## メンション | # | タイトル | 更新日 | ``` 4. **次のアクション提案**: 優先度の高い順に次にやるべき作業を提案する。「main に戻りましょう」は提案しない(作業ブランチで ` /d issue ` を実行すれば自動的に origin/main ベースのブランチが作成されるため) ### ` /d new <タイトル> ` 新しい Issue を起票する(自分が取り組むとは限らない)。 1. 引数を要約してタイトルにする(なければユーザーに聞く) 2. ` gh issue list --state open --json number,title ` で既存の類似 Issue をチェック 3. 説明文の案を生成してユーザーに提示(経緯・現状・期待効果を含める) 4. ` gh label list --json name,description ` で適切なラベルを判定 5. ` gh issue create --title "..." --body "..." --label "..." ` で作成 6. URL を表示 7. **次のアクションを必ず選択肢として提示**(省略不可): 1. 自分をアサインして今から取り組む → ` /d issue ` の処理を続行 2. 自分をアサインして作業に戻る → ` gh issue edit <番号> --add-assignee "@me" ` のみ 3. 他の人をアサインする(対象者を指定) 4. アサインせず終了 ### ` /d issue <番号またはURL> ` (エイリアス: ` /d i ` ) 既存 Issue に自分が取り組む。ブランチ作成・プッシュで着手を宣言してから方針コメントを投稿する。 1. Issue 番号を特定し、内容取得 + 自分をアサイン: ```bash gh issue view <番号> --json title,body,labels,assignees gh issue edit <番号> --add-assignee "@me" ``` 2. ` git fetch origin && git branch -a --list "*/<issue番号>-*" ` で既存ブランチを確認: - **あり**: 他人のコミットがあればユーザーに確認。なければチェックアウト + 「main 最新取り込み」を実行 - **なし**: Issue からブランチ名を生成(「ブランチ命名規則」参照)。**確認不要で** 作成・push する: ```bash git checkout -b "<prefix>/<番号>-<説明>" origin/main git push -u origin HEAD ``` 3. 方針・実装計画をユーザーに提示 → 承認後 ` gh issue comment ` で投稿(投稿の確認不要) **ここがポイント**: ブランチを push してIssueコメントを残すことで、他メンバーに「自分が #<番号> に着手中」が見えるようになる。重複着手を未然に防ぐ。 ### ` /d commit ` 変更をコミット・プッシュし、PR が未作成なら Draft PR も作成する。 **ブランチ判定:** - **`main` の場合**: 変更内容から prefix を判断し、ブランチ名を生成 → ` git checkout -b "<prefix>/<説明>" ` → 次の手順へ - **作業ブランチの場合**: そのまま次の手順へ **手順:** 1. 変更確認(共通ルール) 2. ステージング判断(共通ルール) 3. ブランチ名から Issue 番号を抽出( ` feat/123-xxx ` の ` / ` の後の数字) 4. コミットメッセージ生成 → ` git add && git commit ` 5. main 最新取り込み(共通ルール) 6. ` git push -u origin HEAD ` 7. ` gh pr list --head <ブランチ> --json number,title,isDraft,url,author ` で PR 確認 8. **レビュー実行**( ` is_own_pr=true ` , ` post_to_pr=true ` ): - **PR がない場合**: ` /d pr ` に従ってDraft PR 作成 → レビュー実行 — 初回レビューは精度優先 - **PR が既存の場合**: 追加コミットの差分をレビュー 9. PR マージ確認(共通ルール) 10. 結果表示: コミットハッシュ・メッセージ、プッシュ先、PR URL、レビュー結果 ### ` /d pr ` Pull Requestを作成。または、作成済のPRに対して必要なアクションをする。 1. ブランチが ` main ` ならエラー 2. ` gh pr view --json number,title,isDraft,url ` で既存 PR 確認 3. **PR あり**: PR コメント確認 → 未対応あれば対応 4. ` git fetch origin main ` → ` git log origin/main..HEAD --oneline ` + ` git diff origin/main...HEAD --stat ` で差分取得 5. PR タイトル(70文字以内)と本文を生成( ` 概要 / 関連Issue / やったこと / やっていないこと ` 。 ` 関連Issue ` は共通ルールに従い ` Closes ` / ` Refs ` ) 6. ` git push -u origin HEAD ` → PR なしなら Draft 作成、あればタイトル・本文を更新 7. レビュー実行( ` is_own_pr=true ` , ` post_to_pr=true ` , ` effort=high ` )→ 結果表示 8. URL 表示 9. PR マージ確認(共通ルール) ### ` /d review ` 作業ブランチの変更をレビュー。PR があればレビューとして投稿可能。 1. ブランチが ` main ` ならエラー 2. ` gh pr view --json number,title,url,isDraft,author ` で PR 確認。 ` gh api user --jq .login ` と ` author.login ` を比較して ` is_own_pr ` を決定 3. レビュー実行( ` is_own_pr=<判定> ` , ` is_draft=<取得値、なければtrue> ` , ` post_to_pr=false ` , ` effort=high ` )→ 結果表示 4. **PR あり**: 投稿するか確認 → 投稿する場合は「PR への投稿」を実行( ` post_to_pr=true ` )。Draft かつマージ可能なら Ready 化が走る 5. PR マージ確認(共通ルール) ### ` /d improve <改善内容> ` ` /d ` スキル自体の改善提案を Issue 起票する。 1. 引数があればそれを改善内容にする。引数がない場合は直前の会話の文脈(不満や違和感の表明、うまくいかなかった操作など)から推測する 2. 改善内容をもとに簡潔な Issue タイトル(日本語)を生成 3. Issue を作成: ```bash gh issue create --title "<タイトル>" --body "$(cat <<'EOF' ## 改善内容 <スキル改善内容> ## 代替案 <claudeの設定など、スキル自体の改善以外で実現可能な代替案> EOF )" ``` 4. 作成した Issue の URL を表示 ### ` /d help ` 以下をそのまま出力する: ``` ## 開発プロセス ### (1) アサインされたタスクに取り組む 1. `/d` で自分のタスクを確認する 2. `/d issue <番号>` で Issue に着手する(アサイン→ブランチ作成→方針コメント) 3. 実装する 4. `/d commit` でコミット・プッシュ・PR作成 5. `/d review` でレビュー・Ready化 ### (2) 新しい課題を起票する `/d new <タイトル>` で Issue を作成する。自分で取り組むかどうかはその場で選択できる。 ### (3) Issue を立てずに実装する 1. 実装する(main ブランチ上でも `/d commit` が自動でブランチを作成する) 2. `/d commit` でコミット・プッシュ・PR作成 3. `/d review` でレビュー・Ready化 ### (4) このスキルの改善リクエスト `/d improve <不満点や改善案>` で改善提案を Issue 起票する。 ## コマンド一覧 | コマンド | 説明 | |---|---| | `/d` | `/d help` と同じ(サブコマンド省略時) | | `/d todo` | 自分のアサインタスク・メンション・レビュー依頼を一覧 | | `/d new <タイトル>` | 新規 GitHub Issue を起票 | | `/d issue <番号>` (`/d i`) | 既存 Issue に着手(アサイン→ブランチ作成→方針コメント) | | `/d commit` | コミット→push→Draft PR作成→AIレビュー | | `/d pr` | PR 作成・更新 | | `/d review` | 作業内容のレビュー | | `/d improve <内容>` (`/d imp`) | スキル自身の改善提案を Issue 起票 | | `/d help` | このヘルプを表示 | ## ヒント - 厳密なサブコマンド名を覚えていなくても、`/d 42番のIssueに着手して` のように自然言語で指示すれば適切なサブコマンドが実行される - 困ったら `/d` だけ打って、表示された選択肢から選べばよい ``` サブコマンド一覧 サブコマンド 役割 /d (引数なし) /d help と同じ /d todo 自分のアサインタスク・メンション・レビュー依頼を一覧 /d new <タイトル> 新規Issueを起票 /d issue <番号> 既存Issueに着手(アサイン→ブランチ作成→push→方針コメント) /d commit コミット→push→Draft PR作成→AIレビュー /d pr PRの作成・更新 /d review 作業内容のレビュー /d improve <内容> スキル自身の改善提案をIssue起票 /d help 全コマンド一覧と典型フローを表示 個別スキルではなくサブコマンド方式にしたことで、利用者は 「困ったら /d に続けてやりたいことを伝える」だけ で、スキルで規定したルールに則れます。 主役は /d todo / /d issue / /d commit / /d review の4つ 主役サブコマンドは、 作業者がもともと意識している作業アクション に対応します。 自分のタスクを確認する 着手する 成果物を提出する レビューする いずれも Git/GitHubとは無関係に作業過程に存在するアクション です。これらを主役に据え、ブランチ作成・PR作成・mainブランチ取り込みといったGit/GitHub起因の操作は内側に隠してAIが自動化します。 さらに /d todo はIssueのアサイン情報に基づいて着手すべきIssueを提案し、 /d commit はコミットからPR作成、AIレビューまでまとめて実行するため、 典型フローで利用者が実際に打つのは /d todo → /d commit の2つで済むことも多い です。 動かしてみる:2つの典型シナリオ 入口は2通りありますが、 どちらも最後は /d commit に合流し、PRベースの開発フローが進む のがポイントです。 シナリオA:Issue駆動で開発を進める場合 UXデザイナの佐藤さんに「ログイン画面の入力欄の余白を調整してほしい」という Issue #58 がアサインされた。 Step 1: /d todo で確認し、そのまま着手する > /d todo スキルは「現在のブランチ・アサイン済みIssue・レビュー依頼・メンション」を並列取得して整形表示し、 最後に「次に何をすべきか」まで提案します 。 ## 現在のブランチ - ✓ main(クリーン) ## アサイン済み Issue | # | タイトル | 状態 | ラベル | |----|---------------------------------------|--------|--------| | 58 | ログイン画面の入力欄の余白を調整したい | 未着手 | feat | (レビュー依頼・メンションはありません) --- 未着手の Issue が1件あります。優先度の高い #58 から着手しますか? (アサイン → ブランチ作成 → push → 方針コメント まで実行します) (y/n) /d todo は一覧を並べて終わりではなく、 「未着手の #58 から着手しますか?」と次の一手まで提案 します。利用者は表を眺めて「次に何をしよう」と考える必要がありません。ここで y と答えれば、着手処理がそのまま走ります。 # 「はい」と答えた後にスキルが実行する内部処理 gh issue edit 58 --add-assignee "@me" git checkout -b "feat/58-login-margin" origin/main git push -u origin HEAD gh issue comment 58 --body "<実装方針>" ブランチがpushされた瞬間、GitHubの他メンバーには「佐藤さんが #58 着手中」が見えます。 これだけで重複着手を大きく減らせます。 着手の入口は2通り、どちらでもよい — Issue番号が最初からわかっているなら、 /d todo を経由せず /d issue 58 を直接打っても同じ着手処理に入ります。「 /d todo の提案に乗る」か「 /d issue を直接打つ」かは、利用者が好きな方を選べます。 Step 2: 実装 → /d commit 佐藤さんはClaude Codeに実装を任せ、完了したら /d commit を実行。 コミット → push → Draft PR → AIレビュー → Ready化 → マージ → Issueクローズ までが一気に流れます。 結局、利用者が打つのは /d todo (提案に乗って着手)→ /d commit の実質2コマンドだけ。ブランチ名やコミットメッセージ、PR本文を書く場面はありません。 補足:Issueがまだ無いときは /d new で起票する シナリオAはアサイン済みの Issue #58 から始めましたが、そもそも取り組みたいことがまだIssueになっていないこともあります。その場合は /d new に概要を渡すだけで起票できます。 > /d new ログイン画面の入力欄の余白を調整したい スキルは既存の類似Issueを確認したうえで、タイトル・説明文・ラベルの案を生成して起票し、作成後に 「誰が取り組むか」を選択肢で提示 します。 Issue #59 を作成しました: https://github.com/<owner>/<repo>/issues/59 続けてどうしますか? 1. 自分をアサインして今から取り組む(そのまま着手処理へ) 2. 自分をアサインして後で取り組む 3. 他の人をアサインする 4. アサインせず終了 1 を選べば、そのまま /d issue 相当の着手処理(アサイン → ブランチ作成 → push → 方針コメント)に流れます。 「起票 → 着手」がコマンドを打ち替えずに一本でつながる のがポイントです。起票だけして他の人に任せたい( 3 )、あとで自分でやる( 2 )といった分岐も、その場で選ぶだけで済みます。 また /d new は、機能追加のようなきちんとしたIssueだけでなく、 「このドキュメントを直してほしい」「Claudeのスキルを修正して」といったちょっとした作業依頼 にも気軽に使えます。口頭やチャットで流れがちな細かい依頼もIssueとして残り、依頼のハードルが下がります。さらに 受けた側が /d issue で着手するときには、AIがIssue本文(背景・経緯・期待する結果)を文脈として読み取れます 。チャットの断片的なやり取りと違い、要件がまとまっているぶん、AIは意図を汲んだ実装や方針コメントを返しやすくなります。これは冒頭で触れた 「AIが文脈を理解しやすいようにGit/GitHubへ集約する」 流れに、気軽な起票がそのまま乗る形です。 シナリオB:Issueを立てず、思いついた改善案をいきなり作り始める場合 UXデザイナの佐藤さんは、ふと思いついたUIの改善案をその場でClaude Codeに作らせてみた。Issueも立てず、ブランチも main のままローカルに修正案ができあがっている。仕上がりが良かったので、そのまま /d commit を実行する。 > /d commit このとき、スキルは変更内容を確認し、 変更内容から適切なブランチ名( fix/update-signup-form-warning-message など)を判断 自動でブランチを切ってから コミット そのブランチをpushし、Draft PRを作成 続けて AIレビューが走り 、変更内容に問題がなければReady化 シナリオAと同じく、 /d commit の先はDraft PR作成からAIレビュー・Ready化まで一気に流れます。佐藤さんは「ブランチを切り忘れた」「Issueを立て忘れた」と慌てる必要がなく、思いついた改善案を形にすることだけに集中できます。 「アイデアを止めずに作り、後から正しい形に整える」 ── バイブコーディングのリズムを保ったまま、結果的にお行儀の良い形に着地します。 スキル改善の経緯と考え方 /d は最初から今の姿だったわけではありません。初期はもっと細かく「ブランチを作る」「Pull Requestを作る」といった Gitの操作にも1つずつコマンドを紐づけており、個々の操作をAIで補完しているだけでした。エンジニアにとっては違和感がなくとも、エンジニア以外の利用者から見ると どのコマンドを打つか選ぶ時点でGitの知識が必要 で、開発フローの作法を覚える負担が残っていました。 そこで 「ツールではなく目的中心でスキルのあり方を決める」 ことを強く意識し、使いやすさを追求して改善を重ねました。判断軸として参照したのが、UX設計の古典である ヤコブ・ニールセンのユーザビリティ10原則 です。スキル開発は「自分が便利な機能を足す」方向に流れがちですが、10原則に照らすことで「これは利用者目線の仕様になっているか?」を問い直せました。 10原則は以下のとおりです(和訳は本記事での表記)。 Visibility of system status / 状態の可視性 Match between the system and the real world / 現実世界との調和 User control and freedom / ユーザーコントロールと自由 Consistency and standards / 一貫性と標準 Error prevention / エラー予防 Recognition rather than recall / 再生より再認 Flexibility and efficiency of use / 柔軟性と効率性 Aesthetic and minimalist design / 最小限デザイン Help users recognize, diagnose, and recover from errors / エラー回復 Help and documentation / ヘルプとドキュメンテーション この章では、特に大きく効いた 4つの改善 を、対応する原則とともに紹介します。 改善1:コマンドを「Git操作」から「作業アクション」へ(原則2 現実世界との調和) 最大の改善が、コマンド体系そのものの組み替えです。 Before — ブランチ作成・コミット・PR作成…と、Git/GitHubの操作を利用者が1つずつ呼び出す体系 After — /d todo (見る)・ /d issue (着手)・ /d commit (提出)・ /d review (レビュー)の4つ。ブランチ作成やPR作成はこの内側に隠れる 原則2「現実世界との調和」は、 利用者が現実世界から類推するイメージにシステムを合わせよ という原則です。タスクを見る・着手する・成果物を提出する・レビューする ── いずれもGit/GitHubに関係なく開発の作業過程に存在するアクションであり、利用者が説明されなくてもする行動です。ここに揃えたことで「開発ツールの使い方を学ぶ」という壁が解消されました。 改善2:「誰が何をやっているか」が自然に見える(原則1 状態の可視性) 原則1「状態の可視性」は、 システムの状態を利用者に常に見えるようにせよ という原則です。 /d ではこれを個人の画面にとどめず、 チームに対する作業状況の可視化 に広げました。改善1で「着手」の内側に束ねた一連の操作が、そのまま 着手宣言プロトコル として機能します。 /d issue 58 を実行した時点で、 アサイン + 作業ブランチのリモートpush + 方針コメントの投稿 が走ります。コミットがまだ無くても「私が #58 やってます」が周囲に見えるようになります。地味ですが、これだけで 実装を二重に進めてしまう事故 を大きく減らせます。自分から「やってます」と声を上げなくても着手した時点で自然に共有され、チーム全体での作業状況が見えやすくなります。 改善3:誤操作は注意ではなく仕組みで防ぐ(原則5 エラー予防) 原則5「エラー予防」は、 丁寧な注意喚起よりも、そもそもエラーが起きない設計を優先せよ という原則です。Gitを使っていて起きがちな失敗に対して、「気を付けてね」と促すのではなく仕組みで潰します。 /d スキルを使いながら取り入れた予防の仕組みをいくつか紹介します。 # 起きがちな失敗 スキルでの解決 1 同じ内容のIssueを重複起票 起票前に既存Issueとの類似をチェック 2 mainで作業して直push 変更を検知し、自動でブランチを切ってからコミット 3 test tmp 等でブランチ名が乱立 Issue・変更内容から命名規則に沿って自動命名 4 同じIssueを別ブランチで重複着手 着手時に既存ブランチを確認、他人のコミットがあれば確認 5 .env ・ node_modules 等を誤commit ステージング前に自動検知して確認 6 Issueと無関係なファイルが混入 ブランチ名から推測した作業内容と照合して警告 7 未コミット変更を抱えたままcheckout 切り替え前に確認し、コミット/中断を提示 8 ローカルのmainが古いまま進めてconflict地獄 作業着手時やpush前にmainとの差を自動チェックし取り込みを提案 9 Issue・コミット・PRの説明の作文が面倒で省略・雑になる 変更内容からAIがタイトル・本文・コミットメッセージ・PR説明を自動作文 改善4:思い出させない・迷わせない(原則6 再生より再認) 原則6は、認知科学でいう 「再生(recall)より再認(recognition)の方が遥かに楽」 という性質に基づく原則です。「次に何をすべきか」を利用者が思い出す(再生)必要をなくし、 提示された選択肢から選ぶ(再認) だけで正しい手順を歩めるようにします。 「次にやること」を選択肢で提示する サブコマンドの終わりには、必ず 次の候補アクションを選択肢で提示 します。 /d todo の最後 → 優先度の高い順に次のタスクを提案 /d new で起票後 → 「自分をアサインして取り組む / アサインのみ / 他の人にアサイン / アサインしない」 /d commit のレビュー完了後 → 「マージしますか? (y/n)」 利用者は「次に何をすればよかったっけ」と考える必要がなく、選ぶだけで正しい手順に乗れます。 リスト出力に必ず識別子を振る 「選ぶだけ」のやり取りを支えるため、表・箇条書き・選択肢など複数項目が並ぶ出力には、 必ず連番や記号の識別子を振る ルールにしました。Issue番号のような既存IDがあればそれを使い、無ければ連番を振ります。たとえば実装前に手順の計画を出させると、こうなります。 実装計画: 1. 入力欄コンポーネントの余白を変数化 2. ログイン画面へ適用 3. モバイル表示のスタイル調整 4. 他画面のフォームへ横展開 5. 不要になった旧スタイルの削除 どこまで進めますか? 地味ですが効果は大きく、利用者は 「一旦3まで進めて」「4と5は不要」 のように番号だけで指示できます。AIとのチャットでは対象を言葉で説明し直したり長い引用をコピペしたりが負担になりがちですが、識別子があるとやり取りが一気に短くなります。 10原則ダイジェスト:残りの原則も設計に対応づける 改善1〜4で使った原則(1・2・5・6)以外も、 /d の設計判断のあちこちに対応しています。残り6つをダイジェストで紹介します。 原則3 ユーザーコントロールと自由 — Issue起点のフローに限定せず、mainでの思いつき着手も許容。破壊的操作の前には必ず (y/n) 確認 原則4 一貫性と標準 — issue commit などの用語は技術側に合わせ、利用者の用語習得やエンジニアとの意思疎通を重視 原則7 柔軟性と効率性 — 初心者は /d todo の提案に乗るだけで着手まで進み、慣れたら /d issue を直接打つ・エイリアス( /d i )を使うなど効率化できる。さらに /d improve でスキル自体を進化させられる 原則8 最小限デザイン — 覚えるべきコマンドを少なくし、自然言語でも動くようにすることで、スキルの使い方をシンプルに 原則9 エラー回復 — ワークフロー操作をAIが実施することで、エラー時もAIが能動的に調査・回復できる。使いづらさがあれば /d improve で不満を改善案としてIssue化できる 原則10 ヘルプとドキュメンテーション — /d help で全コマンドと典型フローを表示 おわりに 本記事では、Git/GitHubを使った開発フローをエンジニア以外のメンバーと協働して進めるためのスキルについて紹介しました。エンジニア以外のメンバーとともに開発するチームで、 全員が安心して開発できる環境づくりの一助になれば幸いです。 「こうしたらもっと良くなる」「自分のチームではこうしてる」などがあれば、是非コメントください!
はじめに こんにちは、情報セキュリティ部の 兵藤 です。日々ZOZOの安全を守るためSOC業務に取り組んでいます。 本記事では、SOCでの業務効率化のためにClaude Codeを活用して、自動アラートトリアージエージェント(以降SOC Agent)を構築した事例を紹介します。 また、情報セキュリティ部ではその他にもZOZOを守るための取り組みを行っています。詳細については以下の「OpenCTIをSplunkに食わせてみた」をご覧ください。 techblog.zozo.com 目次 はじめに 目次 背景と概要 SOC Agentの設計 Agentの全体像 Splunk MCPの活用 OpenCTI MCPの活用 SOC AgentのSubAgent設計 opencti-agent log-search-agent memoryの活用 SOC Agentの運用 SOC Agent Skillsのコマンド notable-response threat-hunting slack-alert-triage SOARの活用 おわりに 背景と概要 ZOZOのSOCメンバーは3人体制で、日々大量のセキュリティアラートを処理しています。これらのアラートは、ZOZOTOWNやWEARなどのプロダクトや社内システムのログから生成され、3人で分担して対応するにしては量が多く、負荷がとても高い状況でした。 そこでClaude Codeを活用して、アラートの内容を分析し、優先的に対応すべきアラートを自動で選別するエージェントを構築することにしました。これにより、SOCメンバーは重要なアラートへ集中できるようになり、効率的な対応が可能になると考えました。 また、このSOC AgentのSkillsによってある程度網羅的な調査が可能になるため、SOCメンバーの負荷軽減だけでなく、アラート対応における質の平準化にも寄与しています。 SOC Agentの設計 このAgentが担うのは、初動対応の切り分けです。一般的にはTier1の初動対応に相当します。具体的なレスポンスや即時対応はSOARで行う想定のため、SOC AgentはRead権限で完結する設計にしています。 Agentの全体像 SOC Agentは以下のようなフロー設計で構築しました。 SOC Agentの全体像 SOCアナリストの指示、またはSlackのアラート通知のもと、Claude Codeが動作 Splunk MCPを通じ、アラートデータや詳細なログデータを取得 ZOZOで活用している脅威インテリジェンスプラットフォーム(TIP)であるOpenCTIから、脅威インテリジェンスを取得 取得した情報をもとに、SOC Agentがアラートの優先度を評価し、対応案を検討 レポートを生成し、Slackに対応サマリを投稿 Slackに対する起動は定期実行も可能で、未処理アラートを自動検知して対応サマリを投稿 Splunk MCPの活用 SOC AgentはSplunk MCPを活用して、アラートデータや詳細なログデータを取得しています。Splunk MCPを活用する際、Splunk Cloudにはレガシーなエンドポイントも存在します。ただし、オンプレミスのSplunkと同様に Splunk MCP Server の公式Splunk Appを利用することが推奨されています 1 。 このAppを利用すると、通常のSplunk APIを利用する場合と異なり、MCP専用のTokenをUserごとに払い出すことが可能です。 Splunk MCP Server このMCP Serverに接続するためには IP allow lists を設定する必要があります。見落としがちな点のため、注意してください。 また、このMCPを利用するためのRoleはこのSOC Agentにおいて基本的に以下の4つで、SPLを実行するためのRead権限があれば十分でした。 search get_metadata indexes_list_all mcp_tool_execute クライアント側の設定は基本的に .mcp.json などのファイルに記載します。以下は .mcp.json の例です。 { " mcpServers ": { " splunk-mcp-server ": { " command ": " op ", " args ": [ " run ", " -- ", " npx ", " -y ", " mcp-remote ", " https://<stack-name>.splunkcloud.com:8089/services/mcp ", " --header ", " Authorization: Bearer ${AUTH_TOKEN} " ] , " env ": { " AUTH_TOKEN ": " op://<vault-name>/<item-name>/<token-field> " } } } } 上記のように1Password CLIを利用してMCP ServerのTokenを取得します。このSOC AgentのコードはチームでGitHub管理しているため、誤ってTokenをコミットしてしまうリスクを避けるために、VaultからTokenを取得しています。 MCPのエンドポイントは443ポートのもの( /en-US/splunkd/__raw/services/mcp )もあります。ただし、内部的には8089ポートにリダイレクトされるのでどちらを使っても問題ありません。 OpenCTI MCPの活用 実際の攻撃手法や攻撃に使われたIOC情報などを取得して危険度を評価するために、OpenCTI MCPも活用しています。OpenCTI MCPはFiligran社から公式に MCP が提供されています。 OpenCTI MCPを利用するにはTokenが必要なため、MCPを使うためのロール、グループ、サービスアカウントの作成が必要です。アカウントの作成に大きな手間はかかりませんが、ロールに関しては実際のAgentにどこまで作業をさせるかで必要な権限が変わります。今回のSOC AgentではRead権限のみで完結するように設計しているため、以下のようなロールを作成しました。 OpenCTI MCP ロール設定 基本的にこの Access knowledge のRoleがあればこのAgentの機能は十分に動かすことができました。caseまで記載させたい場合は別の権限が必要でしょう。 また、グループの作成の際にそのグループがアクセスできるインテリジェンスの範囲を定義できます。これは組織によってAIのオプトアウトの設定やインテリジェンスの発行元、TLPなどを考慮して設定する必要があります。個々の組織にあったポリシーを設定してください。 以下のような画面でグループのアクセス範囲を設定できます。「TLP:RED」のインテリジェンスは定義上見せない設定が基本でしょう。「TLP:AMBER」に関しては状況によるでしょう。 OpenCTI MCP グループ設定 クライアント側の設定は以下の記載で接続できます。 { " mcpServers ": { " opencti-mcp-server ": { " command ": " op ", " args ": [ " run ", " -- ", " <path-to-python-venv>/.venv/bin/python3 ", " -m ", " opencti_mcp.server " ] , " env ": { " OPENCTI_URL ": " op://<vault-name>/<item-name>/<url-field> ", " OPENCTI_TOKEN ": " op://<vault-name>/<item-name>/<token-field> ", " PYTHONPATH ": " <path-to-xtm-mcp> " } } } } このサーバは from opencti_mcp.graphql_queries などの記述でPythonモジュールをimportしているため、 PYTHONPATH の環境設定が必要です。 これらのMCPの設定のように、AIはある程度予期せぬ挙動を取る可能性も考え、与えるTokenの権限を絞ることをまずお勧めします。AIには自由にさせた方が柔軟に対応してくれます。変更されたくない接続先の権限を絞ることで、万が一の暴走リスクを減らせます。 SOC AgentのSubAgent設計 このSOC Agentは、特定のSkillを呼び出すAgentを並列起動できるようSubAgentを設計しています。具体的には、OpenCTIから脅威インテリジェンスを取得するSubAgentと、Splunkからログを取得するSubAgentの2つです。 Agent名 説明 opencti-agent OpenCTI MCPを通じて脅威インテリジェンスを取得するSubAgent log-search-agent Splunk MCPを通じてログデータを取得するSubAgent 全体像は以下のとおりです。 SubAgentの構成 この2つのSubAgentが調査によって数十体並列で呼び出されます。IOCの種類や調査するログの種類によって呼び出すSubAgentを分けることで、効率的に必要な情報を取得できるようにしています。 opencti-agent このAgentはOpenCTI MCPを通じて脅威インテリジェンスを取得するSubAgentです。OpenCTIから攻撃手法や攻撃に使われたIOC情報などを取得して、SOC AgentのメインのAgentがアラートの優先度を評価する際に活用します。基本的には別途設計したOpenCTIへGraphQLを投げる opencti-lookup Skillを参考にしています。大量の調査結果やインテリジェンスを収集する目的で利用するため、分析機能を持たせず、ひたすらクエリを投げる設計にしています。高度な分析を必要としないため、 sonnet のモデルで動かしています。 上記Skillのreferenceに各種GraphQLのテンプレートを記載することで、必要な情報を取得する際のクエリを定義しています。例えば、「Reportの基本情報」を取得する際には以下のようなクエリを定義しています。 query ReportById { report(id: "<REPORT_ID>") { id standard_id entity_type name description published report_types confidence created_at updated_at objectLabel { value color } createdBy { ... on Identity { id name entity_type } } } } 念のため、 Hooks にて create や delete 、リレーションを変更する stixCoreRelationshipEdit などRead権限以外の操作するクエリは禁止しています。 " hooks ": { " PreToolUse ": [ { " matcher ": " ^mcp__opencti-mcp-server__(execute_graphql_query|validate_graphql_query)$ ", " hooks ": [ { " type ": " command ", " command ": " python3 \" $CLAUDE_PROJECT_DIR \" /.claude/hooks/validate-opencti-graphql.py ", " timeout ": 5 , " statusMessage ": " Validating OpenCTI GraphQL safety policy " } ] } ] } この validate-opencti-graphql.py には、禁止するGraphQLのパターンを tool_input から正規表現でマッチさせるPythonコードが記載されています。 SOCの対応でVirusTotalなどの判定を利用するフローも一般的に存在します。一方ZOZOでは脅威情報をOpenCTIに集約しているため、このエージェント単体で完結させています。 また、OpenCTIにはZOZO独自で調査している脅威情報も蓄積しているため、外部の脅威情報と社内の知見を組み合わせてアラートの優先度評価ができるようになっています。例えば以下のようなMalware解析のレポートなどを参照します。 qiita.com log-search-agent このAgentはSplunk MCPを通じてログデータを取得するSubAgentです。NotableのReference IDなどをもとに、アラートの概要を取得したり、より詳細なログを取得するSPLを投げたりするために利用します。こちらも分析機能は持たせず、別途設計した splunk-search Skillをもとに、ひたすらクエリを投げる設計にしています。高度な分析を必要としないため、 sonnet のモデルで動かしています。 上記Skillのreferenceに各種SPLのテンプレートを記載することで、必要な情報を取得する際のクエリを定義しています。例えば、「Notableの概要」を取得する際には以下のようなSPLを定義しています。 index=notable source_event_id="<SOURCE_EVENT_ID>" | sort -_time | head 5 | table _time source_event_id event_id notable_event_id orig_event_id search_name rule_title notable_title signature security_domain urgency severity status status_label owner src dest user host risk_object risk_object_type risk_score info_min_time info_max_time SplunkのMCP側で詳細なSPL制御ができません。そこで、OpenCTI同様に Hooks を利用して outputlookup や outputcsv などの作成・変更を伴うSPLは以下の設定で利用禁止にしています。 " hooks ": { " PreToolUse ": [ { " matcher ": " ^mcp__splunk-mcp-server__splunk_run_query$ ", " hooks ": [ { " type ": " command ", " command ": " python3 \" $CLAUDE_PROJECT_DIR \" /.claude/hooks/validate-splunk-spl.py ", " timeout ": 5 , " statusMessage ": " Validating Splunk SPL safety policy " } ] } ] } このMCPの利用に際して、JSON形式で入れ子になっているログはSubAgentの判断で最初に spath などのSPLを打つことがあります。簡易なログだと問題ありませんが、Endpoint系のログだと大量のkeyに対して展開するため、各種SPLのreferenceを詳細に定義しておく方が安全です。また、サーチマクロを定義しておけば、Agentの調査の平準化やトークン消費の最適化が可能です。 memoryの活用 このSOC Agentでは、過去の調査履歴も活用しています。「このインシデントは過去に過検知フィードバックがあったものだ」や「引き続きこの証跡と同じアクターが関与している可能性が高い」といった情報を基に、調査の効率化や精度向上を図っています。 SOC Agentの運用 SOC Agent Skillsのコマンド このAgentには様々なSkillsを実装しています。その中でもZOZOのSOCアナリストが利用するコマンドに絞ってここでは紹介します。 コマンド 説明 /notable-response NotableのReference IDからインシデントを取得し、自動調査を実行するコマンド /threat-hunting OpenCTIのレポートから脅威ハンティングを実行するコマンド /slack-alert-triage Slackのアラートを自動でトリアージし、調査結果をスレッドに投稿するコマンド notable-response このコマンドでのワークフローは以下のイメージです。 SOCアナリストが /notable-response <Reference ID etc> を入力 SOC AgentがSplunk MCPを通じてNotableの概要を取得 SOC AgentがNotableの内容をもとに、opencti-agentとlog-search-agentを呼び出して、関連する脅威インテリジェンスやログデータを取得 SOC Agentが取得した情報をもとに、Notableの相関分析や脅威判定し、対応案を生成 深掘りが必要な場合は、さらに追加の情報を取得するために3からのステップを繰り返す レポート作成、メモリに事象の内容や調査結果を保存 引数には調査観点の概要を含めて渡すことでカスタムした調査が可能です。 threat-hunting このコマンドでのワークフローは以下のイメージです。 SOCアナリストがSlackで /threat-hunting <Report ID> を入力 SOC AgentがOpenCTI MCPを通じてレポートの内容を取得 SOC Agentがレポートの内容をもとに、関連するIOCや攻撃手法を抽出 SOC Agentが抽出したIOCや攻撃手法をもとに、log-search-agentを呼び出して、関連するログデータを取得 SOC Agentが取得した情報をもとに、脅威ハンティングの結果を分析し、対応案を生成 深掘りが必要な場合は、さらに追加の情報を取得するために4からのステップを繰り返す レポート作成、メモリに事象の内容や調査結果を保存 Report IDは別途ZOZOで活用しているMalware解析Agentの結果を渡すこともできます。 slack-alert-triage このコマンドでのワークフローは以下のイメージです。 SOCアナリストがSlackで /slack-alert-triage <time> を入力 SOC Agentが指定された時間範囲のアラートをSlack MCPを通じて取得 SOC Agentが取得したアラートをもとに、NotableのReference IDを抽出 SOC Agentが抽出したReference IDをもとに、notable-responseと同様にNotableの内容を取得 Notableの内容をもとに関連事象をグルーピング、Slackのスレッドに調査開始の投稿 各グループごとにopencti-agentとlog-search-agentを呼び出して、関連する脅威インテリジェンスやログデータを取得 SOC Agentが取得した情報をもとに、Notableの相関分析や脅威判定し、対応案を生成 深掘りが必要な場合は、さらに追加の情報を取得するために6からのステップを繰り返す レポート作成、Slackスレッドに対応サマリを投稿 脅威度がCritical判定の場合は、SOCアナリストにメンション通知 このコマンドを /loop 1h /slack-alert-triage 1h のように定期実行することで、未処理のアラートを自動的に検知して対応サマリを投稿しています。24時間365日対応が難しい場合でも、こういった自動化を活用することでSOCメンバーの負荷を軽減できます。 SOARの活用 /slack-alert-triage コマンドのポイントはSlackのアラートにReference IDが含まれていることです。通常のSplunk ESの「Edit event-based detection」だと「Adaptive response」はNotableの作成とは別のアクションを実行するため、Reference IDがSlackのアラートに含まれません。そこでSplunk SOARを用いて、NotableのReference IDをSlackのアラートに含めています。こうすることで、SOC AgentがSlackのアラートからNotableのReference IDを抽出し、調査を開始できます。 SOARは以下のformatとSlackへのsend messageの Splunk App の設定だけで済みます。 Splunk SOAR 設定 formatはSlackのblocks項目に以下の記述をすれば、ビジュアライズされたアラートをSlackに送れます。 [ {{ " type ": " header ", " text ": {{ " type ": " plain_text ", " text ": " 🟢 Splunk Finding Detected ", " emoji ": true }} }} , {{ " type ": " section ", " fields ": [ {{ " type ": " mrkdwn ", " text ": " *🔎 Name* \n {0} " }} , {{ " type ": " mrkdwn ", " text ": " *🆔 Reference ID* \n `{1}` " }} ] }} ] {0} にはアラート名、 {1} にはReference IDを入れるように設定しています。これでSOC AgentがSlackのアラートからReference IDを抽出し、調査を開始できます。 SOC Agentの本命のSkillはこのコマンドです。ループ処理することでTier1相当の対応をAIで完全自動化することに成功しており、SOCメンバーの負荷軽減に大きく寄与しています。 以下はSOC Agentの対応例です。 SOC Agentの対応例 おわりに 本記事ではClaude Codeを用いたSOC Agentを紹介しました。SOC Agentの導入によって少人数のSOC業務を改善し、アラート対応の効率化、平準化、SOCメンバーのさらなる高度業務へのアサインを図れました。 ZOZOでは、一緒に安全なサービスを作り上げてくれる仲間を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください! hrmos.co About MCP Server for Splunk platform ↩
.images-row {width: 100% !important;} Developer Engagementブロックの @ikkou です。2026年5月22・23日の2日間にわたりベルサール羽田空港で「TSKaigi 2026」が開催されました。 ZOZOはGold Sponsorとして協賛し、スポンサーブースを出展しました。ZOZOがTSKaigiに協賛するのは今回が初めてです。 technote.zozo.com 本記事では、前半はZOZOのWebフロントエンドエンジニアが気になったセッションを紹介します。後半では、ZOZOのスポンサーブースの様子と各社のブースにおけるコーディネートを写真中心に報告します。 ZOZOのWebフロントエンドエンジニアが気になったセッション 開発体験を左右するライブラリの API 設計 ― GraphQL スキーマ構築ライブラリから考える 「関数型プログラミング」を分解する.ts 純粋性について 型でエフェクトを表す いつテストを書くか?―ソフトウェア開発における安心と不安について考える LLM時代のリファクタリング戦略:AIエージェントによる段階的・安全なTS移行方法 TypeScript の型で副作用の実行順序を制御する ZOZOのスポンサーブースの紹介 協賛企業ブースのコーディネートまとめ おわりに ZOZOのWebフロントエンドエンジニアが気になったセッション 開発体験を左右するライブラリの API 設計 ― GraphQL スキーマ構築ライブラリから考える ssssota です。izumin5210さんの「 開発体験を左右するライブラリの API 設計 ― GraphQL スキーマ構築ライブラリから考える 」を紹介します。 speakerdeck.com このセッションでは、スキーマや型情報をいかにTypeScriptの実装に接続するかという観点で、既存ライブラリのアプローチやその長短を深ぼる内容でした。弊社ではOpenAPIを使っているケースが非常に多く、いかにOpenAPIスキーマを実装に接続するかは往々にして発生する問題の1つです。 セッションではGraphQLに焦点が当てられていましたが、スキーマから実装を生成するスキーマファースト、コードからスキーマを生成するコードファースト、コードファーストのうちDecoratorsを使うパターン、DSL的な独自のbuilderパターン、計3パターンについて評価していました。比較・評価軸として、1.スキーマと実装の分離、2.型整合性、3.DBモデルとの接続、の3軸を用いています。 スキーマと実装の分離については、スキーマファーストが優れているのは言うまでもありませんが分離する強いモチベーションがなければ優先度は低くなります。型整合性は採用するライブラリのtype ergonomicに依りますが、コードファーストなDSL builderパターンが強い傾向にあります。DBモデルとの接続においてはGraphQL特有と見ることができますが、コードファーストなDSL builderパターンで型整合問題と合わせて解決できることを示唆しています。 セッションの最後には、自作のライブラリでこのギャップを埋める取り組みとAIを用いた評価結果を紹介していました。気になる方はスライドも合わせて確認してみてはいかがでしょうか。 私自身、OpenAPIスキーマと実装の接続に関して関心があり、ライブラリ( openapi-ts-hono )を作った経験から非常に共感できるところがありました。もちろんGraphQLとはギャップがありますが、スキーマと実装の分離、型整合性などは感覚としてもっていながらも、改めて言語化されることで気付きのあるセッションでした。 「関数型プログラミング」を分解する.ts www_REM_zzz です。おーみーさんの『 「関数型プログラミング」を分解する.ts 』を紹介します。 tsk-2026-aumy.vercel.app 自分の話ですが、TypeScriptに入門する前はScalaを書いていた経験があります。当時はコップ本と呼ばれる本とHaskellの公式ドキュメントが日本語で関数型プログラミングに入門する入口でした。Object指向プログラミングとは全く別の世界からやってきたような考え方で、面白くもあり、苦労もした過去があります。 このセッションでは、そもそも関数型プログラミングとは何なのかの考え方に触れながら、TypeScriptで真の関数型はできないのかに触れられています。僕もTypeScriptで真の関数型が書けたらいいのにと思った一人です(OCaml書けよというのは一旦置いといて)。スライドの中で語られた関数型プログラミングは「いい感じのソフトウェアを作るため」というのは本質的だなと思いました。ついつい手段に引っ張られてしまうところがあるのですが、心に留めておきたいです。 純粋性について 特に純粋性についてのところはReactでも他のライブラリでも語られる部分であり、意味の純粋性の部分は悩ましいと感じたことがあるので共感しました。 // 「副作用を表す値」を返すだけ(純粋関数) function pureAlert ( msg : string ) { return [ "alert" , msg ] as const ; } // 副作用の実行は別の関数に委ねる function executeAction ( action : readonly [ "alert" | "confirm" , string ] ) { switch (action[ 0 ]) { case "alert" : alert (action[ 1 ]); break ; case "confirm" : confirm (action[ 1 ]); break ; } } const actions = [ pureAlert( "hey" ), pureAlert( "bye" ) ] ; actions. forEach (( a ) => executeAction(a)); 引用: https://tsk-2026-aumy.vercel.app/29 このような「何をするかの宣言」と「実行」が分離されている書き方は普段からできるし、メンテナンスを考えると普段から実践していきたいと思いました。 return は「この関数の呼び出し元(= 継続)に値を渡して戻る」という考え方はTSを書いていてなんとなく感じていたものがはっきりと言語化されてスッキリした気持ちになりました。 型でエフェクトを表す () => T // 特に何も起きない純粋な処理 () => Option< T > // 失敗しうる処理 () => Promise < T > // 非同期処理 これを徹底すると 関数の型を見るだけで「何が起きるか・何が起きないか」がわかる 純粋な部分と副作用のある部分が型レベルで分離される 「支払い処理を起こしうる部分」だけを特定して二重実行を防げる これはTypeScriptを堅牢に書くうえで実践したいと思います。ちょうど業務でも似たシチュエーションがあることを思い出して、まず「この関数は副作用を持つか?」を命名( execute , get , ! 記法)で示すのが現実的な入口かなと思いました。 いつテストを書くか?―ソフトウェア開発における安心と不安について考える ジン( @Jin_pro_01 )です。自分の気になったセッションとして、 lacolacoさん の「 いつテストを書くか?―ソフトウェア開発における安心と不安について考える 」を紹介します。 docs.google.com このセッションでは、テストをどのような時に書くべきなのかを「開発者の安心と不安」を起点に問い直したlacolacoさんの気づきの共有、問いの提示、視点の提案をするというセッションでした。 セッションの中ではソフトウェアの保守性の本質は「変更容易性」であり、それは予期的変更容易性(変更する前に感じる不安)と経験的変更容易性(変更をする中で実際に感じる手応え)の二層モデルとして見ることができるとしていました。その上でテストはその両方にフィードバックを返すセンサーであるとし、変更前に感じる不安があるならそれを取り除く安心のために書き、変更のしやすさを試したり構造に問題が見つかったりするなら設計を見直すために書くという体系的な整理がされており、とても興味深いセッションでした。 自分が従事しているZOZOTOWNでは、新規機能の実装や既存機能の改修と並行で、フロントエンドリプレイスも各チームで進行しています。ZOZOTOWNの発展を止めずに開発を進める体制である一方、考慮すべきことが多く、自分にとっては比較的「予期的変更容易性」が低い状態だと表現できることに気づきました。そして、まさにこの「予期的変更容易性」を高めるためのテストへの投資価値が高いと感じました。 さらにAIを使ってコーディングをしていく時代に入り、開発の生産量が増える一方で、自分が直接書いていないコードや構造との距離は広がっていきます。その距離は新たな不安、つまり予期的変更容易性の低下にもつながると感じています。だからこそ変更の前後で「振る舞いが変わっていないこと」を担保し、その不安を取り除くセンサーとしてのテストの価値は、AI時代にこそますます高まっていくのだと考えました。 最大の収穫は、テストを書く目的を「ソフトウェアがソフトであり続けるための、変更容易性のセンサー」と説明できるようになったことです。テストはあくまで手段の1つと捉えつつ、ZOZOTOWNがソフトであり続けるために、他に何ができるかも考えていきたいと思いました。 LLM時代のリファクタリング戦略:AIエージェントによる段階的・安全なTS移行方法 いもけん( @iimokeenpi )です。「 LLM時代のリファクタリング戦略:AIエージェントによる段階的・安全なTS移行方法 」について紹介します。 speakerdeck.com このセッションは、JSのコードをAIエージェントを使い安全にTSに移行するというものでした。しかし、JSからTSへの移行のみならず日常的なリファクタリングにおいても活用できそうなノウハウが詰まっていました。 特に自分が興味を持った部分としては”test-firstフロー”と”役割ごとにサブエージェントを切り出す”の2つがあります。AIエージェントの使用有無にかかわらずリファクタリングの際にデグレには細心の注意を払って行っていきたいところです。そこで”test-firstフロー”というのは、デグレの防止策としても効果が高くAIエージェントとの相性もかなり良いなと感じました。 そして“役割ごとにサブエージェントを切り出す”という点に関してです。自分は基本的に全てOpusで乗り切ろうとしていたのですが、消費トークンの効率や時間的な効率の面でも損をすることが多々あります。なので役割ごとにサブエージェントを切り出し、モデルを使い分けることはすぐにでも実践したいと感じました。 TypeScript の型で副作用の実行順序を制御する 佐藤です。私が印象に残ったセッションは「 TypeScript の型で副作用の実行順序を制御する 」です。 speakerdeck.com Branded Typeは「 UserId と ProductId を区別するためのタグ付け」くらいにしか使えないと思っていましたが、Type-State Patternを使えばそれが実行順序の制御に転用できます。TypeScriptの型システムでここまで表現できるのかと、型に対する認識が更新されました。 加えて魅力的なのが、ライブラリ依存ゼロで既存コードに薄く入れられる点です。Effect-TSやXStateは強力ですが導入コストは高いです。Type-Stateパターンなら守りたい箇所だけにピンポイントで適用できます。 実際、 getServerSideProps 内に「バリデーション→取得→加工」のような実行順序を守らなければならない処理があり、これまではAIのルールや運用上の規約に頼らざるを得ませんでした。型で制御できるようになれば、コードレビューや属人的な注意に依存せず、エディタ上でミスを即座に検出できます。自分のチームに導入できないか実践したいと思えるトークでした。 サンプルコードは GitHubで公開されています 。既存ライブラリとの比較実装も含まれているので、ぜひ手元で動かしてみてください。 ZOZOのスポンサーブースの紹介 ZOZOのスポンサーブースとWebフロントエンドエンジニアたち ZOZOのスポンサーブースでは「 Google I/O 2026から帰国したばかりのZOZOフロントエンドエンジニア テックリード ssssota に挑戦! 」と題したTypeScript & JavaScript Quizをメインコンテンツとして提供しました。日替わりで全10問、ブースにはその日のクイズから1問だけ掲示しました。 TypeScript & JavaScript Quiz Day 1 & Day 2 ZOZOブースでは #GoogleIO から帰国したばかりの Web フロントエンド テックリード @ssssotaro が考えた JavaScript & TypeScript Quiz を実施中です!難易度は高め!ぜひ挑戦してください! #TSKaigi pic.twitter.com/7K9ZTt22Qq — ZOZO Developers (@zozotech) 2026年5月22日 \TSKaigi 2026 最終日/ 今日もクイズ企画を開催しています!昨日とは異なる問題で、今日は特典をゲットしやすくなっています! オリジナル洗濯ネットをご用意していますので、ぜひご参加ください! #TSKaigi pic.twitter.com/QwR6v2F96t — ZOZO Developers (@zozotech) 2026年5月23日 難しい! ということが話題になり、とても多くの方に挑戦してもらいました。難しいのは作問者の意図通りですが、この「難しい」ということが反響を呼び、楽しんでもらえたのではないでしょうか。 No Bugs, Just Clean. というメッセージの込められた特製ノベルティの洗濯ネット クイズに挑戦し、7問以上正解した方には特製ノベルティの「洗濯ネット」をお渡ししました(Day 2は3問以上正解した方に変更)。 Day 1、Day 2の7問以上正解者 また、上位正解者の皆さんにはリーダーボードにもハンドルネームなどを書いてもらいました。2日間を通しての全問正解者は、Day 1が @uhyo_ さんと @vaaaaanquish さんの2名、Day 2が @U3Qc9 さんの1名だけでした。改めて全問正解おめでとうございます! このTypeScript & JavaScript Quizに関する解説記事を別記事として公開しています。あのクイズの答えが気になるという方はもちろん、もう一度あのクイズに挑戦したい、当日できなかったので挑戦したい! という方もぜひご覧ください。 techblog.zozo.com 10分セッションに登壇中のテックリード ssssota この難問揃いのクイズを作問したテックリードのssssotaはDay 2に「 ReactとSvelteのその先、Ripple-TS 」というタイトルで10分セッションにも登壇しています。こちらもあわせてご覧ください。 speakerdeck.com 協賛企業ブースのコーディネートまとめ ジン( @Jin_pro_01 )です。セッションを見たり、自社ブースに立ったりしている合間にTSKaigi 2026の全協賛企業ブースを回ってきました。当日の会場の様子を思い出しながら、各社の個性や雰囲気の出るデザイン・着こなしをぜひご覧ください。 ウェルスナビさん。 / @WealthNavi_Tech AVITAさん。 Dress Codeさん。 / @dresscode_com Hacobuさん。 / @MHacobu sattoさん。 / @satto_ai_agent アサインさん。 / @ASSIGN_dev レバレジーズさん。 PLAINERさん。 / @plainer_inc ビットキーさん。 / @bitkey_dev UPSIDERさん。 / @upsider_inc ニーリーさん。 / @nealle_pr LayerXさん。 / @LayerX_tech エブリーさん。 / @every_engineer スリーシェイクさん。 / @3shake_Inc ミツモアさん。 / @meetsmore Ubieさん。 / @UbieCorp_JP Nstockさん。 / @Nstock_jp プレイドさん。 / @PLAID_Tech ギークプラスさん。 / @GeekJapan1 ウォンテッドリーさん。 / @wantedly_dev サイボウズさん。 / @cybozuinsideout ドワンゴさん。 / @dwango_tech CodeRabbitさん。 / @Coderabbitaija シェルパ・アンド・カンパニーさん。 ファインディさん。 / @findy_code ディップさん。 / @dip_developers RightTouchさん。 / @righttouch_dev Gaji-Laboさん。 / @gaji_labo スタメンさん。 / @stmn_eng TOKIUMさん。 / @TOKIUM_Dev カオナビさん。 / @kaonavi_jp テイラーさん。 / @TailorERP_JP KINTOテクノロジーズさん。 / @KintoTech_Dev MOSHさん。 / @MOSHinc_jp 皆さん照れていたりウキウキしていたりしてよかったです! ご協力いただいた皆さん本当にありがとうございました! おわりに TSKaigi 2026 協賛企業一覧 TSKaigiへの初協賛を通して、ZOZOのことが少しでも来場者の皆さまに伝わっていれば嬉しいです。みなさま、ありがとうございました! TSKaigi 2026をきっかけとしてZOZOのWebフロントエンドエンジニアに興味を持たれた方は、技術スタックなどがまとまったページをぜひご覧ください。 techblog.zozo.com ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com

動画

該当するコンテンツが見つかりませんでした

書籍