最終更新:
GitHub Copilotカスタム指示: チーム開発でのAI活用最適化
カスタム指示(Custom Instructions)とは
GitHub Copilot Custom Instructionsは、プロジェクト固有のコーディング規約、アーキテクチャパターン、命名規則などをCopilotに学習させ、より的確なコード提案を受けられる機能です。2024年後半から利用可能になりました。
なぜカスタム指示が必要か
// カスタム指示なし: 一般的なReactコンポーネント
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(setUser);
}, [userId]);
return <div>{user?.name}</div>;
}
// カスタム指示あり: プロジェクトの規約に準拠
import { useQuery } from '@tanstack/react-query';
import { userApi } from '@/lib/api/user';
import type { User } from '@/types/user';
interface UserProfileProps {
userId: string;
}
export function UserProfile({ userId }: UserProfileProps) {
const { data: user, isLoading, error } = useQuery({
queryKey: ['user', userId],
queryFn: () => userApi.getById(userId),
});
if (isLoading) return <LoadingSpinner />;
if (error) return <ErrorMessage error={error} />;
if (!user) return null;
return (
<div className="user-profile">
<h2>{user.name}</h2>
</div>
);
}
セットアップ
1. .github/copilot-instructions.mdの作成
# GitHub Copilot Custom Instructions
## プロジェクト概要
このプロジェクトはNext.js 15 + TypeScriptを使用したEコマースプラットフォームです。
## コーディング規約
### TypeScript
- すべてのファイルで厳格な型定義を使用
- `any`型の使用禁止
- 関数の戻り値の型を明示
- interfaceよりtypeエイリアスを優先
### 命名規則
- コンポーネント: PascalCase (`UserProfile`, `ProductCard`)
- フック: use接頭辞 (`useUser`, `useCart`)
- 定数: UPPER_SNAKE_CASE (`API_BASE_URL`)
- 関数: camelCase (`fetchUser`, `calculateTotal`)
### インポート順序
1. React/Next.js
2. サードパーティライブラリ
3. 内部モジュール(@/から始まる)
4. 相対パス
5. 型定義
6. スタイル
### ファイル構造
src/ app/ # App Router components/ # 再利用可能なコンポーネント lib/ # ユーティリティ、API client hooks/ # カスタムフック types/ # 型定義 styles/ # グローバルスタイル
## 使用ライブラリ
### 状態管理
- React Query v5 (サーバー状態)
- Zustand (クライアント状態)
### UI
- shadcn/ui (コンポーネント)
- Tailwind CSS (スタイリング)
### バリデーション
- Zod (スキーマ検証)
### フォーム
- React Hook Form + Zod
## アーキテクチャパターン
### API呼び出し
- すべてのAPIコールは`lib/api/`配下に集約
- React Queryでラップ
- エラーハンドリングは統一
```typescript
// lib/api/user.ts
import { z } from 'zod';
import { apiClient } from './client';
const UserSchema = z.object({
id: z.string(),
name: z.string(),
email: z.string().email(),
});
export const userApi = {
getById: async (id: string) => {
const response = await apiClient.get(`/users/${id}`);
return UserSchema.parse(response.data);
},
};
コンポーネント設計
- Server Componentsをデフォルト
- インタラクションが必要な場合のみ’use client’
- propsはinterfaceで型定義
- childrenを受け取る場合はReact.ReactNodeを使用
ベストプラクティス
パフォーマンス
- 画像は必ずnext/imageを使用
- 動的インポートで大きなコンポーネントを遅延ロード
- useMemoとuseCallbackは必要な場合のみ使用
アクセシビリティ
- すべてのボタンにaria-labelを設定
- フォーム要素にはlabelを関連付け
- セマンティックHTMLを優先
エラーハンドリング
- すべての非同期処理にtry-catchを追加
- ユーザーフレンドリーなエラーメッセージ
- エラーログをSentryに送信
禁止事項
- console.logの使用(開発時のみ許可)
- 直接のfetch使用(apiClient経由)
- インラインスタイル
- varキーワード
### 2. VS Code設定の追加
```json
// .vscode/settings.json
{
"github.copilot.enable": {
"*": true,
"yaml": false,
"plaintext": false
},
"github.copilot.chat.codeGeneration.instructions": [
{
"file": ".github/copilot-instructions.md"
}
]
}
実践例
React Queryパターンの自動生成
// コメントで指示
// Create a custom hook to fetch user by ID using React Query
// Copilotの生成結果
import { useQuery } from '@tanstack/react-query';
import { userApi } from '@/lib/api/user';
import type { User } from '@/types/user';
export function useUser(userId: string) {
return useQuery({
queryKey: ['user', userId],
queryFn: () => userApi.getById(userId),
staleTime: 5 * 60 * 1000, // 5分
});
}
フォームバリデーションの自動生成
// Create a form schema for user registration
// Copilotの生成結果
import { z } from 'zod';
export const registerSchema = z.object({
username: z
.string()
.min(3, 'ユーザー名は3文字以上必要です')
.max(20, 'ユーザー名は20文字以内です'),
email: z
.string()
.email('有効なメールアドレスを入力してください'),
password: z
.string()
.min(8, 'パスワードは8文字以上必要です')
.regex(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
'パスワードは大文字、小文字、数字を含む必要があります'
),
confirmPassword: z.string(),
}).refine((data) => data.password === data.confirmPassword, {
message: 'パスワードが一致しません',
path: ['confirmPassword'],
});
export type RegisterInput = z.infer<typeof registerSchema>;
チーム別のカスタム指示例
バックエンドチーム
# Backend Custom Instructions
## 使用技術
- Node.js 20 + TypeScript
- Hono (Web Framework)
- Drizzle ORM
- PostgreSQL
## API設計
- RESTful API
- OpenAPI 3.1仕様に準拠
- すべてのエンドポイントで認証必須(除: /health)
## エラーハンドリング
```typescript
export class AppError extends Error {
constructor(
public statusCode: number,
message: string,
public isOperational = true
) {
super(message);
}
}
// 使用例
throw new AppError(404, 'User not found');
データベース
- マイグレーションファイルは必ず作成
- トランザクションを適切に使用
- N+1クエリを避ける
セキュリティ
- すべての入力をバリデーション
- SQLインジェクション対策(prepared statements)
- レート制限を設定
### フロントエンドチーム
```markdown
# Frontend Custom Instructions
## 状態管理
```typescript
// Zustandストアの標準パターン
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
interface CartState {
items: CartItem[];
addItem: (item: CartItem) => void;
removeItem: (id: string) => void;
clearCart: () => void;
}
export const useCartStore = create<CartState>()(
devtools(
persist(
(set) => ({
items: [],
addItem: (item) =>
set((state) => ({ items: [...state.items, item] })),
removeItem: (id) =>
set((state) => ({
items: state.items.filter((item) => item.id !== id),
})),
clearCart: () => set({ items: [] }),
}),
{ name: 'cart-storage' }
)
)
);
コンポーネントパターン
- Compound Components パターンを優先
- Render Props は避ける
- カスタムフックでロジックを抽出
テスト
- Testing Libraryを使用
- ユーザーの操作をテスト
- 実装詳細をテストしない
### インフラチーム
```markdown
# Infrastructure Custom Instructions
## IaC
- Terraform 1.6以上
- モジュール化を徹底
- 変数はvariables.tfに集約
```hcl
# 標準的なモジュール構造
module "vpc" {
source = "./modules/vpc"
vpc_cidr = var.vpc_cidr
environment = var.environment
project_name = var.project_name
tags = merge(
var.common_tags,
{
Name = "${var.project_name}-vpc"
}
)
}
CI/CD
- GitHub Actionsを使用
- すべてのジョブにtimeoutを設定
- SecretsはGitHub Secretsで管理
セキュリティ
- 最小権限の原則
- すべてのリソースにタグ付け
- 本番環境は別アカウント
## 高度なテクニック
### コンテキストファイルの活用
```markdown
# .github/copilot-context.md
## 現在のスプリント目標
- ユーザー認証機能の実装
- OAuth (Google, GitHub) 対応
- メール認証フロー
## 既知の問題
- Safari でのCookie問題 → SameSite=None対応済み
- iOS PWA のトークン保存 → IndexedDB使用
## 最近の設計決定
- セッション管理: JWTではなくsession token
- 理由: リフレッシュトークンの複雑さを避けるため
プロジェクト固有の略語
## 略語・専門用語
- SKU: Stock Keeping Unit (商品管理コード)
- PDP: Product Detail Page (商品詳細ページ)
- PLP: Product Listing Page (商品一覧ページ)
- CTA: Call To Action (行動喚起ボタン)
## 使用例
```typescript
// ✅ Good
interface ProductSKU {
code: string;
variant: string;
}
// ❌ Bad
interface ProductCode {
code: string;
variant: string;
}
### チーム固有のコメントスタイル
```markdown
## コメント規約
### TODOコメント
```typescript
// TODO(username): 説明 - 期日
// TODO(john): API v2への移行 - 2024-12-31
// FIXME: 緊急の修正が必要
// FIXME: メモリリークの可能性
// NOTE: 重要な情報
// NOTE: この関数は非推奨。代わりにnewFunctionを使用
アーキテクチャ決定記録(ADR)
/**
* ADR-001: React Queryの採用
*
* 決定日: 2024-01-15
* 理由:
* - サーバー状態管理の統一
* - 自動キャッシング・再検証
* - Optimistic Updates対応
*
* 代替案:
* - SWR: React Queryより機能が少ない
* - Redux Toolkit Query: Reduxへの依存
*/
## チームでの運用
### 定期的なレビュー
```markdown
# カスタム指示レビュー (月次)
## チェックリスト
- [ ] 新しいライブラリの追加反映
- [ ] 非推奨パターンの削除
- [ ] チームフィードバックの反映
- [ ] 生成品質の確認
## メトリクス
- Copilot採用率: 提案の何%を受け入れたか
- 修正率: 生成コードの何%を修正したか
- 時間削減: コーディング時間の削減率
オンボーディング
# 新メンバー向けガイド
## 初日
1. `.github/copilot-instructions.md`を熟読
2. サンプルコードで動作確認
3. 既存コードの生成を試す
## 1週間目
- チームのコーディング規約に沿った提案か確認
- 不適切な提案があれば報告
## フィードバック方法
- Slackの#copilot-feedbackチャンネル
- 良い/悪い例を共有
トラブルシューティング
Copilotが規約を無視する場合
// ❌ 規約無視の例
function fetchUser(id) {
return fetch(`/api/users/${id}`);
}
// 解決策1: より具体的な指示
// Create a type-safe user fetcher using our apiClient from @/lib/api
// 解決策2: インラインコメントで補足
/**
* Fetch user by ID
* @requirements
* - Use apiClient from @/lib/api
* - Return type must be User from @/types/user
* - Use Zod for validation
*/
カスタム指示が反映されない
# VS Code の Copilot キャッシュをクリア
# Command Palette (Cmd+Shift+P)
> GitHub Copilot: Clear Chat History
# VS Code 再起動
まとめ
GitHub Copilot Custom Instructionsを活用することで、チーム固有のコーディング規約やベストプラクティスに準拠したコード生成が可能になります。プロジェクトの成長に合わせて指示を更新し、チーム全体で品質の高いコードを効率的に生産できます。
次のステップ
- カスタム指示の定期的なレビューとアップデート
- チームメンバーからのフィードバック収集
- 生成コードの品質メトリクス測定
- 他のAIツール(Cursor, Codeium)との比較検討