Skip to main content
Eric Gregory
Eric Gregory
Eric Gregory
||4 min read

Customize your wash CLI with WebAssembly components and wash plugins

Cross-posted from the wasmCloud blog.

In wash v0.28, we introduced wash plugins: a simple system for extending the wasmCloud Shell (wash) CLI with WebAssembly components. Users can install plugins from OCI registries, local files, or over HTTP, then execute the plugin as a subcommand to wash. Plugin developers simply build a given piece of CLI functionality as a component.

In this post, we'll show you how to install your first plugin. In themselves, plugins represent powerful, versatile tools that will accelerate workflows and help developers tailor tooling to their needs. But wash plugins are also a great example of how modular CLIs can be implemented with WebAssembly—and how components can accelerate development across a team.

Faster development with components

Using components for plugin functionality means that very little of the implementation is particular to wash or wasmCloud. Taylor Thomas, who built the plugin system, describes it as "essentially a thin shim around wasi:cli/run." In fact, you can run plugins in Wasmtime with minimal configuration. The common interface of WASI makes components ideally suited to building modular CLIs, and even reusing plugins across different component-powered CLIs.

Because the plugin design is so firmly rooted in standards, the feature could be spun out of only a few days' work during the wasmCloud maintainers' Spring Hackathon. About a week after the Hackathon, plugins were merged into wash—a few days after that, Brooks Townsend had his wit2wadm project working as a plugin. The wasmCloud project has been all-in on components for a while now, but the team was a bit surprised by just how quickly these projects could go from independent ideas to integrated releases.

Getting started with wash plugins

If you have wash v0.28 or later installed, you've got everything you need. (If not, head on over to the Installation page.) You can run wash -V to check your version.

With wash installed, installing a plugin is just a matter of running wash plugin install against a target, whether that's a local file, an OCI registry, or an HTTP address. For this example, we'll use the wit2wadm plugin which is available as an OCI artifact hosted on GitHub Packages. wit2wadm will let us generate application deployment manifests automatically from a components' defined interfaces, cutting way down on time spent writing YAML and speeding up local development workflows.

wash plugin install oci://ghcr.io/brooksmtownsend/wit2wadm:0.2.0

We can see our installed plugins:

wash plugin list

Now we can generate deployment manifests by targeting a component with the wit2wadm subcommand. For the purposes of our demo, we'll create a new "Hello world" component:

wash new component hello --template-name hello-world-rust

Now we can navigate to the project directory and build our component from the Rust template:

cd hello
wash build

To generate the manifest, we'll simply target the .wasm file generated by our build:

wash wit2wadm ./build/http_hello_world_s.wasm

And here's our manifest:

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: wit2wadm
  annotations:
    description: A wasmCloud Application
    version: v0.1.0
  labels:
    generated-by: wit2wadm
spec:
  components:
    - name: wit2wadm
      type: component
      properties:
        image: myregistry.io/wit2wadm:v0.1.0
      traits:
        - type: spreadscaler
          properties:
            instances: 1
    - name: wasi:http-source
      type: capability
      properties:
        image: ghcr.io/wasmcloud/http-server:canary
      traits:
        - type: link
          properties:
            target: wit2wadm
            namespace: wasi
            package: http
            interfaces:
              - incoming-handler

The wit2wadm plugin extrapolates and defines things like links from the component, and then fills in unknown values (like the component's name or registry source) with placeholder values. We can use CLI flags to define those values as well:

wash wit2wadm --name demo --version 0.2.0 --description "Say hello" ./build/http_hello_world_s.wasm
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: demo
  annotations:
    description: Say hello
    version: 0.2.0
  labels:
    generated-by: wit2wadm
spec:
  components:
    - name: demo
      type: component
      properties:
        image: myregistry.io/demo:0.2.0
      traits:
        - type: spreadscaler
          properties:
            instances: 1
    - name: wasi:http-source
      type: capability
      properties:
        image: ghcr.io/wasmcloud/http-server:canary
      traits:
        - type: link
          properties:
            target: demo
            namespace: wasi
            package: http
            interfaces:
              - incoming-handler

You can learn more about the wit2wadm project in the GitHub repo, and more about using wash plugin in the wasmCloud documentation.

Developing wash plugins

If you're interested in developing wash plugins, the wasmCloud documentation includes a wash plugin developer guide. The developer guide breaks down the plugin API (a small wrapper around the wasi:cli/run interface) along with details on implementing the run function, accessing local files, plugin configuration, and more.

Join the community

We're excited to see what the community does with wash plugins, both as users and developers. If you have questions, want to share a plugin, give feedback on the feature, or just talk components and wasmCloud, join us on the wasmCloud community Slack!

Keep up to date

Subscribe to Cosmonic for occasional communication straight to your inbox.