GitHub Copilotコンテキスト注入の内部メカニズム【図解】¶
対象:
GitHub CopilotまたはClaude Codeのインストラクション設定を使っているが、「なぜそう設定すべきか」の技術的根拠を理解したい開発者
この記事のポイント¶
- Copilotのカスタムインストラクションは、VS Codeチームの実装解説によればchat context(system prompt側)に追加される。Claude CodeのCLAUDE.mdは公式仕様でUser Messageとして注入される。この違いがルールの持続性を決定的に分ける
- Copilotの簡潔さが必要な主因は「毎リクエストごとのコンテキスト消費」。ただし長すぎると見落とされる(context limits)問題も別途ある
- 両ツールの仕組みを理解すると、「何をどこに書くか」の判断基準が明確になる
背景:「なぜ簡潔に」の根拠が曖昧なまま広まった問題¶
GitHub Copilotのカスタムインストラクションに関するベストプラクティスとして、「ファイルは簡潔に保つべき」「外部ドキュメントへの参照を活用すべき」という指針が広く知られている。
しかし、なぜ簡潔に保つ必要があるのか——その技術的根拠まで踏み込んだ解説は少ない。
「公式が推奨しているから」ではなく、LLMへのプロンプト注入の仕組みを理解することで、インストラクション設計の判断基準が根本から変わる。
本記事では、GitHub CopilotとClaude Codeの内部メカニズムを比較しながら、「何をどこに書くべきか」の技術的根拠を解説する。
関連記事
カスタムインストラクションの具体的な設定方法・ベストプラクティスについては GitHub Copilot カスタムインストラクション完全ガイド を参照。
GitHub Copilotの内部プロンプト構造¶
LLMに送られるプロンプトの全体像¶
GitHub Copilot(VS Code)がLLMにリクエストを送る際、プロンプトは大きくSystem PromptとUser Messageの2つの領域で構成される。VS Codeチームメンバーの実装解説1によれば、カスタムインストラクションはSystem Prompt側に追加されると説明されている(公式ドキュメント上は "chat contextへ追加" という表現で、内部領域の保証までは明言されていない2)。
graph TB
subgraph SP["🔒 System Prompt / Chat Context(モデルの振る舞いの基盤)"]
direction TB
A["Core Identity & Global Rules<br><i>例: あなたはエキスパートのAIプログラミングアシスタントです...</i>"]
B["General Instructions<br><i>モデル別に動的変化</i>"]
C["Tool Use Instructions<br><i>ターミナル実行・ファイル編集のガイドライン</i>"]
D["Output Format Instructions<br><i>応答のフォーマット規則</i>"]
E["📄 .instructions.md の内容<br><i>applyTo / semantic matchingで条件付き追加</i>"]:::inst
F["📄 copilot-instructions.md の内容<br><i>chat contextへ追加(個人 > リポジトリ > 組織の優先度)</i>"]:::inst
G["📄 Custom Agent の指示<br><i>使用時のみ追記</i>"]:::inst
A --> B --> C --> D --> E --> F --> G
end
subgraph UM["💬 User Message(会話の一部)"]
direction TB
H["Prompt Files の内容<br><i>明示的に参照した場合のみ</i>"]
I["Environment / Workspace Info<br><i>OS情報、ディレクトリ構造</i>"]
J["Editor Context<br><i>開いているファイル、選択範囲</i>"]
K["ユーザーの実際のプロンプト"]
H --> I --> J --> K
end
SP --> UM
classDef inst fill:#0288d1,color:#ffffff,stroke:#01579b,stroke-width:2px出典について
上図の構造はVS Codeチームメンバー(Burke Holland)の実装解説1に基づく。公式ドキュメントは「chat contextへ結合して追加する」と表現しており、各要素の内部的な配置順序や領域区分までは仕様として保証されていない2。
インストラクションの注入が意味すること¶
instructionsはリクエストごとにchat contextに含まれる。VS Codeチームの解説では「system prompt側に追加される」とされているが、その特性として重要なのは以下の2点である。
持続性: 「ターンが進むほど位置が古くなる」タイプの減衰(Claude Code の CLAUDE.md がこれにあたる)とは異なり、毎リクエスト時点で新しくコンテキストが組み立てられる。このため、セッション後半でも適用ルールの重みは原理的に変わらない。
コスト: instructionsのトークンは毎回のリクエストで消費される。100行のインストラクションを書けば、そのトークン分だけコード生成や応答に使えるコンテキスト枠が減る。また、非常に長い場合は一部の指示が見落とされることがある(context limits3)。
つまり、Copilotにおいて「簡潔に保つべき」主因は、ターン後半での位置的な減衰ではなく、毎回のリクエストでのコンテキスト消費である。ただし、「長すぎると見落とされる」問題(context limits)は別途存在する点も押さえておく必要がある。
applyToによるpath-specific instructionsの適用タイミング¶
.instructions.mdファイルのYAML FrontmatterでapplyToを指定した場合、そのインストラクションは条件に一致したリクエスト時のみchat contextに追加される2。
適用判定は2つの経路がある。
- applyTo glob一致: 開いているファイルのパスが
applyToパターンに一致した場合 - semantic matching: タスク内容からエージェントが関連性を判断した場合
sequenceDiagram
participant Dev as 開発者
participant VSCode as VS Code
participant LLM as LLM
Dev->>VSCode: src/api/users.ts を開いてChat質問
VSCode->>VSCode: applyTo glob / semantic matchingで評価
VSCode->>LLM: chat contextに<br>backend.instructions.md を追加
Note over LLM: ※各リクエストで再評価。<br>このリクエストのコンテキスト:<br>copilot-instructions.md +<br>backend.instructions.md
Dev->>VSCode: src/components/Button.tsx を開いてChat質問
VSCode->>VSCode: applyTo glob / semantic matchingで評価
VSCode->>LLM: chat contextに<br>frontend.instructions.md を追加
Note over LLM: ※各リクエストで再評価。<br>このリクエストのコンテキスト:<br>copilot-instructions.md +<br>frontend.instructions.mdこの仕組みにより、必要なルールを必要な場面でのみ追加できる。全ルールをcopilot-instructions.mdに詰め込む必要がない。なお、前のリクエストで適用されたpath-specificなinstructionsが次のリクエストに自動で引き継がれるわけではなく、毎回リクエスト時点で再評価・再組み立てされる。
Copilot Code Reviewの制約¶
Copilot Code Reviewでは、カスタムインストラクションファイルの最初の4,000文字のみが読み込まれる3。この制限はCopilot ChatやCoding Agentには適用されないが、レビュー用途では特にインストラクションの優先順位付けが重要になる。copilot-instructions.mdの推奨サイズ目安(50行 ≈ 1,500〜2,000文字)であれば、Code Reviewでも全文が読み込まれる計算になる。
公式が認めている3つの限界¶
GitHub公式ドキュメントでは、カスタムインストラクションの以下の限界が明示されている3。
非決定的な振る舞い: Copilotがすべてのインストラクションに毎回完璧に従うとは限らない。LLMの確率的な性質に起因する。
コンテキスト制限: 非常に長いインストラクションファイルは、一部の指示が無視される可能性がある。
具体性の重要性: 曖昧な指示よりも、明確で具体的な指示の方が効果が高い。
Agent Skillsのオンデマンド注入:第3の仕組み¶
Custom InstructionsともapplyToとも異なる、第3の注入メカニズムがAgent Skillsに存在する。
VS Code公式ドキュメントによると、Skillsは3段階の段階的開示(Progressive Disclosure)で動作する7。
| 段階 | 読み込まれるもの | タイミング |
|---|---|---|
| Level 1 | name と description のみ | 常時(name/descriptionを用いた発見・関連判定用。入力への含め方は実装依存7) |
| Level 2 | SKILL.md本文(指示・ガイドライン) | エージェントが関連性を判断した時、またはユーザーが / で明示的に呼び出した時 |
| Level 3 | バンドルされたリソース(scripts/, references/, templates/) | Skill内の指示がそれらを参照した時 |
sequenceDiagram
participant User as ユーザー
participant Agent as Copilot Agent
participant LLM as LLM
Note over Agent,LLM: Level 1: name/descriptionを用いた<br>発見・関連判定用メタデータ<br>(配置/可視化は実装依存)
Agent->>LLM: name + description(発見判定用メタデータ)
User->>Agent: 「このコードをレビューして」
Agent->>Agent: description から関連Skillを判定
Agent->>LLM: Level 2: SKILL.md本文を注入
Note over LLM: 必要なSkillの指示のみ追加
LLM->>Agent: Skill内でリソース参照が必要
Agent->>LLM: Level 3: scripts/参照ファイルを注入この仕組みにより、必要な詳細指示をオンデマンドで注入できる。ただしトレードオフとして、Level 2以降の注入はエージェントの判断に依存するため、確実に読み込まれる保証がない。
また、大量のSkillsを登録すると可視性の上限に当たることがある8。
Claude Code(CLAUDE.md)の内部メカニズム¶
User Messageとして注入される¶
Claude Codeでは、CLAUDE.mdの内容はSystem Promptではなく、セッション最初のUser Messageとして注入される4。Copilotがchat context(system prompt側)にインストラクションを持つのと対照的な構造だ。
CLAUDE.md adds the contents as a user message following Claude Code's default system prompt.4
graph TB
subgraph SP2["🔒 System Prompt"]
direction TB
A2["Claude Code のデフォルト System Prompt"]
end
subgraph UM2["💬 User Messages(時系列順)"]
direction TB
B2["📄 CLAUDE.md の内容<br><i>セッション冒頭に注入</i>"]:::claude
C2["ユーザーのプロンプト #1"]
D2["Claude の応答 #1"]
E2["...(会話が進むほど CLAUDE.md は遠くなる)"]
F2["ユーザーのプロンプト #N"]
B2 --> C2 --> D2 --> E2 --> F2
end
SP2 --> UM2
classDef claude fill:#e65100,color:#ffffff,stroke:#bf360c,stroke-width:2pxこのUser Message注入の特性により、セッション後半ではCLAUDE.mdに書いたルールの影響力が薄れる傾向がある(lost-in-the-middle効果6)。これがCopilotとの決定的な違いであり、次の比較表で全体像を確認する。
比較:5つの注入メカニズム全体像¶
3つのツールの仕組みを並べると、「コンテキスト消費 vs ルール持続性」のトレードオフ構造が完全に見える。
| 仕組み | 追加先 | コンテキスト消費 | ルール持続性 | 読み込みタイミング |
|---|---|---|---|---|
copilot-instructions.md | chat context(system prompt側1) | 常時消費(毎リクエスト) | 高 | 常時 |
.instructions.md + applyTo | chat context(system prompt側1) | 条件付き消費 | 高 | applyTo glob一致 or semantic matching時 |
| Agent Skills | chat context(L1: 発見判定用 / L2以降: オンデマンド) | 最小(L1のみ常時、配置は実装依存) | 中(確実性に課題) | エージェント判断 or /呼び出し |
CLAUDE.md | User Message(公式仕様4) | 常時消費 | 低〜中(後半で減衰、/compact後に再注入5) | セッション開始時(/compact後に再注入) |
.claude/rules/ | コンテキスト(形式は公式未明記5) | 条件付き消費 | 中 | 該当ファイル初回操作時(遅延ロード) |
graph LR
subgraph Copilot["GitHub Copilot"]
direction TB
CopSP["System Prompt / Chat Context<br>─────────<br>copilot-instructions.md<br>.instructions.md<br>Skills(L1: 発見判定用 / L2+: オンデマンド)"]:::sp
CopUM["User Messages<br>─────────<br>Prompt Files<br>ユーザーの質問"]:::um
CopSP --- CopUM
end
subgraph ClaudeCode["Claude Code"]
direction TB
CCSP["System Prompt<br>─────────<br>デフォルトのみ<br><i>(--append-system-prompt<br>使用時は追記可)</i>"]:::sp
CCUM["User Messages<br>─────────<br>CLAUDE.md<br>.claude/rules/<br>ユーザーの質問"]:::um
CCSP --- CCUM
end
classDef sp fill:#2e7d32,color:#ffffff,stroke:#1b5e20,stroke-width:2px
classDef um fill:#b71c1c,color:#ffffff,stroke:#880e4f,stroke-width:2px設計判断への影響¶
この構造的違いから、以下の設計判断が導かれる。
Copilotの場合: ルールをSystem Promptに書けるため、「セッション全体を通じて守らせたいルール」をcopilot-instructions.mdに書くことは合理的。ただし、トークン消費を最小化するため、内容は簡潔に、詳細は外部ドキュメント参照パターンで対応する。繰り返し呼び出す専門的な指示(コード生成テンプレート、デバッグ手順など)はSkillsに分離するとコンテキスト効率が大幅に上がる。
Claude Codeの場合: CLAUDE.mdはUser Messageであるため(公式仕様4)、Copilotのchat context注入とは持続性の特性が異なる。Claude Codeの設計ベストプラクティスは別途詳しく扱う。
実践:メカニズムを踏まえたインストラクション設計¶
Copilotでの推奨構成¶
.github/
├── copilot-instructions.md # 毎リクエスト適用(常時コンテキスト消費)
│ → 技術スタック、命名規約、必須ルール
│ → 簡潔に(目安: 50行以下)
│ → 詳細は docs/ への参照で対応
│
└── instructions/
├── frontend.instructions.md # applyTo でフロントのみ
├── backend.instructions.md # applyTo でバックエンドのみ
└── testing.instructions.md # applyTo でテストのみ
→ 必要な場面でのみ追加
→ copilot-instructions.md のコンテキスト消費を節約
設計原則: instructionsは毎リクエストでコンテキストを消費するコストを意識し、「全場面で必要か?」を判断基準にする。特定パスでのみ必要なルールは.instructions.mdに分離することで、不要なトークン消費を避ける。
まとめ¶
インストラクション設計の最適解は、内部メカニズムを理解して初めて見える。
「簡潔に保つべき」の本質は、Copilotでは毎リクエストごとのコンテキスト消費(VS Codeチームの実装解説によるとsystem prompt側)であり、Claude Codeではコンテキスト内での位置的減衰(公式仕様:User Message)である。同じ結論(簡潔に保つ)でも、根拠が異なる。なお、Claude Codeの場合は/compactでCLAUDE.mdを再注入できるため、減衰の影響は「長いセッションを続ける場合」に限定される。
どちらのツールでも共通するのは、必要なルールを必要なタイミングで必要な場所に追加するという原則。applyTo / semantic matching や .claude/rules/ の paths は、まさにこの原則を実現するための機能である。
次のステップ
カスタムインストラクションの具体的な設定手順・テンプレートについては、以下の記事を参照。
🔗 関連記事¶
- GitHub Copilot カスタムインストラクション完全ガイド 設定方法・ベストプラクティスの実践ガイド
- applyToパターンガイド ファイルパス別の条件分岐型インストラクション管理
- CLAUDE.md設計ガイド Claude Code向けインストラクション設計
Burke Holland (VS Code チーム), "Prompt Files vs Custom Instructions vs Custom Agents" — VS Codeチームメンバーによる実装解説。Custom Instructionsが「system prompt側にappendされる」「always last」と説明されている。公式仕様書ではなく実装解説であることに注意。 ↩↩↩↩
VS Code 公式ドキュメント, "Use custom instructions in VS Code" — 公式は「chat contextへ結合して追加する」と表現。applyToのglob一致 + semantic matchingによる適用判定、衝突時の優先度(personal > repository > organization)が仕様として明記。ファイル結合の順序保証はない。 ↩↩↩
GitHub Docs, "Using custom instructions to unlock the power of Copilot code review" — Code Reviewの4,000文字制限、non-deterministic behavior(毎回完璧に従うとは限らない)、context limits(長すぎると見落とされる可能性)が仕様として明記。 ↩↩↩
Claude Code 公式ドキュメント, "Output styles" — 「CLAUDE.md adds the contents as a user message following Claude Code's default system prompt」と明記。--append-system-promptはsystem prompt末尾への追記。 ↩↩↩↩
Claude Code 公式ドキュメント, "Memory management" — 「Claude treats them as context, not enforced configuration」と明記。.claude/rules/はpaths条件付きで「contextへload」。注入形式(User Messageかどうか)は明記されていない。 ↩↩
CureApp テックブログ (7tsuno), "CLAUDE.mdに本当は何を書くべきなのか" — Session Start Hookとしての位置づけ、セッション後半での影響力低下の解説。二次解説として参考。 ↩
VS Code 公式ドキュメント, "Use agent skills in VS Code" — Skillsの3段階Progressive Disclosure(name/description → SKILL.md本文 → リソース)の仕組み。 ↩↩
GitHub copilot-cli Issue #1130, "Skills token limit impact on context window" — Copilot CLI で49 Skillsを登録した際に31しか表示されなかった実例報告。これはCopilot CLIの実装上の制約例であり、VS Code一般の仕様として断定できない点に注意。 ↩