Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ build/
# ============================================================================
target/
src-tauri/target/
src-tauri/Cargo.lock
*.dylib

# ============================================================================
Expand Down
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,28 @@ xattr -dr com.apple.quarantine /Applications/Thoth.app

### First launch (Linux)

**AppImage:**

1. Download the `.AppImage` from the [latest release](https://github.com/poodle64/thoth/releases/latest)
2. Make it executable: `chmod +x Thoth_*.AppImage`
3. Run it: `./Thoth_*.AppImage`

**NixOS (flake):**

Add Thoth as a flake input and install the package:

```nix
# flake.nix
{
inputs.thoth.url = "github:poodle64/thoth";

# In your system or home-manager config:
environment.systemPackages = [ inputs.thoth.packages.${system}.default ];
}
```

The flake builds with CUDA support and wraps runtime dependencies (`wl-clipboard`, `wtype`) automatically.

> **NVIDIA users**: Ensure CUDA drivers are installed for GPU-accelerated transcription.
> Without them, Thoth falls back to CPU.

Expand Down Expand Up @@ -141,7 +159,7 @@ The app walks you through three quick steps:
- macOS native (Apple Silicon)
- Global keyboard shortcuts
- Recording indicator near cursor
- Linux support planned
- Linux/Wayland support

</td>
</tr>
Expand Down
121 changes: 118 additions & 3 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
};

outputs = { self, nixpkgs, flake-utils, rust-overlay, ... }:
flake-utils.lib.eachDefaultSystem (system:
(flake-utils.lib.eachDefaultSystem (system:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
Expand All @@ -30,6 +30,113 @@
cudaPackages = pkgs.cudaPackages_12;

in {
# =====================================================================
# Nix package — installable via `nix build` or as a flake input
# =====================================================================
packages.default = pkgs.rustPlatform.buildRustPackage (finalAttrs: {
pname = "thoth";
version = "2026.2.7";
src = ./.;

cargoRoot = "src-tauri";
buildAndTestSubdir = "src-tauri";
cargoHash = "sha256-bWRmk1cvPxPqnzhB6KnW586Xhlqd4z6vFUOn/ujsQJk=";

# Disable default features to exclude fluidaudio (macOS-only git dep
# that fails in Nix sandbox) and parakeet (download-binaries feature)
buildNoDefaultFeatures = true;
buildFeatures = [ "cuda" ];

# Pre-fetched pnpm dependencies for the Svelte frontend
pnpmDeps = pkgs.fetchPnpmDeps {
inherit (finalAttrs) pname version src;
fetcherVersion = 3;
hash = "sha256-2/TWfSxppLkweslAwlWLRjHJQd44x20FKraY9o5HCGI=";
};

nativeBuildInputs = with pkgs; [
cargo-tauri.hook # Replaces cargoBuildHook/cargoInstallHook
nodejs
pnpmConfigHook # Sets up pre-fetched pnpm deps
pnpm
pkg-config
cmake # Required by whisper.cpp (whisper-rs dependency)
git # Required by whisper.cpp CMakeLists.txt
llvmPackages.libclang # Required by bindgen for whisper.cpp
wrapGAppsHook4 # GTK/GLib schema wrapping
makeWrapper # For wrapping runtime PATH deps
cudaPackages.cuda_nvcc
gcc # Required for CUDA compilation
];

buildInputs = with pkgs; [
openssl
webkitgtk_4_1
glib
glib-networking # HTTPS support in webkitgtk
libsecret # Credential storage
libappindicator-gtk3
alsa-lib
librsvg
libx11
libxcursor
libxrandr
libxi
vulkan-loader
vulkan-headers
shaderc
cudaPackages.cudatoolkit
cudaPackages.cuda_cudart
cudaPackages.cuda_cccl
cudaPackages.libcublas
];

env = {
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
WEBKIT_DISABLE_COMPOSITING_MODE = "1";
CUDA_PATH = "${cudaPackages.cudatoolkit}";
RUSTFLAGS = "-C relocation-model=dynamic-no-pic -L ${cudaPackages.cuda_cudart}/lib/stubs";
};

postFixup = ''
wrapProgram $out/bin/thoth \
--prefix PATH : ${pkgs.lib.makeBinPath [
pkgs.wl-clipboard # wl-copy, wl-paste
pkgs.wtype # Wayland keyboard simulation
pkgs.glib.bin # gsettings (theme detection)
pkgs.libcanberra-gtk3 # canberra-gtk-play (sound feedback)
pkgs.hyprland # hyprctl (indicator positioning, keybind bridge)
pkgs.socat # Unix socket IPC for Hyprland shortcut delivery
]} \
--prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath [
pkgs.libappindicator-gtk3
pkgs.vulkan-loader
cudaPackages.cuda_cudart
cudaPackages.libcublas
]}:/run/opengl-driver/lib \
--set WEBKIT_DISABLE_COMPOSITING_MODE 1
'';

# Disable updater artifact signing (no private key in nix sandbox)
preBuild = ''
substituteInPlace src-tauri/tauri.conf.json \
--replace-fail '"createUpdaterArtifacts": true' '"createUpdaterArtifacts": false'
'';

doCheck = false; # Tests need audio hardware

meta = with pkgs.lib; {
description = "Privacy-first, offline-capable voice transcription";
homepage = "https://github.com/kirin-ri/thoth";
license = licenses.mit;
platforms = platforms.linux;
mainProgram = "thoth";
};
});

# =====================================================================
# Development shell — unchanged from original
# =====================================================================
devShells.default = pkgs.mkShell {
# Platform-specific library paths (Linux)
LD_LIBRARY_PATH = pkgs.lib.optionalString pkgs.stdenv.isLinux
Expand All @@ -55,7 +162,9 @@
CUDA_HOME = pkgs.lib.optionalString pkgs.stdenv.isLinux "${cudaPackages.cudatoolkit}";

# Linker search path for CUDA driver (libcuda.so)
RUSTFLAGS = pkgs.lib.optionalString pkgs.stdenv.isLinux "-L /run/opengl-driver/lib";
# NOTE: -C relocation-model=dynamic-no-pic is REQUIRED for sherpa-rs static linking on Linux
# See: https://github.com/thewh1teagle/sherpa-rs/issues/62
RUSTFLAGS = pkgs.lib.optionalString pkgs.stdenv.isLinux "-C relocation-model=dynamic-no-pic -L /run/opengl-driver/lib";

packages = with pkgs; [
# Rust / Tauri
Expand Down Expand Up @@ -135,5 +244,11 @@
echo " --features vulkan - Cross-platform (experimental)"
'';
};
});
}
)) // {
# Overlay — defined outside eachDefaultSystem (overlays are system-independent)
overlays.default = final: prev: {
thoth = self.packages.${final.system}.default;
};
};
}
Loading