Skip to main content

tacheles

Dictation that speaks your stack. Push a key, talk, push again. The text lands where you were typing. For developers who would explain the whole thing to their coding agent if writing it out were not such an effort, and who are tired of transcription that mangles every identifier.

Tacheles reden is German, from the Yiddish תכלית takhlis, "purpose". It means talking plainly and getting to the point. Pronounced TAH-khe-les.


It knows your vocabulary

General speech models have never heard of your stack. tacheles has.

Correcting technical vocabulary

fast APIFastAPI. red isRedis. post gres SQLPostgreSQL. None of that is guesswork. It sends your vocabulary with every request, then corrects what comes back against that same list.

It learns the rest

The jargon no model could guess, you teach once. It sticks, permanently, and it is applied deterministically, not re-guessed each time.

tacheles fix 'P and PM' pnpm      # said once, corrected forever
tacheles review                   # confirm what it was unsure about

It also ships with corrections for manglings that no vocabulary hint fixes, because what the model heard is nothing like the right word: P and PM for pnpm, Griffana for Grafana, item potent for idempotent, cloud code for Claude Code. Those work on a fresh install, and your own always take precedence.

Every automatic correction is inspectable, and anything it is not certain about is suggested rather than silently applied. It never rewrites a real word behind your back.

It speaks more than one language, mid-sentence

Three languages in one sentence

English, German and Russian in a single breath, each kept in its own script, with no setting required. Declaring the languages you mix is supported and harmless, but in testing here it made no measurable difference: Russian came back in correct Cyrillic even when only English was declared.

It can run entirely on your machine

Point it at a local whisper.cpp, faster-whisper or Speaches server and no audio leaves your computer at all. The vocabulary and learning layers work exactly the same, and they matter more, because small local models are worse at rare terms rather than better.

[transcription]
backend = "local"

See docs/LOCAL.md for setup, and for an honest account of what you trade away.


Why not just use the dictation built into your editor?

Because it was not built for this. Dictation bundled into AI tools tends to transcribe everything: every "um", every false start, every repeated word. You get a wall of text and then have to edit it. And none of it knows what pnpm is.

tacheles takes the opposite position on both counts:

Built-in dictation tacheles
Filler words Transcribed verbatim Dropped, while keeping how you actually talk
Your jargon Guessed phonetically Sent as vocabulary, then corrected against it
Getting it wrong twice Every time Teach it once, never again
Mixed languages Usually one language wins Each kept in its own script
Where your audio goes Their servers OpenAI, or nowhere but your own machine

Why this exists

The bottleneck in working with coding agents is not typing speed. It is the small, constant reluctance to explain something properly.

You know the shape of what you want. Writing it out means four paragraphs of context: what the code does now, what it should do instead, which edge case bit you last time, what not to touch. Every one of those paragraphs has a cost, and when you are tired or in the middle of something else you pay it by writing less. You send three lines instead of thirty, the agent guesses at the rest, and you spend the afternoon correcting work that would have been right if you had just said the whole thing.

Speaking it costs almost nothing. So you say the whole thing, first time.

That is the actual win, and it is not about words per minute. Building PolySimulator, a paper-trading platform for Polymarket prediction markets, we run a lot of agents at once. The scarce resource is not keystrokes, it is attention: holding the architecture in your head, reading what came back, judging whether it is right, deciding what happens next. Composing precise English is a tax on exactly that attention. Paying it ten times a day leaves less of you for the parts that actually need a person.

Which is what the name is about. Tacheles reden means saying the thing plainly and getting on with it, with no throat-clearing and no working up to it. Say what you want; let the work start.

There was one thing standing in the way on Linux. Dictation here is bad. Browser microphone buttons are flaky, desktop apps cannot type into other apps on Wayland, and local models either want a GPU or mangle every technical term. Every tool that got this right turned out to be macOS-only, which I discovered the hard way while looking for a name: the good ones were already taken by macOS dictation apps.

And general transcription mangles developer speech specifically. It writes "P and PM" for pnpm, "fast API" for FastAPI, "red is" for Redis, and turns a colleague's name into something unrecognisable. When half your sentences carry identifiers, that is not a small annoyance, because fixing the transcript costs more than typing it would have. The friction comes straight back, just somewhere else.

So tacheles sends your vocabulary with every request, corrects what comes back against that same vocabulary, and permanently learns whatever you tell it once. The point is that dictating stays cheaper than typing all the way through, including the proofreading.

It is ~3,700 lines of Python that shells out to tools you already have (pw-record, wl-copy, notify-send) and uses OpenAI, or a local Whisper server, for the hard part.

Tacheles, from the Yiddish תכלית takhlis, "purpose", is the German idiom for talking plainly and getting to the point. Tacheles reden. Pronounced TAH-khe-les.

Install

git clone https://github.com/ErikEremenko/tacheles && cd tacheles
./install.sh

install.sh creates a private virtualenv, installs tacheles into it, and registers the GNOME shortcuts. Then give it a key and check the setup:

tacheles auth login      # stored in the GNOME keyring, or a 0600 file
tacheles doctor          # explains anything that will not work, and why

Your key never leaves your machine except in requests to OpenAI. Nobody involved in this project receives it, and docs/CREDENTIALS.md shows you how to verify that rather than take it on trust. It also covers using a secret manager (Bitwarden Secrets Manager, pass, 1Password, gopass) instead of storing the key at all.

tacheles doctor is the first thing to run whenever something misbehaves. It reports your recorder, credentials, model, delivery method, keyboard layout and hotkeys in one screen.

How the text reaches your app

This is the genuinely hard part on Wayland, which deliberately stops one app synthesising input into another. tacheles has three modes, and always writes the clipboard first so a failure downstream can never lose your transcript.

Mode What it does Setup Notes
clipboard (default) Copies the text; you press Ctrl+V none Always works
paste Copies, then synthesises Ctrl+V tacheles setup-paste Needs ydotool on GNOME
type Types the text keystroke by keystroke tacheles setup-paste US layout only, see below

A warning about type mode. ydotool emits raw US keycodes and ignores your active XKB layout. If you have a non-US layout configured, typed text comes out mangled. tacheles detects this and refuses rather than producing garbage. paste mode is unaffected, because only the Ctrl+V chord travels through the keyboard, and the text itself goes via the clipboard.

Seeing what it is doing

GNOME hides notification banners after a few seconds whatever expire-timeout you ask for, so a notification cannot tell you a recording is still running. The optional top-bar indicator can:

tacheles install-indicator     # then log out and back in

It shows the state in the panel: microphone when idle, a red dot and a running timer while recording, an amber icon while transcribing, a green tick when the text is ready. Clicking it opens your recent transcripts; clicking one copies it again, and a middle click on the icon copies the newest without opening anything.

That list matters more than it sounds. wl-copy holds the clipboard in a child process, so a session restart empties the clipboard even though the transcript was produced correctly. Nothing is ever lost, because it is in the history either way:

tacheles last --copy       # put the most recent transcript back on the clipboard
tacheles last -n 5         # or look at the last five

Audio cues are on by default. tacheles sounds plays each one, and they are configurable under [notify].

Vocabulary profiles

Profiles live in ~/.config/tacheles/profiles/*.toml and shadow the bundled ones.

name = "coding"
language = "en"
prompt = """
Technical software-development dictation. Keep technical terms in canonical casing.
"""
keywords = ["pnpm", "FastAPI", "PostgreSQL", "Grafana", "idempotent"]

inherits = "coding" merges another profile's keywords, so a profile of your own project's names can extend the general technical vocabulary rather than repeat it.

tacheles profiles              # list them
tacheles toggle -p coding      # use one for a single dictation

Safety and cost

  • Auto-stop. A forgotten recording stops itself after audio.max_seconds (default 5 minutes) and transcribes what it captured. Set max_seconds_action = "discard" to spend nothing instead, or max_seconds = 0 to disable.
  • Silence guard. An all-silent recording is never uploaded, so a muted mic costs nothing.
  • Spend tracking. tacheles history --totals shows minutes dictated and estimated cost.

Commands

tacheles toggle [-p PROFILE]   start, or stop and transcribe
tacheles cancel                discard the current recording
tacheles status                is it recording?
tacheles transcribe FILE       transcribe an existing audio file
tacheles doctor                check everything
tacheles models                transcription models your key can use
tacheles history [--totals]    recent transcripts and spend
tacheles config edit           edit the config
tacheles install-hotkeys       register GNOME shortcuts
tacheles uninstall-hotkeys     remove them and restore GNOME's originals

Hotkeys and your input-source switcher

GNOME ships Super+Space bound to switch input source. Rather than leaving you without a layout switcher, tacheles install-hotkeys moves that binding to the Windows-style Shift+Alt and records the original. tacheles uninstall-hotkeys puts it back exactly as it was.

Shortcuts are appended to your existing custom shortcuts, never overwritten.

Support

The part that does the work is plain Linux. Recording goes through pw-record, parecord or arecord, so PipeWire, PulseAudio and ALSA are all covered; the clipboard through wl-copy, xclip or xsel, so Wayland and X11 both are; notifications through notify-send, which is a freedesktop standard. Nothing in the recording, transcription or correction path needs GNOME, and that is checked rather than assumed: the core runs in an environment stripped of D-Bus, DISPLAY and gsettings.

What GNOME adds is convenience, and each piece degrades on its own when it is absent.

Status
Recording, transcription, vocabulary, corrections, clipboard Works anywhere. Verified with no GNOME present
GNOME / Wayland Everything, including hotkey installation and the top-bar indicator. Used daily by the author
GNOME / X11 Should work; xclip and xdotool cover clipboard and pasting. Not tested
KDE, sway, Hyprland, others Core works; bind the commands yourself, see docs/HOTKEYS.md. Not tested
Automatic paste-chord selection GNOME only, because the extension is what can see the focused window. Falls back to the configured chord elsewhere

"Not tested" means exactly that. It is expected to work and nobody has confirmed it. If you run one of those, an issue saying so either way is genuinely useful.

Configuration

tacheles config init writes a fully commented file with every default. Highlights:

[general]
profile = "coding"        # default vocabulary profile
output_mode = "auto"      # auto | clipboard | paste | type

[openai]
model = "gpt-transcribe"  # $0.0045/min; falls back if unavailable to your key

[audio]
max_seconds = 300         # auto-stop safety limit
silence_rms = 30          # below this, do not bother uploading

[postprocess]
enabled = false           # optional second pass to tidy punctuation

How this was built

Written by Erik Eremenko, largely with Claude Code driving the keyboard. I am stating that plainly because it is true and because you can see it in the commit history anyway. A project about dictating to AI agents that hid its own use of them would be a bit ridiculous.

What that means for you as a user or contributor: every design decision here was tested against this machine rather than assumed, and the awkward findings are documented rather than smoothed over: the ~100 ms clipboard wait, the refusal to type on non-US layouts, the German compound word that silently inverted meaning. Where something is unverified, it says so.

If you find something that was clearly never exercised, open an issue. That is the failure mode worth watching for, and I would rather hear about it.

License

MIT. See LICENSE. Contributions welcome; see CONTRIBUTING.md.

Download files

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

Source Distribution

tacheles-0.1.0.tar.gz (400.9 kB view details)

Uploaded Source

Built Distribution

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

tacheles-0.1.0-py3-none-any.whl (75.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: tacheles-0.1.0.tar.gz
  • Upload date:
  • Size: 400.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for tacheles-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dbefbec024f91a31ac08c12205f0a5b60a7888244210c0156f44a794864b5935
MD5 e8e2412c1fd19d2436062aef676a313a
BLAKE2b-256 891a4da875719503ccddb82d4c9c8f81728505e8ee38156b649f22af7a750c6b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: tacheles-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 75.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.7

File hashes

Hashes for tacheles-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3afdfe50c11c336fdaab7267fe78e432299143c9d093588c639e5d6def9c6e83
MD5 cf322b5518a8f814298e30a77e329cef
BLAKE2b-256 14363dbcbdffc5c5e3705aa56b6f78be4987bd5ba57ec0b6c318dd2cf3c850e9

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page