System & files
Everything that reaches outside the program: the disk, the process table, the environment, the clock and the terminal. This is also where permissions bite, so that section comes first.
Permissions
OS/hardware namespaces are sandboxed by default. Grant access with a three-level permission model:
// Level 1 — serez.json (project-wide)
// { "permissions": ["Terminal", "OS", "Env"] }
// Level 2 — file-level
use permissions { OS, Time }
// Level 3 — operation-level (unsafe required for destructive ops)
unsafe {
OS.exec("git", ["status"])
File.delete("temp.txt")
}File I/O
Read and write files with the File namespace:
// Write a file (creates it if it doesn't exist, overwrites if it does)
File.write("data.txt", "Hello, world!")
// Check if it exists
out File.exists("data.txt") // → true
// Read the whole file as a string
let content = File.read("data.txt")
out content // → Hello, world!
// Create an empty file (no-op if it already exists)
File.create("log.txt")Binary files
// Read raw bytes — returns [int] where each value is 0-255
let bytes = File.read_asBinary("image.png")
out bytes.length // number of bytes
// Write raw bytes
File.write_asBinary("copy.png", bytes)Extended file system methods
// List directory contents
let entries = File.listDir("./src")
out entries // → [main.sz, utils.sz, ...]
// Create a directory (including parent dirs)
File.mkdir("output/logs")
// File metadata
let stat = File.stat("data.txt")
out stat.size // → bytes
out stat.isDir // → false
out stat.modified // → Unix ms timestamp
// Rename / move (requires unsafe)
unsafe {
File.rename("old.txt", "new.txt")
}
// Delete file or directory (requires unsafe)
unsafe {
File.delete("temp_dir")
}Practical example — save and load JSON data
let data <string, any> = (
{"name", "Sergio"},
{"score", 42},
{"active", true}
)
// Save
File.write("save.json", JSON.stringify(data))
// Load
let loaded = JSON.parse(File.read("save.json"))
out loaded["name"] // → SergioOS
Process and operating system information. Requires use permissions { OS }.
use permissions { OS }
out OS.platform() // → "windows" | "linux" | "macos"
out OS.pid() // → current process ID
// Execute external command (requires unsafe)
let result = null
unsafe {
result = OS.exec("git", ["log", "--oneline", "-5"])
}
out result.stdout // command output
out result.code // exit code (0 = success)
// Kill a process by PID (requires unsafe)
unsafe {
OS.kill(1234)
}Env
Environment variables and command-line arguments. Requires use permissions { Env }.
use permissions { Env }
out Env.get("HOME") // → "/Users/sergio" or null if not set
out Env.get("PATH") // → full PATH string
let args = Env.args() // command-line args including program name
out args.length
// Set env var (requires unsafe — not thread-safe)
unsafe {
Env.set("MY_VAR", "hello")
}
out Env.get("MY_VAR") // → helloSystem
Read-only system information. Requires use permissions { System }.
use permissions { System }
out System.cpuCount() // → 15 (logical cores)
out System.totalMemory() // → 34279034880 (bytes)
out System.freeMemory() // → 13000000000 (bytes)
out System.hostname() // → "DESKTOP-XYZ"
out System.uptime() // → 168517 (seconds since boot)Time
Timestamps and sleep. Requires use permissions { Time }.
use permissions { Time }
let t1 = Time.now() // Unix timestamp in milliseconds
Time.sleep(500) // pause 500ms
let t2 = Time.now()
out t2 - t1 // → ~500DateTime
Immutable calendar date/time. DateTime.now() / utcNow() read the clock and require use permissions { Time }; from() / fromEpoch() and every field/arithmetic/format operation are pure and need no permission.
let d = DateTime.from(2026, 1, 31, 9, 30, 0)
// fields act as ints, but carry immutable add/reduce/remove
out d.day + 5 // 36
out d.month.add(1) // 2026-02-28T09:30:00 (day clamped to month end)
out d.day.reduce(20) // 2026-01-11T09:30:00
// formatting (moment.js-style; [text] is literal)
out d.format("YYYY-MM-DD HH:mm") // 2026-01-31 09:30
out d.format("D/M/YYYY h:mm A") // 31/1/2026 9:30 AM
out d.weekday // 6 (1=Mon … 7=Sun)
// object-destructuring exposes calendar fields as ints
const {day, month, year} = DateTime.from(2026, 6, 20)
out year + "-" + month + "-" + day // 2026-6-20Members: fields year month day hour minute second ms (each a DateField with .add/.reduce/.remove(n)), read-only weekday dayOfYear daysInMonth, and format(p) toString() iso() timestamp() isLeapYear() isUtc(). Two dates compare by instant.
Terminal
Interact with the terminal emulator — keyboard, mouse, cursor, raw mode. Requires use permissions { Terminal }.
use permissions { Terminal }
// Terminal size
let size = Terminal.getSize()
out "Cols: {size[0]}, Rows: {size[1]}"
// Clear screen and move cursor
Terminal.clear()
Terminal.setCursor(0, 0)
// Write raw byte to stdout (e.g. ANSI ESC = 27)
Terminal.writeByte(27)
// Raw mode + keyboard + mouse (all require unsafe)
unsafe {
Terminal.setRawMode(true)
Terminal.enableMouse(true)
let evt = Terminal.readEvent()
if (evt.type == "key") {
out "Key: {evt.code}" // "a", "Enter", "Esc", "F1", ...
out "Mods: {evt.modifiers}" // ["ctrl"], ["shift"], ...
} else if (evt.type == "mouse") {
out "Mouse {evt.kind} at {evt.col},{evt.row}"
out "Button: {evt.button}" // "left", "right", "middle"
} else if (evt.type == "resize") {
out "New size: {evt.cols}x{evt.rows}"
}
Terminal.enableMouse(false)
Terminal.setRawMode(false)
}Memory (raw allocation)
Manual byte-level allocation, for when you need a buffer with an exact layout. Allocating, freeing, reading, writing, copying and filling must happen inside an unsafe { } block; sizeof, size and offsetOf are safe to call anywhere. A single allocation is capped at 256 MiB.
let ptr = unsafe { Memory.alloc(Memory.sizeof("int64") * 4) }
unsafe {
Memory.fill(ptr, 0) // zero the block
Memory.write(ptr, 0, "int64", 42) // handle, offset, type, value
out Memory.read(ptr, 0, "int64") // 42
out Memory.size(ptr) // 32 — bytes in the allocation
Memory.free(ptr)
}
out sizeof(int) // 8 — the global takes a TYPE, not a stringNote the two are different things. Memory.sizeof("int64") takes a layout name as a string; the global sizeof(int) takes a type keyword and nothing else — sizeof(5) or sizeof(x) is a parse error. See sizeof in the language reference.
The type names accepted by sizeof, read and write are bool, byte, int8, int16, int32, int64, int, uint8, uint16, uint32, uint64, float32, float64, decimal, ptr and str. Out-of-bounds offsets and unknown handles raise a catchable MemoryError.
| Method | Returns | Description |
|---|---|---|
Memory.sizeof(type) | int | Size in bytes of a type name — safe outside unsafe |
Memory.alloc(n) | int | Allocates n bytes (1 B – 256 MiB) → opaque handle — unsafe |
Memory.free(handle) | null | Releases the allocation — unsafe |
Memory.size(handle) | int | Bytes in the allocation — safe outside unsafe |
Memory.read(handle, offset, type) | any | Reads a typed value at a byte offset — unsafe |
Memory.write(handle, offset, type, value) | null | Writes a typed value at a byte offset — unsafe |
Memory.copy(src, dst, n) | null | Copies n bytes between allocations — unsafe |
Memory.fill(handle, byte) | null | Fills the block with a byte value (0–255) — unsafe |
Memory.offsetOf(class, field) | int | Byte offset of a field within a class — safe outside unsafe |