| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| PeekESPv0.1.0.apk | 2026-10-18 | 11.5 MB | |
| firmware-panels-1.2.1.zip | 2026-10-12 | 6.2 MB | |
| PeekESP-merged.bin | 2026-10-12 | 1.4 MB | |
| peek-agent.exe | 2026-10-12 | 9.1 MB | |
| PeekESP-1.2.1-win-x64.zip | 2026-10-12 | 27.4 MB | |
| PeekESP-1.2.1-win-x64.zip.sha256 | 2026-10-12 | 93 Bytes | |
| PeekESP.exe | 2026-10-12 | 18.8 MB | |
| peekesp_1.2.1_all.deb | 2026-10-12 | 19.4 kB | |
| winget-manifests-1.2.1.zip | 2026-10-12 | 1.6 kB | |
| PeekESP v1.2.1 source code.tar.gz | 2026-10-10 | 12.1 MB | |
| PeekESP v1.2.1 source code.zip | 2026-10-10 | 12.2 MB | |
| README.md | 2026-10-10 | 13.5 kB | |
| Totals: 12 Items | 98.8 MB | 3 | |
PeekESP v1.2.1
A physical system-metrics dashboard. An ESP32 with a 1.14" display shows live CPU, RAM, storage, temperature and network throughput for machines anywhere on the internet — no port forward, no VPN, no account.
No ESP32? The new Android app and its home-screen widget show the same readings on your phone, with or without a display.
By rhshourav · MIT
Downloads
winget install rhshourav.PeekESP
Or take what you need directly:
File | What it is -- | -- PeekESP.exe | The tray app. Double-click it — this is the one most people want on Windows peek-agent.exe | Headless, for a service or scheduled task PeekESP-1.2.1-win-x64.zip | Both of the above plus the licence. This is what winget installs PeekESP.apk | Android app and home-screen widget. Android 8.1 or newer peekesp_1.2.1_all.deb | Debian, Ubuntu, Raspberry Pi OS, DietPi PeekESP-merged.bin | Firmware for the board — python tools/flash.py winget-manifests-1.2.1.zip | Only needed to submit this version to wingetNot verified
The device-side work in this release has not run on hardware. Standby, the clock, the corrected battery reading, the redesigned settings page, the multi-network join and the commands all compile; that is what can be said.
The charging threshold is still inferred — 4.15 V — because there is no charge-status pin to check it against. The voltage is on screen beside the percentage so it can be corrected against a real board.
Known limits
The free tier is a request budget, not a device count. At a 5-second
interval each agent costs 17,280 requests/day and each display 17,280, against
Cloudflare's 100,000. A display with two machines is ~52k and fits; four is
~86k and is close. peekesp set interval 15 divides it by three. A phone or
widget that polls counts like another display, so count it in.
The Android app is installed from the APK for now. It is not on Google Play
yet, so it will not update itself; install the next release's PeekESP.apk over
this one. Android also decides how often a widget may refresh, so it updates far
less often than a display. [TODO: actual widget refresh interval.]
There is no over-the-air update. The huge_app scheme has one application
slot, and the image no longer fits a two-slot layout. Updating the firmware
means a cable.
Temperature on Windows is an ACPI zone unless LibreHardwareMonitor is running. Real reading, real place, not the CPU die.
2.4 GHz only, WPA2. An ESP32 has no 5 GHz radio.
Re-flashing keeps the pairing code. It lives in NVS and survives a firmware
update. python tools/flash.py --erase gets a new one, and so does the button
on the settings page.
An ESP32 cannot join a Tailscale network. Tailscale is WireGuard plus a control plane, and none of that has an embedded client. The relay exists because of this.
Thanks
LVGL, TFT_eSPI, ArduinoJson, and LilyGO for the board.
PeekESP v1.2.1
A physical system-metrics dashboard. An ESP32 with a 1.14" display shows live CPU, RAM, storage, temperature and network throughput for machines anywhere on the internet — no port forward, no VPN, no account.
No ESP32? The new Android app and its home-screen widget show the same readings on your phone, with or without a display.
By rhshourav· MIT
Downloads
:::powershell
winget install rhshourav.PeekESP
Or take what you need directly:
| File | What it is |
|---|---|
PeekESP.exe |
The tray app. Double-click it — this is the one most people want on Windows |
peek-agent.exe |
Headless, for a service or scheduled task |
PeekESP-1.2.1-win-x64.zip |
Both of the above plus the licence. This is what winget installs |
PeekESP.apk |
Android app and home-screen widget. Android 8.1 or newer |
peekesp_1.2.1_all.deb |
Debian, Ubuntu, Raspberry Pi OS, DietPi |
PeekESP-merged.bin |
Firmware for the board — python tools/flash.py |
winget-manifests-1.2.1.zip |
Only needed to submit this version to winget |
Linux, one line:
:::bash
curl -fsSL https://raw.githubusercontent.com/rhshourav/PeekESP/main/dietpi/install.sh | sudo sh
Android: download PeekESP.apk from this page and open it. It is not on Google
Play yet — that listing is coming — so Android will ask you to allow Install
unknown apps for your browser or file manager the first time. Switch that
permission off again afterwards.
The Windows executables are unsigned, so SmartScreen warns the first time:
More info → Run anyway. The .sha256 beside the zip lets you check the file
is the one that was built. Why it is unsigned, and what fixing it
costs.
New in 1.2.1
- Android support —
PeekESP.apk, an app plus a home-screen widget. See below. - The repository has moved from
shouravxtorhshourav, the original account. Both accounts belong to the same person, MD Shourav Hossain. Every reference toshouravxhas been changed torhshourav. - Some minor UI changes.
Android app
The app lets you use PeekESP from your phone, with or without an ESP32. It reads the same relay as every other client, so a phone, a desk display and Home Assistant can all watch the same machines at once.
- Join an existing network — type the code your device or agents already
use, e.g.
K7M2-P4QX-9R. Dashes and case are ignored. - Create a new network — the app generates a code. Give that same code to
each agent (
sudo peekesp pair CODEon Linux, Settings → Pair a device in the Windows app). [TODO: say whether an ESP32 can adopt an app-made code, and how.] - Home-screen widget — long-press the home screen → Widgets → PeekESP. It shows CPU and RAM, storage, temperature, network throughput, uptime and link status, depending on what the machine reports.
Needs Android 8.1 or newer. Every machine run with the same code appears in the app, up to six, exactly as on the display.
Update checks, and commands from the desktop
The relay is talking to the device anyway, so it now carries the latest release
tag with the reply and the device raises a banner when it is behind. The
alternative — every device polling api.github.com — is a second host, a
second certificate authority in an image with no room, and a second request per
device per interval against the budget that is the actual limit here.
The tray app checks for its own updates on a six-hour floor, and can send the device a short, closed list of commands: reboot, standby, wake, refresh, identify (flashes the screen, so you can tell two boards apart), jump to a page, and set the backlight.
A command is left at the relay and collected on the next poll, so there is still nothing listening anywhere. It is delivered at most once and dropped after five minutes. Nothing in that vocabulary changes configuration and everything in it is undone by pressing a button on the device — configuration is what the settings page is for, behind its own password.
Packaging and CI
peekesp_1.2.1_all.deb—sudo apt install ./peekesp_1.2.1_all.deb. Built withdpkg-debalone, no container and no sponsor.packaging/aur/PKGBUILDfor Arch.- The release is built by CI from the tag: the Linux package is installed
and its files checked, the Windows agent is run and its JSON parsed, the tag
is checked against the
VERSIONfile, and every asset is named rather than counted. It stops at a draft — publishing is a person clicking publish. - The firmware compiles on every push, under
--warnings all, with a size ceiling and a check that the committed image is not older than the sketch.
A landing page
rhshourav.github.io/PeekESP — photographs of the real device, what it does, and how to flash it.
What's in the box
Firmware — LVGL dashboard on a LilyGO TTGO T-Display. Two arcs, a bar, a temperature and throughput panel, a clock and a power page. Values sweep to new readings over 500 ms rather than snapping. Swiping between machines slides the whole dashboard body as one object, with values swapped at the midpoint while nothing is visible.
Android app — a phone-based way to view the same data, with a home-screen widget. Join an existing network or create a new one from a code; the ESP32 is optional.
Cloudflare Worker relay — the hosts push, the device polls, both only ever dial out. Three modes on one deployment: paired (no secrets at all), private (two tokens), shared (named streams). 86 automated tests.
Agents — Linux and Windows, both standard-library only. The Windows build
adds a tray app with a settings window and a headless peek-agent.exe.
Prebuilt firmware — firmware/PeekESP-merged.bin. Flashing needs no
Arduino IDE, no ESP32 core and no libraries; only esptool.
Architecture
Two pinned FreeRTOS tasks sharing nothing but a mutex-guarded struct. Core 0
does WiFi, NTP, the blocking HTTPS request and the battery ADC. Core 1 runs
lv_timer_handler() and never opens a socket, so a slow link cannot drop a
frame. The ADC moved off the render path in this release: sampling it inside
the LVGL loop meant a battery reading and an animation frame competing for the
same core.
The pairing derivation is the same three lines in every client:
stream = SHA-256("peek-stream:" + CODE) first 16 hex
push = SHA-256("peek-push:" + CODE) first 48 hex
read = SHA-256("peek-read:" + CODE) first 48 hex
C++ on the device, Python in the Windows app, Python again in the Linux agent,
JavaScript in the Worker — all pinned against vectors generated independently
by openssl. The Android app uses the same derivation, so a code means the
same stream on a phone as on the display. [TODO: confirm the Android app is covered by the same test vectors.]
A drift between any two would mean a machine pushing to a stream the device
never reads, with every request still looking perfectly valid from both ends.
Verified
| Firmware | compiles clean under --warnings all, 43 % of a 3 MB partition |
| Worker | 86 unit tests, plus live checks against the real deployment |
| Multi-device | three machines under one code, proven live end to end |
| Agents | Windows snapshot checked against PowerShell; Linux run in CI |
| Packaging | the .deb is installed and inspected in CI; manifests pass winget validate |
| Android | [TODO: devices and Android versions it has been run on] |
Not verified
The device-side work in this release has not run on hardware. Standby, the clock, the corrected battery reading, the redesigned settings page, the multi-network join and the commands all compile; that is what can be said.
The charging threshold is still inferred — 4.15 V — because there is no charge-status pin to check it against. The voltage is on screen beside the percentage so it can be corrected against a real board.
Known limits
The free tier is a request budget, not a device count. At a 5-second
interval each agent costs 17,280 requests/day and each display 17,280, against
Cloudflare's 100,000. A display with two machines is ~52k and fits; four is
~86k and is close. peekesp set interval 15 divides it by three. A phone or
widget that polls counts like another display, so count it in.
The Android app is installed from the APK for now. It is not on Google Play
yet, so it will not update itself; install the next release's PeekESP.apk over
this one. Android also decides how often a widget may refresh, so it updates far
less often than a display. [TODO: actual widget refresh interval.]
There is no over-the-air update. The huge_app scheme has one application
slot, and the image no longer fits a two-slot layout. Updating the firmware
means a cable.
Temperature on Windows is an ACPI zone unless LibreHardwareMonitor is running. Real reading, real place, not the CPU die.
2.4 GHz only, WPA2. An ESP32 has no 5 GHz radio.
Re-flashing keeps the pairing code. It lives in NVS and survives a firmware
update. python tools/flash.py --erase gets a new one, and so does the button
on the settings page.
An ESP32 cannot join a Tailscale network. Tailscale is WireGuard plus a control plane, and none of that has an embedded client. The relay exists because of this.
Thanks
LVGL, TFT_eSPI, ArduinoJson, and LilyGO for the board.