Arrival
Arrival is a sandboxed R7RS-subset Scheme for LLM agents that need to compute, not just call tools. Embed it when an agent should filter, map, and compose inside a symbolic REPL and hand plain JavaScript back to the host, instead of emitting a stream of opaque JSON tool calls.
The language is a faithful R7RS subset: no set!, no call/cc. Syntax extends toward Clojure, Racket, and Common Lisp only where R7RS is silent; a violation gets a diagnostic that names the intended form. The API is 0.x and still settling.
Install and run
Section titled “Install and run”@inhuman.tools/arrival is ESM-only and needs Node.js 22 or newer.
npm install @inhuman.tools/arrivalimport { exec } from "@inhuman.tools/arrival";
// One plain JS value per top-level form. The base roster assembles on first call.const [result] = await exec(`(filter (lambda (x) (> x 5)) (list 1 3 7 9 2))`);console.log(result); // [7, 9]exec(code, options?) parses, runs, and unwraps each top-level result to plain JS. BASE_ROSTER (R7RS, the default SRFIs, and the polyglot packs) is always assembled. Pass capabilities to add tools; they do not replace the base.
A bare exec or execState mints a fresh scope (scope ?? LexicalScope.fresh()), so top-level defines do not accumulate. Reuse one LexicalScope.fresh() when a multi-turn session should keep bindings. Isolation across calls is the default.
When to use the CLI
Section titled “When to use the CLI”Call exec from the library when your process is the host. Use the CLI when a person or a script should run a program, open a REPL, or check a file without embedding the interpreter.
npx @inhuman.tools/arrival-cli --help# or: npm install -g @inhuman.tools/arrival-cli # installs the `arrival` bin@inhuman.tools/arrival-cli is arrival run, a REPL, and arrival check. Its contract is packages/arrival-cli; this page does not restate it.
Sandbox caveat
Section titled “Sandbox caveat”The base reaches nothing ambient by construction: no filesystem, no process, no network, no ports, no clock, no random, and no host globals (window, global, process, require). That is algebraic as well as practical. An ambient read has no construction site to root a value’s lineage at, so effects return as capability verbs that stamp provenance at the membrane.
At 0.x this is not a hard security boundary. Sandbox escape is still feasible, at least via property access and some rosetta-layer aspects.
Do not expose Arrival to untrusted input without additional isolation, use it in security-critical contexts, deploy it without containerization, or trust the sandbox. Isolation reports: security@here.build.
Interpretation is roughly 10–100× native JS. Keep Scheme for orchestration; register hot functions as capability verbs.
What’s next
Section titled “What’s next”- A tool is an
EnvCapability: a name, a doc line, a typed contract, an implementation. Authoring ispackages/arrival/docs/writing-capabilities.md. - Host data enters as a typed
define/overridableparameter through theoverridablecapability andconfig.params, not as an ambient global. staticValidation: "on"reports every problem before evaluation (default"off"). The pass cannot see bindings a(require …)spills at runtime.- Lineage is opt-in:
tap: new EvalTrace()from@inhuman.tools/arrival/provenance. Without a tap, provenance reads[]. - Read
packages/arrival/docs/PRINCIPLES.md,docs/PROVENANCE.md, and, for agents,docs/llm-agent-card.md.
Early-stage work welcomes security review of the sandbox, performance benchmarks, Chibi conformance (every flipped it.fails is a gift), and teaching doors on dead-end errors. Issues are welcome; external pull requests are not the current focus. Sibling packages are listed in the repository README. Each package’s LICENSE.md is authoritative (MIT; the interpreter is a fork of LIPS.js).
Sources
Section titled “Sources”arrival/README.mdarrival/packages/arrival/README.md