SCUA

How-to

Read command-line arguments

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)