Metadata-Version: 2.4
Name: moonsway-tts
Version: 0.1.1
Summary: On-device Moonshine dictation for Sway and wtype
Keywords: cli,dictation,moonshine,speech-to-text,sway,wayland
Author: Chris Paganon
Author-email: Chris Paganon <info@chrispaganon.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Utilities
Requires-Dist: click>=8.3.1,<9
Requires-Dist: moonshine-voice>=0.1.5,<0.2
Requires-Dist: typer>=0.25.1,<1
Requires-Python: >=3.12
Project-URL: Homepage, https://codeberg.org/chris-paganon/moonsway-tts
Project-URL: Repository, https://codeberg.org/chris-paganon/moonsway-tts
Project-URL: Issues, https://codeberg.org/chris-paganon/moonsway-tts/issues
Description-Content-Type: text/markdown

# Moonsway TTS

`Moonsway TTS` is a small on-device push-to-toggle dictation CLI for Sway.
[Moonshine Voice](https://github.com/moonshine-ai/moonshine) transcribes the
microphone locally, and each finalized transcript line is typed into the
keyboard-focused application with `wtype`.

Partial hypotheses are deliberately not typed. They can change while you speak,
so inserting them would require destructive Backspace-based rewrites.

## Requirements

- Linux with Sway or another Wayland compositor supporting
  `virtual-keyboard-unstable-v1`
- `wtype`
- Python 3.12+
- A working PortAudio input device

On Arch Linux, install the external system dependencies with:

```bash
sudo pacman -S portaudio wtype
```

The selected Moonshine model is downloaded on the first daemon launch and
reused from the local cache. No API key or hosted speech service is used.

## Installation

Run without installing:

```bash
uvx moonsway-tts --help
```

Install as a tool with `uv`:

```bash
uv tool install moonsway-tts
```

Install with `pip`:

```bash
pip install moonsway-tts
```

Or use my Forgejo PyPI instance:

```bash
uvx --index https://forgejo.chrispaganon.com/api/packages/chris-paganon/pypi/simple/ moonsway-tts --help
uv tool install --index https://forgejo.chrispaganon.com/api/packages/chris-paganon/pypi/simple/ moonsway-tts
pip install --index-url https://forgejo.chrispaganon.com/api/packages/chris-paganon/pypi/simple/ moonsway-tts
```

## Usage

Start the long-running daemon:

```bash
moonsway-tts daemon
```

The model loads immediately, but the microphone remains stopped until a control
command is sent. Stopping dictation closes the microphone capture stream, so
the idle daemon does not reserve the input device and other applications can
continue using it. Starting dictation opens the stream again without reloading
the model. From another terminal:

```bash
moonsway-tts status
moonsway-tts start
moonsway-tts toggle
moonsway-tts stop
```

Each completed Moonshine line is trimmed, followed by one space, and passed to
`wtype` over standard input without a shell. Use `--separator` to change the
suffix and `--wtype-delay` if an application drops very fast key events:

```bash
moonsway-tts daemon --separator $'\n' --wtype-delay 2
```

The default delay is 1 ms because `wtype` 0.4 rejects a zero delay. Inspect all
model, language, logging, and socket options with:

```bash
moonsway-tts --help
moonsway-tts daemon --help
moonsway-tts --version
```

## Sway configuration

Install Moonsway TTS as a tool, then locate its executable:

```bash
uv tool install moonsway-tts
uv tool dir --bin
```

Add the executable path reported by `uv tool dir --bin` to the Sway
configuration. For the usual `uv` tool location:

```text
set $moonsway_tts /home/you/.local/bin/moonsway-tts
exec $moonsway_tts daemon
bindsym --release --no-repeat F9 exec $moonsway_tts toggle
```

Replace `/home/you` and `F9` as needed. An unmodified key released before the
command runs avoids physical Ctrl, Shift, Alt, or Super state interfering with
injected text.

Do not run another microphone dictation service on the same binding. If
replacing Handy, remove or comment out its autostart and binding. Reloading a
Sway configuration adds the binding, but Sway's ordinary `exec` is intended for
session startup; start the daemon in a terminal for the current session or
restart the Sway session.

Text goes to the keyboard-focused field, not necessarily the window under the
mouse pointer. Avoid moving focus or the caret until the finalized line has been
inserted.

## Development

Clone the repository and install the locked environment:

```bash
git clone https://codeberg.org/chris-paganon/moonsway-tts.git
cd moonsway-tts
uv sync --locked
```

Run the quality checks:

```bash
uv run ruff check .
uv run ruff format --check .
uv run mypy src tests
uv run pytest -q
```
