README: Rudder, the first plugin that ships as a real desktop app (Linux screenshot)

- documentation/readme-images/deploy5-desktop-rudder.png: the Rudder desktop app running on Linux,
  window content only — the window title bar is cropped (it shows the desktop's theme) and the file is
  rewritten as pixels only: no text, time, software, EXIF, density or colour-profile chunks. Taken with
  RUDDER_PRIVATE_LABELS=1 and a fresh profile, so no device names, volumes or saved drafts show.
- README Output 3: the Rudder desktop app, the screenshot and the two build commands; macOS/Windows
  marked built-but-never-run and the first-run model download as not built yet.
- engine: RUDDER_PRIVATE_LABELS=1 now also hides volume levels and switched-off sound cards (a card's
  name identifies the machine's audio chipset).
This commit is contained in:
Doxa Maps 2026-09-28 04:55:52 +00:00
parent c0a1c7f6dd
commit 209ffff1e3
3 changed files with 23 additions and 2 deletions

View file

@ -475,6 +475,20 @@ bun run phone # builds the app and installs it on a phone or emulator
![Desktop app (Tauri) — proven, not yet in production](documentation/readme-images/deploy5-desktop.png)
**And the first plugin that ships as a real desktop app: Rudder**, private voice-to-text, built from the
same `plugin-designs/rudder-voice/` folder that runs in the Plugin Studio. On Linux it installs as a `.deb`,
starts its own local speech engine, and transcribes offline — no account, no cloud, no telemetry.
![Rudder desktop app on Linux — streaming voice-to-text, offline](documentation/readme-images/deploy5-desktop-rudder.png)
```bash
# Linux — the full path is in documentation/HOWTO-build-the-desktop-app.md
bash backend/rudder-engine/setup-runtime.sh # once: the speech runtime + model, verified by SHA-256
./node_modules/.bin/tauri build --config deployment/src-tauri/rudder.conf.json # → Rudder_0.1.0_amd64.deb
```
<sub>macOS and Windows: built but never run. The 742 MB model is not yet downloaded by the app on first run.</sub>
<details>
<summary><b>More about the desktop app</b></summary>

View file

@ -117,8 +117,9 @@ func listDevices() DeviceList {
if bus, ok := s.Properties["device.bus"].(string); ok {
d.Bus = bus
}
// RUDDER_PRIVATE_LABELS=1: show microphones by KIND, not by name. Device names are often personal
// ("Anna's AirPods") — use this for screenshots, screen-sharing and demos.
// RUDDER_PRIVATE_LABELS=1: show microphones by KIND, not by name, and hide volume levels and
// switched-off sound cards. Device and card names are personal or identify the hardware ("Anna's
// AirPods", a laptop's audio chipset) — use this for screenshots, screen-sharing and demos.
if os.Getenv("RUDDER_PRIVATE_LABELS") == "1" {
d.Label = map[string]string{"bluetooth": "Bluetooth headset", "usb": "USB microphone", "pci": "Built-in microphone"}[d.Bus]
if d.Label == "" {
@ -133,8 +134,14 @@ func listDevices() DeviceList {
}
}
}
if os.Getenv("RUDDER_PRIVATE_LABELS") == "1" {
d.Volume = "" // a volume level is a detail of this machine's settings
}
out.Devices = append(out.Devices, d)
}
if os.Getenv("RUDDER_PRIVATE_LABELS") == "1" {
return out // no card names in private mode
}
// Cards whose active profile is "off" but which offer an input profile.
if b, err := runPactl("-f", "json", "list", "cards"); err == nil {
var cards []struct {

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB