Planche ドキュメント

Planche の機能を、アプリで見える画面とともに説明します。スクリーンショットと同じサンプルデータベースは、ブラウザでそのまま開けます。

はじめに

Planche はブラウザで使うデータベースクライアントです。SQLite ファイルはページ内で直接開き、MySQL や PostgreSQL などのネットワーク型データベースには、自分のパソコンで動かすエージェントを通じて接続します。2 つの方法は併用できます。

SQLite ファイル: インストール不要

.sqlite、.db、.sqlite3 ファイルをページにドロップするか、開始画面から選びます。WebAssembly にコンパイルされた SQLite がページの中で読み込むので、ファイルがアップロードされることはありません。ブラウザが File System Access API に対応していれば元のファイルに書き戻せますし、対応していなければコピーをダウンロードします。

MySQL、PostgreSQL、SQL Server、Oracle、Neon、Supabase、Cloudflare D1: コマンド 1 行

ブラウザからデータベースへ直接 TCP 接続することはできません。接続はローカルエージェントが代行します。

npx planche

エージェントは 127.0.0.1:8888 で起動し、ペアリングリンクを表示します。リンクを開くとアプリが接続された状態で起動します(--open を付けるとブラウザで自動的に開きます)。リンクには使い捨てのコードが含まれ、アプリはそれをエージェントのトークンと交換します。そのためトークン自体は URL やシェル履歴に残りません。以後、ブラウザは 127.0.0.1 とだけ通信し、エージェントがデータベースへ接続します。ホスト・ユーザー・パスワードは手元のマシンにとどまります。

開始画面: 利用規約に同意し、エージェントを起動するか、サンプルデータベースを試せます。
開始画面: 利用規約に同意し、エージェントを起動するか、サンプルデータベースを試せます。

エージェントには Node.js 22 以上が必要です。npx が npm レジストリから取得して実行します。npx planche@latest は最新バージョンを実行します。特定のバージョンを使う場合は、latest の代わりにバージョン番号を指定してください。

npx の代わりにインストールする

マシンに Node.js がない場合、あるいは常設のコマンドとして使いたい場合は、1 行でインストールできます:

macOS, Linux

curl -fsSL https://planche.dev/install.sh | sh

Windows

irm https://planche.dev/install.ps1 | iex

すべてホームディレクトリの下に収まり、管理者権限は求めません。Node.js 22 以上がすでにあればそれを使い、なければ公式ランタイムの複製をダウンロードして、nodejs.org が公開しているチェックサムで検証します。以後は planche が PATH 上のコマンドになり、レジストリへの往復なしにすぐ起動します。インストールが終わるとスクリプトがそのままエージェントを起動するので、最初の 1 回は他に何もする必要がありません — シェルが新しい PATH を読むのは新しいターミナルからです。

更新は planche upgrade、削除は planche uninstall で、~/.planche の設定はどちらでも残ります。新しいバージョンが出ると、エージェントが 1 日 1 回までお知らせします(PLANCHE_NO_UPDATE_CHECK=1 で無効化できます)。インストールスクリプトはただのテキストなので、実行前に読むこともできます: curl -fsSL https://planche.dev/install.sh -o install.sh。

インターネットがない、またはネットワークで planche.dev が遮断されている場合、エージェントは起動時に検知して、同梱のアプリを自分のアドレスで配信します。サンプルデータベースを除く機能は同じです。この場合、アプリのバージョンはエージェントと一致します。npx planche@latest を実行すれば更新できます。

制限された社内網・閉域網で使う

外部が必要なのはエージェントを持ち込む工程だけです。npx は npm レジストリから取得するためです。それが塞がれている場合は、npm に到達できるマシンで一度インストールして持ち込むか(npm i -g planche)、npm pack planche で tarball を作って搬入するか、社内レジストリに公開してください。

その後はネットワークの外に出る通信はありません。エージェントが自分のアドレスでアプリを配信し、そのページは手元のマシンの外へ一切リクエストを出しません。エディタも SQLite エンジンもアイコンもすべて同梱されており、CDN も Web フォントも利用統計もありません。--serve-app を付ければ到達確認を省いて最初からローカルで配信します。リクエストを拒否せず飲み込んでしまうネットワーク(たとえばキャプティブポータルがどのアドレスにも応答する場合)でも、このオプションが有効です。

諦めることになるのは、本当にインターネットを必要とするものだけです。ホスト型サービス(Neon、Supabase、Cloudflare D1)、到達できないホストへの SSH、そしてサンプルデータベースです。ネットワーク内のデータベースは、チーム全体で使うゲートウェイも含めて、ほかの環境とまったく同じように動きます。

ワークスペース

ブラウザのタブ 1 つで、複数のデータベース接続を開けます。接続ごとにツールバーの下へタブが追加され、クリックするとそのデータベースに切り替わります。

サンプルデータベースを開いた画面。上に接続タブ、左にスキーマツリー、中央に SQL エディタ、下に結果。
サンプルデータベースを開いた画面。上に接続タブ、左にスキーマツリー、中央に SQL エディタ、下に結果。

接続を切り替えると画面全体がその接続のものに入れ替わります。接続ごとに状態を別々に保持しているからです。別の接続に行って戻ってくると、開いていたクエリタブ、書きかけの SQL、表示していた結果がそのまま残っています。

  • スキーマツリー(左) — この接続のデータベース、テーブル、ビュー、プロシージャなどの一覧です。クリックで展開し、右クリックするとそのオブジェクトに対してできる操作が出ます。
  • クエリタブ(右上) — タブ 1 つが SQL エディタ 1 つで、必要なだけ開けます。ツリーの「Open Table」で開いたタブは、エディタの代わりにそのテーブルの行をグリッドで表示します。
  • 結果パネル(下) — Message には各文が何をしたか(影響行数、エラー、所要時間)が記録され、その隣に Info と History があります。結果セットが返るたびに Result タブが 1 つ増えます。
  • フッター — 今見ている接続の名前、読み取り専用やトランザクション中であることを示すバッジ、直近のステータスメッセージ。

ブラウザを閉じても作業は失われません。開き直すと接続は自動で再接続し、クエリタブとその中の SQL が戻り、ファイルから開いた SQLite データベースはファイルへのアクセスを許可し直す前でもローカルの複製から復元されます。

データベースへの接続

Connection › Connect(Alt + N)で接続マネージャを開き、Add New から DBMS を選びます。フォームにはそのエンジンに必要な項目だけが表示されます。Test Connection は設定だけを確認し、Connect は接続タブを開きます。

MySQL のプロファイル。左は保存済みプロファイル、右のフォームはエンジンによって変わります。
MySQL のプロファイル。左は保存済みプロファイル、右のフォームはエンジンによって変わります。

エンジンごとに必要なもの

  • MySQL / MariaDB — ホスト、ポート(3306)、ユーザー、パスワード。データベースは任意で、ツリーにはすべて表示されます。文字セットの既定は utf8mb4 です。
  • PostgreSQL — ホスト、ポート(5432)、ユーザー、パスワード、そしてデータベース(必須)。PostgreSQL のセッションはデータベースを切り替えられないためです。代わりにその中のスキーマがツリー上の「データベース」として扱われ、SET search_path で切り替えます。
  • SQL Server — ホスト、ポート(1433)、ログイン、パスワード、データベース。スキーマ(dbo など)が「データベース」として扱われます。Azure SQL では TLS を有効に、自己署名証明書ならサーバー証明書の検証はオフのままにします。
  • Oracle — ホスト、ポート(1521)、ユーザー、パスワード、そしてサービス名(例: FREEPDB1)。エージェントは純粋な JavaScript の thin ドライバを使うので Instant Client のインストールは不要です。スキーマはユーザーそのもので、ALTER SESSION SET CURRENT_SCHEMA で切り替えます。
  • SQLite — 開き方を選びます。ブラウザでは何もインストールせず、ファイルのメモリ上のコピーを扱います。エージェント経由はエージェントが動くマシンで本物の SQLite がファイルを開くため、ロックや WAL が正しく働き、他のプログラムと併用しても安全です。この場合はパスを入力し、ファイルがなければ作成させることもできます。
  • Neon / Supabase — コンソールの接続文字列を貼り付ければ、ホスト・ユーザー・パスワード・データベースが自動で入ります。TLS は常時有効で SSH の手順はありません。Supabase ではセッションプーラー(ポート 5432)か直接接続を使ってください。ポート 6543 はトランザクションプーラーで、文ごとに別のバックエンドに届く可能性があるためスキーマ切り替え・一時テーブル・手動トランザクションが機能せず、選ぶと Planche が警告します。
  • Cloudflare D1 — アカウント ID、データベース ID、そして D1 Edit 権限(読み取り専用なら D1 Read)の API トークン。エージェントがそれで Cloudflare REST API を呼び出すため、TCP 接続も SSH もありません。すべてのリクエストが自動コミットされるので、D1 では手動トランザクションは無効です。
  • Redis — ホスト、ポート(6379)、パスワード、そしてサーバーに ACL ユーザーがあればそのユーザー(default ユーザーなら空のままにします)。データベース欄は最初に使う論理データベース(db0)です。TLS と SSH は SQL エンジンと同じように使えます。
  • Elasticsearch / OpenSearch — ホストとポート(9200)。ユーザーとパスワードを入れると Basic 認証でサインインし、ユーザーを空にするとパスワードが API キー(エンコード済みの id:key)として送られます。https なら TLS を有効にし、自己署名証明書(Elasticsearch 8 の既定)ならサーバー証明書の検証はオフのままにします。
  • Cloudflare DO (wrangler dev) — wrangler dev サーバー URL(既定値 http://localhost:8787)だけを指定し、アカウント ID、トークン、パスワードは不要です。ローカルの wrangler dev セッションだけを読み、デプロイ済み Durable Objects は非対応で、各オブジェクトが別々のデータベースとして表示されます。

パスワード、トークン、ガードレール

  • Save password — オフならパスワードはタブを閉じるまで、オンならプロファイルとともにこのブラウザに保存されます。どちらの場合も自分のエージェント以外には送られません。
  • Agent token — 空にするとペアリングリンクで受け取ったトークンを使います。エージェントを複数動かす場合や手動でペアリングした場合だけ入力してください。
  • 読み取り専用、環境カラー、トランザクションモードはプロファイルごとの設定です。安全をご覧ください。

SSH トンネル

踏み台ホスト経由で接続するデータベースには SSH トンネルを使います。プロファイルで SSH tunnel をオンにして踏み台の情報を入力すると、ローカルエージェントがトンネルを開いて接続を通します。

SSH の項目: 踏み台ホスト、ユーザー、認証方法。上のホスト・ポートは踏み台から見たデータベースのアドレスです。
SSH の項目: 踏み台ホスト、ユーザー、認証方法。上のホスト・ポートは踏み台から見たデータベースのアドレスです。

入力項目

  • SSH Host / Port — 踏み台。~/.ssh/config の Host エイリアスをそのまま使えます。Planche は ssh コマンドとまったく同じように解決し、HostName、User、Port、IdentityFile を補います(Include も辿ります。ProxyJump は未対応です)。
  • SSH User — 空にすると設定ブロックのユーザーを使います。
  • SSH Auth — 秘密鍵、パスワード、ssh-agent から選びます。
    • 秘密鍵: 鍵ファイルを選ぶか、空にすると設定の IdentityFile、それもなければ ~/.ssh/id_* を使います。鍵にパスフレーズがあれば入力してください。
    • ssh-agent: npx planche を動かしているマシンのエージェントソケット(SSH_AUTH_SOCK)を使うので、ハードウェアキーや転送されたエージェントもそのまま利用できます。
  • 上のフォームのデータベースのホストとポートは踏み台から見たものとして解決されます。多くの場合 127.0.0.1 か内部名です。

ホストキー

初めて接続する踏み台ではフィンガープリントを表示し、受け入れるか確認します。受け入れた鍵は ~/.planche/known_hosts に追記され、既存の ~/.ssh/known_hosts も読み込まれます。後で鍵が変わった場合は、もう一度信頼するのではなく接続を拒否します — ssh コマンドと同じ規則です。

知っておくと良いこと

  • 鍵とパスフレーズは Save password の設定に従い、ブラウザから自分のローカルエージェントへしか渡りません。
  • トンネルは接続と一緒に閉じられます。
  • SSH の認証失敗はデータベースのエラーと区別して報告されるので、どちらを直すべきかすぐ分かります。
  • エージェントに ~/.ssh/config と既定の鍵を一切見せたくない場合は、起動前に PLANCHE_SSH_CONFIG=none を設定してください。

wrangler dev の Cloudflare Durable Objects

Cloudflare DO (wrangler dev) はローカル開発専用です。自分のマシンで実行中の wrangler dev セッションにある Durable Objects を読み取ります。デプロイ済みの Durable Objects はサポートされません。

オブジェクトごとにデータベースとして表示される理由

各 Durable Object は専用の非公開 SQLite データベースを持つため、スキーマツリーでは各オブジェクトが別々のデータベースとして表示されます。名前付きオブジェクトは <namespaceId>/<object> 形式です。たとえば do-probe-Counter/probe-one は do-probe-Counter 名前空間の probe-one オブジェクトで、名前空間 ID は <script>-<ClassName> です。これは通常のデータベース名ではなく、idFromName() に渡したオブジェクト名です。newUniqueId() で作成したオブジェクトには名前がないため、64 文字の 16 進 ID で表示されます。

wrangler は開発レジストリを保持します。同時に動いている別の wrangler dev セッションの Durable Objects も表示されるため、1 つの Planche プロファイルで複数のローカルプロジェクトを調べられます。

接続

  1. Worker プロジェクトで wrangler dev を実行します。
  2. npx planche を実行し、Cloudflare DO (wrangler dev) 接続を作成します。
  3. wrangler dev サーバー URL を入力します。既定値は http://localhost:8787 です。アカウント ID、API トークン、パスワード、SSH 設定はありません。

ローカルエージェントは <devUrl>/cdn-cgi/local/explorer/api にある wrangler の Local Explorer API を読み取るため、Worker 側にコンポーネントをインストールしたりデプロイしたりする必要はありません。URL はループバックでなければなりません。それ以外を許すと、エージェントが任意のホストへの HTTP プロキシになるためです。

何も待ち受けていない場合: Cannot reach a wrangler dev server at http://localhost:8787 (fetch failed). Run `wrangler dev` in your Worker project and try again.

別のサーバーのポートの場合: ... answered (HTTP 401) but is not a wrangler dev server. Check the port, and that `wrangler dev` (wrangler 4.x) is what is running there.

SQLite の機能とストレージ

Durable Object ストレージは SQLite なので、SQL エディタと ctx.storage.sql のテーブルは他の SQLite データベースと同様に使えます。Planche は sqlite_master と PRAGMA からテーブル、ビュー、トリガー、列、インデックスを読み取り、CREATE TABLE DDL、外部キーからの ERD、単一テーブル SELECT を元テーブルに対応付けた結果グリッドでの行編集をサポートします。

miniflare の内部管理テーブル __miniflare_do_name はツリーから隠します。ctx.storage.put() のデータが入る _cf_KV は確認する価値があるため表示します。

各リクエストは自動コミットされます。BEGIN、COMMIT、ROLLBACK は説明付きで拒否され、Cloudflare D1 と同様に手動トランザクションの設定も隠されます。

デプロイ済みオブジェクトが非対応である理由

Cloudflare の公開 API で文書化されている Durable Objects のメソッドは、名前空間一覧とオブジェクト一覧の 2 つだけです。オブジェクトのストレージを照会する、文書化された SQL エンドポイントはありません。

Cloudflare ダッシュボードにはデプロイ済みオブジェクトを照会する Data Studio タブ(Beta)があり、その背後のエンドポイントには API トークンで到達できます。しかし公開 API リファレンスにはなく、予告なく変更される可能性があります。Durable Objects 専用のトークン権限もありません。D1 の D1 Read/D1 Edit や Workers KV、R2 の専用権限と異なり、このエンドポイントを使える唯一の権限は Workers Scripts Edit です。これはアカウント内のすべての Worker をデプロイ、変更できる書き込み権限です。Planche はデータ閲覧のためにその権限を求めません。

現在デプロイ済みオブジェクトにアクセスするには、ダッシュボードの Data Studio を使うか、Worker から独自のエンドポイントを公開してください。

Redis

Redis プロファイルは Redis 6 と 7、および同じプロトコルを話すサーバー(Valkey、KeyDB、Dragonfly)で使えます。エージェントはプロファイルごとに接続を 1 本保持し、Pub/Sub または Monitor のタブを開いている間はもう 1 本使います。

キーツリー

ツリーには論理データベース(既定では db0 から db15)がキー数とともに並びます。データベースを展開すると、キーが最初の : 区切り(user:、session:)でグループ化され、各グループも同じように展開できます。どの階層も SCAN で 1,000 キーずつ読み込み、10,000 キーで止めてその旨を表示します。KEYS は実行しません。KEYS はキー空間全体をたどる間ずっとサーバーをブロックするためです。キー名はセッションをまたいで保存されません。

キービューア

キーをダブルクリックすると専用のタブで開きます。ヘッダーには型、有効期限(TTL)、長さ、メモリ(MEMORY USAGE)が表示されます。TTL と名前はそこで変更でき、確認のあとでキーを削除できます。名前の変更には RENAMENX を使うので、既存のキーが上書きされることはありません。

  • ハッシュ、セット、ソート済みセット — HSCAN / SSCAN / ZSCAN で読むテーブルで、フィルタ(プレーンテキスト、または a* のような glob)と Load more があります。値とスコアはその場で編集し、行はテーブルから追加・削除します。
  • リスト — インデックスと値を 200 件ずつ読みます。要素の編集、両端への追加、削除ができます。Redis はリストの要素を値でしか削除できないため、削除はまず要素を一意のマーカーで上書きし、次にそのマーカーを削除します。コマンドは 2 回で、その間に別のクライアントがリストをずらすとインデックスが変わることがあります。
  • ストリーム — 新しいエントリから順に、フィールドとともに表示します。エントリの追加(field value; field value)と削除ができます。
  • 文字列と RedisJSON — JSON の値は折りたためるツリーとして、HTML の値は描画されたページとして開きます。編集するには Text に切り替えます。1 MB を超える値は、残りを要求するまで最初の 1 MB だけを読み込みます。HTML はスクリプトを実行せず他のホストから何も読み込まない sandbox フレームで描画します。

コンソール

Redis 接続のクエリタブはコンソールです。1 行に 1 コマンドを redis-cli の構文で書きます(ダブルクォートでは \n, \xHH のエスケープが使え、シングルクォートはそのまま)。コメントは # と // です。Ctrl / ⌘ + Enter はカーソル行のコマンドを実行し、スクリプト全体の実行ではコマンドを 1 つずつ順に実行します。SELECT n はタブをそのデータベースに移します。単一オブジェクトの応答は JSON で、レコードはテーブルで開き、結果の上の Table / JSON スイッチで切り替えられます。

SUBSCRIBE、PSUBSCRIBE、MONITOR はコンソールでは拒否されます。これらは接続を占有し続け、ツリーと他のすべてのタブを止めてしまうためです。代わりに Pub/Sub と Monitor のツールを使ってください。

ツール

ツリーの空いている場所を右クリックするか、Tools メニューを使います。

  • サーバー情報 — INFO をカード(バージョン、メモリ、ヒット率、毎秒の操作数、永続化、レプリケーション)で表示し、各データベースのキー数と、フィルタ付きの全フィールドも示します。指定すれば 5 秒ごとに更新します。
  • スローログ — SLOWLOG GET の新しい 128 件を所要時間とクライアントとともに表示し、記録対象になるしきい値も示します。クリアは先に確認します。
  • クライアント — CLIENT LIST。他のクライアントは確認のあとで切断できます。アプリ自身の接続には印が付き、ここからは切断できません。
  • Pub/Sub — チャンネルと glob パターン(news orders.*)を購読してメッセージの到着を見られます。チャンネルに発行すると、何人の購読者が受け取ったかが分かります。
  • Monitor — すべてのクライアントが実行するすべてのコマンドを、実行と同時に表示します。Redis は各コマンドをすべてのモニターにコピーするので、負荷の高いサーバーではスループットが下がります。短時間だけ使ってください。フィードがエージェントの上限(100 ms あたり 500 イベント)を超えると、スキップしたコマンドの数を表示します。
  • メモリ分析 — データベースをスキャンし(最大 10,000、100,000、1,000,000 キー)、各キーのサイズ、型、有効期限をバッチで問い合わせます。型別、プレフィックス別、有効期限別のメモリと、最大 50 キーを表示します。20,000 キーで約 1 秒かかります。MEMORY USAGE は大きなコレクションを要素のサンプルから推定します。キーをクリックすると開き、プレフィックスをクリックするとそのキーを削除できます。
  • パターンでキーを削除 — パターンに一致するキーを探し(1 回の実行で最大 100,000)、件数と 20 個のキーを示し、パターンの再入力を求めてから UNLINK で 500 個ずつ削除します。履歴には 1 回の実行が 1 件として記録されます。データベースやプレフィックスのノードのメニューからも使えます。

安全

読み取り専用プロファイルは、Planche の読み取りコマンド一覧にあるコマンドだけを受け付けます。ゲートウェイエージェントは各コマンドをサーバー自身の COMMAND INFO フラグと照合します。FLUSHDB、FLUSHALL、SWAPDB、SHUTDOWN などのコマンドは実行前に確認します。AUTH、HELLO … AUTH、MIGRATE … AUTH、CONFIG SET requirepass、ACL SETUSER のパスワードは履歴でマスクされます。

未対応

Redis Cluster と Sentinel。クラスタノードに接続すると、Planche は db0 にそのノードのキーだけを表示し、別のノードが持つキーについては、リダイレクトをたどる代わりにそのノードを示します。

スキーマツリー

スキーマツリーの構成はエンジンごとに異なります。MySQL と SQLite はデータベース › オブジェクト、PostgreSQL と SQL Server にはスキーマ階層があります。フォルダの件数で、展開前にもテーブル数を確認できます。

サンプルデータベースのテーブル・ビュー・トリガーと件数。
サンプルデータベースのテーブル・ビュー・トリガーと件数。

どのノードでも右クリックすると、その場に合った操作が出ます。

  • Open Table — 設定の行数制限を適用してデータグリッドを開きます。
  • Generate SQL — 実際の列と主キーから作った SELECT・INSERT・UPDATE・DELETE のひな形をカーソル位置に挿入します。
  • Show Create / Alter — オブジェクトの DDL、またはテーブルデザイナ。
  • Copy Table to… / 比較 / データ比較 — 後の節で説明します。
  • Truncate / Drop — メニューの最下部に離して置かれ、どちらもオブジェクト名の再入力が必要です。

SQL エディタ

エディタは VS Code と同じ Monaco を使い、アプリに同梱されています。補完には方言のキーワードや関数のほか、接続中のテーブルと列も表示されます。

実際のスキーマからの補完と、方言のキーワード。
実際のスキーマからの補完と、方言のキーワード。

文の実行

  • Ctrl / ⌘ + Enter — 選択範囲、またはカーソル位置の文を 1 つ実行します。
  • F9 — 設定 › 安全 › 実行範囲に従います(既定はスクリプト全体)。
  • Ctrl / ⌘ + Shift + Enter — 常にスクリプト全体を実行します。

スクリプトはセミコロンではなく本物のパーサで分割します。BEGIN … END の本体は壊れず、クライアントの DELIMITER コマンド、PostgreSQL の $$ ドル引用、SQL Server の GO バッチ、/ で終わる Oracle の PL/SQL ブロックをすべて理解します。各文を分類しているからこそ、行数制限・破壊的な文の確認・ドライランが可能になります。

行数の上限

制限のない SELECT には LIMIT(エンジンにより TOP や FETCH FIRST)を付け、巨大なテーブルに誤って SELECT * を投げてもブラウザが埋もれないようにします。既定は 500 行で、適用されたときは結果に表示されます。すでに自分で制限している文はそのままです。

履歴とローカルスナップショット

実行時間、行数、実行した接続まで残る実行履歴。
実行時間、行数、実行した接続まで残る実行履歴。

History タブは実行した文を一覧し、Query › Local History は各エディタタブのテキストのスナップショットを保持するので、置き換えたり実行したりしたテキストを戻せます。保存前にパスワードのリテラルはマスクされ、設定で保存自体をオフにもできます。

結果グリッド

グリッドは表示領域だけを描画するため、数十万セルでも滑らかにスクロールします。結果の全列が同じテーブルに由来し、主キーがあればその場で編集できます。

ツリーから開いたテーブル: 編集ツールバー、検索、並び替え、列の選択。
ツリーから開いたテーブル: 編集ツールバー、検索、並び替え、列の選択。

編集

セルをダブルクリックして編集し(クリックしておいたセルで F2 / Enter でも入れます)、挿入は Add row か Add with form、削除は行を選択して行います。Commit を押すまで何も実行されず、既定では生成された UPDATE・INSERT・DELETE 文を先に表示します。Discard は保留中の編集を破棄します。

選択とコピー

画面の文字はドラッグでは選択されないので、グリッドの上でマウスを動かしてもラベルが反転することはありません。行はクリックで選びます。1 行をクリックし、別の行を Shift+クリックするとその間がすべて選択され、⌘ / Ctrl+クリックはその行だけを選択に加えたり外したりします。セルのコンテキストメニューで選んだ操作は、選択したすべての行に適用されます。

セルメニューは選択範囲に作用します: リンク、値でフィルタ、コピー、編集、列の表示切り替え。
セルメニューは選択範囲に作用します: リンク、値でフィルタ、コピー、編集、列の表示切り替え。
  • フィルタ: 列 = この値 — その値で完全一致フィルタをかけてテーブルを読み直します。
  • コピー — セルの値、列名、または選択した行を TSV(ヘッダー付き)・CSV・JSON・そのまま実行できる INSERT 文として。
  • 編集 / NULL にする / 空文字にする / 行を削除 — いずれもコミットまで保留です。
  • スクラッチパッドへ送る — 次の節で説明します。
  • 列を隠す — ツールバーの列選択で戻せます。

前回の読み込みからの変化

テーブルタブを更新すると、主キーを手がかりに前回の読み込みと比較します。変わったセルは強調され(ホバーで以前の値が見えます)、新しい行は印が付き、消えた行の数はバッジで示されます。デプロイ直後やバッチ処理のあとに便利です。比較結果はそのタブの中だけにあり、× で消せます。

スクラッチパッド

スクラッチパッドはブラウザの中にある SQLite データベースです。どのグリッドからでも、セルのコンテキストメニューで行をコピーして入れられます — 1 行、選択した行、または読み込んだ全行。

サーバーのテーブルから送った行が、自由に問い合わせできるスクラッチパッドのテーブルになります。
サーバーのテーブルから送った行が、自由に問い合わせできるスクラッチパッドのテーブルになります。

列の型は元の型から決まり、作られたテーブルはすぐスクラッチパッドのスキーマツリーに現れます。普通のブラウザ SQLite 接続なので他のデータベースと同じように問い合わせ・編集ができ、Connection › Save Database File で .db ファイルとして書き出せます。ローカルにキャッシュされるのでリロードしても残ります。スクラッチパッドの内容がどこかに送られることはありません。

Tools › スクラッチパッド でいつでも開いたり切り替えたりできます。

接続をまたぐクエリ

スクラッチパッドのクエリタブでは、開いている任意の接続のテーブルを 3 つの部分からなる名前 "接続名".データベース.テーブル で参照し、他のものと結合できます。

SELECT o.id, o.total, u.email
FROM "Shop MySQL".shop.orders o
JOIN "User service".public.users u ON u.id = o.user_id
WHERE o.status = 'paid';

実行前に、参照したテーブルごとにローカルコピーが作られ、SQL はそのコピーを使う形に書き換えられます。結合処理はブラウザ内の SQLite が行います。そのため、サーバー側を準備しなくても MySQL のテーブルと PostgreSQL のテーブルを結合できます。

リモートのテーブルをスクラッチパッドに取り込み、ローカルで集計した結果。
リモートのテーブルをスクラッチパッドに取り込み、ローカルで集計した結果。

コピーは実行のたびに更新され、テーブルあたり 10 万行が上限で、進捗はフッターに表示されます。Tools › 統合クエリを開くと、構文と現在開いている接続名があらかじめ入ったタブが出ます。

比較とコピー

この3つのツールは、データベースを直接変更しません。確認・編集してから自分で実行できるスクリプトを生成します。

スキーマの比較

2 つのデータベースを並べて: 足りないもの、違うもの、余分なもの。
2 つのデータベースを並べて: 足りないもの、違うもの、余分なもの。

Database › スキーマを比較(またはツリーノードの「テーブルを比較…」)は、開いている 2 つの接続の間でテーブル・列・インデックス・ビュー・プロシージャ・関数・トリガー・イベントを比較します。CREATE 文は DEFINER、SQL SECURITY、ALGORITHM、データベース修飾といったノイズを取り除いて比較するので、本当の違いだけが現れます。スクリプトをエディタで開くを押すと、対象の方言の ALTER・CREATE 文が手に入ります。DROP はチェックを入れない限りすべてコメントアウトされています。

データの比較

比較元の主キーを手がかりにした行単位の比較。
比較元の主キーを手がかりにした行単位の比較。

Database › データを比較は比較元テーブルの主キーで行を対応付け、値を正規化したテキストとして比べるため、ドライバごとに異なる日付・小数・JSON の表現による偽の差分が出ません。比較先にない行、値が違う行(列ごと)、比較先だけにある行を示し、INSERT・UPDATE・DELETE のスクリプトも作ります(DELETE は既定でコメントアウト)。片側あたり最大 5 万行を、進捗を表示しながら読み込みます。

テーブルのコピー

別の接続にテーブルを作り直す — 構造だけ、または行も一緒に。
別の接続にテーブルを作り直す — 構造だけ、または行も一緒に。

テーブルを右クリックして Copy Table to… を選ぶと、開いている別の接続やデータベースにそのテーブルを作り直します。CREATE TABLE はコピー先の方言で生成され編集可能な状態で表示されるので、型を少し直せば MySQL のテーブルを PostgreSQL にコピーできます。行はバッチで転送され、進捗バーが表示されます。同名のテーブルが既にある場合、コピーは中止されます。「削除して作り直す」を選ぶと、先にテーブル名の再入力が必要です。

AI アシスタント

右のパネルは、コピーするための SQL を書いて終わりではありません。アプリそのものを操作します。スキーマを読み、クエリタブを開き、そこで実行し、データを変える前には承認を求めます。右端のアイコンか、ツール › AI アシスタントから開きます。

質問が答えになるまで

パネルがスキーマを読み、タブを開いてクエリを実行したところ。答えの上のカードが呼び出したツールです。
パネルがスキーマを読み、タブを開いてクエリを実行したところ。答えの上のカードが呼び出したツールです。

普段の言葉で尋ねれば十分です。モデルは画面を見られないので、まず何が開いているかをアプリに尋ね、使うテーブルのカラムを読みます。呼び出したツールがカードとして残るため、何を根拠にクエリを組み立てたかがそのまま見えます。出来上がった文はクエリタブに開いてそこで実行されるので、進行が見え、途中で止められ、結果も他のクエリと同じように並べ替えたり書き出したりできます。

モデルが書いた文は、実行の前にエンジンが計画を立ててみます。存在しないカラムを参照していればそのエラーがモデルに返って自分で直すので、壊れたクエリが画面に届きません。大きなテーブルを丸ごと走査する計画なら、実行前に確認します。

やらないこと

書き込みはここで止まります。カードが文を示し、プレビューが書き込む前に行数を数えます。
書き込みはここで止まります。カードが文を示し、プレビューが書き込む前に行数を数えます。
ai-dry-run
  • 接続は一つだけ — いま開いているものです。別の接続を指定する引数も、接続を開閉するツールもありません。使うデータベースは、利用者がそれを使うことで決まります。
  • DROP と TRUNCATE は実行されません — 承認しても、言い換えても、セミコロンの後ろに隠しても同じです。タブに書き出して何が失われるか伝えることはできますが、実行は利用者の役目です。
  • 書き込みは先に尋ねます — そのうえで、自分で入力した文と同じ確認を通ります。何行変わるかを見せるドライラン、破壊的な文の確認、読み取り専用接続での拒否がそのまま働きます。

モデルはどこから来るのか

設定 › AI。このうち二つはキーが要りません。
設定 › AI。このうち二つはキーが要りません。

設定 › AI で決めます。キーはローカルエージェントに渡されてそこで使われます。ブラウザには保存されず planche.dev にも送られません。SQL やスキーマも同じです。

  • API キー — Anthropic、OpenAI 互換エンドポイント、Gemini から選べます。保存するかは選択で、保存する場合は書き込む先のファイルを先に示します。
  • このマシンのログイン — ant auth login 済みなら SDK が資格情報を自分で見つけるので、貼り付けるものはありません。
  • ローカル CLI — すでに導入しサインイン済みの Claude Code や Codex を使います。キーは一切要りません。

別のエージェントから Planche を操作する

ヘルプ › AI エージェントを接続。トークンの届く範囲と、貼り付ける一行。
ヘルプ › AI エージェントを接続。トークンの届く範囲と、貼り付ける一行。

ヘルプ › AI エージェントを接続 から設定を受け取れます。HTTP 経由の MCP に対応していれば何でもよく、エディタのエージェントが同じツールを使えます。呼び出しはブラウザタブで同じ確認を経て実行され、書き込みはそこで承認を求め、外部からの要求として表示されます。渡されるトークンはその一つのエンドポイントに使われ再起動後も残り、失効させると渡したプログラムがすべて切れます。

安全

本番データベースで WHERE なしの DELETE を実行すると、多くの行を意図せず削除するおそれがあります。Planche は実行前に複数の確認を行います。必要に応じて、各保護機能は設定から無効にできます。

ドライラン: 変更する前に対象の行を見る

UPDATE を SELECT としてプレビュー: 何行が、どの行が変わるのか。
UPDATE を SELECT としてプレビュー: 何行が、どの行が変わるのか。

エディタから UPDATE や DELETE を実行する前に、Planche はその文が触れる行を読む SELECT に書き換えて実行し、件数とサンプルを見せます。結合の形もすべての方言で扱えます — MySQL の UPDATE a JOIN b、PostgreSQL の UPDATE … FROM と DELETE … USING、SQL Server の UPDATE 別名 … FROM、Oracle の相関サブクエリ。パーサが安全に書き換えられない文は、誤ったプレビューを見せる代わりにプレビューなしで実行します。

そのほかの網

  • 破壊的な文の確認 — DROP、TRUNCATE、WHERE のない DELETE・UPDATE は、実行される文をそのまま示して先に確認します。ツリーからテーブルやデータベースを削除するときは名前の再入力も必要です。
  • 読み取り専用の接続 — 書き込みはデータベースに届く前に拒否されます。
  • グリッドのコミットプレビュー — 編集が書き込まれる前に生成された文を表示します。
  • 手動トランザクション — 自分でコミットするまで確定しません。
  • 環境カラー — 本番がステージングと違って見えます。
設定 › 安全 — 邪魔なガードレールはオフにできます。
設定 › 安全 — 邪魔なガードレールはオフにできます。

ERD

Tools › ERD を表示は、選んだデータベースの外部キーから ER 図を描きます。鳥の足記法、ドラッグできるエンティティ、幅を変えられる列に対応しています。レイアウトはデータベースごとに保存されるので、整えた配置は明日もそのままです。

サンプルデータベース: 23 個のテーブルと外部キー。
サンプルデータベース: 23 個のテーブルと外部キー。

自分で定義した列リンクは破線の関係として現れます。リンクが図の外のテーブル(別のデータベースや別の接続)を指す場合は、元のテーブルの隣にゴーストのエンティティを置いて関係が見えるようにします。

テーブル設計

Create Table と Alter Table は、列・インデックス・(対応するエンジンでは)ストレージ属性の 3 つのタブを持つデザイナを開きます。

型、長さ、既定値、NULL 可否、主キーを扱う列の編集。
型、長さ、既定値、NULL 可否、主キーを扱う列の編集。

SQL タブは Planche が実行する文を、自分のエンジンの方言で、入力に合わせて更新しながら表示します。方言を学ぶにも、これから何をするのか確かめるにも便利です。

フォームと常に同期している生成 DDL。
フォームと常に同期している生成 DDL。

残りは Table と Database のメニューにあります。名前の変更、構造の複製、データベースの作成と削除、そしてエンジンが対応していればユーザー管理・プロセスリスト・サーバー変数・ステータスも。

エクスポート

テーブルのエクスポート: 区切り文字、ヘッダー、そしてストリーミング中の進捗バー。
テーブルのエクスポート: 区切り文字、ヘッダー、そしてストリーミング中の進捗バー。
  • CSV でダウンロード — 現在の結果、またはテーブル全体。テーブルは主キー順にページ単位で読み込み、ブラウザが File System Access API に対応していれば選んだファイルへ直接書き込むので、大きなテーブルでもメモリに収める必要がありません。進捗が表示され、途中で止められます。
  • スキーマを HTML に — チェックしたテーブルの列とインデックスをまとめた単一ページ。
  • 列リンクのエクスポート/インポート — 仮想の外部キーを JSON ファイルに。別のマシンや同僚へ渡すときに。
  • INSERT としてコピー — グリッドから数行だけ手で移すときに。
  • データベースファイルを保存 — ブラウザ SQLite のデータベース(スクラッチパッドを含む)をディスクに書き戻します。

=、+、-、@ で始まる CSV の値にはアポストロフィを付けて、表計算ソフトが数式ではなくテキストとして扱うようにしています。

ゲートウェイモード(チーム)

エージェント 1 つでチーム全体をまかなえます。ゲートウェイモードでは、データベースの認証情報は共有ホスト上の設定ファイルに置かれ、ブラウザはプロファイルを名前で選ぶだけです。

Terminal

npx planche --gateway gateway.json --addr 0.0.0.0 --allow-remote \
  --token "$(openssl rand -base64 24)" --public-url https://sql.example.com

gateway.json

{
  "name": "Acme staging",
  "profiles": [
    {
      "name": "Shop (read-only)",
      "driver": "mysql",
      "host": "db.internal",
      "port": 3306,
      "user": "reporting",
      "password": "…",
      "database": "shop"
    },
    {
      "name": "Shop (writable)",
      "readOnly": false,
      "driver": "postgres",
      "host": "pg.internal",
      "port": 5432,
      "user": "app",
      "password": "…",
      "database": "shop"
    }
  ]
}
  • name — ゲートウェイの名前で、接続画面に表示されます。
  • profiles[].name — ブラウザに表示される名前です。クライアントがサーバーへ送るのはこの名前だけです。
  • profiles[].readOnly — 省略すると読み取り専用になります。書き込みを許可するには false を指定します。
  • 残りは接続フォームで入力する項目と同じ名前です。driver(mysql、postgres、mssql、oracle、sqlite、d1)、host、port、user、password、database に加えて、Oracle は serviceName、SQLite は file、Cloudflare D1 は accountId・databaseId・apiToken を使います。ssh ブロックもそのまま書けます。

踏み台を経由するプロファイルには ssh ブロックを入れます。その場合、上の host・port は踏み台から見たアドレスとして解決されるため、たいてい 127.0.0.1 になります。

gateway.json(profiles の 1 項目)

{
  "name": "Shop via bastion (read-only)",
  "driver": "mysql",
  "host": "127.0.0.1",
  "port": 3306,
  "user": "reporting",
  "password": "…",
  "database": "shop",
  "ssh": {
    "host": "bastion.example.com",
    "port": 22,
    "user": "deploy",
    "auth": "key"
  }
}
  • auth は key、agent、password のいずれかです。key にして privateKey を書かない場合、ゲートウェイ側の ~/.ssh/config でそのホストに指定された IdentityFile を使い、なければ ~/.ssh/id_* を探します。鍵が設定ファイルに残らないので、サーバーではこの形が一般的です。agent はゲートウェイの SSH_AUTH_SOCK を、password は password 項目を使います。
  • privateKey を書く場合、その値はパスではなく鍵ファイルの内容(PEM / OpenSSH)です。鍵にパスフレーズがあれば passphrase も添えます。
  • 踏み台のホストキーは、ゲートウェイのマシンで先に信頼されている必要があります。 そのマシンで一度 ssh bastion.example.com して登録するか、プロファイルの acceptHostKey に SHA256:… のフィンガープリントを書いて固定してください。ゲートウェイモードでブラウザが送るのはプロファイル名だけなので、「未知のホストキー」の確認には答えられません。
  • プロファイルは既定で読み取り専用で、それをエージェント自身が強制します。1 リクエストにつき SELECT 形の文を 1 つだけ受け付け、エンジンが対応していればセッション自体も読み取り専用にします。ブラウザ側のガードレールは利便性のためのものですが、こちらはクライアントから回避できません。
  • プロファイル名ではなく認証情報を送るリクエストは拒否されます。
  • エージェントが Web アプリ自体を配信するため、ページは自分のオリジンとだけ通信し、厳格なコンテンツセキュリティポリシーがそのまま保たれます。
  • 平文 HTTP で動くので、前段に TLS のリバースプロキシを置き、--public-url で公開 URL を渡してください。

チームメンバーはその URL を開き、接続ダイアログの Configure 欄にトークンを一度貼り付けるだけです。すると開始画面と接続マネージャにプロファイルが現れます。

接続の同期(エンドツーエンド暗号化)

接続の同期を使うと、接続プロファイルを planche.dev に預けて別のコンピューターからも使えます。データはアップロードする前にブラウザの中で暗号化され、その鍵がサーバーに渡ることはありません。メニューの 接続 › 接続の同期 から開きます。1.0 からは Pro 機能になる予定ですが、0.x のリリースではすべて無料です。

有効にする

  1. GitHub でサインインします。サインインは、どの保管庫があなたのものかをサーバーが知るためだけに使います。
  2. 10 文字以上のパスフレーズを決め、確認のためにもう一度入力します。GitHub のログインとあえて分けているのは、ログイン情報はサーバーから見えるため、それをデータの鍵にはできないからです。
  3. プロファイルが暗号化され、アップロードされます。別のコンピューターでは同じアカウントでサインインし、同じパスフレーズを入力すれば読み込めます。

暗号化の仕組み

  • ブラウザはパスフレーズから PBKDF2-SHA256(600,000 回の反復、ランダムな 16 バイトのソルト)で 256 ビットの AES-GCM 鍵を作ります。保存のたびに新しい 12 バイトのノンスを使います。
  • 鍵は取り出せない(non-extractable)鍵として作られ、タブのメモリの中にしかありません。鍵もパスフレーズもディスクに書かれず、どこにも送られないので、新しいセッションを始めるたびにパスフレーズを聞かれます。
  • サーバーはアカウントごとに暗号化された保管庫を 1 つ持ちます。その横に暗号化せずに置いているのは、鍵を作り直すための値(ソルトと反復回数)、ノンス、バージョン番号、最後に保存した時刻だけです。どれも中身については何も明かしません。
  • アカウントについてサーバーが保存するのは、GitHub の ID とメールアドレス(メールアドレスを非公開にしている場合は GitHub のユーザー名)、そしてサインインしている間のセッションです。

保管庫に入るもの

  • 接続プロファイル:ホスト、ポート、ユーザー、各種オプション、そのプロファイルに設定した列リンク。
  • パスワード、SSH のパスワードと秘密鍵。ただし パスワードを保存 をオンにしたプロファイルの分だけです。このコンピューターに残さないと決めた秘密情報は、サーバーにも残りません。
  • サンプルデータベースとスクラッチパッドは入りません。どちらも必要になったコンピューターでその都度作られます。
  • クエリ履歴、クエリの結果、データベースの中のデータが入ることはありません。

2 台のコンピューターで使う

プロファイルにはそれぞれ最終更新時刻が記録されていて、2 つの保管庫をマージするときは新しいほうが残ります。削除したことは 90 日間記録されるので、片方のコンピューターで消したプロファイルがもう片方から復活することはありません。2 台が同時に保存した場合、サーバーは後から来た保存を拒否します。拒否されたコンピューターは上書きせず、新しいほうの保管庫をマージしてから保存し直します。

パスフレーズを忘れたら

サーバーにある保管庫は、私たちを含めて誰にも復号できないため、復元する方法はありません。プロファイルがまだ残っているコンピューターで サーバーから削除 を選び、新しいパスフレーズで同期を有効にし直してください。アカウントを削除 を選ぶと、保管庫とサインイン情報が消えます。どちらを選んでも、各コンピューターにあるプロファイルには一切手を付けません。

同期が動くのは planche.dev だけです。ローカルのエージェントが配信するアプリはインターネットに接続しないため、そこでは同期を使えません。

プライバシーとセキュリティ

  • データが私たちに届くことはありません。 planche.dev は静的なページを配信するだけで、クエリと結果はブラウザと自分のエージェントの間だけを行き来します(ブラウザ SQLite ならページの中に留まります)。
  • 認証情報は手元に残ります。 プロファイルはブラウザのストレージにあり、パスワードや SSH の秘密情報は保存を選ばない限りセッションの間だけ保持されます。アプリはループバックにないエージェント(そのページを配信したエージェント以外)との通信を拒否します。リモートのエージェントは、認証情報をネットワークに送ることを意味するからです。
  • エージェントはすべてのリクエストを認証します。 ヘルスチェック以外のすべての経路にトークンが必要で、間違ったトークンが続くと認証が一時的にロックされ、許可されたオリジンだけが呼び出せ、ループバック以外へのバインドには明示的な指定とトークンが要ります。
  • SQLite ファイルへのアクセスは制限されます。 エージェントはホームディレクトリ(隠しフォルダやシステムフォルダを除く)か指定したディレクトリの下のファイルだけを開き、有効にしない限り ATTACH を拒否します。
  • クエリ履歴はマスクされます。 履歴やスナップショットを保存する前にパスワードのリテラルを伏せ字にし、保存そのものをオフにもできます。
  • 統計は匿名で任意です。 どのエンジンか、どのダイアログか、文が成功したかといったカテゴリ的な事実だけを数え、SQL のテキストやホスト名、データベース・テーブル・ファイル名は決して集めません。設定のスイッチ 1 つでオフにできます。

Planche は現状のまま提供されます。ここで説明した安全策は利便性のためのもので、保証ではありません。実行するすべての文の責任は利用者にありますので、バックアップを取っておいてください。

キーボードショートカット

エディタのショートカットは SQL エディタにフォーカスがあるときに、それ以外はどこでも動作します。

キー動作
F9実行 — 設定 › 安全 › 実行範囲に従って、スクリプト全体またはカーソル位置の文を実行します。
Ctrl / ⌘ + Enter選択範囲、またはカーソル位置の文を 1 つ実行します。
Ctrl / ⌘ + Shift + Enter実行範囲の設定にかかわらず、スクリプト全体を実行します。
Ctrl / ⌘ + Kクイックコマンドパレット: テーブル、メニュー操作、接続を入力して呼び出します。
Alt + N接続マネージャを開きます。
Alt + T現在の接続に新しいクエリタブを開きます。
Shift / ⌘ / Ctrl + click結果グリッドで選択範囲を広げる(Shift)/切り替える(⌘ / Ctrl)。
F2 / Enter結果グリッドで、クリックしておいたセルを編集(ダブルクリックと同じ)。
Ctrl / ⌘ + Fエディタ内の検索と置換。