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.

A simplified version of the clock sync my LED rings run. No leader; each node just averages with whoever it can hear. largest group spread 0 ms

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
Three LED rings lit in the dark
What I built
Fleet simulators · same engine code as the firmware
Signed over-the-air updates · rollback
Gossip clock sync + pattern engine
Zephyr firmware · OpenThread
Carrier PCB · KiCad
Printed enclosure · code-CAD

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
Termwall overlay showing six agent sessions
What I built
Phone client · PWA, web push
Hotkey overlay · Qt
Session discovery · tmux + transcripts
Guard hooks and scoped MCP tools
Claude Code, Codex · the agents themselves

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
What I built
Messaging by node name
Discovery and collision rules
AES-128 + HMAC link encryption
ACK, retry and backoff link layer
Radio channel simulator
SX1262 radio · vendor stack

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
What I built
Agent roles and workflow gates
3D review viewer · three.js
Experiment ledger and outcome log
Code-CAD, slice and print pipeline
Printer, slicer, agent runtime · off the shelf

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
The check-in kiosk with the lights off
What I built
Fleet provisioning and monitoring
Live web dashboard
Peer gateways · Raspberry Pi, Thread border router
Scanner firmware · Zephyr, sleepy end device
Kiosk enclosure · CAD as code
nRF52840 and Pi modules · off the shelf

Smaller things

Van power dashboard: battery, solar, shore, heater tiles and an 8 hour chart

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.