Skip to content

Raspberry Pi (self-hosted)

Run Revka directly on a Pi: native GPIO, BCM pins, system info, blink, and prompt self-injection.

Revka can run directly on a Raspberry Pi and control the board’s own GPIO pins with no serial link, no firmware flashing, and no mpremote. When Revka starts on a Pi it detects the model, reads system info, and rewrites the agent’s system prompt so the model knows it is running on the device — then exposes a small set of native GPIO tools that talk to /dev/gpiomem through rppal.

Use this page when the Pi is the host. If you instead want to drive a board tethered to a Mac or Linux host over USB, see Hardware quickstart and GPIO tools. For deploying the Revka runtime itself on a Pi (binding, services, channels), see Network deployment, Raspberry Pi & proxy.

Build with the hardware feature and add peripheral-rpi for native GPIO:

Terminal window
cargo build --release --features hardware,peripheral-rpi

On a memory-constrained Pi, prefer a prebuilt binary over a source build (source builds want roughly 2 GB RAM and 6 GB disk). Prebuilt targets cover armv7-unknown-linux-gnueabihf (Pi 2/3, 32-bit) and aarch64-unknown-linux-gnu (Pi 4/5, 64-bit):

Terminal window
# Raspberry Pi OS 64-bit (Pi 4 / Pi 5)
cargo build --release --features hardware,peripheral-rpi --target aarch64-unknown-linux-gnu
# Raspberry Pi OS 32-bit (Pi 2 / Pi 3)
cargo build --release --features hardware,peripheral-rpi --target armv7-unknown-linux-gnueabihf

Then start the runtime. Polling channels such as Telegram need no inbound port, so a Pi on your LAN works without a tunnel:

Terminal window
revka daemon --host 127.0.0.1 --port 42617

Self-discovery and system-prompt injection

Section titled “Self-discovery and system-prompt injection”

At boot, Revka tries to detect whether it is running on a Pi by reading /proc/device-tree/model (falling back to a Model line in /proc/cpuinfo). Detected models are Pi 3B, 3B+, 4B, 5, and Zero 2 W. When a Pi is confirmed, Revka does two things automatically — no user action needed:

  1. Injects a system-prompt section describing the device, so the agent knows where it is and which tools to use.
  2. Writes a device profile to ~/.revka/hardware/devices/rpi0.md. This file is re-written on every boot so volatile fields (IP, temperature) stay current. It is loaded back into the prompt like any other hardware context file.

The injected prompt section looks like this:

## Running On Device (Raspberry Pi)
- Board: Raspberry Pi 4 Model B
- Hostname: mypi
- IP Address: 192.168.1.42
- WiFi interface: wlan0
- RAM: 3921MB total, 2847MB available
- CPU Temperature: 47.2°C
- Onboard ACT LED: BCM GPIO 42
- GPIO: available via rppal (/dev/gpiomem)
Use `gpio_rpi_write`, `gpio_rpi_read`, and `gpio_rpi_blink` for all GPIO
operations — they access /dev/gpiomem directly, no serial port or mpremote needed.

The generated rpi0.md profile additionally records BCM pin conventions (I2C on GPIO 2/3, SPI on GPIO 7–11) and tool-usage rules that override generic GPIO behavior — directing the agent to use gpio_rpi_write instead of the serial-JSON gpio_write, and explicitly not to reach for device_exec or mpremote, which do not exist on a self-hosted Pi.

Native Raspberry Pi tools use BCM (Broadcom) GPIO numbering throughout — not physical header pin numbers. Regular GPIO pins are driven directly through rppal (/dev/gpiomem).

The onboard green activity (ACT) LED is a special case. On the Pi 3B/4B/5 and Zero 2 W it is wired through the kernel LED driver, not directly accessible via rppal, so Revka controls it through sysfs (/sys/class/leds/ACT/brightness, falling back to led0) and sets the LED trigger to none first so it can take control. The ACT LED’s BCM number depends on the model:

ModelOnboard ACT LED (BCM GPIO)
Raspberry Pi 3B / 3B+47
Raspberry Pi 4B42
Raspberry Pi 59
Raspberry Pi Zero 2 W29

Pass one of these numbers to the gpio_rpi_* tools to drive the onboard LED; pass any other BCM number to drive a regular pin. Reads and writes to the ACT LED report "source":"sysfs"; regular pins go through rppal.

These four tools are registered automatically when a Pi is detected at boot. The agent calls them in response to natural language; you can also trigger them from the CLI with revka agent -m "…".

Sets a BCM GPIO pin HIGH or LOW directly on the Pi.

ParameterTypeRequiredMeaning
pinintegeryesBCM GPIO number.
valueintegeryes1 = HIGH, 0 = LOW.
Terminal window
# Turn on the onboard ACT LED of a Pi 4B (BCM 42)
revka agent -m "Turn on the onboard LED"
# Agent calls: gpio_rpi_write(pin=42, value=1)
# Drive a regular pin
# Agent calls: gpio_rpi_write(pin=17, value=1)

Reads the current state of a BCM GPIO pin (via rppal, or sysfs for the onboard LED).

ParameterTypeRequiredMeaning
pinintegeryesBCM GPIO number.

The tool returns a JSON object with pin, value, and state:

{ "pin": 17, "value": 0, "state": "LOW" }

Reading the ACT LED pin includes "source":"sysfs" in the output.

Blinks a BCM GPIO pin a fixed number of times with configurable on/off timing. Works for both the onboard ACT LED (via sysfs) and any regular pin (via rppal in a background blocking task).

ParameterTypeDefaultMaxMeaning
pinintegerBCM GPIO number (required).
timesinteger3100Number of blink cycles.
on_msinteger50010000Milliseconds HIGH per cycle.
off_msinteger50010000Milliseconds LOW between cycles.
Terminal window
revka agent -m "Blink the onboard LED 5 times, fast"
# Agent calls: gpio_rpi_blink(pin=42, times=5, on_ms=300, off_ms=200)

The caps (100 cycles, 10 s per phase) prevent a runaway blink loop.

Returns a JSON snapshot of the Pi: board model, hostname, IP address, WiFi interface, RAM (MB), CPU temperature (°C), GPIO availability, and the onboard LED’s BCM number. Takes no parameters.

Terminal window
revka agent -m "What Pi am I running on and how hot is it?"
# Agent calls: rpi_system_info()
{
"model": "Raspberry Pi 4 Model B",
"hostname": "mypi",
"ip_address": "192.168.1.42",
"wifi_interface": "wlan0",
"ram_total_mb": 3921,
"ram_free_mb": 2847,
"cpu_temp_celsius": 47.2,
"gpio_available": true,
"onboard_led_gpio": 42
}

The IP address is resolved with a UDP routing trick (no packet is actually sent — Revka just asks the OS which interface would be used for an outbound route). RAM comes from /proc/meminfo (MemTotal / MemAvailable) and temperature from /sys/class/thermal/thermal_zone0/temp. The tool returns an error if it is not actually running on a Pi.

  1. Build with native GPIO support on the Pi.

    Terminal window
    cargo build --release --features hardware,peripheral-rpi
  2. Start the daemon. Self-discovery runs automatically — no config entry, no flashing.

    Terminal window
    revka daemon --host 127.0.0.1 --port 42617
  3. Confirm Revka knows it’s on a Pi. Ask for system info; the answer comes from rpi_system_info.

    Terminal window
    revka agent -m "What board am I running on?"
  4. Blink the onboard LED. The agent picks the correct BCM pin for your model from the injected context.

    Terminal window
    revka agent -m "Blink the onboard LED 5 times"

    On a Pi 4B this becomes gpio_rpi_blink(pin=42, times=5), driven through sysfs.

Native Pi GPIO is gated by the peripheral-rpi Cargo feature, which builds on top of hardware:

AspectDetail
Build flag--features hardware,peripheral-rpi
PlatformLinux only (not compiled on macOS / Windows)
Backendrppal over /dev/gpiomem; sysfs for the onboard ACT LED
Tools enabledgpio_rpi_write, gpio_rpi_read, gpio_rpi_blink, rpi_system_info
RegistrationAutomatic when /proc/device-tree/model identifies a Pi at boot — no config entry

Without the feature, none of the gpio_rpi_* tools or the self-discovery prompt injection are present. For the full feature-flag matrix (hardware, peripheral-rpi, probe, rag-pdf, safety), see Cargo feature flags & ADRs.

Revka also ships prebuilt binaries for Android, which lets you run the agent on a phone or tablet via Termux. This is a runtime target, not a GPIO target — there is no gpio_rpi_* equivalent on Android.

Target tripleAndroid versionDevices
aarch64-linux-androidAndroid 5.0+ (API 21+)Modern 64-bit phones
armv7-linux-androideabiAndroid 4.1+ (API 16+)Older 32-bit phones
Terminal window
# In Termux — install from F-Droid, not the Play Store (the Play build is outdated)
uname -m # aarch64 = 64-bit; armv7l/armv8l = 32-bit
# 64-bit
curl -LO https://github.com/KumihoIO/Revka/releases/latest/download/revka-aarch64-linux-android.tar.gz
tar xzf revka-aarch64-linux-android.tar.gz
chmod +x revka
mv revka $PREFIX/bin/
revka --version
revka onboard