Documentation

RPCortex Pulsar v0.9.1  •  Full reference for the shell, commands, registry, and hardware

Version: v0.8.1 v0.9.1

Getting Started

What you need:

Thonny note: Thonny's built-in REPL works for basic use, but arrow key navigation, history, and the editor all require a proper terminal emulator. Use PuTTY for the full experience.

Installation

  1. Flash MicroPython to your board
  2. Copy all files from the repo to the root of the board's filesystem
  3. Connect your serial terminal at 115200 baud
  4. Reboot — main.py starts automatically on power-up

First boot

A setup wizard runs on first boot:

  1. You set the root password (the administrator account)
  2. You choose whether to enable verbose boot (detailed POST messages on each startup)
  3. A guest account is created automatically — it accepts any password including blank

The official package repo is added automatically. Run pkg update after first boot to fetch the package list.

After that, log in and you're at the shell prompt. The wizard only runs once.

Boot Sequence

main.py
  └── Core/post.py              POST: hardware checks, registry, WiFi
       └── Core/initialization.py   reads startup mode, runs login loop
            └── Core/launchpad.py   launchpad_init -- the interactive shell

If initialization fails, recovery_init() starts an unauthenticated shell so you can diagnose the problem. The recovery shell has access to all the same commands.

The Shell

The shell prompt format is:

username@pulsar:~>
username@pulsar:~/docs>
username@pulsar:/Core>

~ is shorthand for the user's home directory (/Users/<username>/). The shell starts there on login. cd ~ and bare cd both return home.

Keyboard shortcuts

KeyAction
Up / DownScroll command history (last 50)
Left / RightMove cursor within the line
Home / Ctrl+AJump to beginning of line
End / Ctrl+EJump to end of line
DeleteDelete character under cursor
BackspaceDelete character before cursor
Ctrl+CCancel current input

Characters are inserted at the cursor position — you can edit anywhere in the line, not just at the end.

Command loading

Built-in commands (sys_fs, sys_sys, sys_net, sys_user, wifi, settings) are loaded via __import__() and live in sys.modules permanently. After a cache clear they reload for free — no re-reading or recompiling. Package-installed commands use a separate exec-based path.

Critical commands

reboot, sreboot, freeup, gc, alias, unalias, and rawrepl are implemented as inline functions that bypass the loader entirely. They always work regardless of heap state.

Aliases

Aliases let you define shorthand for any command. They persist across reboots — saved to /Pulsar/Registry/aliases.cfg and reloaded at shell start. Critical built-ins can't be shadowed.

alias ll=ls
alias cls=clear
alias              # list all aliases
unalias ll

Multi-command lines

Multiple commands can be run on a single line separated by ;. Commands execute left-to-right; if the shell exits (logout) mid-line the remaining commands are skipped.

mkdir /data; cd /data; touch notes.txt
ls; pwd; whoami

Single and double quotes protect ; inside arguments (e.g., echo "a;b" prints a;b, not two commands).

Pipes and conditional chaining (v0.9.1)

Commands can be piped together with | — the left command's output becomes the right command's input. The consumers grep, wc, sort, uniq, cat, head, and tail read piped input when given no file argument.

cat /Pulsar/Logs/latest.log | grep ERROR | wc
ls /Core | sort | head 5

Commands can also be chained on exit status: && runs the next command only if the previous one succeeded, || only if it failed. A command "fails" if it reported an error.

wifi connect && pkg update          # update only if WiFi connected
ping novalabs.app || echo offline

Heap management

The RP2040 has 264 KB of RAM. After loading several commands or running HTTPS requests, the heap may become fragmented — gc.mem_free() can show 90 KB free while a MemoryError still occurs, because no single contiguous block is large enough for a new allocation. Run freeup to compact the heap. The shell also automatically retries after a cache clear on MemoryError.

Filesystem Commands

CommandDescription
ls [path]List directory — type, size, modification time, name
cd <path>Change directory. cd, cd ~, and cd ~/sub all work
pwdPrint working directory
mkdir <path>Create directory
rm <path>Remove file or directory (recursive for directories)
touch <file>Create an empty file
read / cat <file>...Print file contents; accepts multiple files (header per file)
head <file> [n]First n lines (default 10)
tail <file> [n]Last n lines (default 10)
mv <src> <dst>Move or rename (relative or absolute; instant same-FS rename, streamed across FS)
cp <src> <dst>Copy file (relative or absolute; streamed in 1 KB chunks — large-file safe)
rename <old> <new>Rename in place (relative or absolute)
dfFlash usage: total, used, free
du [path]Total size of a file or directory tree (recursive)
tree [path]Recursive directory listing
exec <file>Run a Python file directly

Text Processing Commands

Line-by-line text utilities tuned for low RAM usage. All I/O is streamed where possible — files are not loaded in full unless the command requires it (sort being the exception).

CommandDescription
grep <pattern> <file>Search file for pattern (substring); shows line numbers in gray and a match count
wc <file>Count lines, words, and bytes
find [dir] [pattern]Recursive file search by name substring; max depth 8; omit pattern to list all files
sort <file>Print lines sorted alphabetically; warns if the file is larger than 8 KB before loading
uniq <file>Filter consecutive duplicate lines (pair with sort for full dedup)
hex <file> [n]Hexdump first n bytes (default 256) — address, hex, and ASCII columns
basename <path>File name portion of a path
dirname <path>Directory portion of a path
grep error /Pulsar/Logs/session.log
wc /Users/root/notes.txt
find /Core .py
sort /Users/root/list.txt | uniq
hex /Core/launchpad.py 64
basename /Core/Launchpad/sys_sys.py
dirname /Core/Launchpad/sys_sys.py

System Commands

CommandDescription
sysinfoOS version, user, CPU, RAM, flash summary
meminfoDetailed RAM breakdown
uptimeTime since last boot
dateCurrent date/time from RTC
date set <Y-M-D [H:M:S]>Set the hardware RTC (so log timestamps are correct)
watch [-n <secs>] <cmd>Re-run a command periodically (default 2 s) until Ctrl+C
verOS version string
clear / clsClear the terminal
fetch / neofetchSystem info display with ASCII logo
rebootHard reset
sreboot / softresetSoft reset (faster, keeps filesystem)
freeup / gcClear command cache, run GC, report RAM freed
sleep <secs>Pause the shell for the given number of seconds (e.g. sleep 2.5)
which <cmd>Show where a command is defined: built-in, .lp registry path, or alias
rawreplExit the OS and return to MicroPython REPL — use to re-flash via Web Installer
alias [name=cmd]Define or list aliases — persisted to aliases.cfg, survive reboots
unalias <name>Remove an alias (and update the persisted file)
echo <text>Print text
historyShow command history
env [section]Dump registry contents
reg get <key>Read a registry key
reg set <key> <val>Write a registry key
settingsOpen the settings panel
edit [file]Open the built-in editor
benchRun the RPCMark benchmark

pulse subcommands

CommandDescription
pulse statusShow clock info (current freq, boot OC state)
pulse set <MHz>Set CPU frequency for this session (e.g. pulse set 220)
pulse min <MHz>Save minimum clock value (e.g. pulse min 30)
pulse max <MHz>Save maximum clock value (e.g. pulse max 220)
pulse boot <MHz>Set boot clock and enable OC on boot (e.g. pulse boot 200)
pulse boot on|offEnable or disable boot overclock
Overclock note: POST calibration stores 220 MHz as the safe max for RP2040/RP2350. You can set any value manually with pulse set <MHz> — a warning is shown above 220 MHz, but the clock is set regardless. Stability beyond 220 MHz is not guaranteed.

Automation & Scripting v0.9.1

RPCortex can run on its own. Combine these with pipes and && / || chaining to build real device behaviour without a host computer.

Startup tasks

Commands listed in /Pulsar/Registry/startup.cfg run once automatically after login, before the prompt opens.

CommandDescription
startupList configured startup tasks
startup add <command>Append a command (e.g. startup add wifi connect)
startup remove <n>Remove task number n
startup clearRemove all startup tasks
startup runRun the tasks now, without rebooting

Scheduled tasks

Run commands on a repeating interval (timed by software uptime — no battery RTC needed). Stored in /Pulsar/Registry/tasks.cfg.

CommandDescription
taskList scheduled tasks
task add <secs> <command>Run <command> every <secs> seconds
task remove <n>Remove task number n
task clearRemove all scheduled tasks
task runStart the scheduler loop (press q / Ctrl+C to stop)
Headless autonomy: startup add task run makes the device boot straight into the scheduler — an unattended controller with no terminal needed. (Concurrent background tasks alongside an interactive prompt arrive with uasyncio in v1.0; the shell's input read is blocking by design.)

Scripts (.rps)

Run a script with script <file.rps>. Scripts run through the live shell, so every command (and pipes / chaining) is available. Variables are untyped text; $NAME expands anywhere on a line.

StatementMeaning
# commentComment line (ignored)
set NAME VALUEDefine a variable; $NAME expands it anywhere
inc NAME [n] / dec NAME [n]Add / subtract n (default 1) on a numeric variable
prompt NAME [text]Read a line of input from the user into NAME
capture NAME <command>Run a command and store its output in NAME
if COND … else … endConditional block (else optional)
while COND … endLoop while COND is true
break / continueExit / skip the current while iteration
stopEnd the script early
<any command>Run a shell command (pipes, &&, || all work)

Conditions. A COND is a builtin test, or any shell command (true when it exits without error):

TestTrue when
eq A B / ne A BA equals / does not equal B
gt A B / lt A BA > B / A < B (numeric when both look like numbers, else text)
ge A B / le A BA ≥ B / A ≤ B
contains A BB is a substring of A
exists PATHThe file or directory exists
empty AA is empty
not CONDNegates any of the above (or a command)

A counted loop, using inc and a numeric test:

# countdown.rps
set i 5
while gt $i 0
  echo $i...
  dec i
  sleep 1
end
echo liftoff!

Command output capture and interactive input:

# greet.rps
prompt name What is your name?
capture me whoami
echo Hello $name, you are logged in as $me.

A GPIO blink loop that stops when a flag file is removed:

# blink.rps
set pin 25
while exists /run.flag
  gpio set $pin high
  sleep 0.5
  gpio set $pin low
  sleep 0.5
end

Recovery & Diagnostics v0.9.1

Diagnostic and repair tools, available from the normal shell or recovery mode. They're registered through their own recovery.lp, so they still load even if the main command registry is damaged.

CommandDescription
fscheckVerify core OS files exist and are non-empty
diagHealth snapshot: free RAM, free flash, registry, version
logdump [n]Print the session log (last n lines if given)
regresetDelete registry.cfg so POST rebuilds defaults — keeps user accounts and saved WiFi
pkgdisable <name>Disable a package without removing it
pkgenable <name>Re-enable a disabled package
recoveryEnter recovery mode (limited shell, no auth)

OS Management

These commands manage the OS itself — over-the-air updates, file-based updates, factory reset, and full reinstall.

update check / update online

Over-the-air updates over WiFi. update check fetches the release manifest and tells you whether a newer version exists; update online downloads and installs it, then reboots:

update check                   # is there a newer release?
update online                  # download + install the latest, then reboot
update online --force          # reinstall even if already up to date

update from-file

Extracts a .rpc release archive to the running OS:

update from-file /path/to/os.rpc
Browser update: You can also update from the browser at rpc.novalabs.app/update — no WiFi required on the device. The page transfers the archive over the serial connection.

factoryreset

Soft reset — restores the OS to a clean first-run state while keeping core files intact:

factoryreset

reinstall

Full OS wipe — deletes everything and writes a self-contained reinstall stub:

reinstall                      # wipe and show Web Installer instructions
reinstall /path/to/os.rpc      # wipe and stage .rpc for auto-install on boot

rawrepl

Cleanly exit the OS and return to the MicroPython >>> REPL without rebooting:

rawrepl

Use this when RPCortex is already installed but you want a completely fresh flash via the Web Installer — no full wipe required. After running rawrepl:

  1. The shell exits and the MicroPython REPL becomes active (>>> prompt visible in your terminal).
  2. Open rpc.novalabs.app/install in Chrome or Edge.
  3. Click Connect Device and flash normally.
How it works: rawrepl raises SystemExit(0) — a BaseException, not caught by any except Exception block. It propagates through all OS layers (launchpad.py, initialization.py, main.py) and MicroPython drops to the REPL after main.py returns.

OS update workflow overview

ScenarioCommand / Tool
Update OS, keep all user dataupdate from-file /path/to/os.rpc or browser update page
Reset to clean factory statefactoryreset
Use Web Installer without rebootingrawrepl
Full wipe + re-flashreinstall or rawrepl + Web Installer

User Management

CommandDescription
whoamiCurrent logged-in user
usersList all accounts with active / admin / nopass tags
mkacctCreate a new account (prompts for username and password)
rmuser <user>Delete an account. Non-root users must verify the target's password first.
chpswd <user>Change a password
logout / exitEnd session, return to login

Account details

Networking

WiFi works on any board with a network module: Pico W, Pico 2 W, and most ESP32 variants.

WiFi commands

CommandDescription
wifi statusConnection state, SSID, IP
wifi scanNearby networks with signal strength
wifi connect [ssid]Connect (prompts for password; uses saved if available)
wifi disconnectDrop the current connection
wifi listSaved networks
wifi add <ssid>Save a network
wifi forget <ssid>Remove a saved network

Any number of networks can be saved (stored in networks.cfg). Enable autoconnect on boot:

reg set Settings.Network_Autoconnect true

Or toggle it in settings.

Download commands

CommandDescription
wget <url> [file]Download to flash — streams directly, with a progress bar (v0.9.1)
curl <url> [flags]Fetch a URL (see flags below)
runurl <url> [--keep]Fetch and execute a Python file; deletes after unless --keep
ping <host> [n]TCP connectivity test
nslookup <host>DNS lookup

curl flags (v0.9.1): -v verbose, -s silent, -I headers only, -X <method>, -d <data> (sends a body; implies POST), -H '<header>', -o <file> (save to file), --timeout <secs>. Quotes group flag values: curl api.x/v1 -X POST -H 'Authorization: Bearer t' -d '{"q":1}'.

Both HTTP and HTTPS are supported. The client follows redirects iteratively (for GET) with a configurable socket timeout (default 15 s).

HTTPS on Pico 1 W: TLS needs ~9.5 KB contiguous heap. Run freeup before network-heavy work, or use HTTPS from a fresh boot. If your host uses Cloudflare's "Always Use HTTPS" redirect, HTTP requests will be 301'd and may hit this limit. Use https:// URLs directly or disable that Cloudflare setting for your repo host.

Package Manager

Packages are .pkg files: standard ZIP archives with a package.cfg metadata file inside.

Package metadata (package.cfg)

KeyDescription
pkg.nameDisplay name
pkg.devAuthor
pkg.verVersion string
pkg.dirInstall path (e.g. /Packages/HelloWorld)
pkg.descShort description
pkg.cmdShell command: name:/path/handler.py:function

Commands

CommandDescription
pkg availableList all packages in the repo cache
pkg search <query>Search cache by name or description
pkg install <name>Install from repo cache
pkg install <file.pkg>Install a local archive
pkg remove <name>Uninstall
pkg listInstalled packages
pkg info <name>Details for an installed package
pkg updateRefresh repo indexes from the network
pkg upgradeUpgrade installed packages that have newer versions in cache
pkg repo listConfigured repo URLs
pkg repo add <url>Add a repo
pkg repo remove <url>Remove a repo

Commands installed by packages are available immediately after install. They vanish immediately after removal. No reboot required either way.

Quick start

pkg repo add https://raw.githubusercontent.com/dash1101/RPCortex-repo/main/repo/index.json
pkg update
pkg available
pkg install HelloWorld

Repo index format

Repos are JSON files hosted anywhere (GitHub raw URLs work):

{
  "name": "My Repo",
  "packages": [
    {
      "name": "HelloWorld",
      "ver": "1.0.0",
      "author": "dash1101",
      "desc": "Sample package",
      "url": "https://..."
    }
  ]
}

Building packages

repo/make_pkg.py is a PC-side script that builds a .pkg from a source directory:

python make_pkg.py MyPackage/

Packages must use ZIP_STORED (no compression) — make_pkg.py handles this automatically. If you build with a standard ZIP tool using deflate, install will fail unless the target firmware has zlib.

Full package development guide →

Web Tools

Three browser-based tools let you interact with a connected device over USB — no WiFi, no raw REPL required. All use the Web Serial API (Chromium-based browsers: Chrome, Edge).

Web Installer

Flash MicroPython and copy RPCortex to the board directly from your browser. No software to install.

Package Browser

Browse and install packages while the device is running the shell. Files are pushed via the _xfer serial protocol. One-click install, no reboot needed, no WiFi required on the device. Each package card also has a Download .pkg button to save the package file to your computer.

OS Update

Update RPCortex from a browser tab while the shell is running. Load a .rpc archive from your computer or pick a version from the server. The page reads the archive with JSZip, skips user data paths, pushes each file via _xfer, and sends reboot when done.

Editor

The built-in terminal editor is invoked with:

edit myfile.py
nano /Core/somefile.py
vi                         # scratch buffer, no file

Controls

KeyAction
Arrow keysMove cursor
Ctrl+SSave
Ctrl+QQuit
Ctrl+XSave and quit
Ctrl+KCut line
Ctrl+UPaste line
Ctrl+FFind
Ctrl+GGo to line number
Requires a real terminal emulator. Thonny's REPL doesn't render ANSI escape sequences correctly.

Settings Panel

Run settings to open an interactive panel. As of v0.9.1 it uses the SysMon-style borderless layout and redraws efficiently — toggling a setting repaints only that row, not the whole screen:

  RPCortex Settings                      125 MHz  27.4C  92 KB
══════════════════════════════════════════════════════════════

══ SYSTEM ════════════════════════════════════════════════════
  [1] Verbose Boot         : OFF
  [2] Program Execution    : ON

══ HARDWARE ══════════════════════════════════════════════════
  [3] Boot Overclock       : OFF
  [4] Beeper               : OFF
  [5] SD Card Support      : OFF

══ NETWORK ═══════════════════════════════════════════════════
  [6] WiFi Autoconnect     : ON

══ PERSONALIZATION ═══════════════════════════════════════════
  [o] Owner                : Dash
  [t] Timezone Offset      : -5       hrs from UTC
  [d] Device ID            : pulsar   hostname
  [i] Idle Logout          : 0        minutes (0 = off)

══════════════════════════════════════════════════════════════
  [1-6] toggle   [o/t/d/i] edit   [r] refresh   [q] quit

[1–6] toggle a setting. [o/t/d/i] edit a personalization value (no more reg set needed). [r] refreshes the title-bar stats. [q] exits.

Settings reference

KeySettingRegistry key
1Verbose BootSettings.Verbose_Boot
2Program ExecutionFeatures.Program_Execution
3Boot OverclockSettings.OC_On_Boot
4BeeperFeatures.beeper
5SD Card SupportFeatures.SD_Support
6WiFi AutoconnectSettings.Network_Autoconnect
oOwnerSystem.Owner
tTimezone OffsetSystem.TZ_Offset
dDevice IDSystem.Device_ID
iIdle Logout (minutes; 0 = off)Settings.Idle_Logout

Registry

The registry lives at /Pulsar/Registry/registry.cfg as a plain INI file. It's created from an embedded template on first boot if missing.

[System]

KeyValuesDescription
CodenamestringRelease codename (e.g. RPCortex B9 - Pulsar); re-synced from the running code every boot
Device_IDstringHostname shown in the shell prompt (user@<Device_ID>). Change it: reg set System.Device_ID mypico
Owner (v0.9.1)stringDevice owner name, shown in sysinfo; prompted at first-run setup. reg set System.Owner Dash
TZ_Offset (v0.9.1)integerTimezone offset in whole hours (e.g. -5), applied to date output. Default 0 (UTC).

[Settings]

KeyValuesDescription
Setuptrue/falseFirst-run wizard completed
OC_On_Boottrue/falseApply max clock on every boot
Verbose_Boottrue/falseShow POST info messages
Network_Autoconnecttrue/falseWiFi autoconnect on boot
Idle_Logout (v0.9.1)integerAuto-logout after this many minutes of shell inactivity. 0 (default) disables it; read live, so it applies without re-login.
Active_UserstringCurrent session user
Startup0 / 1 / 3 / 6 / 7Boot state sentinel. 0 = clean, 1 = session active, 3 = update crashed, 6 = clock calibration crashed, 7 = boot clock crashed
VersionstringOS version; re-synced from the running code every boot (can't drift after an update)
NotestringOne-shot post-action notification. Set to "update_ok" after a successful update; displayed at next login then cleared.

[Hardware]

KeyDescription
Clockabletrue after clock calibration completes
Min_ClockMinimum safe CPU clock (e.g. 30.0MHz)
Max_ClockMaximum safe CPU clock (e.g. 220.0MHz)
Boot_ClockSpecific boot clock override (blank = use Max_Clock)
beeper_pinGPIO pin for beeper, or None

[Networks]

Saved WiFi networks are stored separately in /Pulsar/Registry/networks.cfg (tab-separated SSID/password, unlimited entries) — not in the registry. wifi connect saves automatically and reuses saved passwords.

[Features]

KeyDefaultDescription
Program_ExecutiontrueAllow running scripts with exec
SerialtrueSerial interface active
SD_SupportfalseSD card (not yet implemented)
NovafalseNova GUI (future)

Shell access

reg get Settings.OC_On_Boot        # read a key
reg set Settings.OC_On_Boot true   # write a key
env                                 # dump all sections
env Settings                        # dump one section

POST

POST runs on every boot before the login prompt. It prints status for each check and stops if a critical check fails.

CheckCriticalNotes
RegistryYesCreates registry from template if missing
CPU arithmeticYesFloat, int, comparison, bitwise
RAMYesAllocates a buffer and verifies a write pattern
Clock calibrationNoRuns once; RP2 gets 220 MHz max without probing
WLANNoChecks for WiFi hardware; autoconnects if configured
BeeperNoInitializes GPIO beeper if configured

Session Logging

Every session is logged to /Pulsar/Logs/latest.log. The log captures everything printed through the OS output functions (ok, info, warn, error, fatal).

Log rotation on each boot:

latest.log -> log_1.log -> log_2.log -> ... -> log_9.log (dropped)

Up to 10 logs are kept. The /Pulsar/Logs/ directory is created automatically by POST on first boot. You don't need to create it manually.

Hardware & Performance

Overclocking

RPCortex detects the CPU's safe clock range on first boot. For RP2040/RP2350 the stored max is 220 MHz.

pulse set 220      # set CPU to 220 MHz for this session
pulse set 240      # overclock beyond safe default (warning shown)
pulse boot on      # apply on every boot
settings           # toggle via settings panel

Manual overclock beyond 220 MHz is allowed. A warning is shown but the clock is set to whatever you specify. The RP2040 is generally stable up to around 240–250 MHz with the right flash timing.

RPCMark

bench runs the RPCMark suite: integer ops, floating-point ops, Mandelbrot iteration, and Pi approximation. Results are printed as calculation times in milliseconds. (Formerly “NebulaMark” / “PulseMark” — RPCMark is the permanent name.)

Heap and fragmentation

freeup clears the command cache and runs garbage collection. Use it before heavy network operations or when you get a MemoryError despite apparent free RAM. meminfo shows the current heap state.

Supported Hardware

BoardStatusRAM
Raspberry Pi Pico 2 W (RP2350 + WiFi)Recommended520 KB
ESP32-S3RecommendedVaries
Raspberry Pi Pico (RP2040)Supported264 KB
Raspberry Pi Pico W (RP2040 + WiFi)Supported264 KB
Raspberry Pi Pico 2 (RP2350)Supported520 KB
ESP32 / ESP32-S2SupportedVaries

MicroPython v1.25+  •  4 MB flash recommended  •  256 KB+ RAM  •  Serial terminal at 115200 baud

Security

Known Limitations

RPCortex Pulsar v0.9.1  •  by dash1101