<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Zero-Shot Log</title><description>Tech Blog by Ten</description><link>https://zeroshotlog.com/</link><language>ja-jp</language><item><title>Codex の experimental な Hooks を有効化して活用する</title><link>https://zeroshotlog.com/blog/2026/03/22/codex-hooks/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/2026/03/22/codex-hooks/</guid><description>OpenAI Codex に隠れている experimental な Hooks 機能の発見経緯・有効化方法・設定構造・対応イベントを、ソースコードを読んで調査した結果をまとめた。</description><pubDate>Sun, 22 Mar 2026 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Codex には「under development」（開発中）ステータスの Hooks 機能があり、&lt;code&gt;codex features enable codex_hooks&lt;/code&gt; で有効化できる&lt;/li&gt;
&lt;li&gt;対応イベントは &lt;code&gt;SessionStart&lt;/code&gt; / &lt;code&gt;UserPromptSubmit&lt;/code&gt; / &lt;code&gt;Stop&lt;/code&gt; の3つ&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;はじめに&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;本記事の内容は Codex v0.115.0（2026年3月時点）で検証しています。開発中の機能のため、今後のバージョンで仕様が変更される可能性があります。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Codex には公式にはまだ Hooks 機能がありません。公式ドキュメントにも記載はなく、&lt;a href=&quot;https://developers.openai.com/codex/changelog&quot;&gt;Changelog&lt;/a&gt; に「experimental hooks engine」という一行が載っている程度です。&lt;/p&gt;
&lt;p&gt;ところが、実は「under development」ステータスで &lt;strong&gt;すでに動く Hooks が実装されています&lt;/strong&gt;。&lt;code&gt;codex features list&lt;/code&gt; を実行してみたところ &lt;code&gt;codex_hooks&lt;/code&gt; というフィーチャーフラグが見つかり、有効化すると実際にフックが発火することを確認しました。&lt;/p&gt;
&lt;p&gt;ただし設定の JSON 構造や対応イベントの詳細はどこにも書かれていないため、OSS として公開されている &lt;a href=&quot;https://github.com/openai/codex&quot;&gt;openai/codex リポジトリ&lt;/a&gt;（Apache License 2.0）の Rust ソースコード（&lt;code&gt;codex-rs/hooks/&lt;/code&gt;）を読んで仕様を特定しました。本記事ではその調査結果をまとめます。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. 発見と有効化&lt;/h2&gt;
&lt;h3&gt;フィーチャーフラグの確認&lt;/h3&gt;
&lt;p&gt;Codex には &lt;code&gt;codex features list&lt;/code&gt; というフィーチャーフラグの一覧を表示するコマンドがあります。Hooks の存在を知ったのもこのコマンドがきっかけで、実行してみたところ &lt;code&gt;codex_hooks&lt;/code&gt; が「under development」として表示されました。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ codex features list
codex_hooks    under development  false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;デフォルトは無効です。&lt;/p&gt;
&lt;h3&gt;有効化&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# config.toml に永続化される
codex features enable codex_hooks
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有効化すると起動時に以下の警告が表示されます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;⚠ Under-development features enabled: codex_hooks. Under-development features are incomplete
  and may behave unpredictably.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 設定ファイル&lt;/h2&gt;
&lt;h3&gt;ファイルパスと形式&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;項目&lt;/th&gt;
&lt;th&gt;値&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;グローバル設定&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.codex/hooks.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;プロジェクト設定&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;project&amp;gt;/.codex/hooks.json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;形式&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Codex の一般設定は &lt;code&gt;~/.codex/config.toml&lt;/code&gt;（TOML 形式）ですが、Hooks 設定は &lt;strong&gt;&lt;code&gt;hooks.json&lt;/code&gt;（JSON 形式）&lt;/strong&gt; という別ファイルです。&lt;code&gt;config.toml&lt;/code&gt; に hooks を書いても読まれません。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.codex/
├── config.toml      ← 一般設定・feature flags
└── hooks.json       ← hooks 設定（JSON）
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;JSON 構造&lt;/h3&gt;
&lt;p&gt;構造がやや独特で、イベント名の配列にハンドラを直接並べるのではなく、&lt;strong&gt;一段ラッパーを挟む&lt;/strong&gt;必要があります。ソースコード（&lt;code&gt;codex-rs/hooks/src/engine/config.rs&lt;/code&gt;）では &lt;code&gt;MatcherGroup&lt;/code&gt; という構造体で定義されており、&lt;code&gt;matcher&lt;/code&gt;（正規表現フィルタ）と &lt;code&gt;hooks&lt;/code&gt;（ハンドラ配列）を持ちます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;hooks.&amp;lt;EventName&amp;gt;[].matcher  → フィルタ条件（省略可）
hooks.&amp;lt;EventName&amp;gt;[].hooks[]  → 実行するハンドラの配列
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;具体的な JSON は以下のようになります。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;hooks&quot;: {
    &quot;SessionStart&quot;: [
      {
        &quot;hooks&quot;: [
          {
            &quot;type&quot;: &quot;command&quot;,
            &quot;command&quot;: &quot;echo &apos;session started&apos;&quot;,
            &quot;timeout&quot;: 10
          }
        ]
      }
    ],
    &quot;Stop&quot;: [
      {
        &quot;hooks&quot;: [
          {
            &quot;type&quot;: &quot;command&quot;,
            &quot;command&quot;: &quot;echo &apos;session stopped&apos;&quot;,
            &quot;timeout&quot;: 10
          }
        ]
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;timeout&lt;/code&gt; はオプションで、デフォルトは600秒です。&lt;/p&gt;
&lt;h3&gt;動かない書き方&lt;/h3&gt;
&lt;p&gt;この入れ子構造を知らずに、イベント配列に直接ハンドラを並べる書き方をすると動きません。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;hooks&quot;: {
    &quot;SessionStart&quot;: [
      {
        &quot;type&quot;: &quot;command&quot;,
        &quot;command&quot;: &quot;echo &apos;session started&apos;&quot;
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;実際にこの書き方で動かず、ソースコードを読んで入れ子が必要なことに気づきました。公式ドキュメントがないため、ソースコードが唯一の正確な情報源です。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 対応イベント&lt;/h2&gt;
&lt;h3&gt;サポートされている3イベント&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;イベント&lt;/th&gt;
&lt;th&gt;発火タイミング&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SessionStart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;セッション開始・再開時&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UserPromptSubmit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ユーザーがプロンプトを送信した時&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Stop&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;エージェント応答完了時&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;ツール実行やサブエージェント関連のイベントは未実装です。&lt;/p&gt;
&lt;h3&gt;ハンドラタイプ&lt;/h3&gt;
&lt;p&gt;ハンドラタイプは「フックが発火したときに何を実行するか」の種類です。ソースコード（&lt;code&gt;codex-rs/hooks/src/engine/config.rs&lt;/code&gt;）上は &lt;code&gt;command&lt;/code&gt;・&lt;code&gt;prompt&lt;/code&gt;・&lt;code&gt;agent&lt;/code&gt; の3タイプが定義されていますが、現時点で実際に動作するのは &lt;code&gt;command&lt;/code&gt;（シェルコマンド実行）のみです。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;タイプ&lt;/th&gt;
&lt;th&gt;内容&lt;/th&gt;
&lt;th&gt;状態&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;command&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;シェルコマンドを実行する&lt;/td&gt;
&lt;td&gt;動作する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prompt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;エージェントのコンテキストにプロンプトを注入する&lt;/td&gt;
&lt;td&gt;未実装（&lt;code&gt;&quot;skipping prompt hook&quot;&lt;/code&gt; とログに表示される）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;agent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;別のエージェントを起動して処理させる&lt;/td&gt;
&lt;td&gt;未実装&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;async: true&lt;/code&gt;（非同期実行）も定義はありますが未実装です。&lt;code&gt;prompt&lt;/code&gt; が使えるようになれば「プロンプト送信時に毎回追加の指示を注入する」、&lt;code&gt;agent&lt;/code&gt; なら「応答完了後に別のエージェントでレビューを走らせる」といった使い方が考えられますが、現状は「イベント発火 → シェルコマンド実行」の一択です。&lt;/p&gt;
&lt;h3&gt;stdin に渡される JSON ペイロード&lt;/h3&gt;
&lt;p&gt;hook コマンドは &lt;code&gt;$SHELL -l -c &quot;&amp;lt;command&amp;gt;&quot;&lt;/code&gt; で実行され、&lt;strong&gt;stdin に JSON ペイロード&lt;/strong&gt; が渡されます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;session_id&quot;: &quot;019d07b0-...&quot;,
  &quot;cwd&quot;: &quot;/Users/user/project&quot;,
  &quot;hook_event_name&quot;: &quot;SessionStart&quot;,
  &quot;model&quot;: &quot;o3-pro&quot;,
  &quot;permission_mode&quot;: &quot;default&quot;,
  &quot;source&quot;: &quot;startup&quot;,
  &quot;transcript_path&quot;: null
}
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;フィールド&lt;/th&gt;
&lt;th&gt;説明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;session_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;セッションID（UUID v7）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cwd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;作業ディレクトリ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hook_event_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;イベント名&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;model&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;使用中のモデル&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;permission_mode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;承認ポリシー&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;source&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;開始種別（SessionStart のみ）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;transcript_path&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;会話履歴ファイルのパス（現状 null）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;イベントごとに追加されるフィールドがあります。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;フィールド&lt;/th&gt;
&lt;th&gt;イベント&lt;/th&gt;
&lt;th&gt;説明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;source&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SessionStart&lt;/td&gt;
&lt;td&gt;&lt;code&gt;startup&lt;/code&gt; / &lt;code&gt;resume&lt;/code&gt; / &lt;code&gt;clear&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;prompt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;UserPromptSubmit&lt;/td&gt;
&lt;td&gt;ユーザー入力テキスト&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;turn_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;UserPromptSubmit / Stop&lt;/td&gt;
&lt;td&gt;会話ターンの識別子&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;last_assistant_message&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stop&lt;/td&gt;
&lt;td&gt;最後のアシスタント応答&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stop_hook_active&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stop&lt;/td&gt;
&lt;td&gt;Stop フックがアクティブか&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;session_id&lt;/code&gt;、&lt;code&gt;cwd&lt;/code&gt;、&lt;code&gt;hook_event_name&lt;/code&gt;、&lt;code&gt;model&lt;/code&gt;、&lt;code&gt;permission_mode&lt;/code&gt; は全イベント共通です。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;4. 活用事例: 複数エージェントセッションの一元管理&lt;/h2&gt;
&lt;p&gt;自作のデスクトップアプリで、AI コーディングエージェントの Hooks を利用して複数セッションの状態を一元管理しています。&lt;code&gt;SessionStart&lt;/code&gt; / &lt;code&gt;Stop&lt;/code&gt; イベントを受け取ってセッション一覧を更新する仕組みです。&lt;/p&gt;
&lt;p&gt;Codex でもこの Hooks が使えることがわかったので、同じアプリで Codex のセッションも管理できるように拡張しました。&lt;/p&gt;
&lt;h3&gt;hooks.json で何を設定しているか&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;hooks.json&lt;/code&gt; にイベントとコマンドを書いておくと、そのイベントが発火したときにコマンドが実行されます。逆に言うと、&lt;code&gt;hooks.json&lt;/code&gt; が空だったり存在しなければ、フィーチャーフラグを有効にしても何も起きません。&lt;/p&gt;
&lt;p&gt;以下の設定例では、全イベントで同じことをしています。stdin に渡される JSON ペイロードを &lt;code&gt;$(cat)&lt;/code&gt; で読み取り、&lt;code&gt;curl&lt;/code&gt; で自作アプリの API にそのまま転送するだけです。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;hooks&quot;: {
    &quot;SessionStart&quot;: [
      {
        &quot;hooks&quot;: [
          {
            &quot;type&quot;: &quot;command&quot;,
            &quot;command&quot;: &quot;curl -s -X POST http://localhost:3000/api/hook -H &apos;Content-Type: application/json&apos; -d \&quot;$(cat)\&quot;&quot;,
            &quot;timeout&quot;: 10
          }
        ]
      }
    ],
    &quot;UserPromptSubmit&quot;: [
      {
        &quot;hooks&quot;: [
          {
            &quot;type&quot;: &quot;command&quot;,
            &quot;command&quot;: &quot;curl -s -X POST http://localhost:3000/api/hook -H &apos;Content-Type: application/json&apos; -d \&quot;$(cat)\&quot;&quot;,
            &quot;timeout&quot;: 10
          }
        ]
      }
    ],
    &quot;Stop&quot;: [
      {
        &quot;hooks&quot;: [
          {
            &quot;type&quot;: &quot;command&quot;,
            &quot;command&quot;: &quot;curl -s -X POST http://localhost:3000/api/hook -H &apos;Content-Type: application/json&apos; -d \&quot;$(cat)\&quot;&quot;,
            &quot;timeout&quot;: 10
          }
        ]
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;受け取る側のアプリは、JSON 内の &lt;code&gt;session_id&lt;/code&gt; と &lt;code&gt;hook_event_name&lt;/code&gt; を見てセッションの状態を更新します。この仕組みは他のツールの Hooks とも共通なので、同じ API エンドポイントで複数のエージェントツールを一元管理できています。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. 制限事項と今後の展望&lt;/h2&gt;
&lt;h3&gt;現時点の制限&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;開発中ステータス&lt;/strong&gt;: API が変更される可能性がある&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;イベント粒度が粗い&lt;/strong&gt;: ツール実行単位のフックがないため、作業中のリアルタイム進捗は取得できない&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;command タイプのみ&lt;/strong&gt;: &lt;code&gt;prompt&lt;/code&gt;、&lt;code&gt;agent&lt;/code&gt;、&lt;code&gt;async&lt;/code&gt; タイプのハンドラは未サポート&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;公式ドキュメントがない&lt;/strong&gt;: ソースコードを読まないと正確な仕様がわからない&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;OSS ならではの利点&lt;/h3&gt;
&lt;p&gt;制限が多い一方で、Codex は Apache License 2.0 の OSS であるため、Hooks の実装を直接ソースコードで確認できます。本記事の内容も &lt;code&gt;codex-rs/hooks/src/&lt;/code&gt; のソースを読んで特定したものです。仕様が不明な場合にソースコードが読めるのは大きな安心感があります。&lt;/p&gt;
&lt;h3&gt;今後の可能性&lt;/h3&gt;
&lt;p&gt;GitHub の &lt;a href=&quot;https://github.com/openai/codex/discussions/2150&quot;&gt;Discussion #2150&lt;/a&gt; では、Hooks 機能のリクエストスレッドに多数のコメントが寄せられており、コミュニティの関心の高さがうかがえます。今後ツールイベントの追加やハンドラタイプの拡充が期待されます。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;まとめ&lt;/h2&gt;
&lt;p&gt;Codex の Hooks はまだ開発中で機能も限定的ですが、フィーチャーフラグを有効にすれば今すぐ使えます。セッションの開始・終了を検知してコマンドを実行する程度の用途であれば、十分活用できそうです。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.openai.com/codex/changelog&quot;&gt;Codex Changelog&lt;/a&gt; - hooks engine 追加のアナウンス&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openai/codex&quot;&gt;openai/codex - GitHub&lt;/a&gt; - ソースコード（Apache License 2.0）&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/openai/codex/discussions/2150&quot;&gt;Discussion #2150: Hook would be a great feature&lt;/a&gt; - コミュニティのリクエストスレッド&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Claude Code の /loop 機能を触ってみた</title><link>https://zeroshotlog.com/blog/2026/03/11/claude-code-loop/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/2026/03/11/claude-code-loop/</guid><description>Claude Code の /loop で定期実行ジョブを自然言語で作成。API監視やissue監視の実用パターン、自動コンパクトと間隔設計の注意点、Hooksとの連携についてまとめた。</description><pubDate>Wed, 11 Mar 2026 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Claude Code の &lt;code&gt;/loop&lt;/code&gt; を使うと、自然言語で定期実行ジョブを作れる&lt;/li&gt;
&lt;li&gt;API の定期チェックや issue 監視など、開発フローの軽量な自動化に便利&lt;/li&gt;
&lt;li&gt;自動コンパクト中は定期実行が止まるため、コンテキスト消費量を意識した間隔設計が大事&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;はじめに&lt;/h2&gt;
&lt;p&gt;Claude Code の &lt;code&gt;/loop&lt;/code&gt; 機能は段階的にロールアウト中で、自分のアカウントでも使えるようになっていたので触ってみました。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. /loop の基本&lt;/h2&gt;
&lt;h3&gt;構文&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;/loop [間隔] &amp;lt;プロンプト&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;間隔を省略すると &lt;strong&gt;デフォルト10分&lt;/strong&gt; で実行されます。&lt;/p&gt;
&lt;h3&gt;間隔の指定パターン（3通り）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# パターン1: 先頭に間隔を記述
/loop 5m git status を確認して

# パターン2: 末尾に &quot;every&quot; で記述
/loop デプロイ状況を確認して every 20m

# パターン3: 間隔なし（デフォルト10分）
/loop テスト結果を確認して
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;指定できる単位は &lt;code&gt;s&lt;/code&gt;（秒）、&lt;code&gt;m&lt;/code&gt;（分）、&lt;code&gt;h&lt;/code&gt;（時間）、&lt;code&gt;d&lt;/code&gt;（日）です。ただし cron の最小粒度は1分なので、秒指定は繰り上げられます。&lt;/p&gt;
&lt;h3&gt;内部の仕組み&lt;/h3&gt;
&lt;p&gt;ユーザーが &lt;code&gt;/loop&lt;/code&gt; を実行すると、裏側では以下の3つのツールが動いています。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ツール&lt;/th&gt;
&lt;th&gt;役割&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CronCreate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ジョブの作成&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CronList&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ジョブの一覧表示&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CronDelete&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ジョブの削除&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;とはいえ、これらのツール名を直接知っている必要はありません。自然言語で十分操作できます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;「今動いてるジョブある？」 → CronList が呼ばれる
「ループ止めて」           → CronDelete が呼ばれる
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このあたりの体験は正直かなり良くて、「ジョブ管理を自然言語でできる」という点だけでも触ってみる価値があると感じました。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 実用ユースケース&lt;/h2&gt;
&lt;h3&gt;ユースケース1: API エンドポイントの定期チェック&lt;/h3&gt;
&lt;p&gt;外部 API のレスポンスを定期的にチェックして、変化があれば報告してもらうパターンです。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/loop 5m https://api.example.com/v1/status を確認して、前回と変化があれば報告して
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ステータス監視やレスポンス内容の変化検知など、シンプルな API チェックに向いています。&lt;/p&gt;
&lt;h3&gt;ユースケース2: GitHub issue 監視&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;/loop 5m gh issue list --label &quot;bug&quot; で新しいissueがないか確認して、
あれば内容を分析して対応方針を提案して
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;issue をトリガーにした開発フローとの相性が良さそうです。たとえば、新しい issue が立ったら自動で内容を分析して対応ブランチを作る、といった使い方もできるかもしれません。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 自動コンパクトと間隔設計&lt;/h2&gt;
&lt;h3&gt;認識しておくべきこと&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;/loop&lt;/code&gt; で情報取得系の処理を回すと、ループのたびに取得結果がコンテキストに蓄積されていきます。Claude Code では、会話履歴が長くなると古い内容を要約して圧縮する&lt;strong&gt;自動コンパクト&lt;/strong&gt;が走ります（&lt;code&gt;/compact&lt;/code&gt; で手動実行もできます）。&lt;/p&gt;
&lt;p&gt;この自動コンパクト自体は通常の Claude Code 利用でも発生するものですが、&lt;code&gt;/loop&lt;/code&gt; と組み合わせると少し気になる点があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;自動コンパクト中は処理がブロックされるため、その間のloop間隔がずれる&lt;/li&gt;
&lt;li&gt;自動コンパクト中に溜まった cron イベントが、完了後にまとめて発火することがある&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特に情報取得系の処理はコンテキスト消費が大きいため、短い間隔で回すとすぐに自動コンパクトが発生しやすいようです。&lt;code&gt;/loop&lt;/code&gt; にそこまで正確なタイミングを求めるものではないと思いますが、認識しておくと間隔設計の参考になりそうです。&lt;/p&gt;
&lt;h3&gt;間隔設計の目安&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ユースケース&lt;/th&gt;
&lt;th&gt;推奨間隔&lt;/th&gt;
&lt;th&gt;理由&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;軽量チェック（&lt;code&gt;git fetch&lt;/code&gt; 等）&lt;/td&gt;
&lt;td&gt;3〜5分&lt;/td&gt;
&lt;td&gt;コンテキスト消費が少ない&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API レスポンス監視&lt;/td&gt;
&lt;td&gt;5〜10分&lt;/td&gt;
&lt;td&gt;レスポンスサイズによる&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;テスト実行&lt;/td&gt;
&lt;td&gt;10〜30分&lt;/td&gt;
&lt;td&gt;実行時間自体が長く、結果も大きい&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;間隔の設定は「どれくらいの頻度で確認したいか」だけでなく、&lt;strong&gt;「1回のチェックでどれくらいコンテキストを消費するか」&lt;/strong&gt; も意識しておくと良さそうです。&lt;/p&gt;
&lt;p&gt;また、プロンプトに「変化がなければ『変化なし』とだけ報告して」と明記すると、無駄なコンテキスト消費を抑えられます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/loop 5m サイトを確認して、変化がなければ「変化なし」とだけ報告して
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;4. Hooks との連携&lt;/h2&gt;
&lt;h3&gt;問題: cron トリガーと手動入力を区別できない&lt;/h3&gt;
&lt;p&gt;Hooks と組み合わせて「cron 発火時だけ特定の処理を走らせたい」と考えるのは自然な発想です。しかし現状、&lt;code&gt;UserPromptSubmit&lt;/code&gt; イベントのペイロードには&lt;strong&gt;トリガーソースを示すフィールドがありません&lt;/strong&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;session_id&quot;: &quot;abc123&quot;,
  &quot;hook_event_name&quot;: &quot;UserPromptSubmit&quot;,
  &quot;prompt&quot;: &quot;送信されたテキスト&quot;
  // trigger_source のようなフィールドはない
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;cron が自動で発火したのか、ユーザーが手動入力したのか、Hook 側では判別できません。&lt;/p&gt;
&lt;h3&gt;回避策: プレフィックス方式&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;プロンプトにプレフィックスを付ける&lt;/strong&gt; ことで区別できるかもしれません。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/loop 5m [CRON] git fetch して新しいissueがあれば分析して
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hook 側では &lt;code&gt;[CRON]&lt;/code&gt; の有無で分岐します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# check_cron.py
import json, sys

data = json.load(sys.stdin)
prompt = data.get(&quot;prompt&quot;, &quot;&quot;)

if &quot;[CRON]&quot; in prompt:
    # cron トリガーの場合の処理
    print(&quot;Cron-triggered prompt detected&quot;, file=sys.stderr)
else:
    # 手動入力の場合の処理
    pass
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;正式にトリガーソースフィールドが追加されるまでは、こういった方法で対処することになりそうです。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. 制約と棲み分け&lt;/h2&gt;
&lt;h3&gt;/loop の制約&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;制約&lt;/th&gt;
&lt;th&gt;詳細&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;セッション依存&lt;/td&gt;
&lt;td&gt;セッション（ターミナル）を閉じると全ジョブが停止する&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3日間の期限切れ&lt;/td&gt;
&lt;td&gt;ジョブは作成から3日後に自動削除される&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;承認プロンプト&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git push&lt;/code&gt; 等の破壊的操作は確認ダイアログが出る&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;間隔精度&lt;/td&gt;
&lt;td&gt;cron ベースのため最小粒度は1分。実行時間分の遅延もある&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;同時実行上限&lt;/td&gt;
&lt;td&gt;1セッションあたり最大50ジョブ&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;GitHub Actions 等との棲み分け&lt;/h3&gt;
&lt;p&gt;この制約を踏まえると、&lt;code&gt;/loop&lt;/code&gt; は &lt;strong&gt;「軽量・一時的な自動化」&lt;/strong&gt; 向きだと感じました。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;用途&lt;/th&gt;
&lt;th&gt;/loop&lt;/th&gt;
&lt;th&gt;GitHub Actions / 従来 cron&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;数時間だけ状況を見守りたい&lt;/td&gt;
&lt;td&gt;向いている&lt;/td&gt;
&lt;td&gt;オーバーキル&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PR のマージまで監視したい&lt;/td&gt;
&lt;td&gt;向いている&lt;/td&gt;
&lt;td&gt;セットアップが面倒&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;本番環境の継続的な監視&lt;/td&gt;
&lt;td&gt;向いていない&lt;/td&gt;
&lt;td&gt;こちらが適切&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;チーム全体で共有する自動化&lt;/td&gt;
&lt;td&gt;向いていない&lt;/td&gt;
&lt;td&gt;こちらが適切&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;個人の開発フローの中で一時的に自動化したい場面では、外部 CI/CD なしで完結する手軽さが魅力的でした。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;まとめ&lt;/h2&gt;
&lt;h3&gt;/loop の良いところ&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;手軽さ&lt;/strong&gt;: 自然言語でジョブの作成・管理ができる&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;柔軟さ&lt;/strong&gt;: API チェック、issue 監視、テスト実行など多様な用途に対応&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;完結性&lt;/strong&gt;: 外部ツール不要で GitHub 操作まで自動化できそう&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;少し触ってみただけでも、「ちょっとした自動化を爆速で組める」便利さを感じました。間隔設計はコンテキスト消費量とセットで考えておくのが良さそうです。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://code.claude.com/docs/en/scheduled-tasks&quot;&gt;Claude Code 公式ドキュメント - Run prompts on a schedule&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://winbuzzer.com/2026/03/09/anthropic-claude-code-cron-scheduling-background-worker-loop-xcxwbn/&quot;&gt;Claude Code Gets Cron Scheduling to Run as a Background Worker - WinBuzzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@joe.njenga/claude-code-loop-create-new-native-autonomous-loops-that-work-29934d615402&quot;&gt;Claude Code /loop — How I Create New Native Autonomous Loops That Work! - Medium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Claude Code Agent Teams: 既存のスキル・エージェントのナレッジ活用法</title><link>https://zeroshotlog.com/blog/2026/02/13/claude-code-agent-teams/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/2026/02/13/claude-code-agent-teams/</guid><description>Agent Teamsの概要と従来のサブエージェントとの違い、既存のスキルやエージェント定義をAgent Teamsで活用する際の現状と工夫、トークン消費の実態を解説。</description><pubDate>Fri, 13 Feb 2026 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Agent Teamsは複数のClaude Codeインスタンスをチームとして協調動作させる仕組み。従来のサブエージェント（Task tool）とはアーキテクチャが異なる&lt;/li&gt;
&lt;li&gt;既存のスキルやエージェント定義のナレッジをAgent Teamsで活用するには、プロンプト内でファイルパスを明示的に指定して読み込ませる必要がある（構造的な指定方法は未提供）&lt;/li&gt;
&lt;li&gt;トークン消費はスキル方式の数倍。スキル方式で十分な作業はスキルで、並列実行の価値が明確な場合にAgent Teamsを試すのが現実的&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Agent Teamsの概要&lt;/h2&gt;
&lt;p&gt;2026年2月5日、Claude Opus 4.6と同時に公開された実験的プレビュー機能です。複数のClaude Codeインスタンスが「チーム」として並列で動きます。&lt;/p&gt;
&lt;p&gt;Claude Codeの拡張機構にはいくつかのレイヤーがあります。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;スキル（Skill tool）
  └── メインセッション内で展開・実行
       └── 内部でTask toolを使うこともある

サブエージェント（Task tool）
  └── 独立インスタンスとして起動
  └── subagent_type でカスタムエージェント定義を指定可能

Agent Teams（TeamCreate + SendMessage + TaskList等）
  └── チームメイト起動 = Task tool + チーム間通信・タスク共有
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;従来の&lt;strong&gt;サブエージェント&lt;/strong&gt;はTask toolで起動される独立インスタンスで、親→子のハブ&amp;amp;スポーク型です。子同士は会話できず、結果を親に返すだけ。Task toolにはビルトインで Bash / general-purpose / Explore / Plan の4タイプがあり、さらに &lt;code&gt;subagent_type&lt;/code&gt; でカスタムエージェント定義（&lt;code&gt;.claude/agents/*.md&lt;/code&gt;）を指定すると、定義に書かれたナレッジが自動的に読み込まれます。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agent Teams&lt;/strong&gt;はこのTask toolの上にチーム間通信やタスク共有の仕組みを追加したオーケストレーション層です。チームメイト同士が直接メッセージを送り合えるのが大きな違いです。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;【サブエージェント方式】
  親エージェント
    ├── Task → 子A（結果を親に返却）
    ├── Task → 子B（結果を親に返却）
    └── Task → 子C（結果を親に返却）
  ※ 子同士は会話できない。subagent_typeで定義を指定可能

【Agent Teams方式】
  Team Lead
    ├── Teammate A ←→ Teammate B
    ├── Teammate B ←→ Teammate C
    └── Teammate A ←→ Teammate C
  ※ チームメイト同士がメッセージを送り合える
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;なお、チームメイトも独立したClaude Codeインスタンスなので、仕組み上はTask toolでサブエージェントを呼び出せるはずです（公式の制限は「ネストチーム不可」であり、Task tool単体の利用は制限されていません）。しかし実際に試したところ&lt;strong&gt;うまく動作しませんでした&lt;/strong&gt;。これができれば既存のカスタムエージェント定義をそのまま活用できるので、今後の改善に期待したいところです。&lt;/p&gt;
&lt;p&gt;以下は7人のレビュアーがtmux split panesで並列動作している様子です。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2026/02/13/agent-teams-tmux-split-panes.png&quot; alt=&quot;Agent Teamsでコードレビューチームが並列動作している画面&quot; /&gt;&lt;/p&gt;
&lt;p&gt;チーム全体で共有するタスクリストがあり、タスクの状態管理や依存関係の定義ができます。ブロックが解消されると空いたチームメイトが次のタスクを自律的にクレームする仕組みです。ただしファイルレベルのロック機構はないので、同じファイルへの同時書き込みには注意が必要です。&lt;/p&gt;
&lt;h3&gt;有効化と使い方&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;settings.json&lt;/code&gt;で有効化します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// ~/.claude/settings.json
{
  &quot;env&quot;: {
    &quot;CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS&quot;: &quot;1&quot;
  },
  &quot;teammateMode&quot;: &quot;auto&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;teammateMode&lt;/code&gt; の &lt;code&gt;&quot;auto&quot;&lt;/code&gt; はtmux内ならsplit panes、それ以外ではin-process（Shift+Up/Downで切替）を自動選択します。使い方は自然言語で指示するだけです。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;このプロジェクトのPR #42をレビューするチームを作って。
3人のレビュアーをスポーンして:
- セキュリティ担当
- パフォーマンス担当
- テストカバレッジ担当
それぞれレビューして結果を報告させて。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;前提として、Max 5x ($100/月) 以上のプランを推奨します。Proプラン ($20/月) では制限に達しやすいです。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;既存ナレッジの活用: 自然言語プロンプトの現状&lt;/h2&gt;
&lt;p&gt;Agent Teamsを使ううえで知っておくべき点があります。&lt;/p&gt;
&lt;p&gt;Claude Codeにはスキル（&lt;code&gt;SKILL.md&lt;/code&gt;）やカスタムエージェント（&lt;code&gt;.claude/agents/*.md&lt;/code&gt;）といった既存の拡張機構があります。単体セッションでは自動的に読み込まれますし、Task toolのサブエージェントでも &lt;code&gt;subagent_type&lt;/code&gt; で名前を指定するだけで使えます。&lt;/p&gt;
&lt;p&gt;ところが、Agent Teamsではチームメイトに「このスキルを使え」「このエージェント定義で動け」といった構造的な指定方法が&lt;strong&gt;現時点では提供されていません&lt;/strong&gt;。チームメイトに既存の定義ファイルを活用させたい場合、プロンプト内でファイルパスを書いて「このファイルを読め」と自然言語で指示する形になります。&lt;/p&gt;
&lt;h3&gt;パスを細かく指定するしかない&lt;/h3&gt;
&lt;p&gt;たとえば、コードレビュー用のエージェント定義を &lt;code&gt;~/.claude/agents/&lt;/code&gt; に用意しているとします。Agent Teamsでこれを活用するには、ディレクトリ構造とファイルパスをプロンプトに書き出して、各チームメイトに「どのファイルを読み、どう使うか」を伝える必要があります。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;### ディレクトリ構造

~/.claude/
├── agents/                       # レビュー観点の定義
│   ├── review-architecture.md
│   ├── review-naming.md
│   └── review-frontend.md
└── knowledge/                    # 参考ナレッジ
    ├── architecture/
    │   ├── patterns.md
    │   └── anti-patterns.md
    └── naming/
        └── conventions.md

### チームメイトの読み込み手順

1. `~/.claude/agents/review-{自分の担当}.md` を読み、
   レビュー観点・出力形式を把握する
2. 定義内に参照ファイルがあれば、対応するナレッジを読み込む
3. ナレッジの内容をレビューの根拠として活用する
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;スキル方式やTask tool方式なら、エージェント定義のパスや読み込み順は仕組み側が処理してくれます。Agent Teamsでは&lt;strong&gt;プロンプトの中で自分で書く&lt;/strong&gt;しかないのが現状です。&lt;/p&gt;
&lt;h3&gt;スキル方式との比較&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;観点&lt;/th&gt;
&lt;th&gt;スキル / Task tool&lt;/th&gt;
&lt;th&gt;Agent Teams&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;エージェント定義の指定&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;subagent_type&lt;/code&gt; で名前指定&lt;/td&gt;
&lt;td&gt;プロンプト内でファイルパスを記述&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ナレッジの読み込み&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;定義ファイル内の参照で自動&lt;/td&gt;
&lt;td&gt;プロンプト内で手順を記述&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;出力先の管理&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;スキル内で定義済み&lt;/td&gt;
&lt;td&gt;プロンプト内で個別に指定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;実行制御&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;スキルのフローに従う&lt;/td&gt;
&lt;td&gt;Phase構造などをプロンプトで設計&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;つまり、スキルやエージェント定義として蓄積してきたナレッジがあっても、Agent Teamsで活用するには&lt;strong&gt;その内容を自然言語プロンプトに変換する作業&lt;/strong&gt;が必要です。将来的にAgent Teamsからスキルやエージェント定義を直接参照できるようになれば解消されるはずですが、2026年2月時点ではまだその段階にありません。&lt;/p&gt;
&lt;h2&gt;プロンプト設計のポイント&lt;/h2&gt;
&lt;p&gt;Agent Teamsの公式ドキュメントとコミュニティの知見から、押さえておくべきポイントをまとめます。&lt;/p&gt;
&lt;h3&gt;チームメイトへのコンテキスト共有&lt;/h3&gt;
&lt;p&gt;チームメイトはリーダーの会話履歴を引き継がず、独立したインスタンスとして起動します。CLAUDE.mdやMCPサーバーは自動で読み込まれますが、それ以外の情報はスポーン時のプロンプトに含めるか、ファイル経由で渡す必要があります。&lt;/p&gt;
&lt;h3&gt;出力ファイルの分離&lt;/h3&gt;
&lt;p&gt;ファイルレベルのロック機構がないので、各チームメイトが異なるファイルセットを担当するように設計してください。&lt;/p&gt;
&lt;h3&gt;Phase構造による段階制御&lt;/h3&gt;
&lt;p&gt;プロンプトをPhaseに分けて「準備 → 並列実行 → 統合 → 完了」の流れを明示すると、Team Leadの動きを制御しやすくなります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Delegate Mode（Shift+Tab）&lt;/strong&gt; も有効です。リーダーのツール実行権限を制限して、コーディネーションに専念させるモードですが、2026年2月時点でチームメイトがツールアクセスを失うバグが報告されています（&lt;a href=&quot;https://github.com/anthropics/claude-code/issues/24073&quot;&gt;GitHub Issue #24073&lt;/a&gt;）。&lt;/p&gt;
&lt;h2&gt;サンプル: Agent Teamsでコードレビューするプロンプト&lt;/h2&gt;
&lt;p&gt;上記のポイントを反映した、Agent Teams版コードレビュープロンプトのサンプルです。既存のエージェント定義ファイルをチームメイトに読み込ませる構成例になっています。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;前提&lt;/strong&gt;: &lt;code&gt;~/.claude/agents/&lt;/code&gt; にエージェント定義ファイルを配置していることを想定しています。定義ファイルがなくてもチームは起動しますが、レビューの観点や出力形式は定義の内容に依存します。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;lt;details open&amp;gt;
&amp;lt;summary&amp;gt;エージェント定義ファイルの雛形（簡易サンプル）&amp;lt;/summary&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;review-architecture.md（アーキテクチャ担当）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Architecture Reviewer

## 役割
アーキテクチャ・設計レベルのコードレビューを行う。

## レビュー観点
- ディレクトリ構造とレイヤー分離の妥当性
- 依存関係の方向
- 単一責任の原則の遵守
- 過度な抽象化や不要な複雑性

## スコアリング
各指摘に重要度タグを付与:
- [Critical]: 重大な問題
- [Warning]: 改善が望ましい懸念
- [Suggestion]: より良い設計への提案

## 出力形式
- **[重要度]** ファイル名:行番号 - 指摘内容
  - 理由: なぜ問題か
  - 改善案: どう修正すべきか
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;review-naming.md（命名規約担当）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Naming Reviewer

## 役割
変数・関数・クラス・ファイル名の命名規約をレビューする。

## レビュー観点
- 言語別の命名規約（camelCase / snake_case / PascalCase）の遵守
- 名前から役割が推測できるか（意味の明確さ）
- 略語の一貫性（例: btn vs button の混在）
- Boolean変数のプレフィックス（is / has / should）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;review-frontend.md（フロントエンド担当）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Frontend Reviewer

## 役割
React/Vue等のフロントエンド固有パターンをレビューする。

## レビュー観点
- コンポーネント分割の粒度とProps設計
- 状態管理パターンの適切性
- パフォーマンス（不要な再レンダリング、メモ化の過不足）
- アクセシビリティ（セマンティックHTML、ARIA属性）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;lt;/details&amp;gt;&lt;/p&gt;
&lt;h3&gt;プロンプト全文&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;このリポジトリでエージェントチームを使ってコードレビューを実行してください。
手順に従い、自律的に進めてください。判断に迷う場合のみユーザーに確認してください。

## 参照ファイルガイド

レビューに必要な定義ファイルとナレッジが `~/.claude/` 配下にあります。
各チームメイトは自分の担当に対応するファイルを読み込んで活用してください。

### ディレクトリ構造

~/.claude/
├── agents/                       # レビュー観点の定義（観点・出力形式）
│   ├── review-architecture.md    # アーキテクチャレビュー
│   ├── review-naming.md          # 命名規約レビュー
│   └── review-frontend.md        # フロントエンド固有（条件付き）
│
└── knowledge/                    # 参考ナレッジ
    ├── architecture/
    │   ├── patterns.md
    │   └── anti-patterns.md
    ├── naming/
    │   └── conventions.md
    └── frontend/
        └── best-practices.md

### チームメイトの読み込み手順

1. `~/.claude/agents/review-{自分の担当}.md` を読み、
   レビュー観点・出力形式を把握する
2. 定義内に参照ファイルがあれば、
   `~/.claude/knowledge/` から対応するファイルを読み込む
3. ナレッジの内容をレビューの根拠として活用する

---

## 手順

### Phase 0: レビュー対象の確認

ユーザーに以下を確認してください:

1. **レビュー対象**: 特定ファイル / 直近コミット / プロジェクト全体
2. **レビュー深度**: フル（デフォルト） / クイック（Criticalのみ）

### Phase 1: 準備（Team Lead が実行）

1. スクラッチディレクトリを作成:
   `.claude/code-review-team/.scratch/{YYYY-MM-DD-HHmm}/`

2. 「直近コミット」が選ばれた場合のみ差分コンテキストを生成:
   - `git diff HEAD~N` の結果を `{スクラッチ}/diff-context.md` に保存

3. テックスタック検出を実行:
   `package.json`、`requirements.txt` 等からフレームワークを特定し、
   結果を `{スクラッチ}/stack-detection.md` に出力

4. 検出結果を読み、Phase 2 のチーム構成を決定

### Phase 2: チーム作成 &amp;amp; 並列レビュー

チーム名 &quot;code-review&quot; でチームを作成し、
以下のチームメイトを並列でスポーンしてください。

#### 必須メンバー（常に起動）

1. **architecture-reviewer**
   - 役割: アーキテクチャ・設計レベルのレビュー
   - 定義: `~/.claude/agents/review-architecture.md`
   - 出力先: `{スクラッチ}/architecture-review.md`

2. **naming-reviewer**
   - 役割: 命名規約のレビュー
   - 定義: `~/.claude/agents/review-naming.md`
   - 出力先: `{スクラッチ}/naming-review.md`

#### 条件付きメンバー（スタック検出結果に基づき追加）

- **frontend-reviewer** — React/Vue等の検出時
  定義: `~/.claude/agents/review-frontend.md`
  出力先: `{スクラッチ}/frontend-review.md`

#### 全チームメイト共通ルール

- まず `{スクラッチ}/stack-detection.md` を読み込むこと
- 自分のエージェント定義を読み、観点・出力形式に従うこと
- 定義内に参照ファイルがあれば `~/.claude/knowledge/` から読み込むこと
- レビュー結果はインクリメンタルに出力先ファイルに書き込むこと
- 各指摘に重要度タグを付与: [Critical] / [Warning] / [Suggestion]
- 完了したら Team Lead にメッセージで報告:
  「レビュー完了。Critical: X件, Warning: Y件。詳細は {出力先} を参照」

### Phase 3: レポート統合

全チームメイトの完了を確認したら:

1. `{スクラッチ}/` 配下の全レビューファイルを読み込み、
   重複を排除し優先度を統一して統合レポートを生成
   **注意**: 統合対象は今回のスクラッチ内のファイルのみ
2. 出力先: `docs/code-review-team/{YYYY-MM-DD-HHmm}-review.md`

### Phase 4: 完了

1. チーム &quot;code-review&quot; を削除
2. レポートをユーザーに提示し、修正方針を確認:
   - 全指摘を一括修正
   - Critical/Warning のみ修正
   - 修正は自分で行う（レポートのみ）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;このサンプルのポイントは、&lt;strong&gt;プロンプト冒頭にディレクトリ構造を記載し、各チームメイトに読み込むべきファイルのパスを明示している&lt;/strong&gt;点です。スキル方式なら不要な記述ですが、Agent Teamsでは現状これが必要です。&lt;/p&gt;
&lt;h2&gt;トークン消費について&lt;/h2&gt;
&lt;p&gt;Agent Teamsのトークン消費はかなり大きいです。各チームメイトが独立したClaude Codeインスタンスとして動作するので、チーム人数に比例してコストが増えます。&lt;/p&gt;
&lt;p&gt;Max 20x（$200/月）プランで、5人以上のチームメイトを含むチームを1時間に2-3回実行した場合、Max使用量の約4%を消費しました。各チームメイトが独立したインスタンスなので、人数が増えるほどコストは膨らみます。&lt;/p&gt;
&lt;p&gt;正直なところ、&lt;strong&gt;スキル方式（Task tool）とAgent Teamsで最終的なアウトプットの品質にどれだけ差が出るかは、数回使った程度では測りきれていません&lt;/strong&gt;。並列実行による速度面の利点は体感できますが、その差に見合う品質向上が得られるかは継続的な検証が必要です。&lt;/p&gt;
&lt;p&gt;チームメイトにSonnetを指定すればコストは抑えられますが、Proプラン ($20/月) では現実的に厳しく、Max ($100-200/月) が最低ラインだと思います。&lt;/p&gt;
&lt;h3&gt;週次リセットの活用&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Claude Codeの使用量制限は7日間のローリングウィンドウでリセットされます。&lt;code&gt;/usage&lt;/code&gt; コマンドで次のリセットタイミングを確認できるので、余裕がある時期にAgent Teamsを試すと計画的に組み込みやすくなります。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;制限事項（2026年2月時点）&lt;/h2&gt;
&lt;p&gt;Agent Teamsは実験的プレビュー段階です。主な制限をまとめておきます。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;制限&lt;/th&gt;
&lt;th&gt;影響&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;セッション再開不可&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/resume&lt;/code&gt;でチームメイトが復元されない&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ファイルロックなし&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;同じファイルの同時編集で上書きが発生しうる&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1セッション1チーム&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;複数チームの同時運用不可&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ネストチーム不可&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;チームメイトがサブチームを作れない&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;split panesの制約&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;VS Code統合ターミナル、Windows Terminal、Ghostty非対応&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;シャットダウンが遅い&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;チームメイトが現在のリクエストやツール呼び出しを完了するまで待つため時間がかかる&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;既存ナレッジの直接参照なし&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;スキルやエージェント定義をAgent Teamsから構造的に指定する方法がない&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;まとめ&lt;/h2&gt;
&lt;p&gt;Agent Teamsは、チームメイト間の直接通信と共有タスクリストによる自律的な連携を実現する仕組みです。&lt;/p&gt;
&lt;p&gt;ただ、現時点ではチーム構成のすべてを自然言語プロンプトで記述する必要があり、既存のスキルやエージェント定義を活用するにはファイルパスを細かく指定するしかありません。スキル方式なら仕組み側がやってくれていたことを、プロンプトの中で自分で書くことになります。&lt;/p&gt;
&lt;p&gt;トークン消費も大きく、スキル方式との明確な効果の差はまだ十分に検証できていません。今後スキルやエージェント定義との統合が進むことに期待しつつ、現時点では「スキル方式で十分な作業はスキルで、並列実行の価値が明確な場合にAgent Teamsを試す」という使い分けが現実的だと思います。&lt;/p&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://code.claude.com/docs/en/agent-teams&quot;&gt;Orchestrate teams of Claude Code sessions - Claude Code公式ドキュメント&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.anthropic.com/news/claude-opus-4-6&quot;&gt;Introducing Claude Opus 4.6 - Anthropic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://zeroshotlog.com/images/2026/02/13/agent-teams-hero.png" length="0" type="image/png"/></item><item><title>Lost in the Middle — LLMの位置バイアスを克服するプロンプト設計</title><link>https://zeroshotlog.com/blog/2026/02/04/llm-prompt-design-pitfalls/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/2026/02/04/llm-prompt-design-pitfalls/</guid><description>LLMは長いプロンプトの中間部分を見落としやすい（Lost in the Middle問題）。原因と、末尾チェックリスト・サンドイッチ戦略・XMLタグ構造化など実務で使える対策手法を紹介。</description><pubDate>Wed, 04 Feb 2026 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;LLMは長いプロンプトの&lt;strong&gt;中間部分の情報を見落としやすい&lt;/strong&gt;（Lost in the Middle問題）&lt;/li&gt;
&lt;li&gt;主要な原因の一つはRoPE（Rotary Position Embedding）の長期減衰効果にあり、因果的注意マスクや学習データの偏りなど複数の構造的要因が関与している&lt;/li&gt;
&lt;li&gt;対策として&lt;strong&gt;末尾チェックリストパターン&lt;/strong&gt;、&lt;strong&gt;サンドイッチ戦略&lt;/strong&gt;、&lt;strong&gt;XMLタグ構造化&lt;/strong&gt;など複数の手法が存在する&lt;/li&gt;
&lt;li&gt;手法ごとにトークンコストや適用場面が異なるため、状況に応じた使い分けが重要&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;1. Lost in the Middle問題とは&lt;/h2&gt;
&lt;h3&gt;LLMの位置バイアス&lt;/h3&gt;
&lt;p&gt;LLMを使ったアプリケーション開発で、「プロンプトに書いた指示が無視される」という経験はないでしょうか。特に、システムプロンプトが数百行に及ぶ複雑なアプリケーションでは、この問題が頻繁に発生します。&lt;/p&gt;
&lt;p&gt;これは&lt;strong&gt;Lost in the Middle&lt;/strong&gt;と呼ばれる現象です。Liu et al. (2023) の研究 &quot;&lt;a href=&quot;https://arxiv.org/abs/2307.03172&quot;&gt;Lost in the Middle: How Language Models Use Long Contexts&lt;/a&gt;&quot; で体系的に報告されました。&lt;/p&gt;
&lt;p&gt;この研究の核心的な発見は、LLMが&lt;strong&gt;U字型の性能曲線&lt;/strong&gt;を示すことです。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;性能
 ▲
 │  ★                                    ★
 │   ★                                 ★
 │    ★★                            ★★
 │      ★★★                     ★★★
 │         ★★★★★★★★★★★★★
 │
 └──────────────────────────────────────► 情報の位置
   先頭        中間（性能低下）        末尾
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;具体的な数値として、複数の文書を参照して質問に回答させるタスクにおいて、中間に配置された情報の利用性能は先頭・末尾と比較して&lt;strong&gt;30%以上低下&lt;/strong&gt;するケースが報告されています（Liu et al., 2023。低下幅はモデルやタスクにより異なります）。&lt;/p&gt;
&lt;h3&gt;なぜ中間の情報が失われるのか — RoPEの長期減衰効果&lt;/h3&gt;
&lt;p&gt;この現象の主要な原因の一つは、多くのLLMで採用されている&lt;strong&gt;RoPE（Rotary Position Embedding）の長期減衰効果&lt;/strong&gt;にあると考えられています。なお、位置バイアスはRoPEだけでなく、因果的注意マスク——各トークンが自分より後ろのトークンを参照できないよう制限する三角行列状のマスク——の構造や、学習データにおける位置分布の偏りなど、複数の要因が複合的に関与していると指摘されています。&lt;/p&gt;
&lt;p&gt;RoPEは、トークン間の相対位置に基づいて注意（Attention）の強度を調整する仕組みです。通常のTransformerは「このトークンが入力の何番目にあるか」を絶対位置として記憶しますが、RoPEは代わりに「2つのトークンがどれだけ離れているか」という相対的な距離を、ベクトルの回転角度として表現します。この回転角度は距離が離れるほど大きくなり、結果として遠いトークン同士の注意スコアが自然に減衰します。&lt;/p&gt;
&lt;p&gt;プロンプトの先頭の指示は直近の生成トークンからは「遠い」位置にあります。しかし、因果的言語モデル（causal language model）——つまり左から右へ1トークンずつ順に生成し、各トークンはそれより前のトークンしか参照できないモデル——の特性により、先頭のトークンは後続の全てのトークンの処理に繰り返し参照されます。この累積的な影響により、結果的に先頭と末尾の情報は強く保持されます。&lt;/p&gt;
&lt;p&gt;一方で、中間のトークンは先頭ほどの累積的な影響力を持たず、かつ末尾ほど生成トークンに近くもないため、いわば「注意の谷間」に陥ります。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 実務で遭遇する具体例&lt;/h2&gt;
&lt;h3&gt;どのくらいの長さで問題になるのか&lt;/h3&gt;
&lt;p&gt;最新のモデルでは、数十行程度のプロンプトでこの問題が顕在化することはほぼありません。筆者の体感では、&lt;strong&gt;数百行規模のシステムプロンプト&lt;/strong&gt;——たとえばRAGで大量のコンテキストを注入するケースや、複雑なルールセットを持つエージェント型アプリケーション——で初めて影響が目立ち始めます。&lt;/p&gt;
&lt;p&gt;この問題は最新モデルでも解消されていません。Modarressi et al. (2025) の研究 &quot;&lt;a href=&quot;https://arxiv.org/abs/2502.05167&quot;&gt;NoLiMa: Long-Context Evaluation Beyond Literal Matching&lt;/a&gt;&quot;（ICML 2025）では、GPT-4oやGemini 1.5 Pro、Claude 3.5 Sonnetを含む13モデル中11モデルが、32Kトークンのコンテキストにおいて短文時のベースライン性能の50%未満にまで低下しました。その後の追加評価ではGPT-4.1やGemini 2.5 Flashでも同様の傾向が確認されています。&lt;/p&gt;
&lt;p&gt;また、Chroma Researchの研究 &quot;&lt;a href=&quot;https://research.trychroma.com/context-rot&quot;&gt;Context Rot: How Increasing Input Tokens Impacts LLM Performance&lt;/a&gt;&quot;（2025年7月）では、18モデルを対象に長文コンテキストでの性能劣化が検証されています。興味深いのはモデルファミリーごとに劣化パターンが異なる点で、GPTモデルは誤った回答を自信を持って返す（ハルシネーション）傾向が強いのに対し、Claudeモデルは不確実な場合に回答を控える（棄権する）傾向が見られました。なお、同研究ではLiu et al.が報告したU字型の検索パターンは一貫しては観察されなかったとも報告されており、位置バイアスの現れ方はタスクやモデルによって異なる可能性があります。&lt;/p&gt;
&lt;p&gt;筆者もGPT-4.1 miniで同様の現象を確認しており、モデルの世代が進んでも位置バイアスは&lt;strong&gt;緩和されつつあるが根本的には解消されていない&lt;/strong&gt;のが現状です。&lt;/p&gt;
&lt;p&gt;以下に示す例は構造を理解するために簡略化したものですが、実際にはこうしたセクションが何十個も並び、全体で数百行〜数千トークンに膨らんだときに問題が発生します。&lt;/p&gt;
&lt;h3&gt;システムプロンプトでの中間ルール無視&lt;/h3&gt;
&lt;p&gt;たとえば、以下のようなセクション構成を持つシステムプロンプトが数百行に及ぶ場合を考えます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;あなたはカスタマーサポートアシスタントです。   ← 先頭付近: 遵守される

## 基本ルール
- 丁寧な言葉遣いで応答してください
- ユーザーの名前を使って応答してください

... （数十セクションが続く）

## 応答フォーマット                               ← 中間に埋もれる
- 回答は3文以内にまとめてください
- 箇条書きを使用してください

## データ参照ガイド                               ← 中間に埋もれる
- 価格情報は必ずデータベースを参照すること

... （さらに多数のセクションが続く）

## 禁止事項                                       ← 末尾付近: 遵守される
- 競合他社の製品を推奨しないでください
- 個人情報を聞き出さないでください
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;先頭の「基本ルール」と末尾の「禁止事項」は遵守されるのに、中間に埋もれた「応答フォーマット」や「データ参照ガイド」のセクションが無視される——プロンプトが長くなるほど、このパターンに遭遇しやすくなります。&lt;/p&gt;
&lt;h3&gt;コード生成タスクでの要件欠落&lt;/h3&gt;
&lt;p&gt;コード生成タスクでも、要件セクションが多い場合に同様の問題が発生します。先頭の技術スタック指定や末尾のレスポンス形式は遵守されるのに、中間に記載したバリデーション要件やエラーハンドリング要件が丸ごと抜け落ちるケースです。プロンプト全体が短ければ問題にならないものの、コンテキストや例示が増えて全体が長くなると影響が出始めます。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. 末尾チェックリストパターン&lt;/h2&gt;
&lt;h3&gt;パターンの概要&lt;/h3&gt;
&lt;p&gt;Lost in the Middle問題に対する最も実践的な対策が、&lt;strong&gt;末尾チェックリストパターン&lt;/strong&gt;です。プロンプトの末尾にチェックリスト形式で重要な指示を再掲し、LLMに「二重確認」を促します。&lt;/p&gt;
&lt;h3&gt;Before / After&lt;/h3&gt;
&lt;p&gt;以下は数百行のシステムプロンプトの構造を簡略化したものです。実際には各セクションがさらに詳細で、間に多くのルールやコンテキストが挟まります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Before（中間の指示が埋もれる構成）:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;あなたはコードレビューアシスタントです。

## レビュー観点
...（5項目）

... （多数のセクション: コーディング規約、言語別ルール、例外ケース...）

## 出力フォーマット                    ← 中間に埋もれる
- 重要度を「高/中/低」で分類
- 各指摘に修正案のコード例を添付
- 影響範囲を明記

... （さらにセクションが続く）

## レビュー対象
{code}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;After（末尾にチェックリストを追加）:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;あなたはコードレビューアシスタントです。

## レビュー観点
...（5項目）

... （多数のセクション: コーディング規約、言語別ルール、例外ケース...）

## 出力フォーマット
- 重要度を「高/中/低」で分類
- 各指摘に修正案のコード例を添付
- 影響範囲を明記

... （さらにセクションが続く）

## レビュー対象
{code}

---
## 出力前の最終チェックリスト           ← ここを追加
回答を出力する前に、以下の全項目を確認してください:
- [ ] 5つの観点全てに言及したか
- [ ] 各指摘に重要度（高/中/低）を付与したか
- [ ] 各指摘に修正案のコード例を添付したか
- [ ] 影響範囲を明記したか
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;末尾にチェックリストを配置することで、LLMは生成直前にこれらの条件を「再認識」します。U字型性能曲線の特性を逆手に取り、末尾という最も注意が向きやすい位置に確認項目を置くわけです。&lt;/p&gt;
&lt;p&gt;筆者の経験では、このパターンを導入してから中間部の指示が無視される頻度は体感的にかなり減りました。特に「出力フォーマット」のようなプロンプト中間部に記載しがちな指示に対して効果を感じています。&lt;/p&gt;
&lt;h3&gt;実体験: 構造化JSON出力での改善&lt;/h3&gt;
&lt;p&gt;筆者が実際にこの問題に直面したのは、LangChainでOpenAIモデルを使い、ユーザーの自由入力テキストから構造化されたJSONを抽出するタスクでした。LangChainの &lt;code&gt;with_structured_output&lt;/code&gt; を使用しており、Pydanticモデルの &lt;code&gt;Field(description=...)&lt;/code&gt; でスキーマとフィールドの説明を定義しつつ、プロンプト側にも各フィールドの抽出ルール（必須/任意の区別、デフォルト値、フォーマット指定など）を別途記載する構成です。&lt;/p&gt;
&lt;p&gt;フィールド数が多くなるにつれて、プロンプト中間部に記載した特定フィールドの抽出精度が目に見えて落ちていきました。先頭付近に書いたフィールドのルールと、末尾付近のルールは問題なく適用されるのに、中間に埋もれたフィールドだけが &lt;code&gt;null&lt;/code&gt; や不正確な値で返ってくる——まさにU字型曲線の通りの挙動です。&lt;/p&gt;
&lt;p&gt;この問題に対して、プロンプト末尾（ユーザー入力の後）にリマインダーを追加したところ、該当フィールドの抽出精度が明確に改善しました。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field

# Pydanticスキーマ定義（descriptionもLLMに渡される）
class TaskSchema(BaseModel):
    category: str = Field(description=&quot;定義済みカテゴリから選択&quot;)
    priority: int = Field(description=&quot;1-5の整数&quot;)
    due_date: str | None = Field(description=&quot;ISO 8601形式の日付、不明ならnull&quot;)

prompt = ChatPromptTemplate.from_messages([
    (&quot;system&quot;, &quot;&quot;&quot;あなたはタスク情報を抽出するアシスタントです。
ユーザーの入力から構造化データを抽出してください。&quot;&quot;&quot;),
    (&quot;human&quot;, &quot;&quot;&quot;{user_input}

## 出力前の確認
以下のフィールドが正しく抽出されていることを確認してから出力してください:
- &quot;category&quot;: 必ず定義済みカテゴリから選択すること（推測しない）
- &quot;priority&quot;: 1-5の整数であること
- &quot;due_date&quot;: ISO 8601形式であること（入力に日付がなければnull）&quot;&quot;&quot;),
])

structured_llm = llm.with_structured_output(TaskSchema)
messages = prompt.format_messages(user_input=user_input)
result = structured_llm.invoke(messages)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;この末尾リマインダーの追加で注目すべきは、他のフィールド（もともと正しく抽出できていたもの）の出力にほとんど影響がなかった点です。同じ指示をプロンプト中間部の該当フィールド定義を強調する形で追記した場合は、周辺フィールドの抽出にも微妙なブレが生じることがありましたが、末尾への配置ではそういった副作用がほぼ見られませんでした。末尾チェックリストは、既存の出力を壊さずにピンポイントで弱い箇所を補強できるという利点があります。&lt;/p&gt;
&lt;p&gt;ここで一つ注意点があります。プロンプト側の抽出ルールを修正したとき、Pydanticモデルの &lt;code&gt;Field(description=...)&lt;/code&gt; も合わせて更新しないと、プロンプトとスキーマ定義で矛盾が生じ、せっかくの修正の精度が落ちることがありました。&lt;code&gt;with_structured_output&lt;/code&gt; はスキーマの &lt;code&gt;description&lt;/code&gt; もLLMに渡すため、プロンプトとスキーマの両方を同期して更新する必要があります。地味ですが実務では見落としやすいポイントです。&lt;/p&gt;
&lt;p&gt;なお、LangChainにおけるドメイン固有知識のプロンプト注入に関しては、LangChainブログの記事 &quot;&lt;a href=&quot;https://blog.langchain.com/incorporating-domain-specific-knowledge-in-sql-llm-solutions/&quot;&gt;Incorporating domain specific knowledge in SQL-LLM solutions&lt;/a&gt;&quot; でも、静的なプロンプトではなく動的にFew-shot exampleを検索して注入するアプローチが紹介されています。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A more powerful approach is to have a robust dataset of good examples, and &lt;em&gt;dynamically&lt;/em&gt; include those which are relevant to the user question.&lt;/p&gt;
&lt;p&gt;（より強力なアプローチは、良質なexampleの堅牢なデータセットを用意し、ユーザーの質問に関連するものを動的に含めることである。）&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;具体的には、ベクトルデータベースを活用したカスタムRetriever Toolを作成し、ユーザーの質問に意味的に類似したexampleを動的に取得する方法が示されています。フィールド数が多い構造化出力タスクでは、全ルールを静的に並べるよりも、入力内容に応じて関連するフィールドの抽出ルールを動的に選択・配置する方がLost in the Middleの影響を受けにくいかもしれません。&lt;/p&gt;
&lt;h3&gt;末尾チェックリストが効きにくいケース&lt;/h3&gt;
&lt;p&gt;ただし、この手法にも限界があります。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;チェック項目が多すぎると効果が低下する&lt;/strong&gt;: 研究 &quot;&lt;a href=&quot;https://openreview.net/forum?id=R6q67CDBCH&quot;&gt;Curse of Instructions&lt;/a&gt;&quot;（ManyIFEval, 2024; ICLR 2025）によれば、個別の指示に90%従えるLLMでも、10個の指示を同時に満たす成功率は理論上 0.9^10 ≒ 約35% にまで低下します（実際の値はモデルにより異なります）。チェックリストが長くなると、リスト内で再び「Lost in the Middle」が発生するリスクもあります&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;指示が曖昧な場合&lt;/strong&gt;: 「適切に処理すること」のような曖昧なチェック項目はLLMが解釈を揺らす原因になる&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生成タスクが創造的な場合&lt;/strong&gt;: 自由度の高い文章生成では、チェックリストが制約として機能しすぎて出力品質が低下することがある&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;実装上のポイント&lt;/h3&gt;
&lt;p&gt;末尾チェックリストパターンを効果的に使うためのポイントをまとめます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1. チェックリストは「本文の繰り返し」ではなく「確認事項」として書く
   - NG: 同じ文章をそのままコピー
   - OK: 確認すべきポイントを簡潔にリスト化

2. 項目数は5〜10個に絞る
   - 多すぎると逆効果（チェックリスト自体のLost in the Middle）

3. 「回答の前に確認してください」と明示する
   - LLMに確認プロセスを促す

4. 最も見落とされやすい項目を優先する
   - 全てを再掲するのではなく、実績として漏れやすい指示を重点的に
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;4. その他のアプローチ&lt;/h2&gt;
&lt;p&gt;末尾チェックリストは手軽で効果的ですが、プロンプトの構造自体を改善するアプローチや、RAGパイプラインなどプロンプト外の仕組みで対策するアプローチもあります。&lt;/p&gt;
&lt;h3&gt;サンドイッチ戦略&lt;/h3&gt;
&lt;p&gt;最も重要な情報をプロンプトの&lt;strong&gt;先頭と末尾の両方&lt;/strong&gt;に配置する方法です。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;## 最重要ルール
出力は必ずJSON形式で返してください。

## コンテキスト情報
{大量のコンテキスト...}

## 補足情報
{追加のコンテキスト...}

## リマインダー: 出力は必ずJSON形式で返してください。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;U字型曲線の両端、つまり性能が最も高い位置に重要な指示を配置するため、シンプルながら効果的です。ただし、「最重要」を1つに絞る必要があるため、複数の指示を同時に強調したい場合には不向きです。&lt;/p&gt;
&lt;h3&gt;XMLタグによる構造化とセクション分割&lt;/h3&gt;
&lt;p&gt;XMLタグやMarkdownのヘッダーを使ってプロンプトを明確にセクション分割し、LLMがパースしやすい構造にします。&lt;/p&gt;
&lt;p&gt;Anthropicのプロンプトエンジニアリングチュートリアルでは、XMLタグによるデータと指示の分離が推奨されています。&lt;code&gt;&amp;lt;sentences&amp;gt;...&amp;lt;/sentences&amp;gt;&lt;/code&gt; のようなタグで入力データを明確に区切ることで、LLMがデータ領域と指示領域を区別しやすくなり、中間情報の見落としを軽減できる可能性があります。ただし、XMLタグ構造化は位置バイアスそのものを解消するものではなく、他の手法と組み合わせて使用することが推奨されます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;system&amp;gt;
あなたはデータ分析アシスタントです。
&amp;lt;/system&amp;gt;

&amp;lt;rules&amp;gt;
&amp;lt;rule priority=&quot;high&quot;&amp;gt;数値は必ず出典を明記すること&amp;lt;/rule&amp;gt;
&amp;lt;rule priority=&quot;high&quot;&amp;gt;推測値には「推定」と明記すること&amp;lt;/rule&amp;gt;
&amp;lt;rule priority=&quot;medium&quot;&amp;gt;グラフの説明には軸ラベルを含めること&amp;lt;/rule&amp;gt;
&amp;lt;/rules&amp;gt;

&amp;lt;context&amp;gt;
{分析対象のデータ}
&amp;lt;/context&amp;gt;

&amp;lt;output_format&amp;gt;
{出力フォーマットの指定}
&amp;lt;/output_format&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;priority&lt;/code&gt; 属性を付与することで、LLMが重要度を判断する補助にもなります。構造化によって「どこに何が書かれているか」を明示的にすることで、中間部の情報が埋もれるリスクを下げる効果が期待できます。&lt;/p&gt;
&lt;h3&gt;RAGにおける戦略的ドキュメント配置&lt;/h3&gt;
&lt;p&gt;RAG（Retrieval-Augmented Generation）パイプラインでは、検索されたドキュメントの&lt;strong&gt;配置順序&lt;/strong&gt;が回答精度に直結します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def reorder_documents(docs: list[str], scores: list[float]) -&amp;gt; list[str]:
    &quot;&quot;&quot;
    Lost in the Middle対策として、
    関連度の高いドキュメントを先頭と末尾に配置する。

    例: スコア順 [A(0.9), B(0.8), C(0.7), D(0.6), E(0.5)]
    結果: [A(0.9), C(0.7), E(0.5), D(0.6), B(0.8)]
           ^^^^^^                           ^^^^^^
           先頭に高スコア              末尾に高スコア
    &quot;&quot;&quot;
    scored_docs = list(zip(docs, scores))
    scored_docs.sort(key=lambda x: x[1], reverse=True)

    head = []  # 先頭側（偶数インデックス: 1位, 3位, 5位...）
    tail = []  # 末尾側（奇数インデックス: 2位, 4位, 6位...）

    for i, (doc, score) in enumerate(scored_docs):
        if i % 2 == 0:
            head.append(doc)
        else:
            tail.append(doc)

    # 末尾側は逆順にして、高スコアが末尾端に来るようにする
    return head + tail[::-1]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;この手法は、関連度スコアの高いドキュメントを先頭と末尾に配置し、中間にはスコアの低いドキュメントを置くことで、重要な情報が見落とされるリスクを軽減します。&lt;/p&gt;
&lt;h3&gt;情報位置と精度の定量的検証&lt;/h3&gt;
&lt;p&gt;Lost in the Middle問題は、Few-shot promptingの文脈でも影響を及ぼします。Anthropicのブログ記事 &quot;&lt;a href=&quot;https://www.anthropic.com/news/prompting-long-context&quot;&gt;Prompt engineering for Claude&apos;s long context window&lt;/a&gt;&quot; では、長文コンテキストからの情報検索精度を高めるテクニックとして、質問に関連する引用を先に抽出させる手法や、正しく回答されたQ&amp;amp;Aの例をプロンプトに追加する手法が定量的に検証されています。&lt;/p&gt;
&lt;p&gt;自分のプロンプトで位置バイアスの影響度合いを確認したい場合、このようなベンチマークを参考に検証パイプラインを構築することが有効です。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. まとめ&lt;/h2&gt;
&lt;h3&gt;手法の比較&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;手法&lt;/th&gt;
&lt;th&gt;適用場面&lt;/th&gt;
&lt;th&gt;トークンコスト&lt;/th&gt;
&lt;th&gt;実装難易度&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;末尾チェックリスト&lt;/td&gt;
&lt;td&gt;システムプロンプト全般&lt;/td&gt;
&lt;td&gt;低（リスト追加分のみ）&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;サンドイッチ戦略&lt;/td&gt;
&lt;td&gt;最重要ルールが1つの場合&lt;/td&gt;
&lt;td&gt;低（1文の再掲）&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XMLタグ構造化&lt;/td&gt;
&lt;td&gt;複数種類の情報を扱う場合&lt;/td&gt;
&lt;td&gt;中（タグ分の増加）&lt;/td&gt;
&lt;td&gt;中&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAGドキュメント配置&lt;/td&gt;
&lt;td&gt;RAGパイプライン&lt;/td&gt;
&lt;td&gt;なし（並び替えのみ）&lt;/td&gt;
&lt;td&gt;中&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;情報の配置に気を配る&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;最も重要な指示は&lt;strong&gt;先頭と末尾&lt;/strong&gt;に配置します&lt;/li&gt;
&lt;li&gt;中間に配置せざるを得ない場合は、末尾で再掲します&lt;/li&gt;
&lt;li&gt;プロンプトが長くなるほど、Lost in the Middleのリスクは高まります&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;末尾チェックリストで二重確認する&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;プロンプト末尾に「出力前の最終チェックリスト」を設けます&lt;/li&gt;
&lt;li&gt;過去に見落とされた指示を優先的にリストアップします&lt;/li&gt;
&lt;li&gt;チェック項目は5〜10個に絞ります&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;継続的にプロンプトの精度をモニタリングする&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;プロンプトの変更前後で精度を比較する仕組みを設けます&lt;/li&gt;
&lt;li&gt;特定の入力パターンで失敗が集中していないか定期的に確認します&lt;/li&gt;
&lt;li&gt;Lost in the Middleの影響度はモデルのバージョンアップで変動する可能性があるため、モデル更新時にも確認します&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;学んだこと&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;LLMの位置バイアスは&lt;strong&gt;アーキテクチャに起因する構造的な問題&lt;/strong&gt;であり、プロンプトの書き方だけでは根本解決できない。しかし、構造を理解した上で対策を講じることで実用上の精度は大幅に改善できる&lt;/li&gt;
&lt;li&gt;2025年時点の最新モデルでもこの問題は解消されておらず、さらにモデルファミリーによって劣化パターンが異なる（ハルシネーション vs 棄権）。使用モデルに応じた検証が欠かせない&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Liu et al. (2023) &quot;Lost in the Middle: How Language Models Use Long Contexts&quot; - &lt;a href=&quot;https://arxiv.org/abs/2307.03172&quot;&gt;arXiv:2307.03172&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Su et al. (2021) &quot;RoFormer: Enhanced Transformer with Rotary Position Embedding&quot; - &lt;a href=&quot;https://arxiv.org/abs/2104.09864&quot;&gt;arXiv:2104.09864&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anthropic &quot;Prompt Engineering: Use XML Tags&quot; - &lt;a href=&quot;https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/use-xml-tags&quot;&gt;docs.anthropic.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LangChain Blog &quot;Incorporating domain specific knowledge in SQL-LLM solutions&quot; - &lt;a href=&quot;https://blog.langchain.com/incorporating-domain-specific-knowledge-in-sql-llm-solutions/&quot;&gt;blog.langchain.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Anthropic &quot;Prompt engineering for Claude&apos;s long context window&quot; - &lt;a href=&quot;https://www.anthropic.com/news/prompting-long-context&quot;&gt;anthropic.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Modarressi et al. (2025) &quot;NoLiMa: Long-Context Evaluation Beyond Literal Matching&quot; - &lt;a href=&quot;https://arxiv.org/abs/2502.05167&quot;&gt;arXiv:2502.05167&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Chroma Research (2025) &quot;Context Rot: How Increasing Input Tokens Impacts LLM Performance&quot; - &lt;a href=&quot;https://research.trychroma.com/context-rot&quot;&gt;research.trychroma.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&quot;Curse of Instructions: Large Language Models Cannot Follow Multiple Instructions at Once&quot; (2024; ICLR 2025) - &lt;a href=&quot;https://openreview.net/forum?id=R6q67CDBCH&quot;&gt;OpenReview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://zeroshotlog.com/images/2026/02/04/lost-in-the-middle.png" length="0" type="image/png"/></item><item><title>AIが生成する「紫グラデーション」から脱却した話</title><link>https://zeroshotlog.com/blog/2026/01/18/design-renewal/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/2026/01/18/design-renewal/</guid><description>技術ブログのデザインをリニューアル。Claude Code + Playwright MCP + Stitch AIを組み合わせたワークフローと、AI生成デザインの典型から抜け出す工夫を紹介します。</description><pubDate>Sun, 18 Jan 2026 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;import { Tweet } from &apos;astro-embed&apos;;&lt;/p&gt;
&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AIに何も指示せずにUIを作らせると、高確率で「紫グラデーション」になる&lt;/li&gt;
&lt;li&gt;Claude Code + Playwright MCP + デザインAI（Stitch）でリニューアルを実行&lt;/li&gt;
&lt;li&gt;新カラーは amber-500（琥珀色）、ターミナル/コード風のデザインへ&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;紫グラデーション問題&lt;/h2&gt;
&lt;p&gt;このブログ「Zero-Shot Log」は、元々AIでデザインを生成していました。&lt;/p&gt;
&lt;p&gt;見た目は悪くない。でも、どこかで見たことがある気がする。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2026/01/18/before-desktop.png&quot; alt=&quot;旧デザイン（紫グラデーション）&quot; /&gt;&lt;/p&gt;
&lt;p&gt;原因は「紫のグラデーション」です。&lt;/p&gt;
&lt;p&gt;この現象について、Xで興味深いポストを見かけました。&lt;/p&gt;
&lt;p&gt;&amp;lt;Tweet id=&quot;https://twitter.com/seltzer/status/2010678415142039560&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;このポストへのリプライでは「TailwindのBg-indigo-500の影響を大きく受けている」という指摘がありました。&lt;/p&gt;
&lt;p&gt;&amp;lt;Tweet id=&quot;https://twitter.com/masayanishigaki/status/2010689800030871814&quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;AIが学習データからindigo/purple系のグラデーションを「最適なデフォルト」として学習した結果では、とのことです。&lt;/p&gt;
&lt;p&gt;脱却することにしました。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;リニューアルのワークフロー&lt;/h2&gt;
&lt;p&gt;今回のリニューアルでは、3つのAIツールを組み合わせました。&lt;/p&gt;
&lt;h3&gt;1. 現状把握: Claude Code + Playwright MCP&lt;/h3&gt;
&lt;p&gt;まず、Claude CodeにPlaywright MCPを接続して現行サイトのスクリーンショットを取得。デスクトップ・モバイルそれぞれのトップページと記事ページを撮影しました。&lt;/p&gt;
&lt;p&gt;これにより、デザイナーAIへの依頼時に「現状」を正確に伝えられます。&lt;/p&gt;
&lt;h3&gt;2. デザイン依頼書の作成&lt;/h3&gt;
&lt;p&gt;取得したスクリーンショットをもとに、デザイナーAIへの依頼書（design-brief.md）を作成。含めた内容は以下の通りです。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;サイト情報（名前、コンセプト、ページ構成）&lt;/li&gt;
&lt;li&gt;現在のカラースキームと問題点の洗い出し&lt;/li&gt;
&lt;li&gt;避けたいデザイン要素（紫グラデーション、派手なグロー等）&lt;/li&gt;
&lt;li&gt;期待する方向性（ミニマル、ウォームダーク、ターミナル/Vibe Coding風等）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;「何が嫌か」を明確に伝えることで、AIの出力をコントロールしようという狙いです。&lt;/p&gt;
&lt;h3&gt;3. デザインAI（Stitch）への依頼&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://stitch.withgoogle.com/&quot;&gt;Stitch&lt;/a&gt;はGoogle Labsが提供するUI生成AIツール。Gemini 2.5 Proを搭載し、テキストや画像からUIデザインを生成できます。現在ベータ版で無料利用可能。&lt;/p&gt;
&lt;p&gt;このStitchにスクリーンショットと依頼書を渡し、新しいデザイン案を受け取りました。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2026/01/18/designer-output.png&quot; alt=&quot;Stitchからの成果物&quot; /&gt;&lt;/p&gt;
&lt;p&gt;出てきたのはHTMLファイルとプレビュー画像。amber系のウォームな配色で、依頼内容は反映されています。&lt;/p&gt;
&lt;h3&gt;4. 実装&lt;/h3&gt;
&lt;p&gt;Stitchの成果物にはHTMLも含まれていますが、これは画像では伝わらない詳細情報を補完するためのもの。既存のAstroコンポーネントにそのまま適用できるわけではないので、カラーパレットやフォント選定などのコンセプトを参考にしながら、Claude Codeでスタイルを書き直しました。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;AI生成デザインの「紫グラデーション」問題は、明示的な指示で回避できる&lt;/li&gt;
&lt;li&gt;「スクショ＋依頼書→デザインAI→実装」の流れでリニューアルがスムーズに進む&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;デザインのリニューアルがAIでここまで手軽にできる、良い時代になりました。&lt;/p&gt;
</content:encoded></item><item><title>プロンプト拡張ツール「Query Expander」を作った</title><link>https://zeroshotlog.com/blog/query-expander-introduction/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/query-expander-introduction/</guid><description>曖昧なプロンプトを明確に拡張するツールをClaude Artifactで作成。Claudeにログインしていればいつでも使えます。</description><pubDate>Mon, 12 Jan 2026 12:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;LLMへの依頼内容を明確に拡張するツール「&lt;a href=&quot;https://claude.ai/public/artifacts/9a14629b-bc73-41ab-bd96-c8be99c8feee&quot;&gt;Query Expander&lt;/a&gt;」を作った&lt;/li&gt;
&lt;li&gt;Claude Artifactとして動作するため、Claudeにログインしていればいつでも使える&lt;/li&gt;
&lt;li&gt;3段階の詳細レベル（Concise / Standard / Detailed）で出力を調整可能&lt;/li&gt;
&lt;li&gt;日本語・英語を自動判定して出力&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;2026年2月 更新&lt;/strong&gt;: v1.1.1にアップデートしました。コピーボタンが機能しない不具合を修正しています。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;作った経緯&lt;/h2&gt;
&lt;p&gt;Claude Codeで調査や実装を依頼するとき、依頼内容を明確にしておくと精度が上がります。&lt;/p&gt;
&lt;p&gt;RAGの文脈では、ユーザーの曖昧なクエリを検索に適した形に変換することを「クエリ拡張（Query Expansion）」と呼びます。これと同じ発想で、LLMへのプロンプトも拡張できないかと考えました。&lt;/p&gt;
&lt;p&gt;以前は、依頼内容を拡張するためのルールをClaudeに設定して使っていました。例えば「〇〇について調べて」という曖昧な指示を、目的・対象・期待するフォーマットを含んだ明確なプロンプトに変換してもらう、といった具合です。&lt;/p&gt;
&lt;p&gt;ただ、この作業の頻度がかなり高かった。仕事中も頻繁に使うので、毎回チャットを開くのがめんどくさくなってきました。&lt;/p&gt;
&lt;p&gt;そこで、Claude Artifactとして独立したツールにしてみました。Claudeにログインしていれば使えるので、いつでも気軽にプロンプトを拡張できます。自分のプラン内で動作するため、APIのトークン消費を気にする必要もありません。&lt;/p&gt;
&lt;p&gt;UIデザインにはGoogleの&lt;a href=&quot;https://stitch.withgoogle.com/&quot;&gt;Stitch&lt;/a&gt;を使いました。プロンプトからUIを生成してくれるツールで、ベースのデザインを素早く作れます。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Query Expanderとは&lt;/h2&gt;
&lt;p&gt;Query Expanderは、曖昧なプロンプトを明確で構造化されたプロンプトに変換するツールです。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主な機能:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;3段階の詳細レベル&lt;/strong&gt;: Concise（簡潔）/ Standard（標準）/ Detailed（詳細）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Refine Onlyモード&lt;/strong&gt;: 元の構造を維持しつつ文章を洗練&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;言語自動判定&lt;/strong&gt;: 入力が日本語なら日本語で、英語なら英語で出力&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Markdown保持&lt;/strong&gt;: 見出しやリスト構造を維持したまま拡張&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;使い方&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;テキストエリアに拡張したいプロンプトを入力&lt;/li&gt;
&lt;li&gt;詳細レベル（Concise / Standard / Detailed）を選択&lt;/li&gt;
&lt;li&gt;「ENHANCE QUERY」をクリック&lt;/li&gt;
&lt;li&gt;拡張されたプロンプトをコピーして使用&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;詳細レベルの使い分け&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;レベル&lt;/th&gt;
&lt;th&gt;出力量&lt;/th&gt;
&lt;th&gt;用途&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Concise&lt;/td&gt;
&lt;td&gt;1〜2文&lt;/td&gt;
&lt;td&gt;軽微な修正、誤字脱字の修正&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard&lt;/td&gt;
&lt;td&gt;2〜4文&lt;/td&gt;
&lt;td&gt;一般的なプロンプト改善（デフォルト）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Detailed&lt;/td&gt;
&lt;td&gt;3〜5項目&lt;/td&gt;
&lt;td&gt;複雑なタスク、詳細な指示が必要な場合&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Refine Onlyモード&lt;/h3&gt;
&lt;p&gt;通常モードはプロンプトを「拡張」しますが、Refine Onlyモードは元の構造を維持したまま「洗練」します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;通常モードとの違い:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;モード&lt;/th&gt;
&lt;th&gt;動作&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;通常&lt;/td&gt;
&lt;td&gt;目的・対象・フォーマットなどを追加して拡張&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refine Only&lt;/td&gt;
&lt;td&gt;元の構造を維持しつつ、表現を洗練&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Refine Onlyが向いているケース:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;既に構造化されたプロンプトの文章を磨きたい&lt;/li&gt;
&lt;li&gt;元のフォーマットを崩したくない&lt;/li&gt;
&lt;li&gt;トーンだけ調整したい（カジュアル→フォーマルなど）&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;使用例&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;入力:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Reactのstate管理について調べて
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Standard出力（イメージ）:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Reactにおけるstate管理の主要なアプローチについて調査してください。
対象として、useState、useReducer、Context API、および外部ライブラリ（Redux、Zustand、Jotai等）を含めてください。
それぞれの特徴、適切なユースケース、パフォーマンス面での考慮点を比較形式でまとめてください。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;曖昧な「調べて」が、目的・対象・期待するフォーマットを含んだ明確なプロンプトに変換されます。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;リンク&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/public/artifacts/9a14629b-bc73-41ab-bd96-c8be99c8feee&quot;&gt;Query Expander&lt;/a&gt; - Claude Artifactへのリンク&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://query-expander.gitbook.io/docs&quot;&gt;ドキュメント&lt;/a&gt; - 詳細な使い方&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;まとめ&lt;/h2&gt;
&lt;p&gt;プロンプトを明確にする作業は地味ですが、LLMの出力精度に直結します。Query Expanderを使えば、この作業を手軽に行えます。&lt;/p&gt;
&lt;p&gt;Claudeにログインしていれば無料で使えるので、日常的にLLMを使う方はぜひ試してみてください。&lt;/p&gt;
</content:encoded><enclosure url="https://zeroshotlog.com/images/2026/01/12/query-expander.png" length="0" type="image/png"/></item><item><title>Antigravityが重くなった時の会話引き継ぎ方法</title><link>https://zeroshotlog.com/blog/antigravity-hidden-brain-feature/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/antigravity-hidden-brain-feature/</guid><description>Antigravityで長時間作業すると動作が重くなる現象の対策と、brainディレクトリを使った会話引き継ぎ方法を解説。UUIDを指定するだけで新しいセッションにコンテキストを引き継げます。</description><pubDate>Sat, 03 Jan 2026 10:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Antigravityで長時間作業すると動作が重くなる現象に遭遇&lt;/li&gt;
&lt;li&gt;セッション分割で改善するが、コンテキストの引き継ぎが課題&lt;/li&gt;
&lt;li&gt;Antigravityに引き継ぎ方法を聞いたことがきっかけで「brainディレクトリ」を発見&lt;/li&gt;
&lt;li&gt;brainを活用すれば、新しいセッションでもスムーズに作業を継続できる&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;何が起きたか&lt;/h2&gt;
&lt;h3&gt;長い会話で動作が重くなる&lt;/h3&gt;
&lt;p&gt;Antigravityを使っていたときのことです。&lt;/p&gt;
&lt;p&gt;あるプロジェクトで長めの実装作業を任せていたら、徐々にレスポンスが遅くなり始めました。UIの反応が鈍くなり、エージェントの応答も明らかに遅延している。アクティビティモニタを確認すると、メモリ使用量がかなり高くなっていました。&lt;/p&gt;
&lt;h3&gt;原因はトークン予算の圧迫&lt;/h3&gt;
&lt;p&gt;調べてみると、Antigravityには1会話あたり約200,000トークンの予算があるとのこと。会話が長くなると、このトークン予算を消費していき、処理負荷が上がっていくようです。&lt;/p&gt;
&lt;p&gt;また、会話履歴が増えるとローカルのストレージも圧迫されます。Antigravityはスクリーンショットや録画などの「Artifacts（成果物）」をローカルに保存するため、これも動作に影響している可能性がありました。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;セッション分割で改善&lt;/h2&gt;
&lt;h3&gt;基本的な対策&lt;/h3&gt;
&lt;p&gt;パフォーマンス問題の対策として、以下が有効でした。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 古い会話ログを削除する&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Agent Managerの履歴から、不要になった会話を削除します。数十セッション以上溜まっていると、IDE全体のレスポンスに影響することがあります。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 長い作業はセッションを分割する&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1つの会話で長時間作業を続けるのではなく、キリの良いところで新しい会話に切り替えます。トークン予算がリセットされ、動作が軽快になります。&lt;/p&gt;
&lt;h3&gt;残った課題：コンテキストの引き継ぎ&lt;/h3&gt;
&lt;p&gt;セッション分割で動作は改善しました。しかし、新しい問題が生まれました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;新しいセッションに、前の作業のコンテキストをどう引き継ぐか？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;毎回「前回はここまでやった」「この方針で進めていた」と説明し直すのは面倒です。特に複雑な実装の途中だと、説明漏れも起きやすい。&lt;/p&gt;
&lt;p&gt;AntigravityにはKnowledge Itemsという自動学習の仕組みがあり、蓄積された知識は自動的に引き継がれます。ただ、どの範囲（ワークスペース単位？ディレクトリ単位？）でどれだけ引き継がれるのか、ドキュメントを見ても明確にはわかりませんでした。特定の会話のタスクやファイルを明示的に引き継ぎたい場面もあります。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;偶然の発見：Antigravityの回答&lt;/h2&gt;
&lt;p&gt;セッションを切り替える前に、Antigravityにこう聞いてみました。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;「新しい会話に引き継ぐにはどうすればいい？」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;すると、こんな回答が返ってきました：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;「別の会話を開始する際に、「前回の会話（a1b2c3d4-...）の続きから」と伝えていただければ、これらのドキュメントを参照して作業を継続できます。特に current_issues.md には、次のセッションで対応すべき内容を詳細にまとめています。」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;え、そんな機能あるの？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;current_issues.md&lt;/code&gt; とは何か。どこにあるのか。気になって調べてみると、ホームディレクトリに見慣れないフォルダがありました。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ls ~/.gemini/antigravity/brain/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ここに、セッションごとのArtifactsが保存されていたのです。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;brainディレクトリとは&lt;/h2&gt;
&lt;h3&gt;概要&lt;/h3&gt;
&lt;p&gt;brainディレクトリ（&lt;code&gt;~/.gemini/antigravity/brain/&lt;/code&gt;）は、Antigravityのエージェントが作業中に生成する記録の保存場所です。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.gemini/antigravity/brain/
├── a1b2c3d4-5678-90ab-cdef-1234567890ab/
│   ├── task.md
│   ├── implementation_plan.md
│   ├── walkthrough.md
│   ├── current_issues.md
│   ├── uploaded_image_1234567890123.png
│   └── uploaded_image_1234567890456.png
├── b2c3d4e5-6789-01bc-def0-2345678901bc/
│   └── ...
└── ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;各フォルダ名のUUIDが、それぞれの会話セッションに対応しています。&lt;/p&gt;
&lt;h3&gt;保存されるファイル&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ファイル&lt;/th&gt;
&lt;th&gt;内容&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;task.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;タスクの進捗管理（チェックリスト形式）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;implementation_plan.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;実装計画の技術的詳細&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;walkthrough.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;実装完了後の変更サマリー&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;current_issues.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;次セッションで対応すべき課題&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;uploaded_image_*.png&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;会話中にアップロードした画像&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;特に &lt;code&gt;current_issues.md&lt;/code&gt; が引き継ぎに重要です。未解決の課題や、次回やるべきことがまとまっています。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;brainを活用した会話引き継ぎ方法&lt;/h2&gt;
&lt;h3&gt;方法1: UUIDを指定して引き継ぐ&lt;/h3&gt;
&lt;p&gt;新しい会話を開始し、前回のセッションIDを伝えます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;前回の会話（a1b2c3d4-5678-90ab-cdef-1234567890ab）の続きから作業してください。
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;エージェントはbrainディレクトリ内の該当Artifactsを参照し、コンテキストを理解した上で作業を継続します。&lt;/p&gt;
&lt;h3&gt;方法2: current_issues.mdを直接参照させる&lt;/h3&gt;
&lt;p&gt;より確実に引き継ぎたい場合は、ファイルパスを直接指定します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.gemini/antigravity/brain/a1b2c3d4-.../current_issues.md を確認して、
未解決の課題から作業を再開してください。
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;会話IDの確認方法&lt;/h3&gt;
&lt;p&gt;会話IDは、Antigravityに直接以下のように聞くことで確認できます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;この会話の会話ID（UUID）教えて
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;回答例：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;「この会話のIDは a1b2c3d4-5678-90ab-cdef-1234567890ab です。」&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;※ PlanningモードでGemini 3 Proを使用した際に確認。モデルや状況によっては回答が異なる可能性があります。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;実践的なワークフロー&lt;/h2&gt;
&lt;h3&gt;Antigravity単体での運用&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;作業開始&lt;/strong&gt;: 新しい会話でタスクを指示&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作業中&lt;/strong&gt;: エージェントが&lt;code&gt;task.md&lt;/code&gt;、&lt;code&gt;implementation_plan.md&lt;/code&gt;などを自動生成&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;区切り&lt;/strong&gt;: 動作が重くなってきたら、エージェントに「Artifactsを最新の状態にして」と依頼。&lt;code&gt;task.md&lt;/code&gt;、&lt;code&gt;implementation_plan.md&lt;/code&gt;、&lt;code&gt;current_issues.md&lt;/code&gt;などが更新される&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;UUID確認&lt;/strong&gt;: 「この会話のUUID教えて」と聞いてメモしておく&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;引き継ぎ&lt;/strong&gt;: 新しい会話を開始し、「前回の会話（UUID）の続きから」と伝える&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;ポイント&lt;/strong&gt;: 引き継ぎ前にArtifactsを最新にしておくことが重要です。古い状態のまま引き継ぐと、新しいセッションで認識のズレが生じます。&lt;/p&gt;
&lt;h3&gt;Claude Codeとの併用&lt;/h3&gt;
&lt;p&gt;brainのファイルはMarkdown形式なので、Claude Codeなど他のAIツールからも読み取れます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Claude Codeでbrainの内容を確認
cat ~/.gemini/antigravity/brain/a1b2c3d4-.../implementation_plan.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Antigravityで作成した&lt;code&gt;implementation_plan.md&lt;/code&gt;をClaude Codeに読ませて「この計画をレビューして」と頼んだりできます。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;注意点&lt;/h2&gt;
&lt;h3&gt;brainには会話全文は保存されない&lt;/h3&gt;
&lt;p&gt;brainに保存されるのはArtifacts（成果物）のみで、会話のやり取り全文は保存されません。細かいニュアンスや議論の経緯は失われる可能性があるため、重要な決定事項はエージェントにArtifactsへ明示的に記録させましょう。&lt;/p&gt;
&lt;p&gt;なお、&lt;code&gt;~/.gemini/antigravity/conversations/&lt;/code&gt; には &lt;code&gt;.pb&lt;/code&gt;（Protocol Buffers）形式のファイルがあり、バイナリ形式で会話データが保存されているようです。直接読むことはできませんが、会話履歴はここに残っていそうです。&lt;/p&gt;
&lt;h3&gt;ストレージ容量&lt;/h3&gt;
&lt;p&gt;brainディレクトリ以外にも、Antigravityは &lt;code&gt;browser_recordings/&lt;/code&gt; ディレクトリなどに証跡ファイルを生成します。スクリーンショットやブラウザ録画が蓄積すると、ディスク容量を圧迫することがあります。不要なセッションは定期的に削除することをおすすめします。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 古いセッションの確認
ls -la ~/.gemini/antigravity/brain/

# 不要なセッションの削除
rm -rf ~/.gemini/antigravity/brain/&amp;lt;不要なUUID&amp;gt;/
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;まとめ&lt;/h2&gt;
&lt;p&gt;Antigravityが重くなる問題は、セッション分割で解決できます。そして、会話の引き継ぎには &lt;strong&gt;brainディレクトリのUUIDを指定する&lt;/strong&gt; という方法が使えます。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;問題&lt;/strong&gt;: 長い会話でトークン予算を消費し、動作が重くなる&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;解決策&lt;/strong&gt;: 新しいセッションに切り替え、brainのArtifactsを参照して引き継ぐ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隠し機能&lt;/strong&gt;: 「前回の会話（UUID）の続きから」と伝えるだけで、brainのArtifactsを参照してくれる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;この機能は、Antigravityに会話引き継ぎ方法を聞いたことで偶然発見しました。Antigravityの回答がハルシネーションだった可能性もありますが、実際にbrainディレクトリは存在しますし、ファイルを参照させることで引き継ぎできるのは確かです。公式ドキュメントにも記載が見当たらないので、ちょっとした裏技として使えそうです。&lt;/p&gt;
&lt;p&gt;パフォーマンス問題で困っている方は、ぜひbrainを活用したセッション管理を試してみてください。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://antigravity.codes/troubleshooting&quot;&gt;Troubleshooting Google Antigravity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vertexdigest.com/blogs/mastering-anti-gravity-artifacts&quot;&gt;Mastering Anti-Gravity Artifacts - Vertex Digest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://moghaoui.substack.com/p/hack-dont-lose-to-googles-antigravity&quot;&gt;Hack: Don&apos;t lose to Google&apos;s Antigravity - Substack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://note.com/biwakonbu/n/n04482fc86825&quot;&gt;note - Antigravity で会話履歴が長くなると重くなってきている気がする&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://note.com/honest_kudu5817/n/ndcdc33f2538f&quot;&gt;note - 【Google Antigravity】大量の証跡がローカルストレージを圧迫&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://zeroshotlog.com/images/2026/01/03/antigravity-hidden-brain-feature.png" length="0" type="image/png"/></item><item><title>macOSでNeovimを快適に使うための設定入門</title><link>https://zeroshotlog.com/blog/neovim-macos-setup-guide/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/neovim-macos-setup-guide/</guid><description>macOSでのIME問題の解決、Neovim 0.11のプラグイン互換性、Nerd Font不要のミニマル設定、LSP/補完の基本設定について解説します。</description><pubDate>Tue, 30 Dec 2025 11:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;macOSでのIME問題は &lt;code&gt;im-select.nvim&lt;/code&gt; + &lt;code&gt;macism&lt;/code&gt; で解決できる&lt;/li&gt;
&lt;li&gt;Neovim 0.11ではプラグインの互換性に注意が必要（Telescopeは&lt;code&gt;0.1.x&lt;/code&gt;タグを使用）&lt;/li&gt;
&lt;li&gt;Nerd Fontなしでもシンプルな設定で十分実用的な環境が作れる&lt;/li&gt;
&lt;li&gt;LSP/補完は &lt;code&gt;mason.nvim&lt;/code&gt; + &lt;code&gt;nvim-cmp&lt;/code&gt; の組み合わせが初心者にも扱いやすい&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;はじめに&lt;/h2&gt;
&lt;p&gt;この記事では、macOSでNeovimを快適に使うための設定を解説します。Vimの基本操作（モード切り替え、カーソル移動、保存・終了など）は知っているが、Neovimのプラグイン設定は初めてという方を想定しています。&lt;/p&gt;
&lt;p&gt;以下の4つのトピックを扱います：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;macOS IME問題の解決&lt;/strong&gt; - 日本語入力で最もハマりやすいポイント&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Neovim 0.11のプラグイン互換性&lt;/strong&gt; - 最新版を使う際の注意点&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nerd Font不要のミニマル設定&lt;/strong&gt; - フォント設定なしで使える環境&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LSP/補完の基本設定&lt;/strong&gt; - 定義ジャンプや自動補完を実現&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;前提環境&lt;/h2&gt;
&lt;p&gt;この記事の設定は以下の環境で動作確認しています：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;項目&lt;/th&gt;
&lt;th&gt;バージョン&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;Sonoma 14.x 以降&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Neovim&lt;/td&gt;
&lt;td&gt;0.11.3 以降（LSP新APIに必要）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Homebrew&lt;/td&gt;
&lt;td&gt;インストール済み&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ターミナル&lt;/td&gt;
&lt;td&gt;iTerm2（Terminal.appでも可）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;まだNeovimをインストールしていない場合は、以下のコマンドでインストールできます：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brew install neovim
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;1. macOS IME問題の解決&lt;/h2&gt;
&lt;h3&gt;問題の概要&lt;/h3&gt;
&lt;p&gt;macOSでNeovim（Vim）を使う際、多くの人がつまずくのがIME（日本語入力）の問題です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;具体的には&lt;/strong&gt;: 日本語入力モードのままノーマルモードに戻ると、&lt;code&gt;j&lt;/code&gt;や&lt;code&gt;k&lt;/code&gt;などのコマンドが効かなくなる。&lt;/p&gt;
&lt;p&gt;これは、InsertモードからNormalモードに戻っても、macOSのIME状態がそのままになるためです。日本語で文章を書いた後、&lt;code&gt;Esc&lt;/code&gt;でノーマルモードに戻ると、IMEが日本語入力のままなので、&lt;code&gt;jjj...&lt;/code&gt;と入力しても「っっっ...」と日本語が入力されてしまいます。&lt;/p&gt;
&lt;h3&gt;解決策: im-select.nvim + macism&lt;/h3&gt;
&lt;p&gt;この問題を解決するには、2つのコンポーネントを組み合わせます：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/keaising/im-select.nvim&quot;&gt;im-select.nvim&lt;/a&gt;&lt;/strong&gt;（Neovimプラグイン）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;モード切り替え（Insert→Normal等）を検知&lt;/li&gt;
&lt;li&gt;外部のCLIツールを呼び出してIMEを切り替え&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/laishulu/macism&quot;&gt;macism&lt;/a&gt;&lt;/strong&gt;（CLIツール）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;実際にmacOSのIMEを切り替えるコマンド&lt;/li&gt;
&lt;li&gt;im-select.nvimから呼び出される&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;つまり、im-select.nvimがNeovim内でモード変更を監視し、変更を検知したらmacismコマンドを実行してIMEを英数に切り替える、という仕組みです。&lt;/p&gt;
&lt;h4&gt;なぜmacismなのか&lt;/h4&gt;
&lt;p&gt;im-select.nvimはmacOS上でIMEを切り替えるCLIツールを呼び出します。macOS用のツールは複数ありますが、&lt;strong&gt;im-select.nvimの公式READMEではmacismを推奨&lt;/strong&gt;しています。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Please install macism, this is the only one CLI tool can switch CJK and English input methods in macOS correctly.
— &lt;a href=&quot;https://github.com/keaising/im-select.nvim&quot;&gt;im-select.nvim README&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;macismは、日本語などのCJK入力ソースを確実に切り替えられます。他のツール（&lt;code&gt;input-source-switcher&lt;/code&gt;等）ではmacOSのバグにより、メニューバーのアイコンは変わっても実際には切り替わらない問題が発生することがあるようです。&lt;/p&gt;
&lt;h4&gt;インストール手順&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;macism&lt;/code&gt;は公式のHomebrew tapにないため、サードパーティのtapを追加する必要があります：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# tapの追加
brew tap laishulu/homebrew

# macismのインストール
brew install laishulu/homebrew/macism
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;インストール後、動作確認をしてみましょう：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 現在の入力ソースを確認
macism

# 出力例: com.apple.inputmethod.Kotoeri.RomajiTyping.Japanese
# または: com.apple.keylayout.ABC
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Neovimの設定&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;im-select.nvim&lt;/code&gt;プラグインを使って、モード切り替え時の動作を設定します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- プラグインマネージャー（lazy.nvim）での設定例
{
  &quot;keaising/im-select.nvim&quot;,
  config = function()
    require(&quot;im_select&quot;).setup({
      -- 切り替え先の入力ソース（英数キーボード）
      default_im_select = &quot;com.apple.keylayout.ABC&quot;,

      -- macismの絶対パス（Intel Macの場合は /usr/local/bin/macism）
      default_command = &quot;/opt/homebrew/bin/macism&quot;,

      -- 英数に切り替えるタイミング
      set_default_events = {
        &quot;VimEnter&quot;,       -- Neovim起動時
        &quot;FocusGained&quot;,    -- ウィンドウにフォーカスが戻った時
        &quot;InsertLeave&quot;,    -- Insertモードを抜けた時
        &quot;CmdlineLeave&quot;    -- コマンドラインモードを抜けた時
      },

      -- InsertEnter時に前のIMEに戻す設定（空にして無効化）
      set_previous_events = {},
    })
  end,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;設定のポイント: なぜ &lt;code&gt;set_previous_events = {}&lt;/code&gt; にしたか&lt;/h4&gt;
&lt;p&gt;デフォルトでは、&lt;code&gt;set_previous_events = { &quot;InsertEnter&quot; }&lt;/code&gt; となっており、Insertモードに入ると直前のIME状態に戻ります。&lt;/p&gt;
&lt;p&gt;しかし、この設定を空にして無効化しました。理由は以下の通りです：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;トレードオフの比較&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;設定&lt;/th&gt;
&lt;th&gt;メリット&lt;/th&gt;
&lt;th&gt;デメリット&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{ &quot;InsertEnter&quot; }&lt;/code&gt;（デフォルト）&lt;/td&gt;
&lt;td&gt;日本語の連続入力に便利&lt;/td&gt;
&lt;td&gt;英語コードを書く際に毎回切り替えが必要&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;{}&lt;/code&gt;（無効化）&lt;/td&gt;
&lt;td&gt;常に英数から始まるので予測しやすい&lt;/td&gt;
&lt;td&gt;日本語を続けて書く際は手動切り替え&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;プログラミングでは英語入力が圧倒的に多いため、「常に英数に戻る」動作の方が快適でした。日本語を書く際は、手動で日本語入力に切り替えれば済みます。&lt;/p&gt;
&lt;p&gt;もし日本語でドキュメントを書く機会が多い場合は、デフォルトの &lt;code&gt;{ &quot;InsertEnter&quot; }&lt;/code&gt; の方が便利かもしれません。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. Neovim 0.11のプラグイン互換性&lt;/h2&gt;
&lt;h3&gt;問題の概要&lt;/h3&gt;
&lt;p&gt;2025年3月にリリースされたNeovim 0.11では、LSP関連のAPIが大きく変更されました。この影響で、一部のプラグインがそのままでは動作しない場合があります。&lt;/p&gt;
&lt;h3&gt;Telescope.nvimの互換性問題&lt;/h3&gt;
&lt;p&gt;最も多くのユーザーが遭遇するのが、Telescope.nvim（ファジーファインダー）の問題です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;症状&lt;/strong&gt;: Telescopeを開くとエラーが発生する、または表示がおかしい&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;: Telescope.nvimの安定版ブランチ（&lt;code&gt;0.1.x&lt;/code&gt;）がNeovim 0.11のAPI変更に追従していない&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解決策&lt;/strong&gt;: &lt;code&gt;0.1.x&lt;/code&gt;タグを使用する（最新版では修正済み）&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- Neovim 0.11対応版
{
  &quot;nvim-telescope/telescope.nvim&quot;,
  tag = &quot;0.1.x&quot;,  -- 安定版タグ（Neovim 0.11対応済み）
  dependencies = { &quot;nvim-lua/plenary.nvim&quot; },
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;バージョン選択のポイント&lt;/h4&gt;
&lt;p&gt;2025年末時点では、Telescope v0.2.0もリリースされています。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指定方法&lt;/th&gt;
&lt;th&gt;特徴&lt;/th&gt;
&lt;th&gt;推奨度&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tag = &quot;0.1.x&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;安定版、Neovim 0.11対応済み&lt;/td&gt;
&lt;td&gt;推奨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tag = &quot;0.1.8&quot;&lt;/code&gt; 等&lt;/td&gt;
&lt;td&gt;特定バージョン固定&lt;/td&gt;
&lt;td&gt;再現性重視なら&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;branch = &quot;master&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;最新開発版&lt;/td&gt;
&lt;td&gt;新機能を試したい場合&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;以前は&lt;code&gt;0.1.x&lt;/code&gt;ブランチがNeovim 0.11非対応でしたが、現在は修正されています。特に理由がなければ&lt;code&gt;tag = &quot;0.1.x&quot;&lt;/code&gt;を使えば問題ありません。&lt;/p&gt;
&lt;h3&gt;その他の互換性確認方法&lt;/h3&gt;
&lt;p&gt;プラグインが動作しない場合は、以下の手順で調査できます：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GitHubのIssuesを確認&lt;/strong&gt;: &lt;code&gt;[プラグイン名] Neovim 0.11&lt;/code&gt;で検索&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;READMEのRequirementsを確認&lt;/strong&gt;: 対応するNeovimバージョンが明記されていることが多い&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;最新版に更新&lt;/strong&gt;: &lt;code&gt;:Lazy sync&lt;/code&gt;でプラグインを最新化&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;3. Nerd Font不要のミニマル設定&lt;/h2&gt;
&lt;h3&gt;Nerd Fontとは&lt;/h3&gt;
&lt;p&gt;多くのNeovim設定記事では「Nerd Fontをインストールしてください」と書かれています。Nerd Fontは、通常のフォントにアイコン（ファイルタイプ、Git状態、フォルダなど）を追加したフォントファミリーです。&lt;/p&gt;
&lt;p&gt;しかし、Nerd Fontの導入には以下のステップが必要です：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Nerd Fontのダウンロード&lt;/li&gt;
&lt;li&gt;システムへのインストール&lt;/li&gt;
&lt;li&gt;ターミナルのフォント設定変更&lt;/li&gt;
&lt;li&gt;設定の反映確認&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;なぜNerd Fontなしを選んだか&lt;/h3&gt;
&lt;p&gt;Nerd Fontを使わない選択をした理由は以下の通りです：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;メリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ターミナルのフォント設定をいじらなくて済む&lt;/li&gt;
&lt;li&gt;複数マシン間で設定を共有しやすい（フォントのインストール不要）&lt;/li&gt;
&lt;li&gt;シンプルで軽量な見た目&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;デメリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ファイルタイプが視覚的に分かりにくい&lt;/li&gt;
&lt;li&gt;見た目が地味&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;プログラミング中はファイル名を見ればファイルタイプは分かるため、アイコンがなくても実用上の問題はありませんでした。&lt;/p&gt;
&lt;h3&gt;アイコンを無効化する設定&lt;/h3&gt;
&lt;p&gt;主要なプラグインでアイコンを無効化する方法を紹介します。&lt;/p&gt;
&lt;h4&gt;nvim-tree（ファイルエクスプローラー）&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;nvim-tree/nvim-tree.lua&quot;,
  config = function()
    require(&quot;nvim-tree&quot;).setup({
      renderer = {
        icons = {
          show = {
            file = false,        -- ファイルアイコン非表示
            folder = false,      -- フォルダアイコン非表示
            folder_arrow = true, -- 展開/折りたたみの矢印は表示
            git = false,         -- Git状態アイコン非表示
          },
          glyphs = {
            folder = {
              arrow_closed = &quot;&amp;gt;&quot;,  -- 折りたたみ時の矢印
              arrow_open = &quot;v&quot;,    -- 展開時の矢印
            },
          },
        },
      },
    })
  end,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;lualine（ステータスライン）&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;nvim-lualine/lualine.nvim&quot;,
  config = function()
    require(&quot;lualine&quot;).setup({
      options = {
        icons_enabled = false,       -- アイコン全体を無効化
        section_separators = &quot;&quot;,     -- セクション区切りなし
        component_separators = &quot;|&quot;,  -- 区切り文字をシンプルに
      },
    })
  end,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;見た目の比較&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Nerd Fontあり&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  init.lua    main   lua  utf-8  100%  42:1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Nerd Fontなし&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;NORMAL | main | init.lua | lua | utf-8 | 100% | 42:1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;アイコンの代わりにテキストで情報が表示されます。慣れれば十分読みやすいです。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;4. LSP/補完の基本設定&lt;/h2&gt;
&lt;h3&gt;LSPとは&lt;/h3&gt;
&lt;p&gt;LSP（Language Server Protocol）は、エディタと言語サーバーの間の通信プロトコルです。これを使うことで、以下の機能が実現できます：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;定義ジャンプ&lt;/strong&gt;: 関数や変数の定義元にジャンプ&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;参照検索&lt;/strong&gt;: 関数や変数がどこで使われているか一覧表示&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自動補完&lt;/strong&gt;: 入力中に候補を表示&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;診断&lt;/strong&gt;: エラーや警告をリアルタイムで表示&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;リネーム&lt;/strong&gt;: シンボル名を一括変更&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;プラグイン構成の全体像&lt;/h3&gt;
&lt;p&gt;LSP/補完を実現するために、以下のプラグインを組み合わせます：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mason.nvim              # 言語サーバーのインストーラー
  └── mason-lspconfig   # masonとlspconfigの橋渡し
        └── nvim-lspconfig  # 言語サーバーの設定

nvim-cmp                # 補完エンジン
  ├── cmp-nvim-lsp      # LSPからの補完ソース
  ├── cmp-buffer        # バッファ内の単語を補完
  ├── cmp-path          # ファイルパスを補完
  └── LuaSnip           # スニペット展開
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;なぜこの構成を選んだか&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;観点&lt;/th&gt;
&lt;th&gt;選択&lt;/th&gt;
&lt;th&gt;理由&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LSPインストール&lt;/td&gt;
&lt;td&gt;mason.nvim&lt;/td&gt;
&lt;td&gt;GUIで管理でき、初心者に分かりやすい&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;補完エンジン&lt;/td&gt;
&lt;td&gt;nvim-cmp&lt;/td&gt;
&lt;td&gt;最も広く使われており、情報が豊富&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;スニペット&lt;/td&gt;
&lt;td&gt;LuaSnip&lt;/td&gt;
&lt;td&gt;nvim-cmpとの連携がスムーズ&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;mason.nvimによる言語サーバーの自動インストール&lt;/h3&gt;
&lt;p&gt;mason.nvimを使うと、&lt;code&gt;:Mason&lt;/code&gt;コマンドでGUIから言語サーバーを管理できます。また、&lt;code&gt;mason-lspconfig&lt;/code&gt;を使えば、必要な言語サーバーを自動でインストールできます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;neovim/nvim-lspconfig&quot;,
  dependencies = {
    &quot;williamboman/mason.nvim&quot;,
    &quot;williamboman/mason-lspconfig.nvim&quot;,
  },
  config = function()
    -- masonの初期化（:Masonコマンドが使えるようになる）
    require(&quot;mason&quot;).setup()

    -- 自動インストールする言語サーバーを指定
    require(&quot;mason-lspconfig&quot;).setup({
      ensure_installed = {
        &quot;lua_ls&quot;,   -- Lua
        &quot;ts_ls&quot;,    -- TypeScript/JavaScript
        &quot;pyright&quot;,  -- Python
      },
    })
  end,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;初回起動時に、指定した言語サーバーが自動でインストールされます。&lt;/p&gt;
&lt;h3&gt;Neovim 0.11の新しいLSP設定API&lt;/h3&gt;
&lt;p&gt;Neovim 0.11では、LSPの設定方法が大きく変わりました。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;旧来の方法&lt;/strong&gt;（nvim-lspconfig依存）:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;local lspconfig = require(&quot;lspconfig&quot;)
lspconfig.lua_ls.setup({
  settings = {
    Lua = {
      diagnostics = { globals = { &quot;vim&quot; } },
    },
  },
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;新しい方法&lt;/strong&gt;（Neovim 0.11.3+ネイティブ）:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;-- 言語サーバーごとの設定
vim.lsp.config(&apos;lua_ls&apos;, {
  settings = {
    Lua = {
      diagnostics = { globals = { &quot;vim&quot; } },
    },
  },
})

-- 言語サーバーを有効化
vim.lsp.enable({ &quot;lua_ls&quot;, &quot;pyright&quot;, &quot;ts_ls&quot; })
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: nvim-lspconfigは廃止されていません。内部的に&lt;code&gt;vim.lsp.config&lt;/code&gt;を呼び出すラッパーとして機能するため、従来の&lt;code&gt;lspconfig.xxx.setup({})&lt;/code&gt;形式も引き続き使えます。新規で設定する場合は、プラグイン依存を減らせる新APIがおすすめです。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;新しいAPIを使うメリット：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Neovimのビルトイン機能なので、将来的に安定&lt;/li&gt;
&lt;li&gt;シンプルで分かりやすい記述&lt;/li&gt;
&lt;li&gt;ファイルベースの設定も可能（&lt;code&gt;~/.config/nvim/lsp/&lt;/code&gt;配下）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;LSPキーマップの設定&lt;/h3&gt;
&lt;p&gt;LSPの機能をキーに割り当てます。&lt;code&gt;LspAttach&lt;/code&gt;イベントを使うと、LSPが有効なバッファでのみキーマップが設定されます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;vim.api.nvim_create_autocmd(&quot;LspAttach&quot;, {
  callback = function(args)
    local bufnr = args.buf
    local opts = { buffer = bufnr, silent = true }

    -- 定義・宣言・実装へのジャンプ
    vim.keymap.set(&quot;n&quot;, &quot;gd&quot;, vim.lsp.buf.definition, opts)
    vim.keymap.set(&quot;n&quot;, &quot;gD&quot;, vim.lsp.buf.declaration, opts)
    vim.keymap.set(&quot;n&quot;, &quot;gi&quot;, vim.lsp.buf.implementation, opts)

    -- ドキュメント表示・編集操作
    vim.keymap.set(&quot;n&quot;, &quot;K&quot;, vim.lsp.buf.hover, opts)
    vim.keymap.set(&quot;n&quot;, &quot;&amp;lt;leader&amp;gt;rn&quot;, vim.lsp.buf.rename, opts)
    vim.keymap.set(&quot;n&quot;, &quot;&amp;lt;leader&amp;gt;ca&quot;, vim.lsp.buf.code_action, opts)

    -- 診断の移動
    vim.keymap.set(&quot;n&quot;, &quot;[d&quot;, vim.diagnostic.goto_prev, opts)
    vim.keymap.set(&quot;n&quot;, &quot;]d&quot;, vim.diagnostic.goto_next, opts)
    vim.keymap.set(&quot;n&quot;, &quot;&amp;lt;leader&amp;gt;e&quot;, vim.diagnostic.open_float, opts)
  end,
})
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;なぜLspAttachイベントを使うか&lt;/h4&gt;
&lt;p&gt;キーマップの設定方法には複数の選択肢があります：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;方法&lt;/th&gt;
&lt;th&gt;説明&lt;/th&gt;
&lt;th&gt;問題点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;グローバルキーマップ&lt;/td&gt;
&lt;td&gt;全バッファで有効&lt;/td&gt;
&lt;td&gt;LSPがないファイルでもキーが有効&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lspconfig.on_attach&lt;/td&gt;
&lt;td&gt;lspconfig経由で設定&lt;/td&gt;
&lt;td&gt;lspconfigに依存&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LspAttachイベント&lt;/td&gt;
&lt;td&gt;LSPアタッチ時に設定&lt;/td&gt;
&lt;td&gt;なし&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;code&gt;LspAttach&lt;/code&gt;はNeovimのビルトインイベントなので、プラグインに依存せず、確実に動作します。&lt;/p&gt;
&lt;h3&gt;nvim-cmpによる補完設定&lt;/h3&gt;
&lt;p&gt;補完エンジン&lt;code&gt;nvim-cmp&lt;/code&gt;の基本設定です。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &quot;hrsh7th/nvim-cmp&quot;,
  dependencies = {
    &quot;hrsh7th/cmp-nvim-lsp&quot;,   -- LSP補完ソース
    &quot;hrsh7th/cmp-buffer&quot;,     -- バッファ補完
    &quot;hrsh7th/cmp-path&quot;,       -- パス補完
    &quot;L3MON4D3/LuaSnip&quot;,       -- スニペットエンジン
    &quot;saadparwaiz1/cmp_luasnip&quot;, -- スニペット補完
  },
  config = function()
    local cmp = require(&quot;cmp&quot;)
    local luasnip = require(&quot;luasnip&quot;)

    cmp.setup({
      -- スニペット展開の設定
      snippet = {
        expand = function(args)
          luasnip.lsp_expand(args.body)
        end,
      },

      -- キーマップ
      mapping = cmp.mapping.preset.insert({
        [&quot;&amp;lt;C-Space&amp;gt;&quot;] = cmp.mapping.complete(),   -- 手動で補完を開く
        [&quot;&amp;lt;C-e&amp;gt;&quot;] = cmp.mapping.abort(),          -- 補完をキャンセル
        [&quot;&amp;lt;CR&amp;gt;&quot;] = cmp.mapping.confirm({ select = true }), -- 確定
        [&quot;&amp;lt;Tab&amp;gt;&quot;] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_next_item()  -- 次の候補
          else
            fallback()
          end
        end, { &quot;i&quot;, &quot;s&quot; }),
        [&quot;&amp;lt;S-Tab&amp;gt;&quot;] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_prev_item()  -- 前の候補
          else
            fallback()
          end
        end, { &quot;i&quot;, &quot;s&quot; }),
      }),

      -- 補完ソースの優先順位
      sources = cmp.config.sources({
        { name = &quot;nvim_lsp&quot; },  -- LSP（最優先）
        { name = &quot;luasnip&quot; },   -- スニペット
      }, {
        { name = &quot;buffer&quot; },    -- バッファ内の単語
        { name = &quot;path&quot; },      -- ファイルパス
      }),
    })
  end,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;補完ソースの優先順位は、最初のグループ（LSP、スニペット）が優先され、該当がなければ次のグループ（バッファ、パス）から候補が表示されます。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;設定ファイルの構成について&lt;/h2&gt;
&lt;p&gt;この記事で紹介した設定は、すべて&lt;code&gt;~/.config/nvim/init.lua&lt;/code&gt;一つにまとめています。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;なぜ単一ファイルにしたか&lt;/strong&gt;:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;構成&lt;/th&gt;
&lt;th&gt;メリット&lt;/th&gt;
&lt;th&gt;デメリット&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;単一ファイル&lt;/td&gt;
&lt;td&gt;全体が見渡せる、検索しやすい&lt;/td&gt;
&lt;td&gt;長くなると見づらい&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;複数ファイル&lt;/td&gt;
&lt;td&gt;責務が明確、大規模向き&lt;/td&gt;
&lt;td&gt;ファイル間の依存関係が複雑&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;400行程度の設定であれば、単一ファイルで十分管理できます。設定が増えてきたら分割を検討すれば良いでしょう。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;まとめ&lt;/h2&gt;
&lt;p&gt;この記事では、macOSでNeovimを快適に使うための4つの設定を解説しました。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;IME問題&lt;/strong&gt;: &lt;code&gt;im-select.nvim&lt;/code&gt; + &lt;code&gt;macism&lt;/code&gt;で解決。&lt;code&gt;set_previous_events = {}&lt;/code&gt;で常に英数に戻す設定がプログラミング向き&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Neovim 0.11互換性&lt;/strong&gt;: Telescopeは&lt;code&gt;0.1.x&lt;/code&gt;タグを使用（修正済み）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nerd Font不要&lt;/strong&gt;: 各プラグインでアイコンを無効化すればシンプルな環境が作れる&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LSP/補完&lt;/strong&gt;: mason.nvim + nvim-cmpの組み合わせで、GUIでの管理と豊富な補完が実現&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;これらの設定は、あくまで一つの選択肢です。使っていく中で、自分の好みや用途に合わせてカスタマイズしていってください。&lt;/p&gt;
&lt;h2&gt;参考資料&lt;/h2&gt;
&lt;h3&gt;公式ドキュメント&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://neovim.io/doc/user/lsp.html&quot;&gt;Neovim Documentation - LSP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gpanders.com/blog/whats-new-in-neovim-0-11/&quot;&gt;What&apos;s New in Neovim 0.11&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;プラグイン&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/keaising/im-select.nvim&quot;&gt;im-select.nvim&lt;/a&gt; - IME自動切り替え&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/laishulu/macism&quot;&gt;macism&lt;/a&gt; - macOS用IME制御CLI&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/neovim/nvim-lspconfig&quot;&gt;nvim-lspconfig&lt;/a&gt; - LSP設定&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/williamboman/mason.nvim&quot;&gt;mason.nvim&lt;/a&gt; - 言語サーバー管理&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/hrsh7th/nvim-cmp&quot;&gt;nvim-cmp&lt;/a&gt; - 補完エンジン&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/nvim-telescope/telescope.nvim&quot;&gt;telescope.nvim&lt;/a&gt; - ファジーファインダー&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/folke/lazy.nvim&quot;&gt;lazy.nvim&lt;/a&gt; - プラグインマネージャー&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;関連記事&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://davelage.com/posts/neovim-lsp-0.11/&quot;&gt;Neovim LSP 0.11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.diovani.com/technology/2025/06/13/configuring-neovim-011-lsp.html&quot;&gt;Configuring Neovim 0.11 LSP from scratch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://0xunicorn.com/neovim-native-lsp-config/&quot;&gt;Native LSP config in Neovim V0.11&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://zeroshotlog.com/images/2025/12/30/neovim-macos.png" length="0" type="image/png"/></item><item><title>GitとGitHub CLIの複数アカウントを、cdするだけで自動切り替えする</title><link>https://zeroshotlog.com/blog/git-github-multi-account-auto-switch/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/git-github-multi-account-auto-switch/</guid><description>仕事用と個人用のGitHubアカウントを、ディレクトリ移動だけで自動切り替えする方法。includeIf + insteadOf + gh関数ラッパーの3層設定で完全自動化を実現します。</description><pubDate>Tue, 30 Dec 2025 10:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;TL;DR&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;仕事用と個人用のGitHubアカウントを使い分けるには、&lt;strong&gt;3層の設定&lt;/strong&gt;が必要&lt;/li&gt;
&lt;li&gt;&lt;code&gt;includeIf&lt;/code&gt; + &lt;code&gt;insteadOf&lt;/code&gt; + &lt;code&gt;gh&lt;/code&gt;関数ラッパーを組み合わせることで完全自動化&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/work/&lt;/code&gt;配下にcdするだけで、すべてが仕事用に切り替わる&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;2026年1月 更新&lt;/strong&gt;: 層3の&lt;code&gt;gh&lt;/code&gt;コマンド切り替え方式を改善しました。以前の&lt;code&gt;chpwd&lt;/code&gt;フック + &lt;code&gt;gh auth switch&lt;/code&gt;方式から、関数ラッパー + &lt;code&gt;GH_TOKEN&lt;/code&gt;環境変数方式に変更しています。複数ターミナルウィンドウでの並行作業に対応しました。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;背景・課題&lt;/h2&gt;
&lt;h3&gt;解決したかった問題&lt;/h3&gt;
&lt;p&gt;「仕事用と個人用のGitHubアカウントを使い分けたい」&lt;/p&gt;
&lt;p&gt;これは多くの開発者が直面する課題です。手動で切り替えることもできますが、以下の問題がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;切り替え忘れ&lt;/strong&gt;: 個人リポジトリに仕事用のメールアドレスでコミットしてしまう&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;操作の煩雑さ&lt;/strong&gt;: &lt;code&gt;git config&lt;/code&gt;やSSHキーを毎回手動で切り替えるのは面倒&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gh CLIの存在&lt;/strong&gt;: GitだけでなくGitHub CLI（&lt;code&gt;gh&lt;/code&gt;）も別途切り替えが必要&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;理想の状態&lt;/h3&gt;
&lt;p&gt;「ディレクトリを移動するだけで、すべてが自動で切り替わる」&lt;/p&gt;
&lt;p&gt;具体的には、&lt;code&gt;~/work/&lt;/code&gt;配下に移動したら仕事用、それ以外は個人用として、以下がすべて自動で切り替わる状態を目指しました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gitのコミット情報（&lt;code&gt;user.name&lt;/code&gt;、&lt;code&gt;user.email&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;SSHキー（GitHubへの認証）&lt;/li&gt;
&lt;li&gt;GitHub CLI（&lt;code&gt;gh&lt;/code&gt;コマンド）のアカウント&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;検討した選択肢&lt;/h2&gt;
&lt;h3&gt;選択肢A: 手動で都度設定&lt;/h3&gt;
&lt;p&gt;各リポジトリで &lt;code&gt;git config user.email&lt;/code&gt; を手動設定する方法です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;メリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;追加の設定が不要&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;デメリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;リポジトリを作るたびに設定が必要&lt;/li&gt;
&lt;li&gt;設定し忘れると間違ったアカウントでコミットしてしまう&lt;/li&gt;
&lt;li&gt;SSHキーやgh CLIは別途管理が必要&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;選択肢B: direnv + GH_TOKEN&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://direnv.net/&quot;&gt;direnv&lt;/a&gt;を使って、ディレクトリごとに環境変数を設定する方法です。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# ~/work/.envrc
export GH_TOKEN=&quot;ghp_xxxx&quot;
export GIT_AUTHOR_EMAIL=&quot;work@example.com&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;メリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;環境変数で統一的に管理できる&lt;/li&gt;
&lt;li&gt;direnvは広く使われているツール&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;デメリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;direnvの追加インストールが必要&lt;/li&gt;
&lt;li&gt;トークンをファイルに書く必要がある（セキュリティ懸念）&lt;/li&gt;
&lt;li&gt;プロジェクトごとに&lt;code&gt;.envrc&lt;/code&gt;が必要&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;選択肢C: includeIf + insteadOf + gh関数ラッパー（採用）&lt;/h3&gt;
&lt;p&gt;Gitの標準機能とシェル関数を組み合わせる方法です。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;メリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;追加ツール不要（Git/Zsh標準機能を使用）&lt;/li&gt;
&lt;li&gt;設定は一度だけ、以降は自動&lt;/li&gt;
&lt;li&gt;トークンをファイルに書く必要がない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;デメリット&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;設定項目が多い（3層の設定が必要）&lt;/li&gt;
&lt;li&gt;仕組みの理解が必要&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;比較表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;観点&lt;/th&gt;
&lt;th&gt;手動設定&lt;/th&gt;
&lt;th&gt;direnv&lt;/th&gt;
&lt;th&gt;includeIf+α（採用）&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;初期設定の手間&lt;/td&gt;
&lt;td&gt;なし&lt;/td&gt;
&lt;td&gt;中&lt;/td&gt;
&lt;td&gt;大&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;日常の手間&lt;/td&gt;
&lt;td&gt;大&lt;/td&gt;
&lt;td&gt;小&lt;/td&gt;
&lt;td&gt;なし&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;追加ツール&lt;/td&gt;
&lt;td&gt;不要&lt;/td&gt;
&lt;td&gt;direnv&lt;/td&gt;
&lt;td&gt;不要&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;セキュリティ&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;トークンをファイルに保存&lt;/td&gt;
&lt;td&gt;OSキーチェーン&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;設定忘れのリスク&lt;/td&gt;
&lt;td&gt;高&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;td&gt;なし&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;複数ウィンドウでの並行作業&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;対応&lt;/td&gt;
&lt;td&gt;対応&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;最終判断&lt;/h2&gt;
&lt;h3&gt;採用: includeIf + insteadOf + gh関数ラッパー&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;決め手となった理由&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;追加ツール不要&lt;/strong&gt;: GitとZshの標準機能だけで実現できる&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;設定忘れがない&lt;/strong&gt;: ディレクトリ構造に基づいて自動で判定される&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;セキュリティ&lt;/strong&gt;: gh CLIのトークンはOSのキーチェーンに保存される&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;複数ウィンドウ対応&lt;/strong&gt;: 環境変数でプロセスごとに認証するため、他のターミナルに影響しない&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;受け入れたトレードオフ&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;初期設定は複雑になる（この記事で解説します）&lt;/li&gt;
&lt;li&gt;仕組みを理解していないとトラブルシューティングが難しい&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;なぜ「3層」が必要なのか&lt;/h2&gt;
&lt;p&gt;ここからが本題です。GitとGitHubのアカウント切り替えには、&lt;strong&gt;3つの異なる設定&lt;/strong&gt;が必要です。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────────────────────────────────────┐
│                   あなたのPC                        │
├─────────────────────────────────────────────────────┤
│                                                     │
│  [層1] Gitのuser設定                                │
│    → コミットに記録される名前・メールアドレス       │
│    → .gitconfig の includeIf で切り替え            │
│                                                     │
│  [層2] SSHキー                                      │
│    → GitHubへpush/pullするときの認証               │
│    → SSH Hostエイリアス + insteadOf で切り替え     │
│                                                     │
│  [層3] gh CLIのアカウント                           │
│    → gh pr create などGitHub操作時のアカウント      │
│    → gh関数ラッパー + GH_TOKEN で切り替え          │
│                                                     │
└─────────────────────────────────────────────────────┘
                         │
                         ▼
              ┌─────────────────────┐
              │      GitHub         │
              │  (個人 or 仕事用)   │
              └─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;なぜ別々に設定が必要なのか&lt;/h3&gt;
&lt;p&gt;それぞれが&lt;strong&gt;異なるタイミング&lt;/strong&gt;で使われるからです。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;層&lt;/th&gt;
&lt;th&gt;いつ使われるか&lt;/th&gt;
&lt;th&gt;何を識別するか&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;層1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git commit&lt;/code&gt; 時&lt;/td&gt;
&lt;td&gt;コミットの作者（Author）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;層2&lt;/td&gt;
&lt;td&gt;&lt;code&gt;git push/pull&lt;/code&gt; 時&lt;/td&gt;
&lt;td&gt;GitHubへの接続認証&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;層3&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gh pr create&lt;/code&gt; 等&lt;/td&gt;
&lt;td&gt;GitHub APIの操作者&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;例えば、層1だけ設定しても、push時に間違ったSSHキーが使われてしまいます。3層すべてを正しく設定して初めて、完全な切り替えが実現します。&lt;/p&gt;
&lt;h2&gt;各層の設定方法&lt;/h2&gt;
&lt;p&gt;以下、&lt;code&gt;~/work/&lt;/code&gt;配下を仕事用、それ以外を個人用として設定する例を示します。&lt;/p&gt;
&lt;h3&gt;層1: includeIfによるuser設定の自動切り替え&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;includeIf&lt;/code&gt;は、条件に応じて別の設定ファイルを読み込むGitの機能です。&lt;/p&gt;
&lt;h4&gt;~/.gitconfig（メインの設定ファイル）&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# デフォルト（個人用）の設定
[user]
    name = Your Personal Name
    email = personal@example.com

# ~/work/ 配下では仕事用設定を追加で読み込む
[includeIf &quot;gitdir:~/work/&quot;]
    path = ~/.gitconfig-work
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;~/.gitconfig-work（仕事用の設定ファイル）&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;[user]
    name = Your Work Name
    email = work@company.com
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;解説&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[includeIf &quot;gitdir:~/work/&quot;]&lt;/code&gt;: 現在のリポジトリが &lt;code&gt;~/work/&lt;/code&gt; 配下にある場合に適用&lt;/li&gt;
&lt;li&gt;&lt;code&gt;path = ~/.gitconfig-work&lt;/code&gt;: この設定ファイルを読み込む&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;重要なポイント&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gitdir:&lt;/code&gt; の後のパスは&lt;strong&gt;末尾に &lt;code&gt;/&lt;/code&gt; を付ける&lt;/strong&gt;（&lt;code&gt;~/work/&lt;/code&gt; であって &lt;code&gt;~/work&lt;/code&gt; ではない）&lt;/li&gt;
&lt;li&gt;末尾の &lt;code&gt;/&lt;/code&gt; は &lt;code&gt;**&lt;/code&gt;（任意のサブディレクトリ）として解釈される&lt;/li&gt;
&lt;li&gt;後から読み込まれた設定が優先される（だから仕事用の&lt;code&gt;user.name&lt;/code&gt;で上書きされる）&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;動作確認&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 個人用ディレクトリで確認
cd ~/personal/some-repo
git config user.email
# → personal@example.com

# 仕事用ディレクトリで確認
cd ~/work/some-project
git config user.email
# → work@company.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;設定が正しく読み込まれているかは、以下のコマンドで詳しく確認できます。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git config --list --show-origin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;これにより、各設定がどのファイルから来ているかが表示されます。&lt;/p&gt;
&lt;h3&gt;層2: SSH Hostエイリアス + insteadOfによるSSHキー切り替え&lt;/h3&gt;
&lt;p&gt;SSHキーの切り替えは2つの設定を組み合わせます。&lt;/p&gt;
&lt;h4&gt;ステップ1: SSH設定ファイルでHostエイリアスを定義&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;~/.ssh/config&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 個人用（デフォルト）
Host github.com
    IdentityFile ~/.ssh/id_ed25519_personal

# 仕事用（エイリアス）
Host github-work
    HostName github.com
    IdentityFile ~/.ssh/id_ed25519_work
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;解説&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Host github.com&lt;/code&gt;: &lt;code&gt;github.com&lt;/code&gt;に接続するときの設定&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Host github-work&lt;/code&gt;: &lt;code&gt;github-work&lt;/code&gt;という&lt;strong&gt;架空のホスト名&lt;/strong&gt;を定義
&lt;ul&gt;
&lt;li&gt;実際の接続先は &lt;code&gt;HostName github.com&lt;/code&gt;（本物のGitHub）&lt;/li&gt;
&lt;li&gt;でも使うSSHキーは &lt;code&gt;id_ed25519_work&lt;/code&gt;（仕事用）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;これにより、&lt;code&gt;git@github-work:org/repo.git&lt;/code&gt;にアクセスすると、仕事用のSSHキーが使われます。&lt;/p&gt;
&lt;h4&gt;ステップ2: GitのinsteadOfでURLを自動変換&lt;/h4&gt;
&lt;p&gt;仕事用リポジトリでは、&lt;code&gt;github.com&lt;/code&gt;へのアクセスを自動的に&lt;code&gt;github-work&lt;/code&gt;に書き換えます。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/.gitconfig-work&lt;/code&gt; に以下を追加します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[user]
    name = Your Work Name
    email = work@company.com

# SSH形式のURLを変換
[url &quot;git@github-work:&quot;]
    insteadOf = git@github.com:

# HTTPS形式のURLも変換
[url &quot;git@github-work:&quot;]
    insteadOf = https://github.com/
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;解説&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;insteadOf&lt;/code&gt;: GitがURLを解決するとき、自動的に置換する&lt;/li&gt;
&lt;li&gt;例えば &lt;code&gt;git clone git@github.com:org/repo.git&lt;/code&gt; を実行すると
&lt;ul&gt;
&lt;li&gt;内部的には &lt;code&gt;git@github-work:org/repo.git&lt;/code&gt; に変換される&lt;/li&gt;
&lt;li&gt;SSH設定により &lt;code&gt;github-work&lt;/code&gt; は仕事用SSHキーで接続される&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;動作確認&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 仕事用リポジトリでリモートURLを確認
cd ~/work/some-project
git remote -v
# → origin  git@github.com:company/repo.git (fetch)
#    ↑ 表示はgithub.comのまま

# 実際に使われるURLを確認
git config --get-regexp &apos;url.*&apos;
# → url.git@github-work:.insteadof git@github.com:
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;層3: gh関数ラッパーによるgh CLIアカウント切り替え&lt;/h3&gt;
&lt;p&gt;GitHub CLI（&lt;code&gt;gh&lt;/code&gt;）は、v2.40.0から複数アカウントのサポートが追加されました。&lt;/p&gt;
&lt;h4&gt;事前準備: 両方のアカウントでログイン&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 1つ目のアカウントでログイン
gh auth login

# 2つ目のアカウントでログイン（追加される）
gh auth login

# ログイン状況を確認
gh auth status
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;gh auth status&lt;/code&gt;を実行すると、ログイン済みの全アカウントと、現在アクティブなアカウントが表示されます。&lt;/p&gt;
&lt;h4&gt;~/.zshrcへの設定追加&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;########################################
# GitHub CLI アカウント切り替え（関数ラッパー方式）
# ~/work 配下では仕事用、それ以外は個人用
# アカウント名は ~/.zshrc.local で設定:
#   GH_PERSONAL_ACCOUNT=&quot;your-personal&quot;
#   GH_WORK_ACCOUNT=&quot;your-work&quot;
########################################
gh() {
  local token
  if [[ &quot;$PWD&quot; == &quot;$HOME/work&quot;* ]]; then
    token=$(command gh auth token --user &quot;$GH_WORK_ACCOUNT&quot; 2&amp;gt;/dev/null)
  else
    token=$(command gh auth token --user &quot;$GH_PERSONAL_ACCOUNT&quot; 2&amp;gt;/dev/null)
  fi

  if [[ -n &quot;$token&quot; ]]; then
    GH_TOKEN=&quot;$token&quot; command gh &quot;$@&quot;
  else
    command gh &quot;$@&quot;
  fi
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;~/.zshrc.local でアカウント名を設定&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# GitHubのユーザー名を設定
GH_PERSONAL_ACCOUNT=&quot;your-personal-username&quot;
GH_WORK_ACCOUNT=&quot;your-work-username&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;解説&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;関数ラッパー方式とは&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;シェル関数で&lt;code&gt;gh&lt;/code&gt;コマンドをラップし、実行時にディレクトリをチェックして適切なトークンを使用します。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;要素&lt;/th&gt;
&lt;th&gt;説明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gh auth token --user&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;指定アカウントのトークンを取得&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GH_TOKEN=&quot;...&quot; command gh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;環境変数をそのコマンドにのみ渡す（プロセスローカル）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;command gh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;関数ではなく実際の&lt;code&gt;gh&lt;/code&gt;コマンドを呼ぶ&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;command&lt;/code&gt;キーワードのポイント&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;command gh &quot;$@&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;シェル関数内で&lt;code&gt;gh&lt;/code&gt;を呼ぶと再帰的に自分自身が呼ばれてしまいます。&lt;code&gt;command&lt;/code&gt;キーワードを使うことで、関数ではなく実際のコマンドを呼び出します。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;なぜこの方式を採用したか&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;以前は&lt;code&gt;chpwd&lt;/code&gt;フック + &lt;code&gt;gh auth switch&lt;/code&gt;方式を使用していましたが、&lt;strong&gt;複数のターミナルウィンドウで並行作業する際に問題&lt;/strong&gt;がありました。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;旧方式: &lt;code&gt;gh auth switch&lt;/code&gt;はグローバル設定を変更するため、片方のウィンドウでの切り替えがもう片方にも影響する&lt;/li&gt;
&lt;li&gt;新方式: &lt;code&gt;GH_TOKEN&lt;/code&gt;環境変数はそのコマンドの実行時のみ有効（プロセスローカル）なので、他のウィンドウに影響しない&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;なぜ~/.zshrc.localにアカウント名を書くのか&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;アカウント名は個人情報なので、dotfilesリポジトリには含めたくない&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.zshrc.local&lt;/code&gt;はGit管理外のファイルとして運用する&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;動作確認&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;# 仕事用ディレクトリで確認
cd ~/work/some-project
gh api user --jq &apos;.login&apos;
# → work-username

# 個人用ディレクトリで確認
cd ~/personal/my-repo
gh api user --jq &apos;.login&apos;
# → personal-username
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;: &lt;code&gt;gh auth status&lt;/code&gt;はグローバル設定を表示するため、関数ラッパー方式では現在の状態を正確に反映しません。実際に使用されるアカウントを確認するには、上記のように&lt;code&gt;gh api user&lt;/code&gt;を使用してください。&lt;/p&gt;
&lt;h2&gt;全体の動作確認&lt;/h2&gt;
&lt;p&gt;設定が完了したら、以下の手順で確認します。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 1. 個人用ディレクトリで確認
cd ~/personal/my-repo
git config user.email          # → personal@example.com
gh api user --jq &apos;.login&apos;      # → personal-username

# 2. 仕事用ディレクトリで確認
cd ~/work/company-project
git config user.email          # → work@company.com
gh api user --jq &apos;.login&apos;      # → work-username

# 3. 実際にpushできるか確認（仕事用リポジトリで）
git push --dry-run             # 仕事用SSHキーで認証される
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;採用後の結果&lt;/h2&gt;
&lt;h3&gt;うまくいったこと&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;切り替え忘れがゼロに&lt;/strong&gt;: ディレクトリ構造で自動判定されるので、意識する必要がない&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作業開始の手間が消えた&lt;/strong&gt;: 以前は毎回「どのアカウントだっけ」と確認していた&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;トラブルが減った&lt;/strong&gt;: 間違ったアカウントでコミット/プッシュする事故がなくなった&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;複数ウィンドウでの並行作業が可能に&lt;/strong&gt;: 関数ラッパー方式により、仕事用と個人用のターミナルを同時に開いて作業できるようになった&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;改善の経緯&lt;/h3&gt;
&lt;p&gt;当初は&lt;code&gt;chpwd&lt;/code&gt;フック + &lt;code&gt;gh auth switch&lt;/code&gt;方式を採用していましたが、&lt;strong&gt;複数のターミナルウィンドウで並行作業する際に問題&lt;/strong&gt;が発生しました。&lt;code&gt;gh auth switch&lt;/code&gt;はグローバル設定を変更するため、片方のウィンドウでの切り替えがもう片方にも影響してしまいます。&lt;/p&gt;
&lt;p&gt;そこで関数ラッパー + &lt;code&gt;GH_TOKEN&lt;/code&gt;環境変数方式に変更しました。この方式では：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;環境変数はコマンド実行時のみ有効（プロセスローカル）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd&lt;/code&gt;時のフックが不要でシンプル&lt;/li&gt;
&lt;li&gt;グローバル設定（&lt;code&gt;gh auth status&lt;/code&gt;）を変更しない&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;学んだこと&lt;/h2&gt;
&lt;h3&gt;1. GitとGitHubの認証は別物&lt;/h3&gt;
&lt;p&gt;「Git設定を変えればOK」と思いがちですが、実際にはSSH認証、GitHub API認証など複数のレイヤーがあります。それぞれを理解して設定する必要があります。&lt;/p&gt;
&lt;h3&gt;2. 標準機能の組み合わせで実現できる&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;includeIf&lt;/code&gt;、&lt;code&gt;insteadOf&lt;/code&gt;、シェル関数はすべて標準機能です。新しいツールを追加しなくても、既存の仕組みの組み合わせで目的を達成できました。&lt;/p&gt;
&lt;h3&gt;3. UXを追求する価値&lt;/h3&gt;
&lt;p&gt;「cdするだけ」という体験にこだわりました。設定は複雑ですが、日常の操作はシンプルになります。初期投資と日常のコストのバランスを考えて判断することが重要です。&lt;/p&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;h3&gt;公式ドキュメント&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://cli.github.com/manual/gh_auth_token&quot;&gt;gh auth token - GitHub CLI Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.github.com/en/github-cli/github-cli/using-multiple-accounts&quot;&gt;Using the GitHub CLI across GitHub platforms - GitHub Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git-scm.com/docs/git-config#_includes&quot;&gt;git-config - includeIf - Git Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;関連記事&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.blog/changelog/2023-12-17-log-in-to-multiple-github-accounts-with-the-cli/&quot;&gt;Log in to multiple GitHub accounts with the CLI - GitHub Changelog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gist.github.com/bgauduch/06a8c4ec2fec8fef6354afe94358c89e&quot;&gt;Git config with multiple identities - GitHub Gist&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><enclosure url="https://zeroshotlog.com/images/2025/12/30/git-multi-account.png" length="0" type="image/png"/></item><item><title>Astroで技術ブログを構築しました</title><link>https://zeroshotlog.com/blog/hello-world/</link><guid isPermaLink="true">https://zeroshotlog.com/blog/hello-world/</guid><description>Astro + Tailwind CSS + Vercelで爆速な技術ブログを作ってみました。構成の選定理由や構築手順について紹介します。</description><pubDate>Tue, 30 Dec 2025 09:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Zero-Shot Logへようこそ&lt;/h2&gt;
&lt;p&gt;このブログは &lt;strong&gt;Astro&lt;/strong&gt; で構築されています。&lt;/p&gt;
&lt;h3&gt;なぜAstroなのか？&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;パフォーマンス&lt;/strong&gt;: 不要なJavaScriptを排除し、静的サイトとしての最速のパフォーマンスを実現します。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DX (Developer Experience)&lt;/strong&gt;: React, Vue, Svelteなど好きなフレームワークのコンポーネントを利用できます。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Markdown重視&lt;/strong&gt;: コンテンツをMarkdownで管理できるため、エンジニアにとって非常に扱いやすいです。&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;console.log(&quot;Hello, Astro!&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;これから技術的な知見をどんどん発信していきます！&lt;/p&gt;
</content:encoded><enclosure url="https://zeroshotlog.com/images/2025/12/30/astro-blog.png" length="0" type="image/png"/></item></channel></rss>