ClaudeにPixeltableスキルを入れてマルチモーダルAIアプリを作る
Pixeltableのスキル(プラグイン)をClaude Codeに入れ、app.pyにテーブルと計算列を宣言させる手順。導入3経路、禁止事項、UDFの落とし穴、検証ループの組み方を扱います。
Pixeltableのスキルは、Claude Codeに「テーブルと計算列でバックエンドを組む」流儀を教える配布物です。LangChainやpandasや別立てのベクトルDBに手が伸びるのを止め、app.py 1本にスキーマとAPIを宣言させます。
ここでは、導入の3経路、スキルの中身、Claudeに守らせる検証ループ、つまずきやすい箇所を順に扱います。
PixeltableスキルがClaudeに教えること
Pixeltableは、画像・動画・音声・ドキュメントを扱うAIアプリのために、テーブル・計算列・埋め込み検索・サービング(HTTP公開)を1つの仕組みにまとめたものです。スキルのリポジトリは、これを組む手順をClaudeに渡す役目を持ちます。
README冒頭の説明では、対象はテーブルと計算列、埋め込みインデックスとベクトル検索、RAG、ツール呼び出しエージェント、25社以上のAIプロバイダーにまたがる動画・音声・画像・ドキュメントのパイプラインです。Claudeは app.py に TableModel クラスでスキーマを宣言し、pxt schema update でテーブルを作り、pxt service update でHTTPルートを立てます。
構成はシンプルです。
skills/pixeltable-skill/
├── SKILL.md # 契約: app.py、schema update、service update
└── references/
├── core-api.md # テーブル、クエリ、ビュー、UDF、設定
├── cli.md # pxt CLI
├── providers.md # import の仕方と出力の形
├── workflows.md # FastAPIRouter
└── anti-patterns.md # 誤った構成と正しい構成SKILL.md は入口で、詳細は references/ に分かれています。Claudeは必要な参照ファイルだけ開く作りです。スキル全体の仕組みはClaude Code Skills完全ガイドにあります。
SKILL.md のfrontmatterには、起動のきっかけも書かれています。pathPatterns に **/*.py、importPatterns に import pixeltable as pxt、bashPatterns に pxt で始まるコマンド、promptSignals.phrases に computed column や TableModel などです。Pythonファイルを触ったり pxt を打ったりすると、スキルが関連づけられる設計になっています。description の末尾には「一般的なPythonやPostgreSQLの直接管理には使わない」とも明記されています。
導入は3経路 — どれを選ぶか
導入手段は複数あり、前提が少しずつ違います。
| 経路 | コマンド | 入るもの |
|---|---|---|
| スキルのみ(npx) | コマンドnpx skills add pixeltable/pixeltable-skill | 入るものSKILL.md と参照ファイル |
| スキルのみ(pxt) | コマンドpxt skills install | 入るもの.claude/skills/pixeltable と .agents/skills/pixeltable |
| プラグイン一式 | コマンド/plugin marketplace add pixeltable/pixeltable-skill | 入るものスキル、コマンド、エージェント、フック |
pxt skills install はPixeltable 0.7.17以降が必要で、Pythonだけで完結します。更新は pxt skills install -f です。READMEによると、Google Antigravityだけは npx skills の書き込み先と読み込み先が違うため、./install.sh --platform antigravity で入れます。
Claude Codeでプラグイン一式を入れる場合は、リポジトリ自体がマーケットプレイスとして使えます。
/plugin marketplace add pixeltable/pixeltable-skill
/plugin install pixeltable@pixeltable-skillインストール後は、再起動するか新しい会話を始めます。セッション中に反映したいときは /reload-plugins が使えます。/plugin marketplace add がGitHubの owner/repo を受け取る点は、Claude Code側のドキュメントに書かれた仕様どおりです。マーケットプレイスの扱い全般はプラグイン完全ガイドにまとめています。
Claudeのマーケットプレイスページにも「Pixeltable」の掲載があり、Claude Codeボタンから入れられます。READMEには「リポジトリのマーケットプレイスはチーム配布用で、公開ディレクトリには載せない」とあるので、ページ上の掲載とは別物として読むのが安全です。
プラグイン一式で増える2つのエージェントと2つのコマンド
マーケットプレイスのページによると、プラグインにはスペシャリスト2体とスラッシュコマンド2つが入ります。
プラグイン一式の追加要素
Pipeline Architect(エージェント)
テーブル、ビュー、計算列、インデックス、UDFを割り当て、マルチモーダルMLパイプラインのスキーマを設計します。
Debugger(エージェント)
CLIでの確認とSDKの検証で、失敗した・古いままのパイプラインの原因を絞ります。
/scaffold
ナレッジベース、チャットエージェント、音声文字起こし、動画検索などのテンプレートから、新規プロジェクトを生成します。
/add-provider
対応プロバイダーを、テーブルの計算列として組み込む手順を案内します。
スキルだけで始めても、アプリの骨格は組めます。設計とデバッグを別の役割に切り分けたいときにプラグイン一式が向きます。
前提環境と実行方式
ここは見落としやすい箇所です。SKILL.md の開始手順は次のとおりです。
pip install 'pixeltable[serve]' # Python 3.11+
pxt init
pxt service example --out app.py
pxt schema check app.py
pxt schema update app.py my_app
pxt service update app.py my_app -f
pxt service listPython 3.11以上が必要です。-f を付けるのは、TTYの無い環境(Claudeが叩くシェルがこれに当たります)で、-f が無いと保留中の起動が終了コード3で止まるためです。ポートは pxt service list で調べ、:8000 を決め打ちしないよう書かれています。
my_app はディスク上のフォルダではなく、カタログ内のディレクトリ名です。python app.py で起動する作りでもありません。ここを取り違えると、Claudeが普通のFastAPIアプリのつもりで実行して空振りします。
APIキーはもう1点の落とし穴です。OPENAI_API_KEY などは環境変数か ~/.pixeltable/config.toml から読まれ、デーモンが起動時に1回だけ読みます。キーを変えたら pxt daemon restart が必要で、それまで各コマンドは409を返します。そのあと pxt service restart my_app/ingest で再起動します。
app.pyの契約 — 注釈は保存列、代入は計算列
スキルの核心は、app.py の書き方を1通りに固定している点です。SKILL.md が示す最小形は次のとおりです。
import pixeltable as pxt
import pixeltable.functions as pxtf
from pixeltable.serving import FastAPIRouter
TableModel = pxt.model_base()
@pxt.udf
def excerpt(text: str, n: int = 12) -> str:
return text if len(text) <= n else f'{text[:n]}...'
class Docs(TableModel, name='docs'):
id = pxt.Column(value=pxtf.uuid.uuid7(), primary_key=True)
title: pxt.String
body: pxt.String | None
title_upper = pxtf.string.upper(title)
summary = excerpt(title)
ingest = FastAPIRouter(name='ingest')
ingest.add_insert_route(
Docs, path='/docs', inputs=[Docs.title, Docs.body],
outputs=[Docs.id, Docs.title_upper, Docs.summary],
)読み方のルールは3つです。
- 型注釈だけの属性は、保存される列
- 代入した属性は、計算列。行を挿入すると自動で計算される
- 省略可能な列は
T | Noneと書き、pxt.Requiredは使わない
title_upper と summary は、行を入れた時点で自動的に埋まります。「保存」と「計算」を宣言の形だけで見分けられるため、Claudeが後から列を足す場面でも迷いにくくなります。
UDF(ユーザー定義関数)は型ヒントが必須で、app.excerpt のようにプロジェクトルートからのモジュールパスとして記録されます。UDFを書く前に、pixeltable.functions に同じ処理が同梱されていないかを確かめるよう、core-api.md が指示しています。
テーブルを作る関数をimport時に呼ばせない
anti-patterns.md の表には、app.py で pxt.create_table() や get_table() をimport時に呼ぶ書き方が誤りとして載っています。正しい形は TableModel と pxt schema update で、importがカタログを書き換えてはいけない、という理由です。ノートブックでは逆に create_table と add_computed_column が使えます。アプリとノートブックで流儀が違うので、どちらの文脈かをClaudeに最初に伝えるとぶれません。
Claudeに守らせる5つの禁止事項
SKILL.md の冒頭には「STOP」の節があります。次のものをimportしかけたら脱線の合図、という作りです。
よくある書き方と、スキルが求める書き方
Claudeが選びがちな構成
LangChainでチャンク分割し、ChromaやPineconeにベクトルを置き、for row in df.iterrows(): でモデルを呼び、while True: でエージェントを回す。
スキルが求める構成
分割は document_splitter、検索は .similarity()、モデル呼び出しは計算列、ツールは pxt.tools() と invoke_tools()。エージェントは行を挿入すれば計算列の連鎖が動く。
5項目は、LangChain系フレームワークを使わない、pandasを作業用ストアにしない、モデルを呼ぶforループを書かない、別のベクトルDBを入れない、whileループのエージェントを書かない、です。anti-patterns.md は6つ目として、UDF本体の中でモデルをロードする誤りを加えています。
実装の形で見ると、RAGの分割と検索は次のように1つのモデル宣言に収まります。workflows.md の例を縮めた形です。
class Chunks(
TableModel,
name='chunks',
base=Docs,
iterator=pxtf.document.document_splitter(
Docs.document, separators='token_limit', limit=512
),
):
__indexes__ = [
pxt.EmbeddingIndex(
text,
embedding=embed_fn,
name='chunks_embed',
)
]検索はクエリ側で Chunks.text.similarity(string=query_text) と書きます。similarity(query) と位置引数で渡す書き方は誤りで、string= を付けます。画像で検索するなら image=、音声なら audio= です。
別のベクトルDBが要らないのは、インデックスがテーブルの宣言に含まれるからです。token_limit で分割するには tiktoken が、separators='sentence' にはspaCyが、sentence_transformer のインデックスにはtorchが追加で要る点も workflows.md に書かれています。スキルが「ユーザーが求めない限りHugging FaceやspaCyを足さない」と指示しているのは、この依存の連鎖を避けるためです。
検証ループをClaudeに回させる
スキルは「動くことの確認」まで手順に含めています。挿入すれば計算が走るので、Claudeに任せる検証は次の流れで組めます。
Claudeが回す検証ループ
- 1
スキーマを検査する
pxt schema check app.pyでファイルを検証します。appという名前が隠されていれば警告が出ます。 - 2
スキーマを適用する
pxt schema update app.py my_appでテーブルを作ります。この時点ではHTTPは立ちません。 - 3
サービスを起動する
pxt service update app.py my_app -fでHTTPを立て、pxt service listで実際のエンドポイントを取ります。 - 4
curlで行を挿入して結果を読む
curl -X POSTでルートを叩き、計算列の出力が返ることを見ます。失敗はpxt errors my_app/docsやpxt service logsで読みます。
workflows.md には、エンドポイントの取り出しとアップロードの例があります。
URL=$(pxt service list my_app --json | jq -r '.[] | select(.name == "ingest") | .endpoint')
curl -X POST "$URL/api/upload" -F document=@paper.pdf -F timestamp=2026-09-28T08:00:00
curl -X POST "$URL/api/search" -H 'content-type: application/json' \
-d '{"query_text": "results"}'テストコマンドの出力を読んで完了を判定させる考え方は、FastAPIバックエンドの実装フローと同じ型です。Pixeltableの場合、判定の根拠が「テストの緑」でなく「計算列が埋まったか」と「サービスが返すJSON」になります。
CLAUDE.mdとpermissionsに置く断片
スキルに頼るだけでなく、プロジェクト側にも2か所書いておくと、ぶれが減ります。以下は筆者の例で、スキルの配布物には含まれません。
CLAUDE.mdには、実行方式の取り違えを防ぐ数行を置きます。
## Pixeltable
- app.py は python で実行しない。pxt schema update、pxt service update の順で反映する
- サービス起動は pxt service update app.py my_app -f(TTYなしでは -f 必須)
- ポートは pxt service list で取得し、決め打ちしない
- APIキーを変えたら pxt daemon restart を先に実行する.claude/settings.json には、読み取り系だけを許可しておけます。
{
"permissions": {
"allow": [
"Bash(pxt schema check *)",
"Bash(pxt service list *)",
"Bash(pxt ls *)",
"Bash(pxt errors *)"
]
}
}schema update と service update はカタログやサービスを書き換えるので、許可リストに入れず、都度承認にしておく運用が考えられます。Cloudに向けた pxt schema update ... pxt://org:db は特に、ローカルとは影響範囲が違います。
UDFと計算列で踏みやすい落とし穴
core-api.md と anti-patterns.md が繰り返し警告している点を、症状から引けるようにまとめます。
| 症状 | 原因 | 対処 |
|---|---|---|
セルが None なのにエラーメッセージも空 | 原因null許容の列を、非nullのパラメーターを持つUDFに渡した。呼び出し自体がスキップされる | 対処引数を x: str | None にして本体で None を処理する |
| 行ごとに処理が極端に遅い | 原因UDF本体で whisper.load_model(...) を呼び、行ごとに重みを再ロードしている | 対処同梱ラッパー(pxtf.whisper.transcribe など)か、モジュールスコープでキャッシュしたローダーを使う |
| 無音の動画で文字起こしが空 | 原因extract_audio が Audio | None を返し、文字起こしは非nullの audio を要求する | 対処スキップ規則に従い、None を許す設計にする |
| スキーマ変更後にルートが409を返す | 原因スキーマ変更後はサービスが古いまま | 対処pxt service update ... -f をもう一度実行する |
| 列の型を後から変更できない | 原因型の変更は UNSUPPORTED で、更新全体が適用されない | 対処計算列はリネームして作り直す。保存列は最初から T | None で宣言する |
anti-patterns.md は、重みをUDF本体で読み込むと100msの処理が1.8秒になる、という具体的な数字も挙げています。同梱ラッパーはモデルをプロセス単位でキャッシュするためです。
落とし穴
Nullの列を渡すと、エラーも出さずに計算が飛ぶ
非nullのパラメーターに None を渡すと、呼び出しがスキップされ、セルは None のままになります。errormsg も空なので、失敗として表に出ません。UDFを書くときは、入力列がnull許容かどうかを先に見ます。Claudeにも「null許容の列を受けるUDFは T | None で受ける」と指示しておくと、この症状を最初から避けられます。
Cloud MCPとの関係
READMEによると、このプラグインはMCPサーバーを設定しません。Pixeltable Cloudの利用者は、ホスト型のCloud MCPを別途追加できます。サインイン時に選んだ組織のデータベース、サービス、スキーマ、ログを読め、1回の呼び出しで最大25行のテーブル行も読めます。
停止や再起動、シークレットの設定は、まずプレビューが返り、confirm: true を付けて再呼び出しして初めて実行されます。削除とデプロイは行わず、それらは pxt CLIの役割です。URLに ?read_only=true を足すと読み取りツールだけになります。MCPをClaude Codeにつなぐ作法はSkillsとMCPの違いで整理しています。
導入前に知っておく条件
- 動作確認の記録はPixeltable 0.7.11向けです。
pxt skills installは0.7.17以降を要求します。手元のバージョンと、スキル側の想定がずれていないか、pip show pixeltableで見てから入れます - ライセンスはApache 2.0です
allowed-toolsは空で、executes-code: falseと宣言されています。スキル自体は文書であり、コードを実行するのはClaudeが叩くpxtコマンドです- ブラウザ操作を伴う検証を足したいときは、別のスキルを組み合わせます。例はwebapp-testingスキルです
スキルの置き場所を自分のリポジトリに固定したい場合は、pxt skills install が書き込む .claude/skills/pixeltable をコミットする手があります。プロジェクトのスキルはリポジトリ内に置けば、チームの全員に届きます。
まとめ
PixeltableスキルがClaudeに渡しているのは、APIの知識よりも「やらないことのリスト」です。LangChain、pandas、別立てのベクトルDB、forループ、whileループを避け、app.py の宣言と3つのコマンドだけで動かす。その型を先に与えると、Claudeが自前の配線を書き始める回数が減ります。
最初の一歩は、pxt service example で雛形を作り、pxt schema update と pxt service update -f を通して、curlで返るJSONを読むところまでです。そこが通れば、動画や音声の列を足していく作業はスキルの参照ファイルに沿って進められます。