Skip to content

Repository files navigation

PushDictate — Push-to-Talk Dictation for Windows

Dictate into any window that has a text cursor — including the terminal. Hold Ctrl+Space, speak, release. The text appears where your cursor is.

License: MIT Platform Python

🇩🇪 Deutsche Anleitung → README.de.md

Published through Proving Lab — tools released together with the measurements behind them. See below.


Why this exists

Windows Speech Recognition and most dictation tools inject text through Windows' text-services layer. That layer is unavailable in console windows, in many Electron apps, and in anything running inside WSL. The moment you want to dictate a commit message, a prompt to a coding agent, or a shell command, the built-in dictation stops working.

PushDictate takes a different route: record → transcribe → clipboard → paste. A clipboard paste works in every window that accepts text. That single design decision is the whole point of the tool.

Where it works that others don't

Target Windows Dictation PushDictate
Windows Terminal, PowerShell, cmd
WSL / Ubuntu shell
Coding agents in the terminal
VS Code integrated terminal
SSH sessions
Word, Outlook, browsers

Verified in daily use on Windows 11, not in a systematic test series across Windows versions. If a row is wrong on your setup, please open an issue — it gets corrected here.


Use cases

Terminal and coding agents. Long prompts are miserable to type and trivial to say — speaking a multi-sentence instruction is markedly faster than typing it. (Not measured; treat it as experience, not a benchmark.)

Documents and email. Draft out loud, correct in writing. The vocabulary file keeps proper nouns intact.

Commit messages and issues. Speaking the why tends to produce longer, more useful messages than typing does.

Notes while your hands are busy. Reading, holding a cable, cooking — the hotkey is one chord away.


Install

Requirements: Windows 10 or 11, Python 3.10+ (64-bit), git, and an OpenAI API key of your own. No git? Use GitHub's Code -> Download ZIP and unpack it instead of the first line.

git clone https://github.com/Bubu89/pushdictate.git
cd pushdictate
py -m pip install -r requirements.txt

py -m pip rather than plain pip on purpose: on machines with several Python installations, pip often belongs to a different one than py, and the packages land where nothing will look for them.

Verify before you start anything:

py pushdictate.py --check

It reports packages, key and write access, and exits non-zero if the program would not start.

Setting it up without a window

The first start opens a small setup window. That is fine at a desk and useless in a script, over a remote session, or when an agent does the installing -- the window waits and nothing is reported. Every step therefore has a window-free path:

py pushdictate.py --set-key sk-...        # write the key into .env
echo sk-... | py pushdictate.py --set-key -   # or from standard input
py pushdictate.py --check --json          # machine-readable status
py pushdictate.py --no-setup              # fail instead of opening a window

Exit codes: 0 fine, 1 check failed, 2 bad invocation, 3 key missing and no window allowed. PUSHDICTATE_NO_SETUP=1 does the same as --no-setup.

A full unattended install is four lines:

git clone https://github.com/Bubu89/pushdictate.git && cd pushdictate
py -m pip install -r requirements.txt
py pushdictate.py --set-key "$OPENAI_API_KEY"
py pushdictate.py --check || exit 1

First start: the setup assistant

PushDictate ships without an API key and never will. Whisper transcription is billed to whoever owns the key, so it has to be yours.

On the first launch a setup window opens and walks you through it:

  1. A button opens https://platform.openai.com/api-keys in your browser
  2. You paste the key into the field
  3. Click Save and start — done

The assistant writes the .env file for you. No copying, no renaming, no editing config files by hand. The key stays on this machine and .env is gitignored.

The key is checked for plausibility before it is saved: an empty field or something that isn't an OpenAI key gets a clear message instead of a failure three steps later.

Cost: billed per minute of audio. Ten minutes a day is 300 minutes a month — multiply that by the per-minute rate on OpenAI's pricing page to get your figure. Current rates: https://openai.com/api/pricing/. No number is quoted here on purpose: a price frozen into a README goes stale silently.

Start it

wscript start_silent.vbs      # no console window — normal daily use
python pushdictate.py        # with console — for debugging

A coloured dot appears at the screen edge and an icon in the system tray. On the very first run a quick guide opens showing the keys and what the dot colours mean. Right-click the dot to reopen that guide at any time.


Use it

Action Key
Start recording Ctrl + Space
Stop and insert Space

The dot shows the state:

Colour Meaning
Red idle, ready
Yellow microphone opening — don't speak yet
Green recording (you heard the start tone)
Orange transcribing

Wait for green. Starting at yellow cuts off your first word.

Two low tones mean nothing was inserted — silent microphone, empty result, or a dictation queued for retry.


What you get

  • Push-to-talk, not always-on. The microphone opens when you ask. Nothing is recorded in between.
  • Works in the terminal. The reason the tool exists.
  • Custom vocabulary. vocab.txt (max. ~700 characters) is passed to Whisper as a hint so proper nouns come back spelled correctly. Applies immediately, no restart.
  • Media auto-pause. Music or video pauses while you dictate and resumes afterwards — including on every failure path, so nothing stays stuck.
  • Offline queue. If transcription fails on a network error, the audio goes to pending/ and is retried automatically; text lands in the clipboard.
  • Crash and sleep recovery. A scheduled task restarts the app if it dies; the audio stream is rebuilt after standby instead of going silently deaf.
  • Single instance. A named mutex stops a second copy stealing the hotkey.
  • History. The last 20 transcriptions in the tray menu.
  • Quick guide on demand. Right-click the dot for keys, dot colours and tips — no need to come back to this page.

Privacy

Audio leaves your machine. Recordings go to the OpenAI API for transcription, under your key and OpenAI's terms. No other server is involved: no telemetry, no analytics, no account with the author.

Everything else stays local and is gitignored:

File Contents
.env your API key
settings.json device and language choice
*.log, *.jsonl timing, errors and excerpts of your dictated text
pending/ audio awaiting retry
mute_state.json which application was playing sound during dictation
heartbeat.json timestamp of the last sign of life

If your audio must not reach a third party, use a local Whisper model instead — this tool is the wrong choice for that requirement.


Troubleshooting

Cloudflare WARP blocks transcription

If it fails with Connection error on /audio/transcriptions while Cloudflare WARP is running, WARP's Gateway is blocking DNS for api.openai.com — it is categorised as a tracker.

nslookup api.openai.com
# blocked if the address comes back 0.0.0.0 or ::

Allow api.openai.com and *.openai.com in both places:

  1. Split-Tunnel exclusions (routing)
  2. Cloudflare Gateway allow rule (DNS)

Either one alone is not enough.

The dot disappears behind other windows

Fixed in the current version — the overlay reasserts itself every three seconds. If it still happens, open an issue with your Windows build number.

The first word is missing

You started speaking at yellow. Wait for green and the start tone.


Contributing

Issues and pull requests welcome. Useful reports include your Windows and Python versions plus relevant lines from the log. Please strip transcribed text before pasting — those are your words, not debug data.


Proving Lab

PushDictate is published through provinglab.dev, where tools appear together with the measurements behind them rather than with marketing claims.

The rule there: no number without a measurement, no claim without a test. Where something hasn't been measured, that is stated rather than estimated — which is why the cost section above points at OpenAI's pricing page instead of freezing a figure that would quietly go stale.

Also from Proving Lab: Full Page PDF Snap — save any webpage as one high-resolution PDF, entirely on your device.


License

Code: MIT — see LICENSE. Use it, change it, ship it. No warranty. Documentation (README, CHANGELOG): CC BY 4.0. A software licence says nothing about prose, so this is spelled out rather than assumed.

Releases

Packages

Contributors

Languages