Map: repl (the ral binary)
ral/ is the ral binary — a thin front-end over ral-core.
It is argv dispatch into an engine it boots in process and speaks to only
through the engine protocol, driving one of three
selectable frontends over the REPL session and plugins; the language,
evaluator, and capability machinery all live in core, and neither front-end
holds a Shell.
- Argv dispatch.
cli.rsresolves argv to aMode— interactive (carrying a login flag), script, or-c(Command) — each carrying only the flags valid for it;startup.rsdecides whether this process is the shell at all and holds the binary’s two engine installers (repl,batch),main.rsis the thin dispatch over the answer, andbatch.rsruns the non-interactive modes. - One boot, one door. Batch and the REPL both boot an
IdentityTransportfrom their installer, then dispatch the_ral-bootdoor (ral/src/boot_door.rs) as their first run, so both keepexit Nand the--capabilitiesstatus 2 identically; every evaluation after it — a line, a script, a prompt, a hook — is one dispatch throughdispatch_to_report, and every read of engine state is a typed probe. - Two frontends. The interactive REPL presents one
Surface— minimal (canonical-stdin fallback), readline (the default full editor), selected with--surfaceor the rcsurface:key. The structural surface (a ratatui projection) was retired in 261006 (repl-as-structural-surface).
The frontend is a layer above the engine. Editor state is host-side, in the
REPL’s ReplHost and PluginRuntime; the _ed-* builtins are thin
engine-side doors that ask the host for it through the `repl-editor
enquiry, and core holds no editor state at all
(repl-builtins-stay-in-repl).
A guiding constraint: ral’s top-level runs carry persistent state, and the
REPL makes that state the thing the loop threads.
Subsystems
- startup — argv →
Mode, the engine installers, batch execution over its own engine, the build-baked prelude, platform glue (ral/src/main.rs,startup.rs,cli.rs,batch.rs,boot_door.rs,platform.rs,build.rs). - loop — the
Sessionstate machine and one-dispatch cycle: the two-stage boot, theReplHost, prompt, rc/profile sourcing engine-side, value printing, error formatting (ral/src/repl/session*,exec.rs,host.rs,enquiry.rs,prompt.rs,config*,theme.rs,errfmt.rs). - frontend — the
Frontendtrait and its two implementations (minimal, rustyline), plus the frontend-neutral prefix-then-fuzzy completion engine and shared highlight table (ral/src/repl/frontend*,completion.rs,complete.rs,cursor.rs,highlight_style.rs). - plugins — the plugin runtime, the
_ed-*editor doors, the plugin load doors, and the one ordered keybinding router (chord, guard, first match, built-in tail) every frontend dispatches through; hooks and aliases live engine-side, editor state host-side, and every hook run is a dispatch (ral/src/repl/plugin*,plugin/ed_builtins.rs,plugin/load.rs,keybinding.rs).
The POSIX bridge
ral/src/bridge.rs is ral invoked as ral-sh, a symlink registered in
/etc/shells (single-binary, docs/SPEC.md
§16.7). main asks it after refuse_setuid and before argv is read as text.
decide is pure and takes the first match over the arguments: a short cluster
with c, or any argument that is not a cluster or --login → /bin/sh; a
cluster with l/i, or --login → ral; no arguments on a tty → ral;
otherwise /bin/sh. So -l script.sh reaches /bin/sh and -l alone reaches
ral.
The bridge resolves nothing through the environment (/bin/sh is a literal
path, and the ral branch does not exec but continues as ral), forwards argv
as OsString untouched, and turns a leading dash on argv[0] into -sh. Its one
exec is the silent syscall site silent:respawn-posix-sh
(io-surface).
Siblings
core is the engine this frontend drives; exarch is the agent that embeds the same engine instead of a human at the prompt.
These pages point at code, they do not restate it. The design rationale lives
in the durable layer; the formal account is docs/SPEC.md.