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.rs resolves argv to a Mode — interactive (carrying a login flag), script, or -c (Command) — each carrying only the flags valid for it; startup.rs decides whether this process is the shell at all and holds the binary’s two engine installers (repl, batch), main.rs is the thin dispatch over the answer, and batch.rs runs the non-interactive modes.
  • One boot, one door. Batch and the REPL both boot an IdentityTransport from their installer, then dispatch the _ral-boot door (ral/src/boot_door.rs) as their first run, so both keep exit N and the --capabilities status 2 identically; every evaluation after it — a line, a script, a prompt, a hook — is one dispatch through dispatch_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 --surface or the rc surface: 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 Session state machine and one-dispatch cycle: the two-stage boot, the ReplHost, 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 Frontend trait 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.