Simterm emulates a realistic POSIX shell that feels like a real compromised box — but no campaign author has to write a single line of per-command output to make it work. The system shell is synthesized automatically from theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/0x-unkwn0wn/simterm/llms.txt
Use this file to discover all available pages before exploring further.
TargetNode definition the author already wrote: hostname, IP address, OS version, services, and the env / processes campaign fields. The result is a consistent, accurate shell that responds correctly to standard POSIX verbs regardless of which campaign is loaded.
How Synthesis Works
Every system command derives its output from existing state rather than authored strings:unamereadsTargetNode.osand the hostname.psmaps each service name to a plausible process name, appends thecampaign.processeslist, and adds a base set of system processes (init,sshd, your shell).netstat/ssreadsTargetNode.servicesfor its listening port table.ifconfig/ip areadsTargetNode.ipfor the interface address.envmerges derived variables withcampaign.envand any session overrides set viaexport.whoami/idreflects whether you have a foothold and whether you are root.
uname, hostname, ps, netstat, ss, ifconfig, ip, env, export) require an active shell — they return bash: <verb>: command not found (exit 127) if called without a foothold.
Synthesized System Commands
| Command | Synthesized from |
|---|---|
whoami | Root vs user session; prints the current username (root or user) |
id | Root vs user session; produces uid=0(root) or uid=1000(user) |
uname [-a] | os + hostname; -a produces the full Linux kernel string |
hostname [-f] | Host name (short without -f; FQDN with -f) |
ps [aux] | services (name→process) + base procs (init, sshd) + processes |
netstat -tlnp / ss | services (listening ports) |
ifconfig / ip a | Host ip + loopback |
env | env map + derived (USER, HOME, PWD, HOSTNAME, SHELL, LOGNAME) |
export VAR=val | Sets a session variable (reset on mission change) |
grep PAT FILE | The VFS — filters lines by pattern |
head [-n N] FILE | The VFS — first N lines (default 10) |
tail [-n N] FILE | The VFS — last N lines (default 10) |
wc FILE | The VFS — line, word, and byte count |
file FILE | The VFS — reports ASCII text or ELF 64-bit binary |
Environment Variable Expansion
The engine supports three expansion forms, consistent with standard bash behavior:$VAR— expands the named variable.${VAR}— same, with explicit delimiters (useful adjacent to other text).$?— expands to the exit code of the last command.
echo arguments and inside campaign TerminalCommand output templates. An unknown variable expands to an empty string — the engine never errors on an undefined variable.
Environment layering
The finalenv table merges three sources in priority order (lowest to highest):
- Derived variables — computed from game state:
USER,LOGNAME,HOME,PWD,HOSTNAME,SHELL. - Campaign
envmap — static key/value pairs defined in the campaign file. These can override derived variables (for example, setting a customPATHorSHELL). - Session overrides — variables set with
export VAR=valduring the current mission. These reset when the mission changes.
How processes and env Extend the Shell
Campaign authors can make the shell feel even more authentic by supplying extra data:
campaign.processes— a list of raw process strings appended verbatim to thepsoutput. Use this to add application-layer processes (a web app, a cron daemon, a custom service) that do not correspond to a port-mapped service.campaign.env— a key/value map merged into the environment. Useful for settingPATH,LANG, application secrets, or anything else a realistic shell on that host would export.
Unknown Verb Behavior
Any verb that is not a built-in command, not in the campaign’scommands, terminal, or easter_eggs, resolves to the POSIX fallback:
$? variable will reflect this after the call.
Shell Tone
All system command output is authentic POSIX English, regardless of the campaign’s configuredlanguage. An operator running a Spanish-language campaign still sees:
Shell output is always POSIX English. If your campaign targets a non-English-speaking audience, do not rely on system command output to carry narrative meaning — use the mission briefing, debrief, loot notes, and declarative command lines for localized storytelling instead.
Mini-Experience Commands
These built-in commands provide terminal flavor and lightweight minigames. Their content can be customized by the campaign through thefortunes and signals fields in the campaign definition.
| Command | Aliases | Purpose |
|---|---|---|
fortune | Print a random campaign fortune from the fortunes list | |
signal | Intercept a coded signal built from signals campaign words | |
decode <text> | decrypt <text> | Decode the latest signal-style intercepted text |
crack <0000-9999> | Try a four-digit numeric keypad code | |
mastermind [guess] | bulls [guess], mm [guess] | Play the mastermind-style code-breaking minigame |
fortune— prints one randomly selected entry fromcampaign.fortunes. If the campaign defines no fortunes, a default set is used.signal— generates a coded intercept using words fromcampaign.signalsand a light cipher. Calldecodewith the output to reverse it.mastermindwith no argument starts a new game; with a four-digit guess it scores the attempt (correct digit in correct position = “bull”; correct digit in wrong position = “cow”).cracktakes a four-digit code and checks it against the campaign-defined keypad answer, if one exists.