Pyrite CLI is a focused command-line toolkit for MicroPython boards. It helps you find devices, flash files, sync projects, inspect the device filesystem, install packages through mpremote mip, monitor GPIO inputs, open a REPL, mount device files through WebDAV, and reverse-mount host files through mpremote from one pyrcli command surface. It's also friendly to agents like Codex and Claude Code that coding with your device will be much easier.
It talks to boards through UART raw REPL by default, and can use WebREPL over WebSocket when you add --ws.
| Task | Command | Notes |
|---|---|---|
| Find boards | pyrcli scan |
Serial scan, optional board probing, JSON output |
| Name a serial port | pyrcli board register COM3 --name lab |
Save a local name -> port alias |
| Flash one file | pyrcli flash COM3 main.py /main.py |
Preprocess, optionally compile to .mpy, transfer, verify |
| Sync a project | pyrcli project flash COM3 . /app |
Upload only added or changed files |
| Develop live | pyrcli project dev COM3 . /app --lens |
Watch, sync, map tracebacks, and run device tests |
| Run device tests | pyrcli test COM3 test_device/ |
Upload tests to the board and parse result frames |
| Snapshot files | pyrcli snapshot save COM3 before-change |
Save, diff, and restore device filesystem snapshots |
| Tunnel host features | pyrcli tunnel network COM3 --allow example.com |
Keyboard input and restricted HTTP(S) forwarding |
| Browse files | pyrcli fs ls COM3 / |
List, upload, download, remove, move, and copy files |
| Install packages | pyrcli pkg install COM3 aioble |
Delegate host-side package install to mpremote mip install |
| Monitor GPIO | pyrcli monitor COM3 --pins 0,2,4 --count 10 |
Read GPIO inputs without changing pulls or output mode |
| Mount files | pyrcli mount COM3 |
Expose the device filesystem through local WebDAV |
| Reverse mount | pyrcli remount COM3 . |
Expose a host directory to the device as /remote through mpremote |
| Debug live | pyrcli repl COM3 |
Open an interactive MicroPython REPL |
| Use WebREPL | --ws ws://XXX:XXXX |
Route device commands through WebREPL |
Pyrite CLI requires Python 3.10 or newer.
pip install pyrite-climpremote is installed as a runtime dependency and is used by pyrcli remount and pyrcli pkg.
For local development from this repository:
pip install -e .Use the examples with your own serial port in place of COM3.
# Find connected boards
pyrcli scan
pyrcli scan -i
# Inspect a board
pyrcli debug board-info COM3
# Save a local serial-port alias, then use it anywhere a serial PORT is accepted
pyrcli board register COM3 --name lab
pyrcli debug board-info @lab
# Flash, then use the REPL
pyrcli flash @lab main.py /main.py
pyrcli repl @lab
# In the REPL: import machine; print(machine.freq())
# Watch the project and expand tracebacks to local source context
pyrcli project dev COM3 . /app --lens
pyrcli project dev COM3 . /app --test-on-save=all --test-path test_device/
# Work with files
pyrcli fs ls COM3 /
pyrcli fs put COM3 local.py /remote.py
pyrcli fs get COM3 /remote.py local_copy.pyMount the device filesystem in your desktop file manager:
pyrcli mount COM3Reverse-mount the current host directory so code on the device can import and open files from /remote:
pyrcli remount COM3 .Install a MicroPython package through the host-side mpremote mip path, or inspect the plan first:
pyrcli pkg install COM3 aioble --target /lib --dry-run
pyrcli pkg install COM3 aioble --target /libMonitor GPIO inputs:
pyrcli monitor COM3 --pins 0,2,4,5 --interval 0.2 --count 20
pyrcli monitor COM3 --pins 0,2 --format json --count 5Save and restore a device filesystem snapshot:
pyrcli snapshot save COM3 before-change --remote-path /app
pyrcli snapshot diff COM3 before-change --remote-path /app
pyrcli snapshot restore COM3 before-change
pyrcli snapshot restore COM3 before-change --apply --yesForward host-side capabilities to a device helper:
pyrcli tunnel kb COM3
pyrcli tunnel network COM3 --allow example.comUse WebREPL instead of serial by adding --ws. The positional PORT stays in place for a consistent CLI shape; the WebSocket URL is the actual transport target.
pyrcli debug board-info COM3 --ws ws://192.168.4.1:8266 --password mypass
pyrcli flash COM3 main.py /main.py --ws ws://esp32.local:8266
pyrcli mount COM3 --ws ws://esp32.local:8266 --password mypassIf --password is omitted, WebREPL password resolution is: CLI option, PYRITE_WEBREPL_PASSWORD, then interactive prompt.
Pyrite CLI connects your device, transfers code in chunks, verifies the result, and restores the device session. Python files can be compiled to .mpy automatically before upload(Expect the main.py and boot.py). Pyrite CLI will check the update the code with smaller blocks that flashing can be much faster.
Board Alias stores only a local name -> serial port mapping. Manage aliases with pyrcli board register/list/show/remove/resolve, then use @alias anywhere a device serial PORT is accepted, including project setup and package installation.
The default store is .pyrite_board_aliases.json in the current directory. Set PYRITE_BOARD_ALIAS_FILE to choose another file, or pass --alias-file to a pyrcli board command. If no new alias file exists, the legacy .pyrite_board_profiles.json file is read only as a migration source; only its names and ports are imported when the next alias change writes the new format.
pyrcli project hash records local SHA256 hashes. pyrcli project flash compares that state and uploads only added or changed files.
pyrcli project dev watches a project and incrementally flashes changes. --lens expands MicroPython tracebacks into local source context, and --test-on-save=all|changed|off can run device-side tests after a successful sync. pyrcli test can upload and run test_device/ independently. On that command, --timeout / PYRITE_TIMEOUT controls device-test execution; --connect-timeout / PYRITE_CONNECT_TIMEOUT controls the device connection and I/O timeout.
pyrcli snapshot save/list/diff/restore saves device filesystem state, previews differences, and restores files. restore is dry-run by default and only writes to the device with --apply; diffing computes SHA256 on the host side for older firmware compatibility.
A Target is the board build identity used to activate board tags. It is independent of the local Board Alias and project connection settings. Use @feature("wifi"), @target("esp32"), with feature(...), and with target(...) to keep one source tree for several boards or firmware variants. Pyrite CLI rewrites the syntax with libcst, not regular expressions.
manifest.py can select modules and packages, remap remote paths, and filter files by feature tags. Use pyrcli manifest plan --target esp32_s3 to inspect the resolved plan and pyrcli manifest lock --target esp32_s3 to write pyrite.lock. Lockfile version 2 records target; version 1 lockfiles containing profile remain readable for compatibility. The manifest is parsed with ast and does not execute arbitrary code.
pyrcli mount starts a local WebDAV server and maps desktop file-manager actions to MicroPython file operations. Windows can map a drive letter; Linux and macOS open the WebDAV location in the default file manager.
pyrcli remount delegates to mpremote mount so the device sees a host directory at /remote. Pyrite CLI does not reimplement the mount protocol; it validates local arguments, locates mpremote, and hands the interactive session to it.
pyrcli pkg install delegates to mpremote mip install, keeping package resolution and downloads on the host side. --dry-run prints an auditable plan without connecting to the device. pyrcli pkg cache currently plans cache locations and audits local package.json metadata; it does not perform network downloads itself.
pyrcli monitor samples GPIO pins as machine.Pin(pin, machine.Pin.IN) only. You can pass --pins, --count, --duration, --edge changed, and --format json for scriptable runs.
pyrcli tunnel kb forwards host keyboard events to a device helper. pyrcli tunnel network lets the device request restricted HTTP(S) through the host; it requires explicit --allow, and private addresses require --allow-private.
When opening a serial port fails like it is occupied, an interactive terminal can ask whether to scan and terminate the holding process. Windows prefers Sysinternals handle.exe; Linux and macOS use lsof or fuser. Non-interactive runs skip this flow.
Serial and WebREPL share the same high-level MicroPython operations. Most device commands accept --ws and --password.
Create a project and prepare editor support:
pyrcli project new my-project
pyrcli project new my-project --platform esp32
pyrcli project new my-project --port COM3
pyrcli project new my-project --port COM3 --baudrate 115200 --timeout 15
pyrcli project init --port COM3 --baudrate 115200 --timeout 15When project new or project init probes a device through --port, --baudrate / PYRITE_BAUDRATE and --timeout / PYRITE_TIMEOUT override the project config defaults.
Flash a directory:
pyrcli flash-program COM3 src/ /app
pyrcli flash-program COM3 src/ /app --manifest manifest.pySync a project incrementally:
pyrcli project hash .
pyrcli project status COM3 . /app
pyrcli project flash COM3 . /app
pyrcli project flash COM3 . /app --snapshot-before before-flash
pyrcli project pull COM3 . /app
pyrcli project dev COM3 . /app --lens --test-on-save=allBrowse and mount files:
pyrcli fs ls COM3 ./
pyrcli fs cat COM3 /main.py
pyrcli mount COM3
pyrcli remount COM3 .Install packages and watch GPIO:
pyrcli pkg install COM3 aioble --target /lib --dry-run
pyrcli pkg install-offline COM3 .pyrite/pkg-cache/aioble
pyrcli monitor COM3 --pins 0,2,4,5 --count 20Pyrite CLI looks for .pyrite_config.json from the current directory upward.
{
"chunk_size": 4096,
"download_threads": 4,
"auto_compile": true,
"verify": "crc32",
"delta_flash": "auto",
"precheck": "basic",
"precheck_compat": "warn",
"precheck_mp_version": "",
"max_retries": 2,
"baudrate": 921600,
"timeout": 10
}The project config is one flat top-level JSON object. Legacy profile and profiles keys are ignored with a warning. For ordinary connection settings, precedence is: --baudrate / --timeout or PYRITE_BAUDRATE / PYRITE_TIMEOUT, then .pyrite_config.json, then the built-in default.
pyrcli test is the naming exception: --timeout / PYRITE_TIMEOUT is its device-test execution timeout, while --connect-timeout / PYRITE_CONNECT_TIMEOUT is its connection timeout.
| Field | Default | Meaning |
|---|---|---|
chunk_size |
4096 |
Maximum bytes per write |
download_threads |
4 |
Stub download concurrency, clamped to 1-12 |
auto_compile |
true |
Compile .py to .mpy automatically |
verify |
"size" |
off, size, or crc32 verification |
delta_flash |
"auto" |
Single-file delta flashing policy: off, auto, or on |
precheck |
"basic" |
Pre-flash code check: off, basic, or strict |
precheck_compat |
"warn" |
Strict compatibility handling: warn, error, or off |
precheck_mp_version |
"" |
Optional target MicroPython firmware version |
max_retries |
2 |
Retry count after verification or connection failure |
baudrate |
921600 |
Default serial baudrate |
timeout |
10 |
Default serial connection and I/O timeout in seconds |
Board tags can be extended in pyproject.toml:
[tool.pyrite.board_tags]
ESP32_S3 = ["ESP32", "wifi"]
C3 = ["ESP32", "wifi"]| Topic | Document |
|---|---|
| First steps, commands, config | Quick Start |
| Flashing protocol and project sync | Device Flashing and Project Sync |
| Conditional compilation guide | Conditional Compilation: Practical Guide |
| Conditional compilation syntax | Conditional Compilation & Macro Preprocessing |
| WebDAV desktop mount | WebDAV Mount |
| MicroPython firmware feature probes | MicroPython Firmware Feature Probes |
| Architecture notes | Architecture |
| Command | Purpose |
|---|---|
scan |
Scan serial devices, with filters and JSON output |
flash |
Flash one local file to the device |
flash-program |
Recursively flash a local directory |
repl |
Open an interactive REPL |
reset |
Soft-reset the device through raw REPL |
test |
Upload and run MicroPython tests on the device |
debug board-info |
Print firmware, CPU, memory, flash, and filesystem info |
debug doctor |
Run serial, raw REPL, filesystem, memory, and runtime feature diagnostics |
monitor |
Monitor GPIO input state |
mount |
Mount the device filesystem through local WebDAV |
remount |
Reverse-mount a host directory to device /remote through mpremote |
snapshot |
Save, diff, and restore device filesystem snapshots |
tunnel |
Forward keyboard input and restricted HTTP(S) requests |
pkg |
Install MicroPython packages via mpremote mip |
board |
Register, list, show, remove, and resolve local serial-port aliases |
manifest |
Preview a manifest plan or write a target-aware pyrite.lock |
config |
Create a default .pyrite_config.json |
| Command | Purpose |
|---|---|
project new |
Create a project and download stubs |
project init |
Add MicroPython stubs to an existing project |
project hash / project scan |
Calculate local file hashes |
project flash |
Upload only changed files |
project status |
Show local/device differences |
project pull |
Pull files from the device |
project run |
Sync, then enter REPL monitoring |
project dev |
Watch, incrementally sync, open REPL, map tracebacks, and run tests |
| Command | Purpose |
|---|---|
fs ls |
List files, with recursion, sorting, and paging |
fs cat |
Print a device text file |
fs put |
Upload a local file |
fs get |
Download a device file |
fs rm |
Remove a file or directory |
fs tree |
Show a tree view |
fs mv |
Move or rename |
fs cp |
Copy |
flash and fs put accept - as stdin input, and fs get REMOTE - writes raw bytes to stdout. If you need a literal file named -, use ./-.
Batch pipe commands use JSONL: one JSON object per line in, one JSON object per line out. Upload records accept {"local":"main.py","remote":"/main.py"} or self-contained {"remote":"/main.py","content_b64":"..."}; download records use {"remote":"/main.py"} and return content_b64.
printf '{"remote":"/main.py","content_b64":"cHJpbnQoMSkK"}\n' | pyrcli flash-batch COM3 --force
printf '{"remote":"/main.py"}\n' | pyrcli fs get-batch COM3 | jq -r '.content_b64' | base64 -d
printf '{"path":"/tmp.txt"}\n' | pyrcli fs rm-batch COM3 --force
pyrcli device backup COM3 ignored /app --stdout-jsonl > app-backup.jsonl
pyrcli device restore COM3 - /app --stdin-jsonl app-backup.jsonl
pyrcli snapshot restore COM3 - --stdin-jsonl app-backup.jsonl --apply --yes| Command | Purpose |
|---|---|
pkg install |
Run or dry-run mpremote mip install for a package name or URL |
pkg cache |
Plan local cache paths and audit local package metadata |
pkg install-offline |
Install a local package.json or package directory through mpremote mip |