Script context GitHub issue
- All slots at a glance
- Detail
- %engine.root
- %engine.tmp
- %engine.stdin / %engine.stdout / %engine.stderr
- %engine.network
- %engine.network.http_client
- %engine.network.sockets
- %engine.network.uds
- %engine.network.puck
- %engine.env
- %engine.argv
- %engine.now
- %engine.random
- %engine.random.uuid
- %engine.random.number
- %engine.random.string
- %engine.pid
- %engine.platform
- %engine.platform.os
- %engine.platform.architecture
- %engine.encryption
- %engine.encryption.signing
- %engine.encryption.sha
- %engine[<key>] — arbitrary engine-passed values
- See also
vibecode
{"vibecode": { "doc": "script_context", "role": "catalog of what the engine passes INTO a running Caspian script via %engine. Opens with a single flat list of every standard %engine.X slot, with each slot name linking to its detailed entry below. Plus the %engine[<key>] escape hatch for arbitrary engine-passed values.", "audience": "Caspian developers asking 'what does the engine put in my script's hands?'", "scope_boundary": "what_engine_actively_binds_via_percent_engine; does_NOT_cover_sugar_apis_like_percent_net_percent_utils_percent_chain_or_predefined_classes_reachable_via_percent_puck", "layout": "single_glance_list_at_top_with_links_to_details_below", "key_concepts": ["percent_engine_is_the_only_passing_in_surface", "single_flat_list_with_links_to_details", "standard_slots_plus_bracket_access_escape_hatch", "user_role_only_top_level_only"] }}
The engine binds %engine as the user script's gateway to host resources. This doc catalogs every standard slot on %engine plus the arbitrary-value escape hatch.
%engine is user-role-only and top-level only — only user code can reach %engine; nested libraries and other roles cannot. Capabilities flow down the chain by being passed as parameters, never by reaching back up to %engine. See roles.md.
Out of scope here: sugar APIs like %net, %utils, %chain (those wrap engine slots and are documented in their own specs), classes reachable via %puck['...'] lookup (those are looked up, not passed in), and context-specific bindings inside blocks ($request, $fork, $hash, etc. — each documented at its feature's home).
All slots at a glance GitHub issue
⚠ Only user code can access
%engine.*. Every slot in the table below is user-role-only. Nested libraries and other roles cannot reach%engineat all. Idiomatic code uses the global form (rightmost column) when one exists;%engine.*is reserved for the few capabilities where there's no global, or where user code is the only role that should ever touch the surface.
| Slot | Type | One-line purpose | Global form |
|---|---|---|---|
%engine.root |
dirjail | Root filesystem dirjail | %utils.file_system |
%engine.tmp |
dirjail (fresh per access) | Each access returns a new temp dirjail; auto-deletes when out of scope | %utils.tmp |
%engine.stdin |
stream | Standard input | %stdin |
%engine.stdout |
stream | Standard output | %stdout |
%engine.stderr |
stream | Standard error | %stderr |
%engine.network |
object | Overall network surface | %net |
%engine.network.http_client |
factory | Produces new HTTP client instances | %net.http_client (plus %net.fetch sugar) |
%engine.network.sockets |
namespace | Raw socket constructors (tcp, ssl, udp) |
%net.tcp, %net.udp, %net.ssl, %net.tcp_listen, %net.udp_listen |
%engine.network.uds |
namespace | Unix-domain-socket server constructor | %utils.network.uds |
%engine.network.puck |
object | The Puck interface — class lookup, registration, deletion | %puck (plus %[url] shorthand) |
%engine.env |
hash-shaped | Environment-variable accessor | %utils.env |
%engine.argv |
array of strings | Command-line arguments | %utils.argv |
%engine.now |
timestamp | Current timestamp | %utils.now |
%engine.random |
namespace | uuid, number, string — random-data primitives |
%utils.random |
%engine.random.uuid |
method | Fresh UUID | %utils.random.uuid |
%engine.random.number |
method | Random number in a given range | %utils.random.number |
%engine.random.string |
method | Random string of a given length/alphabet | %utils.random.string |
%engine.pid |
integer | OS process ID | (TBD — none yet; %process.pid possible) |
%engine.platform |
namespace | Container for os and architecture |
no global form |
%engine.platform.os |
hash | OS family, distribution, version, kernel, etc. | no global form |
%engine.platform.architecture |
string | x86_64, arm64, etc. |
no global form |
%engine.encryption |
namespace | Container for signing and sha |
%utils.encryption |
%engine.encryption.signing |
object | Ed25519 signing and verification | %utils.encryption.signing |
%engine.encryption.sha |
object | SHA-family hashing primitives | %utils.encryption.sha |
%engine[<key>] |
any | Arbitrary engine-passed values (escape hatch) | (no global form — engine-direct only) |
The pattern. %engine.X is the user-only, top-level slot — direct access to the underlying capability. Most slots also have a global form under %utils, %net, %puck, or a dedicated top-level method like %stdout. The global forms are reachable from any role (subject to that role having been granted the capability); %engine.X access is restricted to top-level user code. Where a global form is (TBD), the capability hasn't been given a non-user surface yet — either because it doesn't make sense for non-user roles, or because the sugar hasn't been designed.
Detail GitHub issue
%engine.root GitHub issue
Root filesystem dirjail. Often encompasses the entire local system; gated by --allow-fs.
Caspian doesn't have a meaningful current-working-directory concept. Filesystem access is by explicit dirjails granted by the engine, not relative to where the script was launched. Avoids the "what cwd is this script in?" class of surprises that bite shell-pipeline-launched programs.
Global form: %utils.file_system.
%engine.tmp GitHub issue
Each access returns a fresh temp dirjail. See %utils.tmp for the full API (direct-access, block form, explicit close, properties).
Separable from broader filesystem access. %engine.tmp is a narrower capability than %engine.root: a script can be granted access to scratch space (%utils.tmp) without being granted access to the rest of the filesystem (%engine.root). The two capabilities have separate permission grants (--allow-tmp vs --allow-fs, names TBD).
Global form: %utils.tmp.
%engine.stdin / %engine.stdout / %engine.stderr GitHub issue
Standard input, output, and error streams.
Global forms: %stdin, %stdout, %stderr (top-level system methods reachable from any role with the relevant capability; see #630 for the .global = true opt-in pattern).
%engine.network GitHub issue
Overall network surface. Container for the sub-namespaces below. Gated by --allow-net and friends; see network/index.md for the full permission model.
Global form: %net.
%engine.network.http_client GitHub issue
The HTTP client capability. Backing class is puck.uno/http/client; you don't reach for the class directly — you go through the global form.
Standard usage (via the global, which is what developers actually write):
$resp = %net.http_client.get('https://foo.com/api')
For a configured, reusable client:
$client = %net.http_client.new(
timeout: 30,
headers: {'User-Agent': 'my-script/1.0'}
)
$resp = $client.get('https://foo.com/api')
Each .new() returns an independent instance with its own configuration. %net.fetch is the further-shortened form for a one-shot default request.
%engine.network.http_client exists as the underlying user-only slot but is rarely used directly — examples and idiomatic code go through %net.http_client (or %net.fetch).
Global form: %net.http_client (plus %net.fetch sugar for one-shot requests).
%engine.network.sockets GitHub issue
Raw socket constructors: tcp, ssl, udp. The foundational layer that the HTTP client and other protocol clients are built on. Most user code doesn't reach here directly.
Global forms: %net.tcp, %net.udp, %net.ssl, %net.tcp_listen, %net.udp_listen — each a sugar form for the underlying socket constructor.
%engine.network.uds GitHub issue
Unix-domain-socket server constructor (%engine.network.uds.new). Used to build local-only HTTP servers; the foundation of $uds.share and $uds.mikobase.
Global form: %utils.network.uds — same constructor surface, reachable from any role.
%engine.network.puck GitHub issue
The Puck interface — class lookup by URL, class registration, class deletion. Lives under %engine.network because remote-class lookup is one of the things resolved through the network fetcher chain. Working surface:
| Operation | Form |
|---|---|
| Look up a class by URL | %engine.network.puck['foo.com/bar'] |
| Register a class under a URL | %engine.network.puck['foo.com/bar'] = $class |
| Delete a registration | %engine.network.puck.delete('foo.com/bar') |
%puck is the role-agnostic shorthand that points at the same underlying registry — any role can do %puck['url'] to look up a class, but writes are gated by creator-based ownership (the role that first assigned an entry owns it; other roles can't overwrite it). %engine.network.puck is the user's named access to the same surface; %puck is the universal handle reachable from any role.
The %[url] / %puck[url] shortform is sugar over %puck['url'].
Global form: %puck (plus %[url] shorthand).
%engine.env GitHub issue
Environment-variable accessor (hash-shaped). Read environment variables that were set when the script was launched.
Global form: %utils.env.
%engine.argv GitHub issue
Command-line arguments after the script name, as an array of strings.
$args = %utils.argv # standard idiom — bind to a regular variable
$args is just a variable name the script chooses; it isn't an engine-provided global. Bind to whatever name reads cleanly in your script.
Global form: %utils.argv.
%engine.now GitHub issue
Current timestamp from the engine-controlled clock. Engine-controlled rather than directly from the OS so that test harnesses can inject a fixed clock for deterministic runs.
Global form: %utils.now.
%engine.random GitHub issue
Namespace for random-data primitives. Backed by the OS entropy source (e.g., /dev/urandom on Linux). Three named methods underneath: uuid, number, string.
Global form: %utils.random.
%engine.random.uuid GitHub issue
Fresh UUID. See uuid-generation.md for the canonical surface (version, format, etc.).
$id = %utils.random.uuid
Global form: %utils.random.uuid.
%engine.random.number GitHub issue
Random number drawn from a given range.
$n = %utils.random.number(min: 0, max: 100) # integer in [0, 100]
$f = %utils.random.number(min: 0.0, max: 1.0) # float in [0.0, 1.0]
Type follows the range bounds (integer bounds → integer; float bounds → float). Exact kwarg shape TBD.
Global form: %utils.random.number.
%engine.random.string GitHub issue
Random string of a given length, optionally from a specified alphabet.
$token = %utils.random.string(length: 32) # default alphabet
$hex = %utils.random.string(length: 16, alphabet: 'hex') # hex characters
$pin = %utils.random.string(length: 6, alphabet: '0123456789') # explicit alphabet
Default alphabet is TBD (likely alphanumeric or URL-safe base64). Exact kwarg shape TBD.
Global form: %utils.random.string.
%engine.pid GitHub issue
OS process ID of the running script.
Global form: none yet (TBD). %process.pid is the natural home if added later (%process already exists as a top-level system method).
%engine.platform GitHub issue
Container namespace for OS and CPU-architecture info. Two named slots underneath: %engine.platform.os and %engine.platform.architecture.
Global form: none. Platform info is only available through %engine — user-role concern only. Libraries that need it take what they need as a parameter from user.
%engine.platform.os GitHub issue
Hash of OS information — as much as the engine can cheaply pull together from the host. The exact fields vary by platform; the script can check for what it cares about with .has_key?. Common fields:
| Field | Type | Example | Notes |
|---|---|---|---|
family |
string | 'linux', 'macos', 'windows', 'freebsd' |
Always present |
name |
string | 'Ubuntu', 'macOS', 'Windows' |
Always present |
version |
string | '22.04', '13.5', '11' |
Always present |
pretty_name |
string | 'Ubuntu 22.04.3 LTS', 'macOS Sonoma 14.5' |
Best human-readable form; assembled by the engine if not directly available |
kernel |
string | '6.5.0-1-amd64', '23.6.0' |
uname -r equivalent |
distro |
string | 'ubuntu', 'debian', 'fedora' |
Linux-specific; omitted on macOS/Windows |
codename |
string | 'jammy', 'bookworm', 'sonoma' |
Present where the platform has one; omitted otherwise |
build |
string | '22631' (Windows), '23F79' (macOS) |
Build identifier where available |
Sources the engine pulls from (no special permission required):
- Linux:
/etc/os-release(ID →distro, NAME →name, VERSIONID →version, PRETTYNAME →pretty_name, VERSION_CODENAME →codename);uname -r→kernel. - macOS:
sw_vers(ProductName →name, ProductVersion →version, BuildVersion →build);uname -r→kernel; codename derived from version (Ventura, Sonoma, etc.). - Windows: Win32 API (
GetVersionEx/ registry) →name,version,build.
$os = %engine.platform.os
if $os['family'] == 'linux' and $os['distro'] == 'ubuntu'
# use the apt path
end
puts $os['pretty_name'] # "Ubuntu 22.04.3 LTS"
Engine reads these once at startup and caches; reading %engine.platform.os is cheap.
Global form: none.
%engine.platform.architecture GitHub issue
CPU architecture: x86_64, arm64, etc. Verbose name per the long-names-for-rare-methods principle — most scripts won't query this.
Global form: none.
%engine.encryption GitHub issue
Container namespace for cryptographic primitives. Two named slots underneath: %engine.encryption.signing and %engine.encryption.sha. Both expose well-audited implementations backed by kernel/OS-level entropy.
Global form: %utils.encryption.
%engine.encryption.signing GitHub issue
Ed25519 signing and verification. Used by the blockchain integration for signed library endorsements, signed authority blocks, and signed records. Working surface:
| Method | Purpose |
|---|---|
.generate_keypair() |
Fresh Ed25519 keypair |
.sign($private_key, $bytes) |
Produce a signature |
.verify($public_key, $signature, $bytes) |
Check a signature; returns boolean |
.keypair_from_seed($seed) |
Deterministic keypair from a seed (reproducible test fixtures, KDF-derived keys) |
.import_key(...) / .export_key(...) |
PEM / DER / raw-bytes interchange |
NOT for password storage — passwords have their own spec at ideas/caspian/passwords/ (separate primitives, separate KDF).
Global form: %utils.encryption.signing.
%engine.encryption.sha GitHub issue
SHA-family hashing primitives. SHA-256 is the most common (blockchain content addressing, file fingerprinting, library-artifact hashes); SHA-512 and HMAC variants are also exposed.
| Method | Purpose |
|---|---|
.sha256($data) |
SHA-256 digest as a hex string |
.sha512($data) |
SHA-512 digest as a hex string |
.hmac_sha256($key, $data) |
HMAC-SHA-256 (keyed-MAC use cases) |
.hmac_sha512($key, $data) |
HMAC-SHA-512 |
| Streaming interface for large inputs | TBD shape (probably .open(:sha256) style for hashing a file without loading it all into memory) |
Slot is named sha rather than hash because it's the SHA family specifically. Other hash families (BLAKE2/3, etc.) would get their own slots if and when they're needed.
NOT for password storage — see passwords/passkeys for the password story (uses a proper KDF like Argon2id or scrypt, TBD which).
Global form: %utils.encryption.sha.
%engine[<key>] — arbitrary engine-passed values GitHub issue
Escape hatch for anything beyond the standard named slots above. The engine may bind arbitrary keys at startup for context-specific values: test-harness injections, agent-context data, plugin bindings, environment-specific configuration, anything else not deserving its own standard slot.
$test_fixture = %engine['test_fixture']
$agent_context = %engine['puckai_agent_context']
%engine.<name> and %engine['<name>'] access the same surface for valid-identifier keys. The bracket form is required for keys with special characters or for keys computed at runtime.
The standard slots above are documented; engine-injected keys via bracket access are open-ended. The script knows what to look for by convention (e.g., a test harness sets a known key; the script reads it).
Global form: none by design — the bracket-access escape hatch is engine-direct only. Capabilities passed through %engine[<key>] are scoped to the user-role script that owns the %engine reach; nothing surfaces them under %utils or other global namespaces.
See also GitHub issue
- Engine config — declarative resource requirements at the top of a script.
- Roles — why
%engineis user-only and how capabilities flow down. - Permission flags /
--allow-*— how engine slots are gated at launch.