Metadata-Version: 2.4
Name: voxy-linux
Version: 0.1.0
Summary: Local offline voice dictation for Linux
License: MIT License
        
        Copyright (c) 2025 Samuel Diop
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: faster-whisper
Requires-Dist: sounddevice
Requires-Dist: evdev; sys_platform == "linux"
Requires-Dist: pynput
Requires-Dist: numpy
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Dynamic: license-file

# voxy 🎙️

> **Hold. Speak. Release. Done.**

Local, offline voice dictation for Linux — text appears instantly in whatever window is active. No cloud. No subscription. No audio ever leaves your machine.

Built on [faster-whisper](https://github.com/SYSTRAN/faster-whisper) (2–4× faster than openai-whisper on CPU, same accuracy). Works on X11 and Wayland. Ships as a Nix flake.

---

## Installation

### uvx (try without installing)

```bash
uvx voxy-linux
```

### pipx (persistent isolated install)

```bash
pipx install voxy-linux
```

### AUR (Arch / Manjaro)

```bash
yay -S voxy-linux
```

### NixOS

See the [NixOS](#nixos) section below.

---

## Prerequisites

Before installing via `pip` / `pipx` / `uvx`, install the required system packages.

**Audio** (required)

| Distro | Command |
|---|---|
| Debian / Ubuntu | `sudo apt install libportaudio2` |
| Fedora | `sudo dnf install portaudio` |
| Arch | `sudo pacman -S portaudio` |

**Text insertion** (install the set that matches your display server)

| Display server | Packages |
|---|---|
| X11 | `xclip` + `xdotool` |
| Wayland | `wl-clipboard` + `ydotool` |

> **macOS / Windows:** voxy is Linux-only. The package will install but will not run on other platforms.

---

## How it works

1. Hold the hotkey (default: **Right Alt**)
2. Speak
3. Release — transcribed text is pasted into the active window

That's it.

A small overlay appears in a configurable screen corner:

- **REC** (red) — microphone is active
- **…** (amber) — transcribing and processing
- Overlay disappears once text is inserted

---

## Quick start

```bash
voxy                        # run in foreground
voxy --daemon install       # install as a systemd user service
voxy --daemon remove        # stop and remove the service
voxy --daemon status        # check service status
```

On first run a default config is written to `~/.config/voxy/config.toml` and the Whisper model is downloaded to `~/.cache/voxy/models/`.

---

## Configuration

`~/.config/voxy/config.toml` — created with defaults on first run, fully commented.

```toml
[hotkey]
key = "right_alt"              # evdev/pynput key name

[model]
size = "small"                 # tiny | base | small | medium | large-v3
language = "auto"              # auto-detect per utterance, or a BCP-47 code
fallback_language = "en"

[insertion]
method = "auto"                # auto | x11 | wayland

[post_processing]
punctuation_commands = true    # say "comma" → ,  "period" → .  "new line" → ↵
auto_capitalize = true
strip_fillers = false
fillers = ["uh", "um", "hmm"]

[post_processing.substitutions]
"new line"      = "\n"
"new paragraph" = "\n\n"
"comma"         = ","
"period"        = "."

[ui]
overlay = true
overlay_corner = "bottom-right"    # top-left | top-right | bottom-left | bottom-right
audio_feedback = false

[logging]
level = "info"
```

**Terminal paste:** when a terminal emulator is the active window (alacritty, kitty, ghostty, gnome-terminal, konsole), voxy automatically uses Ctrl+Shift+V instead of Ctrl+V. No configuration needed.

**Config path override:** set `VOXY_CONFIG=/path/to/config.toml` to point voxy at a specific file. This takes priority over `~/.config/voxy/config.toml`.

---

## NixOS

### Add to your flake

```nix
# flake.nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    voxy.url    = "github:Slownite/voxy-linux";
  };

  outputs = { nixpkgs, voxy, ... }: {
    nixosConfigurations.my-host = nixpkgs.lib.nixosSystem {
      modules = [
        voxy.nixosModules.voxy
        ./configuration.nix
      ];
    };
  };
}
```

### Minimal config

```nix
# configuration.nix
{
  services.voxy.enable = true;

  # Required: the voxy user needs access to /dev/input for hotkey capture.
  users.users.your-username.extraGroups = [ "input" ];
}
```

### All options

| Option | Type | Default | Description |
|---|---|---|---|
| `services.voxy.enable` | `bool` | `false` | Enable voxy |
| `services.voxy.hotkey` | `string` | `"right_alt"` | Push-to-talk key (evdev/pynput name) |
| `services.voxy.modelSize` | `enum` | `"small"` | Whisper model size |
| `services.voxy.overlayCorner` | `enum` | `"bottom-right"` | Recording overlay corner |

**`modelSize`** — `tiny` · `tiny.en` · `base` · `base.en` · `small` · `small.en` · `medium` · `medium.en` · `large-v1` · `large-v2` · `large-v3`

**`overlayCorner`** — `top-left` · `top-right` · `bottom-left` · `bottom-right`

### Example with custom options

```nix
services.voxy = {
  enable      = true;
  hotkey      = "right_ctrl";
  modelSize   = "base";
  overlayCorner = "top-right";
};
```

> **Note:** The NixOS module generates a `config.toml` from your declared options and passes it to the service via `VOXY_CONFIG`. `VOXY_CONFIG` takes priority over `~/.config/voxy/config.toml` — so the system-level declaration wins unless you run voxy manually without the env var set.

---

## Development

```bash
nix develop                         # enter the dev shell (Python + all deps)
nix develop --command pytest        # run the test suite
nix develop --command mypy --strict src/   # strict type check
```

---

## Troubleshooting

**Overlay not visible when running as a service**

The service starts after `graphical-session.target`, but display auth (`XAUTHORITY`) may not be ready immediately. If `journalctl --user -u voxy.service` shows "overlay disabled", add a short delay:

```nix
# configuration.nix
systemd.user.services.voxy.serviceConfig.ExecStartPre = "/bin/sleep 2";
```

**Indicator stays amber / nothing is pasted**

Make sure you have rebuilt after any `flake.nix` change:

```bash
sudo nixos-rebuild switch
```

Or run from the dev shell directly — the installed package won't pick up source changes:

```bash
nix develop --command python -m voxy
```

**Hotkey not captured**

Your user must be in the `input` group:

```nix
users.users.your-username.extraGroups = [ "input" ];
```

Apply with `sudo nixos-rebuild switch`, then log out and back in.

---

## Credits

UX reference: [WisprFlow](https://wisprflow.ai/) — voxy is the Linux-native, offline, open-source answer to it.
