Chalk Notebooks
Mix and match SQL, Python, and Markdown cells to explore, analyze and productionize features.
Chalk Notebooks build on the notebook format you already know. You’ll be on familiar ground if you’ve spent time in Jupyter or a similar environment: the interface is made up of cells. Chalk extends that with additional cell types, and your features, resolvers, and queries are all available from a notebook, so you can explore your data and create new features in one place. Those cells run on Chalk Compute, which runs sandboxed compute inside your own cloud, so notebook code executes on infrastructure you own and control rather than in a Chalk-hosted environment. Any data source you have already configured under Integrations is natively queryable from a notebook — no re-configuration and no new credentials.
This page covers the notebooks Chalk hosts for you, which you can drive from the dashboard or
from the chalk notebook CLI. You can also connect a notebook you run
yourself, in Jupyter, Colab, Hex, or Deepnote: see
External Notebooks for that setup, and the
Jupyter notebook tutorial for a worked example that builds features
and resolvers end to end.
Use SQL to select orders, Python to summarize the resulting DataFrame, and an online query to inspect Chalk features and their execution plan. This example brings the three cells together; select an operator in the plan to inspect its details.
Pick a type when you add a cell.
Every cell that computes something leaves its result behind for the rest of the notebook to use. Output renders directly beneath the cell that produced it, and the value is bound to a name that later cells can read.
All cells share one Python session, so a name defined in one cell stays defined for the cells after it. Python cells bind names the ordinary way, by assignment. SQL and Input cells bind their output to a result variable instead. You can rename that variable, and it is worth naming it well early, because downstream cells refer to it by name. The variable explorer lists what the session currently holds, with a preview of each value.
For examples and output details, see SQL cells, Python cells, and Text and Markdown cells.
Because cell results can be referenced by name, work can be split across cells instead of piling into one. A SQL cell pulls a dataset, a Python cell reads that result by name and reshapes it, and a Single value cell surfaces one number from the reshaped frame. Each step stays independently runnable and independently readable.
You never declare these connections. Chalk infers each cell’s dependencies from what that cell reads and what it writes, and those inferred dependencies drive the notebook’s run modes and its tracking of which cells have gone stale.
Everything on this page also has a CLI equivalent. chalk notebook create, cell add, run,
get, and results cover creating a notebook, adding and running cells, and reading back their
output from a terminal or a script instead of the dashboard, and
chalk notebook dependencies lists the packages installed in a
notebook’s kernel. See the CLI reference for every command and flag, or run
chalk notebook --help.
When querying a branch from Python, set the branch on the client inside the cell. See Querying a branch.
An AI coding assistant can reach notebooks two other ways. Chalk’s
MCP server exposes the same ground as tools, covering creating a
notebook, editing its cells, running them, and reading their results. Separately,
the chalk-notebooks agent skill covers the same
workflow for assistants that read one.
Every notebook’s own controls sit in one bar at the top right, above the cells. The rest of this page walks that bar from left to right.
App switches the notebook into app view, a dashboard canvas that presents results without the code behind them. It is a view toggle, not a publish step: the button flips to Notebook, which switches you back, and the view is recorded in the URL, so a refresh or a pasted link reopens it.
Nothing reaches the canvas on its own. Every cell carries an Add to app dashboard button in its action rail, and clicking it places that cell on the app dashboard; the same button then offers Remove from app dashboard to take it back off. The Add cell dropdown in app view is the second path, and it also offers Add all cells — a notebook with no placed cells opens as an empty canvas.
Placed cells render their results only — source code is never shown. Input cells stay interactive, so the controls that drive the notebook drive the app too. Section cells render as titles, and Single value cells render as metrics. You position widgets by dragging and resizing them, and the layout persists.
The warning badge shows how many cells have errored. Click it to jump to the cell with the error.
How many cells a run covers is a setting. Pick a Run mode from the dropdown next to Run all, and every subsequent run obeys it until you change it. The mode is expressed in terms of the dependencies described above: “upstream” means the cells the selected cell reads from, and “downstream” means the cells that read from it.
Auto: runs the selected cell and everything downstream of it, and refreshes any cells that had gone stale. Auto is the default, and a run in Auto never leaves a cell stale. In every other mode, a cell goes stale when something it depends on runs more recently than it did.
Cell + upstream: runs the cells the selected cell depends on, then the selected cell.
Cell only: runs the selected cell and nothing else.
Cell + downstream: runs the selected cell, then the cells that depend on it.
A handful of shortcuts are worth knowing. The Esc-prefixed ones are command-mode shortcuts:
pressing Esc leaves the cell’s editor while keeping the cell selected, so the keys that follow
act on the cell as a whole rather than on its text. Finish a sequence within two seconds, or it
resets.
| Shortcut | Action |
|---|---|
Shift + Enter | Run the selected cell using the active run mode, then select the next cell |
Cmd + Enter | Run the selected cell using the active run mode and stay on it |
Cmd + Click | Select multiple cells |
Esc then A | Insert a Python cell above the selected cell |
Esc then B | Insert a Python cell below the selected cell |
Esc then D, D | Delete the selected cell |
Esc then Cmd + Up | Move the selected cell up one position in the notebook |
Esc then Cmd + Down | Move the selected cell down one position in the notebook |
Esc then F, F | Open the selected cell full screen |
Esc then F, S | Format the selected SQL cell |
Two whole-notebook actions sit in the same place. Run all runs the notebook end to end, and Run all without cached results does the same with caching bypassed, so every SQL cell executes against its datasource.
Comments come at two levels. The speech-bubble button in the toolbar opens the notebook’s comments, and every cell carries its own comment button, which comments on that cell alone — so a notebook is something several people can work on together.
The dependencies button opens a Dependencies drawer on the right-hand side of the notebook — “Variable data-flow between cells, analyzed by the kernel.” It draws the notebook top to bottom as an interactive graph. The drawer is resizable, and it is recorded in the URL, so a refresh or a pasted link reopens it.
Most nodes are cells, drawn as a miniature preview of the source with the cell’s name, how long its last run took, and a pill for each variable the cell outputs. A ring around a node marks it as selected, succeeded, or errored. Input cells render their live control inside the node. A SQL cell’s datasource appears as its own node upstream of the cell, labeled with the datasource name. Edges are data flow, labeled with the actual variable names crossing them.
Selection syncs in both directions: selecting a cell pans the graph, and clicking a node reveals that cell in the notebook. A minimap, zoom to fit, and zoom to selection handle navigation in a large notebook.
The graph comes from static analysis of your Python source, run inside the kernel process. Cells are not executed to build it. Only module-level names are considered, so a name bound inside a function body or a class body does not become a dependency.
Two limits are worth knowing. The drawer needs a running notebook runtime: without one you see the cells but no edges, and the empty state says so — “Add runnable cells, then start the notebook runtime so the kernel can analyze their variable dependencies.” And the graph is built from the saved document, so an edit you have just typed is not reflected until autosave picks it up.
The share button creates read-only links to the notebook. Each link carries a label, visible only to you, which is how you tell links apart later when you go to revoke one.
Require a Chalk account is on by default. With it on, a viewer has to sign in and already have read access to the environment — the link points them at the notebook, it does not grant access on its own. With it off, anyone holding the URL can open the notebook without an account, so treat the URL itself as the credential.
Each link has an expiry: 7, 30, or 90 days, or 1 year. The default is 30 days.
The URL is shown exactly once, when you create the link. Chalk stores only a hash of it and will not display it again, so copy it then — if you lose it, revoke the link and create a new one.
Active links lists every link the notebook has: its label, whether it requires sign-in or is public, when it expires, when it was last opened, and a Revoke button.
Whoever opens a link sees the notebook, including its cells and the results of the most recent run, but
cannot edit it, run it, read its secrets, or reach the app canvas. Interpolated Markdown renders
for them too, since resolved values are saved with cell output; see
Text and Markdown cells. Shared pages are set to noindex, so
search engines do not index them.
Runtime options that apply to the whole notebook can be found in the Notebook settings panel, which can be opened from the settings button in the toolbar. From there, you can:
The history button opens History & versions, one reverse-chronological timeline of what has happened to the notebook.
Recent runs appear in it, paginated behind Load more runs, each labeled by what the run covered (“Ran all cells”, “Ran cell + upstream”), along with its status, its duration, and who ran it. Open a run to see it cell by cell: per-cell status and duration, output and row counts, and the text of any error inline. Run history is retained for 30 days.
Cell edits share the same timeline, one row per cell, and open into a syntax-highlighted view of that cell’s source.