System
Sandbox capability
Several sys/* functions are gated by sandbox capabilities: environment access (env, sys/env-all, sys/set-env) requires ENV_READ or ENV_WRITE, and process operations (shell, sys/which, signal hooks, exit) require PROCESS. They run unrestricted under sema by default but are restricted in sandboxed environments (e.g., the WASM playground). A sandboxed script that attempts to use them without the capability will receive an error.
Environment Variables
env
Get the value of an environment variable. Returns nil if not set.
(env "HOME") ; => "/Users/ada"
(env "PATH") ; => "/usr/bin:/bin:..."
(env "MISSING") ; => nilsys/env-all
Return all environment variables as a map.
(sys/env-all) ; => {:HOME "/Users/ada" :PATH "..." ...}sys/set-env
Set an environment variable for the current process.
(sys/set-env "KEY" "value")
(env "KEY") ; => "value"System Information
sys/args
Return the command-line arguments as a list.
(sys/args) ; => ("sema" "script.sema" "--flag")sys/cwd
Return the current working directory.
(sys/cwd) ; => "/current/dir"sys/platform
Return the platform name.
(sys/platform) ; => "macos" / "linux" / "windows"sys/os
Return the operating system name.
(sys/os) ; => "macos"sys/arch
Return the CPU architecture.
(sys/arch) ; => "aarch64" / "x86_64"Process Information
sys/pid
Return the current process ID.
(sys/pid) ; => 12345sys/tty
Return the TTY device path, or nil if not running in a terminal.
(sys/tty) ; => "/dev/ttys003" or nilsys/which
Find the full path to an executable, or nil if not found.
(sys/which "cargo") ; => "/Users/ada/.cargo/bin/cargo"
(sys/which "nonexistent") ; => nilsys/elapsed
Return nanoseconds elapsed since the process started.
(sys/elapsed) ; => 482937100Session Information
sys/interactive?
Test if stdin is a TTY (i.e., running interactively).
(sys/interactive?) ; => #t in REPL, #f in scriptssys/hostname
Return the system hostname.
(sys/hostname) ; => "my-machine"sys/user
Return the current username.
(sys/user) ; => "ada"Directory Paths
sys/home-dir
Return the user's home directory.
(sys/home-dir) ; => "/Users/ada"sys/temp-dir
Return the system temporary directory.
(sys/temp-dir) ; => "/tmp"Terminal
sys/term-size
Return the terminal's current size as a map {:rows N :cols M}, or nil when no controlling TTY is attached (e.g., when stdout is redirected to a file). Queries ioctl(TIOCGWINSZ) against stdout, then stderr, then stdin.
(sys/term-size)
;; => {:rows 47 :cols 180}Pair with sys/on-signal :winch to redraw on terminal resize:
(define (redraw size)
;; ... layout for size ...
)
(redraw (sys/term-size))
(sys/on-signal :winch (fn () (redraw (sys/term-size))))Unix only
Returns nil on Windows and any non-Unix target.
Signals
Async-signal-safe handlers backed by atomic flags. Signal handlers themselves only flip a flag — your callbacks run later, in the main thread, when you call sys/check-signals. This keeps the single-threaded Rc-based runtime intact.
Unix only
Signal hooks are no-ops on Windows.
sys/on-signal
Register a callback for a signal. Multiple callbacks per signal are supported; they fire in registration order.
Supported signals:
| Keyword | Signal | Typical use |
|---|---|---|
:winch | SIGWINCH | Terminal resize — redraw the UI |
:int | SIGINT | Ctrl-C — clean shutdown |
:term | SIGTERM | Termination request — clean shutdown |
(sys/on-signal :int (fn ()
(println "interrupted, cleaning up")
(exit 0)))sys/check-signals
Dispatch any pending signal callbacks. Call this from your event loop (typically right after io/read-key / io/read-key-timeout returns) so handlers run in a predictable place rather than asynchronously interrupting Sema code.
(let loop ()
(sys/check-signals)
(let ((key (io/read-key-timeout 50)))
(when key (handle-key key))
(loop)))If no signals are pending, this is essentially free — it just checks three atomic booleans.
Shell & Process Control
shell
Run a shell command and return its stdout as a string.
(shell "ls -la") ; => "total 42\n..."
(shell "echo hello") ; => "hello\n"exit
Exit the process with a given status code.
(exit 0) ; exit successfully
(exit 1) ; exit with error