Lunatic is an Erlang-inspired runtime for WebAssembly

Lunatic logo


Lunatic is a universal runtime for fast, robust and scalable server-side applications. It's inspired by Erlang and can be used from any language that compiles to WebAssembly. You can read more about the motivation behind Lunatic here.

We currently provide libraries to take full advantage of Lunatic's features for:

If you would like to see other languages supported or just follow the discussions around Lunatic, join our discord server.

Supported features

  • Creating, cancelling & waiting on processes
  • Fine-grained process permissions
  • Process supervision
  • Channel based message passing
  • TCP networking
  • Filesystem access
  • Distributed nodes
  • Hot reloading


We provide pre-built binaries for Windows, Linux and macOS on the releases page.

On macOS you can also use Hombrew:

brew tap lunatic-solutions/lunatic
brew install lunatic

To build the project from source you will need to have rustup installed:

# Add wasm32 compilation target
rustup target add wasm32-unknown-unknown
# Clone the repository
git clone
# Jump into the cloned folder
cd lunatic
# Build and install Lunatic
cargo install --path .


After installation, you can use the lunatic binary to run WASM modules.

To learn how to build modules, check out language-specific bindings:


Lunatic's design is all about spawning super lightweight processes, also known as green threads or go-routines in other runtimes. Lunatic's processes are fast to create, have a small memory footprint and a low scheduling overhead. They are designed for massive concurrency. It's not uncommon to have hundreds of thousands of such processes concurrently running in your app.

Some common use cases for processes are:

  • HTTP request handling
  • Long running requests, like Websocket connections
  • Long running background tasks, like email sending
  • Calling untrusted libraries in an sandboxed environment


What makes the last use case possible are the sandboxing capabilities of WebAssembly. WebAssembly was originally developed to run in the browser and provides extremely strong sandboxing on multiple levels. Lunatic's processes inherit these properties.

Each process has its own stack, heap, and even syscalls. If one process fails, it will not affect the rest of the system. This allows you to create very powerful and fault-tolerant abstraction.

This is also true for some other runtimes, but Lunatic goes one step further and makes it possible to use C bindings directly in your app without any fear. If the C code contains any security vulnerabilities or crashes, those issues will only affect the process currently executing the code. The only requirement is that the C code can be compiled to WebAssembly.

It's possible to give per process fine-grained access to resources (filesystem, memory, network connections, ...). This is enforced on the syscall level.


All processes running on Lunatic are preemptively scheduled and executed by a work stealing async executor. This gives you the freedom to write simple blocking code, but the runtime is going to make sure it actually never blocks a thread if waiting on I/O.

Even if you have an infinite loop somewhere in your code, the scheduling will always be fair and not permanently block the execution thread. The best part is that you don't need to do anything special to achieve this, the runtime will take care of it no matter which programming language you use.


We intend to eventually make Lunatic completely compatible with WASI. Ideally, you could take existing code, compile it to WebAssembly and run on top of Lunatic; creating the best developer experience possible. We're not quite there yet.


Licensed under either of

at your option.

  • Replace tcp with quic for distributed nodes

    Replace tcp with quic for distributed nodes

    Use QUIC for node-to-node and node-to-control connections. On older Linux kernel, the s2n-quic crate didn't work (it wouldn't send more that ~2000 bytes) so now default is quinn. During registration, nodes generate a certificate signing request which is signed by a control node. To simplify testing, you can use the --test-ca command line flag which will simply use built-in certificate and keys (so this is only for testing!).

    For example:

    lunatic --control --control-server --no-entry --test-ca & # run the control server and node
    sleep 1
    lunatic --control  --node --no-entry --test-ca & # run some additional nodes
    lunatic --control  --node --no-entry --test-ca &
    lunatic --control  --node --no-entry --test-ca &
    sleep 1
    lunatic --control  --node --test-ca \
       "lunatic-rs/target/wasm32-wasi/release/examples/distributed.wasm" # run example from lunatic Rust binding repo

    The next step is to implement multiple streams and chunking of messages to enable bandwidth control.

    opened by kosticmarin 14
  • Multiple definition linker error on fresh install

    Multiple definition linker error on fresh install

    Just did a fresh install (literally installed rustup and did cargo install lunatic-runtime) and got this error:

    error: linking with `cc` failed: exit status: 1
      = note: "cc" "-m64" "/tmp/rustcrGJOdl/symbols.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.0.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.1.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.10.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.11.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.12.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.13.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.14.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.15.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.2.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.3.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.4.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.5.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.6.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.7.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.8.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.lunatic.c3e7b227-cgu.9.rcgu.o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9.3r91if9yi76wrqn7.rcgu.o" "-Wl,--as-needed" "-L" "/home/lotus/./.cargo/target/release/deps" "-L" "/home/lotus/./.cargo/target/release/build/psm-1a9a392a57de01c4/out" "-L" "/home/lotus/./.cargo/target/release/build/zstd-sys-c711d78fdd601bbc/out" "-L" "/home/lotus/./.cargo/target/release/build/wasmtime-fiber-c08d6472d90b0d6d/out" "-L" "/home/lotus/./.cargo/target/release/build/ittapi-rs-5ca8f1b2c40f97d0/out" "-L" "/home/lotus/./.cargo/target/release/build/wasmtime-runtime-de56bef3e6c7ff2d/out" "-L" "/home/lotus/./.cargo/target/release/build/wasmtime-runtime-fbf7fdfb213f8248/out" "-L" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/lotus/.cargo/target/release/deps/liblunatic_runtime-03b482a8a341c5d9.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_registry_api-1e61444b6b80ea92.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_version_api-8972a81873d5fb9e.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_messaging_api-8973855eb3f874fb.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_networking_api-db9986b2d19fd9a3.rlib" "/home/lotus/.cargo/target/release/deps/libasync_net-3559d62c20c0facd.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_process_api-3893312dfdbc7e68.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_wasi_api-be35f836107a8a56.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_wasi-8d3da9bc7099c9ba.rlib" "/home/lotus/.cargo/target/release/deps/libwasi_cap_std_sync-ccdd6ce5912e8f6c.rlib" "/home/lotus/.cargo/target/release/deps/libis_terminal-cdefa316b034f14c.rlib" "/home/lotus/.cargo/target/release/deps/libsystem_interface-064a28ad54ff9fc7.rlib" "/home/lotus/.cargo/target/release/deps/libcap_fs_ext-dd2a504a088f818c.rlib" "/home/lotus/.cargo/target/release/deps/libcap_time_ext-30a27455ee86913c.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_stdout_capture-9ca1092da368e24f.rlib" "/home/lotus/.cargo/target/release/deps/libwiggle-81d4626939e1a453.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime-033597db0ad5bdbc.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_jit-8bdd7f88efe79e9b.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_runtime-fe3c7d4426ae828c.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_jit_debug-7bc2b3b11f933251.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_environ-e48dd5dc617c9bf7.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_types-46c1019201b1c79a.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_entity-ef68ccc872e33696.rlib" "/home/lotus/.cargo/target/release/deps/libwitx-e56c979ba2606b44.rlib" "/home/lotus/.cargo/target/release/deps/libwast-3eea21d6eaf71c6d.rlib" "/home/lotus/.cargo/target/release/deps/libwasi_common-c0a6a1fcd14e68bf.rlib" "/home/lotus/.cargo/target/release/deps/libwiggle-87543ed5a5e08537.rlib" "/home/lotus/.cargo/target/release/deps/libtracing-ed2c73608e6bf01b.rlib" "/home/lotus/.cargo/target/release/deps/libtracing_core-1b7fe123d081d012.rlib" "/home/lotus/.cargo/target/release/deps/libcap_rand-bb7a4e218386760d.rlib" "/home/lotus/.cargo/target/release/deps/libcap_std-02d92acada068d8e.rlib" "/home/lotus/.cargo/target/release/deps/libcap_primitives-b530c7fae98fea43.rlib" "/home/lotus/.cargo/target/release/deps/libipnet-806dc9ccd737a847.rlib" "/home/lotus/.cargo/target/release/deps/libmaybe_owned-0f11d887b12748a7.rlib" "/home/lotus/.cargo/target/release/deps/libfs_set_times-f77cd1885ae19e8a.rlib" "/home/lotus/.cargo/target/release/deps/libio_extras-ee128db75c7adde4.rlib" "/home/lotus/.cargo/target/release/deps/libambient_authority-d4bdae4a8ed2754e.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_error_api-934a9b0973dc971d.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_common_api-314691bd7bfa9905.rlib" "/home/lotus/.cargo/target/release/deps/liblunatic_process-a2cc9825c1de9f34.rlib" "/home/lotus/.cargo/target/release/deps/libtokio-92272a32569d64b3.rlib" "/home/lotus/.cargo/target/release/deps/libuuid-708e2e8467e131af.rlib" "/home/lotus/.cargo/target/release/deps/libhash_map_id-554c77a4ecdc0aa7.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime-ea0c1857fe63eea1.rlib" "/home/lotus/.cargo/target/release/deps/libwat-767ed27e4d0f39bb.rlib" "/home/lotus/.cargo/target/release/deps/libwast-666682f174472117.rlib" "/home/lotus/.cargo/target/release/deps/libwasm_encoder-416e4cc50ed2759e.rlib" "/home/lotus/.cargo/target/release/deps/libleb128-ae0d8a529842c665.rlib" "/home/lotus/.cargo/target/release/deps/libunicode_width-c420ccdeb5fd199d.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_cranelift-16d81e84c82b06bb.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_native-39961aefe356fa20.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_wasm-87b18b72bcf23d29.rlib" "/home/lotus/.cargo/target/release/deps/libitertools-f2ad876a50acb2d0.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_frontend-d4b286c7d0529133.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_codegen-8c99c7223f1061ec.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_codegen_shared-35daceea25e73e8e.rlib" "/home/lotus/.cargo/target/release/deps/libregalloc-0e9b321300b6cf62.rlib" "/home/lotus/.cargo/target/release/deps/librustc_hash-25b604ccd7f235a3.rlib" "/home/lotus/.cargo/target/release/deps/libsmallvec-7914fba9a73e7b81.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_bforest-3c7bebec176e3697.rlib" "/home/lotus/.cargo/target/release/deps/libpsm-c1850cb83d862cfd.rlib" "/home/lotus/.cargo/target/release/deps/librayon-477b931e8bf78a02.rlib" "/home/lotus/.cargo/target/release/deps/librayon_core-72994d7e71bf287b.rlib" "/home/lotus/.cargo/target/release/deps/libcrossbeam_deque-7d1ca271d1deba55.rlib" "/home/lotus/.cargo/target/release/deps/libcrossbeam_epoch-10c58bc96126443c.rlib" "/home/lotus/.cargo/target/release/deps/libscopeguard-91dcd07744d1313e.rlib" "/home/lotus/.cargo/target/release/deps/libcrossbeam_channel-2a3b363da691a57a.rlib" "/home/lotus/.cargo/target/release/deps/libeither-5ca4aa86e514235d.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_jit-96ca4fa525d86e92.rlib" "/home/lotus/.cargo/target/release/deps/libcpp_demangle-278605d5690f22e4.rlib" "/home/lotus/.cargo/target/release/deps/libittapi_rs-c00ba84c2d5000db.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_cache-50e88e8d11c2bed2.rlib" "/home/lotus/.cargo/target/release/deps/libbase64-fcaf4d86daae2873.rlib" "/home/lotus/.cargo/target/release/deps/libbincode-f2d2a4b3fd7631b4.rlib" "/home/lotus/.cargo/target/release/deps/libfile_per_thread_logger-687aae944fad5ab8.rlib" "/home/lotus/.cargo/target/release/deps/libenv_logger-15c42bed0f789174.rlib" "/home/lotus/.cargo/target/release/deps/libhumantime-aad0b24b99ec8652.rlib" "/home/lotus/.cargo/target/release/deps/libregex-4cca14c248349eff.rlib" "/home/lotus/.cargo/target/release/deps/libaho_corasick-c0eef6fa9f7df825.rlib" "/home/lotus/.cargo/target/release/deps/libregex_syntax-9d6db44b9c0cec5a.rlib" "/home/lotus/.cargo/target/release/deps/libtoml-10c4aa57eae7f6b1.rlib" "/home/lotus/.cargo/target/release/deps/libzstd-83d7d508ba173572.rlib" "/home/lotus/.cargo/target/release/deps/libzstd_safe-acfa6dc221366795.rlib" "/home/lotus/.cargo/target/release/deps/libzstd_sys-045b632b830e0364.rlib" "/home/lotus/.cargo/target/release/deps/libdirectories_next-507ee0ed3eccafc8.rlib" "/home/lotus/.cargo/target/release/deps/libdirs_sys_next-6fe71a06e3d6e078.rlib" "/home/lotus/.cargo/target/release/deps/libsha2-062044c1a7e84a19.rlib" "/home/lotus/.cargo/target/release/deps/libcpufeatures-8fe634dad9fe1a55.rlib" "/home/lotus/.cargo/target/release/deps/libopaque_debug-30bca6372ba015ab.rlib" "/home/lotus/.cargo/target/release/deps/libdigest-fc38524b5b316935.rlib" "/home/lotus/.cargo/target/release/deps/libblock_buffer-24e527d6b3ba59f3.rlib" "/home/lotus/.cargo/target/release/deps/libgeneric_array-9c741897873636cd.rlib" "/home/lotus/.cargo/target/release/deps/libtypenum-7c26863d84f6e6dc.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_runtime-9de67d4b5e08a324.rlib" "/home/lotus/.cargo/target/release/deps/libmemfd-fc79cb4eca6dc178.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_fiber-8884a1857f825d91.rlib" "/home/lotus/.cargo/target/release/deps/libregion-291310fb14dd551a.rlib" "/home/lotus/.cargo/target/release/deps/libbacktrace-9b566d370f48425e.rlib" "/home/lotus/.cargo/target/release/deps/libminiz_oxide-05774ee8e8228cf8.rlib" "/home/lotus/.cargo/target/release/deps/libadler-93a3aafa08255620.rlib" "/home/lotus/.cargo/target/release/deps/libobject-83123cd3489d21cf.rlib" "/home/lotus/.cargo/target/release/deps/libaddr2line-0476ba4c0dd5ab5f.rlib" "/home/lotus/.cargo/target/release/deps/librustc_demangle-f1c891421c8c36f9.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_jit_debug-5fc271d9335edbd9.rlib" "/home/lotus/.cargo/target/release/deps/librustix-59867dbcc714b349.rlib" "/home/lotus/.cargo/target/release/deps/libitoa-f5762eaa3bbe4bb3.rlib" "/home/lotus/.cargo/target/release/deps/libio_lifetimes-e8316e8e64156a97.rlib" "/home/lotus/.cargo/target/release/deps/liblinux_raw_sys-0dbf178634e06305.rlib" "/home/lotus/.cargo/target/release/deps/liblazy_static-53863b77cbb23189.rlib" "/home/lotus/.cargo/target/release/deps/librand-6036e47689e64144.rlib" "/home/lotus/.cargo/target/release/deps/librand_chacha-db67fd8528e54369.rlib" "/home/lotus/.cargo/target/release/deps/libppv_lite86-8e5c7f9497a3dd4b.rlib" "/home/lotus/.cargo/target/release/deps/librand_core-52d8c705db2cff2c.rlib" "/home/lotus/.cargo/target/release/deps/libgetrandom-3c2ca12d65a651c6.rlib" "/home/lotus/.cargo/target/release/deps/libmemoffset-b6667f27ce16838c.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_environ-78b0c86c77eb3957.rlib" "/home/lotus/.cargo/target/release/deps/libgimli-8435c1db7225820f.rlib" "/home/lotus/.cargo/target/release/deps/libfallible_iterator-702ae43ad81c13a3.rlib" "/home/lotus/.cargo/target/release/deps/libstable_deref_trait-b556d4b03bdd9327.rlib" "/home/lotus/.cargo/target/release/deps/libmore_asserts-d0ccdea0f8ecf3d1.rlib" "/home/lotus/.cargo/target/release/deps/libwasmtime_types-3fece135773c39c7.rlib" "/home/lotus/.cargo/target/release/deps/libwasmparser-e23c81319f7ad0b5.rlib" "/home/lotus/.cargo/target/release/deps/libcranelift_entity-f63a4ae4fb84ace4.rlib" "/home/lotus/.cargo/target/release/deps/libtarget_lexicon-5f61c9ae748e07bb.rlib" "/home/lotus/.cargo/target/release/deps/libthiserror-3d2247a492ac88e2.rlib" "/home/lotus/.cargo/target/release/deps/libobject-59b66ecf5143d8bb.rlib" "/home/lotus/.cargo/target/release/deps/libcrc32fast-d3deb61882f3577f.rlib" "/home/lotus/.cargo/target/release/deps/libasync_std-ae48b8945ad433d2.rlib" "/home/lotus/.cargo/target/release/deps/libasync_global_executor-92457259c5f84258.rlib" "/home/lotus/.cargo/target/release/deps/libblocking-ef890de4d4f992eb.rlib" "/home/lotus/.cargo/target/release/deps/libatomic_waker-a2c9e3e5190b8f84.rlib" "/home/lotus/.cargo/target/release/deps/libasync_executor-6652838247d0912d.rlib" "/home/lotus/.cargo/target/release/deps/libasync_task-f99b00f7841c0ef2.rlib" "/home/lotus/.cargo/target/release/deps/libcrossbeam_utils-0d819927e6db9495.rlib" "/home/lotus/.cargo/target/release/deps/libasync_process-522042b57ee93762.rlib" "/home/lotus/.cargo/target/release/deps/libsignal_hook-d0d0aedc771ceed5.rlib" "/home/lotus/.cargo/target/release/deps/libsignal_hook_registry-9f20c86a3948a02d.rlib" "/home/lotus/.cargo/target/release/deps/libasync_io-2f26ec70ac164425.rlib" "/home/lotus/.cargo/target/release/deps/libslab-3b80d8f761e90519.rlib" "/home/lotus/.cargo/target/release/deps/libpolling-f47aa9b5e6d6cf56.rlib" "/home/lotus/.cargo/target/release/deps/libsocket2-9152082a97e45544.rlib" "/home/lotus/.cargo/target/release/deps/libfutures_lite-93e2c7d0e72bf6b9.rlib" "/home/lotus/.cargo/target/release/deps/libmemchr-82ac28409f03df8b.rlib" "/home/lotus/.cargo/target/release/deps/libfastrand-deacf0164f3f7777.rlib" "/home/lotus/.cargo/target/release/deps/libwaker_fn-c20a05be103f4ee6.rlib" "/home/lotus/.cargo/target/release/deps/libparking-aaad4e9e88c721ec.rlib" "/home/lotus/.cargo/target/release/deps/libfutures_io-52ff59f513108bf0.rlib" "/home/lotus/.cargo/target/release/deps/libasync_channel-8523c3d5861ae4ce.rlib" "/home/lotus/.cargo/target/release/deps/libconcurrent_queue-2e508a8cd80809a1.rlib" "/home/lotus/.cargo/target/release/deps/libcache_padded-6458f3a9c373fa67.rlib" "/home/lotus/.cargo/target/release/deps/libasync_lock-8f2c8635bce6ece5.rlib" "/home/lotus/.cargo/target/release/deps/libevent_listener-46bb95ba4f92548a.rlib" "/home/lotus/.cargo/target/release/deps/libpin_project_lite-fde9e586f72c7c9b.rlib" "/home/lotus/.cargo/target/release/deps/libpin_utils-d6f018c56e01fe8c.rlib" "/home/lotus/.cargo/target/release/deps/libfutures_core-cc3f95c48f424582.rlib" "/home/lotus/.cargo/target/release/deps/libkv_log_macro-6221e6cfd40dc6bf.rlib" "/home/lotus/.cargo/target/release/deps/liblog-c11df26e7280ff73.rlib" "/home/lotus/.cargo/target/release/deps/libvalue_bag-b00a6f9af3abe045.rlib" "/home/lotus/.cargo/target/release/deps/libdashmap-ff8a4fa275f3a281.rlib" "/home/lotus/.cargo/target/release/deps/libnum_cpus-aea3dd5006fc8173.rlib" "/home/lotus/.cargo/target/release/deps/libcfg_if-ae9304d0b4aa9b61.rlib" "/home/lotus/.cargo/target/release/deps/libclap-baf9e6a6210992bb.rlib" "/home/lotus/.cargo/target/release/deps/libatty-ae5489d74ff09fd2.rlib" "/home/lotus/.cargo/target/release/deps/liblibc-6fce902828354ed3.rlib" "/home/lotus/.cargo/target/release/deps/libstrsim-1690bcaa0e46981f.rlib" "/home/lotus/.cargo/target/release/deps/libtermcolor-1e3f58e07a9169f7.rlib" "/home/lotus/.cargo/target/release/deps/libtextwrap-ee4bb8f572f17702.rlib" "/home/lotus/.cargo/target/release/deps/libclap_lex-69bd0881b1817e9c.rlib" "/home/lotus/.cargo/target/release/deps/libos_str_bytes-606bef0f72d16215.rlib" "/home/lotus/.cargo/target/release/deps/libindexmap-1a8bddde9a1abfd0.rlib" "/home/lotus/.cargo/target/release/deps/libhashbrown-a583d5d85e228ff2.rlib" "/home/lotus/.cargo/target/release/deps/libserde-e2b53d50a972090e.rlib" "/home/lotus/.cargo/target/release/deps/libbitflags-d4b6a1deff53cdce.rlib" "/home/lotus/.cargo/target/release/deps/libonce_cell-c3b9943d0c9975b4.rlib" "/home/lotus/.cargo/target/release/deps/libanyhow-4a2af6bbff1dbb5b.rlib" "-Wl,--start-group" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-7ca39ac42651c3df.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-62c6d032818141a1.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libobject-50484fc03eb1eb5b.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libmemchr-758be083b246d9c6.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libaddr2line-3cdf9a3c68f76e2d.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libgimli-3a1b74821c25a0e1.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_demangle-e046d82ebd84bb7f.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd_detect-a61cdd33cfa8394f.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libhashbrown-410c38f8df854235.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libminiz_oxide-f79d7458e122215f.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libadler-7d24b750ce5b22e8.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_alloc-4c2aa1ea3133ab73.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-41220dc85a7f114f.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcfg_if-230d004276c898f9.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-03ae30169a5438be.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-6f82c44b7818af35.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_std_workspace_core-1a0b7681f7efa789.rlib" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-83735dd4dae9b02c.rlib" "-Wl,--end-group" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-385029872275478f.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "/opt/rust/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "/home/lotus/./.cargo/target/release/deps/lunatic-c7112cfc902fd5e9" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro,-znow" "-Wl,-O1" "-nodefaultlibs"
      = note: /usr/bin/ld: /home/lotus/.cargo/target/release/deps/libwasmtime_runtime-9de67d4b5e08a324.rlib(wasmtime_runtime-9de67d4b5e08a324.wasmtime_runtime.1178b907-cgu.4.rcgu.o): in function `resolve_vmctx_memory':
              wasmtime_runtime.1178b907-cgu.4:(.text.resolve_vmctx_memory+0x0): multiple definition of `resolve_vmctx_memory'; /home/lotus/.cargo/target/release/deps/libwasmtime_runtime-fe3c7d4426ae828c.rlib(wasmtime_runtime-fe3c7d4426ae828c.wasmtime_runtime.2863bd74-cgu.11.rcgu.o):wasmtime_runtime.2863bd74-cgu.11:(.text.resolve_vmctx_memory+0x0): first defined here
              /usr/bin/ld: /home/lotus/.cargo/target/release/deps/libwasmtime_runtime-9de67d4b5e08a324.rlib(wasmtime_runtime-9de67d4b5e08a324.wasmtime_runtime.1178b907-cgu.4.rcgu.o): in function `resolve_vmctx_memory_ptr':
              wasmtime_runtime.1178b907-cgu.4:(.text.resolve_vmctx_memory_ptr+0x0): multiple definition of `resolve_vmctx_memory_ptr'; /home/lotus/.cargo/target/release/deps/libwasmtime_runtime-fe3c7d4426ae828c.rlib(wasmtime_runtime-fe3c7d4426ae828c.wasmtime_runtime.2863bd74-cgu.11.rcgu.o):wasmtime_runtime.2863bd74-cgu.11:(.text.resolve_vmctx_memory_ptr+0x0): first defined here
              /usr/bin/ld: /home/lotus/.cargo/target/release/deps/libwasmtime_runtime-9de67d4b5e08a324.rlib(wasmtime_runtime-9de67d4b5e08a324.wasmtime_runtime.1178b907-cgu.4.rcgu.o): in function `set_vmctx_memory':
              wasmtime_runtime.1178b907-cgu.4:(.text.set_vmctx_memory+0x0): multiple definition of `set_vmctx_memory'; /home/lotus/.cargo/target/release/deps/libwasmtime_runtime-fe3c7d4426ae828c.rlib(wasmtime_runtime-fe3c7d4426ae828c.wasmtime_runtime.2863bd74-cgu.11.rcgu.o):wasmtime_runtime.2863bd74-cgu.11:(.text.set_vmctx_memory+0x0): first defined here
              collect2: error: ld returned 1 exit status
    error: could not compile `lunatic-runtime` due to previous error
    error: failed to compile `lunatic-runtime v0.9.0`, intermediate artifacts can be found at `/home/lotus/./.cargo/target`

    Running on a clean Pop OS:

    ❯ lsb_release -a && uname -a
    No LSB modules are available.
    Distributor ID:	Pop
    Description:	Pop!_OS 22.04 LTS
    Release:	22.04
    Codename:	jammy
    Linux pop-os 5.17.15-76051715-generic #202206141358~1655919116~22.04~1db9e34 SMP PREEMPT Wed Jun 22 19 x86_64 x86_64 x86_64 GNU/Linux

    I haven't used wasmtime before lunatic and it does a great job at keeping it hidden away from me so I don't know how to even try to debug this.

    opened by Fryuni 12
  • Shared compiled wasm modules

    Shared compiled wasm modules

    Allows compiled wasm modules to be shared between the same node.

    Two new host functions were added:

    • "lunatic::message::push_module"
    • "lunatic::message::take_module"

    Modules are no longer pre-linked. The upside of this is that WasmtimeCompiledModule no longer has a generic (which removes generics from many other places too), but the downside is that it might be a little less performant.

    I'll try to get some benchmarks done to test this PR's performance compared to before.

    opened by tqwewe 8
  • Switch to from async_std

    Switch to from async_std

    I would like to propose switching back to as lunatic's async executor.

    Many projects are moving away from async_std ( and some "high profile" rust community members are advocating for everyone to just adopt tokio. There are many other good reasons to switch to tokio, like more active development and bigger community & library support.

    We are already using tokio's select! macro and have it as a dependency. The only reason why I decided to switch to async_std is the fact that async_std's TcpStream is Clone. This allows us to expose a simple primitive to guest code that can be shared between processes. And having one process read from the TcpStream and another write to it is a common pattern in lunatic.

    As I hinted already in this comment, we could introduce a split function and ReadTcpStream & WriteTcpStream primitive to work around this. This would also provide us with more security, because you can't accidentally write to WriteTcpStream from 2 processes (exclusively owned). At the same time, many (all?) other io_uring based async runtimes also provide this split approach to TcpStreams and introducing this change wouldn't stop us from adopting another async executor in the future.

    opened by bkolobara 6
  • Refactor into workspace

    Refactor into workspace

    It might be worth refactoring Lunatic so that the API is defined in separate crates, which can then be activated through feature flags (so that we can add more experimental APIs that can be excluded from more stable builds).

    It might also be worth bringing the rust-lib into the main repo, so that it can be tested in tandem with the runtime.

    opened by teymour-aldridge 6
  • Feature/reply


    Add simple support for message id which are local to the running process and reply ids which are set by Lunatic (and not guest) based on message ids. The idea is that the sender can match against reply id and a sent message (sending now returns message id).

    opened by withtypes 6
  • Implement a Stacked Scratch Area

    Implement a Stacked Scratch Area

    This allows for messages to be stacked. Calling create_message() adds a message onto the stack, and any message modificatiosn modify the message on the top of the stack.

    This is an experiment per a discussion I had with @bkolobara .

    opened by jtenner 4
  • Add a testing framework to the vm

    Add a testing framework to the vm

    After trying to find a nice testing solution for code running on lunatic (see over the last few months, I concluded that it is probably impossible to do so without direct support from the vm.

    There is an issue tracking custom testing frameworks for Rust, but it didn't see almost any progress in the last 5 years and I don't see this changing soon. Other solutions relay on libraries like inventory that require specific life-before-main solutions that don't work in Wasm code. This basically leaves us with only one way forward, provide a testing mode inside of the vm and decorate Rust guest code with a custom macro (#[lunatic::test]) that exposes tests to the vm.

    I would at the same time use this opportunity to introduce sub-commands in the CLI. E.g lunatic run file.wasm, lunatic test file.wasm, and maybe some diagnostics in the future lunatic inspect file.wasm. If you run lunatic run file.wasm the vm would behave like it did until now. Load the wasm file, look for a _start function, spawn a process from it and wait until the process finishes.

    The new testing mode would behave differently, it would look up all exported functions starting with __lunatic_test_ and spawn a process from them. If the process finishes without trapping the test would be marked as OK, otherwise as FAIL. The testing mode would expose a few additional host functions to allow the tested process to name the test and change the configuration (should_trap=true?). This would automatically parallelise all test execution and let the schedule auto balance any waiting. This would also just be the starting point (unit tests), later we can extend the functionality to cover more complicated testing scenarios.

    Maybe we should also provide some heuristics for automatically detecting the testing mode? Rust guest code can configure only one runner (e.g. lunatic run) that is also used when you run cargo test. It could be useful for the lunatic command to default to run mode, except if it detects some environment variables that indicate tests running. This would provide a seamless integration with cargo test & cargo run for Rust's use case.

    I'm wonderring how other languages, like AssemblyScript could integrate with this? From what I have seen, AssemblyScript doesn't have a standardised test runner. Having a lunatic custom one wouldn't impact the developer experience? @jtenner

    opened by bkolobara 4
  • Implement udp functions

    Implement udp functions

    This pull request is an attempt to add support for UdpSocket to lunatic. The work I suspect needs to be done:

    • [x] udp_bind to address with exact same signature as tcp_bind
    • [x] udp_connect
    • [x] drop_udp_socket
    • [x] clone_udp_socket
    • [x] udp_send_to
    • [x] udp_read
    • [x] set_udp_socket_broadcast
    • [x] get_udp_socket_broadcast
    • [x] set_udp_socket_ttl
    • [x] get_udp_socket_ttl

    and in the mailbox namespace

    • [x] push_udp_socket
    • [x] take_udp_socket

    Looks like udp_bind wasn't so bad.


    Rename the udp_read function to udp_receive, to stay consistent in the naming.

    • [x] Add the udp_receive_from function, currently you can udp_send_to without connecting, but can't receive.
    • [x] Add udp_send, same reason as the previous point. You should be able to send when connected.
    • [ ] Add some documentation that udp_send & udp_receive will fail if you didn't call udp_connect before.
    • [ ] Add all the new host functions to this test file:
    opened by jtenner 4
  • Add version API.

    Add version API.

    This provides a way to obtain the version of the runtime. This is useful because if the client and host are of different versions, then this could cause unsafe behavior.

    • lunatic::version::major - returns an integer containing the major version of the runtime
    • lunatic::version::minor - returns an integer containing the minor version of the runtime
    • lunatic::version::patch - returns an integer containing the patch version of the runtime
    opened by teymour-aldridge 4
  • Udate wasmtime resolving breaking change

    Udate wasmtime resolving breaking change

    Was trying to install lunatic and it was complaining about not being able to pick the right wasmtime version so updated it and resolved the breaking change that the new version has which doesn't seem to have any impact.

    opened by olanod 4
  • Add trace methods

    Add trace methods

    These functions should help developers of testing libraries to obtain stack traces. This is a draft pull request because I don't know how effective this is.

    opened by jtenner 0
  • Sqlite support

    Sqlite support

    Extended the excellent work of @jtenner and built rust guest bindings against this branch. I'd keep this open for now because I want to build a larger interface for better integration with ORMs etc.

    It's usable for testing though. If you add this FFI in the lunatic-rs lib:

    pub mod sqlite {
        #[link(wasm_import_module = "lunatic::sqlite")]
        extern "C" {
            pub fn open(path: *const u8, path_len: usize, conn_id: *mut u32) -> u64;
            pub fn query_prepare(
                conn_id: u64,
                query_str: *const u8,
                query_str_len: u32,
                len_ptr: *mut u32,
                resource_id: *mut u32,
            ) -> ();
            pub fn query_result_get(resource_id: u64, write_buf: *const u8, write_buf_len: u32) -> ();
            pub fn drop_query_result(resource_id: u64) -> ();
            pub fn execute(conn_id: u64, exec_str: *const u8, exec_str_len: u32) -> u32;

    Then add a couple of convenience wrapper methods for the host functions:

    use crate::host::api;
    use std::path::Path;
    pub fn open(path: &Path) -> u64 {
        let conn_id = 0u64;
        let path_str = path.to_str().unwrap();
        unsafe {
            api::sqlite::open(path_str.as_ptr(), path_str.len(), &mut (conn_id as u32));
    /// returns a tuple consisting of the length of data written to the buf
    /// as well as the resource id
    pub fn query_prepare(conn_id: u64, query: &str) -> (u32, u64) {
        let mut len = 0u32;
        let resource_id = 0u64;
        unsafe {
                query.len() as u32,
                &mut len,
                &mut (resource_id as u32),
            (len, resource_id)
    pub fn query_result_get(resource_id: u64, buf: &mut [u8]) -> () {
        unsafe {
            api::sqlite::query_result_get(resource_id, buf.as_ptr(), buf.len() as u32);
    pub fn drop_query_result(resource_id: u64) -> () {
        unsafe {
    pub fn execute(conn_id: u64, exec_str: &str) -> u32 {
        unsafe { api::sqlite::execute(conn_id, exec_str.as_ptr(), exec_str.len() as u32) }

    You'll be able to run this example:

    use lunatic::sqlite;
    use std::path::Path;
    fn main() {
        println!("Opening connection to sqlite...");
        let db = sqlite::open(Path::new("./test_db"));
        println!("Connected to sqlite");
        let x = sqlite::execute(db, "CREATE TABLE IF NOT EXISTS movie(title, year, score)");
        println!("RESULT OF EXEC {:?}", x);
        INSERT INTO movie VALUES
            ('Monty Python and the Holy Grail', 1975, 8.2),
            ('And Now for Something Completely Different', 1971, 7.5)",
        let (len, result_id) = sqlite::query_prepare(db, "SELECT title, score FROM movie");
        let mut buf = vec![0u8; len as usize];
        sqlite::query_result_get(result_id.into(), &mut buf);
        println!("RECEIVED DATA FROM SQLITE {:?}", String::from_utf8(buf));
    opened by SquattingSocrates 11
  • Native plugins support

    Native plugins support

    Adds support for native plugins (.dll/.so/.dylib) which can be loaded with the --plugins flag.

    An example exists in the examples/ directory, along with some docs on running the example.

    Related to (nice)

    opened by tqwewe 2
  • curious, when hot reload will be avail?

    curious, when hot reload will be avail?

    great work!

    1. curious, when hot reload will be available?
    2. is it a good replacement for erlang after hot reload is available? (need websocket, telecom, fault tolenerant chat app kind of thing)
    3. how's the benchmark like against erlang?
    opened by ultperf 1
  • Spawning operating system processes

    Spawning operating system processes

    Sometimes it's useful to just offload the workload to some command line tool. Under the hood, it would just use Rust's process::Command.

    We would also need an additional configuration option to add an allow-list for specific processes. By default it would be empty.

    It would also be useful to capture the status and output.

    opened by bkolobara 4
  • v0.12.0(Nov 15, 2022)


    • Compiled modules can now be sent between processes (@tqwewe)
    • TLS support added (@SquattingSocrates)
    • Metrics added to the VM (@HurricanKai)
    • Improvements to distributed lunatic (@kosticmarin)
    • Distributed metadata added (@kosticmarin)
    • Improved error reporting (@alecthomas)
    • TCP read/write timeouts added back (@SquattingSocrates)
    • Time API moved from async-std to (@MarkintoshZ)
    • FIX: Sender can be dropped during execution (@HurricanKai)
    • FIX: Dependency issues (@pinkforest)
    Source code(tar.gz)
    Source code(zip)
    lunatic-linux-amd64.tar.gz(7.78 MB)
    lunatic-macos-universal.tar.gz(11.73 MB) MB)
  • v0.10.1(Sep 26, 2022)

  • v0.10.0(Aug 3, 2022)


    This release is bringing back distributed lunatic 🎉! But this time it's using QUIC as the protocol for node to node communication. Check out this example on how to spawn processes on remote nodes.

    Other changes

    • Switched from async_std to tokio (@kosticmarin)
    • kill host function added (@zhamlin)
    • send_after & cancel_timer host functions added (@zhamlin)
    • changed timeout type in host functions from u32 to u64
    • timeout parameters are removed for networking read/write calls

    Changes in lunatic-rs

    • UDP support added (@pinkforest)
    • #[abstract_process] macro added (@MarkintoshZ)
    • Added support for distributed lunatic (@withtypes)
    • FuncRef support added as a safe interface to send function pointers between processes (@zhamlin)
    • block_until_shutdown method added to Supervisor (@MarkintoshZ)
    • OneForAll and RestForOne supervisor strategies added (@MarkintoshZ)
    • Debug, Hash and Eq traits added for a few types (@MarkintoshZ and @thehabbos007)
    • All serializers (except the default bincode) are now behind a feature flag.

    And a bunch of other smaller performance and bug fixes!

    Source code(tar.gz)
    Source code(zip)
    lunatic-linux-amd64.tar.gz(7.50 MB)
    lunatic-macos-universal.tar.gz(11.04 MB) MB)
  • v0.9.0(Apr 25, 2022)

  • v0.7.5(Jan 20, 2022)

  • v0.7.4(Jan 15, 2022)

  • v0.7.0(Dec 1, 2021)


    This is the first release that supports connecting multiple lunatic instances together :tada:. From the perspective of developers that are targeting lunatic there should be no difference between locally running processes or remote ones. Spawning and sending messages to them uses the same APIs.

    To turn your local lunatic instance into a distributed node you will need to provide a unique name and socket to bind to. Both of them can be set through the cli.


    To start a distributed node you can run:

    lunatic --node --node-name foo --no-entry

    This starts a lunatic node with the name foo listening the specified port. The --no-entry flag means that this node doesn't have a start function, it will just block forever.

    If you want to connect to a node you can pass in the --peer flag:

    lunatic --node localhost:8334 --node-name bar --peer file.wasm

    Once you connect to one node all others known ones will be dynamically discovered.

    Usage from guest code (Rust)

    A great property of lunatic is that much of the functionality provided by the runtime is directly exposed to the code running inside of it. This allows you to dynamically load WebAssembly code from already running WebAssembly code, or to create sandboxed environments to execute code on the fly.

    The abstraction of an Environment, that we used previously to sandbox and limit process resources, fits perfectly into the world of distributed lunatic. Every time you create a new Environment you need to explicitly add Wasm Modules to it, because we may need to JIT re-compile the module with the new limitations that have been set. Spawning a process from the same function in different Environments may use different machine generated code to be more efficient in regards to the provided sandbox.

    Now that a Module may be sent over the network to a computer running a different operating system or even using a different CPU architecture, no changes need to be done to this already existing pattern inside of lunatic.

    Here is an example of using the new API from Rust guest code:

    use lunatic::{Config, Environment, Mailbox};
    fn main(_: Mailbox<()>) {
      // Give full access to the remote environment.
      let mut config = Config::new(0xA00000000, None);
      // Create a new environment on the remote node with the name "foo"
      let mut env = Environment::new_remote("foo", config).unwrap();
      // Add the currently running module to the environment.
      // This allows us to spawn a process from a closure, because the remote module will have the same
      // bytecode available.
      let module = env.add_this_module().unwrap();
      // Spawn a process on a remote machine as you would do it locally.
      let _ = module.spawn(|_: Mailbox<()>| println!("Hello world"));

    This will print out Hello world on the node labeled foo. Adding this to the rust library required only a few lines of code changes. The whole implementation complexity stays inside of the VM. From the developer's perspective it's trivial to just send a closure to be executed on a completely different machine that may use a different operating system or CPU architecture.

    Known issues

    • At the moment nodes send plain text messages between each other and each node connects to each other over TCP.
    • If a node disappears from the network linked processes will not be notified that the links broke.
    Source code(tar.gz)
    Source code(zip)
    lunatic-linux-amd64.tar.gz(6.15 MB)
    lunatic-macos-amd64.tar.gz(4.61 MB) MB)
  • v0.6.1(Sep 10, 2021)

  • v0.6.0(Aug 31, 2021)


    This release contains mostly internal changes that should improve the developer experience of people working on the VM, but also adds some cool new features.


    • Processes now have a more general abstraction, the Process trait. It allows us to treat anything that can receive a "message" as a process. At the moment this can only be a WebAssembly process or native Rust closures, but it could be extended in the future with other resources that act as processes.

    • Tags were added to messages, allowing for selective receives. A common use case for them is to make a request to a process and ignore all other messages until the response arrives. This can be now done by giving the request message a specific tag (i64 value) and waiting for a response on that tag with lunatic::message::receive. The receive function will first search the existing mailbox for the first message matching the tag or block until a message with the specified tag arrives. If we know that such a tag can't yet exist in the mailbox, we can use the atomic send and receive operation (send_receive_skip_search) that will not look through the mailbox.

    • Messages are now just a special kind of signals that a process can receive. Other signals are Kill, Link, Unlink, ...

    • A test was added for catching signature changes of host functions.

    • The messaging API was extended, including functions write_data and read_data that allow for streaming zero-copy message de/serialization.

    • The Environment was extended with a concept of a registry and 3 host functions: register, unregister and lookup. Processes can now be registered inside the Environment under a well known name and version number. When looking up processes inside the Environment with a query, the lookup will follow semantic versioning rules for the version. If we have a process under the name "test" and version "1.2.3", a lookup query with the name "test" and version "^1.2" will match it.

    • Fixed an issue around async Rust cancellation safety and receives with timeouts.

    • Improved handling of command line arguments and environment variables.

    Rust library

    • The Message trait was removed and we now solely rely on serde's Serialize & Deserialize traits to define what can be a message. Originally I was thinking that this is going to be an issue once we get support for Rust's native TcpStream and we can't define serde's traits for it, but this can be solved with remote derives in the future. This removes a really big and complex macro from the library and allows us to use the new write_data and read_data host functions for zero-copy de/serialization.

    • MessagePack is now used as the default message serialization format.

    • A request/reply API was added, that was built on the new selective receive functionality.

    • The Environment struct was extended with the new registry functionality.

    • New lunatic::main & lunatic::test macros were added to improve developer experiences.

    • lunatic::process::this_env was added to get the environment that the process was spawned in.

    Source code(tar.gz)
    Source code(zip)
    lunatic-linux-amd64.tar.gz(5.63 MB)
    lunatic-macos-amd64.tar.gz(4.57 MB) MB)
  • v0.5.0(Jul 29, 2021)


    Lunatic was completely re-written from scratch. Now it's built on top of Wasmtime's async support and doesn't contain any unsafe code.

    The architecture of the runtime was changed to closer mirror Erlang's features. Processes now only contain one mailbox and the channels API was removed. Processes can also be linked together to propagate failure, so that supervisor like tools can be built on top of them.


    Environments allow you to specify some characteristics of the execution, like how much memory or CPU processes can use. They can also define host function namespaces that are allowed to be called. Processes that are spawned into an environment inherit theses characteristics, allowing you to dynamically create execution contexts for new processes.

    Dynamic module loading

    WebAssembly modules can be loaded from other WebAssembly modules during runtime. Combined together with Environments this can be used to load untrusted code and run it inside a sandbox.


    The Rust library was also completely re-written to support the new abstractions. Check out the new docs!

    The AssemblyScript update is still WIP.

    Next steps

    The next part is going to be adding support for distributed workloads. We should be able to build on top of the Environment abstraction and say "create a new environment but on this other machine". All processes spawned into this environment would be spawned onto a different node. All other parts like message passing and linking should stay transparent to processes, no matter on what machine they run.

    Source code(tar.gz)
    Source code(zip)
    lunatic-linux-amd64.tar.gz(5.60 MB)
    lunatic-macos-amd64.tar.gz(1.34 MB) MB)
  • v0.3(Jan 26, 2021)

    Thanks for checking out Lunatic! Join our discord server. We are still a small community, but steadily growing.


    1. Created uptown_funk (this link leads to a YouTube music video)

    This is by far the biggest change in this release and one that took up most of the development time. uptown_funk is a crate that lets you elegantly define Wasm host functions that are compatible with both Wasmtime and Wasmer runtimes.

    It consists of a macro and a few structs/traits that let you translate from Wasm primitive types to higher level Rust types, and back.

    Lets look at an example of a host function definition using uptown_funk:

    #[host_functions(namespace = "wasi_snapshot_preview1")]
    impl WasiState {
        async fn fd_pread(&mut self, fd: u32, iovs: &mut [IoSliceMut<'_>], offset: Filesize) -> (Status, u32) {
            // ...
        // .. Other functions depending on the WasiState struct.

    The host_function macro lets us grab any host side struct and use it as state for the Wasm instances. Instead of dealing with low level pointers + lengths passed from the WebAssembly guests, we can pretend to receive higher level Rust type (e.g. &mut [IoSliceMut<'_>]) and the macro is going to create appropriate wrappers for us. And of course, it correctly works with async functions on Lunatic.

    This was an important step forward to make Lunatic runtime agnostic. Currently we support bot Wasmer and Wasmtime, but if we wanted, we could add support for another runtime in the future by just adding support to uptown_funk.

    Sadly, uptown_funk doesn't have any documentation yet and is not that useful to other projects. But I intend to invest more time into this in the future.

    2. Fixed Process canceling cleanup

    This issue needs a bit context. All Lunatic processes are executed on a separate stack and if they are waiting for some I/O they will be moved off the execution thread. Now, you can decide while you are waiting on something just to cancel this process. Until now this would free the memory region belonging to the stack/heap and finish. However, it can happen that the separate stack contains pointers to resources held by the runtime (channels, other processes, etc.). Their drop() methods would never have been called in this case and the resources would have been leaked.

    This required a fix in the async-wormhole crate. Now, every time when a generator is dropped and the closure didn't yet finish running, a stack unwind will be triggered on the separate stack. This will clean up all the resources left behind.

    3. Updated Rust's library

    The Lunatic Rust library allows you to write Rust applications that can take complete advantage of Lunatic's features, not to embed the Lunatic runtime in your Rust application (coming soon). The Rust library has seen almost a complete rewrite and takes much better advantage of Rust's ownership model now. Especially when sending host resources between processes.

    4. Added initial WASI filesystem support

    This is still a WIP area, but the basic functionality is there for opening files, reading directories, etc.

    5. Added TCP support

    A few APIs are still missing, but we have enough to create a TCP listener/client.

    6. Miscellaneous fixes

    There are too many other small fixes and additions to mention here, but Lunatic is much more stable now than just 2 months ago and I have removed the experimental warning in the Readme :)

    Source code(tar.gz)
    Source code(zip)
    lunatic-linux-amd64.tar.gz(4.12 MB)
    lunatic-macos-amd64.tar.gz(3.13 MB) MB)
  • v0.1(Oct 20, 2020)

Lunatic is an Erlang inspired runtime for WebAssembly
WebAssembly to Lua translator, with runtime

This is a WIP (read: absolutely not ready for serious work) tool for translating WebAssembly into Lua. Support is specifically for LuaJIT, with the se

null 43 Dec 31, 2022
Wasmtime - Standalone JIT-style runtime for WebAssembly, using Cranelift

wasmtime A standalone runtime for WebAssembly A Bytecode Alliance project Guide | Contributing | Website | Chat Installation The Wasmtime CLI can be i

Bytecode Alliance 11.1k Jan 2, 2023
Standalone JIT-style runtime for WebAssembly, using Cranelift

wasmtime A standalone runtime for WebAssembly A Bytecode Alliance project Guide | Contributing | Website | Chat Installation The Wasmtime CLI can be i

Bytecode Alliance 11.1k Dec 31, 2022
Lumen - A new compiler and runtime for BEAM languages

An alternative BEAM implementation, designed for WebAssembly

Lumen 3.1k Dec 26, 2022
A high-performance, secure, extensible, and OCI-complaint JavaScript runtime for WasmEdge.

Run JavaScript in WebAssembly Now supporting wasmedge socket for HTTP requests and Tensorflow in JavaScript programs! Prerequisites Install Rust and w

Second State 219 Jan 3, 2023
Wasm runtime written in Rust

Wasm runtime written in Rust

Teppei Fukuda 1 Oct 29, 2021
A prototype WebAssembly linker using module linking.

WebAssembly Module Linker Please note: this is an experimental project. wasmlink is a prototype WebAssembly module linker that can link together a mod

Peter Huene 19 Oct 28, 2022
Sealed boxes implementation for Rust/WebAssembly.

Sealed boxes for Rust/WebAssembly This Rust crate provides libsodium sealed boxes for WebAssembly. Usage: // Recipient: create a new key pair let reci

Frank Denis 16 Aug 28, 2022
WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies.

WebAssembly Tour WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies. We spend a lot of ti

Thang Chung 129 Dec 28, 2022
WebAssembly modules that use Azure services

This is an experimental repository containing WebAssembly modules running on top of WAGI (WebAssembly Gateway Interface, which allows you to run WebAssembly WASI binaries as HTTP handlers) and using Azure services.

null 7 Apr 18, 2022
WebAssembly Service Porter

WebAssembly Service Porter.

henrylee2cn 12 Dec 12, 2022
WAGI: WebAssembly Gateway Interface

Write HTTP handlers in WebAssembly with a minimal amount of work

null 724 Jan 6, 2023
A console and web-based Gomoku written in Rust and WebAssembly

?? rust-gomoku A console and web-based Gomoku written in Rust and WebAssembly Getting started with cargo & npm Install required program, run # install

namkyu1999 2 Jan 4, 2022
WebAssembly development with Trunk & Vite.js

Trunk & Vite.js Demo Trunk is a WASM web application bundler for Rust, and Vite.js is next Generation Frontend Tooling. Ok, they are together now for

Libing Chen 6 Nov 24, 2021
darkforest is a console and web-based Roguelike written in Rust and WebAssembly.

darkforest darkforest is a console and web-based Roguelike written in Rust and WebAssembly. Key Features TBA Quick Start TBA How To Contribute Contrib

Chris Ohk 5 Oct 5, 2021
A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly

ESP Stack Trace Decoder A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly. It is composed of a ⌨️ Rust library,

Maxime BORGES 20 Oct 5, 2022
Simple file sharing with client-side encryption, powered by Rust and WebAssembly

Hako Simple file sharing with client-side encryption, powered by Rust and WebAssembly Not feature-packed, but basic functionalities are just working.

Jaehyeon Park 30 Nov 25, 2022
bn.js bindings for Rust & WebAssembly with primitive-types support bn.js bindings for Rust & WebAssembly with primitive-types support Write Rust code that uses BN use std::str::FromStr; use primitive_types::{H1

Alexey Shekhirin 23 Nov 22, 2022
A handy calculator, based on Rust and WebAssembly.

qubit ?? Visit Website To Use Calculator Example ?? Visit Website To Use Calculator 2 + 2

Abhimanyu Sharma 55 Dec 26, 2022