A curated subset of the Go standard library, re-published as a Go module so that the mvm interpreter can load it through the Go module proxy like any other dependency.
mvm interprets Go source. For packages that are pure Go (no assembly, no syscalls, no compiler intrinsics), it is more flexible to interpret the upstream source than to expose a hand-written native bridge:
- Bridges have to track upstream behavior across Go versions; source is upstream behavior.
- Source can be fetched lazily and version-pinned without rebuilding mvm.
- The mvm playground (WASM) embeds a frozen snapshot of this module as
its offline floor and pulls anything else on demand from
proxy.golang.org.
This module is a deliberately partial mirror: performance-critical
or hard-to-interpret packages (fmt, runtime, reflect, sync,
time, crypto/* with assembly fast paths, etc.) stay as pre-compiled
native bridges inside mvm and are intentionally not listed here. mvm's
import resolver checks native bindings before consulting any source FS,
so the choice of which packages to publish here is policy, not a
shadowing concern.
The Makefile copies a curated list of stdlib packages from
$GOROOT/src into the repo root, one directory per package. Test files
(*_test.go) are kept so mvm's mvm test <pkg> runner can exercise
them.
Subdirectories of upstream packages (e.g. crypto/internal, testdata/)
are not copied. Multi-directory packages have to be added explicitly,
one entry per directory.
After installing or upgrading a Go toolchain:
make update
This refreshes every listed package from $(go env GOROOT)/src.
Override GOROOT to sync from a specific install:
make update GOROOT=/path/to/go
Then commit, tag, and push:
git add -A
git commit -m "sync from $(go version | awk '{print $3}')"
git tag v0.X.Y
git push --follow-tags
Note that go build ./... is not the right validation here: upstream
packages routinely import internal/* (e.g. errors/wrap.go pulls
internal/reflectlite), which the standard Go toolchain refuses outside
the std tree. The meaningful check is whether mvm can interpret each
package -- run mvm test github.com/mvm-sh/std/<pkg> and address the
failures by extending mvm (resolving internal/* imports, handling
unsupported syntax, adding missing native bridges) rather than by
mutating the upstream source.
Bump the matching Version constant in mvm
(stdlib/stdmod/stdmod.go) and regenerate the embedded zip:
go generate ./stdlib/...
- Append the import path to
PACKAGESin theMakefile. make update.- Run mvm against the package (
mvm test github.com/mvm-sh/std/<pkg>from a directory outside this module, or wire it as a local replace) and fix any interpreter bugs the new source exposes.
If a package needs subdirectory contents (e.g. path/filepath), add the
subdirectory as its own Makefile entry instead of recursing -- this
keeps the imported set explicit and reviewable.
Some upstream packages cannot be interpreted by mvm without local
adjustment -- typically because they reach into internal/race,
unsafe, or //go:linkname runtime entry points that mvm has no way
to provide. When a small surgical change to the upstream source is the
cleaner fix than a broad mvm extension, commit a patches/<pkg>/
overlay rather than mutating the synced tree by hand (which make update would wipe).
Patching only applies to stdlib packages mirrored into this repo from
$GOROOT. Third-party modules fetched via the Go proxy are never
patched -- mvm adapts to those through native bridges or interpreter
fixes.
patches/
<pkg>/
*.go # full-file overrides; same name overwrites upstream,
# new name adds a sibling file
.delete # newline-separated relative paths to remove after sync
# (lines starting with # and blank lines are ignored)
NOTES.md # human rationale; not copied into the package
The Makefile applies .delete first, then drops the *.go overrides
on top. Anything not listed is left as the upstream copy.
Upstream iter/iter.go (~470 lines in go1.26) defines Seq, Seq2
and the Pull/Pull2 push-to-pull adapters. The adapters use
linkname'd runtime coroutine primitives (newcoro, coroswitch) plus
internal/race -- none available to mvm.
patches/iter/ reduces the package to just the type declarations:
iter.go-- 21-line replacement keepingSeqandSeq2, dropping Pull/Pull2 and their imports..delete-- removespull_test.go, which exercises only the dropped functions and would no longer compile.NOTES.md-- explains why and what mvm users should do instead (range-over-func is interpreted natively, sofor v := range seqworks withoutiter.Pull).
After a Go upgrade, run
make diff-upstream
to see every mvm-specific delta against a fresh upstream sync. Use it before tagging a new version to confirm patches still mean what they meant.
The packages here are copies of upstream Go sources and remain under
their original BSD-3-Clause license; see LICENSE.