A fork of wazero — the zero-dependency WebAssembly runtime for Go — with CodeTracer execution tracing built in.
Upstream wazero is a conformant WebAssembly runtime that compiles and executes
.wasm modules with zero external dependencies. This fork adds execution
tracing: as a WASM program runs, every step, function call, return, and
variable mutation is recorded into a CodeTracer trace that can be loaded into
the CodeTracer time-traveling debugger.
Key additions on top of upstream wazero:
--out-dirflag on therunsubcommand — produces a CTFS trace bundle that the CodeTracer time-travel debugger can load. Falls back to theCODETRACER_WASM_RECORDER_OUT_DIRenvironment variable when omitted.CODETRACER_WASM_RECORDER_DISABLEDenvironment variable — when set, runs the target through wazero without writing any trace artefacts. Useful for wrapping wazero under a recording-aware CI / IDE harness without rebuilding the command line.--stylusflag — enables EVM hook functions for Arbitrum Stylusdebug_traceTransactionsupport.tracewriter/package — aTraceRecorderinterface and a single CTFS-producing implementation (CtfsTraceWriter) that links via cgo into the Nim C FFI exposed bycodetracer-trace-format-nim. Pre-2026-05-08 the package also exposed a pure-Go writer (GoWriter, legacy three-file JSON layout) and a Rust FFI writer with aRustFormatenum (FMT_JSON/FMT_BINARY_V0/FMT_BINARY) selectable through a--formatflag; all were removed in the convention compliance pass documented inAUDIT-CTFS-2026-05.md.- Tracing hooks in
internal/— wazero internals are instrumented to call theTraceRecorderat each execution step.
The CodeTracer recorder convention names binaries
codetracer-<language>-recorder (see
codetracer-specs/Recorder-CLI-Conventions.md
§1). The wasm recorder is the one documented exception — this is a
fork of Tetrate's wazero with
tracing layered in, not a CodeTracer-named tool, so the binary keeps the
upstream wazero name. Convention §1 explicitly carves this out.
The upstream wazero code is kept largely intact; tracing is injected via hooks rather than invasive modifications, making it straightforward to merge upstream updates.
The recorder always writes CTFS (Recorder-CLI-Conventions.md §4). There is
no --format flag and no CODETRACER_FORMAT environment variable. For
human-readable inspection of a recorded trace, pipe the bundle through
ct print from
codetracer-trace-format-nim:
wazero run --out-dir ./traces program.wasm
ct-print --full --strip-paths ./traces/program.ct- Go 1.22+ (tested with Go 1.24)
- Nix (recommended) — provides all dependencies via
nix develop
nix develop # enters dev shell with Go, Rust, and tools
just build # produces ./wazero binarygo build -o wazero ./cmd/wazero # pure-Go build (no FFI)The recorder lives alongside its sibling repos in the metacraft workspace:
metacraft/
├── codetracer-wasm-recorder/ # this repo
├── codetracer-trace-format-nim/ # ships the `ct-print` CLI used by tests
├── codetracer/ # main CodeTracer repo
└── ...
The nix develop shell hook runs scripts/detect-trace-format.sh to
locate the sibling codetracer-trace-format-nim checkout, build the Nim
C FFI static library if necessary, and export the cgo flags needed to
link the wazero binary against libcodetracer_trace_writer.a +
libzstd. The recorder will fail to link without these inputs.
nix build # wazero with the CTFS-stub fallback (recording non-functional)To produce a recording-capable binary, the consuming flake must pass a
pre-built codetracer-trace-format-nim derivation to wazero.nix.
just test # full upstream wazero test suite + cgo CTFS writer
just test-tracewriter-go # tracewriter package tests (currently empty)
just check-all # lint + tracewriter tests + CLI convention check
just cross-test # WASM flow integration tests against sibling codetracerCI workflows run on self-hosted NixOS runners:
- CI (
ci.yml) — lint, tracewriter tests, and Nix flake build verification. The CTFS writer test path requires thecodetracer-trace-formatsibling, whose revision is resolved from the repo-workspaces workspace lock viascripts/resolve-sibling-rev.sh, so the cgo build can link against the FFI library. - Cross-Repo Integration Tests (
cross-repo-tests.yml) — builds the wazero binary and runs end-to-end WASM flow tests in the codetracer repo's db-backend. Supports bidirectional triggering viarepository_dispatchso the codetracer repo can trigger these tests when WASM-related code changes. Sibling revisions are resolved from the workspace lock viascripts/resolve-sibling-rev.sh; the workflow_dispatch / repository_dispatchcodetracer_refinputs still override the codetracer revision. - Upstream Tests (
commit.yaml) — the original wazero test matrix (multi-platform, multi-Go-version, scratch container, BSD VMs, fuzzing).
# Run a WASM program and produce a CTFS trace bundle:
./wazero run --out-dir ./trace-output program.wasm
# Same, but configured through the env-var fallback (Recorder-CLI-Conventions.md §5):
CODETRACER_WASM_RECORDER_OUT_DIR=./trace-output ./wazero run program.wasm
# Run the target without recording — useful when a wrapping harness
# always invokes wazero with --out-dir but the user wants to skip
# recording for one invocation:
CODETRACER_WASM_RECORDER_DISABLED=1 ./wazero run --out-dir ./trace-output program.wasm
# Mount a directory and pass environment variables:
./wazero run --mount ./data:/data --env KEY=VALUE program.wasm
# Arbitrum Stylus debug tracing:
./wazero run --out-dir ./trace-output --stylus ./evm-hooks.so program.wasm
# Convert a recorded bundle to JSON via ct print (sibling repo
# codetracer-trace-format-nim). The output is a single
# `<program-basename>.ct` (CTFS) container; ct-print --full decodes it
# back to JSON.
ct-print --full --strip-paths ./trace-output/program.ctSee examples/ for ready-to-record WASM programs and a
walkthrough of recording + replay via the ct CLI, including the
column-aware step-over demo built on
examples/recorder-golden/column_aware.rs.
cmd/wazero/ CLI entry point (compile, run, version subcommands)
tracewriter/ TraceRecorder interface + cgo CtfsTraceWriter + Nim FFI header
scripts/ Dev environment and cross-repo test scripts
internal/ Upstream wazero internals with tracing hooks
experimental/ Upstream experimental features (logging, sockets)
vendor/ Vendored Go dependencies
This repo is part of the CodeTracer ecosystem. Related repositories:
| Repository | Purpose |
|---|---|
| codetracer | Main CodeTracer debugger (Nim + Electron) |
| codetracer-trace-format-nim | Nim CTFS writer + C FFI consumed by the cgo CtfsTraceWriter |
| trace_record | Go library exporting the value-record types used in tracewriter/ |
| codetracer-python-recorder | Python execution recorder |
| codetracer-native-backend | Record/replay backend |
| codetracer-shell-recorders | Bash/Zsh recorders |
This project is licensed under the Apache 2.0 License — see LICENSE for details.
wazero is a registered trademark of Tetrate.io, Inc.