Before you start
You’ll need three things: a Hack Club Sprig, a USB cable that carries data (not just power), and Python 3 on your computer. Shelby is MicroPython, so the device firmware and your machine’s Python are separate — your machine only runs the upload tool.
Installing
1 — Get the firmware
Clone the repository (or download a release tarball) and install mpremote, the official MicroPython upload tool.
# clone + tooling git clone https://github.com/Swamstick911/Shelby cd Shelby pip install mpremote
2 — Configure your secrets
Copy the example file and fill it in (see secrets.py below). Without it, the device boots to a friendly secrets.py not found! screen and waits.
cp secret.py.example secrets.py
3 — Flash it
Plug the Sprig in, then copy the whole tree to the device and reset.
mpremote connect auto fs cp -r . : mpremote reset
mpremote connect COM5.secrets.py
A single Python dict named secrets. Everything Shelby needs to reach the network and the APIs lives here. It’s git-ignored — your tokens never leave the device.
| Key | What it’s for |
|---|---|
| ssid | Your Wi‑Fi network name. Needed for the clock’s NTP sync and every API app. |
| password | Wi‑Fi password. |
| timezone | UTC offset in hours (e.g. 5.5 for IST). Drives the clock. |
| github_user | The username whose contribution graph you want. |
| github_token | A personal access token (read-only is plenty) for the GitHub API. |
| hackatime_key | Your Hackatime API key, for the coding-hours app. |
secrets = {
"ssid": "home-net",
"password": "••••••••",
"timezone": 5.5,
"github_user": "swamstick911",
"github_token": "ghp_••••",
"hackatime_key": "••••",
}
tasks.json
The Tasks app reads this file straight off the device. No account, no sync — edit the file, reflash, done. It’s a plain list of strings (or objects, if you want a done flag).
[
{ "text": "flash the firmware", "done": true },
{ "text": "write the docs", "done": false },
{ "text": "ship the website", "done": false }
]
Button map
Two D-pads, eight buttons. Shelby borrows the keys the Sprig editor already taught your fingers.
| Button | Does |
|---|---|
| L | From the clock, open the menu. |
| W / S | Move the selection up / down. |
| I | Select / open / tick a task. |
| J | Back — to the menu, or from the menu to the clock. |
| A / D / K | Context actions inside apps (volume, paging). |
App reference
Clock
The home screen. Syncs over NTP on boot, applies your timezone offset, and redraws once a minute. A hint bar along the bottom previews what’s waiting (new GitHub activity, pending tasks).
GitHub
Pulls 18 weeks of contributions for github_user and draws the familiar heat-grid, plus a total and current streak. Needs Wi‑Fi and a valid github_token.
Hackatime
Shows today’s and this week’s coding time with a per-project breakdown, pulled from the Hackatime API using hackatime_key.
System
Live vitals: free RAM against the 264 KB ceiling, Wi‑Fi state and signal, current clock speed, and uptime.
Tasks
Renders tasks.json. Move with W/S, tick with I.
Music
Plays simple tones through the buzzer with a small visualizer and an adjustable volume.
Overclocking
Shelby runs the RP2040 at 250 MHz instead of the stock 133. The clock’s once-a-minute full redraw stutters at stock speed; the bump smooths it out and every app feels snappier. It’s well within the chip’s tolerance, but if you’d rather not, set the frequency back in main.py.
Troubleshooting
“secrets.py not found!”
The file didn’t make it to the device, or it’s named wrong. Reflash and confirm mpremote fs ls lists secrets.py at the root.
Clock shows the wrong time
Check timezone in secrets.py — it’s an hour offset, and it can be fractional (e.g. 5.5, -4). NTP only runs when Wi‑Fi connects.
GitHub / Hackatime screens are empty
Almost always Wi‑Fi or a stale token. The System app will tell you if Wi‑Fi is down. Regenerate the token if it’s old.
Out of memory
Apps lazy-load and unload to fit 264 KB. If you’ve added your own app, make sure it cleans up on exit so the next one has room.