Pixie Agent Visualizer
Live AI-agent activity on a Firefly Pixie hardware wallet. While opencode runs on your laptop, the Pixie shows what the agent is doing right now — current tool call, status, errors — over a custom background.
An opencode agent (DeepSeek, Claude, GPT, etc) drives the work. A TypeScript
plugin subscribes to its lifecycle events and ships them through a Unix socket
to a Python BLE bridge, which encodes them as CBOR-RPC over the Firefly Serial
Protocol and writes them to a custom Hollows app on the Pixie. The device
renders a multi-state UI on its 240×240 display:
┌──────────────────────────────┐ ← header bar
│ Code Force 1 BLE ● │ color encodes state
├──────────────────────────────┤
│ │
│ $ bash │ ← state-specific content
│ ls -la /tmp │
│ running... │
│ │
├──────────────────────────────┤ ← footer hints
│ Tool in flight │
└──────────────────────────────┘
Header color encodes the mode at a glance: gray for idle, dark blue for thinking, dark cyan for a tool running, red for an error or a required permission.
Hardware approval
The killer feature: opencode pauses on dangerous tools (bash, write, edit)
and the Pixie shows a full-screen APPROVE? panel with the command preview. The
four physical buttons are paired — either left button rejects, either right
button approves. Run a prompt that needs bash and the agent literally pauses
until you press the hardware.
Architecture
opencode (any model)
└─ pixie-agent-visualizer plugin (TS, @opencode-ai/plugin)
└─ Unix socket /tmp/pixie-agent.sock (newline-JSON)
└─ pixie-agent-bridge (Python · bleak · cbor2)
└─ FSP CBOR-RPC over BLE GATT 0xabf0/0xabf1
└─ Firefly Pixie (custom Hollows panel)
The split keeps BLE off Node (fragile on macOS) and lets the plugin crash and reload with an opencode session without dropping the BLE link. The bridge can later take events from other sources — Claude Agent SDK, MCP — without rewriting firmware.
It’s an open-source hardware project: ESP32-C3 firmware, the opencode plugin, and the Python bridge. Full build instructions are in the repo.