01 / deck interface
NeurOShell Reference
NeurOShell is the command-line interface on a powered cyberdeck. It is used to inspect the deck, create and manage scripts, read namespace manuals, and run NeurOScript programs. NeurOShell commands act on the deck itself; NeurOScript is the Lua-based language executed by the deck.
For the scripting language and namespace APIs, see the NeurOScript Reference.
#Opening the Shell
The shell is available while a powered cyberdeck is in your inventory and held in both hands. Cyberdecks are two-handed items, so holding one normally fills both hand slots.
hold Ghost Deck
power Ghost Deck on
> status
The order of hold and power does not matter. If the deck is stashed, dropped, powered off, or no longer occupies both hands, its shell becomes unavailable.
Every shell command begins with >:
> help
> list
> man net
> ./probe 10.100.101.1
Whitespace after > is optional, so >list and > list are equivalent. This reference includes the space for readability. Built-in command names are case-insensitive; script names are matched as written.
#Quick Start
Create, debug, assemble, and run a script:
> write hello
Enter this line in the editor:
system.log("Hello from NeurOS.")
Save and leave the editor, then finish the lifecycle:
:wq
> debug hello
> asm hello
> ./hello
write produces an unassembled script. debug can test that source directly, but normal execution with ./ requires it to be assembled first.
#Command Summary
| Command |
Description |
> help [<command>] |
List shell commands or show help for one command. |
> status |
Show deck hardware, power, heat, and resources. |
> list |
List scripts in memory and storage. |
> man [<namespace>] |
List or read NeurOScript namespace manuals. |
> nmcli [<object>] |
Inspect and control the deck's NetworkManager. |
> ps [<pid|script>] |
Show the running script or inspect it in detail. |
> write <script> |
Create or edit a loaded script. |
> cat <script> |
Print a loaded script's source. |
> debug <script> |
Test a loaded script without changing the deck or network. |
> asm <script> |
Assemble a loaded script for execution. |
> ./<script> [args...] |
Run a loaded, assembled script. |
> kill <pid|script> |
Stop the running script by PID or script name. |
> unload <script> |
Move a script from memory to storage. |
> load <script> |
Move a script from storage to memory. |
> rm <script> |
Permanently delete a script. |
> shutdown |
Power off the deck and close the shell. |
> reboot |
Power-cycle the deck. |
#NetworkManager (nmcli)
All interactive networking is managed through nmcli. NeurOS follows the familiar object/command form:
> nmcli [help|status|hostname|networking|radio|connection|device]
With no arguments, nmcli shows overall status. Common aliases are con/c, dev/d, net, host, and r.
#Status and Identity
> nmcli status
> nmcli hostname
> nmcli hostname black-ice
The hostname is the deck's network-visible identity, not the cyberdeck object's name. It is lowercase, 1–32 characters, and may contain letters, digits, and internal hyphens.
#Networking and Radios
> nmcli networking [status|on|off|connectivity [check]]
> nmcli radio [all|wifi|wwan|satellite|mesh|quantum [on|off]]
Disabling networking drops every active connection. Disabling a radio drops connections using adapters of that type. Hostname and switch settings persist across reboot, but active connections do not. Ethernet is not radio-controlled.
#Devices and Discovery
> nmcli device status
> nmcli device show [<interface>]
> nmcli device scan [<interface>]
Devices are local installed adapters such as wlan0, eth0, and mesh0. Scanning lists reachable remote nodes. An active connection can expose nodes behind it, so later scans may reveal a deeper network frontier.
#Connections
> nmcli connection show [--active] [<id>]
> nmcli connection up <network-id> [ifname <interface>]
> nmcli connection down <id>
If ifname is omitted, NeurOS chooses the enabled adapter with the most free bandwidth. Connection IDs may be supplied in full or by a unique prefix of at least four characters. Connections consume bandwidth on their selected adapter and persist until disconnected, networking is disabled, their radio is disabled, or the deck powers off.
nmcli controls transport only. Probing capabilities, breaching ICE, protected reads, remote commands, and payload installation remain NeurOScript operations. Breach authorization is local to one script execution and is never retained by the shell. Network-changing nmcli commands are blocked while a script runs; read-only status, show, connectivity, and scan commands remain available.
#Script States and Locations
> list divides scripts by location and shows the state of each loaded script.
#Locations
| Location |
Resource |
Meaning |
| Loaded (Memory) |
RAM |
The script can be read, edited, debugged, assembled, or run. |
| Stored (Disk) |
Storage |
The script persists without using RAM, but must be loaded before use. |
Loading and unloading are moves, not copies. load removes a script from storage and places it in memory. unload removes it from memory and attempts to place it in storage.
#Loaded States
| Marker |
Meaning |
[UNASSEMBLED] |
Source exists but cannot be run with ./. It can still be edited or debugged. |
[READY] |
Assembled and ready to run. |
[ACTIVE] |
Currently running. |
Editing an existing script replaces its source and returns it to [UNASSEMBLED]; assemble it again before the next normal run.
Only one script can run or be debugged at a time. A running script cannot be removed or unloaded; stop it or wait for it to finish.
#Qn and Capacity
NeurOS measures script size and deck capacity in Qn (Quan):
Use > status for total resource information and > list for current RAM and storage use.
#Command Details
#help
> help
> help <command>
Without an argument, lists every built-in and the ./ execution form. With an argument, shows that topic's usage and description.
Aliases and topic normalization:
> ? is an alias for > help.
> help ? opens the help topic.
> help assemble opens the asm topic.
- Any topic beginning with
./, such as > help ./probe, opens the script
execution topic.
help documents shell commands. Use man for NeurOScript namespaces.
#status
> status
Shows the deck's power state, installed hardware, available capabilities, thermal state, RAM, storage, bandwidth, and other deck resources.
#list
> list
Lists scripts loaded in RAM and scripts stored on disk. Loaded entries show their loaded size and [UNASSEMBLED], [READY], or [ACTIVE] state. Stored entries show their compiled size.
#man
> man
> man <namespace>
Without an argument, prints the manual index available to the deck. With a namespace, opens its manual page:
> man system
> man net
> man interface
The manual pages describe NeurOScript APIs, not shell built-ins. Hardware can control which namespaces a deck can use at runtime. The complete API is also listed in the NeurOScript Reference.
#write
> write <script>
Creates a loaded script or opens an existing loaded script in the line editor. It does not open a stored-only script; load that script first.
Script names:
- Must begin with a letter.
- May contain letters, digits, hyphens, and underscores.
- May be at most 32 characters long.
- May not contain spaces.
Examples of valid names:
probe
door_unlock
scan-v2
The most useful editor commands are:
| Editor command |
Effect |
<text> |
Append a new line to the buffer. |
: |
Display the buffer with line numbers. |
:h |
Display full editor help. |
:w |
Save without leaving the editor. |
:wq |
Save and leave the editor. |
:q |
Leave, prompting to save if changed. |
:q! |
Leave without saving. |
:u |
Undo. |
:uu |
Redo. |
:DD |
Clear the entire buffer. |
Saving requires the same powered deck to remain held in both hands. If the deck becomes unavailable while editing, the buffer is not saved.
#cat
> cat <script>
Prints the source of a loaded script and its loaded size. cat does not read scripts directly from storage; use load first.
#debug
> debug <script>
Tests a loaded script without changing the deck, network, or connected devices. Assembly is not required, and any output or errors are displayed.
The debugger can test every NeurOScript namespace even if the current deck does not have the hardware needed for a normal run.
#asm
> asm <script>
> assemble <script>
Assembles a loaded [UNASSEMBLED] script and marks it [READY]. assemble is an alias for asm.
An edited script must be assembled again.
#Script Execution
> ./<script> [args...]
Runs a loaded, assembled script:
> ./probe
> ./probe 10.100.101.1 fast
Arguments are split on whitespace and exposed to NeurOScript through the one-indexed global arg table:
local target = arg[1]
local mode = arg[2]
system.log("arguments: " .. #arg)
NeurOShell does not interpret options, quotes, pipes, redirection, environment variables, or wildcard expansion. Every token after the script name is passed as a string.
A normal run:
- Requires the script to be loaded and assembled.
- Uses only namespaces enabled by installed hardware.
- Adds heat and records the script as
[ACTIVE] while it runs.
- Takes time based on loaded size and processing speed.
- Applies successful network and device effects when the run completes.
- Does not apply unfinished effects if the script fails or is aborted.
If heat reaches the deck's cooling capacity, NeurOS aborts the script, powers the deck off, and disengages the shell. The deck cannot power back on until it has cooled below its lockout threshold.
> ps
> ps <pid|script>
Without an argument, ps shows the running script's PID, mode, state, elapsed time, RAM use, and command. The detailed form also shows its expected runtime, arguments, and whether it is stopping. Finished scripts are not listed; an idle deck reports No processes.
A script may be starting, running, waiting to finish, or stopping.
#kill
> kill <pid|script>
Stops the running script by PID or exact script name. A script may take a moment to stop. A waiting script stops immediately.
#unload
> unload <script>
Removes a loaded script from RAM and attempts to save it to disk. If a stored script with the same name exists, the unloaded version replaces it.
This command has no confirmation prompt. If the deck has no storage, or if the script does not fit in available storage, the script is permanently lost.
#load
> load <script>
Moves a stored script from disk into RAM. The operation fails without changing the stored copy if there is not enough available RAM. A successfully loaded script retains its assembled or unassembled state.
> rm <script>
Permanently deletes a script, whether it is loaded in memory or stored on disk. This command has no confirmation prompt and cannot be undone.
#shutdown
> shutdown
Aborts running scripts, powers the deck off, and disengages the shell. Power the deck back on with the regular game command:
power <deck> on
#reboot
> reboot
Aborts running scripts and power-cycles the deck. The shell remains available if the deck successfully returns to the powered-on state. An overheated deck can remain off until it cools sufficiently.
#Common Workflows
#Create and Run
> write netscan
:wq
> debug netscan
> asm netscan
> ./netscan
#Edit an Existing Script
> write netscan
:wq
> debug netscan
> asm netscan
Saving the edit makes the script unassembled, so the final asm is required.
#Archive and Restore
> unload netscan
> list
> load netscan
Check available disk space before unloading: a failed storage fit loses the script.
#Run with Arguments
> ./quickjack door_lock quiet
local node_type = arg[1]
local mode = arg[2]
#Shell Limits and Safety Notes
- The shell operates only on the powered deck currently held in both hands.
- Commands take one script name; script names cannot contain spaces.
- There are no pipelines, command chaining, background operators, or file
paths.
rm and a storage-less or storage-full unload are destructive and do not
ask for confirmation.
shutdown, reboot, overheating, and kill abort running scripts.
- Script limits are documented in the
NeurOScript Reference.
02 / language & APIs
NeurOScript Reference
NeurOScript (NOS) is the scripting language used by the NeurOS operating system on cyberdecks. It uses Lua syntax and provides commands for network intrusion, device manipulation, and deck automation.
For the cyberdeck command line used to create, assemble, manage, and run these scripts, see the NeurOShell Reference.
#Language Basics
NOS uses Lua syntax. Variables are declared with local, strings use single or double quotes, tables (arrays/dicts) use curly braces, and .. concatenates strings.
local name = "Ghost"
local count = 42
local devices = {}
local msg = "Deck: " .. name
#Control Flow
if condition then
-- ...
elseif other then
-- ...
else
-- ...
end
for i = 1, 10 do
-- ...
end
while condition do
-- ...
end
#Tables
Tables are the only data structure. They work as both arrays and dictionaries.
-- Array style
local list = {"alpha", "bravo", "charlie"}
for i = 1, #list do
system.log(list[i])
end
-- Dict style
local info = {name = "Panel", level = 3}
system.log(info["name"])
#Script Arguments
Arguments supplied when a script is run from NeurOShell are available through the global arg table. Run a loaded, assembled script with arguments after its name:
> ./probe 10.100.101.1 fast
NeurOScript receives those arguments as one-indexed strings:
local target = arg[1] -- "10.100.101.1"
local mode = arg[2] -- "fast"
local count = #arg -- 2
system.log("Target: " .. target)
The arg table is always available. If the script is run without arguments, #arg is 0 and arg[1] is nil:
if #arg == 0 then
system.log("Usage: ./probe <target> [mode]")
return
end
NeurOShell splits arguments on whitespace. It does not process quotes, escapes, variables, wildcards, or other shell expansion, so a single argument cannot contain spaces. All arguments arrive as strings; use tonumber(arg[n]) when a script requires a number.
See Script Execution (./) in the NeurOShell reference for the command-side details.
#Available Standard Library
The following Lua standard library functions are available in NOS:
- math: sin, cos, tan, sqrt, exp, log, pow, random, randomseed, floor, ceil, abs, min, max, modf, fmod, huge, pi
- string: format, rep, gmatch, gsub, match, find, sub, upper, lower, reverse, len, byte, char
- table: insert, remove, concat, sort, pack, unpack
- globals: print, tostring, tonumber, type, ipairs, pairs, next, pcall, xpcall, error, assert, unpack, select, rawequal, rawlen
Functions not listed above are not available in NeurOScript.
#Namespaces
Namespaces are groups of functions that NeurOS exposes to scripts. Some are always available; others require specific hardware to be installed in the deck.
#Always Available
#system
Deck basics: logging, introspection, control.
| Function |
Qn |
Returns |
Description |
system.log(message) |
0.1 |
string |
Display a message on the deck console. Returns the formatted log entry. |
system.info() |
0.1 |
table |
Returns {os, deck, owner} — the OS version, deck name, and owner name. |
system.uptime() |
0.1 |
number |
Seconds since the deck was powered on. |
system.reboot() |
0.5 |
string |
Request a deck reboot. Requires confirmation. |
#chrono
Time operations: timestamps, durations, delays.
| Function |
Qn |
Returns |
Description |
chrono.get_time() |
0.1 |
number |
Current timestamp (seconds since epoch). |
chrono.format_time(timestamp) |
0.1 |
string |
Format a timestamp as "YYYY-MM-DD HH:MM:SS". |
chrono.time_since(timestamp) |
0.1 |
number |
Seconds elapsed since the given timestamp. |
chrono.format_duration(seconds) |
0.1 |
string |
Human-readable duration: "45s", "2m 30s", "1h 15m". |
chrono.wait(seconds) |
0.3 |
number |
Pause execution. Capped at 5 seconds. Returns actual duration. Abortable. |
chrono.set_timer(duration, callback) |
0.5 |
string |
Not yet implemented. |
#Requires Network Adapter
These namespaces unlock when a network adapter (Wi-Fi Module, Mesh Radio, Quantum Communicator, etc.) is installed.
#net
Network transport: scanning for devices, establishing and dropping connections.
| Function |
Qn |
Returns |
Description |
net.scan_devices() |
0.3 |
table[] |
Scan the local network. Returns a list of device tables, each with {network_id, name, node_type, connected}. |
net.connect(network_id) |
0.5 |
table |
Connect to a device by network ID. Returns {ok, connection_id} on success, {ok=false, error} on failure. Costs 1 bandwidth. |
net.disconnect(connection_id) |
0.2 |
table |
Drop a connection. Returns {ok} or {ok=false, error}. Frees 1 bandwidth. |
Bandwidth: Each connection costs bandwidth. Total bandwidth is the sum of all installed network adapters. When bandwidth is exhausted, net.connect fails.
Network IDs: Every network node has a unique network_id — its fingerprint on the net. Network IDs are stable — the same node always has the same ID. They're the primary way to identify and reconnect to devices.
Persistence: Connections persist across script runs. A script can connect, finish, and a later script can use the same connection. Power-off drops all connections.
NetworkManager: Interactive network setup uses NeurOShell's nmcli command. The net namespace remains the scripting API, but it shares the same networking switches, radio availability, active connections, and per-adapter bandwidth. net.connect automatically chooses the enabled adapter with the most free bandwidth. If networking or every usable adapter is disabled, scans return no devices and connection attempts return an error.
#interface
Device interaction: once connected via net.connect, use interface to interact with the device. Every function takes a connection_id (from net.connect) as its first argument.
| Function |
Qn |
Returns |
Description |
interface.breach(connection_id) |
2.0 |
table |
Attempt to break through a device's ICE. Required before send_command, read_data, or install_payload on secured devices. Returns {ok} or {ok=false, error}. See ICE section below. |
interface.probe(connection_id) |
0.5 |
table |
Query device capabilities. Returns {ok, commands, data_keys, accepts_payloads}. Works without breaching. |
interface.send_command(connection_id, command) |
0.5 |
table |
Send a command string to the device. Requires breach on secured devices. Returns {ok, command, result} or {ok=false, error}. |
interface.read_data(connection_id, key) |
0.3 |
table |
Read data from the device. Requires breach on secured devices. Returns {ok, key, value} or {ok, data}. |
interface.install_payload(connection_id, script_name) |
3.0 |
table |
Install a script as a payload on the device. Requires breach. Returns {ok, message} or {ok=false, error}. |
interface.get_status(connection_id) |
0.2 |
table |
Check connection state. Returns {ok, connected, alert_level, noise, trace_active, trace_remaining}. Works without breaching. |
The three-step pattern: net finds and connects; interface.breach cracks the ICE; interface.send_command acts. A typical intrusion: scan → connect → probe → breach → send_command → disconnect.
Node-owned commands: Each device type defines its own valid commands and data. A door lock accepts "unlock", "lock", "log_clear". A camera accepts "disable", "loop_feed", "rotate". Sending an invalid command returns an error.
Payloads: A payload is a script from your deck installed on a remote device. Only some devices accept payloads (servers, terminals). Payload installation is the most expensive operation in NOS (3.0 Qn).
#ICE (Intrusion Countermeasures Electronics)
Devices with a security level above 0 run ICE. You must breach the ICE before you can send commands, read data, or install payloads. probe and get_status always work — you can look before you commit.
#Breach
Call interface.breach(connection_id) to attempt to crack the ICE. This is a blind commitment — you don't know how strong the ICE is until you try.
- Success depends on your deck's crypto capability (encryption rating from your compute module + encryption boost from expansion cards like the Encryption Module or GPU). If your crypto meets or exceeds the difficulty, the breach succeeds.
- Time depends on the ICE strength and your deck's processing speed. Stronger ICE takes longer. Better processors reduce the time.
- Breach is per-session. It doesn't persist across script runs. Every script that needs to interact with a secured device must breach again.
#Alert Levels
Every device tracks an alert level during your session. Every action you take generates noise, and noise accumulates.
| Level |
Name |
What happens |
| 1 |
Passive |
Default. No logging. You're invisible. |
| 2 |
Logging |
The device starts recording: your adapter's identity, timestamps, everything. |
| 3 |
Alert |
Network security is alerted. |
| 4 |
Intrusion |
A trace begins. You have 60 seconds. |
#Noise
Every interface action generates noise. Better crypto hardware reduces how much noise you make. Noise decays during periods of inactivity — if your script waits between actions, noise drops.
Actions and their base noise (before hardware reduction):
probe: 0.5
send_command: 1.0
read_data: 0.3
install_payload: 2.0
- Successful breach: 2.0
- Failed breach: 10.0 (and alert jumps straight to 4)
#Trace
At alert level 4, a 60-second trace begins. Check with interface.get_status(conn) — it shows trace_active and trace_remaining.
Disconnect before the trace completes and your deck survives. But everything you did since alert level 2 is logged on the device — your adapter's identity, what commands you ran, when.
If the trace completes while you're still connected, the ICE captures your deck's data and fries it permanently.
#Hardware and ICE
Your deck's ability to breach ICE and operate quietly depends on installed hardware:
- Compute module: Base encryption rating and processing speed
- Encryption Module (exp_crypto): +10 encryption boost
- GPU (exp_gpu): +5 encryption boost, +8 processing boost
- AI Co-Processor (exp_ai_copro): +15 processing boost
- Signal Processing Unit (exp_signal): +3 processing boost
A deck with no crypto expansion cards can only breach the weakest ICE. Corporate and military targets require dedicated hardware.
#mail
Messaging between deckers. Not yet implemented.
| Function |
Qn |
Returns |
Description |
mail.send(subject, body, to) |
0.5 |
— |
Send a message to another decker. |
mail.receive() |
0.3 |
— |
Check for incoming messages. |
#Requires Expansion Card or I/O Device
#device
Hardware management for connected peripherals. Not yet implemented.
| Function |
Qn |
Returns |
Description |
device.list() |
0.2 |
— |
List connected hardware devices. |
device.connect(device_id) |
0.5 |
— |
Connect to a hardware device. |
device.disconnect(device_id) |
0.3 |
— |
Disconnect from a hardware device. |
device.send_command(device_id, command) |
0.5 |
— |
Send a command to a hardware device. |
device.get_status(device_id) |
0.3 |
— |
Get hardware device status. |
#Requires Encryption Module or GPU
#security
Cryptographic and intrusion detection operations. Not yet implemented.
| Function |
Qn |
Returns |
Description |
security.bypass_firewall(connection, method) |
2.5 |
— |
Attempt to bypass a firewall. |
security.decrypt_data(data, key) |
2.0 |
— |
Decrypt encrypted data. |
security.detect_intrusion() |
1.5 |
— |
Scan for intrusion attempts on your deck. |
#Requires Storage Drive
File system operations on the deck's storage. Not yet implemented.
| Function |
Qn |
Returns |
Description |
fs.read(path) |
0.3 |
— |
Read a file from storage. |
fs.write(path, data) |
0.5 |
— |
Write data to a file. |
fs.list(path) |
0.2 |
— |
List directory contents. |
fs.exec(script_name) |
1.0 |
— |
Execute a stored script. |
#Script Size (Qn)
Every script has three size measurements, all in Qn (Quan):
- Raw size: The script's size before assembly.
- Compiled size: The storage space used after assembly.
- Loaded size: The RAM used while the script is loaded.
What contributes to size:
| Source |
Counts toward |
Cost |
Namespace API call (e.g. net.connect) |
Raw, Compiled, Loaded |
Per-function (see tables above) |
Control flow (if, for, while, elseif, repeat) |
Raw, Compiled, Loaded |
0.05 each |
| Base script overhead |
Raw, Compiled, Loaded |
0.2 |
Standard function (e.g. string.format) |
Loaded only |
0.02 - 0.25 depending on function |
String concatenation (..) |
Loaded only |
0.15 each |
Storage uses compiled size. RAM uses loaded size. A script must fit in both to be usable.
#Script Limits
| Limit |
Value |
| Max output lines |
100 |
| Max line length |
1,024 characters |
Max chrono.wait() |
5 seconds |
A script stops if the deck overheats. Better cooling allows longer runs.
#Network Node Types
Devices in the world that scripts can scan and interact with. Each type has different commands and data.
Commands marked with * produce a visible effect in the room (other players can see them). Silent commands produce no room-visible output.
| Node Type |
Security |
Commands |
Data |
Payloads |
| Security Panel |
2 |
disable, enable, reset* |
log, status |
No |
| Security Camera |
1 |
disable, loop_feed, rotate* |
feed, storage |
No |
| Server Rack |
5 |
query, shutdown*, extract |
cpu_load, users_active |
Yes |
| Public Terminal |
0 |
login*, browse, download |
uptime, network |
Yes |
| Electronic Door Lock |
3 |
unlock, lock, log_clear |
status, last_access |
No |
| Vending Machine |
0 |
dispense, restock, diagnostics |
inventory, revenue |
No |
Visible effects occur when the script finishes. Repeating the same command on the same device during one run produces one visible effect.
#Example: Full Intrusion Script
-- Connect to a door lock, unlock it, clean the log, disconnect.
system.log("=== LOCKPICK ===")
local devices = net.scan_devices()
local target = nil
for i = 1, #devices do
if devices[i]["node_type"] == "door_lock" then
target = devices[i]
break
end
end
if not target then
system.log("[!] No door lock in range.")
return
end
local r = net.connect(target["network_id"])
if not r["ok"] then
system.log("[!] " .. r["error"])
return
end
local conn = r["connection_id"]
local info = interface.probe(conn)
if not info["ok"] then
system.log("[!] " .. info["error"])
net.disconnect(conn)
return
end
system.log("[*] Commands: " .. table.concat(info["commands"], ", "))
local breach = interface.breach(conn)
if not breach["ok"] then
system.log("[!] " .. breach["error"])
net.disconnect(conn)
return
end
local result = interface.send_command(conn, "unlock")
if result["ok"] then
system.log("[+] Door unlocked.")
local cleared = interface.send_command(conn, "log_clear")
if cleared["ok"] then
system.log("[+] Logs cleared.")
else
system.log("[!] " .. cleared["error"])
end
else
system.log("[!] " .. result["error"])
end
net.disconnect(conn)
system.log("[-] Clean exit.")