Metadata-Version: 2.4
Name: novavoice
Version: 0.2.0
Summary: Local, offline voice dictation for Linux, macOS, and Windows — hold a key, speak, release
Project-URL: Homepage, https://github.com/novafabric/novavoice
Project-URL: Repository, https://github.com/novafabric/novavoice
Project-URL: Bug Tracker, https://github.com/novafabric/novavoice/issues
Author-email: Mohsen Seyedkazemi Moghadam <mohsen.seyedkazemi@gmail.com>
License: Apache-2.0
License-File: LICENSE
Keywords: accessibility,dictation,linux,speech-to-text,voice,whisper
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: No Input/Output (Daemon)
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Requires-Python: >=3.11
Requires-Dist: evdev>=1.9.3; sys_platform == 'linux'
Requires-Dist: faster-whisper>=1.2.1
Requires-Dist: numpy>=2.4.4
Requires-Dist: pillow>=11.0; sys_platform == 'win32'
Requires-Dist: platformdirs>=4.3
Requires-Dist: pyobjc-framework-applicationservices>=11; sys_platform == 'darwin'
Requires-Dist: pyobjc-framework-avfoundation>=11; sys_platform == 'darwin'
Requires-Dist: pyobjc-framework-cocoa>=11; sys_platform == 'darwin'
Requires-Dist: pyobjc-framework-quartz>=11; sys_platform == 'darwin'
Requires-Dist: pystray>=0.19.5; sys_platform == 'win32'
Requires-Dist: pywin32>=308; sys_platform == 'win32'
Requires-Dist: rumps>=0.4.0; sys_platform == 'darwin'
Requires-Dist: sounddevice>=0.5.5
Requires-Dist: typer>=0.25.1
Description-Content-Type: text/markdown

# NovaVoice

Local, offline voice dictation for **Linux**, **macOS**, and **Windows**. Hold a key, speak, release — the transcribed text appears in whatever app is focused. No cloud, no GPU.

[![Tests](https://github.com/novafabric/novavoice/actions/workflows/test.yml/badge.svg)](https://github.com/novafabric/novavoice/actions/workflows/test.yml)
[![PyPI](https://img.shields.io/pypi/v/novavoice)](https://pypi.org/project/novavoice/)
[![Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)

```
Hold the dictation key (>0.5s) → speak → release → text appears
```

Powered by [faster-whisper](https://github.com/SYSTRAN/faster-whisper) (CPU/int8). Works in browsers, terminals, IDEs, chat apps — anywhere the OS lets keystrokes reach the focused window.

---

## Supported platforms

| OS      | Hotkey default | Install                                 | Status |
|---------|----------------|-----------------------------------------|--------|
| Linux   | `Space`        | apt / snap / PPA / pipx / .deb / installer | Stable |
| macOS   | `Right Option` | `.dmg` (Homebrew Cask coming)           | Developer preview (unsigned) |
| Windows | `Right Ctrl`   | `.exe` installer (winget coming)        | Developer preview (unsigned) |

> **Why Right Ctrl on Windows, not Right Alt?** On many international layouts Right Alt acts as **AltGr** — used to type `@`, `€`, `{}`, `[]`, `\`, `~`, etc. Hijacking it would break normal typing. Right Ctrl is rarely used for typing, so it's the safer default. Every platform's hotkey is configurable in `config.toml`.

---

## Quick install

### macOS

1. Download `NovaVoice-<version>.dmg` from the [latest release](https://github.com/novafabric/novavoice/releases/latest).
2. Open the `.dmg`, drag **NovaVoice.app** into **Applications**.
3. **First launch**: right-click → Open (the v0 build is unsigned; signing is coming).
4. Grant **Accessibility** + **Microphone** in System Settings when prompted.
5. Hold **Right Option** anywhere, speak, release.

Full guide: [`docs/macos-install.md`](docs/macos-install.md).

### Windows

1. Download `NovaVoice-<version>-windows-x64.exe` from the [latest release](https://github.com/novafabric/novavoice/releases/latest).
2. Run it. SmartScreen may say *"unrecognized app"* — click **More info → Run anyway** (the v0 build is unsigned).
3. Optionally tick **Start NovaVoice automatically when I sign in** in the installer.
4. Hold **Right Ctrl** anywhere, speak, release.

Full guide: [`docs/windows-install.md`](docs/windows-install.md).

### Linux

Pick the channel that matches your setup:

```bash
# One-line installer (Debian/Ubuntu derivatives)
bash <(curl -fsSL https://raw.githubusercontent.com/novafabric/novavoice/main/install.sh)

# APT repo (Debian/Ubuntu)
curl -fsSL https://novafabric.github.io/novavoice/apt/KEY.gpg \
  | sudo gpg --dearmor -o /usr/share/keyrings/novavoice.gpg
echo "deb [signed-by=/usr/share/keyrings/novavoice.gpg] https://novafabric.github.io/novavoice/apt ./" \
  | sudo tee /etc/apt/sources.list.d/novavoice.list
sudo apt update && sudo apt install novavoice

# Launchpad PPA (Ubuntu)
sudo add-apt-repository ppa:novafabric/novavoice
sudo apt update && sudo apt install novavoice

# Snap
sudo snap install novavoice --classic

# pipx (any Linux)
sudo apt install libportaudio2 xdotool xclip pipx
pipx install novavoice
```

After install, add yourself to the `input` group and re-login:

```bash
sudo usermod -aG input "$USER"
# log out and back in
systemctl --user enable --now novavoice.service
```

---

## Usage

NovaVoice runs silently in the background. The same CLI works on every platform.

| Command                        | What it does                                  |
|--------------------------------|-----------------------------------------------|
| Hold the hotkey, speak, release | Transcribe and inject text into focused app  |
| `novavoice status`             | Daemon state, model, hotkey, backend, uptime  |
| `novavoice start` / `stop`     | Manage the daemon                             |
| `novavoice doctor`             | Per-platform prerequisite check               |
| `novavoice inject "hello"`     | Type text without recording (debug)           |

On macOS and Windows the **NovaVoice tray icon** changes color to reflect state (idle / recording / transcribing / error).

---

## Configuration

`config.toml` lives in the platform's standard config dir:

| OS      | Path                                                      |
|---------|-----------------------------------------------------------|
| Linux   | `~/.config/novavoice/config.toml`                         |
| macOS   | `~/Library/Application Support/novavoice/config.toml`     |
| Windows | `%APPDATA%\novavoice\config.toml`                         |

```toml
[stt]
model = "tiny.en"   # tiny.en (fast) | base.en (more accurate, slower)

[hotkey]
# "auto" → Space (Linux) / right_option (macOS) / right_ctrl (Windows).
# Or pick: "right_ctrl", "right_alt", "right_option", "right_shift",
#          "left_ctrl", "left_alt", "left_option", "space", ...
key = "auto"
hold_threshold_ms = 500

[audio]
sample_rate = 16000
max_record_seconds = 90

[tray]
enabled = "auto"   # default true on macOS/Windows, false on Linux v0

[general]
log_level = "INFO"
```

---

## How it works

```
┌──────────────┐   ┌──────────────┐   ┌──────────────────┐   ┌─────────────────┐
│ Hotkey hook  │──▶│ Audio (16kHz │──▶│ faster-whisper   │──▶│ Text injector   │
│ (per-OS API) │   │  via         │   │ (CPU / int8)     │   │ (per-OS API)    │
│              │   │  PortAudio)  │   │                  │   │                 │
└──────────────┘   └──────────────┘   └──────────────────┘   └─────────────────┘
       │                                                              ▲
       └─────────── daemon process ──────────────────────────────────┘
                          ▲
              JSON-RPC over Unix socket / named pipe
                          │
                ┌─────────┴─────────┐
                │     CLI / tray    │
                └───────────────────┘
```

Every platform-specific surface (keyboard hook, text injection, autostart, IPC, paths, permissions, tray) lives behind a single Protocol-based abstraction in `src/novavoice/platform/`. Adding a fifth platform is a matter of writing one more sub-package.

---

## Build from source

```bash
git clone https://github.com/novafabric/novavoice
cd novavoice
uv sync
uv run pytest tests/ -v
```

Platform-specific installers:

```bash
# macOS — produces dist/NovaVoice-<v>.dmg
./scripts/build-macos.sh

# Windows — produces dist/NovaVoice-<v>-windows-x64.exe
./scripts/build-windows.ps1

# Linux .deb
./scripts/build-deb.sh
```

CI builds the unsigned `.dmg` and `.exe` on every PR that touches the relevant code paths.

---

## Troubleshooting

- `novavoice doctor` — first stop. Tells you what's missing on the current OS.
- **macOS**: see [`docs/macos-install.md`](docs/macos-install.md) for Gatekeeper / Accessibility / Microphone.
- **Windows**: see [`docs/windows-install.md`](docs/windows-install.md) for SmartScreen / antivirus / privacy.
- **Linux**: confirm you're in the `input` group; check `journalctl --user -u novavoice.service -f`.

---

## License

Apache 2.0 — see [LICENSE](LICENSE).
