[BUG] NotebookEdit tool writes non-standard Jupyter Notebook format.

Status Closed — not planned
Maintainer reply None cached
Activity 5 comments · opened Apr 16, 2026 · closed May 24, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When Claude Code uses NotebookEdit tool to edit a notebook cell, it changes the source formatting from JSON array to single string.

e.g. here is what Claude Code produces:

  {
   "cell_type": "markdown",
   "id": "ec27bf33",
   "source": "### Sample header\nThis is line 1  \nThis is line 2"
  }

While the above is valid, the Jupyter interface on clicking Save or executing cell turns it into:

  {
   "cell_type": "markdown",
   "id": "ec27bf33",
   "source": [
    "### Sample header\n",
    "This is line 1  \n",
    "This is line 2"
   ]
  }

Issue

Claude Code's notebook formatting makes it difficult to use it interactively with Jupyter as any edit by Claude Code changes the entire notebook cell contents causing massive noisy diffs.

What Should Happen?

Claude's NotebookEdit tool should simply follow standard notebook formatting where cell source lines are JSON array. e.g.

{
   "cell_type": "markdown",
   "id": "ec27bf33",
   "source": [
    "### Sample header\n",
    "This is line 1  \n",
    "This is line 2"
   ]
  }

This should be a straightforward change to NotebookEdit tool.

Error Messages/Logs

Steps to Reproduce

  1. Ask Claude Code to edit a notebook cell.
  2. Commit the changes.
  3. Open the notebook in Jupyter & execute the cell
  4. Look at git diff, the notebook file is changed even though content is untouched.

Above issue makes it impossible to use Claude's NotebookEdit capability alongside standard Jupyter.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

v2.1.110

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

5 Comments

0xbrainkid · 6 months ago

NotebookEdit writing source as a single string instead of a JSON array is a format compliance bug — the Jupyter Notebook format specification (nbformat 4) requires source to be an array of strings where each element is a line of content. Writing a single string is technically valid JSON but non-standard Jupyter format, causing downstream tools (Jupyter UI, nbconvert, etc.) to convert it on first save.

From an agent capability and output integrity perspective, this means Claude Code produces notebooks that look correct but are subtly different from what any other Jupyter tool would produce — and that difference causes spurious diffs on every save, contaminating git history with non-substantive format changes.

The correct source format:

{
  "source": [
    "### Sample header\n",
    "This is line 1  \n",
    "This is line 2"
  ]
}

Each line of the cell content should be a separate array element, with \n at the end of every line except the last. The last element has no trailing newline.

Fix: The NotebookEdit tool's cell writer should split the content on newlines and produce an array, with \n appended to each element except the last:

def to_notebook_source(content: str) -> list[str]:
    lines = content.split("\n")
    return [line + "\n" for line in lines[:-1]] + ([lines[-1]] if lines[-1] else [])

This produces standard nbformat-compliant output that matches what Jupyter itself would write, preventing the spurious diffs on first save.

github-actions[bot] · 4 months ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

amit1rrr · 4 months ago

This problem still persists in Claude Code.

@ashwin-ant @dhollman @km-anthropic - can any of you please review and reopen? Issue was auto closed, and I do not have the permission to reopen on this repo.

dolfandringa · 3 months ago

Yeah, this is definitely something to fix. It basically means (git) diff tools do not work well with claude code produced jupyter notebook code.

github-actions[bot] · 1 month ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.