Skip to content

Application architecture

Molt is a three-layer desktop application built with Tauri v2.

The macOS WKWebView renders a React application written in TypeScript.

Its responsibilities include:

  • Rendering the four tabs, toolbar, cells, outputs, warnings, and settings form.
  • Holding notebook state in one Zustand store.
  • Editing Python with CodeMirror 6.
  • Applying the fixed CSS and syntax palette.
  • Coordinating cell execution and translating responses into output records.
  • Loading and debounce-saving durable cell source through Tauri commands.
  • Handling visible keyboard and pointer interactions.

The main window and settings window have separate HTML and React entry points in one Vite build.

The Rust layer owns capabilities that should not live in the WebView:

  • Reading and writing application files.
  • Resolving bundled resources.
  • Validating the Python executable.
  • Spawning, tracking, interrupting, restarting, stopping, and cleaning up child processes.
  • Serializing access to each process.
  • Creating the settings window and native menus.
  • Applying or clearing macOS vibrancy.
  • Exposing typed operations through Tauri’s invoke bridge.

The frontend never opens a Python pipe directly. It invokes Rust commands such as execute_cell, restart_kernel, and save_notebooks.

Each active tab runs the same bundled kernel_server.py under the configured interpreter.

The server:

  • Reads one JSON object per stdin line.
  • Executes code in a persistent globals dictionary.
  • Captures text output and ordinary tracebacks.
  • Writes one JSON response per stdout line.
  • Handles ping and namespace-reset protocol messages.
  • Installs a SIGINT handler.

The server imports only Python’s standard library, so Molt can start in a plain Python installation. User code can still import third-party packages installed in that interpreter.

Cell source in CodeMirror
→ frontend execution coordinator
→ Tauri invoke("execute_cell")
→ Rust per-tab request queue
→ newline-delimited JSON on child stdin
→ Python AST parse, exec, and optional final-expression eval
→ newline-delimited JSON on child stdout
→ Rust response deserialization
→ frontend output records and cell state

The Rust kernel manager stores the interpreter string when the app is set up. Saving TOML does not mutate that manager, so a relaunch is required.

Clear first stops the Rust-managed process, then replaces the tab with one empty cell and leaves it stopped. Restart the tab before running new code.

The frontend extracts only selected store fields before calling save_notebooks. Output and execution state never cross that persistence boundary.

The Python process’s stdin is already the transport. There is no separate frontend prompt protocol for input().

The current response contract carries text fields and a single output_type string. The frontend reserves an image type but does not render it, and the Python server never emits image payloads.

The Tauri configuration creates a visible, transparent, decorated main window. Rust builds standard Molt, File, Edit, and Window menus and creates the settings window on demand.

The app bundle also sets LSUIElement, which removes the Dock icon. The selected release does not create the tray icon or toggle path described in older project specifications; this mismatch is recorded in Current limitations.