Overview
The relay server routes audio and notifications from remote/container environments back to your local machine. When you code over SSH or inside a devcontainer, the relay ensures you hear sounds and see notifications on your laptop. How It Works:- Start relay on your local machine:
peon relay --daemon - SSH with port forwarding:
ssh -R 19998:localhost:19998 remote-host - PeonPing on the remote auto-detects SSH and sends requests to
localhost:19998 - Relay plays sounds locally
relay (foreground)
Start the relay server in the foreground.- Blocks the terminal (foreground process)
- Logs requests to stdout
- Stop with
Ctrl+C
- Port:
19998 - Bind address:
127.0.0.1(localhost only) - Peon dir:
~/.claude/hooks/peon-ping(orCLAUDE_PEON_DIR)
relay —daemon
Start the relay server in the background.- Forks to background
- Writes PID to
.relay.pid - Logs to
.relay.log - Persists across terminal sessions
- Only one daemon can run at a time (second invocation detects existing PID)
relay —stop
Stop the background relay.- Sends
SIGTERMto relay process - Removes
.relay.pidfile - Cleans up stale PID files if process no longer exists
relay —status
Check if the relay is running.0if running1if not running
relay —port
Use a custom port.relay —bind
Bind to a specific address.0.0.0.0listens on ALL network interfaces- Anyone on your network can send requests
- Only use on trusted networks
- Default
127.0.0.1is safer (localhost only)
relay —peon-dir
Use a custom peon-ping directory.- Relay reads
config.jsonand loads packs from this directory - Useful for testing or multi-user setups
- Falls back to
CLAUDE_PEON_DIRenvironment variable
relay —help
Show help message.Relay Endpoints
The relay exposes an HTTP API for remote clients.GET /health
Health check.- Verify relay is running before starting SSH session
- Monitoring scripts
GET /play?category={category}
Play a random sound from a CESP category.- Relay reads
config.jsonto get active pack and volume - Loads pack’s
openpeon.jsonmanifest - Picks a random sound from category (avoids last-played sound)
- Plays on local machine
session.starttask.acknowledgetask.completetask.errorinput.requiredresource.limituser.spam
GET /play?file={path}
Play a specific sound file (legacy).- Path is relative to peon-ping directory
- Subject to path traversal protection (must be within
packs/) - Volume controlled by
X-Volumeheader (default: 0.5)
POST /notify
Send a desktop notification.| Field | Type | Description |
|---|---|---|
title | string | Notification title (max 256 chars) |
message | string | Notification body (max 512 chars) |
color | string | red, yellow, or blue (affects urgency) |
SSH Setup
1. Start Relay Locally
2. SSH with Port Forwarding
-R 19998:localhost:19998forwards remote port19998to local19998- PeonPing on
remote-hostsends requests tolocalhost:19998 - SSH tunnel routes them back to your laptop
3. Verify on Remote
4. Test Sound
Devcontainer / Codespaces Setup
No SSH forwarding needed — PeonPing auto-detects container environments.1. Start Relay on Host
2. Open Devcontainer
PeonPing inside the container auto-detectsREMOTE_CONTAINERS or CODESPACES env vars and routes requests to host.docker.internal:19998.
3. Test
Remote Hook (Lightweight)
If peon-ping isn’t installed on the remote, use a minimal hook that sends category names to the relay:scripts/remote-hook.sh:
~/.claude/settings.json on remote:
- No peon-ping install on remote
- Relay handles pack selection, volume, and no-repeat logic
- Hook only needs to send category name
Examples
Start Relay and SSH to Server
Custom Port for Multiple Remotes
Persistent Relay on Startup
Add to~/.bashrc or ~/.zshrc:
Check Relay Logs
Troubleshooting
Relay Not Running
Port Already in Use
Remote Can’t Reach Relay
Sounds Play on Remote Instead of Local
PeonPing falls back to remote playback if relay is unreachable:Related Commands
peon status— Shows if you’re in SSH/devcontainer (relay auto-detection)peon preview <category>— Test sounds through relaypeon volume— Adjust volume on local machine (relay respects this)