NotebookEdit (Phase 79.13)
Cell-level edits on Jupyter .ipynb notebooks. Pure-Rust round-trip
through serde_json::Value — no jupyter binary, no Python
dependency. Unknown top-level fields survive untouched (forward-compat
with newer nbformat).
Lift from
upstream agent CLI.
Tool shape
{
"notebook_path": "/abs/path/to/nb.ipynb",
"cell_id": "alpha", // UUID-style id, or `cell-N` numeric fallback
"new_source": "x = 1",
"cell_type": "code", // optional for replace, required for insert
"edit_mode": "replace" // replace | insert | delete (default: replace)
}
| Edit mode | Behaviour |
|---|---|
replace | Overwrite cells[i].source. Code cells get execution_count: null and outputs: [] (the diff stays sane). Markdown cells preserve all metadata. |
insert | Add a new cell AFTER the anchor cell_id. Empty cell_id inserts at position 0. cell_type required. nbformat ≥ 4.5 gets a fresh 12-char base-36 id. |
delete | Remove the cell at cell_id. |
cell_id resolution: literal cells[i].id match first; falls back
to cell-N numeric index (matches the upstream parseCellId).
Failure lists up to 10 available ids in the error message.
Defensive behaviour
- Absolute path required. Refuses relative paths to avoid ambiguity across daemon cwd changes.
.ipynbextension required. Other file types fall toFileEdit.- Replace at end-of-cells auto-converts to insert. Lift from
the upstream CLI (
NotebookEditTool.ts:372-377). Requirescell_typein that path. - Bad writes leave the file untouched. Validation runs before
write; any error returns before
std::fs::write.
Plan-mode classification
Classified FileEdit (mutating) in
nexo_core::plan_mode::MUTATING_TOOLS. Plan-mode-on goals get a
PlanModeRefusal rather than a silent edit.
Output
{
"notebook_path": "/abs/path/...",
"edit_mode": "replace" | "insert" | "delete",
"cell_id": "alpha",
"cell_type": "code" | "markdown",
"language": "python", // from notebook.metadata.language_info.name
"total_cells": 3,
"cells_delta": 1 // -1 for delete, +1 for insert, 0 for replace
}
Out of scope (deferred)
- Read-before-Edit guard. the upstream CLI requires
Readto have been called on the file in the same session beforeNotebookEditis allowed. Nexo-rs does not have a shared file-state cache yet — the guard becomes useful when Phase 67 driver-loop adds one. - Attribution / file-history tracking. The upstream
fileHistoryTrackEditrecords edits to a per-session ledger. Skipped — the workspace-git layer (Phase 10.9) covers the same use case. - Multi-cell batch edits. One operation per call by design; callers loop over cell ids.
References
- PRIMARY:
upstream agent CLI,upstream agent CLI. - SECONDARY: OpenClaw
research/— no equivalent (grep -rln "ipynb|jupyter|nbformat" research/src/returns nothing). - Plan + spec:
proyecto/PHASES.md::79.13.