Download Latest Version PeekESP-1.2.1-win-x64.zip (27.4 MB) Google Add to Preferred Sources
Home / v1.2.1
Name Modified Size InfoDownloads / 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 winget

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.

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 shouravx to rhshourav, the original account. Both accounts belong to the same person, MD Shourav Hossain. Every reference to shouravx has been changed to rhshourav.
  • 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 CODE on 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 with dpkg-deb alone, no container and no sponsor.
  • packaging/aur/PKGBUILD for 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 VERSION file, 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.

Source: README.md, updated 2026-10-10