feat: manage Handy preferences and startup declaratively

This commit is contained in:
kiri committed 2026-09-09 20:39:08 +02:00
1 parent 345ef7c56c
commit 0992f3b863
6 files changed
+74 -46

No files matched your search

+23 -34
View File
@@ -119,40 +119,29 @@ reports are not a fresh comparison with this baseline.
## Open choices and next discussion ## Open choices and next discussion
Dictation: plain local transcription is selected; rambling cleanup is deferred. Dictation: plain local transcription is selected; rambling cleanup is deferred.
The shared Niri module installs Handy and starts it hidden with the desktop. Handy preferences are Nix-owned in `modules/capabilities/handy.nix`: Nemotron
Super+D toggles recording; Super+Shift+D cancels. Commands were verified against Streaming 3.5, automatic language detection, default microphone, Live overlay at
the pinned Handy 0.9.1 source. No microphone recording or model download was run. the bottom, Ctrl+Shift+V paste through wtype, preserved clipboard, manual submission
After user activation, launch Handy from Walker, download/select Parakeet V3, and no cloud processing. Other preferences use pinned app defaults. A user service
keep automatic language detection and disable push-to-talk for toggle operation. copies the baseline into Handy's writable store on each start, allowing migrations
In Advanced, choose paste method None and clipboard handling Copy to Clipboard. while resetting GUI edits. Models/recordings stay outside Nix; the selected model
Keep post-processing disabled. Settings/models remain writable app-owned state. is already downloaded on Zenith. Other hosts still need model provisioning.
Start Handy manually for the current session; desktop autostart applies on login. Super+Shift+D toggles; Super+Ctrl+D cancels. Super+D push-to-talk awaits the user's
Try an English and a Dutch recording, paste into Codex with Ctrl+Shift+V, then decision about a keyboard listener: Niri 26.04 has no key-release bindings.
submit manually. User feedback needed: recognition accuracy, delay and shortcut Noctalia suppresses microphone activity popups/indicators; camera and screen-sharing
delivery. Automatic paste can follow if wanted after checking Niri compatibility. indications remain. Automatic paste and live capture need interactive checks.
Verification: formatting, flake evaluation, Zenith and Polaris no-link system
builds, and whitespace checks passed. No system activation or interactive Hang investigation: stopping live Vulkan transcription never completed; cancel
dictation was performed; recognition quality and latency remain unmeasured. returned the UI to idle but subsequent requests reported pipeline busy. Handy was
First-use diagnosis: Handy was set to Nemotron, Direct Input, Don't Modify no longer running when inspected; no crash cause is established. The same saved
Clipboard and push-to-talk. One recording transcribed but output used X11 input 1.56-second recording completed in CPU batch mode (135 ms inference, 729 ms load)
simulation; other recordings returned zero usable samples. Default digital mic and Vulkan batch mode (156 ms inference, 420 ms load). This checks model inference,
is unmuted. Set None + Copy to Clipboard and retry a full sentence; microphone not live capture/stop/cancel. No new audio was recorded. Switching to CPU is not a
selection/voice detection needs further checking if History stays empty. confirmed fix. After activation, retry live recording and stopping, and inspect
Niri Super+D invokes a forced toggle, independent of Handy's push-to-talk setting; the service logs if it hangs.
Handy's Ctrl+Space global binding is not the Niri binding. Keep the user's minimal Verification: formatting, flake evaluation, both workstation builds and whitespace
overlay. Noctalia's native microphone filter suppresses all microphone activity checks passed. Handy loaded the generated settings in an isolated data directory
popups/indicators, while camera and screen-sharing indications remain enabled. without settings parse errors. System activation remains user-owned and pending.
The Noctalia change passed formatting, flake evaluation and both workstation
builds; user activation and the clipboard retry remain pending.
Automatic paste: Niri now includes wtype, which Handy natively uses to deliver
Wayland paste shortcuts. Set Paste Method to Ctrl+Shift+V for Kitty, keep automatic
submission off, and restart Handy after activation. Interactive delivery remains
unverified. Handy 0.9.1 supports Overlay Style Live with streaming models; the
selected Nemotron Streaming 3.5 is a suitable candidate. Minimal hides live text.
This supersedes the initial Parakeet V3/clipboard-only recommendation when live
feedback and automatic paste are wanted; no custom input script is needed.
The wtype addition passed formatting, flake evaluation, both workstation builds
and whitespace checking. Activation and the interactive paste trial are pending.
The focus is the broader environment, not further API/database polish. Candidate The focus is the broader environment, not further API/database polish. Candidate
areas remain places/ownership, navigation/interaction, human/agent collaboration, areas remain places/ownership, navigation/interaction, human/agent collaboration,
+2 -2
View File
@@ -29,8 +29,8 @@ use a flake to declare its tools without Nix owning the surrounding workspace.
interaction with useful connections to the rest of the environment. interaction with useful connections to the rest of the environment.
- Use Handy for local plain dictation, mainly English with occasional Dutch. - Use Handy for local plain dictation, mainly English with occasional Dutch.
Use native Wayland automatic paste and optional live text with a streaming model. Use native Wayland automatic paste and optional live text with a streaming model.
Niri owns recording shortcuts; Nix owns Handy preferences and desktop integration; the user service restores
model downloads and microphone preferences remain application-owned. Cleanup settings on each start. Model downloads and recordings remain application data. Cleanup
through Codex, a cloud API or a local language model is deferred. through Codex, a cloud API or a local language model is deferred.
- Outlook is acceptable as an application, but its interaction and integration - Outlook is acceptable as an application, but its interaction and integration
do not fit as naturally. Accessible mail for tools and agents matters separately do not fit as naturally. Accessible mail for tools and agents matters separately
+46
View File
@@ -0,0 +1,46 @@
{
flake.modules.homeManager.handy =
{ config, pkgs, ... }:
let
settings = (pkgs.formats.json { }).generate "handy-settings.json" {
settings = {
settings_schema_version = 1;
selected_model = "handy-computer/nemotron-3.5-asr-streaming-0.6b-gguf/nemotron-3.5-asr-streaming-0.6b-Q8_0.gguf";
selected_language = "auto";
translate_to_english = false;
selected_microphone = null;
always_on_microphone = false;
push_to_talk = true;
paste_method = "ctrl_shift_v";
typing_tool = "wtype";
clipboard_handling = "dont_modify";
auto_submit = false;
overlay_style = "live";
overlay_position = "bottom";
post_process_enabled = false;
start_hidden = true;
autostart_enabled = false;
update_checks_enabled = false;
show_whats_new_on_update = false;
onboarding_completed = true;
};
};
in
{
home.packages = [ pkgs.handy ];
systemd.user.services.handy = {
Unit = {
Description = "Handy dictation";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Install.WantedBy = [ "graphical-session.target" ];
Service = {
# Handy writes migrations and runtime preferences: restore the Nix baseline on start.
ExecStartPre = "${pkgs.coreutils}/bin/install -Dm600 ${settings} ${config.xdg.dataHome}/com.pais.handy/settings_store.json";
ExecStart = "${pkgs.handy}/bin/handy --start-hidden";
};
};
};
}
+2 -2
View File
@@ -36,7 +36,7 @@ in
}; };
# Dictation # Dictation
"Mod+D" = { "Mod+Shift+D" = {
spawn = [ spawn = [
handy handy
"--toggle-transcription" "--toggle-transcription"
@@ -44,7 +44,7 @@ in
_props.repeat = false; _props.repeat = false;
_props.hotkey-overlay-title = "Toggle Dictation"; _props.hotkey-overlay-title = "Toggle Dictation";
}; };
"Mod+Shift+D" = { "Mod+Ctrl+D" = {
spawn = [ spawn = [
handy handy
"--cancel" "--cancel"
-8
View File
@@ -41,19 +41,11 @@ in
playerctl playerctl
brightnessctl brightnessctl
wireplumber wireplumber
handy
wtype wtype
] ]
++ [ swapMonitorWorkspaces ]; ++ [ swapMonitorWorkspaces ];
}; };
desktop.autostart = [
[
(lib.getExe pkgs.handy)
"--start-hidden"
]
];
dconf.settings."org/gnome/desktop/interface".color-scheme = "prefer-dark"; dconf.settings."org/gnome/desktop/interface".color-scheme = "prefer-dark";
wayland.windowManager.niri = { wayland.windowManager.niri = {
+1
View File
@@ -43,6 +43,7 @@ in
imports = [ imports = [
homeModules.passwords homeModules.passwords
homeModules.clipboard homeModules.clipboard
homeModules.handy
homeModules.desktop-commands homeModules.desktop-commands
homeModules.dev-tools homeModules.dev-tools
homeModules.xdg homeModules.xdg