Home Posts WebAssembly Component Model Cheat Sheet [2026 WIT]
Developer Reference

WebAssembly Component Model Cheat Sheet [2026 WIT]

WebAssembly Component Model Cheat Sheet [2026 WIT]
Dillip Chowdary
Dillip Chowdary
Tech Entrepreneur & Innovator · May 14, 2026 · 12 min read

Bottom Line

Treat WIT as the contract and composition as interface matching, not symbol linking. Most real failures come from world shape, package-version drift, or unresolved imports you could have caught with one inspection command.

Key Takeaways

  • A world is the full component contract; an interface is the reusable slice.
  • wac plug is for simple one-way wiring; wac compose is for explicit multi-component graphs.
  • wasm-tools component wit is the fastest way to spot import/export and version mismatches.
  • wkg.toml local overrides plus wkg wit fetch keep WIT deps reproducible under wit/deps.
  • wasm-tools component new --adapt bridges legacy wasi_snapshot_preview1 modules into components.

As of May 14, 2026, the practical WebAssembly Component Model workflow is clear: define contracts in WIT, generate bindings, inspect the resulting component boundary, and satisfy imports with WAC or a host Linker. This reference is optimized for recall, not theory. Use it when you need exact command shapes, quick reminders on world versus interface, and the linking patterns that usually break first in real projects.

  • A world describes the complete import/export contract of a component.
  • Package IDs use namespace:name@version; version mismatches commonly block composition.
  • wac plug is asymmetric: a primary component imports, dependency components export.
  • wasm-tools component wit is the first debugging command to reach for.
  • Wasmtime runs, serves, and invokes components, but denies system access by default.

Command Quick Reference

Bottom Line

Think in four verbs: define, inspect, compose, and run. If imports do not line up at the interface level, no amount of host glue will save the composition.

Live Search Filter

Shortcuts: / focus filter, Esc clear, 1-5 jump sections.

Keyboard Shortcuts

ShortcutAction
/Focus the live filter
EscClear the filter and show all command groups
1Jump to Command Quick Reference
2Jump to WIT Building Blocks
3Jump to Linking Patterns
4Jump to Configuration
5Jump to Advanced Usage

Install and Scaffold

cargo install cargo-component --locked
cargo install --locked wasm-tools
cargo install wkg
cargo install wasmtime-cli

cargo component new --lib hello-component
cargo component check
  • cargo component new --lib scaffolds a library-style component; without --lib, it defaults to a command component.
  • cargo component check is also the command the official docs recommend wiring into rust-analyzer.

Inspect and Validate

wasm-tools component wit component.wasm
wasm-tools validate component.wasm
wasm-tools print component.wasm
wasm-tools metadata show component.wasm
  • Use component wit to view the embedded import/export contract.
  • Use print when you need to confirm whether the artifact is a top-level (component) or (module).

Compose and Link

wac plug validator-component.wasm --plug regex-component.wasm -o composed.wasm

wac compose \
  --dep docs:regex-impl=regex-component.wasm \
  --dep docs:validator-impl=validator-component.wasm \
  -o composed.wasm \
  composition.wac
  • wac plug is the fast path when one primary component has a few direct imports.
  • wac compose is the explicit path for named graphs and transitive dependencies.

Adapt Legacy WASIp1 Modules

wasm-tools component new my-core.wasm -o my-component.wasm \
  --adapt wasi_snapshot_preview1.reactor.wasm
  • Official adapter modules are published with Wasmtime releases.
  • Choose the adapter by shape: command, reactor, or proxy.

Run, Serve, and Invoke

wasmtime run component.wasm
wasmtime serve http-proxy.wasm
wasmtime run --invoke 'add(1, 2)' add.wasm

jco run component.wasm arg1 arg2
  • wasmtime run targets command components and can invoke typed exports with --invoke.
  • wasmtime serve runs components implementing the wasi:http/proxy world.

WIT Building Blocks

Package, Interface, World

WIT is the IDL of the Component Model. Official docs define three core units: interfaces for focused functionality, worlds for a component’s full contract, and packages for organizing multiple .wit files.

package docs:validator@0.1.0;

interface validator {
    validate-text: func(text: string) -> string;
}

world validator {
    export validator;
    import docs:regex/match@0.1.0;
}
  • A world can import or export whole interfaces, and it can also import or export specific functions.
  • A package ID must contain a namespace:name pair and may include a semver version.
  • All files in the same WIT package use the .wit extension and live in one directory.

Reuse Patterns: use and include

Use smaller interfaces for stable building blocks, then aggregate them through worlds. This is the cleanest way to keep a large surface auditable. When you need tidy examples for docs or reviews, TechBytes’ Code Formatter is a practical companion for keeping WIT readable.

world glow-in-the-dark-multi-function-device {
    include multi-function-device;
    export glow: func(brightness: u8);
}
  • include pulls another world’s imports and exports into the current world.
  • Import and export operate at the interface level, not the package level.

Rich Types That Matter in Real Designs

resource blob {
    constructor(init: list<u8>);
    write: func(bytes: list<u8>);
    read: func(n: u32) -> list<u8>;
    merge: static func(lhs: blob, rhs: blob) -> blob;
}

record customer {
    id: u64,
    name: string,
    picture: option<list<u8>>,
}

variant allowed-destinations {
    none,
    any,
    restricted(list<string>),
}
  • resource models external or non-copyable entities and supports constructors, methods, and static functions.
  • option, result, record, and variant are the usual contract primitives for service-style components.
  • Borrowing and ownership matter at the resource boundary even when the guest language hides the low-level details.

Linking Patterns

Pattern 1: Direct Interface Import

The simplest pattern is one component importing one interface from another package. The official Rust reuse guide shows this shape clearly.

package docs:calculator;

interface calculate {
    eval-expression: func(expr: string) -> u32;
}

world calculator {
    import docs:adder/add@0.1.0;
    export calculate;
}
  • Use this when you want a narrow dependency edge and a stable reusable interface.
  • Keep imported interfaces focused; large worlds make downstream composition harder to reason about.

Pattern 2: Fast Build-Time Composition with wac plug

wac plug is asymmetric. A primary “socket” component imports functionality, and one or more dependency “plug” components export the matching interfaces.

wac plug path/to/component.wasm \
  --plug path/to/dep1.wasm \
  --plug path/to/dep2.wasm \
  -o composed.wasm
  • Good fit for application assembly and simple library wiring.
  • The resulting component keeps the primary component’s exports, not the dependency exports.

Pattern 3: Explicit Graphs with wac compose

Once dependencies themselves have imports, the quick plug workflow stops scaling. Move to a .wac file and name each node deliberately.

// composition.wac
package docs:composition;

let regex = new docs:regex-impl { };
let validator = new docs:validator-impl { match: regex.match, ... };
export validator...;
wac compose --dep docs:regex-impl=regex-component.wasm \
            --dep docs:validator-impl=validator-component.wasm \
            -o composed.wasm \
            composition.wac
  • Use this when you need transitive dependency control or a composition that should be reviewed like source code.
  • The interface contract is still the real linker input; filenames are just bindings for the composition step.
Watch out: Composition happens at the interface level. If a component imports raw functions instead of interfaces, official docs note that composition can fail with non-instance import errors.

Pattern 4: Runtime Linking in the Host

Not every dependency should be flattened at build time. The Wasmtime component API documents the other common pattern: a Component becomes an Instance through a Linker. Use host-side linking when the environment, not another packaged component, should satisfy the import.

  • Good fit for capabilities like filesystem access, environment injection, clocks, networking, or policy-controlled platform services.
  • Prefer build-time composition for portable app bundles; prefer host linking for platform-owned capabilities.

Configuration

Resolve Local WIT Dependencies with wkg.toml

[overrides]
"docs:adder" = { path = "../adder/wit" }
wkg wit fetch
  • Official docs show wkg wit fetch materializing dependencies under wit/deps.
  • This is the lowest-friction way to keep local component contracts reproducible during development.

Rust Analyzer Setup

{
  "rust-analyzer.check.overrideCommand": [
    "cargo",
    "component",
    "check",
    "--workspace",
    "--all-targets",
    "--message-format=json"
  ]
}
  • The cargo-component README recommends overriding the check command so generated bindings stay in sync.
  • cargo component new can write VS Code settings automatically unless you pass --editor none.

Wasmtime CLI Config Files

[optimize]
opt-level = 0
wasmtime compile --config config.toml
  • Wasmtime supports TOML-based configuration for the same families of options exposed through --optimize, --codegen, --debug, --wasm, and --wasi.
  • CLI flags override TOML settings when both are present.

Advanced Usage

Inspect First, Then Fix

wasm-tools component wit composed.wasm
wasm-tools print composed.wasm
wasm-tools validate composed.wasm
  • If versions differ, inspect the embedded WIT instead of guessing from source directories.
  • If you need to distinguish a core module from a component quickly, wasm-tools print exposes the top-level (module) or (component).

Adapt Preview 1 Modules Deliberately

The wit-bindgen README explains the current bridge clearly: many native toolchains still emit wasm32-wasip1 core modules, then wasm-tools component new --adapt lifts them into component-model binaries.

  • Use the command adapter for CLI-style entry points.
  • Use the reactor adapter for library or event-driven shapes without a main.
  • Use the proxy adapter for HTTP-serving flows.

JavaScript Workflow: Componentize, Inspect, Transpile

npx jco componentize \
  string-reverse-upper.mjs \
  --wit wit/ \
  --world-name revup \
  --out string-reverse-upper.incomplete.wasm \
  --disable=all

npx jco wit string-reverse-upper.incomplete.wasm
npx jco transpile string-reverse-upper.wasm -o dist/transpiled
  • The official JavaScript guide uses this flow to build a component, confirm unsatisfied imports, then inspect the completed component after composition.
  • jco run is convenient, but official docs warn that its WASI implementation grants full access to the underlying system resources.
Pro tip: Treat wasm-tools component wit as your equivalent of ldd, nm, and interface docs rolled into one. It is the shortest path from a failing composition to the actual contract mismatch.

2026 Reality Check

  • cargo component still describes itself as experimental and not stable in terms of the code it supports building.
  • wasm-tools compose is marked deprecated in the official README; prefer WAC for composition.
  • Wasmtime’s official component docs note that older versions may still require --wasm component-model when running a component.

Official Docs Worth Bookmarking

Frequently Asked Questions

What is the difference between a WIT interface and a WIT world? +
A WIT interface is a focused collection of type and function declarations. A WIT world is the broader contract for a component: what it imports, what it exports, and therefore what a host or another component must satisfy. In practice, you reuse interfaces and target worlds.
When should I use wac plug instead of wac compose? +
Use wac plug when one primary component has direct imports that can be satisfied by one or a few dependency components. Use wac compose when you need an explicit graph, named component instances, or transitive dependency control. If you are reviewing composition like source code, wac compose is usually the better fit.
How do I debug a component version mismatch? +
Run wasm-tools component wit your-file.wasm and inspect the embedded package and interface versions. Official docs warn that tools are inconsistent about inferring or injecting versions, so source directories are not enough. Match the exact namespace:name@version shape on both the import and export sides.
Can I turn a wasisnapshotpreview1 module into a component? +
Yes. The official wit-bindgen guidance is to use wasm-tools component new --adapt ... with the correct Wasmtime adapter module. Pick command, reactor, or proxy based on the runtime shape of the original core module.

Get Engineering Deep-Dives in Your Inbox

Weekly breakdowns of architecture, security, and developer tooling — no fluff.

Found this useful? Share it.