SupaForge について
SupaForgeは、開発環境や本番環境などのSupabaseプロジェクトを比較・同期するコマンドラインツールです。データベーススキーマ以外の設定も対象とし、一時コピーで修正を検証してから適用できます。
主な機能
- 01スキーマ、RLS、ロール、権限の比較
- 02ストレージ、認証、Edge Functionsの確認
- 03依存順にトランザクションで修正を適用
- 04変更のプレビューと修正の検証
- 05スナップショット、復元、複製、マイグレーション管理
活用シーン
- 01開発環境と本番環境の設定差分の発見
- 02対象環境を変更する前の修正検証
- 03リモートデータベースのローカル複製
- 04機械可読な結果を使ったCIチェック
MCP 対応
READMEでは、SupaForgeをAIエージェントから利用でき、エディター向けMCPサーバーも提供すると説明されています。このサーバーを通じて環境の比較と同期を行えます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
5掲載時のツール一覧 · 1 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| skip | array | いいえ | 特定のチェックをスキップします。CLI の --skip フラグと同等です。設定ファイルの checks.exclude と統合されます。プロジェクト設定を編集せずに、時間がかかるレイヤーや失敗するレイヤーを避けるために使用します。 |
| checks | array | いいえ | スキャン対象を特定のチェックに限定します(例:["rls", "rls-coverage"])。 |
| source | string | いいえ | ソース環境名(設定のデフォルト値を上書きします)。 |
| target | string | いいえ | ターゲット環境名(設定のデフォルト値を上書きします)。 |
| configPath | string | いいえ | supaforge.config.json の絶対パス。サーバーが --allow-config-path を指定して起動されていない場合、このパスは拒否されます。その場合は、サーバー自身の作業ディレクトリにある設定が使用されます。 |
詳細
supaforge
Supabase 環境を比較して同期します。
SupaForge は、2 つの Supabase プロジェクト(たとえば開発環境と本番環境)を、スキーマだけでなく、プロジェクトを構成するあらゆる要素について比較します。すべての差分を報告し、対象をソースと一致させます。修正は依存関係の順に、1 つのトランザクション内で実行され、変更を加える前に使い捨てのコピーで検証できます。単一のプロジェクトでは、スナップショットの作成、復元、複製ができます。
- プロジェクト全体。 スキーマ、RLS、ストレージ、認証、Edge Functions、cron、webhook、Realtime、キュー、パーティションセット、Vault、拡張機能、権限、参照データ、マイグレーション履歴を対象とします。
- デフォルトで安全。 書き込みにはすべて
--applyが必要です。また、データを失ったり、アクセス範囲を広げたりする操作には--allow-destructiveも必要です。適用に失敗しても、対象は変更前の状態を保ちます。 - 本番環境を考慮。 各修正について、稼働中のデータベースにどのような影響があるかを示します。保持するロックと対象テーブル、テーブルを書き換える可能性や全行をスキャンする可能性、トランザクション内で実行できないかどうかがわかります。
- 検証可能。
--proveはマイグレーションを事前に試行し、ソースを再現できない場合や行を失う場合は適用を拒否します。 - あらゆる環境で。 Supabase Cloud、セルフホストのスタック、通常の PostgreSQL の接続先、CI パイプライン、AI エージェント(MCP)で動作します。
アカルが開発しました。
クイックスタート
npm install -g @akal/supaforge
supaforge init # create supaforge.config.json
supaforge diff # what has drifted?
supaforge diff --detail # with the SQL
supaforge diff --apply # fix the target
書き込みを伴う操作はすべて、まずプレビューを表示します。実行するには --apply を追加してください。
インストール
| npm | npm install -g @akal/supaforge を実行するか、npx @akal/supaforge で実行します |
| Homebrew | brew install akalsoftware/tap/supaforge |
| Docker | docker run --rm -v "$PWD:/work" ghcr.io/akalsoftware/supaforge diff |
| GitHub Actions | akalsoftware/supaforge-action — CIを参照してください |
| VS Code とそのフォーク | SupaForge 拡張機能です。コマンドと、エディターのエージェント向け MCP サーバーを提供します。各リリースに .vsix として同梱されています |
| Cursor、VS Code、Claude | MCP サーバーをワンクリックでインストールできます。MCPを参照してください |
Node.js 20 以降が必要です。差分エンジンの DBDiff は、お使いのプラットフォーム向けのネイティブバイナリとして同梱されているため、ほかにインストールするものはありません。Docker イメージは追加のインストールが一切不要で、--prove が使用する PostgreSQL クライアントツールも含まれています。接続文字列は -e で渡し、プロジェクトを /work にマウントしてください。
比較対象
| チェック項目 | 読み取るもの | 修正方法 |
|---|---|---|
| スキーマ | @dbdiff/cli:自分が所有するすべてのスキーマ | SQL |
| 参照データ | checks.data.tables 内のテーブルの行 | SQL |
| RLS ポリシー | pg_policies。テキストではなく意味で比較 | SQL |
| RLS の適用状況 | RLS が無効になっているターゲット内のテーブル(ターゲットのみ) | SQL、オプトイン |
| Edge Functions | Management API、Studio、または Functions ディレクトリ | デプロイコマンド |
| ストレージ | バケットとそのポリシー(オブジェクトはコピーされません) | API と SQL |
| 認証設定 | Management API、またはセルフホスト環境の GoTrue | API(ホステッド) |
| Cron ジョブ | cron.job | SQL |
| キュー | Supabase Queues(pgmq.meta)。pgmq を通じて作成および削除 | SQL |
| パーティションセット | pg_partman の登録(part_config)。create_parent で作成 | SQL |
| Webhook | supabase_functions.http_request を呼び出すトリガー | SQL |
| Realtime | パブリケーションと realtime.messages のポリシー | SQL |
| Vault | シークレットの名前と説明(値は読み取れません) | 実行するコマンド |
| 拡張機能 | pg_extension | SQL |
| マイグレーション履歴 | ローカルのマイグレーションファイルと supabase_migrations の比較(ターゲットのみ) | SQL、オプトイン |
| ロールと権限付与 | カスタムロール、およびテーブル、ビュー、シーケンス、関数への権限付与。anon、authenticated、service_role を含む | SQL |
スキーマチェックでは、テーブル、カラム、キー、インデックス、パーティション、ビュー、
マテリアライズドビュー、関数、集約関数、トリガー、イベントトリガー、ルール、
シーケンス、列挙型、複合型と範囲型、ドメイン、キャスト、拡張統計、
テキスト検索設定と辞書、外部サーバー、ユーザーマッピングと外部テーブル、ポリシー、
デフォルト権限、レプリカ ID、統計ターゲット、拡張機能、コメントを対象にします。名前が変更されたカラム、
テーブル、シーケンスは、削除して再作成するのではなく、行を保持したまま名前を変更します。
Supabase 独自のスキーマ(auth、
storage など)と ignoreSchemas に指定されたスキーマを除くすべてのスキーマで実行されます。拡張機能が所有する
オブジェクトはその拡張機能に属し、比較されません。演算子クラスなど、比較対象外の種類のオブジェクトは、
チェック項目の下に名前が表示されるため手動で確認できますが、ドリフトとしては数えられません。
API 認証情報がない場合など、チェックを実行できない場合は、その旨と理由が表示されます。 正常に完了したとは報告されません。
コマンド
supaforge init Create a config interactively
supaforge diff Report drift (alias: hukam)
supaforge sync Alias for diff --apply
supaforge snapshot --apply Capture an environment's structure and configuration
supaforge restore --apply Rebuild a database from a snapshot or migrations
supaforge clone --apply Copy a remote database to a local one
supaforge migrate create Write a migration file from the current drift
supaforge migrate list Local migrations, applied and pending
supaforge migrate run --apply Run pending migrations
supaforge migrate baseline --apply Mark migrations applied without running them
supaforge report Recent runs, from a local log
supaforge mcp MCP server for AI agents
supaforge help <command> Every flag, e.g. help diff
diff の便利なフラグ:
| フラグ | 機能 |
|---|---|
--check=rls / --skip=storage | 1 つのチェックを指定するか、一部を除くすべてのチェックを実行します(--skip は繰り返し指定できます) |
--tables=orders,items / --exclude-tables='*_log' | スキーマとデータのチェック対象を絞り込みます |
--only=<id,...> | これらの検出結果のみを適用します(ID は --json から取得し、グロブを使用できます) |
--dry-run | 修正を実行順に表示し、実行はしません |
--prove | 使い捨てのコピーで修正を事前にリハーサルします |
--source-dir <dir> | ソースデータベースの代わりに、スキーマファイルのディレクトリ(supabase/schemas など)とターゲットを比較します |
--allow-destructive | 削除とデータの削除も適用します |
--apply-posture | ターゲットのみを対象とするチェックの修正も適用します |
--no-transaction | 修正を 1 つずつ適用し、成功した変更を保持します |
--no-snapshot | クエリを個別に読み取ります。デフォルトでは各データベースを同一時点の状態で読み取るため、スキャン中に行われた変更はすべての読み取りに反映されるか、まったく反映されません。pg_dump と同様、読み取るデータはスキャンが終了するまでロックされます |
--json / --ci | 機械可読な出力、CI アノテーション、終了コードを使用します |
修正の安全な適用
- 最初にプレビューします。
diff、snapshot、restore、clone、migrate runは、--applyを指定しない限り何も書き込みません。 - 破壊的な修正には追加のフラグが必要です。 スキーマ、テーブル、列の削除、行の削除または切り詰め、RLS ポリシーの削除は報告されますが、
--allow-destructiveを追加するまでスキップされます。migrate runも同じ制御を使用します。 - 依存関係の順序。 修正は依存関係の順に実行されます。呼び出し元のトリガーより先に関数を、インデックスより先に列を処理し、削除は最後に行います。削除して再作成する必要がある変更済みオブジェクトは、1 つの修正として扱われます。
- 1 つのトランザクション。 修正に失敗すると、一連の変更全体がロールバックされ、ターゲットは変更されません。拡張機能や、ターゲットにない Supabase スキーマが必要なためにターゲットに保持できない修正は、理由とともにスキップされ、残りの修正は引き続き適用されます。
--prove。 適用時と同じ方法で修正を再実行できるよう、ターゲット自身のサーバー上に作成したターゲットの構造のコピーで、各テーブルの行のサンプルを使って修正を再実行します。結果がソースと一致し、行が保持されない限り適用されません。また、検証を実行できない場合も適用されません。修正によって書き換えられるテーブルも示します。cron ジョブのようにコピーでは保持できない変更(pg_cron はサーバーごとに 1 つのデータベースに存在します)は、検証されていないものとして一覧表示されます。
supaforge diff --dry-run # the plan, in order
supaforge diff --apply --prove # rehearse, then apply
supaforge diff --apply --only='schema-create-*'
状態チェック
RLS カバレッジとマイグレーション履歴はターゲットのみを対象とするため、どのペアを差分比較しても同じ検出結果が報告されます。これらは個別にスコア化され(Posture score)、--fail-on-posture を指定しない限り終了コードには影響しません。また、修正を適用するには --apply-posture を指定するか、--check=rls-coverage --apply のようにチェック名を指定します。これらを無条件に適用すると、ターゲットはソースから離れた状態になります。
スナップショット、復元、クローン
supaforge snapshot --env=prod --apply # capture
supaforge snapshot --env=prod --migration --apply # and write what changed since the last one
supaforge restore --env=local --from-snapshot=latest --apply
supaforge clone --env=prod --apply # local copy, data included
スナップショットには、プロジェクトの構造と設定が記録されます。対象は、スキーマ、RLS ポリシー、cron、ウェブフック、拡張機能、ストレージ、認証、Edge Functions、参照データ、Realtime、Vault の名前と権限です。バックアップではありません。 checks.data.tables にあるデータ以外の行データや、保存されたファイルは含まれません。スキーマは pg_dump によって SQL として出力されます。pg_dump はサーバーと同じか、それより新しいバージョンである必要があります。これがなくてもスナップショットの差分は確認できますが、復元はできません。また、--allow-schema-json-only でそれで十分だと指定しない限り、snapshot は終了コード 1 で終了します。
restore --from-snapshot で復元される項目は次のとおりです。
| 復元される項目 | 備考 |
|---|---|
| 拡張機能、スキーマ、RLS ポリシー、cron ジョブ、ウェブフック、Realtime パブリケーション、権限 | 依存関係の順に SQL として復元されます。ポリシーまたは権限で指定されているロールは、先に作成されます |
| ストレージポリシーとバケット | 対象に storage スキーマがある場合、バケットの行が作成されます。ファイルは復元されません |
| 参照データ | checks.data.tables の行が、親テーブルから子テーブルの順に復元され、シーケンスは復元された ID の次の値に進められます |
認証設定、Edge Functions(supabase functions deploy でデプロイしてください)、Vault のシークレット値は復元できません。これらはそれぞれ出力に表示されます。
- 対象。 復元は 1 つのトランザクションとして実行され、空のデータベースを想定しています。
--forceを指定すると、最初にスナップショットに含まれるスキーマのみを消去し(Supabase のスキーマは消去しません)、消去したものに依存していた、それらのスキーマ外にあるトリガーとポリシーを復元します。復元または適用で、対象が 1 つのトランザクションで許容できる以上のロックが必要になる可能性が高い場合、実行前にその旨を通知します。代わりに--no-transactionを指定すると、処理を進めながらコミットします。 - 通常の PostgreSQL。 通常の PostgreSQL への復元も可能です。存在できないものはスキップされ、その理由が表示されます。これには、
auth.usersへの外部キー、ウェブフック、サーバーに同梱されていない拡張機能、およびそれらを必要とするすべてのものが含まれます。 - 終了コード。 復元で未復元の項目が残った場合、終了コード 1 で終了します。実行が拒否された場合も同様です。
- JSON。 プレビューの場合も含め、
--jsonは JSON のみを出力します。
clone は pg_dump と pg_restore を使って、リモートデータベースをローカルサーバーにコピーします(--schema-only を指定すると行データをコピーしません)。ローカルサーバーにある拡張機能は先にインストールされます。復元できなかったオブジェクトは、原因別に一覧表示されます。その後、設定の target はクローンを指すようになるため、引数なしの diff --apply はリモートではなくクローンに書き込みます。
マイグレーション
supaforge migrate create --name=add_orders # from the drift between source and target
supaforge migrate run --env=prod # preview
supaforge migrate run --env=prod --apply
- ファイルと履歴。 ファイルは
supabase/migrationsに保存されます(変更するにはchecks.migrations.dirを設定してください)。適用済みのバージョンは、Supabase CLI のテーブルであるsupabase_migrations.schema_migrationsに記録されます。 - 破壊的なステートメント。
migrate createは、作成した破壊的なステートメントを一覧表示します。実行するにはmigrate runに--allow-destructiveが必要です。 - 履歴テーブルの権限。 セルフホストのスタックでは、履歴テーブルが管理者ロールに属している場合があります。その場合、SupaForge は単に権限エラーを出すのではなく、必要な
GRANTを示します。 - 追跡対象の履歴がないプロジェクト。
checks.migrations.modeによって、マイグレーション履歴チェックでの報告方法が決まります。auto(追跡対象がない場合に 1 回通知)、warn、またはignoreを指定できます。
設定
{
"environments": {
"dev": { "dbUrl": "$DEV_DATABASE_URL", "projectRef": "abc123", "accessToken": "$SUPABASE_ACCESS_TOKEN" },
"prod": { "dbUrl": "$PROD_DATABASE_URL", "projectRef": "xyz789", "accessToken": "$SUPABASE_ACCESS_TOKEN" }
},
"source": "dev",
"target": "prod",
"checks": {
"data": { "tables": ["plans", "feature_flags"] },
"exclude": ["edge-functions"]
}
}
| フィールド | 意味 |
|---|---|
dbUrl | PostgreSQL 接続文字列です。$VAR と ${VAR} は環境から読み込まれます |
projectRef, accessToken | Management API のチェック(認証、Edge Functions)を有効にします |
apiUrl | セルフホスト型の API ゲートウェイです。projectRef の代わりに使用されます |
studioUrl, functionsPath | セルフホスト型の Edge Functions の読み込み元です |
source, target | 比較対象です。source が正となり、target が修正されます |
ignoreSchemas | 対象から除外する独自スキーマです |
checks.data.tables | 行を比較してスナップショットを作成するテーブルです |
checks.exclude | 実行しないチェックです(--skip と統合されます) |
checks.tables, checks.excludeTables | スキーマチェックとデータチェックのデフォルトの対象範囲です |
checks.migrations.dir, checks.migrations.mode | マイグレーションの保存場所と、履歴チェックのレポート方法です |
- 環境ごとの設定。
checks.excludeとchecks.schema.timeoutは環境ごとにも設定でき、対象環境が target の場合に適用されます。 .envファイル。.envファイルは Next.js と同じ方法で読み込まれます。.env.{NODE_ENV}.local、.env.local、.env.{NODE_ENV}、.envの順です。すでに環境に設定されている値が優先されます。- 単一データベース。 環境が 1 つで
source/targetがない設定も使用できます。snapshot、clone、restoreを使用してください。
| 環境変数 | デフォルト | 用途 |
|---|---|---|
SUPAFORGE_DBDIFF_TIMEOUT | 600 | スキーマまたはデータの差分チェックを中断するまでの秒数です |
SUPAFORGE_DBDIFF_MEMORY | 1G | @dbdiff/cli のメモリ制限です(2G、制限なしの場合は -1) |
SUPAFORGE_CONNECT_TIMEOUT | 15 | 接続を待機する秒数です |
SUPAFORGE_CHECK_CONCURRENCY | 4 | 同時に実行するチェック数です。接続プールの容量が小さい場合は値を下げてください |
SUPAFORGE_PROVE_ROWS | 1000 | 各テーブルから --prove がコピーし、維持されることを確認する行数です。0 の場合は構造のみを確認します |
SUPAFORGE_PG_BIN | — | PostgreSQL クライアントツール(pg_dump、psql)のディレクトリです。PATH より優先して使用されます。PATH 上のツールより新しいサーバーに使用します |
セルフホスト型 Supabase
apiUrl にゲートウェイを、accessToken にサービスロールキーを設定します。すべてのチェックが実行されます。
- Edge Functions。 セルフホスト環境には Edge Functions 用の管理エンドポイントがないため、
studioUrl(ゲートウェイではなく Studio のポート)またはfunctionsPath(マウントされた関数ディレクトリ)を設定してください。環境ごとに両方を組み合わせて使用できます。Studio の関数 API は認証されないため、公開しないでください。 - 認証設定。 セルフホスト環境では、認証設定は GoTrue の設定エンドポイントから読み込まれます。このエンドポイントが返すキーは少なく、書き込みもできません。デプロイ環境の設定を変更してください。
クローンの差分チェック
ローカルクローンは通常の PostgreSQL です。Storage、認証、Edge Functions、Vault、Realtime、Supabase のロールには比較対象がないため、これらのチェックをスキップしてください。
{ "checks": { "exclude": ["storage", "auth", "edge-functions", "vault", "realtime", "roles"] } }
source がクローンで target がクローンではない場合、diff は --apply を実行すると、存在しないものも含め、クローンの構造が target に適用されることを警告します。
CI と終了コード
GitHub Action は
diff --ci を実行し、ドリフトの概要をジョブページに追加します。
- uses: akalsoftware/supaforge-action@v1
env:
DEV_DATABASE_URL: ${{ secrets.DEV_DATABASE_URL }}
PROD_DATABASE_URL: ${{ secrets.PROD_DATABASE_URL }}
それ以外の場合は、CLI を実行します。
npx @akal/supaforge diff --ci
| コード | 意味 |
|---|---|
0 | 要求された処理を実行しました。処理対象がなかった場合も含みます |
1 | ドリフトを検出した、処理を見送った、または失敗したか一部を除外しました |
2 | 実行できませんでした。使用方法に誤りがあるか、--ci で完了できないチェックがありました |
デフォルトでは、--ci は重大なドリフトがあると失敗します。しきい値は
--fail-on=warning または --fail-on=any で設定できます。
MCP(AI エージェント)
SupaForge は MCP サーバーとして動作するため、エディター内の AI エージェントがドリフトを検出して修正できます。書き込みを行う前に、必ず確認を求めます。
-
Claude Desktop:お使いのプラットフォーム用の拡張機能(
supaforge-<version>-<platform>.mcpb)を最新リリースからダウンロードして開きます。プロジェクトディレクトリの指定を求められます。 -
Claude Code:MCP サーバーと、安全に修正を適用するためのスキルを追加するプラグインをインストールします。
/plugin marketplace add akalsoftware/claude-plugins /plugin install supaforge@akalsoftwareまたは、サーバーだけを追加します:
claude mcp add supaforge -- npx -y @akal/supaforge mcp -
その他のクライアント:
{ "mcpServers": { "supaforge": { "command": "npx", "args": ["-y", "@akal/supaforge", "mcp", "--project", "/path/to/project"] } } }
MCP レジストリには、io.github.akalsoftware/supaforgeとして登録されています。
サーバーは次のツールを公開します。
| ツール | 内容 | 注釈 |
|---|---|---|
list_environments | 認証情報を除いた、設定内の環境一覧 | 読み取り専用 |
diff | syncが実行する計画を含む、すべての差分 | 読み取り専用 |
get_check_result | 直近のdiffまたはsyncにおける、指定したチェックの結果 | 読み取り専用 |
sync | 対象に計画を実行します。prove: trueを指定すると、先にコピー上でリハーサルを行います | 破壊的 |
create_migration | migrate createと同様に、ドリフトをマイグレーションファイルに書き込みます | ファイルを書き込み |
take_snapshot | 環境のスナップショットをローカルファイルに保存します | ファイルを書き込み |
diffとsyncは同じ引数を受け取るため、エージェントが提示する計画がそのまま実行されます。テーブルやカラムを削除する修正は、allowDestructiveが設定されていない限り保留されます。
--projectで指定されたディレクトリ(または起動時のディレクトリ)にあるsupaforge.config.jsonを読み込みます。--allow-config-pathを指定して起動していない場合、クライアントからのconfigPathは拒否されます。
フック
import { HookBus, scan, createDefaultRegistry, loadConfig } from '@akal/supaforge'
const bus = new HookBus()
bus.on('supaforge.check.after', ({ check, result }) => {
if (result.status === 'drifted') console.log(`Drift in ${check}`)
})
await scan(createDefaultRegistry(), { config: await loadConfig() }, bus)
開発
cd packages/cli
npm install
npm test # unit tests
npm run lint # type-check
./bin/dev.js diff # run from source
| スイート | コマンド | 必要なもの |
|---|---|---|
| 統合テスト | npm run test:integration | DockerまたはPodman |
| データベースのe2eテスト | npm run test:e2e | DockerまたはPodman |
| シナリオ | npx vitest run -c vitest.scenarios.config.ts | DockerまたはPodman、pg_dump |
| Supabaseのe2eテスト | npm run test:e2e:supabase | Supabase CLI |
| リリース候補 | scripts/test-release-candidates.sh --dbdiff ../DBDiff --pg-conformance ../pg-conformance | PodmanまたはDocker |
リリース候補スクリプトは、リリース時と同じ方法で、ローカルのチェックアウトからDBDiffのバイナリとnpmパッケージをビルドします。それらに対してSupaForgeをユーザーと同じ方法でインストールし、上記のすべてのスイートを実行します。いずれかをリリースする前に、3つのプロジェクトにまたがる変更をテストできます。
シナリオスイートでは、@akal/pg-conformanceのコーパスにあるすべてのケースを、両方向にマイグレーションします。結果をコーパス独自の状態オラクルおよび--proveと照合します。
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。