Skip to main content

Meld

Static WebAssembly component fusion

 

CI Bench codecov Rust WebAssembly Component Model Formal Methods License: Apache-2.0

 

Meld · Loom · Synth · Kiln · Sigil

 

Meld fuses. Loom weaves. Synth transpiles. Kiln fires. Sigil seals.

Meld statically fuses multiple WebAssembly components into a single core module, eliminating the need for runtime linking. Import resolution, index-space merging, and canonical ABI adapter generation happen at build time. The core transformations — resolution, index-space merging, and adapter generation — carry mechanized Rocq proofs, plus local Kani bounded-model-checking harnesses on the Canonical-ABI layout invariants; see Formal Verification for the per-stage coverage (some stages are specified but not yet proved, and the Kani harnesses are run locally, not gated in CI).

Unlike composition tools that produce linked-but-separate component graphs, Meld produces a single monolithic module suitable for whole-program optimization by Loom and native transpilation by Synth.

Quick Start

Prebuilt binaries

Every release ships archives for six targets. On Linux, pick by what the machine has rather than by architecture alone:

use
glibc 2.34 or newer (Ubuntu 22.04+, Debian 12+, Fedora) *-unknown-linux-gnu
anything older, or no glibc at all — Alpine, distroless-static, RHEL 8, Ubuntu 20.04 *-unknown-linux-musl
macOS *-apple-darwin

The musl archives are statically linked: no dynamic loader, no glibc symbol versions, nothing to install alongside them. If you are not sure which your target has, the musl one runs in both places.

TAG=v0.62.0
TARGET=x86_64-unknown-linux-musl
gh release download "$TAG" --repo pulseengine/meld --pattern "meld-${TAG}-${TARGET}.tar.gz"
tar xzf "meld-${TAG}-${TARGET}.tar.gz"
./meld-${TAG}-${TARGET}/meld --version

Verify what you downloaded before running it — see Verifying a Release.

From source

# From source (Cargo) — the only build for meld itself
cargo install --path meld-cli

# Fuse two components
meld fuse component_a.wasm component_b.wasm -o fused.wasm

Full Pipeline

# 1. Build components
cargo component build --release

# 2. Fuse into single module
meld fuse composed.wasm -o fused.wasm

# 3. Optimize with Loom
loom optimize fused.wasm -o optimized.wasm

# 4. Run
wasmtime run optimized.wasm

Bazel Integration

load("@meld//rules:meld.bzl", "meld_fuse")

meld_fuse(
    name = "my_app",
    components = [
        ":component_a",
        ":component_b",
    ],
    # Mandatory: the meld binary that will be recorded as the producer in the
    # fused artifact's attestation. There is deliberately no default — the old
    # one pointed at a Bazel self-build that stamped a version matching nothing
    # (#406).
    meld = "@meld_release//:meld",
)

meld_fuse is for projects that build their components with Bazel. It is not exercised by meld's own CI, so treat it as community-supported.

How It Works

  1. Parse — Extract core modules and type information from components
  2. Resolve — Build import/export graph, identify cross-component calls
  3. Merge — Combine function/memory/table/global index spaces
  4. Adapt — Generate Canonical ABI trampolines for cross-component calls
  5. Encode — Output single core WebAssembly module

Adapter Generation

Cross-component calls may require adapters that handle string transcoding (UTF-8, UTF-16, Latin-1), memory copying between component memories, list/array serialization, and resource handle transfer. Meld generates these adapters using techniques inspired by Wasmtime's FACT (Fused Adapter Compiler of Trampolines).

Memory Strategies

Auto (Default)

Always selects multi-memory, the strategy that is sound for every input. Auto never selects shared memory or address rebasing on its own (#326, #409); both remain available explicitly via --memory shared --address-rebase. The fused module therefore keeps one linear memory per input component, needs wasm-opt --enable-multimemory downstream, and has no single-address-space (MCU) lowering (issue #172).

meld fuse a.wasm b.wasm -o fused.wasm
wasm-opt -Os --enable-multimemory fused.wasm -o fused.opt.wasm

Multi-Memory

Each component retains its own linear memory. Cross-component calls use adapters that allocate in the callee's memory via cabi_realloc and copy data with memory.copy. Requires multi-memory support (WebAssembly Core Spec 3.0) — downstream tools need wasm-opt --enable-multimemory, and single-address-space (MCU) targets have no lowering for it.

meld fuse --memory multi a.wasm b.wasm -o fused.wasm

Shared Memory

All components share a single linear memory; pair with --address-rebase. Unsound if any component uses memory.grow — one component's growth corrupts every other component's address space, which is why auto never selects this form on its own.

meld fuse --memory shared --address-rebase a.wasm b.wasm -o fused.wasm

Further fuse Options

Options for single-address-space targets and for auditing a fusion; the first three require --memory shared. Run meld fuse --help for the full text of each.

Flag Effect
--pack-rebase Place each component at its used data extent (16-byte aligned) instead of its declared page count, and size the merged memory to the packed total. Implies --address-rebase. Opt-in; sound only when a component references no address above its last data segment.
--share-stack Collapse the per-provider shadow stacks into one shared region. Implies --pack-rebase. Requires every provider to carry a __heap_base marker and be stack-first, and fails loudly otherwise. Opt-in; sound only for non-reentrant, single-threaded, mutually non-calling providers.
--domain NAME=INPUT[,INPUT...] Group inputs into memory domains: fuse within a domain, keep the Canonical ABI between domains. Repeat once per domain; every input must be named in exactly one. A domain is a trust boundary and is recorded in the attestation.
--profile safety Require safety-relevant properties to be stated rather than inferred. Today this means --memory must be given: auto is refused. Output is byte-identical to the same explicit invocation under the default --profile ecosystem.
--explain Report, for every fused cross-component call, the call-lowering class chosen (direct, memory-copy, transcode, async-lift) and how it was wired. The same records are embedded in the attestation.
--emit-manifest Emit a meld.signature-manifest section giving, per export, the WIT and core signatures, the flattened parameter count, and the memory, allocator and post-return a host must use to invoke it. Opt-in.
--exports <all|world> Which exports the fused core module keeps. all (default) keeps every export of every inner module. world keeps only the functions that implement the outer world of the input(s), traced through their canon lifts (never by name) and exported under their world name <interface>#<function>, plus what the kept surface and the imports the module still has need: the memory and realloc of the kept lifts and of every canon lower behind a remaining import (a realloc nothing exports is exported as meld:realloc/<component>), cabi_post_*, the [dtor] exports of resources still imported, and the start function. Drops the internal interfaces of a composition, __data_end, __heap_base and every other global or table export. Only the export list changes; function bodies stay. A world function that cannot be traced to an exported fused function is an error. Not valid with --component. Recorded in the attestation.
--reproducible Produce a byte-reproducible artifact: the attestation id is derived from the output content and the timestamp from SOURCE_DATE_EPOCH (default 0). Attested input names are replaced by positional identifiers (component-0, ...).
--opaque-rep IFACE.RESOURCE Mark a resource as opaque-rep, for re-exporters whose representation is treated as a u32 rather than a boxed pointer. Such resources skip the per-resource handle table layer. Repeatable.

Supply Chain Security

Meld integrates with Sigil for supply chain attestation. Each fusion operation records input component hashes, tool version and configuration, and transformation metadata. The attestation is embedded in the output module's custom section.

Verifying a Release

Every tagged release ships with a CycloneDX SBOM, a cosign-signed SHA256SUMS.txt, and a SLSA v1 build-provenance attestation. To verify an installed binary against what GitHub Actions actually built:

# 1. Download an archive plus the signed checksum manifest from the release page.
TAG=v0.62.0
TARGET=x86_64-unknown-linux-gnu
gh release download "$TAG" --repo pulseengine/meld \
  --pattern "meld-${TAG}-${TARGET}.tar.gz" \
  --pattern 'SHA256SUMS.txt' \
  --pattern 'SHA256SUMS.txt.cosign.bundle'

# 2. Verify SHA256SUMS.txt was signed by meld's release workflow (Sigstore keyless).
cosign verify-blob \
  --certificate-identity-regexp \
    'https://github.com/pulseengine/meld/.github/workflows/release.yml@.*' \
  --certificate-oidc-issuer \
    'https://token.actions.githubusercontent.com' \
  --bundle SHA256SUMS.txt.cosign.bundle \
  SHA256SUMS.txt

# 3. Verify the archive's digest is in the signed manifest.
sha256sum --ignore-missing -c SHA256SUMS.txt

# 4. (Optional) Verify the SLSA v1 build provenance attestation.
gh attestation verify "meld-${TAG}-${TARGET}.tar.gz" --repo pulseengine/meld

Step 2 proves the checksum file came from this repo's release.yml; step 3 ties the archive on disk to that signed manifest; step 4 independently confirms the archive was built by the same workflow run via GitHub's attestation API. Each release also includes a meld-<version>.cdx.json (CycloneDX SBOM, transitively covered by the signature on SHA256SUMS.txt) and build-env.txt capturing the runner toolchain versions.

Formal Verification

Meld's core transformations carry mechanized Rocq proofs — 357 closed proofs (Qed) across the resolver, merger, adapter, and specification layers (see proofs/STATUS.md for the per-stage coverage matrix). This is real, substantial verification on the core; it is not yet a whole-pipeline proof: the parser, rewriter, segments, and attestation stages are specified but their proofs are placeholders, orchestration (lib.rs) is unproven, and the semantic-preservation result is a forward simulation (the fused module simulates the original graph step-by-step; the reverse direction and the backward half of trap-equivalence are not yet proved).

Proven properties (Rocq):

  • Merge correctness — Index remapping preserves function/memory/table references (injectivity, completeness, boundedness); memory-layout disjointness.
  • Resolve correctness — Topological sort produces a valid instantiation order; cycle detection terminates.
  • Adapter correctness — Canonical-ABI lift/lower roundtrip and crossing-adapter semantics (no Admitted lemmas remain in proofs/).
  • Forward simulation — The fused module simulates the original component graph step-by-step (forward direction; fully proved).

In addition, the Canonical-ABI layout invariants (size/alignment saturating arithmetic, the #141 stream ring model) carry Kani bounded-model-checking harnesses (abi_proofs.rs, resolver.rs, merger/) that were VERIFICATION SUCCESSFUL locally (SR-40); these are not gated in CI (the shared runners do not ship the Kani toolchain), and the ABI size/alignment and aggregate-padding contracts that did not converge in CBMC fall back to unit tests.

Proofs are built via Bazel using rules_rocq_rust:

bazel build //proofs/transformations/merge:merge_spec
bazel build //proofs/spec:fusion_spec

See proofs/ for the full proof tree and PROOF_GUIDE.md for an introduction.

Limitations

  • Resources — Resource handle transfer across components is limited
  • Async — P3 async lowering (stream<T>, future<T>, async lift/lower) is partial; async cross-component calls are covered only for the shapes exercised by the test suite, and the full async surface is not yet supported
  • String transcoding — all pairs of UTF-8, UTF-16 and latin1+utf16 are implemented for synchronous calls; async cross-encoding transcoding covers a bounded set of types (nested list<list<string>> to depth 2)

Development

cargo build                # Build
cargo test                 # Test
bazel build //proofs/...   # Rocq proofs only (there is no Bazel build of meld)
RUST_LOG=debug cargo run -- fuse a.wasm b.wasm -o out.wasm

Benchmarks

Criterion benchmarks for the fusion pipeline live in meld-core/benches/fusion_benchmarks.rs and exercise four groups:

  • parser — ComponentParser::parse throughput per input byte.
  • merger — Merger::merge throughput per component count.
  • resolver — Resolver::resolve_with_hints throughput per resolved-symbol count.
  • end_to_end — Fuser::fuse_with_stats over small / medium / large graphs.
cargo bench -p meld-core                          # full run
cargo bench -p meld-core --bench fusion_benchmarks -- parser   # one group
cargo bench -p meld-core --no-run                 # compile-only sanity (CI smoke)

CI runs cargo bench --no-run on every PR (.github/workflows/bench.yml) to prevent the bench harness from rotting. Full benches are not run in CI to keep PRs fast and avoid noisy regressions on shared runners.

License

Apache-2.0


Part of PulseEngine — formally verified WebAssembly toolchain for safety-critical systems

Metadata

Release files for meld-cli 0.65.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for meld-cli 0.65.1
File
meld_cli-0.65.1-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details
meld_cli-0.65.1-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details
meld_cli-0.65.1-py3-none-manylinux_2_34_x86_64.whl Python 3 none Linux glibc 2.34+ x86-64 Details
meld_cli-0.65.1-py3-none-manylinux_2_34_aarch64.whl Python 3 none Linux glibc 2.34+ ARM64 Details
meld_cli-0.65.1-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
meld_cli-0.65.1-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 12.5 MB

Release files / meld_cli-0.65.1-py3-none-musllinux_1_2_x86_64.whl

Download URL meld_cli-0.65.1-py3-none-musllinux_1_2_x86_64.whl
Size 2.2 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
67c3d934ad1629f3fed0ce82386b73c0cc728cc5c1f2e825059e331307397809
BLAKE2b-256 checksum
How to use checksums
df5ac696069c89e0c2539ade0824af215d0f3520ca9080a385bc5c66f837cf58
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / meld_cli-0.65.1-py3-none-musllinux_1_2_aarch64.whl

Download URL meld_cli-0.65.1-py3-none-musllinux_1_2_aarch64.whl
Size 2.0 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
89ad7d4676f47441e66ac3e74d83e9053c35c040002d40fcd1b839721e956a77
BLAKE2b-256 checksum
How to use checksums
32afe7556f4f7bf3819f0c204ebbb9a76b1e22342483fb6343aea6487cededbb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / meld_cli-0.65.1-py3-none-manylinux_2_34_x86_64.whl

Download URL meld_cli-0.65.1-py3-none-manylinux_2_34_x86_64.whl
Size 2.2 MB
Tags Linux glibc 2.34+ x86-64 Python 3
SHA-256 checksum
How to use checksums
5b39fd448eda110cb30f0f5e2e4e46a314689964028dd43a28ee16adb02bfa74
BLAKE2b-256 checksum
How to use checksums
9e6c76f5f26cab887c9585f60fa626f0d7030e35ee9b8bd1152a7cea354a528b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / meld_cli-0.65.1-py3-none-manylinux_2_34_aarch64.whl

Download URL meld_cli-0.65.1-py3-none-manylinux_2_34_aarch64.whl
Size 2.0 MB
Tags Linux glibc 2.34+ ARM64 Python 3
SHA-256 checksum
How to use checksums
cb4be43f4fb2f4a6bc3287c651c9bdd0653fe73afd17f2feadf646b78b77abe1
BLAKE2b-256 checksum
How to use checksums
f4f3fa4ee9b8296f38235822a5720dfd563559d8a5e2c64e7868d55c89824e87
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / meld_cli-0.65.1-py3-none-macosx_11_0_arm64.whl

Download URL meld_cli-0.65.1-py3-none-macosx_11_0_arm64.whl
Size 1.9 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
5d04c451e24dce19beab829acf230e55c15449eb81a352633cedb54f7dfa78b4
BLAKE2b-256 checksum
How to use checksums
3fbd6fa34cfa009df10f88e0b7821af155ae3ada5dd94682d0d0e33a016ee3dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Release files / meld_cli-0.65.1-py3-none-macosx_10_12_x86_64.whl

Download URL meld_cli-0.65.1-py3-none-macosx_10_12_x86_64.whl
Size 2.1 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
ab06da175a0f488d01e82304cc2c356126379bedf4d5eebcb1f4ceaa6cec0ed2
BLAKE2b-256 checksum
How to use checksums
d26a3d350676ae8e970799eb7aaeea4c460dbef71a426d306e1c4f32c37eebf8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

Security for meld-cli 0.65.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for meld_cli-0.65.1-py3-none-musllinux_1_2_x86_64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.65.1 This release

6 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page