Single binary
The ral language runtime ships as a single executable. The lexer, elaborator, typechecker, evaluator, the bundled coreutils and grep, and the capability sandbox are all linked into the one binary — none is a separate program ral shells out to. Every re-exec is a multicall of this same binary behind a hidden sentinel flag, never a sibling helper:
- a process-staged pipeline runs each ral stage — and each bundled tool, which
is demoted to a ral stage — through
--ral-pipeline-stage-helper, and pins the group’s pgid with--ral-pipeline-anchor(pipelines); - an
fs/netgrant that drops into an OS sandbox re-execs under--internal-sandbox-block, confined by thesandbox_projectionof the live grant.
A re-exec’d child reconstructs a shell from a wire snapshot, evaluates, and reports a structured outcome through one shared protocol (child_eval). This in-process linking is also what routes the bundled tools through the same capability chokepoint as the structured primitives.
The hard rule concerns the runtime: do not factor ral’s functionality into a sibling helper crate or a second shipped executable, and do not introduce a runtime dependency on an external program for core behaviour.
One deliberate piece stands outside the runtime: ral-sh, a thin POSIX-bridge
login shell (docs/SPEC.md §21.1). It carries no ral-core dependency and
forwards non-interactive invocations to /bin/sh; it exists so ral can be
registered as a login shell, not to divide the runtime. It is a registration
shim, not a functional split.