Sandboxed Python interpreter for Dart and Flutter. Run Python from native, web, and mobile — one package, every platform.
Three API levels — from one-shot execution to full plugin sessions.
// Run Python and get the result final result = await Monty.exec('2 + 2'); print(result.value); // MontyInt(4)
// Variables, functions, classes persist across calls final repl = MontyRepl(); await repl.feed('x = 42'); await repl.feed('def double(n): return n * 2'); final r = await repl.feed('double(x)'); print(r.value); // MontyInt(84)
// Full plugin dispatch — template, messaging, sandboxing final session = ReplSession( plugins: [ DinjaTemplatePlugin(), MessageBusPlugin(), SandboxPlugin(platformFactory: () async => MontyFfi()), ], ); final r = await session.run( "tmpl_render(template='Hello {{ name }}!', context={'name': 'World'})", ); print(r.value); // 'Hello World!'
Functions, classes, closures, and heap objects survive across calls. No JSON serialization — the Rust interpreter maintains state natively.
Low-level REPL with feed() and
feedStart()/resume() for
host function dispatch.
High-level session combining REPL + plugin dispatch + event streaming. The recommended API.
Detects incomplete input (>>> vs
... prompts) for building REPL UIs.
Host functions that Python code can call. All plugins work
with both ReplSession and AgentSession.
Jinja2 template rendering. Variables, loops, conditionals, filters.
In-memory named message channels. Send, receive, peek, stats.
Spawn isolated child interpreters. Parallel execution, gather, plugin inheritance, grandchildren.
Configurable OS call providers for filesystem, time, and environment:
Read/write filesystem in memory. No host disk access.
Mount a host directory read-only into the sandbox.
Copy-on-write layer over a read-only base. Writes go to memory.
One package. Conditional imports select FFI or WASM at compile time.
Dart → dart:ffi → libdart_monty_native → Monty Rust interpreter
Desktop, server, mobile
Dart/JS → js_interop → Web Worker → Monty WASM
Browser (any modern browser)
DefaultMontyBridge orchestrates execution. Plugins register
host functions. When Python calls one, execution suspends, the bridge
dispatches to the handler, and resumes with the result. Every step
emits BridgeEvents for real-time UI updates.
All demos run in your browser via WebAssembly. No server required.
Interactive Python REPL with real plugins (template, message bus).
One-shot Python execution, error handling, external functions.
Python pathlib operations against in-memory VFS.
Stateful agent with plugins, telemetry, and event streaming.
350+ compatibility tests across 21 tiers.
Step-by-step sorting algorithm animations in Python.
dart pub add dart_monty
Works out of the box on macOS, Linux, and Windows. The Rust native library is built automatically via Dart's native assets hook.
Copy the WASM assets to your web directory:
cp packages/dart_monty_wasm/assets/dart_monty_bridge.js web/ cp packages/dart_monty_wasm/assets/dart_monty_worker.js web/ cp packages/dart_monty_wasm/assets/dart_monty_native.wasm web/
Serve with Cross-Origin-Opener-Policy: same-origin
and Cross-Origin-Embedder-Policy: require-corp headers
(required for SharedArrayBuffer).