marimo-pair について
marimo-pairは、カーネルとcode-mode APIを使ってライブのmarimoノートブックを操作するスキルです。リアクティブなデータフローに沿った状態確認と永続的な編集を案内し、稼働中のノートブックファイルを直接変更しないよう促します。
主な機能
- 01ライブカーネルとセル状態の確認
- 02code modeによるセルの作成と編集
- 03セルとリアクティブな依存先の実行
- 04ノートブックのパッケージとウィジェット管理
- 05ノートブックセッションの検出と選択
活用シーン
- 01実行中のノートブック変数の確認
- 02永続化するセルの追加や修正
- 03code modeを使ったウィジェット値の変更
MCP 対応
同梱スクリプトに加え、marimo MCPでのコード実行とノートブックセッション検出について説明しています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ marimo-team/ marimo-pair --skill marimo-pairインストール後、Claude Code で/marimo-pairを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
reference/execution-context.mdfinding-marimo.mdgotchas.mdnotebook-improvements.mdrich-representations.mdscripts/discover-servers.shexecute-code.sh詳細
marimo は、再現可能な Python プログラム(marimo ノートブック)を構築するためのリアクティブな Python ランタイムです。セルは、定義する変数と参照する変数によってつながっています。セルを実行すると、データフローの順序に従って依存するセルが再実行されます。アクティブなランタイムは、カーネルの名前空間、セルの状態、データフローグラフを保持します。ノートブック(.py ファイル)は、セッションの実行中にカーネルがその状態から書き出す成果物です。
ユーザーは、セル、出力、ウィジェットを備えたノートブック UI を通じて、同じランタイムを操作します。
警告。アクティブなランタイムが唯一の信頼できる情報源です。 セッション中は、関連付けられた .py ファイルを直接変更してはいけません。ファイルを編集してもアクティブなカーネルやユーザーには反映されず、保存時にカーネルが変更内容を上書きする可能性があります。ノートブックを変更するには marimo._code_mode(cm)を使用してください。ディスクからの読み取りは問題ありませんが、現在のセルのコードには ctx.cells[...].code を使用することを推奨します。
ハーネスは、この SKILL.md の絶対パスを報告します。現在の作業ディレクトリがノートブックのワークスペースであっても、バンドルされた scripts/... および reference/... のパスは、その親ディレクトリを基準に解決してください。コマンドの例では、/absolute/path/to/marimo-pair をそのディレクトリに置き換えてください。
必須の最初のカーネルコマンド
すべてのコードモードセッションは、次の専用コマンドで開始してください。
bash /absolute/path/to/marimo-pair/scripts/execute-code.sh \
--url http://localhost:2718 \
-c "import marimo._code_mode as cm; help(cm)"
各カーネルでは、読み取り専用のタスクを含め、次の順序で操作してください。
- 検査コマンドを一度実行します。
help(cm)の出力が正常に返るまで待ちます。- その後の呼び出しで、
cm.get_context()または別のcmAPI を使用します。
検査コマンドが正常に完了する前に、タスク固有の cm コードを実行しないでください。
ノートブックへの接続
バンドルされた execute-code.sh を報告されたスキルディレクトリから実行するか、MCP(execute_code(...))を使って、実行中の marimo カーネルで Python コードを実行します。
execute-code.sh では --url が常に必要です。ユーザーがノートブックの URL を指定した場合は、その URL に対して直接、必須の検査を実行してください。
bash /absolute/path/to/marimo-pair/scripts/execute-code.sh \
--url http://localhost:2718 \
-c "import marimo._code_mode as cm; help(cm)"
このコマンドが正常に完了した後、-c CODE、標準入力を指定する -、またはファイルパスを使ってタスクコードを渡します。
bash /absolute/path/to/marimo-pair/scripts/execute-code.sh \
--url http://localhost:2718 - <<'PY'
import marimo._code_mode as cm
async with cm.get_context() as ctx:
cid = ctx.create_cell("x = df.head()")
ctx.run_cell(cid)
PY
ユーザーが URL を指定しなかった場合は、ノートブックを探すか起動してください。bash /absolute/path/to/marimo-pair/scripts/discover-servers.sh、MCP の list_sessions()、またはローカルプロセスのコンテキストを使って実行中のサーバーを探し、報告された url を --url に渡します。開いているノートブックが 1 つならスクリプトが自動的にそれを対象にします。複数ある場合は、ノートブックのファイルキーを --file で指定してください。
サーバーが実行されておらず、ユーザーがノートブックを求めている場合は、--no-token を指定し(--headless は指定せずに)marimo を起動してください。これにより自動的に検出用に登録されます。execute-code が対象にできるよう、ノートブック UI を開いておく必要があります。適切な起動方法は、コンテキスト(プロジェクトのツール、グローバルインストール、サンドボックスモード)によって異なります。ノートブックファイルに PEP 723 の # /// script ヘッダーが含まれている場合は、--sandbox を指定して開かなければなりません。そうしないと marimo はインラインの依存関係を無視します。完全な判断フローは finding-marimo.md、セレクターの解決、スクリプト、MCP、シェルでの引用符の処理については execution-context.md を参照してください。
スクラッチパッドのスコープ
execute-code は、marimo のスクラッチパッドで Python を評価します。スクラッチパッドは、カーネルのグローバル変数を浅くコピーした一時的な名前空間です。ノートブックの変数は名前で使用できますが、新しいトップレベルのバインディングや再バインドは、各呼び出しの後に破棄されます。ノートブックが所有するオブジェクトへのインプレース変更は、それらの名前が引き続きライブオブジェクトを参照するため、保持される場合があります。
各呼び出しでは、スクラッチパッドからの stdout と stderr に加え、その呼び出しが実行させたノートブックセル(リアクティブな子孫を含む)のコンソール出力が報告されます。
通常の Python
スクラッチパッドでは通常の Python を使って、変数の確認、データのサンプリング、変換のテスト、API の調査、インポートの確認、ウィジェットの状態の読み取りを行います。
print(df.head())
x = 10
print(x)
ここでは、df はノートブックのグローバル変数に由来し、x はスクラッチパッド内だけのバインディングです。x は今回の呼び出しでのみ有効で、ノートブックのグローバル変数には追加されません。
cm を使って作業を永続化する
トップレベルのスクラッチパッドでの代入や再束縛は一時的なものです。新しい変数を含め、作業を永続化するには、必ず marimo._code_mode(cm)を通じて変更を送信してください。
marimo._code_mode はプライベートで不安定なエージェント API です(先頭にアンダースコアが付いていることに注意してください)。このスキルのようなツールがスクラッチパッドからライブカーネルを操作するために存在します。ノートブックのセル、ライブラリコード、またはユーザーが実行するコードからインポートしないでください。メソッドは marimo のバージョンやカーネルによって変更されたり、なくなったりする可能性があります。import marimo._code_mode as cm はすべてスクラッチパッド専用として扱ってください。
コードモードのコンテキストを開いて、ノートブックへの変更をキューに追加します。
import marimo._code_mode as cm
async with cm.get_context() as ctx:
cid = ctx.create_cell("x = df.head()")
ctx.run_cell(cid)
スクラッチパッドでは、トップレベルの非同期コードを使用できます。async with を直接使ってください。asyncio.run(...) でラップする必要はなく、カーネルのイベントループと競合する可能性があります。
このブロックが終了して新しいセルが実行されると、x はノートブックの状態になります。後続のスクラッチパッド呼び出しでは、名前で x を読み取れます。同じスクラッチパッド呼び出し内の後続コードでは、セルが実行される前にスクラッチパッドの名前空間がコピーされているため、ctx.globals["x"] を読み取ってください。
コンテキスト内では、キューに追加する変更メソッドは同期的です。そのまま呼び出し、await は付けないでください。各呼び出しは、コンテキストが正常に終了したときに marimo が適用する操作をキューに追加します。ブロックで例外が発生すると、キューは破棄されます。
正常に終了すると、marimo はパッケージを適用し、セルの構造変更を検証して適用し、キューに追加されたセルを実行した後、依存セルを実行する場合があります。キューに追加されたセルの実行時にエラーが発生する可能性があるため、検証の対象は構造のみです。create_cell と edit_cell が変更するのはノートブックの構造だけです。実行するには run_cell を使用してください。
現在、create_cell はデフォルトで hide_code=True に設定されており、UI ではコードエディターが折りたたまれます。作成したセルを手動で展開しなくても表示したい場合は、hide_code=False を渡してください。
marimo のルール
marimo は、ノートブックを有向非巡回グラフ(DAG)として維持できるよう、ノートブックのコードにいくつかのルールを設けています。
- 循環参照は禁止 — セル同士が循環依存することはできません。
- セル間でのパブリック名の再定義は禁止 — 各名前を所有するセルは 1 つだけです。
- ワイルドカードインポートは禁止 —
import *を使うと、定義を静的に解析できなくなります。
これらのルールにより、カーネル、UI、保存された成果物の整合性が保たれます。
cm がセル本体を送信すると、marimo はトップレベルの定義と参照を解析します。パブリック名はグラフに追加されます。_ で始まる名前はそのセル内でのみ有効で、他のセルからは使用できません。cm による編集がこのルールに違反すると、marimo は構造変更を拒否し、検証エラーを返します。
ノートブックの構造
ノートブックは、順序付けられたセルの集合です。ctx.cells はドキュメントのビュー、ctx.graph はデータフローのビューです。
for cell in ctx.cells:
cell # .id, .code, .name, .config, .status, .errors
ctx.cells["setup"] # by name
ctx.cells[0] # by position
list(ctx.cells.keys()) # all IDs, in notebook order
セル ID は不透明な文字列で、ノートブックから取得するか、cm の戻り値から取得できます。
cid = ctx.create_cell("df = pd.read_csv('data.csv')")
print(cid) # e.g. 'Hbol'
また、セルには name を割り当てて参照することもできます。グラフを使うと、データフローにおける役割を把握できます。
for cid, impl in ctx.graph.cells.items():
impl # .defs, .refs (sets of public names)
ctx.graph.descendants(cid) # cells that re-run when this one changes
ctx.graph.ancestors(cid) # cells this one depends on
marimo では、削除は破壊的な操作です。そのため、影響を把握するために、削除する前に子孫セルを確認すると便利です。
ノートブックの変更を記述する
グラフのルールにより、marimo はノートブックを実行し、保存できます。ただし、これらのチェックに合格しただけでは、有用な成果物になるとは限りません。コミットするセルは、読みやすく、再実行可能で、編集可能な状態にしておく必要があります。
ノートブックの既存の名前、インポート、依存関係、UI モデルを再利用し、永続的な編集を行ってください。手を抜かないでください。cm の検証には合格しても、壊れやすいノートブックを残すような、その場しのぎの回避策は避けてください。
セルの本文
セルに記述するコードを送信します。
- セルの内容を送信する —
create_cellとedit_cellには、保存ファイルの@app.cellラッパーではなく、セルの内容を渡します。 - 置き換える前に読み取る — 現時点では、スクラッチパッドの呼び出しの間に別のエディターがセルを変更する場合があります。
edit_cellを呼び出す前に、ctx.cells[...]から現在の本文を読み取り、置き換え後の本文全体を送信してください。 - ノートブックのインポートを再利用する — すでに
npがある場合は、それを使うか、インポートを行うセルを編集してください。グラフを回避するためだけにimport numpy as _npを追加しないでください。 - 各公開名は一度だけ定義する — 公開名を所有するセルは1つだけです。別のセルで再代入すると、
Multiply-defined namesエラーになります。所有するセルを編集するか、結果に新しい名前を付けてください。gotchas.md を参照してください。 - セルは意図的に実行する —
create_cellとedit_cellが変更するのは構造だけです。セルを実行する場合は、ctx.run_cell(...)をキューに追加してください。
セルの境界
セルは再実行の境界でもあります。高コストな計算や再利用可能な計算は、表示処理の前段に置いてください。そうすれば、UI の編集を低コストに保てます。簡潔で読みやすくなる場合は、表示に固有の低コストな処理をビューと一緒に置いてください。
UI の構成要素である場合にのみ、mo.vstack と mo.hstack を使用してください。説明文は、隣接する Markdown セルに置くほうが読みやすいことがよくあります。
cm 管理の変更を優先する
利用できる場合は cm API を使用してください。永続化すべき変更には、ファイルの直接編集、シェルのパッケージコマンド、スクラッチパッドのみの状態を使用しないでください。
.pyアーティファクトを編集しない — ライブセッション中にEdit、Write、NotebookEditを使ってノートブックファイルを編集しないでください。小さな変更であっても、ctx.edit_cell(...)を使用してください。- パッケージは
cmで管理する —uvやpipを直接使う代わりに、ctx.packages.add()またはctx.packages.remove()を使用してください。自明でない依存関係の変更は確認してください。 - 一時的なパスを避ける — 意図的に一時的な作業でない限り、永続化するセルが
/tmp/...に依存しないようにしてください。 - 意図的に削除する — セルを削除すると、そのセルで定義されているグローバル変数も削除されます。必要に応じて空のセルを再利用し、編集後に空のまま残ったセルは削除してください。
UI とウィジェット
変更する前にオブジェクトを確認してください。UI オブジェクトによって、更新方法は異なります。
mo.ui.*はcm経由で設定する —cm.get_context()内でctx.set_ui_value(element, value)を使用してください。- anywidget の traitlets は直接設定する — 同期される traitlets は Python の属性です。たとえば、
widget.value = 5のように設定します。
カスタムの視覚的またはインタラクティブな出力の設計については、rich-representations.md を参照してください。
参考資料
- execution-context.md — スクリプト、MCP、認証、起動、シェルでのクォート
- finding-marimo.md — 適切な marimo の起動方法の選択
- gotchas.md — 名前の再定義、キャッシュされたモジュールプロキシ、ノートブックでの注意点
- rich-representations.md — カスタムウィジェットと可視化
- notebook-improvements.md — 既存のノートブックの改善