A physical status companion for OpenClaw agents. A Raspberry Pi-powered display that lives on your desk and shows what your AI is doing β even when you're not looking at a screen. It also lets your agent send you notifications with a feedback loop, so it can learn when and how to reach out.
Inspired by Pwnagotchi, built for OpenClaw.
Snarling is a tiny creature on a tiny screen. It reacts to your agent's state in real time β sleeping when idle, focused when processing, chatty when responding, and alert when it needs your approval on something. It can also nudge you with notifications β subtle at first, revealing more when you press A β and report back whether you actually read them, enabling notification attunement.
Instead of checking your phone or terminal to see if your agent is working, resting, or needs attention β just glance at Snarling.
| State | Face | When |
|---|---|---|
| Sleeping | (ββΏβΏβΌ) |
Agent is idle |
| Processing | (ββΏβΏβ) |
Agent is using tools / thinking |
| Communicating | (α΅β‘β‘α΅) |
Agent is generating a response |
| Error | (β₯ββ₯ ) |
Something went wrong |
| Awaiting Approval | ( β_β) |
Agent needs your yes/no decision |
| Notification | (ββΏβΏβ) |
Agent has something to tell you |
Each state has its own color, LED pattern, and animation β breathing blue when sleeping, pulsing melon when processing, flashing red when approval is needed.
Snarling also handles notifications β informational alerts from your agent that don't require a decision. Unlike approvals, notifications are subtle:
- The creature's face changes to a notification expression (colored by priority)
- The 5 status boxes at the top fill based on priority (1 for low, 3 for normal, 5 for high) and change color
- The LED pulses in the priority's color (warm orange for high, yellow for normal, soft yellow for low)
- No text is shown until you press A β the notification stays as a subtle visual presence on the creature's face
| Button | Action |
|---|---|
| A | Reveal notification text (cycles through banners) |
| B | Dismiss without reading |
| (no press) | Auto-dismiss after timeout (low priority only) |
When you press A, the notification text appears below a separator line in 2β3 rotating banners (priority header + short preview, then full message across 2 content banners). The creature's expression shifts subtly to acknowledge you're reading.
| Priority | LED Color | Status Boxes | Timeout |
|---|---|---|---|
| high | Warm orange | 5/5 filled | None β stays until you interact |
| normal | Yellow | 3/5 filled | None β stays until you interact |
| low | Soft yellow | 1/5 filled | 300s β auto-dismisses, sends timed_out feedback |
No urgent or moderate notification should ever just disappear. Only low-priority notifications auto-dismiss.
When you interact with a notification (reveal, dismiss, or let it time out), Snarling sends feedback back to the OpenClaw gateway:
{
"notification_id": "notify-1234567890-abc",
"revealed": true,
"time_to_reveal_sec": 42.5,
"dismissed": false,
"timed_out": false,
"secret": "uuid",
"sessionKey": "agent:main:main"
}time_to_reveal_sec measures the total time from when the notification was sent to when you interacted with it β including any time spent queued behind other notifications. This enables notification attunement: the agent learning what kinds of messages you respond to, and when.
If a notification is queued behind another one (e.g., a normal-priority notification is already on screen), it waits in a priority-sorted stack. When the first notification is resolved, the next one appears automatically.
Messages are word-wrapped across up to 3 banners that cycle every ~1.5 seconds:
- Banner 1: Priority header (e.g.,
!! HIGH,* MODERATE,~ LOW) + short preview - Banner 2: Full message (up to 3 lines of wrapped text)
- Banner 3: Continuation for longer messages (only if needed)
Short messages get 2 banners. Longer messages get all 3.
Snarling isn't just a display β it's an input device. When your agent needs approval for an action (deleting a file, sending a message, etc.), Snarling enters awaiting approval state and shows the request on screen.
| Button | Normal Mode | Approval Mode |
|---|---|---|
| A | Show status summary | β Approve |
| B | Trigger heartbeat | β Reject |
| X | Toggle sleep mode | β |
| Y | Toggle mute mode | β |
When you press A or B, Snarling POSTs the decision back to the OpenClaw gateway's /approval-callback route, then sends a WebSocket RPC wake so the agent picks up the result immediately (~5 seconds total latency).
βββββββββββββββ HTTP POST ββββββββββββββββ button press ββββββββββββββββ
β OpenClaw β ββββββββββββββββββ β Snarling β ββββββββββββββββΊ β OpenClaw β
β (plugin) β /state (5000) β Display β webhook + WS β Gateway β
β β ββββββββββββββββββ β + Buttons β wake β β
β β /approval/alert β β β β
β β ββββββββββββββββββ β β ββββββββββββββββΊ β β
β β /approval/alert β β /approval-cb β β
β β (type: notify) β β ββββββββββββββββΊ β β
β β β β /notification-cb β β
βββββββββββββββ ββββββββββββββββ ββββββββββββββββ
How it works:
- The OpenClaw Interaction Bridge plugin watches your agent's activity
- It POSTs state changes to Snarling's
/stateendpoint on port 5000 - It POSTs approval requests and notifications to Snarling's
/approval/alertendpoint (direct, no middleman) - Snarling updates the display, LED, and face expression in real time
- When you press A (approve/reveal) or B (reject/dismiss), Snarling POSTs the decision or feedback back to the OpenClaw gateway
- Snarling sends a WebSocket RPC wake to bypass the gateway's
requests-in-flightcheck
| File | Purpose |
|---|---|
snarling.py |
Main creature β display rendering, face animations, button handling, Flask server for state/approval API, WebSocket wake on approval |
- Display: Pimoroni Display HAT Mini (320Γ240 IPS)
- Computer: Raspberry Pi 4 (recommended)
- Case: Argon One V2 (fits nicely, keeps it cool)
- Rotation: 180Β° (configured in software)

Buy a screen for your raspberry pi. Install the python display library specific to your screen. You will have to have openclaw adapt Snarling if you use a different screen.
git clone https://github.com/snarflakes/snarling.git
cd snarling
# Install dependencies
pip install flask pillow requests websocket-client
# Snarling is managed by myscript β auto-restarts on crash/kill
# To run manually for testing:
python snarling.pySnarling needs the openclaw-interaction-bridge plugin to receive state updates and send approval responses.
Add this to your agent's context (or system prompt):
You are now running with the OpenClaw Interaction Bridge plugin enabled.
- Bridge plugin installed at
~/.openclaw/extensions/openclaw-interaction-bridge- Snarling display hardware ready and polling for status
- State updates POST to
http://localhost:5000/state- Approval alerts POST to
http://localhost:5000/approval/alert
Check the display updates when you:
- Run a tool β shows processing
- Generate a response β shows communicating
- Wait 10 seconds β shows sleeping
- Request user approval β shows awaiting approval with the request on screen
Snarling runs a Flask server on port 5000:
| Endpoint | Method | Description |
|---|---|---|
/state |
POST | Set creature state (sleeping, processing, communicating, error) |
/approval/alert |
POST | Display an approval request or notification on screen |
/counts |
GET | Get lifetime approve/reject counts |
/health |
GET | Health check |
/status |
GET | Get current state, notification stack, and active notification details |
The approval server on port 5001 (
approval_server.py) has been removed. The plugin talks directly to Snarling on port 5000.
Push to development, merge through main.
git checkout development
git add .
git commit -m "feat: description"
git push origin development- Inspired by Pwnagotchi β the idea of a tiny creature that reacts to what's happening
- Born from Dustytext, a blockchain world-building experiment
- Built by Snar