186
186

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェントが「最初から戦力になる」リポジトリ設計 — AGENTS.md・ディレクトリ構造・バリデーション戦略の実践ガイド

186
Posted at

はじめに — 同じCursorを使っているのに、なぜ10倍の差がつくのか

こんな経験、ないでしょうか。

チームの隣の席の人が、CursorやCopilotで爆速開発している。同じツールを使っているのに、自分のプロジェクトだと全然うまくいかない。AIが的外れなコードを吐く。毎回同じ説明をしないといけない。「やっぱりAIって使えないな」と思い始める。

...ちょっと待ってほしい。

正直に言うと、僕も最初はそうだった。Claude CodeやCursorを導入して、ワクワクしながら使い始めて、そして「なんか思ったほどじゃないな」と感じた時期がある。でも、あるとき気づいたんです。

問題はAIの性能じゃない。渡している「文脈」の質が違う。

もっと具体的に言うと、 リポジトリそのもの が「AIに読みやすいかどうか」で、AIの出力品質がまるで変わる。プロンプトをどれだけ工夫しても、コードベースがAIにとって読みにくい構造だったら、根本的に限界がある。

この記事では、AIエージェントが「最初から戦力になる」ためのリポジトリ設計を、 AGENTS.md / CLAUDE.md の書き方ディレクトリ構造の最適化バリデーション戦略 の3つの柱で、実践的に解説します。

テンプレートもチェックリストもそのまま使える形で載せるので、気になるところから試してみてください。


1. AIエージェントがコードベースを「読む」時、実は何を見ているのか

この章でわかること: AIがコードを理解する仕組みと、「読みやすい」リポジトリの条件

コンテキストウィンドウという「視野」

AIエージェントには コンテキストウィンドウ という「一度に見渡せる範囲」がある。2026年現在、Claude 3.5で200Kトークン、GPT-4oで128Kトークン、Gemini 2.0 Proで最大100万トークン。

これを人間に例えると、こういうことかなと思う。

コンテキストウィンドウが広い = 机の上に広げられる書類の量が多い。でも、 机が広くても、書類がぐちゃぐちゃだったら仕事にならない

AIも同じで、コンテキストウィンドウにどれだけの情報を詰め込めるかより、 どんな構造で情報を渡すか の方がはるかに重要なんです。

AIが実際に見ているもの

AIコーディングエージェント(Cursor、Claude Code、GitHub Copilot等)がコードベースを理解する時、主にこういう情報を見ている。

  1. プロジェクトルートのドキュメント — README.md、AGENTS.md、CLAUDE.md、package.json
  2. ディレクトリ構造tree コマンドの出力に相当する全体像
  3. 型定義・インターフェース — TypeScriptの .d.ts やOpenAPIスペック
  4. テストコード — 期待される振る舞いの「仕様書」として読む
  5. リンター・フォーマッター設定 — コードスタイルのルール

逆に言えば、 これらが整っていないリポジトリでは、AIは「暗闇の中で手探りしている」ような状態 になる。毎回「このプロジェクトではどのフレームワーク使ってますか?」「テストの実行方法は?」と聞かれるのは、AIが文脈を掴めていない証拠なんです。

「読みやすい」リポジトリの3条件

条件 説明 NG例
自己記述的 ドキュメントを読めばプロジェクトの全体像がわかる READMEが初期テンプレのまま
規約が明示的 コーディングルールが設定ファイルで定義されている 暗黙のルールが口伝え
検証可能 テスト・リンターで正しさを自動判定できる テストがない or 壊れている

2. AGENTS.md / CLAUDE.md 完全設計ガイド

この章でわかること: 各ファイルの役割、設計原則、コピペ可能なテンプレート

そもそも何のためのファイルか

AGENTS.md は、AIコーディングエージェント全般に向けたプロジェクトの取扱説明書。2026年3月時点で6万以上のリポジトリで採用されていると報告されていて、事実上の標準になりつつある。

CLAUDE.md は、Anthropicの Claude Code が毎セッション自動で読み込む設定ファイル。プロジェクトルートに置くだけで、Claude Codeがそのプロジェクト固有の規約を理解した状態で作業を始める。

.cursorrules は、Cursor向けの同様のファイル。

迷ったらこの使い分けがおすすめ。

ファイル 対応ツール 推奨度
AGENTS.md 汎用(Copilot、Codex等多数) 必須
CLAUDE.md Claude Code Claude Code使うなら必須
.cursorrules Cursor Cursor使うなら推奨

実用的なTips: CLAUDE.mdを作ったら、AGENTS.mdへのシンボリックリンクを作ると両立できる。

# CLAUDE.mdをメインで管理し、AGENTS.mdはシンボリックリンク
ln -s CLAUDE.md AGENTS.md

設計5原則

良いAGENTS.md / CLAUDE.mdを書くための5原則はこういうことかなと思う。

原則1: ルールは「なぜ」付きで書く

# ❌ 悪い例
- App Routerを使う

# ✅ 良い例
- App Routerを使う(Pages Routerは段階的に廃止中。新規ファイルは必ずapp/配下に作成)

「なぜ」がないと、AIは例外ケースで判断を誤る。人間の新メンバーにも言えることだけど、理由を知っている人は応用が効く。

原則2: NEVERセクションを明示する

AIが「やらかしがち」なことを明示的に禁止する。これが意外と重要で、AIは「やっていいこと」より「やってはいけないこと」の方が守りやすい。

## NEVER(絶対にやらないこと)
- デフォルトエクスポートを使わない(named exportのみ)
- node_modules/やvendor/を直接編集しない
- .envファイルをコードに含めない
- 既存のテストを削除しない(修正はOK)
- console.logをプロダクションコードに残さない

原則3: コード例を2-3個入れる

「こういうスタイルで書いてね」を言葉で説明するより、実例を見せた方が100倍伝わる。

## コードスタイル例

### API Route の書き方
``typescript
// app/api/users/route.ts
import { NextResponse } from 'next/server'
import { z } from 'zod'

const querySchema = z.object({
  page: z.coerce.number().min(1).default(1),
  limit: z.coerce.number().min(1).max(100).default(20),
})

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const query = querySchema.parse(Object.fromEntries(searchParams))
  // ... 実装
  return NextResponse.json({ data, pagination })
}
``

原則4: セットアップコマンドを1行で書く

## セットアップ
``bash
npm install && npm run dev    # 開発サーバー起動
npm test                      # 全テスト実行
npm run lint                  # リンター実行
npm run typecheck             # 型チェック
``

AIが何かを試したい時、ワンコマンドで実行できることが生産性に直結する。5つのステップが必要なセットアップは、AIにとっても人間にとっても障壁になる。

原則5: 境界線を明確にする

## 権限
### 自由にやっていい
- src/配下のコード修正
- テストの追加・修正
- ドキュメントの更新

### 確認してから
- package.jsonへの依存関係追加
- データベーススキーマの変更
- 環境変数の追加

### 絶対にやらない
- .env*ファイルの編集
- CI/CDパイプライン設定の変更
- 本番データベースへの直接アクセス

コピペ可能テンプレート

以下は穴埋め形式のテンプレート。 {...} の部分をプロジェクトに合わせて書き換えてください。

# AGENTS.md

## プロジェクト概要
{プロジェクト名}は{1行でプロジェクトの説明}。
技術スタック: {Next.js / TypeScript / MongoDB / etc.}

## アーキテクチャ
- {App Router / Pages Router / etc.}を使用
- {状態管理: Zustand / Redux / etc.}
- {DB: MongoDB / PostgreSQL / etc.} with {ORM: Prisma / Mongoose / etc.}
- {認証: NextAuth / Clerk / etc.}

## ディレクトリ構成
``
{tree出力またはディレクトリ構造の概要}
``

## コーディング規約
- {命名規則: camelCase / PascalCase等}
- {インポート順序のルール}
- {コンポーネントの書き方}

## セットアップ
``bash
{インストールコマンド}
{開発サーバー起動}
{テスト実行}
{リンター実行}
``

## NEVER
- {プロジェクト固有の禁止事項1}
- {プロジェクト固有の禁止事項2}
- {プロジェクト固有の禁止事項3}

## コード例
{プロジェクトの代表的なパターンを2-3個}

## 権限
### 自由にやっていい
- {範囲}
### 確認してから
- {範囲}
### 絶対にやらない
- {範囲}

ここは自分で考える箇所(コピペだけではダメな部分):

  • 「NEVER」セクション: プロジェクトで実際にAIが間違えた経験から追加していく
  • 「コード例」: 汎用サンプルではなく、自分のプロジェクトの実コードを貼る
  • 「アーキテクチャ」: なぜその技術選定をしたかの理由

これは一度書いて終わりじゃなく、AIと一緒に開発する中で「ここ間違えたな」と思ったらNEVERに追加していく、 育てるドキュメント だと思ってほしい。


3. リポジトリ構造をAI-Readyに変える5つの変更

この章でわかること: 既存リポジトリをAIフレンドリーにする具体的な変更5選

① ワンコマンド化

AIエージェントが最も頻繁に実行するのは「テスト」と「リント」。これが1コマンドで動くかどうかで、作業効率がまるで変わる。

// package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "test": "vitest run",
    "test:watch": "vitest",
    "lint": "eslint . --ext .ts,.tsx",
    "typecheck": "tsc --noEmit",
    "validate": "npm run typecheck && npm run lint && npm run test"
  }
}

ポイントは validate コマンド 。型チェック→リント→テストを一発で走らせる。AIが何か変更した後に npm run validate を実行すれば、壊れていないかすぐわかる。

② ディレクトリ構造をVertical Sliceに

Layered Architecture(レイヤー別):

src/
├── controllers/
│   ├── userController.ts
│   ├── orderController.ts
│   └── productController.ts
├── services/
│   ├── userService.ts
│   ├── orderService.ts
│   └── productService.ts
├── repositories/
│   ├── userRepository.ts
│   ├── orderRepository.ts
│   └── productRepository.ts
└── models/
    ├── user.ts
    ├── order.ts
    └── product.ts

Vertical Slice Architecture(機能別):

src/
├── features/
│   ├── users/
│   │   ├── api.ts
│   │   ├── service.ts
│   │   ├── repository.ts
│   │   ├── schema.ts
│   │   ├── types.ts
│   │   └── __tests__/
│   │       └── users.test.ts
│   ├── orders/
│   │   ├── api.ts
│   │   ├── service.ts
│   │   ├── ...
│   └── products/
│       ├── ...
└── shared/
    ├── db.ts
    ├── auth.ts
    └── errors.ts

なんでVertical Sliceを推すかというと、AIにとっては 「1つの機能に関するファイルが1つのフォルダにまとまっている」 方が、コンテキストウィンドウに必要な情報を効率的に詰め込めるからなんです。

Layered Architectureだと、ユーザー機能を理解するために controllers/services/repositories/models/ の4つのディレクトリを横断しないといけない。Vertical Sliceなら features/users/ を見るだけでいい。

これは人間にとっても同じで、新しいメンバーが「ユーザー機能のコードどこ?」と聞いた時に「features/users/ を見て」と一言で済む。

③ 型定義を充実させる

AIにとって型定義は「このプロジェクトのドメインモデル」を理解する最短ルートになる。

// src/features/users/types.ts

/** ユーザーの作成リクエスト */
export interface CreateUserInput {
  /** メールアドレス(RFC 5322準拠) */
  email: string
  /** 表示名(2-50文字) */
  displayName: string
  /** ロール(デフォルト: member) */
  role?: 'admin' | 'member' | 'viewer'
}

/** ユーザーのレスポンス(パスワードハッシュ等の内部情報を除外) */
export interface UserResponse {
  id: string
  email: string
  displayName: string
  role: 'admin' | 'member' | 'viewer'
  createdAt: string
  updatedAt: string
}

/** ユーザー一覧のページネーション付きレスポンス */
export interface UsersListResponse {
  users: UserResponse[]
  pagination: {
    page: number
    limit: number
    total: number
    hasNext: boolean
  }
}

JSDocコメントが重要。AIはこれを読んで「emailはRFC 5322準拠」「displayNameは2-50文字」みたいなバリデーションロジックを自動で推測してくれる。型定義にコメントを書く時間は、後でAIの手戻りを修正する時間よりはるかに短い。

④ エラーメッセージを構造化する

AIが生成したコードのエラーを修正する時、エラーメッセージが構造化されているかどうかで対応速度がまるで違う。

// src/shared/errors.ts

export class AppError extends Error {
  constructor(
    public readonly code: string,
    message: string,
    public readonly statusCode: number = 500,
    public readonly details?: Record<string, unknown>
  ) {
    super(message)
    this.name = 'AppError'
  }
}

// 使い方
throw new AppError(
  'USER_NOT_FOUND',
  `User with id ${userId} not found`,
  404,
  { userId }
)

// ❌ 避けたい書き方
throw new Error('not found')  // 何が見つからないのか不明

USER_NOT_FOUND のようなエラーコードがあると、AIは「あ、ユーザーが見つからないケースか」と即座に理解して適切な修正を提案できる。not found だけだと文脈が失われる。

⑤ 各ディレクトリにREADMEを置く

大規模プロジェクトでは、ルートのAGENTS.mdだけでは情報が足りない。各主要ディレクトリに小さなREADMEを置くことで、AIが必要な時に必要な文脈を取得できる。

<!-- src/features/users/README.md -->
# Users Feature

## 概要
ユーザーのCRUD操作とロール管理を担当。

## 依存関係
- MongoDB(Mongoose経由)
- NextAuth(認証セッション)

## テスト
``bash
npm test -- --filter users
``

## 注意事項
- メールアドレスの一意性制約はDB側で保証
- パスワードハッシュにはbcrypt(rounds=12)を使用
- ユーザー削除は論理削除(deletedAtフィールド)

これは特にモノレポや大規模プロジェクトで効果を発揮する。AIが users 機能を触る時、このREADMEを読むだけで「論理削除なんだな」「bcryptのrounds=12か」と把握できる。


4. バリデーション戦略 — AIの出力を「放置しない」仕組み

この章でわかること: テスト・リンター・CIでAIの出力品質を自動保証する方法

AIが書いたコードを「なんとなく動いてるからOK」で放置するのは、正直かなり危険な気がする。人間が書いたコードだってレビューするわけで、AIのコードも 自動で検証する仕組み が必要。

テストカバレッジとAI生産性の関係

面白い相関があって、テストカバレッジが高いプロジェクトほど、AIの出力品質も高くなる傾向がある。

理由はシンプルで、AIは テストコードを「仕様書」として読む から。テストが充実していれば、AIは「この関数はこういう入力に対してこういう出力を返すべきなんだな」と理解した上でコードを書ける。テストがなければ、推測で書くしかない。

// src/features/users/__tests__/users.test.ts
import { describe, it, expect } from 'vitest'
import { createUser } from '../service'

describe('createUser', () => {
  it('有効な入力でユーザーを作成できる', async () => {
    const input = {
      email: 'test@example.com',
      displayName: 'テスト太郎',
      role: 'member' as const,
    }
    const user = await createUser(input)
    expect(user.email).toBe(input.email)
    expect(user.displayName).toBe(input.displayName)
    expect(user.role).toBe('member')
    expect(user.id).toBeDefined()
  })

  it('重複メールアドレスでエラーを返す', async () => {
    await createUser({ email: 'dup@example.com', displayName: 'A' })
    await expect(
      createUser({ email: 'dup@example.com', displayName: 'B' })
    ).rejects.toThrow('USER_EMAIL_DUPLICATE')
  })

  it('不正なメールアドレスでバリデーションエラーを返す', async () => {
    await expect(
      createUser({ email: 'invalid', displayName: 'C' })
    ).rejects.toThrow('VALIDATION_ERROR')
  })
})

このテストがあれば、AIは createUser の仕様を完全に理解できる。逆にテストがなければ、重複チェックの実装を忘れたり、バリデーションを省略したりするリスクがある。

pre-commitフックで最低限の品質を保証

最低限、これだけ設定しておけばAIの出力品質が大幅に安定する。

# .husky/pre-commit(最小構成)
npm run typecheck && npm run lint
// package.json に追加
{
  "lint-staged": {
    "*.{ts,tsx}": ["eslint --fix", "prettier --write"]
  }
}

これだけで「型エラーがあるコード」「リントに違反するコード」がコミットされなくなる。AIが生成したコードも、この関門を通過したものだけがリポジトリに入る。

CI/CDパイプラインの設定例

# .github/workflows/validate.yml
name: Validate
on: [push, pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'
      - run: npm ci
      - run: npm run typecheck
      - run: npm run lint
      - run: npm run test -- --coverage
      - name: Coverage check
        run: |
          COVERAGE=$(npx vitest run --coverage --reporter=json | jq '.total.lines.pct')
          if (( $(echo "$COVERAGE < 80" | bc -l) )); then
            echo "Coverage $COVERAGE% is below 80% threshold"
            exit 1
          fi

ポイントは カバレッジ閾値 を設定すること。これがあると、AIが新しいコードを追加した時にテストも一緒に書かないとCIが通らない。AIに「テストも書いて」と毎回言わなくても、仕組みで強制できる。


5. AI対応度セルフチェックリスト

自分のリポジトリがどれくらい「AI-Ready」か、チェックしてみてください。

ドキュメント(5項目)

  • AGENTS.md / CLAUDE.md がプロジェクトルートにある
  • プロジェクト概要、技術スタック、アーキテクチャが記載されている
  • NEVERセクション(AIがやってはいけないこと)が明示されている
  • セットアップ手順がワンコマンドで完結する
  • コードスタイルの実例が2-3個含まれている

構造(5項目)

  • 機能単位でディレクトリが分かれている(Vertical Slice的)
  • 型定義ファイル(types.ts等)にJSDocコメントがある
  • エラーが構造化されている(エラーコード + メッセージ + ステータス)
  • 主要ディレクトリにREADMEがある
  • package.jsonの scripts に test / lint / typecheck / validate がある

検証(5項目)

  • テストカバレッジが80%以上ある
  • pre-commitフックで型チェック・リントが走る
  • CIで全テスト + リント + 型チェックが自動実行される
  • カバレッジ閾値が設定されている
  • PRテンプレートにレビュー観点が記載されている

スコアの目安:

  • 12-15個: AI-Ready。AIが最初から戦力として機能する
  • 8-11個: まあまあ。AGENTS.mdの追加とワンコマンド化から始めると効果大
  • 4-7個: 改善の余地大。ただし、ここから始めても遅くない
  • 0-3個: AIに限らず、新メンバーの受け入れにも苦労してるのでは...

まとめ — コードを書く時代から、文脈を設計する時代へ

ここまで読んでくださった方、ありがとうございます。

結局のところ、この記事で伝えたかったのはこういうこと。

AIコーディングツールの性能差は、もうほとんどない。 CursorもCopilotもClaude Codeも、2026年時点ではどれも十分に高性能。差がつくのは、 ツールに渡す文脈の質 。つまりリポジトリの設計。

AGENTS.mdを1ファイル追加するだけでも変わる。ディレクトリ構造を見直すだけでも変わる。テストを充実させるだけでも変わる。全部やる必要はなくて、 まず今日できることを1つだけやる

個人的には、エンジニアの仕事が変わってきている実感がある。

「コードを書く人」から「AIが読める文脈を設計する人」へ。

これを「仕事が奪われる」と感じるか、「仕事の質が上がった」と感じるかは、その人の捉え方次第だと思う。でも少なくとも僕は、AIに渡す文脈を設計している時間が、一番クリエイティブで楽しい。

まず今日やること:

  1. 自分のプロジェクトにAGENTS.mdを1つ作る
  2. npm run validate でテスト・リント・型チェックを一発実行できるようにする
  3. NEVERセクションに「AIがやらかしたこと」を1つ書く

小さな一歩だけど、AIとの協業の質が確実に変わるはず。


この記事が参考になったら、LGTMしていただけると嬉しいです。質問やフィードバックもコメントでお気軽にどうぞ。

186
186
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
186
186

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?