Software engineer · Berkeley, CA
Firmware, radios and production AI agents.
I build things that have to keep working when nobody is watching them. Everything here is side projects. Work history is in the resume.
Work
Each one lists which layers I built, hardware at the bottom.
Embedded · wireless · hardware
LED rings that stay in sync with no leader
39 battery-powered wearable rings. When a few are near each other their patterns line up, with no master clock and no leader election. Each ring gossips its clock in a small beacon and steers toward its neighbours.
- Fleet
- 39 nodes
- Sync, by camera
- 3.6 ms median offset
- Releases
- 41 signed OTA
- MCU
- nRF52840

AI agents · developer tools
Termwall and agent guard rails
I run a lot of coding agents at once on a few machines. Termwall is one hotkey that shows all of them and which ones are waiting on me. Around it are small tools that limit what an agent can do and fail closed.
- Remote install
- none agent sent over ssh
- Clients
- 2 desktop overlay, phone
- Tests
- 89

Embedded · protocol design · open source
LoRaPeerLink
A C++ library for direct device-to-device LoRa links, no LoRaWAN. Version 1 passed its tests and didn't work on real radios, so version 2 started with a simulator of the actual channel: airtime, collisions, loss.
- Delivered, 1 h soak
- 99.6% 1,204 of 1,209
- Test cases
- 185
- Signal during test
- −115 dBm
- Duplicates
- 0
AI agents · physical actions
Faber, an agent that runs my 3D printer
Ask for a part in chat. Faber designs it as code, shows it in a browser for review, and only prints after sign-off. A design review can't start a print, and a slicing guard rejects jobs set up for the wrong bed.
- Recorded prints
- 71 64 accepted
- Projects
- 18
- Commits
- 780
Embedded · mesh networking · fleet operations
RFID scanners on a Thread mesh
Handheld scanners report over a Thread mesh to Raspberry Pi gateways that act as equal peers, replay missed scans after a reconnect, and update and recover on their own. A countertop check-in kiosk grew out of the same work.
- Scanner battery
- ~9 days per charge
- Gateways in the field
- 4
- Kiosk tests in CI
- 114
Smaller things

Van power dashboard
A Raspberry Pi kiosk in my van. It decodes Victron's Bluetooth adverts passively (no pairing), reads the diesel heater, and duty-cycles the Starlink dish from battery state of charge through a relay, with hysteresis and a watchdog so the dish turns itself off if the dashboard dies. Self-updating, with an always-on mirror for when the van is offline. Source
A negative result in music modelling
Fine-tuned a masked audio-token model to bridge between two songs. The ablations showed it was ignoring the controls, and it lost to a simple baseline. Written up as such.
SDR bench
A local web app for a bladeRF: spectrum and waterfall, FM stereo with RDS, 2.4 GHz hop stitching, and a Mode S decoder tested so far only on synthetic frames.
KiCad field notes
Notes from scripting a board end to end: where the Python API crashes, how zones merge, and the placement-origin trap that shifts every part at assembly.