Skip to content

Notebook

Sema includes a Jupyter-inspired notebook interface for interactive development. Write code in cells, evaluate them individually or all at once, and see results inline — all in the browser.

Quick Start

bash
# Create a new notebook
sema notebook new my-notebook.sema-nb

# Open in the browser
sema notebook serve my-notebook.sema-nb

This starts a local server at http://localhost:8888 with the notebook UI.

Cell Types

Code Cells

Code cells contain Sema expressions. Evaluate with Shift+Enter (run and advance) or Cmd/Ctrl+Enter (run and stay).

Cells share a persistent environment — definitions in earlier cells are visible in later ones:

sema
;; Cell 1
(define greet (fn (name) (format "Hello, ~a!" name)))

;; Cell 2 — can use greet from Cell 1
(greet "Sema")  ;=> "Hello, Sema!"

Output from println, display, and print is captured and shown in the cell output area.

Markdown Cells

Markdown cells render formatted text for documentation, section headers, and notes. Supports headings, bold, italic, inline code, code blocks, and lists.

Click rendered markdown to edit. Press Shift+Enter to re-render.

Keyboard Shortcuts

ShortcutAction
Shift+EnterRun cell and advance to next
Cmd/Ctrl+EnterRun cell and stay focused
Cmd/Ctrl+SSave notebook
TabInsert 2 spaces
EscapeDeselect cell

Toolbar

ButtonAction
+ CodeAdd a new code cell at the end
+ MarkdownAdd a new markdown cell at the end
Run AllEvaluate all code cells in order
UndoUndo the last cell evaluation (restores environment)
SaveSave the notebook to disk
ResetClear all outputs and reset the environment

You can also insert cells between existing ones by hovering between cells and clicking the + button that appears.

Undo

After evaluating a cell, click Undo (or the inline "Undo cell" button on error outputs) to roll back:

  • The cell's outputs are restored to their previous state
  • The interpreter environment is rolled back to before the evaluation
  • Downstream stale markers are reverted

This is useful when a cell modifies global state unexpectedly.

File Format

Notebooks are saved as .sema-nb files in JSON format:

json
{
  "version": 1,
  "metadata": {
    "title": "My Notebook",
    "created": "2026-01-01T00:00:00Z",
    "modified": "2026-01-01T12:00:00Z",
    "sema_version": "1.14.2"
  },
  "cells": [
    {
      "id": "c12345678",
      "type": "code",
      "source": "(+ 1 2)",
      "outputs": []
    }
  ]
}

Cell id format

Cell IDs are short stable strings of the form "c" followed by 8 lowercase hexadecimal characters (e.g. "c4a3f2b1"). They are generated by hashing a fresh UUIDv4 to its first 8 hex digits and prefixing with c. Treat them as opaque tokens — they're stable for the lifetime of a cell and used by the REST API to address cells.

stale flag

Code cells carry an optional stale: bool field. When an upstream cell is re-evaluated, all downstream code cells with existing outputs are flipped to stale: true. The field is omitted from serialized JSON when false. A stale cell still displays its previous outputs, but the UI indicates that those outputs may not reflect the current state of the environment until the cell is re-evaluated.

Fully-evaluated cell example

When a code cell has been evaluated, its outputs array contains one or more CellOutput objects. Here is a cell with every field populated:

json
{
  "id": "c4a3f2b1",
  "type": "code",
  "source": "(+ 1 2)",
  "outputs": [
    {
      "type": "value",
      "display": "3",
      "sema_value": "3",
      "timestamp": "2026-01-01T12:34:56.789Z",
      "cost_usd": 0.0,
      "requires_reeval": false,
      "duration_ms": 12
    }
  ]
}

Field reference (CellOutput):

  • type — output discriminator (see table below).
  • display — human-readable string shown in the UI.
  • sema_value — round-trippable S-expression form of the value (omitted when not applicable, e.g. for error / stdout outputs).
  • timestamp — RFC 3339 UTC timestamp of when the output was produced.
  • cost_usd — estimated LLM cost, for outputs from LLM calls; omitted otherwise.
  • requires_reevaltrue for opaque values (lambdas, native fns, macros, streams, thunks) that cannot be round-tripped through sema_value and must be re-evaluated on notebook reload.
  • duration_ms — wall-clock evaluation time of the cell, in milliseconds.

OutputType discriminator

The type field on CellOutput is one of:

ValueMeaning
valueThe cell returned a normal Sema value (the common case for successful evals).
errorEvaluation produced a SemaError; display holds the formatted error message.
stdoutCaptured println / display / print output produced during cell evaluation.

A single evaluated code cell may have both a stdout output (first) and a value or error output (second), in that order.

Version compatibility

The current notebook format version is 1. Tools reading .sema-nb files should treat version as a major version number and refuse to load files where MAJOR != 1 rather than silently mis-parsing them. Forward-compatible field additions (e.g. new optional fields on CellOutput) do not bump version; breaking changes to existing fields will.

Headless Execution

Run all cells without starting the browser UI:

bash
sema notebook run my-notebook.sema-nb

This evaluates all code cells in order, printing stdout to the terminal. Useful for CI validation or batch processing.

Run specific cells by index (1-based):

bash
sema notebook run my-notebook.sema-nb --cells 1,3,5

Export

Export a notebook to Markdown:

bash
# To stdout
sema notebook export my-notebook.sema-nb

# To file
sema notebook export my-notebook.sema-nb -o output.md

The export includes code blocks with output, markdown sections, and error messages.

REST API

The notebook server exposes a JSON HTTP API on the same port as the browser UI. Everything the UI does goes through these endpoints — they're stable enough to script against from external tools.

Notebook & cells

MethodPathDescription
GET/api/notebookReturn the full notebook (cells + metadata)
POST/api/cellsCreate a new cell
GET/api/cells/{id}Fetch a single rendered cell
POST/api/cells/{id}Update a cell's source or type
DELETE/api/cells/{id}Delete a cell
POST/api/cells/{id}/evalEvaluate a single cell
POST/api/cells/reorderReorder cells by id
POST/api/eval-allEvaluate all cells (optionally with edited source)
GET/api/envInspect the current shared cell environment
POST/api/resetReset the evaluation environment
POST/api/undoUndo the last cell edit/delete
POST/api/saveSave the notebook to disk

Create cell request:

json
{ "type": "code", "source": "(+ 1 2)", "after": "<cell-id?>" }

Update cell request:

json
{ "source": "(+ 1 2)", "type": "code" }

Reorder request:

json
{ "cell_ids": ["id-1", "id-2", "id-3"] }

Eval-all request (optional — pass currently-edited sources without saving first):

json
{ "sources": [["cell-id", "(println \"hi\")"]] }

VFS

The notebook server exposes a small virtual filesystem so the browser UI can read and write files alongside the notebook.

MethodPathDescription
GET/vfs/readRead a file: ?path=foo.txt → text body
POST/vfs/writeWrite a file (JSON body, see below)
GET/vfs/listList a directory: ?path=. → JSON entries

Write request:

json
{ "path": "notes.txt", "content": "hello" }

List response (FileEntry[]):

json
[{ "name": "notes.txt", "is_dir": false, "size": 5 }]

VFS scope

VFS endpoints are sandboxed to the parent directory of the notebook file. When sema notebook serve is started without a --notebook path, the VFS root falls back to the current working directory ($PWD). The server prints a warning at startup in that case — prefer passing a notebook path if you don't want the whole $PWD to be reachable.

Security

The notebook server is a trusted-local developer tool. Cells run arbitrary Sema code — including file and network access — with the full privileges of the user who started the server, and the server has no authentication or authorization layer.

For this reason the server binds to the loopback interface (127.0.0.1) by default, so it is only reachable from the local machine. You can override the bind address with --host, but binding to a non-loopback address such as 0.0.0.0 exposes an unauthenticated remote code-execution endpoint to the network. If you need remote access, putting it behind a firewall, VPN, or an authenticating reverse proxy is the operator's responsibility.

CLI Reference

See sema notebook in the CLI reference for all flags and options.