This commit is contained in:
2026-08-04 15:43:12 +09:00
parent 1f1d46ea2a
commit a44a83a587
9 changed files with 270 additions and 30 deletions
Generated
+163 -30
View File
@@ -91,6 +91,32 @@
}
},
"bun2nix": {
"inputs": {
"flake-parts": "flake-parts_2",
"import-tree": "import-tree",
"nixpkgs": [
"handy",
"nixpkgs"
],
"systems": "systems_4",
"treefmt-nix": "treefmt-nix"
},
"locked": {
"lastModified": 1770895533,
"narHash": "sha256-v3QaK9ugy9bN9RXDnjw0i2OifKmz2NnKM82agtqm/UY=",
"owner": "nix-community",
"repo": "bun2nix",
"rev": "c843f477b15f51151f8c6bcc886954699440a6e1",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "2.0.8",
"repo": "bun2nix",
"type": "github"
}
},
"bun2nix_2": {
"inputs": {
"flake-parts": [
"llm-agents",
@@ -292,6 +318,24 @@
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib_2"
},
"locked": {
"lastModified": 1769996383,
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_3": {
"inputs": {
"nixpkgs-lib": [
"llm-agents",
@@ -312,7 +356,7 @@
"type": "github"
}
},
"flake-parts_3": {
"flake-parts_4": {
"inputs": {
"nixpkgs-lib": [
"nixvim",
@@ -333,7 +377,7 @@
"type": "github"
}
},
"flake-parts_4": {
"flake-parts_5": {
"inputs": {
"nixpkgs-lib": [
"stylix",
@@ -470,6 +514,27 @@
"type": "gitlab"
}
},
"handy": {
"inputs": {
"bun2nix": "bun2nix",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1785763469,
"narHash": "sha256-YHfOchlPBKbBbeoaT1amrjKBHJTYMXmcR1Gm31E7TLE=",
"owner": "cjpais",
"repo": "Handy",
"rev": "b1b2d9f9072e55902a46ca6cc655e5893ed7a91d",
"type": "github"
},
"original": {
"owner": "cjpais",
"repo": "Handy",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
@@ -533,6 +598,21 @@
"type": "github"
}
},
"import-tree": {
"locked": {
"lastModified": 1763762820,
"narHash": "sha256-ZvYKbFib3AEwiNMLsejb/CWs/OL/srFQ8AogkebEPF0=",
"owner": "vic",
"repo": "import-tree",
"rev": "3c23749d8013ec6daa1d7255057590e9ca726646",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "import-tree",
"type": "github"
}
},
"lanzaboote": {
"inputs": {
"crane": "crane",
@@ -558,11 +638,11 @@
},
"llm-agents": {
"inputs": {
"bun2nix": "bun2nix",
"flake-parts": "flake-parts_2",
"bun2nix": "bun2nix_2",
"flake-parts": "flake-parts_3",
"nixpkgs": "nixpkgs_4",
"systems": "systems_4",
"treefmt-nix": "treefmt-nix"
"systems": "systems_5",
"treefmt-nix": "treefmt-nix_2"
},
"locked": {
"lastModified": 1785753922,
@@ -765,6 +845,21 @@
"type": "github"
}
},
"nixpkgs-lib_2": {
"locked": {
"lastModified": 1769909678,
"narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "72716169fe93074c333e8d0173151350670b824c",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs-libxml2": {
"locked": {
"lastModified": 1751274312,
@@ -982,11 +1077,11 @@
},
"nixvim": {
"inputs": {
"flake-parts": "flake-parts_3",
"flake-parts": "flake-parts_4",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_5"
"systems": "systems_6"
},
"locked": {
"lastModified": 1782919967,
@@ -1077,6 +1172,7 @@
"flake-parts": "flake-parts",
"ghostty": "ghostty",
"git-hooks-nix": "git-hooks-nix",
"handy": "handy",
"home-manager": "home-manager_2",
"lanzaboote": "lanzaboote",
"llm-agents": "llm-agents",
@@ -1093,8 +1189,8 @@
"services-flake": "services-flake",
"sops-nix": "sops-nix",
"stylix": "stylix",
"systems": "systems_7",
"treefmt-nix": "treefmt-nix_2",
"systems": "systems_8",
"treefmt-nix": "treefmt-nix_3",
"vicinae": "vicinae",
"vicinae-extensions": "vicinae-extensions"
}
@@ -1181,13 +1277,13 @@
"base16-helix": "base16-helix",
"base16-vim": "base16-vim",
"firefox-gnome-theme": "firefox-gnome-theme",
"flake-parts": "flake-parts_4",
"flake-parts": "flake-parts_5",
"gnome-shell": "gnome-shell",
"nixpkgs": [
"nixpkgs"
],
"nur": "nur",
"systems": "systems_6",
"systems": "systems_7",
"tinted-kitty": "tinted-kitty",
"tinted-schemes": "tinted-schemes",
"tinted-tmux": "tinted-tmux",
@@ -1222,6 +1318,21 @@
"type": "github"
}
},
"systems_10": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
@@ -1284,6 +1395,21 @@
}
},
"systems_6": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_7": {
"locked": {
"lastModified": 1774449309,
"narHash": "sha256-brhZ8DmuGtzkCYHJg4HEd602amKm89Y9ytsFZ5uWD1w=",
@@ -1299,21 +1425,6 @@
"type": "github"
}
},
"systems_7": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_8": {
"locked": {
"lastModified": 1681028828,
@@ -1409,6 +1520,28 @@
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"handy",
"bun2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1770228511,
"narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "337a4fe074be1042a35086f15481d763b8ddc0e7",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"treefmt-nix_2": {
"inputs": {
"nixpkgs": [
"llm-agents",
@@ -1429,7 +1562,7 @@
"type": "github"
}
},
"treefmt-nix_2": {
"treefmt-nix_3": {
"inputs": {
"nixpkgs": "nixpkgs_10"
},
@@ -1451,7 +1584,7 @@
"inputs": {
"nixpkgs": "nixpkgs_11",
"soulver-cpp": "soulver-cpp",
"systems": "systems_8"
"systems": "systems_9"
},
"locked": {
"lastModified": 1785733880,
@@ -1473,7 +1606,7 @@
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_9",
"systems": "systems_10",
"vicinae": "vicinae_2"
},
"locked": {
+6
View File
@@ -38,6 +38,12 @@
url = "github:ghostty-org/ghostty";
};
# Speech to text
handy = {
url = "github:cjpais/Handy";
inputs.nixpkgs.follows = "nixpkgs";
};
# Shell / Launcher
vicinae.url = "github:vicinaehq/vicinae";
+8
View File
@@ -0,0 +1,8 @@
{
homebrew.casks = [ "handy" ];
launchd.agents.handy = {
command = "/usr/bin/open -gja Handy --args --start-hidden";
serviceConfig.RunAtLoad = true;
};
}
+74
View File
@@ -0,0 +1,74 @@
{
config,
inputs,
lib,
pkgs,
...
}:
let
handy = inputs.handy.packages.${pkgs.stdenv.hostPlatform.system}.handy;
settingsFile = "${config.xdg.configHome}/com.pais.handy/settings_store.json";
in
{
home.packages = [
handy
pkgs.wtype
];
# Handy has no disabled-shortcut setting. Empty bindings are rejected before
# registration, leaving niri and labwc as the sole owners of Ctrl+Space.
home.activation.disableHandyGlobalShortcuts = {
after = [ "writeBoundary" ];
before = [ ];
data = ''
settingsFile=${lib.escapeShellArg settingsFile}
mkdir -p "$(dirname "$settingsFile")"
if [ -f "$settingsFile" ]; then
${lib.getExe pkgs.jq} \
'.settings.bindings.transcribe.current_binding = ""
| .settings.bindings.transcribe_with_post_process.current_binding = ""' \
"$settingsFile" > "$settingsFile.tmp"
else
${lib.getExe pkgs.jq} -n '
{
settings: {
bindings: {
transcribe: {
id: "transcribe",
name: "Transcribe",
description: "Converts your speech into text.",
default_binding: "ctrl+space",
current_binding: ""
},
transcribe_with_post_process: {
id: "transcribe_with_post_process",
name: "Transcribe with Post-Processing",
description: "Converts your speech into text and applies AI post-processing.",
default_binding: "ctrl+shift+space",
current_binding: ""
}
}
}
}
' > "$settingsFile.tmp"
fi
mv "$settingsFile.tmp" "$settingsFile"
'';
};
systemd.user.services.handy = {
Unit = {
Description = "Handy speech-to-text";
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Service = {
ExecStart = "${lib.getExe handy} --start-hidden";
Restart = "on-failure";
RestartSec = 5;
};
Install.WantedBy = [ "graphical-session.target" ];
};
}
+3
View File
@@ -0,0 +1,3 @@
{
description = "Handy offline speech-to-text";
}
+1
View File
@@ -127,6 +127,7 @@ in
(execute "W-space" "ghostty +toggle-quick-terminal")
(execute "W-p" "wdisplays")
(execute "W-z" "wl-find-cursor -c 0xCCFF453A -s 160 -d 1200")
(execute "C-space" "handy --toggle-transcription")
# Function keys (sync with niri modules/applications/niri/home.nix)
(execute "XF86AudioRaiseVolume" "noctalia msg volume-up")
+7
View File
@@ -119,6 +119,13 @@ in
];
hotkey-overlay.title = "Find Cursor";
};
"Ctrl+Space" = {
action.spawn = [
"handy"
"--toggle-transcription"
];
hotkey-overlay.title = "Toggle Handy Transcription";
};
# Function keys (sync with labwc modules/applications/labwc/home.nix)
"XF86AudioRaiseVolume".action.spawn = [
+7
View File
@@ -63,6 +63,13 @@ enables performance improvements, synced lyrics, tracker blocking, the album
color theme, and custom output-device selection while preserving user-owned
settings such as the selected device.
`workload.personal` also provides Handy for offline speech-to-text. It starts
hidden when the graphical session begins. On niri and labwc, `Ctrl+Space` is
owned by the compositor and invokes Handy's `--toggle-transcription` command;
Handy's own shortcut bindings are disabled on NixOS so it does not monitor
keyboard events under Wayland. Handy uses the Homebrew cask and starts at login
on macOS.
On NixOS, `workload.game` provides Steam with Valve Proton and Proton-GE,
Protontricks, Wayland-compatible Steam Input, GameMode, Gamescope, and MangoHud.
Enabling Steam also activates the 32-bit graphics and PipeWire support required
@@ -6,6 +6,7 @@
"applications.chrome"
"applications.discord"
"applications.gnome-text-editor"
"applications.handy"
"applications.kde"
"applications.moonlight"
"applications.slack"