Claude Media
Claude CodeでPrismaスキーマを設計する — バージョンで変わる移行手順

Claude CodeでPrismaスキーマを設計する — バージョンで変わる移行手順

Claude CodeでPrismaのモデルを設計し、マイグレーションを適用する手順を、Prisma ORM 7とORM 8(RC)の違いを踏まえて解説します。

Claude CodeでPrismaスキーマを設計する前に確認すること

Prismaのスキーマ設計をClaude Codeに任せる前に、まず手元のPrismaがどちらのバージョンかを確認します。npm install prismaで入るのは安定版のPrisma ORM 7ではなく、リリース候補(RC)のPrisma ORM 8です。GA(正式版)は2026年10月を予定しています。既存プロジェクトがPrisma ORM 7で動いているなら、うっかり8系を入れてschema.prismaが読めなくなる事故を避ける必要があります。

確認は次のコマンドで足ります。

npm ls prisma @prisma/client

@prisma/clientが出てくればPrisma ORM 7、出てこずprismaだけならPrisma ORM 8(RC)です。Prisma ORM 8はNode.js 22.18以上(24系は24.11以上)を要求するので、古いNode.jsのままアップデートすると起動時点でエラーになります。

スキーマ設計が必要になる場面は新規プロジェクトだけではありません。LangGraphのようなエージェントフレームワークでも、checkpointerの保存先をインメモリから自前のPostgreSQLへ切り替える際に同じテーブル設計の判断が要ります。この切り替え自体はClaude CodeでLangGraphエージェントを実装する手順で扱っていますが、保存先のテーブル設計はPrismaのようなORM側の作業です。

Prisma ORM 8のcontract化で何が変わったか

Prisma ORM 8では、schema.prismaというファイル名も含め、いくつかの言葉が置き換わりました。同じファイルを指しますが、呼び方と生成物が変わっています。

Prisma ORM 7Prisma ORM 8(RC)備考
schema.prismaPrisma ORM 8(RC)src/prisma/contract.prisma備考同じファイルの名称変更。中身のモデル定義は近い
prisma generatePrisma ORM 8(RC)prisma contract emit備考contract.jsoncontract.d.tsを書き出す
prisma migrate devPrisma ORM 8(RC)prisma db update、またはprisma migration planprisma db migrate備考開発中はdb update、コミットする移行ファイルが要るときはmigration plan
prisma migrate deployPrisma ORM 8(RC)prisma db migrate備考リポジトリ内のマイグレーションファイルを適用
prisma db pushPrisma ORM 8(RC)空DBならprisma db init、既存DBならprisma db update備考
prisma db pullPrisma ORM 8(RC)prisma contract infer備考既存DBからcontractの初稿を生成
prisma studioPrisma ORM 8(RC)8系のCLIには無し備考Prisma ORM 7のツールから接続文字列を指定して起動
new PrismaClient()Prisma ORM 8(RC)db.tsが公開するdb備考生成されたクライアントクラスは存在しない

もう一つの変化は、フィールド型の書き方です。Prisma ORM 7ではString @db.VarChar(255)のように型と@db.属性を分けていましたが、Prisma ORM 8ではVarChar(255)をそのままフィールド型として書きます。JsonJsonbに名前が変わり、Decimal @db.Decimal(10, 2)Numeric(10, 2)になります。

手順0: プロジェクトにPrismaを導入する

モデルを書く前に、CLIでファイルを揃えます。既存プロジェクトにPrisma ORM 8を追加する場合は次のコマンドを実行します。

npx prisma@latest orm init --yes --target postgres --authoring psl

このコマンドはprisma.config.tsと、モデルを書く元になるスターターのsrc/prisma/contract.prisma、クライアントを公開するsrc/prisma/db.tsを生成します。同時に@prisma/orm-postgresが依存パッケージとして追加され、手順3のdb.tsがimportする@prisma/orm-postgres/runtimeもこの時点で使えるようになります。--yesはプロンプトを飛ばすフラグで、CIやエージェントからの実行を想定した書き方です。

.envDATABASE_URLを設定したら準備は完了です。まだテーブルの無い空のデータベースなら、モデルを書いたあと(手順1・2)にnpx prisma db initでテーブルを作成します。既存のテーブルがある場合はcontract inferで初稿を作りdb signで一致を記録する別の手順になりますが、この記事では新規にモデルを設計する流れを扱います。

手順1: Claude Codeにモデルを設計させる

手順0で生成したスターターのcontract.prismaを、要件に合わせて書き換えさせます。要件を日本語でClaude Codeに伝えれば、モデル定義を書かせられます。次のような指示が具体的です。

ユーザーと投稿の1対多を持つブログのモデルを設計してください。投稿タイトルは255文字まで、優先度はlow/high/urgentの3値、投稿の作成日時を記録してください。

Prisma ORM 8向けに書かせると、次のようなcontract.prismaが出てきます。

// use prisma-8
 
types {
  ShortTitle = VarChar(255)
}
 
enum Priority {
  @@type("pg/text@1")
  Low    = "low"
  High   = "high"
  Urgent = "urgent"
}
 
model User {
  id    Uuid   @id @default(uuid())
  email String @unique
  posts Post[]
}
 
model Post {
  id        Uuid      @id @default(uuid())
  title     ShortTitle
  priority  Priority  @default(Low)
  createdAt DateTime  @default(now())
  userId    Uuid
  user      User      @relation(fields: [userId], references: [id])
}

Claude Codeにレビューさせるときに見るべき点は、リレーションのnullabilityです。Prisma ORM 8の8.0.0-rc.10以降、リレーション側と外部キー側で?の有無が食い違うとcontract emitPSL_RELATION_NULLABILITY_MISMATCHで失敗するようになりました。片方だけを必須にする書き方は、Claude Codeが素早くモデルを量産するときほど紛れ込みやすいミスです。

似たようなテーブル定義を何本も並べて書かせる作業は、レビューが必要な設計判断とは負荷が違います。役割ごとに使うAIモデルを割り当てる考え方はClaude Codeサブエージェントのモデル配分設計で扱った基準がそのまま当てはまり、定型的なテーブル定義の雛形は軽量なAIモデルに任せ、リレーションの整合性チェックは呼び出し元のセッションで見直すという分担ができます。

手順2: contractをemitしてマイグレーションを計画する

モデルを書いたら、contractを書き出してからマイグレーションを計画します。順序が決まっています。

npx prisma contract emit
npx prisma migration plan --name init

contract emitcontract.prismaを読み、contract.jsoncontract.d.tsを書き出します。migration planはこのcontract.jsonを読み、まだ何もデータベースへ適用せずに移行内容だけを計算します。データベース接続が要らないため、CIやサンドボックスでも実行できます。

出力の形は公式ドキュメントの例(idemailnameだけを持つ最小限のUserモデル1つ)で確認できます(抜粋)。

migrations/app/20260707T1005_init
├─ Create schema "public"
└─ Create table "user"
 
from:       (baseline)
to:         705b1a62f26f0913caa4bfe3f8b7cb491a1b94bd47fc43471d8711bc480bcbb5

from: (baseline)は空のデータベースから始める最初のマイグレーションという意味です。手順1で書いたUserPostPriorityのcontractを対象にすると、postテーブルの作成や、Priorityの値を検査する制約の作成が操作に加わり、一覧の行数は増えますが、「schemaの作成→各テーブルの作成」という並びとfrom/toのハッシュが付く形は変わりません。計画した内容を実際のデータベースに適用するコマンドは、開発中と本番で書き方が変わります。

npx prisma db migrate --advance-ref db

開発環境では--advance-ref dbを付け、直近まで適用したcontractの状態を記録させます。CIや本番では、このフラグを付けずにnpx prisma db migrateだけを実行します。すでにデータベースがある場合は、contract inferで既存スキーマからcontractの初稿を作るか、テーブルがcontractと一致しているならprisma db signで一致を記録してから計画を始めます。

手順3: db.tsから型付きで参照する

Prisma ORM 8には生成されたPrismaClientクラスがありません。代わりに、contract emitが書き出したcontract.jsoncontract.d.tsから、自分で1回だけクライアントを作ります。

src/prisma/db.ts
import "dotenv/config";
import postgres from "@prisma/orm-postgres/runtime";
import type { Contract } from "./contract.d";
import contractJson from "./contract.json" with { type: "json" };
 
export const db = postgres<Contract>({
  contractJson,
  url: process.env.DATABASE_URL!,
});

以降のアプリコードはこのdbをインポートして使います。クエリの具体的な書き方は公式の「Learn the fundamentals」ページに整理されています。押さえておきたいのは、contract.jsonが機械可読なJSONであるという点です。Prisma公式もこれを「AI-agent friendly」な設計と説明しており、Claude Codeがクエリを書く際にフィールド名やリレーション名をこのファイルから直接確認できます。人間の読むcontract.prismaとエージェントが読むcontract.jsonが、同じ内容を指したまま分業できる形です。

Prisma ORM 7を使っている既存プロジェクトの場合

既存プロジェクトがPrisma ORM 7のままなら、schema.prismaprisma migrate devprisma generateという従来の流れを続けます。Claude Codeへの指示の出し方は変わりません。設計させたモデルをそのままschema.prismaに書き、次のコマンドで反映します。

npx prisma migrate dev --name init
npx prisma generate

migrate devがマイグレーションファイルの作成とデータベースへの適用を1コマンドで済ませ、generate@prisma/clientのクライアントコードを生成します。生成後はnew PrismaClient()でインスタンス化して使う、これまで通りの書き方です。

npx prismaは明示的にバージョンを固定しない限りPrisma ORM 8を指すため、7系を保つにはpackage.json"prisma": "^7""@prisma/client": "^7"を固定し、単発実行するときはnpx prisma@7と書きます。この固定を忘れると、次に依存関係を入れ直した拍子にmigrate devgenerateが見つからないというエラーに変わります。

Claude CodeにPrisma公式のAgent Skillsを同期させる

Prismaはコーディングエージェント向けのSkillを公式に配布しています。プロジェクトで次のコマンドを実行すると、インストール済みのPrismaパッケージからSkillファイルを集めてきます。

npx prisma skills sync

対象は@prisma/orm-postgres@prisma/orm-sqlite@prisma/orm-mongo@prisma/composer、そしてprisma本体が持つprisma-platform-core-conceptsという固定リストで、node_modulesを無差別に走査することはありません。Claude Code向けの出力先は.claude/skillsで、これはgit管理するファイルなのでクローンした直後から同じSkillが読める状態になります。

Skillのバージョンはインストール済みパッケージのバージョンと突き合わせて古さを検知します。ずれていると、コマンド実行のたびに次のような通知が出ます。

Prisma agent skills are out of date (installed @prisma/orm-postgres 8.1.0, synced 8.0.0). Run: prisma skills sync

この通知はTTYの有無を前提にしていません。公式ドキュメントも「エージェントはTTY無しで動く。この通知は元々そのエージェント向けだ」と説明しており、Claude Codeのようなheadless実行を想定した設計です。Prisma ORM 7から8への移行期はコマンド名の変化が大きいため、このSkillを同期しておくと、Claude Codeが古いmigrate dev前提の手順を提案する頻度を減らせます。

よくあるつまずき

意図せずPrisma ORM 8が入る

既存のPrisma ORM 7プロジェクトでnpm installをやり直すと、バージョン固定がない限りPrisma ORM 8(RC)が入り、generatemigrate devdb pushのどれも見つからなくなります。package.jsonでのバージョン固定を先に済ませておきます。

DateTimeがJavaScriptのDateで返ってこない

Prisma ORM 8のDateTimeTemporal.Instantを返します。Node.js 26以降なら標準機能ですが、Node.js 22や24ではtemporal-polyfilldb.tsの先頭でインポートしないとTemporalが未定義のままです。

prisma studioが動かない

Prisma ORM 8のCLIにはStudioが同梱されていません。Prisma ORM 7のツールを別ディレクトリからnpx prisma@7 studio --url "..."のように接続文字列付きで起動します。

一部の機能がまだ使えない

Prisma ORM 8はRCの段階で、$extends・JSONカラム内でのフィルタ・incrementのようなアトミック更新・大半のネストした書き込み・トランザクションの分離レベル指定・P2002系のエラーコードは未対応です。既存アプリでこれらに依存している場合、移行前に該当箇所を洗い出しておく必要があります。

contractの変更を反映し忘れる

contract.prismaを編集してもcontract emitを実行するまでcontract.jsonは更新されません。編集の都度手動で叩くのを忘れがちなら、ファイル保存後に決まったコマンドを自動実行する仕組みが有効です。フックでビルドコマンドを連動させる考え方自体はClaude CodeでNxのaffectedをフックから使う設計で扱った手法と同じで、対象コマンドをprisma contract emitに変えるだけで応用できます。

まとめ

Prismaのスキーマ設計をClaude Codeに任せる前に、まずnpm ls prisma @prisma/clientでバージョンを確認します。Prisma ORM 7ならこれまで通りschema.prismamigrate devgenerateの流れで進め、Prisma ORM 8(RC)を使うならcontract.prismacontract emitmigration plan(またはdb update)・db migrateという新しい語彙に置き換えます。どちらのバージョンでも、モデル定義を書かせた後にリレーションのnullabilityやフィールド型の対応をClaude Codeと一緒に読み返す作業は変わりません。GAは2026年10月を予定しているため、新規プロジェクトで8系を選ぶ場合は、この記事の対応表を都度公式の「Coming from Prisma ORM 7」ページと照らし合わせると、RCの間に変わった箇所に気づきやすくなります。prisma skills syncでエージェント向けSkillを最新化しておけば、Claude Code側の提案もその時点のバージョンに合った形になります。

この記事を共有:XはてブLinkedIn