When you run a script, anything you type after the file name is passed to the program:
scua roll.scua 3 --hard
You read those arguments with the sys module:
import sys
let args = sys.args()
sys.args() returns an array of strings
— the user arguments only, 0-based. It does not include the
interpreter or the script path itself (so args[0] is your
first real argument, not the file name — no off-by-one). It is always an
array, empty when there are none, so you never need a nil check.
sys is a plain, always-available module like
math or str. It needs no capability
grant — arguments are inert, public, fixed-at-launch data
(they're right there on the command line), not the secret-bearing
ambient authority that environment variables are. (Environment
variables, when they arrive, will be a granted capability for
exactly that reason.)
#The grammar
scua [scua-options] <file.scua> [program-arguments...]
SCUA's own options (--fast, --allow-fs,
-D, …) come before the file. Once the file
name is seen, everything after it belongs to your program,
verbatim — including tokens that look like flags:
scua --fast game.scua level3 --hard --players=2
# └ scua's └ file └──────── all yours ─────────┘
So inside game.scua, sys.args() is
["level3", "--hard", "--players=2"]. If you ever need to
pass an argument that would otherwise be read as a scua option, put a
bare -- before the file to stop scua's own option parsing
early:
scua -- ./--oddly-named.scua arg1
#Parsing arguments
Arguments are just strings — parse them however your program needs,
using the value-producing if, membership with
in, and tonumber for numerics:
import sys
let args = sys.args()
let name = if args.len() > 0 then args[0] else "world" end -- positional, with a default
let loud = "--loud" in args -- a presence flag
let count = if args.len() > 1 then tonumber(args[1]) else nil end
let times = if count == nil then 1 else count end -- numeric option with a fallback
print(`hello, {name}`)
for _ in 0:times do
print(if loud then "TICK" else "tick" end)
end
$ scua greet.scua alice 2 --loud
hello, alice
TICK
TICK
See the runnable examples/args.scua.
#Agent tools
For stdin / JSON result / exit-status tools (the
shape AI agents and shell harnesses want) — sys.parse_args,
sys.emit / sys.fail, scua schema,
and scua pack — see Write
tools for AI agents.
#Scope: the entry program only
sys.args() (and sys.stdin()) return data
for the program you launched. Inside a spawned actor, both are empty
([] / "") — an actor is an isolated partition
and doesn't inherit the launching program's arguments or stdin (the same
isolation that keeps capabilities from leaking across partitions). Pass
an actor whatever it needs explicitly, in the message that starts
it.
#A note on encoding
A SCUA string is always valid UTF-8. If an argument
isn't valid UTF-8 (rare — usually a stray byte on POSIX, or a lone
surrogate on Windows), the launch fails immediately with a clear message
rather than silently dropping the argument and shifting every later
index:
$ scua tool.scua $'\xff'
scua: tool.scua: argument #0 is not valid UTF-8 (a SCUA string must be UTF-8)