Environment variables are authority, not inert data:
they're invisible, often hold secrets (DATABASE_URL,
AWS_SECRET_ACCESS_KEY), and span the whole process. So
unlike command-line
arguments (which are public and need no grant), reading the
environment is a host-granted capability — the
env module doesn't exist unless you turn it on.
#Granting the capability
scua --allow-env=PORT,HOST,LOG_LEVEL script.scua # grant exactly those three names (the safe default)
scua --allow-env script.scua # grant every variable (trusted-host shorthand)
Without a grant, import env is a compile
error, before a line runs:
$ scua script.scua
script.scua:1: module `env` needs the `env` capability, which this run was not granted — grant it with `--allow-env` on the CLI, or the host's capability API when embedding
The per-name allowlist is the point: a variable you
didn't grant reads as nil even when it is set in the
environment, so a script can never see a secret it wasn't given.
Prefer --allow-env=NAME,...; reach for bare
--allow-env only when the script and the operator are the
same trusted party.
#Reading values
import env
let port = env.get("PORT") ?? "8080" -- missing/un-allowlisted → nil; ?? gives a default
let host = env.get("HOST") ?? "localhost"
-- required variable
if env.get("API_KEY") == nil then
error("API_KEY is required — set it in your environment")
end
env.get(name) returns the value as a string, or
nil if the variable was unset or not in the allowlist. A
missing variable is a normal nil, not an error. The module
is read-only — there is no env.set.
#What you can rely on
- Snapshot at launch. The environment is captured
once when the script starts, so
env.getis a pure lookup with no surprises mid-run — and a run's inputs are reproducible (recorded alongside the RNG seed). A change to the environment after launch is not seen. - Per-partition. Inside a spawned actor,
envis not granted — authority doesn't leak across partitions. Pass an actor what it needs in its starting message. - UTF-8. Values are UTF-8 strings. A non-UTF-8
allowlisted value fails the launch with a clear message (rather
than silently returning
nil); under bare--allow-env, a non-UTF-8 variable is skipped with a warning.
See the runnable examples/env.scua
(scua --allow-env=PORT,HOME examples/env.scua).