Add WASI (wasip1) build target - #3
Merged
Merged
Conversation
Compile tree2scaffold to a portable GOOS=wasip1 GOARCH=wasm module that runs
under any WASI runtime (wasmtime/wasmer/wazero/Node) with a preopened directory.
- internal/env: a small Environment interface with build-tagged implementations
(native exec-backed; wasip1 no-op). Keeps os/exec out of the WASI binary while
native behavior is unchanged.
- pkg/scaffold generators probe the host (go version, git remote, cwd) through the
injected Environment and fall back gracefully when unavailable; replace the
exec("pwd") call with os.Getwd(); fix go-version parsing for patch-less versions.
- getInput reads stdin directly under WASI, where the clipboard is unavailable and
char-device detection is unreliable; empty input yields an actionable error.
- just: opt-in `build wasm{,-vet,-run,-release}` and `test wasm` recipes, excluded
from `build all`.
- Add a skip-aware WASI integration test and a GitHub Actions wasm workflow.
- Document the WASI build, runtime contract, and sandbox limitations in the README.
The public API of pkg/scaffold is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a supported way to compile
tree2scaffoldto a portableGOOS=wasip1 GOARCH=wasm(WASI Preview 1) module that runs under any WASIruntime (wasmtime, wasmer, wazero, Node) with a preopened directory, scaffolding
real files inside the sandbox from a single architecture-independent
.wasm.The native CLI is unaffected and the public API of
pkg/scaffoldis unchanged.What changed
internal/env— a smallEnvironmentinterface abstracting the hostprobes that don't work under WASI (
go version,gitremote, cwd, clipboard),with build-tag-selected implementations:
env_exec.go(//go:build !wasip1) — exec-backed, as before.env_wasip1.go(//go:build wasip1) —ErrUnsupportedsentinels +os.Getwd.This keeps
os/execout of the WASI binary entirely (verified viago list -deps), while native builds keep their existing behavior.pkg/scaffold— generators probe the host through the injectedEnvironmentand degrade gracefully when a probe is unavailable. Also:exec("pwd")withos.Getwd()(portable, strictly better on native too);go1.24yields1.24(was1);module /.cmd/tree2scaffold—getInputnow reads stdin directly under WASI, wherethe clipboard is unavailable and
ModeCharDevicepipe-detection is unreliable;empty input yields an actionable "pipe a tree via stdin" error.
just— opt-in recipes in.justfiles/, deliberately excluded fromjust build all:just build wasm·wasm-vet·wasm-run·wasm-releasejust test wasmCI —
.github/workflows/wasm.ymlbuilds, smoke-tests under wasmtime, runsthe integration test, and uploads the
.wasm+ SHA-256 (attaching to releases onv*tags).Tests —
test/wasm_integration_test.go, skip-aware (runs only when aruntime is present), reusing the existing scaffold-and-verify pattern.
README — a "Running as WebAssembly (WASI)" section: build, runtime contract,
embedding, and sandbox limitations.
Runtime contract
WASI is capability-based, so the runtime must preopen a writable directory
mapped to the guest root
/and setPWD=/:Sandbox limitations (by design)
WASI Preview 1 has no process model, so exec-backed niceties are inert and fall
back gracefully: clipboard input is unavailable (stdin only), the generated
go.modGo version uses the built-in default, and module-name inference uses adefault. All path-based scaffolding, content generation, and stdio work normally.
Verification
go build ./...,go vet ./..., and the full test suite (TEST_ALL=1 go test ./...) pass.GOOS=wasip1 GOARCH=wasm go build+go vetpass;os/execis absent from theWASI binary's dependency graph.
node:wasi):files written to the host via the preopen, exit code 0.
Toolchain
Standard Go (the project's
go 1.24.2). TinyGo was evaluated and deferred: itsonly edge is binary size, which is irrelevant for a sandbox CLI, and it would
require linking-out
os/execbefore it builds at all.Note on scope
This branch contains two commits ahead of
main:Add justfile and ran go fmt(pre-existing) — introduces the modularjustsystem (
Justfile+.justfiles/) and runsgo fmt. The WASI recipes build onthis. Its
go fmtpass is what produces the formatting-only churn inpkg/parser,pkg/scaffold, andtest/(no behavior change).Add WASI (wasip1) build target— the WASI work described above.