Skip to content
RevolutionLAPublic

About

Push-to-talk dictation for Linux, as a native fcitx5 add-on: hold any key (even Right Ctrl), speak, release, text lands at the cursor. Offline sherpa-onnx backends or cloud, no daemon. A Typeless-style alternative you can actually reconfigure.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Nextless

CI Release License: MIT en · zh

Push-to-talk voice input for fcitx5 — hold a key, speak, release, and the text lands at your cursor.

Nextless is a Typeless-style dictation tool for Linux desktops (Wayland and X11), built as a native fcitx5 add-on. It is a fork of xander-lin/vinput reworked around one idea: the trigger key is yours to choose — including bare modifiers like Right Ctrl — and nothing else about your keyboard behaviour changes.

中文说明 · Roadmap · Contributing · Changelog · Security · Attribution

   hold Right Ctrl        speak         release
  ─────────────────────────────────────────────────▶  your text, at the cursor

Goal

Nextless is the Linux (Ubuntu-first) answer to the "advanced input suite" that Windows and macOS users get for free — voice is the entry point, not the whole story.

The project is done when a Linux user can:

  1. install it with one command, and uninstall it without leaving debris behind;
  2. dictate immediately — model, sounds and a sane trigger key already in place, nothing to fetch by hand;
  3. make it theirs — trigger key, ASR backend, denoiser and notification sounds are all user-swappable; being hackable is the reason this fork exists;
  4. trust it — every commit is built by CI, the failure paths have tests, and no error ever lands in the document.

Today that is a voice-first fcitx5 add-on. The direction is to close the remaining gaps of a real input suite on Linux: punctuation and polish on top of offline recognition, a first-run experience, real packages, and comfortable coexistence with the typing side of the desk (the Chinese IME you already use). Non-goals: writing another input-method engine, or running a cloud service of our own.

Why this exists

Linux has plenty of speech-to-text, but very little dictation that stays out of your way:

Typeless / Wispr Flow openless Electron dictation apps Nextless
Platforms macOS / Windows macOS / Windows cross-platform Linux (Wayland + X11)
Trigger configurable configurable global shortcut, no left/right split any key, incl. Right Ctrl / Alt / Super
Works in every app yes yes via simulated typing yes — it is the input method
Offline backend no no some yes (sherpa-onnx)
Background daemon yes yes yes no
Audio normalisation + denoise + VAD yes varies varies yes

Because Nextless is an fcitx5 module, it commits text through the input-method path your browser, editor and terminal already use. No accessibility permission, no xdotool, no clipboard round-trip, no focus stealing.

Features

  • Configurable push-to-talk key. fcitx5-configtool → Addons → Nextless → Hotkey, or edit ~/.config/fcitx5/conf/nextless.conf. Bare modifiers are allowed (Left/Right Ctrl, Alt, Shift, Super) and combos (Ctrl+Alt+A) work too. A short tap is ignored, so the key keeps typing normally; holding it for 300 ms (tunable) starts dictation.
  • CapsLock still supported, harmlessly. If you pick CapsLock, Nextless re-releases it through /dev/uinput so the lock state never flips. For any other key no virtual keyboard is created at all.
  • Five ASR backends, one hot-swap gesture. Two fully offline (Zipformer bilingual, FireRed ASR2 int8) via sherpa-onnx, two cloud (Doubao Streaming ASR 2.0, Qwen3-ASR) and a mock for testing. Switch with Shift+trigger and ←/→; switch denoiser with ↑/↓.
  • A real audio pipeline, not a raw mic dump: PulseAudio capture → EBU R128 loudness normalisation (−16 LUFS) → denoising (speexdsp by default, DeepFilterNet3 if you install it) → VAD silence trimming with a retained tail so the last syllable is never clipped.
  • Audible state changes. Starting, stopping and switching backend each get a short sound, so you never have to look at the panel to know the key took effect. Drop your own activate.wav, deactivate.wav or switch.wav into ~/.local/share/nextless/sounds/ to replace them; they are generated by tools/gen_sounds.py.
  • Ordering you can trust. You can start the next dictation while the previous one is still being recognised. Each result is bound to the window and input context that was focused when that recording started, and commits happen in recording order (up to three in flight).
  • Your mishearings are fixable. ~/.config/nextless/hotwords.json maps what the model heard to what you meant ({"LIBR": "礼拜二"}). The table post-processes the final text of every backend, local and cloud, before punctuation: longest match wins, replacements never chain, and a missing, empty or malformed file changes nothing. Editing it takes effect on the next utterance — no restart.
  • Errors stay out of your document. Network, service, timeout and microphone failures appear as input-panel status text, never as inserted characters. Silence is a no-op: hold the key, say nothing, release — nothing is committed and nothing is reported.

Limitations (read before you install)

  • Local punctuation is a separate, opt-in model. With the ct-transformer model installed (nextless-get-models --punctuation, ~62 MB), Zipformer and FireRed results come out with ,。? automatically — measured ≈ 0.19 s per 44-character utterance on an i7-1260P, on the recognition thread, never the keypress path. If the model is missing or the punctuation run fails, the raw text is committed instead: the decoration step can never eat an utterance. A binary that fails three times in a row is dropped for the rest of the session (same rule as DeepFilterNet), so a broken or quarantined model costs one slow sentence, not five seconds per sentence forever. Doubao still has richer punctuation plus ITN and its own server-side hotwords (different from the local hotwords.json correction table, which every backend goes through).
  • The correction table is literal. hotwords.json does byte-exact replacement — no word segmentation, case-sensitive, no inflection awareness. Two ways of mishearing one word means two entries.
  • Chinese/English mixed speech is workable on Zipformer bilingual but imperfect on dialect and proper nouns; FireRed is noticeably better and slower.
  • Local models are not shipped. You download them yourself (~360 MB or ~1.2 GB, see below).
  • The .deb is published on the GitHub Releases page (with sha256sums, and tools/install-deb.sh wraps the one-command install); CI builds + installs + removes it on every PR. There is still no apt repository, and fcitx5-nextless-git is not in the AUR yet (issue #35). amd64 is the only prebuilt arch.

Requirements

  • Linux, fcitx5 ≥ 5.1, PulseAudio (PipeWire's Pulse compatibility is fine — tested on PipeWire 1.x)
  • Any desktop: GNOME / KDE / Hyprland, Wayland or X11. A working microphone input.
  • Dictation languages follow the model you pick: the bundled defaults cover Chinese, English and zh-en mixed speech.

Install

0. Pick your route

Arch — build the provided PKGBUILD: makepkg -si (produces fcitx5-nextless-git).

Debian / Ubuntu — one command; it downloads the .deb from the latest GitHub Release, verifies the sha256, and lets apt resolve every dependency (fcitx5 included):

curl -fsSL https://raw.githubusercontent.com/RevolutionLA/nextless/main/tools/install-deb.sh | sudo bash

The script ends by printing the two steps it will not do for you: nextless-get-models --zipformer --punctuation (models are deliberately not in the .deb) and fcitx5 -r -d. Before installing it stops if it cannot match the .deb against the release's sha256sums.txt — an unreachable digest file or an unlisted asset is what a tampered publish looks like, so that path needs an explicit opt-in: ... | sudo bash -s -- --allow-unverified. amd64 only; other architectures build the package themselves:

sudo apt install -y build-essential dpkg-dev debhelper git
git clone https://github.com/RevolutionLA/nextless.git
cd nextless
sudo apt build-dep ./          # the dependency list comes from debian/control, not from this README
dpkg-buildpackage -us -uc -b   # without -d, so that list is checked before building
sudo apt install ../fcitx5-nextless_*.deb && fcitx5 -r -d

1. Build

# Debian / Ubuntu
sudo apt install -y g++ meson ninja-build git \
  libfcitx5core-dev libfcitx5config-dev libfcitx5utils-dev fcitx5-modules-dev \
  libpulse-dev libebur128-dev libcurl4-openssl-dev libspeexdsp-dev libsoxr-dev
# Package names above verified with apt-cache on Ubuntu 26.04. There is no libfcitx5-dev
# meta package in the Ubuntu archive; Debian testing/sid names look the same but are
# unverified — please open an issue if they differ.
# Fedora: dnf install gcc-c++ meson ninja-build pkgconf-pkg-config fcitx5-devel libpulse-devel \
#         libebur128-devel libcurl-devel speexdsp-devel soxr-devel   (not CI-verified yet)

git clone https://github.com/RevolutionLA/nextless.git
cd nextless
meson setup build --prefix=/usr --buildtype=release
ninja -C build
sudo meson install -C build

meson.build sets warning_level=2 with werror=true, and CI builds with exactly that, so any new -Wall/-Wextra warning fails the build. Locally you can drop it with meson configure build -Dwerror=false while experimenting. -Wpedantic is deliberately not enabled: fcitx5's own FCITX_CONFIGURATION / FCITX_DECLARE_PRIVATE macros expand to an "extra ;" that GCC flags on the fcitx5 versions distros package (and the fcitx5 headers are pulled in as system includes for the same reason). That is not our bug to fix.

2. Load the add-on

The manifest installs to /usr/share/fcitx5/addon/nextless.conf with OnDemand=False, so restarting fcitx5 is enough — no need to add Nextless to an input-method list, it is a module, not a method.

fcitx5 -r -d          # replace the running instance; or log out and back in

3. Pick your key

fcitx5-configtool → Addons → Nextless → Push-to-talk key, or:

mkdir -p ~/.config/fcitx5/conf
cat > ~/.config/fcitx5/conf/nextless.conf <<'EOF'
[Hotkey]
0=Control_R

DefaultProvider=zipformer
EOF
fcitx5 -r -d

4. Get models (local backends)

nextless-get-models

That is the whole step. The helper (installed next to the addon; tools/get_models.sh in the repo if you want to run it before installing) detects the CPU architecture, shows the download size before fetching anything, and lets you pick Zipformer, FireRed, or both (--backend=...; with no terminal it asks for that flag instead of assuming you wanted the biggest option). It writes only inside ~/.local/share/nextless/, is safe to re-run — already-installed pieces are skipped — checks every archive against a pinned sha256 before extracting it, and only moves an archive into place after verifying the extracted directory names are the ones advanced.json expects, so a corrupt or substituted download leaves no half-extracted model behind. --dry-run prints the plan without touching anything, and --punctuation also fetches the optional ~62 MB ct-transformer model that gives the local backends ,。? (an interactive run asks; see Limitations) — it refuses to proceed if the pinned sherpa-onnx runtime stops shipping the punctuation binary, rather than installing a config that silently no-ops.

Manual path, if you would rather do it yourself:

mkdir -p ~/.local/share/nextless/sherpa-onnx ~/.local/share/nextless/models
cd /tmp

# sherpa-onnx runtime (shared build: copy bin/ *and* lib/ — the binaries use rpath $ORIGIN/../lib)
# aarch64: the asset name is ...-linux-aarch64-shared-cpu.tar.bz2 (plain -shared is a 404)
V=1.13.8
curl -LO "https://github.com/k2-fsa/sherpa-onnx/releases/download/v${V}/sherpa-onnx-v${V}-linux-x64-shared.tar.bz2"
tar xf "sherpa-onnx-v${V}-linux-x64-shared.tar.bz2"
cp -r "sherpa-onnx-v${V}-linux-x64-shared/"{bin,lib} ~/.local/share/nextless/sherpa-onnx/

# ASR models land under ~/.local/share/nextless/models/<archive-dir>/
M=https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models
mkdir -p ~/.local/share/nextless/models

# Zipformer bilingual zh-en (streaming transducer, ~360 MB of fp32 files)
curl -LO "$M/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2"
tar xf sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 -C ~/.local/share/nextless/models/

# FireRed ASR2 int8 (offline AED, ~1.2 GB, more accurate, slower)
curl -LO "$M/sherpa-onnx-fire-red-asr2-zh_en-int8-2026-02-26.tar.bz2"
tar xf sherpa-onnx-fire-red-asr2-zh_en-int8-2026-02-26.tar.bz2 -C ~/.local/share/nextless/models/

rm -f sherpa-onnx-*.tar.bz2

Both extractions create the directory names the built-in defaults expect, so there is nothing to rename. Different paths can be set in ~/.config/nextless/advanced.json.

If the runtime or a model file is missing when you dictate, the input panel says which piece is missing and tells you to run nextless-get-models — instead of a bare spawn failed / recognition failed. The exact path it looked for goes to the fcitx5 log.

Cloud backends need no models — just credentials:

mkdir -p ~/.config/nextless
echo '{"api_key":"<your Volcengine APP Key>","resource_id":"volc.seedasr.auc"}' > ~/.config/nextless/doubao.json
echo '{"api_key":"<sk-...>"}' > ~/.config/nextless/qwen.json
chmod 600 ~/.config/nextless/*.json

5. Optional: DeepFilterNet3 denoiser

speexdsp ships with the build, and it is enough for a quiet room. For a noisy one you can hand Nextless the deep-filter CLI from DeepFilterNet — it is deliberately not a build dependency, because it is a separate Rust binary carrying its own model:

mkdir -p ~/.local/share/nextless/bin
# whichever you have: a `pip install deepfilternet` binary on PATH, or the
# release asset - the x86_64 musl one is a single 36 MB static binary with the
# model compiled in (no tarball; `deep-filter --version` prints deep_filter 0.5.6),
# so `chmod +x` it and symlink that path directly instead of using command -v.
ln -s "$(command -v deep-filter)" ~/.local/share/nextless/bin/deep-filter

Any location works as long as you point at it, either with the path above or with NEXTLESS_DEEP_FILTER=/usr/bin/deep-filter in the fcitx5 environment. Turn it on with Shift+trigger and ↑/↓ (persisted to ~/.config/nextless/audio.json).

Nextless resamples to 48 kHz for the model and back to 16 kHz for the recogniser. Because the denoiser is an external process, it is treated as untrusted: if the binary is missing, exits with an error, wedges (killed after 5 s) or hands the audio back unchanged, that utterance falls back to speexdsp instead of losing your words — and after three failures in a row DeepFilterNet is switched off for the rest of the session. meson test covers all four cases.

What it costs, measured with the real binary on a 2022 i7-1260P (docs/benchmarks.md): ≈1.0–1.3 s per utterance of 5–10 s speech (RTF 0.13–0.16 across three runs, ~60 MB) versus single-digit milliseconds for speexdsp. The process is spawned per utterance, so that second lands between releasing the key and the first character, and the 5 s deadline stays clear up to well past 30 s of continuous speech. It is also not lossless in the way the bullet above promises: deep-filter hands back 30 ms less than it receives, so Nextless appends the last 30 ms of your raw audio to keep the utterance whole — those final 30 ms are un-denoised, but nothing is cut off (issue #61, fixed; before that the round trip dropped 69–97 ms off the end). speexdsp stays the default because it costs single-digit milliseconds rather than a second per utterance and never touches the audio length.

6. Rolling back

apt remove fcitx5-nextless does not touch fcitx5 itself, so your other input methods (typing-side IMEs, pinyin) stay exactly where they were. One caveat: if nothing else on the machine depends on fcitx5, a later apt autoremove can offer to take it away too - read the list before saying yes.

Installed from the .deb - the three paths named below are exactly what CI's .deb installs clean job asserts are gone after removal, so this is not a guess:

sudo apt remove fcitx5-nextless    # the addon .so, nextless-get-models and nextless.conf go
sudo apt purge fcitx5-nextless     # ...and the /etc/nextless defaults too
fcitx5 -r -d                       # reload without it

remove deliberately leaves the /etc/nextless/*.json conffiles behind (dpkg reports deinstall ok config-files), which is what you want if you mean to reinstall.

To go back to an older release instead - the reason install-deb.sh exists is that a new version can be the broken one:

sudo dpkg -i fcitx5-nextless_0.3.1-1_amd64.deb   # exactly this version, downgrade included

Installed with meson install - meson has no uninstall, but it wrote the manifest for you:

grep -v '^#' build/meson-logs/install-log.txt | sudo xargs -d '\n' rm -f --

Run that from the checkout and build directory you installed from: the log holds absolute paths recorded at install time, so if you reconfigured with a different --prefix since, it no longer describes your system. It removes files, not the empty directories they leave behind.

Neither route touches anything in your home, because those are your files, not the package's:

path what lives there size on a typical box
~/.config/nextless/ your settings, including any API keys ~30 KB
~/.local/share/nextless/models/ the downloaded ASR + punctuation models ~1.8 GB
~/.local/share/nextless/bin/deep-filter the optional denoiser, if you installed it ~35 MB
~/.config/autostart/org.fcitx.Fcitx5.desktop fcitx5 autostart, only if you added it 1 KB

Delete ~/.config/nextless/ before handing a machine over. Deleting the models directory is the only way to get the 1.8 GB back, and nextless-get-models will re-download whatever is missing.

Check what is actually loaded, because a stale install is otherwise invisible:

fcitx5-diagnose | grep -i nextless     # e.g. "Nextless 10.12.0"

If that prints an older version than the release you installed, the running addon is the old one - either the install step did not run, or fcitx5 was never restarted. That is how a machine already bumped to 0.3.x kept advertising Nextless 0.2.0.

Usage

Action Keys
Dictate hold your trigger key → speak → release
Switch ASR backend hold Shift + trigger, then ← / →
Switch denoiser hold Shift + trigger, then ↑ / ↓

While dictating, the input panel beside the cursor shows listening → processing audio → recognizing → text. Releasing the key returns control to fcitx5 immediately; recognition runs asynchronously.

Backends

Provider Type Disk Model Notes
zipformer local ~360 MB sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20 harness-measured: warm RTF ≈ 0.37, first result ≈ 2.3 s for ~5 s audio, peak RSS ~0.5 GB (i7-1260P; docs/benchmarks.md)
fire_red local ~1.2 GB sherpa-onnx-fire-red-asr2-zh_en-int8-2026-02-26 harness-measured: warm RTF ≈ 0.82, first result ≈ 6.1 s, peak RSS ~1.6 GB, clearly better on dialects and long sentences (docs/benchmarks.md)
doubao cloud — Doubao Streaming ASR 2.0 punctuation, ITN and server-side hotwords; needs an API key
qwen cloud — Qwen3-ASR-Flash needs an API key
mock test — — returns hello world; useful for verifying the key/capture path

The hotwords.json correction table applies to all of them — it rewrites the final text after whichever backend produced it. What is not wired is per-model biasing (sherpa-onnx's --hotword decode hook on Zipformer); the correction table currently covers proper nouns and homophones instead.

Both local backends spawn one sherpa-onnx process per utterance on purpose: no resident model server, no orphan process, no warm-up state to leak. (The systemd/ units in this repo are an experimental resident-server path and are not required.)

Configuration

Almost everything is set through the fcitx5 add-on config panel (Fcitx5 Configuration → Add-ons → Nextless → Configure): the push-to-talk key, default provider, activation/notification/debounce timing, denoiser, local model dirs & threads, punctuation toggle, and cloud API keys. Saving there writes the JSON files below in place (preserving any key the panel does not own) and pushes the new values into the running provider, so changes take effect the moment you save — no restart, no hand-editing. The files are still the single source of truth and safe to edit directly; on next load the panel reflects them.

File Purpose
~/.config/fcitx5/conf/nextless.conf trigger key ([Hotkey]), DefaultProvider (fcitx5's own store for the two native add-on options)
~/.config/nextless/nextless.json activation_msec (default 300), notification timeout, debounce
~/.config/nextless/audio.json denoise: none | speexdsp | deepfilter
NEXTLESS_DEEP_FILTER (env) path to a system deep-filter binary, overrides the bundled location
~/.config/nextless/advanced.json model dirs, num_threads, timeouts, LUFS target, VAD thresholds
~/.config/nextless/hotwords.json mishearing correction table {"what it heard": "what you meant"}, applied to every backend's final text
~/.config/nextless/doubao.json / qwen.json API credentials
~/.local/share/nextless/sounds/ optional replacements for the bundled activate / deactivate / switch sounds

meson install ships the config/*.json.example files (renamed to *.json) into the build's sysconfdir/nextless — /etc/nextless for distro builds (the PKGBUILD passes --sysconfdir=/etc, and prefix=/usr alone already resolves there), /usr/local/etc/nextless for a plain source install. The runtime reads that same directory, compiled in: user files win, and a missing user file is copied from the packaged directory on first read. The packaged hotwords.json is a placeholder template — keys starting with YOUR_ are dropped when it is parsed, so the copy can never rewrite real speech until you add entries yourself.

Development

meson setup build --buildtype=debug
ninja -C build
meson test -C build            # 21 unit tests: registry, config fallback, capture, queue, silence, cancellation, denoise, missing components, capture-dir sweep, punctuation, hotwords, get_models contract, CER/WER normaliser, panel JSON patcher, installer digest gate, denoise-benchmark row contract

Tests need a PulseAudio server (the capture tests open a real stream); on a headless runner pulseaudio --start plus pactl load-module module-null-sink is enough — that is what CI does.

  • docs/nextless/ — design notes: interaction model, ASR provider API, failure analysis.
  • docs/fcitx5/ — a short primer on the fcitx5 add-on and configuration system, since Nextless hooks key events at PreInputMethod phase.
  • FINDINGS.md — the measurement log behind the tuning numbers (buffer sizes, model latency, denoiser comparisons). Kept because it explains why defaults are what they are.
  • tools/ — standalone harnesses: record_test, calibrate_silence, tail_loss_test, uinput_key (inject a synthetic key hold so you can self-test push-to-talk without typing), gen_sounds.py (regenerate the bundled notification sounds).

Diagnostics (one JSON object per line, no audio and no recognised text) are opt-in:

meson configure build -Ddiagnostic_logging=true && ninja -C build
~/.local/share/nextless/diagnostic.log

Attribution

Nextless is a fork of vinput by xander-lin (MIT), which it thanks for the audio pipeline, provider abstraction and the ordering/queue design. The fork adds:

  • feat(hotkey): trigger key moved from a hardcoded CapsLock to an fcitx5 KeyListOption, default Right Ctrl, with /dev/uinput revert enabled only when the trigger is a locking key
  • rename to Nextless: add-on/library/config/data paths (~/.config/nextless, ~/.local/share/nextless)
  • fix(defaults): local ASR thread count derived from the CPU instead of a hardcoded 30, and the default Zipformer model directory now matches the real sherpa-onnx archive name

License: MIT — see LICENSE, which retains the upstream copyright notice.

Roadmap

Active work is tracked as GitHub Issues; the list below is the direction, not the queue.

Ordered by the goal, not by fun (review, 2026-10-05)

Each item has a finish line, so whoever picks it up knows when it is done.

Item Done when
1 CI is red: cloud_provider_queue fails in the debug job. The provider's error callback fires before the temp WAV is removed (the deletion lives in a scope guard), so the test's exists() check races cleanup — release passes by luck. Fixed in #10 — all four providers now delete the WAV before the callback (caught intermittently by CI's debug job; local reproduction under taskset -c 0 is probabilistic, ~5% on the old code). ✅ CI is green in both build types; the fix is stronger than this finish line — callback-then-cleanup is now illegal, so the assertion stays strict instead of tolerating it
2 /etc/nextless defaults are never installed: the config loader reads them and copies them into ~/.config/nextless/ on first use, but no install rule ships them, so every source install silently runs on compiled-in defaults. Fixed in #11 — meson installs the examples as *.json into the build's sysconfdir/nextless and compiles the same path into the loader, so install and read cannot drift; CI does a staged install and fails if any packaged example stops landing (six since hotwords.json). ✅ meson ships them — /etc/nextless for distro builds (--sysconfdir=/etc), /usr/local/etc/nextless for a plain source install, the same path the loader reads
3 First run without models or binaries: a missing sherpa-onnx runtime or model currently surfaces as Zipformer: spawn failed / recognition failed, with no hint of what to download. Fixed in #12 — providers pre-check the runtime and each model file and report the exact path; the panel shows "sherpa-onnx runtime missing" / "offline model missing" with the README pointer (test_missing_components drives all four paths against a fake $HOME). ✅ the input panel names the piece and points at the README's download section; the exact path it looked for goes to the fcitx5 log (and feeds the wizard below)
4 Real install and removal path: the .deb half is Fixed in #34 (packaging, dependency list, install/purge assertions in CI) and #38 (published on Releases with sha256sums.txt, tools/install-deb.sh one-command route, fail-closed digest check in #51); model fetch is nextless-get-models (#5). Rollback is now documented (README "Rolling back": apt remove vs purge, downgrading with dpkg -i, the meson install-log manifest, and fcitx5-diagnose as the version check), and remove/purge debris checks run in CI. Still open: a human dictating one sentence on a clean Ubuntu VM. AUR is #35. VM install ✅ in CI, dictate-on-VM ⏳ needs a person, apt remove leaves no debris ✅, rollback documented ✅
5 DeepFilterNet has never run for real: the tests drive it with stub binaries, so one-shot deep-filter cost per utterance is unmeasured. Measured 2026-10-11 with BACKENDS="deepfilter" tools/benchmark/run_bench.sh against deep_filter 0.5.6 — 7/7 utterances (4.7–10 s), 1.0–1.3 s each, RTF 0.13–0.16, 60 MB child RSS. The option stays, and the same run found and fixed issue #61 (the denoiser had been dropping 69–97 ms off the end of every take). ✅ docs/benchmarks.md carries the row plus the committed machine header and raw JSONL
6 Coexistence with the typing-side IME: document the supported combinations (wetype, fcitx5 pinyin) and the key-collision rules. a short doc plus one smoke test per combination

The longer-term list:

  • Local punctuation: integrate sherpa-onnx-offline-punctuation (ct-transformer)
  • Hotwords / custom phrases: ~/.config/nextless/hotwords.json correction table for every backend (per-model biasing still open)
  • First-run wizard that downloads the right sherpa-onnx build (x86_64 / aarch64) — nextless-get-models
  • .deb packaging: built in CI, published on GitHub Releases with sha256sums.txt, and installed by one command — Fixed in #34 (packaging) and #38 (publishing + tools/install-deb.sh)
  • An apt repository, so upgrades arrive through apt upgrade instead of re-running the installer
  • fcitx5-nextless in the AUR — tracked as #35
  • A/B benchmark harness publishing CER / latency / RTF / RSS per model (tools/benchmark/ + docs/benchmarks.md; CER rows still need verified transcripts — recording one's own corpus is documented)
  • Voice cloning / per-user correction learning — undecided, see the discussion thread first
  • CI: build × test matrix on GCC with -Dwerror=true, plus a diagnostics build
  • Silence is a no-op — no ASR error: empty result, and FireRed's <sil> never reaches the document
  • Notification sounds ship with the package (tools/gen_sounds.py regenerates them)
  • DeepFilterNet3 as an opt-in denoiser, with a bounded subprocess and a speexdsp fallback
  • Chinese documentation (README.zh.md)

About

Push-to-talk dictation for Linux, as a native fcitx5 add-on: hold any key (even Right Ctrl), speak, release, text lands at the cursor. Offline sherpa-onnx backends or cloud, no daemon. A Typeless-style alternative you can actually reconfigure.

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages