WHISRSD(1)

πŸ“¦ version 0.1.30, in nixpkgs unstable

πŸ’… WHISRSD β€” the whisrs dictation daemon, bestie edition

okay so you're looking at the whisrsd(1) page and honestly? this one's the main character. it's the background daemon for the whisrs dictation system, and by the end of this you're gonna know it like the back of your hand. periodt.


✨ SYNOPSIS ✨

whisrsd [OPTIONS]

that's it. that's the whole vibe. well β€” the invocation vibe, anyway. keep reading 🫢


🌸 DESCRIPTION 🌸

whisrsd is the background daemon for the whisrs dictation system. it's the one doing all the actual work behind the scenes: managing audio capture, transcription, window tracking, and text injection via a virtual keyboard. lowkey the backbone of the whole operation πŸ’…

the daemon listens on a Unix domain socket for commands from the whisrs(1) CLI client. it runs as a long-lived process β€” either standalone, or as a systemd user service. no cap, it just sits there being reliable.

On startup, the daemon:

  • Loads configuration from ~/.config/whisrs/config.toml
  • Checks /dev/uinput access for virtual keyboard
  • Resolves the [audio] device input and logs which device it will record from
  • Auto-detects the active window manager/compositor
  • Initializes the selected transcription backend
  • Binds the Unix domain socket and begins accepting commands

like a little checklist queen. she does all six every single time she wakes up πŸŽ€


πŸ’– OPTIONS πŸ’–

  • -h, --help β€” Print a short help message and exit. (short and sweet, we love a concise icon)
  • -V, --version β€” Print version information and exit. (so you know exactly which era of whisrs you're in ✨)

πŸ¦‹ STATE MACHINE πŸ¦‹

the daemon maintains one of five states. five! she contains multitudes:

  • idle β€” Waiting for a toggle command. No audio is being captured. just vibing, not recording, minding her business 😌
  • recording β€” Audio is being captured from the microphone. A second toggle or a cancel command transitions out of this state. (yes bestie, it's listening β€” say it with your chest 🎀)
  • transcribing β€” Audio has been sent to the transcription backend. The daemon is waiting for results. Text is typed at the cursor as it becomes available. (the way it types live as it goes?? iconic)
  • synthesizing β€” Read-aloud: generating speech from the selected text. πŸ—£οΈ
  • speaking β€” Read-aloud: playing synthesized speech; a second speak or a cancel stops it. (a second speak OR a cancel β€” both work, no gatekeeping)

πŸ”₯ TRANSCRIPTION BACKENDS πŸ”₯

pick your fighter:

  • groq β€” Groq Whisper API. Free tier available. Audio is chunked at silence boundaries and sent as HTTP POST requests. Timestamp-based deduplication prevents repeated text. (the dedup is doing the lord's work, fr fr)
  • openai-realtime β€” OpenAI Realtime API via WebSocket. Provides true streaming transcription with the lowest latency. Recommended for the best experience. πŸ‘‘ lowkey the crowned favorite
  • openai β€” OpenAI REST API. Simple HTTP POST, non-streaming fallback. (the "if all else fails" bestie, and we respect her)
  • asr-sidecar β€” Generic local HTTP ASR sidecar. Sends WAV audio as multipart form data and expects a JSON response with a text field.
  • local β€” Local transcription via whisper.cpp (requires the local feature flag at compile time). Fully offline. πŸ’€ no internet required, she's self-sufficient

🧚 SOCKET 🧚

the daemon creates a Unix domain socket at:

$XDG_RUNTIME_DIR/whisrs.sock

If XDG_RUNTIME_DIR is not set, it falls back to:

/tmp/whisrs-<uid>.sock

The protocol uses length-prefixed JSON messages (4-byte big-endian length header followed by a JSON body). so: length first, then the JSON body. in that order. always. don't get cute with it 😭

On startup, the daemon checks for and removes stale sockets from previous instances. If another daemon is already running, it exits with an error. (no duplicate daemons allowed β€” there can only be one main character πŸ’…)


🌈 SIGNALS 🌈

  • SIGINT β€” Graceful shutdown. The socket file is removed before exit. (she cleans up after herself, obviously ✨)
  • SIGTERM β€” Graceful shutdown (when run as a systemd service).

πŸ“ ENVIRONMENT πŸ“

  • RUST_LOG β€” Controls log verbosity. Examples: info, debug, whisrs=debug. Default is info.
  • WHISRS_GROQ_API_KEY β€” Groq API key. Overrides the config file value.
  • WHISRS_OPENAI_API_KEY β€” OpenAI API key. Overrides the config file value.
  • XDG_RUNTIME_DIR β€” Socket directory.
  • XDG_CONFIG_HOME β€” Configuration directory.
  • WAYLAND_DISPLAY β€” Used to detect Wayland session for clipboard operations.
  • HYPRLAND_INSTANCE_SIGNATURE β€” Used to detect Hyprland compositor for window tracking.
  • SWAYSOCK β€” Used to detect Sway compositor for window tracking.
  • XDG_SESSION_TYPE β€” Used to detect X11 session for window tracking.

env vars: the original influencers of the config world. set them, and they override. iykyk πŸ’œ


πŸŽ€ FILES πŸŽ€

  • ~/.config/whisrs/config.toml β€” Configuration file.
  • $XDG_RUNTIME_DIR/whisrs.sock β€” IPC socket.
  • ~/.cache/whisrs/recovery/ β€” Audio recovery files saved on transcription failure. (your safety net when the transcribe gods say no 😭)
  • $XDG_DATA_HOME/whisrs/recordings/ β€” Recordings and their transcripts, one folder per recording. Override with [recording] dir in config.toml.

⭐ EXAMPLES ⭐

Run the daemon in the foreground with debug logging:

RUST_LOG=debug whisrsd

Run the daemon in the background:

whisrsd &

Enable as a systemd user service:

systemctl --user enable --now whisrs.service

Enable as an OpenRC user service:

rc-update --user add whisrs default && rc-service --user whisrs start

(all four of these are literally copy-paste ready. go off 🫢)


πŸ¦‹ SEE ALSO πŸ¦‹

  • whisrs(1) β€” the CLI client bestie herself πŸ’–

πŸ‘‘ AUTHORS πŸ‘‘

whisrs contributors


πŸ’œ LICENSE πŸ’œ

MIT


gentle reminder before you go: this is whisrs version 0.1.30, dated 2026-10-20 β€” so if your build says something else, you're on a different era and that's valid too 🌸

okay bye bestie, go dictate something iconic βœ¨πŸŽ€πŸ’…

πŸ“¦ where this page comes from