Claude Media
Claude Codeでmarimoのノートブックを編集する — .pyのまま直せる

Claude Codeでmarimoのノートブックを編集する — .pyのまま直せる

marimoのノートブックは.pyで保存されるため、Claude CodeのEditツールでそのまま直せます。セルの依存関係を壊さない頼み方と、marimo checkでの検証、--watchで画面に反映する流れをまとめました。

marimoのノートブックはPythonファイルとして保存されます。そのため、Claude Codeでは専用のNotebookEditではなく、通常のEditツールで直せます。差分もふつうのgit diffで読めます。

ただし、見た目がただの.pyでも中身はセルの依存グラフです。変数の定義を重複させたり、循環させたりすると、ノートブックが動かなくなります。この記事では、Claude Codeに頼むときに守らせたい約束事と、編集後の検証、ブラウザ側への反映までを順に書きます。

marimoのノートブックは、セルが関数で並ぶ.pyファイル

marimoのドキュメントによると、ノートブックはPythonファイルで、セルは@app.cellで飾った関数として保存されます。関数の引数がそのセルが読む変数、returnがそのセルが定義する変数です。

@app.cell
def memorable_cell_name(auto, determined, references):  # 引数 = 参照する変数
    computed_value = auto + determined + references
    "hello!"                                            # 最後の式が表示される出力
    return computed_value                               # return = 定義する変数

ここがJupyterとの大きな違いです。.ipynbはJSONで、Claude CodeはNotebookEditでセルIDを指定して直します。marimoの.pyはテキストなので、Editが使う文字列の完全一致による置換がそのまま通ります。Edit(old_stringとnew_stringによる置換)の仕様は、ツールのリファレンスにあります。

項目Jupyter(.ipynb)marimo(.py)
保存形式Jupyter(.ipynb)JSONmarimo(.py)Pythonファイル
Claude Codeの編集ツールJupyter(.ipynb)NotebookEdit(セルID指定)marimo(.py)Edit / Write(文字列置換)
git diffJupyter(.ipynb)JSONの差分marimo(.py)コードの差分
セルの実行順Jupyter(.ipynb)画面上の並びmarimo(.py)変数の参照関係で決まる

.ipynb側の扱いはClaude CodeでJupyterノートブックを編集する仕組みに、.ipynbのまま差分を読みやすくする方法はjupytextで.pyの差分を読む手順にあります。marimoは、最初から.pyで持つ側の選択肢です。

依存順を壊さないためにClaudeへ伝えること

marimoは各セルを静的に解析し、参照と定義から依存の有向非巡回グラフを作ります。セルを実行すると、そのセルが定義した変数を参照するセルが自動で実行されます。実行順はページ上の並びではなく、この関係で決まります。

Claude Codeに頼むときは、この仕組みから次の約束を引き出せます。

  • グローバル変数の定義は1セルだけ: marimoは、グローバル変数をただ1つのセルが定義することを求めます。同じ名前を別のセルで再代入させない
  • 一時変数はアンダースコア始まり: _xのような名前はそのセルの中だけの変数になります。ループ変数や中間結果はこちらに寄せる
  • 変数の変更は定義したセルの中で: my_list.append(42)のような変更や属性への代入は追跡されません。別のセルから変更すると、依存するセルが再実行されません。新しい変数を作るか、定義と同じセルで変更する
  • セルの引数とreturnは手で整えようとしない: ドキュメントでは、セルの引数と戻り値の維持はmarimoが担当するとされています

最後の項目は誤解しやすい点です。Claude Codeがセルの引数やreturnを手書きで直す必要はありません。ただし、これはmarimoのエディターが保存するときの話です。外部のエディターやClaude Codeがファイルを直接書き換える場合に、引数とreturnの整合を誰がとるかは、ドキュメントでは説明がありません。そこで次の節のmarimo checkで確かめます。

CLAUDE.mdに書く約束の例

上の4つは、リポジトリのCLAUDE.mdに書いておくと毎回頼まずに済みます。次は、ドキュメントの内容を指示文に直した例です。

## marimoノートブック(notebooks/*.py)
 
- セルは `@app.cell` の関数。Editで直接編集してよい
- グローバル変数は1つのセルだけで定義する。同名の再代入をしない
- 一時変数は `_` 始まりにする
- 変数の変更(append、列の追加)は、その変数を定義したセルの中で行う
- 編集のあとは `uvx marimo check <ファイル>` を実行し、結果を報告する

uvxで実行する書き方は、marimoのpairのドキュメントが使っている形です。marimoをプロジェクトに入れている環境なら、marimo checkでも同じです。

編集後はmarimo checkで依存を確かめる

marimoにはlinterが入っており、marimo checkで実行できます。ファイルやディレクトリを渡すと検査し、--fixを付けると直せる問題を直します。

marimo check notebooks/analysis.py
marimo check --fix notebooks/

検査項目のうち、実行を止める「Breaking」に分類されているのは次の5つです。

コード名前内容
MB001名前unparsable-cells内容セルに解析できないコードがある
MB002名前multiple-definitions内容複数のセルが同じ変数を定義している
MB003名前cycle-dependencies内容セルが循環して依存している
MB004名前setup-cell-dependencies内容セットアップセルが依存を持っている
MB005名前invalid-syntax内容セルがSyntaxErrorになるコードを含む

Claude Codeが起こしやすいのは、MB002とMB003でしょう。たとえば、2つのセルで同じdfに代入するとMB002、セルAがBの変数を読みBがAの変数を読むとMB003になります。ドキュメントの表では、この5つはいずれも--fixで自動修正できない項目です。Claudeには、報告された箇所を読ませて直させます。

編集のたびに自動で走らせたいとき

Claude Codeのhooksには、Edit|Writeの後に処理を差し込むPostToolUseがあります。公式のhooksガイドでは、編集したファイルのパスをjqで取り出し、整形ツールに渡す例が載っています。同じ形でmarimo checkを呼べます。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs uvx marimo check"
          }
        ]
      }
    ]
  }
}

この設定は、marimoでない.pyを編集した場合にも動きます。プロジェクトにmarimoのノートブックとふつうのスクリプトが混在するなら、ノートブックのディレクトリ内だけで動くように、コマンド側でパスを絞ってください。marimo checkが非marimoファイルをどう扱うかは、ドキュメントに記載がありません。

画面を開いたまま直させる: --watch

ブラウザでノートブックを開いたまま、Claude Codeに直させたいことがあります。marimo editに--watchを付けると、marimoがノートブックのファイルを監視します。ファイルの変更はブラウザ上のエディターに流れ込みます。

uvx marimo edit --watch notebooks/analysis.py

既定では、反映されたコードは自動実行されず、該当セルがstale(古い状態)になります。エディターの「Run」ボタンかrunStaleのホットキーで、staleのセルをまとめて実行します。保存のたびに影響を受けるセルを自動実行したい場合は、pyproject.tomlに次を足します。

[tool.marimo.runtime]
watcher_on_save = "autorun"

重い計算を含むノートブックでは、既定のstale表示のほうが安全です。Claude Codeが何度も保存するたびに、重いセルが走り直すのを避けられます。ドキュメントは、パフォーマンスのためにwatchdogの導入と、エディター側の自動保存の有効化も勧めています。

Claudeを実行中のノートブックにつなぐ方法もある

ここまでは「ファイルを直す」使い方です。marimoには、実行中のノートブックに直接つなぐmarimo pairもあります。ドキュメントでは、エージェントが変数を読み、スクラッチパッドでロジックを試し、セルを実行し、セルの追加と削除をし、UI要素まで操作できると説明しています。

使い方は、uvx marimo@latest edit my_notebook.pyでノートブックを開き、メニューの「Connect your agent」からClaudeを選んで、表示されたコマンドをターミナルで実行します。エージェントにノートブックのエラーを送るには、保存済みのノートブックと、Claude Codeのネイティブなinboxセッション(macOSまたはLinux)が必要です。

使い分けは次のとおりです。

  • ファイル編集(この記事の方法): コードの修正、リファクタリング、差分をgitで管理したい変更。変数の中身を見る必要がない
  • marimo pair: データの中身を見ながら探索したい作業。実行中のカーネルの状態に触れる

前者は通常のEditとgit diffだけで完結するので、レビューの流れを変えません。

関数やクラスは、セルの外へ出して取り込める

.pyで持つ利点は、Claude Codeが書いたロジックを別のPythonモジュールから取り込めることです。ドキュメントによると、@app.functionで飾った関数と@app.class_definitionのクラスは、from my_notebook import my_functionのようにインポートできます。ただし、これらは純粋である必要があります。参照できるのは、ほかの純粋な関数とクラス、そしてapp.setupブロックで定義したimportと定数だけです。

with app.setup:
    import numpy as np
    CONSTANT: int = 1
 
@app.function
def my_function(x: np.ndarray):
    return np.mean(x) + CONSTANT

集計ロジックをこの形にまとめさせておくと、ノートブックを開かずにテストしやすくなります。ドキュメントは、ノートブックに対してpytestを実行できるとも説明しています。Claudeへの頼み方としては、「再利用したい関数は@app.functionに出し、グローバル変数を参照しない形にする」で足ります。

既存の.ipynbを変換してから渡す

手元に.ipynbしかない場合は、marimoのCLIで.pyに変換できます。

marimo convert your_notebook.ipynb > your_notebook.py

逆向きにはmarimo export ipynb notebook.py -o notebook.ipynbがあり、.ipynbが必要な相手へは書き出して渡せます。変換後はまずmarimo checkを通し、セルの依存に問題がないかを確かめてからClaude Codeに編集を任せると、原因の切り分けが楽になります。

つまずきやすいところ

同じ変数名が複数のセルに出る

集計の途中でdfを作り直すと、別セルでdf = ...と書いてしまいます。MB002になります。Claudeには「新しい名前をつけるか、定義したセルの中で変更する」と伝えます。

変更が追跡されず、結果が更新されない

df["new"] = ...を別のセルで書いても、dfを参照する他のセルは再実行されません。ドキュメントは、変更は定義と同じセルで行うか、新しい変数を作るよう勧めています。

Markdown形式のファイルを渡してしまう

marimoはノートブックをMarkdownでも保存できますが、ドキュメントによると.pyほど機能が揃っていません。リアクティブなテストは動かず、ライブラリとしてのインポートや、スクリプトとしての実行もできません。Claude Codeに渡すのは.py形式にしておきます。

編集を権限で制限するとき

.ipynbではNotebookEditもEdit(...)のパスルールで制御されます。marimoの.pyはEditとWriteが対象なので、Edit(notebooks/**)のようなルールで足ります。

まとめ

marimoのノートブックは.pyなので、Claude Codeの通常のEditで直せて、差分もコードとして読めます。決めておくことは、グローバル変数を1セルで定義すること、変更を定義側のセルに置くこと、編集のあとにmarimo checkで依存を確かめること、の3つです。ブラウザを開いたまま直させるなら--watch、既定のstale表示のまま重いセルを守れます。

最初は、小さなノートブックをEditで1箇所だけ直させ、marimo checkの結果とgit diffを並べて見るところから始めると、約束事の効き具合が分かります。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/tools-reference
  2. code.claude.com/docs/en/hooks-guide
  3. code.claude.com/docs/en/common-workflows
  4. docs.marimo.io/
  5. docs.marimo.io/guides/reactivity
  6. docs.marimo.io/guides/editor_features/watching
  7. docs.marimo.io/guides/lint_rules
  8. docs.marimo.io/guides/generate_with_ai/marimo_pair
この記事を共有:XはてブLinkedIn