Runtime and Builtins
This page explains the runtime story behind the CLI output and the sts:* builtin modules.
The normal workflow
For most application teams, the path is simple:
- author
.sts - run
soundscript check - use
soundscript compileto produce deployable output - keep packaging and deployment close to how JS/TS teams already work
Compiler-owned builtin modules
soundscript ships a focused builtin module surface under sts:*.
These modules are compiler-owned. They are not regular npm packages that happen to share a prefix. That matters because the checker and compiler can reason about them directly.
import { normalizeThrown } from "sts:failures";
import { U8, type u8 } from "sts:numerics";
The modules most app teams will notice first
sts:prelude
Owns the small shared surface around core value-level helpers such as Result and Option.
sts:failures
Owns Failure, ErrorFrame, and normalizeThrown(...) for the cases where code needs an explicit
normalized error value inside the current scope.
sts:json
Owns JSON boundary helpers so parsing and stringifying can live on an explicit soundscript surface instead of disappearing into unchecked assumptions.
sts:numerics
Owns explicit fixed-width numeric types and helpers for the cases where host number semantics are
too implicit.
Other builtin families
The wider supported builtin surface also includes:
sts:comparests:hashsts:decodests:encodests:codecsts:derivests:asyncsts:hktsts:typeclasses
Those are real parts of the surface, but most application teams should not need all of them on day one.
Why builtins exist at all
The builtin surface gives soundscript a place to define:
- standard failure boundaries
- standard decoding and encoding contracts
- standard numeric semantics where JS host numerics are not enough
- compiler-known helpers that stay consistent across tooling
This is different from “invent a huge new stdlib.” The builtin surface is intentionally focused.
Builtins versus ecosystem packages
soundscript does not require you to avoid ordinary npm packages.
The model is:
- use
sts:*when you want a compiler-owned surface - use normal ecosystem packages when they solve the job
- mark the boundary explicitly when
.stsdepends on regular code
That keeps the language usable in existing JS/TS applications instead of turning every adoption into an ecosystem fork.
A note on Wasm-oriented features
Some builtin surfaces, especially fixed-width numerics and #[value], matter more if you are
thinking about Wasm. The main docs path still starts with ordinary app code.