In the previous Auto-Mode Classifier chapter, we discussed how the AI decides if an action is safe enough to perform automatically.
Now, we need to talk about a specific type of file that is notoriously difficult for AI to edit: Jupyter Notebooks (.ipynb).
If you use FileEditTool on a standard text file, it works perfectly. But if you try to use standard text editing tools on a Notebook, you will likely corrupt the file and break the JSON structure.
Enter the NotebookEditTool. This is a specialized instrument designed to perform surgery on Data Science notebooks without breaking them.
To a human, a Jupyter Notebook looks like a document with text and code blocks.
To a computer, a .ipynb file is actually a giant, messy JSON object.
If you change one comma in the wrong place in that JSON file, the entire notebook becomes unreadable by Jupyter.
The NotebookEditTool solves this by treating the file as a Structure, not just a string of text. It parses the JSON, finds the specific "Cell" you want to change, updates it safely, and saves the file back to disk.
Imagine you are a Data Scientist. You have a notebook experiments.ipynb with 50 cells.
You ask claudeCode: "Update the plotting code in the third cell to use Seaborn instead of Matplotlib."
The tool needs to:
experiments.ipynb.In a notebook, content is divided into chunks called Cells.
The tool operates at the Cell Level, not the line level.
Every cell has a unique identifier (e.g., "cell-8472"). This allows the AI to target a specific block of code even if you move other cells around.
Because notebooks are structured lists, we support three specific actions:
This tool is used automatically by the AI when it detects a .ipynb extension. However, understanding the input helps you understand how the AI "thinks" about your notebooks.
The AI sends a structured command telling the tool exactly which block to modify.
{
"notebook_path": "analysis/data.ipynb",
"edit_mode": "replace",
"cell_id": "83j2-s9d1",
"new_source": "import seaborn as sns\nsns.histplot(data)"
}
Explanation: The AI specifies the file, the specific cell ID to target, and the new code to inject.
If the AI wants to add documentation, it uses the insert mode.
{
"notebook_path": "analysis/data.ipynb",
"edit_mode": "insert",
"cell_type": "markdown",
"new_source": "# Data Analysis Section"
}
Explanation: This adds a new markdown header into the notebook list.
The process is different from editing a normal text file. We must Load -> Parse -> Modify -> Save.
cells array to find the matching ID.Here is the visual flow:
Let's look at tools/NotebookEditTool/NotebookEditTool.ts to see how we handle this safely.
Before we do anything, we ensure we are working with the right file type.
// tools/NotebookEditTool/NotebookEditTool.ts (Simplified)
async validateInput({ notebook_path, edit_mode }) {
// 1. Check extension
if (!notebook_path.endsWith('.ipynb')) {
return { result: false, message: 'Must be a .ipynb file' };
}
// 2. Read file to ensure it exists
const content = readFileSync(notebook_path);
// 3. Ensure it is valid JSON
if (!isValidJSON(content)) {
return { result: false, message: 'Notebook is corrupted' };
}
}
Explanation: We reject the request immediately if the file isn't a notebook or if the JSON is broken. This prevents us from making a bad file worse.
This is the core "surgery." We load the JSON, find the array index, and swap the data.
// Inside the call() function
// 1. Parse the file content into an object
const notebook = JSON.parse(fileContent);
// 2. Find the index of the cell we want to change
const cellIndex = notebook.cells.findIndex(c => c.id === cell_id);
// 3. Perform the edit (Replace example)
if (edit_mode === 'replace') {
// Update the source code
notebook.cells[cellIndex].source = new_source;
// Clear old outputs (graphs/logs) since code changed
notebook.cells[cellIndex].outputs = [];
}
Explanation: Notice how we clear outputs. If you change code, the old graph is now outdated, so we remove it to keep the notebook clean.
Finally, we write the file back to disk.
// Saving the file
import { writeTextContent } from '../../utils/file';
// 1. Convert object back to text (with nice indentation)
const updatedContent = JSON.stringify(notebook, null, 1);
// 2. Write to disk
writeTextContent(fullPath, updatedContent);
// 3. Notify State Management that file changed
updateFileHistoryState(fullPath);
Explanation: We use JSON.stringify to turn our object back into the text format that Jupyter expects.
The NotebookEditTool is a great example of a "Specialized Tool."
FileEditTool, this tool must pass security checks before writing to your disk.
You have learned that the NotebookEditTool allows claudeCode to safely edit Jupyter Notebooks. Instead of treating them as text files, it respects their internal JSON structure, ensuring that cells are updated cleanly without corrupting the document.
Now that we can edit code and notebooks, what if the AI needs information it doesn't have? What if it needs to look up documentation online?
Generated by Code IQ