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
# Create a new notebook
sema notebook new my-notebook.sema-nb
# Open in the browser
sema notebook serve my-notebook.sema-nbThis 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:
;; 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
| Shortcut | Action |
|---|---|
Shift+Enter | Run cell and advance to next |
Cmd/Ctrl+Enter | Run cell and stay focused |
Cmd/Ctrl+S | Save notebook |
Tab | Insert 2 spaces |
Escape | Deselect cell |
Toolbar
| Button | Action |
|---|---|
| + Code | Add a new code cell at the end |
| + Markdown | Add a new markdown cell at the end |
| Run All | Evaluate all code cells in order |
| Undo | Undo the last cell evaluation (restores environment) |
| Save | Save the notebook to disk |
| Reset | Clear 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:
{
"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:
{
"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. forerror/stdoutoutputs).timestamp— RFC 3339 UTC timestamp of when the output was produced.cost_usd— estimated LLM cost, for outputs from LLM calls; omitted otherwise.requires_reeval—truefor opaque values (lambdas, native fns, macros, streams, thunks) that cannot be round-tripped throughsema_valueand 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:
| Value | Meaning |
|---|---|
value | The cell returned a normal Sema value (the common case for successful evals). |
error | Evaluation produced a SemaError; display holds the formatted error message. |
stdout | Captured 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:
sema notebook run my-notebook.sema-nbThis 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):
sema notebook run my-notebook.sema-nb --cells 1,3,5Export
Export a notebook to Markdown:
# To stdout
sema notebook export my-notebook.sema-nb
# To file
sema notebook export my-notebook.sema-nb -o output.mdThe 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
| Method | Path | Description |
|---|---|---|
| GET | /api/notebook | Return the full notebook (cells + metadata) |
| POST | /api/cells | Create 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}/eval | Evaluate a single cell |
| POST | /api/cells/reorder | Reorder cells by id |
| POST | /api/eval-all | Evaluate all cells (optionally with edited source) |
| GET | /api/env | Inspect the current shared cell environment |
| POST | /api/reset | Reset the evaluation environment |
| POST | /api/undo | Undo the last cell edit/delete |
| POST | /api/save | Save the notebook to disk |
Create cell request:
{ "type": "code", "source": "(+ 1 2)", "after": "<cell-id?>" }Update cell request:
{ "source": "(+ 1 2)", "type": "code" }Reorder request:
{ "cell_ids": ["id-1", "id-2", "id-3"] }Eval-all request (optional — pass currently-edited sources without saving first):
{ "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.
| Method | Path | Description |
|---|---|---|
| GET | /vfs/read | Read a file: ?path=foo.txt → text body |
| POST | /vfs/write | Write a file (JSON body, see below) |
| GET | /vfs/list | List a directory: ?path=. → JSON entries |
Write request:
{ "path": "notes.txt", "content": "hello" }List response (FileEntry[]):
[{ "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.