AIに地図を与え、コードのダンプは渡さない

Dev.to / 2026/3/18

💬 オピニオンDeveloper Stack & InfrastructureIdeas & Deep AnalysisTools & Practical Usage

要点

  • AIのコーディングアシスタントはテキストしか見ず、プロジェクトのアーキテクチャを把握できないとされるため『盲目』と見なされ、幻のインポートや不一致のコンポーネントが生じる。
  • プロンプトにコードベース全体を投入するのはトークンを浪費し、AIが必要とする実際の構造を伝えられないため、スケールしない。
  • 提案されている解決策は構造化されたコンテキスト、すなわち技術スタック、ルーティング、APIエンドポイント、データベーススキーマ、エクスポートカタログ、インポートグラフなどを強調する、プロジェクトの簡潔な設計図である。
  • オープンソースのCLIであるOrbitが、この構造化されたコンテキストを生成するツールとして紹介され、プロジェクトに対して人間にもAIにも読めるCLAUDE.md風の設計図を作成する。
  • 生のコードではなく地図をAIに渡すことで、開発者は無駄な時間を減らし、AIが生成するコードの信頼性を向上させることができる。

Claudeは先週、私のプロジェクトのために自信を持って import { db } from './database' を書きました。そのファイルは存在しません。私のデータベースは @/lib/db にあり、Claude が知らなかった 10 個のテーブルがありました — それは私が一度も教えなかったからです。

AI コーディングアシスタントについて誰も語らない問題です。彼らはアルゴリズムを書ける、コードをリファクタリングできる、テストを生成できる — しかし彼らは見えない状態で作業しています。あなたのファイル構造、インポート規約、またはどの10個のデータベーステーブルが実際に存在するかを知りません。だから推測します。そして、時間を節約するはずだった作業を修正するのに 20 分を費やします。

コンテキストの問題

これは AI が愚かだからという話ではなく、AI が 盲目 であることの話です。コードの断片を Claude や Cursor に貼り付けると、AI は テキスト を見ており、アーキテクチャを見ているわけではありません。@/lib/utils があなたのプロジェクトで最もよくインポートされているモジュールで、12 個のファイルで使われていることを知らない。あなたのルーティングパターンやデータベーススキーマを知らないのです。

したがって、欠けている部分をもっともらしく聞こえる推測で埋めます。幻のインポート。存在しないファイルパス。デザインシステムと合致しないコンポーネント。

コードダンプは機能しない理由

明らかな対策は簡単です:AI にもっと多くのコードを与えるだけ。あなたのプロジェクト全体を貼り付けてください。これを自動化するツールもあり、コードベース全体を 1 つの巨大なファイルに連結してプロンプトに投入します。

これは 2 つの理由で機能しません。

まず、トークンを無駄にします。一般的なプロジェクトには数千行のコードがあります。その大半は AI が必要としない実装の詳細です。AI が関数の本体を知る必要があるわけではなく、関数が存在すること、呼び出し名、そしてどこにあるかを知るだけで済むのに、コンテキストウィンドウを各関数の本体で消費しています。

次に、そしてより重要なのは、生のコードは理解力を持つわけではないことです。次のように考えてください:小説の章を書いてもらうよう誰かに頼むとき、辞書を手渡しますか?それともアウトライン — 登場人物、筋の構造、テーマ、スタイルガイド — を渡しますか? AI には、領域全体ではなく、あなたのプロジェクトの地図が必要です。

解決策: 構造化コンテキスト

これは Orbit の考え方です — 無料でオープンソースの CLI がコードベースをスキャンし、AI アシスタントが実際に理解できる構造化されたコンテキストファイルを生成します。

生のコードをダンプする代わりに、Orbit はあなたのプロジェクトの簡潔な「設計図」を作成します:技術スタック、ページルーティング、APIエンドポイント、データベーススキーマ、エクスポートカタログ、そして何より重要な import graph。AI にコードベースのどのモジュールがハブなのかを伝え、正しい方法でインポートするべきものを知るようにします。

実在する Next.js SaaS プロジェクトの生成済み CLAUDE.md は次のようになります:

# Project: example-nextjs-saas

## Tech Stack
React 19.0.0 / TypeScript / Tailwind CSS / Drizzle ORM

## Project Structure
- **Pages (4):** /dashboard /login /pricing /settings
- **API Routes (11):** GET, POST, PUT, PATCH
- **DB Tables (9):** users, sessions, teams, team_members, products,
  orders, order_items, subscriptions, audit_logs

## Key Files
- Largest: schema.ts (85 lines), billing-settings.tsx (34 lines),
  pricing-table.tsx (33 lines)
- 38 source files, ~848 lines

## Exports
- **Components (22):** DashboardPage, RootLayout, LoginPage,
  PricingPage, ProductList, RecentOrders, RevenueChart, StatsCards,
  Hero, PricingTable, BillingSettings, TeamSettings, Navbar, Sidebar...
- **Functions (27):** useAuth, useLogout, useOrders, useOrderStats,
  useProducts, useCreateProduct, useTeam, getSession...
- **Types (14):** DB, CreateProductInput, CreateOrderInput, User,
  Team, Product, Order, Subscription, UserRole, OrderStatus...

## Import Graph
35 files, 81 local imports

Most imported modules:
- `@/lib/utils` (12 imports)
- `@/types` (10 imports)
- `@/lib/auth` (7 imports)
- `@/components/ui/button` (7 imports)
- `@/components/ui/card` (7 imports)
- `@/db` (6 imports)
- `@/db/schema` (6 imports)

## Environment Variables
DATABASE_URL, NEXT_PUBLIC_URL, STRIPE_SECRET_KEY,
STRIPE_WEBHOOK_SECRET

Look at what the AI now knows without seeing a single line of implementation code:

  • The project uses Drizzle ORM, not Prisma — so it won't generate Prisma client calls.
  • The database connection is at @/db, not ./database or lib/prisma.
  • There are 9 specific tables, so the AI knows orders exists but invoices doesn't.
  • @/lib/utils is the most-used module — the AI will import from there, not reinvent utilities.
  • The project uses @/components/ui/button, signaling a component library convention.

This is the difference between an AI that guesses and one that knows.

使い方

npm i -g @orbit-cli/core

Then, in your project root:

orbit scan -g

That's it. One command. Orbit scans your project and generates a CLAUDE.md file in your project root. Claude Code, Cursor, Copilot, and Windsurf all automatically pick up their respective context files.

Want a different format? Orbit supports multiple output targets:

orbit scan -g --target cursor    # generates .cursorrules
orbit scan -g --target copilot   # generates copilot-instructions.md
orbit scan -g --target windsurf  # generates .windsurfrules

No account required. No auth. No config files. Just scan and go.

ビフォーとアフター

具体的な例を挙げます。Claude に次の依頼をする場面を想定します:「チームメンバーの役割を更新する新しい API エンドポイントを追加してください。」

コンテキストなし、Claude は次のように生成する可能性があります:

// app/api/teams/update-role/route.ts
import { prisma } from '@/lib/prisma'

export async function POST(req: Request) {
  const { userId, role } = await req.json()
  const updated = await prisma.teamMember.update({
    where: { userId },
    data: { role }
  })
  return Response.json(updated)
}

3 つの問題: 間違った ORM(Prisma ではなく Drizzle)、間違ったインポートパス、そして更新には既存のパターンが PATCH を使用するのに、POST を使っている点。

Orbit のコンテキストがある場合、Claude はプロジェクトが Drizzle ORM を使用していること、データベースは @/db にあること、スキーマは @/db/schema にあること、既存の API パターンが更新には PATCH を使用していることを知ります。生成します:

// app/api/teams/members/route.ts
import { db } from '@/db'
import { team_members } from '@/db/schema'
import { eq } from 'drizzle-orm'

export async function PATCH(req: Request) {
  const { userId, role } = await req.json()
  const [updated] = await db
    .update(team_members)
    .set({ role })
    .where(eq(team_members.userId, userId))
    .returning()
  return Response.json(updated)
}

正しい ORM。正しいインポート。正しい HTTP メソッド。最初の試みで実際に動作するコード。

試してみる

npm i -g @orbit-cli/core
cd your-project
orbit scan -g

AI アシスタントに必要な文脈を提供してください。幻覚的なインポートの修正をやめましょう。

もし役に立つと感じたら GitHubでスターをつけてください — 他の人がプロジェクトを見つけやすくなります。

Orbit は完全に無料で MIT ライセンスです。Next.js、React、Vue、Express などと一緒に動作します。