Thank you for your interest in contributing to wash! This document provides guidelines and information for contributors.
If you have feature suggestions, find bugs, or have questions, please submit an issue here. Pull requests are welcome! The good first issue label is a great way to find a starting point for new contributors.
- Rust (latest stable version)
- Git
- WebAssembly targets:
wasm32-wasip2andwasm32-wasip1(installed viarustup target add wasm32-wasip2 wasm32-wasip1) are both needed to build thewash-runtimewasm test fixtures.
git clone https://github.com/wasmcloud/wasmCloud.git
cd wasmCloud
cargo buildThe wash-runtime integration tests and benchmarks load precompiled wasm
components from crates/wash-runtime/tests/wasm/. Build them once with the
xtask task runner before running those tests (re-run it whenever you change
a fixture under crates/wash-runtime/tests/fixtures/):
# Build the wasm test fixtures (writes crates/wash-runtime/tests/wasm/*.wasm)
cargo xtask build-fixtures# Run all tests
cargo test
# Run specific test suites
cargo test --lib
cargo test --bin washThis repository is a workspace. The wash CLI lives in crates/wash and the core Wasm runtime it depends on lives in crates/wash-runtime:
crates/
├── bench-tools/ # Benchmarking utilities
├── wash/ # wash CLI crate
│ └── src/
│ ├── cli/ # CLI structs and command handling
│ │ ├── mod.rs
│ │ └── <subcommand>.rs
│ ├── lib.rs # Module exports
│ ├── main.rs # The wash binary entrypoint
│ ├── config.rs # Configuration management
│ └── new.rs # Project creation functionality
└── wash-runtime/ # Core Wasm runtime powering wash
└── src/
├── engine/ # Wasmtime engine setup and execution context
│ ├── ctx.rs # Store context (WASI, linking state)
│ ├── value.rs # Runtime value types
│ └── workload.rs # Workload execution logic
├── host/ # Host-side interface implementations
│ ├── allowed_hosts.rs # Network allow-list enforcement
│ ├── http.rs / http_p3.rs # HTTP outbound host (P2 and P3)
│ └── sysinfo.rs # System information host
├── plugin/ # WASI and wasmCloud capability plugins
│ ├── wasi_blobstore/ # wasi:blobstore implementation
│ ├── wasi_config/ # wasi:config implementation
│ ├── wasi_keyvalue/ # wasi:keyvalue implementation
│ ├── wasi_logging/ # wasi:logging implementation
│ ├── wasi_otel/ # OpenTelemetry WASI bridge
│ ├── wasi_webgpu/ # wasi:webgpu implementation
│ ├── wasmcloud_messaging/ # wasmCloud messaging capability
│ └── wasmcloud_postgres/ # wasmCloud Postgres capability
├── sockets/ # WASI sockets host implementations (TCP/UDP/network)
├── washlet/ # Washlet runner (embedded Wasm plugin host)
├── lib.rs # Crate root and module exports
├── observability.rs # Tracing and metrics setup
├── oci.rs # OCI registry image pulling
├── types.rs # Shared runtime types
└── wit.rs # WIT interface bindings
All Rust code in this project must follow these conventions:
- Never use
unwrap(),expect(), orpanic!()- Use proper error handling withResultandOption - Use
anyhow::Resultfor functions that can return errors - Add context to errors using
.context()method:operation().context("failed to perform operation")? - Error messages and log contexts should start with lowercase and not end with periods
- Use string interpolation:
format!("{value}")instead offormat!("{}", value)
- Never use
println!oreprintln!for output - Use theCommandOutputstruct for all command results - Use
tracingcrate macros for all logging:info!(),debug!(),warn!(),error!(),trace!() - Use the
#[instrument]macro for any operations that take longer than 100ms - Instrumented functions should have descriptive names with verbs (e.g., "Building component", "Fetching template")
- Prefix all environment variables with
WASH_to avoid conflicts and ensure clarity
- Use the
CommandOutputstruct for all command return values - Commands should return structured data that can be formatted as text or JSON
- Follow clap derive patterns for argument parsing
This CLI is instrumented with the tracing crate:
- Use
#[instrument(level = "debug", skip_all, name = "operation_name")]for long-running functions - Log levels should be appropriate:
error!()- Unrecoverable errorswarn!()- Recoverable issues or deprecated usageinfo!()- User-facing progress informationdebug!()- Developer debugging informationtrace!()- Detailed execution flow
Example:
use tracing::{info, instrument};
#[instrument(level = "debug", skip_all, name = "building_component")]
pub async fn build_component(&self, ctx: &CliContext) -> anyhow::Result<CommandOutput> {
info!("Building WebAssembly component");
// ...
Ok(CommandOutput::ok("Component built successfully", None))
}- Fork the repository and create your feature branch from
main - Write tests for any new functionality
- Ensure all tests pass with
cargo test - Follow the code style guidelines outlined above
- Update documentation if you're changing behavior or adding features
- Write clear commit messages that explain what and why, not just what
<type>: <description>
[optional body]
[optional footer]
Types:
feat:- New featurefix:- Bug fixdocs:- Documentation changesstyle:- Code style changes (formatting, etc.)refactor:- Code refactoringtest:- Adding or updating testschore:- Maintenance tasks
All submissions require review. We use GitHub pull requests for this process.
Releases ship every two weeks: each Tuesday at 16:00 UTC on the train's cycle, the next
vX.Y.Z is cut from main automatically. Anything merged before the train leaves ships in
that release. See RELEASE_RUNBOOK.md for details.
- Write unit tests for new functionality
- Include integration tests for CLI commands when appropriate
- Test error cases and edge conditions
- Ensure tests are deterministic and don't depend on external services
- Update README.md if you're changing user-facing functionality
- Add inline documentation for public APIs
- Update command help text if you're modifying CLI behavior
- Rust Style Guide - Official Rust coding standards
- WebAssembly Component Model - Learn about the component model
- WASI Preview 2 - WebAssembly System Interface