Stream: git-wasmtime

Topic: wasmtime / issue #12558 Custom Worlds with `wasi:cli` imp...


view this post on Zulip Wasmtime GitHub notifications bot (Feb 10 2026 at 18:39):

luoluoyuyu opened issue #12558:

Description

I am building a plugin system where the Guest components are compiled using TinyGo. Since TinyGo's runtime initialization relies heavily on WASI P2, my custom world must include include wasi:cli/imports@0.2.0;. Otherwise, the TinyGo component fails to initialize.

However, the current developer experience for this specific (and very common) use case is quite painful. Even with the with mapping in the bindgen! macro and implementing WasiView for my HostState, I am still forced to manually implement all the generated traits for wasi:* interfaces just to "delegate" them back to the wasmtime-wasi implementation.

The Problem

If I have a minimalist WIT like this:

package test:pkg@0.1.0;

interface data {
    resource store {
        constructor(name: string);
    }
}

world processor {
    // Required for TinyGo support
    include wasi:cli/imports@0.2.0;

    import data;
    export process: func(data: list<u8>) -> result<_, string>;
}

Even though wasmtime-wasi already provides a complete implementation for every WASI interface included above, I find myself writing dozens of lines of repetitive boilerplate just to bridge the gap in Rust:

// This feels like unnecessary boilerplate
impl test::pkg::processor::wasi::cli::stdout::Host for MyHost {
    fn get_stdout(&mut self) -> anyhow::Result<Resource<OutputStream>> {
        // I have to manually call the provided implementation
        wasmtime_wasi::bindings::cli::stdout::Host::get_stdout(self)
    }
}

// ... and so on for every other WASI interface TinyGo needs (clocks, streams, etc.)

Is there a more "automated" way to handle this? That is, when the Host has already provided WasiCtx and ResourceTable, bindgen! or Linker should be able to automatically identify and fulfill the requirements of these standard WASI imports without the developer having to write a large amount of repetitive boilerplate code.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 10 2026 at 18:40):

luoluoyuyu edited issue #12558:

Description

I am building a plugin system where the Guest components are compiled using TinyGo. Since TinyGo's runtime initialization relies heavily on WASI P2, my custom world must include include wasi:cli/imports@0.2.0;. Otherwise, the TinyGo component fails to initialize.

However, the current developer experience for this specific (and very common) use case is quite painful. Even with the with mapping in the bindgen! macro and implementing WasiView for my HostState, I am still forced to manually implement all the generated traits for wasi:* interfaces just to "delegate" them back to the wasmtime-wasi implementation.

The Problem

If I have a WIT like this:

package test:pkg@0.1.0;

interface data {
    resource store {
        constructor(name: string);
    }
}

world processor {
    // Required for TinyGo support
    include wasi:cli/imports@0.2.0;

    import data;
    export process: func(data: list<u8>) -> result<_, string>;
}

Even though wasmtime-wasi already provides a complete implementation for every WASI interface included above, I find myself writing dozens of lines of repetitive boilerplate just to bridge the gap in Rust:

// This feels like unnecessary boilerplate
impl test::pkg::processor::wasi::cli::stdout::Host for MyHost {
    fn get_stdout(&mut self) -> anyhow::Result<Resource<OutputStream>> {
        // I have to manually call the provided implementation
        wasmtime_wasi::bindings::cli::stdout::Host::get_stdout(self)
    }
}

// ... and so on for every other WASI interface TinyGo needs (clocks, streams, etc.)

Is there a more "automated" way to handle this? That is, when the Host has already provided WasiCtx and ResourceTable, bindgen! or Linker should be able to automatically identify and fulfill the requirements of these standard WASI imports without the developer having to write a large amount of repetitive boilerplate code.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 10 2026 at 21:16):

alexcrichton commented on issue #12558:

What I'd recommend here is to have a world that focuses on just your embedding, for example the data interface import and the process export. Wasmtime bindings would be generated using that world, and then there'd be a second world which includes this world and also has the WASI imports. This second world would be used for guest bindings generation, for example.

This is also something we could improve in Wasmtime by souping up the with option, but that can get a bit gnarly sometimes. Would the world split work for your use case?

view this post on Zulip Wasmtime GitHub notifications bot (Feb 11 2026 at 15:55):

luoluoyuyu commented on issue #12558:

What I'd recommend here is to have a world that focuses on just your embedding, for example the data interface import and the process export. Wasmtime bindings would be generated using that world, and then there'd be a second world which includes this world and also has the WASI imports. This second world would be used for guest bindings generation, for example.

This is also something we could improve in Wasmtime by souping up the with option, but that can get a bit gnarly sometimes. Would the world split work for your use case?

Thank you for your answer, this solution can solve my problem very well.

view this post on Zulip Wasmtime GitHub notifications bot (Feb 11 2026 at 15:55):

luoluoyuyu closed issue #12558:

Description

I am building a plugin system where the Guest components are compiled using TinyGo. Since TinyGo's runtime initialization relies heavily on WASI P2, my custom world must include include wasi:cli/imports@0.2.0;. Otherwise, the TinyGo component fails to initialize.

However, the current developer experience for this specific (and very common) use case is quite painful. Even with the with mapping in the bindgen! macro and implementing WasiView for my HostState, I am still forced to manually implement all the generated traits for wasi:* interfaces just to "delegate" them back to the wasmtime-wasi implementation.

The Problem

If I have a WIT like this:

package test:pkg@0.1.0;

interface data {
    resource store {
        constructor(name: string);
    }
}

world processor {
    // Required for TinyGo support
    include wasi:cli/imports@0.2.0;

    import data;
    export process: func(data: list<u8>) -> result<_, string>;
}

Even though wasmtime-wasi already provides a complete implementation for every WASI interface included above, I find myself writing dozens of lines of repetitive boilerplate just to bridge the gap in Rust:

// This feels like unnecessary boilerplate
impl test::pkg::processor::wasi::cli::stdout::Host for MyHost {
    fn get_stdout(&mut self) -> anyhow::Result<Resource<OutputStream>> {
        // I have to manually call the provided implementation
        wasmtime_wasi::bindings::cli::stdout::Host::get_stdout(self)
    }
}

// ... and so on for every other WASI interface TinyGo needs (clocks, streams, etc.)

Is there a more "automated" way to handle this? That is, when the Host has already provided WasiCtx and ResourceTable, bindgen! or Linker should be able to automatically identify and fulfill the requirements of these standard WASI imports without the developer having to write a large amount of repetitive boilerplate code.


Last updated: Feb 24 2026 at 04:36 UTC