Skip to main content

Wayland hotkey dictation CLI and daemon; native ASR/LLM fetched on first run.

Project description

Dictum

Dictum is a Python voice-to-text command tool designed for Wayland compositors such as Hyprland and Sway. It is intended to be triggered from a hotkey, record microphone audio, transcribe it with Parakeet TDT v3 0.6B, polish the transcription with a local or cloud LLM, and send the final text to the active window, clipboard, stdout, or a file.

Goals

  • Fast hotkey workflow for dictation and text transformation.
  • Persistent daemon for state, warm models, and lower latency.
  • Companion CLI for key bindings and scripting.
  • Pluggable ASR, LLM, recorder, and output backends.
  • Wayland-first output through wtype, ydotool, wl-copy, or stdout.

Architecture

Hyprland/Sway hotkey
  -> dictum CLI (thin IPC client)
  -> daemon command over local Unix socket
  -> record mic audio (sounddevice/PipeWire)
  -> transcribe with Parakeet (CrispASR HTTP server, port 8081)
  -> polish with LLM (llama.cpp server, port 8080)
  -> paste/copy/print/save result

Moving Parts

Component Technology Purpose
CLI Python + Typer Hotkey-friendly commands (toggle, start, stop, once, status)
Daemon Python + asyncio State machine, IPC server, pipeline orchestration
Recorder sounddevice (PortAudio) PipeWire/PulseAudio capture, silence watchdog
ASR CrispASR (C++/Vulkan) Parakeet TDT v3 0.6B GGUF, HTTP server mode (warm)
LLM llama.cpp (C++/Vulkan) Qwen 3.5-4B GGUF, OpenAI-compatible HTTP server (warm)
Output wtype / ydotool / wl-copy Wayland text insertion
Notify D-Bus (gdbus) Desktop notifications

State Machine

idle -> recording -> transcribing -> polishing -> pasting -> idle
              \-> failed (on error) ----------------------------> idle

polishing is skipped if the profile disables LLM rewriting.


Quick Start

1. Prerequisites

  • GPU: Discrete GPU with Vulkan support (optional but recommended)
  • Vulkan loader: libvulkan1 / vulkan-loader + a compatible ICD
  • Python: 3.11+ with uv (recommended) or pip

2. Install Dictum

# From PyPI, once published
uv tool install dictum-asr

# Or from a local source checkout while developing
git clone https://github.com/hermitm0nk/dictum.git
cd dictum
uv tool install .

The wheel is pure Python and tiny (tens of KB). The native C++ binaries are no longer built from source at install time. Instead, Dictum downloads pinned upstream releases on first use:

  • llama.cppllama-server (Vulkan build, b9699)
  • CrispASRparakeet-main (Vulkan build, v0.7.2)

Pre-fetch them explicitly (recommended before binding a hotkey):

dictum native install            # fetch both, Vulkan variant
dictum native install --lib llama
dictum native install --variant cpu   # if no Vulkan ICD is present
dictum native status             # show what's installed and where

Binaries land under $DICTUM_NATIVE_DIR when set, otherwise under $XDG_DATA_HOME/dictum/native/, or ~/.local/share/dictum/native/. The llama-server binary ships with RUNPATH=$ORIGIN so it finds its sibling .so files automatically; parakeet-main is statically linked. No LD_LIBRARY_PATH is required in normal use.

To override the bundled binaries entirely, set DICTUM_LLM_BIN and/or DICTUM_PARAKEET_BIN to point at your own builds — Dictum will not attempt to download when an override is set.

3. Download Models

# Parakeet ASR (multilingual, 4-bit quant)
huggingface-cli download cstr/parakeet-tdt-0.6b-v3-GGUF \
  parakeet-tdt-0.6b-v3-q4_k.gguf \
  --local-dir ~/.cache/dictum/models/

# Qwen LLM (Q3 quant for polishing)
huggingface-cli download unsloth/Qwen3.5-4B-GGUF \
  Qwen3.5-4B-Q3_K_M.gguf \
  --local-dir ~/.cache/dictum/models/

By default Dictum downloads models on first use into $DICTUM_MODEL_DIR when set, otherwise into $XDG_CACHE_HOME/dictum/models or ~/.cache/dictum/models.

4. Configure (Optional)

mkdir -p ~/.config/dictum
cp examples/config.toml ~/.config/dictum/config.toml
# Edit profiles, ASR/LLM settings, output target

Usage

Start the Daemon

# Foreground (testing)
dictum daemon --profile default

# Or as systemd user service (persistent, see below)

Hotkey Commands

# Toggle recording (press once to start, again to stop & process)
dictum toggle --profile default --result paste

# Explicit start/stop
dictum start --profile default
dictum stop --result paste

# One-shot (no daemon needed)
dictum once --result stdout --duration 30

# Status
dictum status
dictum status --json

Output Targets (--result)

Target Behavior
paste Types into focused window via wtype/ydotool (fallback: clipboard)
clipboard Copies to clipboard via wl-copy
stdout Prints to terminal
file Writes to /tmp/dictum-output.txt
none No output

Systemd User Service (Persistent Daemon)

# Install, enable (starts at login), but do not start now
dictum service install

# Install and start immediately
dictum service install --now

# Check status
dictum service status

# Remove the service
dictum service uninstall

The unit file is bundled with the wheel and copied to ~/.config/systemd/user/dictum.service (or $XDG_CONFIG_HOME/systemd/user/). User units start at graphical/login session, not at boot.

The bundled unit (dictum/data/dictum.service):

[Unit]
Description=Dictum voice dictation daemon
After=graphical-session.target pipewire.service

[Service]
Type=simple
ExecStart=%h/.local/bin/dictum daemon
Restart=on-failure
RestartSec=2

[Install]
WantedBy=default.target

You can still manage the service directly with systemctl --user {start,stop,restart,status} dictum. Edit the installed unit file to customize ExecStart (e.g. add --profile flags) and run systemctl --user daemon-reload.


Hyprland Binding

Add to ~/.config/hypr/hyprland.conf:

# Dictum voice dictation (ScrollLock to toggle)
bind = , Scroll_Lock, exec, dictum toggle --profile default --result paste

Reload config:

hyprctl reload

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dictum_asr-0.1.0.tar.gz (41.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dictum_asr-0.1.0-py3-none-any.whl (37.4 kB view details)

Uploaded Python 3

File details

Details for the file dictum_asr-0.1.0.tar.gz.

File metadata

  • Download URL: dictum_asr-0.1.0.tar.gz
  • Upload date:
  • Size: 41.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dictum_asr-0.1.0.tar.gz
Algorithm Hash digest
SHA256 120fd5c47bee2f32c630e761f56652e4d6f6ab146f22a0e8b94e571dc2ed7485
MD5 a648421bdce11a3d2aed39fd8f11a96a
BLAKE2b-256 d2d46a8081716a61ab1aff8f4bafdd254229483d607b9763acd799bf43502dc3

See more details on using hashes here.

Provenance

The following attestation bundles were made for dictum_asr-0.1.0.tar.gz:

Publisher: pypi-publish.yaml on hermitm0nk/dictum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dictum_asr-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: dictum_asr-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 37.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dictum_asr-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 897541237858ad4e5b551379023070beadd1838fc4a01cebe68f81ed684cbb4b
MD5 7872110cd66b1195bbdb4a429808755c
BLAKE2b-256 7554f0decb9fc4933c16e4c99dc5a17225e4cc6a6c2f581dc79229ecb92d680c

See more details on using hashes here.

Provenance

The following attestation bundles were made for dictum_asr-0.1.0-py3-none-any.whl:

Publisher: pypi-publish.yaml on hermitm0nk/dictum

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page