Skip to main content

Overview

Ganimede includes built-in version control features designed specifically for computational notebooks. Every cell execution is versioned, and you can create checkpoints to save the complete state of your notebook.

Auto Cell Commit

Every time you run a cell in Ganimede, the execution is automatically versioned. This feature is planned but not yet fully implemented.
Ganimede’s auto cell commit feature will ensure that:
  • Each cell execution is tracked
  • You can see the history of outputs for any cell
  • You never lose important intermediate results
  • You can revert to previous cell states
From the Ganimede roadmap:
  • ✅ Auto cell commit concept (feature description)
  • ⏳ Store run history of cells (in development)

Checkpoint System

The checkpoint system allows you to save the complete state of your notebook at any point in time.

Checkpoint Format

When you create a checkpoint, Ganimede saves the notebook with a .ganimede.ipynb extension:
async def checkpoint(self):
    notebook = {
        "cells": [],
        "metadata": {
            "gm": {
                "np_graph": {},
                "pc_graph": {},
            }
        },
    }
    
    # Save to file with .ganimede.ipynb extension
    notebook_path = Path(self.notebook_path)
    notebook_path = notebook_path.parent / (notebook_path.stem + ".ganimede.ipynb")
    with open(notebook_path, "w") as f:
        json.dump(notebook, f)
From api/ganimede/managers/Notebook.py:366-412

What Gets Saved

A checkpoint includes:

Cell Data

For each cell in the notebook:
cell_data = {
    "id": cell_id,
    "cell_type": cell.get("type"),  # code or markdown
    "source": cell.get("source").__str__().split("\n"),
    "outputs": [output for output in cell.get("outputs")],
    "metadata": {
        "gm": {
            "top": cell.get("top"),
            "left": cell.get("left"),
            "height": cell.get("height"),
            "width": cell.get("width"),
            "collapsed": cell.get("collapsed"),
        }
    },
}
From api/ganimede/managers/Notebook.py:380-395
  • Cell content: The source code or markdown text
  • Outputs: All execution results, including text, images, and errors
  • Canvas position: top, left, width, height coordinates
  • Visual state: Collapse state for hiding inputs/outputs

Graph Metadata

Ganimede saves two important graph structures in the notebook metadata:
  1. np_graph (Next-Previous Graph):
    • Defines the execution flow between cells
    • Maps each cell to its next cell(s) in the execution order
    • Enables sequential execution of related cells
  2. pc_graph (Parent-Children Graph):
    • Defines the hierarchical structure of the notebook
    • Created from markdown heading cells (# H1, ## H2, etc.)
    • Maps parent cells to their children cells
    • Enables “tissue grouping” - running all cells under a heading
# Collect np_graph and pc_graph
for id in self.ynp_graph.keys():
    notebook["metadata"]["gm"]["np_graph"][id] = [
        next_id for next_id in self.ynp_graph.get(id)
    ]
for id in self.ypc_graph.keys():
    notebook["metadata"]["gm"]["pc_graph"][id] = [
        child_id for child_id in self.ypc_graph.get(id)
    ]
From api/ganimede/managers/Notebook.py:398-405

File Format

Ganimede uses a custom notebook format: .ganimede.ipynb

Format Structure

{
  "cells": [
    {
      "id": "a1b2c3d4",
      "cell_type": "code",
      "source": ["import numpy as np", "x = np.array([1, 2, 3])"],
      "outputs": [...],
      "metadata": {
        "gm": {
          "top": 100,
          "left": 200,
          "width": 400,
          "height": 300,
          "collapsed": null
        }
      }
    }
  ],
  "metadata": {
    "gm": {
      "np_graph": {
        "a1b2c3d4": ["e5f6g7h8"]
      },
      "pc_graph": {
        "heading_id": ["child1_id", "child2_id"]
      }
    }
  }
}

Compatibility

The .ganimede.ipynb format:
  • Extends the standard Jupyter .ipynb format
  • Adds Ganimede-specific metadata under the gm key
  • Can be converted back to standard .ipynb by removing gm metadata
  • Preserves all standard notebook features (cells, outputs, execution counts)

Working with Checkpoints

Creating a Checkpoint

To create a checkpoint of your current notebook state:
# In your notebook code
await notebook.checkpoint()

Checkpoint File Location

If your original notebook is analysis.ipynb, the checkpoint is saved as:
analysis.ganimede.ipynb
Both files can coexist in the same directory.

Loading from Checkpoint

To load a checkpointed notebook:
ganimede analysis.ganimede.ipynb
Ganimede will restore:
  • All cell positions on the canvas
  • Cell execution outputs
  • The np_graph and pc_graph structures
  • Visual states (collapsed cells, etc.)

Graph-Based Execution

Next-Previous Graph (np_graph)

The np_graph enables linear execution flow:
self.np_graph = {
    "cell_1": ["cell_2"],  # cell_1 → cell_2
    "cell_2": ["cell_3"],  # cell_2 → cell_3
    "cell_3": []           # cell_3 has no next cell
}
This allows you to:
  • Run cells in a defined sequence
  • Execute chains of dependent cells
  • Navigate the execution order visually on the canvas

Parent-Children Graph (pc_graph)

The pc_graph enables hierarchical execution:
self.pc_graph = {
    "heading_1": ["cell_1", "cell_2", "heading_2"],
    "heading_2": ["cell_3", "cell_4"]
}
This allows you to:
  • Run all cells under a heading (“tissue grouping”)
  • Organize complex notebooks hierarchically
  • Collapse entire sections for better overview
The graphs are automatically constructed from your markdown headings and cell order when you first open a standard .ipynb file.

Roadmap

1

Checkpoint System

✅ Implemented - Save complete notebook state with canvas layout
2

Auto Cell Commit

⏳ In Development - Version every cell execution
3

Run History

📋 Planned - Store and browse historical cell outputs
4

Git Integration

📋 Planned - Intuitive git integration for notebook versioning
Ganimede’s version control is designed specifically for notebooks, understanding the unique challenges of versioning code with outputs and canvas layouts.

Build docs developers (and LLMs) love