SignalK Data Lab
SignalK Data Lab
Data notebooks, using Marimo and Python for DAG aware notebooks. Notebooks run entirely in the browser, using WebAssembly (WASM) to keep the server load minimal and best suited to Raspberry Pi, NanoPi etc servers.
It comes with several experiments, working notebooks that use different ways to pull selected paths out of the SignalK History API and demonstration of how the data can be tabluated, charted or otherwise analyzed.
[!TIP] Chrome is recommended for access, since Safari (iOS, macOS etc) will not load some of the resources required unless your SignalK server has a secure (
https) address, and can be much slower starting up. Alternatively, switch onsslin the SignalK settings - it will automatically redirect any links to the oldhttpaddress though you wll be bothered by certificate warnings unless go through the rigmarole of setting up proper cerificates.
Quick Start
- Install from the SignalK App Store
- Launch the Data Lab from the Webapps link on SignalK main menu
You’ll need a History Provider running to capture the SignalK data, such as signalk-parquet, signalk-to-influxdb2 or signalk-questdb. If you have Kip set up as a plotter, it can also act as a history provider. Without one of these, there’s nothing to be queried for data, only raw data files.
Learning about Notebooks
If you’re not familiar with Data Notebooks, try the Marimo Tutorials on YouTube, or the gallery of demonstration notebooks.
If you’re familiar with Jupyter, you’ll feel at home, although Marimo Notebooks are nicer, with dependency aware cells like Excel. They are also pure Python scripts under the hood, so easier to edit, refactor or execute from command line.
Simulating Data
SignalK has several simulator plugins that will generate navigation, environment and similar data. Its also easy to source real live weather data using plugins.
Pure Polars
The Analyze with Polars Dataframes notebook uses Polars (a modern Rust based iteration on pandas) to do all of the SignalK API integration and data manipulation.
Integrate with Ibis Framework
The SignalK Paths in Data Explorer with Ibis notebook, linked from the top of Data Lab, connects Ibis to the History API when it opens. You can then query SignalK data with Ibis expressions and browse it in marimo’s data browser. It takes a few seconds to load the first time.
[!WARNING] Histograms aren’t shown in the data browser for SignalK tables by default. Column stats (counts, missing values, min/max, averages) work, but the charts that need histograms are left out. To turn them on, install
duckdbfrom marimo’s package manager panel; it’s a sizeable download. Overall figures cover the last hour unless you filter ontimestamp.
Export with signalk-cli
The Analyze and Export with signalk-cli notebook, linked from the top of Data Lab, fetches history into a polars DataFrame with the signalk-cli Python API, and charts how much the boat’s position moved in each 15 minutes. You can also download the data as Feather or CSV, in the same format as the signalk-cli command line tool. Paths can be glob or regex patterns, e.g. navigation.*.
[!NOTE] It installs
signalk-cliwhen it opens, which takes a few seconds the first time.
SQL with DuckDB
The SQL with DuckDB notebook fetches history into a signalk_history table and queries it with SQL cells running DuckDB in the browser. Worked examples cover time bucketing, PIVOT, window functions for distance run, and ASOF JOIN to line up sensors that report at different rates. It can also query an uploaded CSV or Parquet file.
[!NOTE] DuckDB and the packages marimo loads alongside it are about 28 MB, so the first visit takes a while. The other notebooks don’t load DuckDB.
Live Stream With signalk-cli
The Live Stream With signalk-cli notebook subscribes to the SignalK delta stream and shows data as it arrives: a chart per path, redrawn every few seconds, and a table of the latest values. It uses the browser’s own WebSocket, since signalk-cli’s streaming client waits for each message in a way that would block the rest of the notebook in the browser. signalk-cli still builds the subscription and reads the messages. Only data received while the page is open is shown.
Each notebook’s opening cell lists the limitations of its approach.
Add Your Own Notebook
The Add Your Own Notebook explains how to save your own notebooks for reuse, within the more confining environment of client-side only Marimo.
Using an AI agent
Marimo’s External agents feature (a Labs feature, turned on in marimo’s settings) can connect Claude Code, Codex, Gemini or OpenCode to the notebook in the browser. It needs a terminal command to start a bridge, so it’s aimed at technical users for now:
npx stdio-to-ws "npx @zed-industries/claude-code-acp" --port 3017The notebook connects to the bridge on the same host name it was loaded from (ws://<host>:3017). If you open Data Lab from another machine, e.g. http://my-boat.local:3000, the bridge has to run on the SignalK server, with Node and a logged-in Claude Code there. You may see file system errors when the agent tries to read or write files, as the browser notebook has no files on disk for it to work with.
For a fuller setup, where the agent edits the notebook file and can see its live outputs, see Working with an AI agent under Development.
Development
Development environment requirements.
Linux Packages
- node
- librsvg2-bin
Also recommended
- signalk-cli Python CLI for exploring and extracting streaming and history daya
Local Execution
To run the notebook outside of SignalK / webbrowser context, use
uv venv .venvsource .venv/bin/activateuv pip install -r requirements.txtmarimo run notebooks/signalk.pyTo work on both the main notebook and the ibis-signalk dev.py notebook from one marimo server, use
SIGNALK_URL=http://my-boat.local:3000 npm run labmarimo’s home page lists both notebooks, and the environment has the packages each one needs.
Ibis and DuckDB
The ibis-signalk backend runs what it can on the SignalK server and computes simple overall figures (counts, sums, min/max, averages) locally with pyarrow. Queries beyond that, notably the histograms marimo’s data browser draws and any joins, need a local query engine, which comes from the optional DuckDB extra (ibis-signalk[duckdb]).
npm run labandpackages/ibis-signalk’suv runinclude DuckDB (via thedevdependency group), so histograms work there.- The browser notebook installs
ibis-signalkwithout DuckDB, to keep loading fast, so histograms aren’t shown for users running from SignalK unless they installduckdbfrom marimo’s package manager. The backend checks for DuckDB on each query, so that takes effect without reloading. - Without DuckDB, those queries raise
NotImplementedErrornaming the extra. marimo catches these and just leaves the chart out.
See packages/ibis-signalk/README.md for how queries are split between the server and local evaluation.
Every marimo notebook in notebooks/ is included in the WASM build: signalk.py (Analyze with Polars Dataframes) becomes the main Data Lab page (datalab.html), and each other notebook becomes <name>.html alongside it, sharing the same assets. index.html is a gallery with a card per notebook, generated by scripts/build-gallery.js from each notebook’s opening markdown cell (its # heading and first paragraph), so a new notebook appears there automatically. Link between them with relative links, e.g. [SignalK Paths in Data Explorer with Ibis](data_source_explorer.html).
The signalk-cli notebooks install signalk-cli>=3.0.0 in the browser with a plain micropip.install; its metadata leaves out zeroconf (mDNS discovery) under Pyodide. signalk-cli is exempt from the exclude-newer release cooldown, in both uv.toml and packages/ibis-signalk/pyproject.toml (which npm run lab runs under), so new releases of it can be used straight away.
To preview the WASM build in a browser, as SignalK would serve it, use
SIGNALK_URL=http://my-boat.local:3000 npm run previewThis builds public/ and serves it on http://localhost:8080 (override with PORT), proxying /signalk/* API calls to SIGNALK_URL (default http://localhost:3000). Use npm run preview:serve to skip the rebuild.
Working with an AI agent
[!NOTE] This setup is for developers working from a clone of this repo. For connecting an agent to the notebook launched from the SignalK Webapps panel, see Using an AI agent (advanced).
The notebooks are plain Python files, so any coding agent can edit them. The repo is set up for Claude Code, which can also see the live notebook’s outputs and errors.
-
Start the notebook with its agent connection enabled, pointing at your SignalK server:
Terminal window SIGNALK_URL=http://my-boat.local:3000 npm run agentThis opens the notebook for editing on http://localhost:2718, reloads it whenever the file changes on disk, and serves a marimo MCP server at http://localhost:2718/mcp/server.
-
In another terminal in the repo, start Claude Code with
claude. The MCP server is registered in .mcp.json, so the first time you’ll be asked to approve themarimoserver. Run/mcpto check it’s connected. -
Ask for changes in plain language, e.g. “add a chart of wind speed against boat speed”. Claude edits
notebooks/signalk.py, the browser tab updates, and Claude can read back cell outputs and errors from the running notebook.
Project settings in .claude/ run marimo check after every notebook edit and feed any problems back to Claude. notebooks/CLAUDE.md covers marimo’s rules and what works in the browser (WASM) build.
npm run agent turns off marimo’s access token so the MCP URL stays the same between runs. It only listens on localhost, but don’t run it on a shared machine.
Release
git tag -f latestnpm publish --tag latest --access publicLimitations
Libraries with compiled code (polars, DuckDB, pyarrow, numpy, pandas and others) run in the browser only as special emscripten (WebAssembly) builds, which usually trail the desktop releases, sometimes by many months. In September 2026, polars in the browser is 1.33 while desktop is 1.44, and pyarrow is 22 against 25. So the browser can lack newer features, and occasionally has bugs that are long fixed on desktop. Code that works in a desktop notebook may fail in Data Lab, and the reverse. This will ease as more projects publish WebAssembly builds of their own, especially now that PEP783 is accepted. Pure Python libraries aren’t affected.
The Marimo environment by default runs server-side, so this may be an option in future with this plugin, or packaged as a separate plugin. The main up-side of running server-side is not being constrained by using pyodide to run Python in the browser, which means latest versions of polars,duckdb etc are available and fewer gotchas. On the other hand, it means Python installed onto the SignalK server, and tiny pi servers on boats might not like the extra load.
Also Check Out
- signalk-cli - A Python based CLI for extracting data and exploring paths on the SignalK APIs, with output to CSV or Apache Arrow dataframe (Feather). Also useful as a Python API for your own code.
- More SignalK plugins from Rhizomatics including support for eInk shelf labels, Bluetti powerbanks, using Teltonika modems as SignalK notifiers, squelching noisy SignalK deltas and more.
- The Boat Tech Directory for the most comprehensive guide on the Internet to boat tech blogs, vendors, open source projects and more.