Getting Started
What you need:
- Raspberry Pi Pico, Pico W, Pico 2, or a compatible ESP32 board
- MicroPython firmware v1.25 or newer (v1.28 recommended)
- A serial terminal at 115200 baud — PuTTY on Windows, minicom or screen on Linux/macOS
Installation
- Flash MicroPython to your board
- Copy all files from the repo to the root of the board's filesystem
- Connect your serial terminal at 115200 baud
- Reboot —
main.pystarts automatically on power-up
First boot
A setup wizard runs on first boot:
- You set the
rootpassword (the administrator account) - You choose whether to enable verbose boot (detailed POST messages on each startup)
- A
guestaccount 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
| Key | Action |
|---|---|
| Up / Down | Scroll command history (last 50) |
| Left / Right | Move cursor within the line |
| Home / Ctrl+A | Jump to beginning of line |
| End / Ctrl+E | Jump to end of line |
| Delete | Delete character under cursor |
| Backspace | Delete character before cursor |
| Ctrl+C | Cancel 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
| Command | Description |
|---|---|
| ls [path] | List directory — type, size, modification time, name |
| cd <path> | Change directory. cd, cd ~, and cd ~/sub all work |
| pwd | Print 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) |
| df | Flash 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).
| Command | Description |
|---|---|
| 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
| Command | Description |
|---|---|
| sysinfo | OS version, user, CPU, RAM, flash summary |
| meminfo | Detailed RAM breakdown |
| uptime | Time since last boot |
| date | Current 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 |
| ver | OS version string |
| clear / cls | Clear the terminal |
| fetch / neofetch | System info display with ASCII logo |
| reboot | Hard reset |
| sreboot / softreset | Soft reset (faster, keeps filesystem) |
| freeup / gc | Clear 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 |
| rawrepl | Exit 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 |
| history | Show command history |
| env [section] | Dump registry contents |
| reg get <key> | Read a registry key |
| reg set <key> <val> | Write a registry key |
| settings | Open the settings panel |
| edit [file] | Open the built-in editor |
| bench | Run the RPCMark benchmark |
pulse subcommands
| Command | Description |
|---|---|
| pulse status | Show 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|off | Enable or disable boot overclock |
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.
| Command | Description |
|---|---|
| startup | List configured startup tasks |
| startup add <command> | Append a command (e.g. startup add wifi connect) |
| startup remove <n> | Remove task number n |
| startup clear | Remove all startup tasks |
| startup run | Run 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.
| Command | Description |
|---|---|
| task | List scheduled tasks |
| task add <secs> <command> | Run <command> every <secs> seconds |
| task remove <n> | Remove task number n |
| task clear | Remove all scheduled tasks |
| task run | Start the scheduler loop (press q / Ctrl+C to stop) |
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.
| Statement | Meaning |
|---|---|
# comment | Comment line (ignored) |
set NAME VALUE | Define 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 … end | Conditional block (else optional) |
while COND … end | Loop while COND is true |
break / continue | Exit / skip the current while iteration |
stop | End 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):
| Test | True when |
|---|---|
eq A B / ne A B | A equals / does not equal B |
gt A B / lt A B | A > B / A < B (numeric when both look like numbers, else text) |
ge A B / le A B | A ≥ B / A ≤ B |
contains A B | B is a substring of A |
exists PATH | The file or directory exists |
empty A | A is empty |
not COND | Negates 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.
| Command | Description |
|---|---|
| fscheck | Verify core OS files exist and are non-empty |
| diag | Health snapshot: free RAM, free flash, registry, version |
| logdump [n] | Print the session log (last n lines if given) |
| regreset | Delete 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 |
| recovery | Enter 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
- Requires a WiFi connection (
wifi connectfirst) - Preserves all user data — accounts, WiFi, settings, and installed packages
- The running version and codename are re-synced from the new code on the next boot, so they can never drift
update from-file
Extracts a .rpc release archive to the running OS:
update from-file /path/to/os.rpc
- Preserves
/Users/,/Pulsar/(accounts, WiFi credentials, package config) - Sets a crash sentinel before writing files — if the device loses power mid-update, the sentinel is detected on the next boot
- Reboots automatically on success; shows "Now running RPCortex vX.Y.Z" at next login
factoryreset
Soft reset — restores the OS to a clean first-run state while keeping core files intact:
factoryreset
- Restores registry defaults
- Wipes all user accounts and home directories
- Removes non-builtin packages
- Clears logs
- Prompts
CONFIRMbefore proceeding - Reboots into the first-run setup wizard
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
- Deletes
/Core/,/Packages/,/Pulsar/,/Users/ - Writes a minimal stub as
/main.pythat extracts/update.rpcon the next boot - Prompts
WIPEbefore proceeding - If a
.rpcpath is given, it is staged as/update.rpcand extracted automatically on the next 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:
- The shell exits and the MicroPython REPL becomes active (
>>>prompt visible in your terminal). - Open rpc.novalabs.app/install in Chrome or Edge.
- Click Connect Device and flash normally.
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
| Scenario | Command / Tool |
|---|---|
| Update OS, keep all user data | update from-file /path/to/os.rpc or browser update page |
| Reset to clean factory state | factoryreset |
| Use Web Installer without rebooting | rawrepl |
| Full wipe + re-flash | reinstall or rawrepl + Web Installer |
User Management
| Command | Description |
|---|---|
| whoami | Current logged-in user |
| users | List all accounts with active / admin / nopass tags |
| mkacct | Create 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 / exit | End session, return to login |
Account details
- Profiles stored in
/Pulsar/Registry/user.cfgas CSV - Each account gets
/Users/<username>/created on account creation - Passwords stored as salted SHA256 — unique salt per account
guestuses theNOPASSmarker — any password, including blank, is acceptedrootis created during first-run setup and is the administrator account
Networking
WiFi works on any board with a network module: Pico W, Pico 2 W, and most ESP32 variants.
WiFi commands
| Command | Description |
|---|---|
| wifi status | Connection state, SSID, IP |
| wifi scan | Nearby networks with signal strength |
| wifi connect [ssid] | Connect (prompts for password; uses saved if available) |
| wifi disconnect | Drop the current connection |
| wifi list | Saved 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
| Command | Description |
|---|---|
| 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).
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)
| Key | Description |
|---|---|
| pkg.name | Display name |
| pkg.dev | Author |
| pkg.ver | Version string |
| pkg.dir | Install path (e.g. /Packages/HelloWorld) |
| pkg.desc | Short description |
| pkg.cmd | Shell command: name:/path/handler.py:function |
Commands
| Command | Description |
|---|---|
| pkg available | List 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 list | Installed packages |
| pkg info <name> | Details for an installed package |
| pkg update | Refresh repo indexes from the network |
| pkg upgrade | Upgrade installed packages that have newer versions in cache |
| pkg repo list | Configured 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
| Key | Action |
|---|---|
| Arrow keys | Move cursor |
| Ctrl+S | Save |
| Ctrl+Q | Quit |
| Ctrl+X | Save and quit |
| Ctrl+K | Cut line |
| Ctrl+U | Paste line |
| Ctrl+F | Find |
| Ctrl+G | Go to line number |
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
| Key | Setting | Registry key |
|---|---|---|
| 1 | Verbose Boot | Settings.Verbose_Boot |
| 2 | Program Execution | Features.Program_Execution |
| 3 | Boot Overclock | Settings.OC_On_Boot |
| 4 | Beeper | Features.beeper |
| 5 | SD Card Support | Features.SD_Support |
| 6 | WiFi Autoconnect | Settings.Network_Autoconnect |
| o | Owner | System.Owner |
| t | Timezone Offset | System.TZ_Offset |
| d | Device ID | System.Device_ID |
| i | Idle 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]
| Key | Values | Description |
|---|---|---|
| Codename | string | Release codename (e.g. RPCortex B9 - Pulsar); re-synced from the running code every boot |
| Device_ID | string | Hostname shown in the shell prompt (user@<Device_ID>). Change it: reg set System.Device_ID mypico |
| Owner (v0.9.1) | string | Device owner name, shown in sysinfo; prompted at first-run setup. reg set System.Owner Dash |
| TZ_Offset (v0.9.1) | integer | Timezone offset in whole hours (e.g. -5), applied to date output. Default 0 (UTC). |
[Settings]
| Key | Values | Description |
|---|---|---|
| Setup | true/false | First-run wizard completed |
| OC_On_Boot | true/false | Apply max clock on every boot |
| Verbose_Boot | true/false | Show POST info messages |
| Network_Autoconnect | true/false | WiFi autoconnect on boot |
| Idle_Logout (v0.9.1) | integer | Auto-logout after this many minutes of shell inactivity. 0 (default) disables it; read live, so it applies without re-login. |
| Active_User | string | Current session user |
| Startup | 0 / 1 / 3 / 6 / 7 | Boot state sentinel. 0 = clean, 1 = session active, 3 = update crashed, 6 = clock calibration crashed, 7 = boot clock crashed |
| Version | string | OS version; re-synced from the running code every boot (can't drift after an update) |
| Note | string | One-shot post-action notification. Set to "update_ok" after a successful update; displayed at next login then cleared. |
[Hardware]
| Key | Description |
|---|---|
| Clockable | true after clock calibration completes |
| Min_Clock | Minimum safe CPU clock (e.g. 30.0MHz) |
| Max_Clock | Maximum safe CPU clock (e.g. 220.0MHz) |
| Boot_Clock | Specific boot clock override (blank = use Max_Clock) |
| beeper_pin | GPIO 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]
| Key | Default | Description |
|---|---|---|
| Program_Execution | true | Allow running scripts with exec |
| Serial | true | Serial interface active |
| SD_Support | false | SD card (not yet implemented) |
| Nova | false | Nova 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.
| Check | Critical | Notes |
|---|---|---|
| Registry | Yes | Creates registry from template if missing |
| CPU arithmetic | Yes | Float, int, comparison, bitwise |
| RAM | Yes | Allocates a buffer and verifies a write pattern |
| Clock calibration | No | Runs once; RP2 gets 220 MHz max without probing |
| WLAN | No | Checks for WiFi hardware; autoconnects if configured |
| Beeper | No | Initializes GPIO beeper if configured |
- Boot clock: if
Settings.OC_On_Boot = true, POST readsHardware.Boot_Clock(falls back toHardware.Max_Clock) and applies it viamachine.freq(). A crash sentinel (7) is written before the clock is applied — if the device crashes here, boot clock is disabled automatically on the next boot. - Verbose boot:
Settings.Verbose_Boot = falseby default. POST only prints warnings and errors. Enable it to see all informational messages. - Crash sentinels:
6is written before clock calibration,7before applying the boot clock. If the device crashes during either, the sentinel disables the relevant feature on the next boot.
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
| Board | Status | RAM |
|---|---|---|
| Raspberry Pi Pico 2 W (RP2350 + WiFi) | Recommended | 520 KB |
| ESP32-S3 | Recommended | Varies |
| Raspberry Pi Pico (RP2040) | Supported | 264 KB |
| Raspberry Pi Pico W (RP2040 + WiFi) | Supported | 264 KB |
| Raspberry Pi Pico 2 (RP2350) | Supported | 520 KB |
| ESP32 / ESP32-S2 | Supported | Varies |
MicroPython v1.25+ • 4 MB flash recommended • 256 KB+ RAM • Serial terminal at 115200 baud
Security
- Passwords use salted SHA256. Each account has a unique random salt, so rainbow tables don't apply. Accounts created before v0.8.0-rc used unsalted SHA256 and upgrade on the next password change.
- WiFi credentials are stored in plaintext in
networks.cfg. There is no secure storage mechanism on this hardware. - Home directories provide logical separation at
/Users/<username>/. There is no kernel-enforced permission model.
Known Limitations
- MemoryError in the shell — may occur after heavy use due to heap fragmentation. Run
freeupto compact the heap. If it persists,rebootclears it. Being actively worked on. - ESP32-S3 temperature sensor — the onboard temperature sensor on ESP32-S3 is not calibrated in the same way as the RP2040.
fetchwill show unrealistic values (typically 300–450 °C). This is a hardware/firmware limitation, not a bug in RPCortex. RP2040/RP2350 temperature is accurate. - No real-time clock on base Pico —
dateshows time since boot epoch until the RTC is set manually - HTTPS on Pico 1 W — TLS needs ~9.5 KB contiguous heap; run
freeupfirst if the heap is fragmented - WiFi passwords stored plaintext — no secure enclave on this hardware
- Editor requires a real terminal — Thonny REPL won't render it
- SD card support — registry key exists, implementation pending
RPCortex Pulsar v0.9.1 • by dash1101