{ config, lib, pkgs, ... }: let cfg = config.services.hyprvoice; hyprvoice = pkgs.buildGoModule rec { pname = "hyprvoice"; version = "1.0.2"; src = pkgs.fetchFromGitHub { owner = "LeonardoTrapani"; repo = "hyprvoice"; rev = "v${version}"; hash = "sha256-ng17y53L9cyxSjupSGKyZkBXOGneJrjprjvODYch6EE="; }; vendorHash = "sha256-b1IsFlhj+xTQT/4PzL97YjVjjS7TQtcIsbeK3dLOxR4="; subPackages = [ "cmd/hyprvoice" ]; # Runtime deps need to be available for whisper-cpp transcription, # audio capture, text injection, and notifications. nativeBuildInputs = [ pkgs.makeWrapper ]; postInstall = '' wrapProgram $out/bin/hyprvoice \ --prefix PATH : ${lib.makeBinPath runtimeDeps} ''; meta = { description = "Voice-powered typing for Wayland desktops"; homepage = "https://github.com/LeonardoTrapani/hyprvoice"; license = lib.licenses.mit; mainProgram = "hyprvoice"; }; }; runtimeDeps = with pkgs; [ whisper-cpp pipewire wl-clipboard wtype libnotify ] ++ lib.optionals cfg.ydotool [ pkgs.ydotool ]; in { options.services.hyprvoice = { enable = lib.mkEnableOption "hyprvoice voice-to-text dictation"; model = lib.mkOption { type = lib.types.str; default = "small.en"; description = "Whisper model to use (e.g., tiny.en, base.en, small.en, medium.en, large-v3-turbo)"; }; ydotool = lib.mkOption { type = lib.types.bool; default = false; description = "Include ydotool as an alternative text injection backend (recommended for Chromium apps)"; }; user = lib.mkOption { type = lib.types.str; description = "User to run the hyprvoice service as"; }; }; config = lib.mkIf cfg.enable { environment.systemPackages = [ hyprvoice ]; systemd.user.services.hyprvoice = { description = "Hyprvoice voice-to-text daemon"; after = [ "pipewire.service" "graphical-session.target" ]; wants = [ "pipewire.service" ]; wantedBy = [ "graphical-session.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${hyprvoice}/bin/hyprvoice serve"; Restart = "on-failure"; RestartSec = 5; }; }; }; }