A floating stop button for macOS say speech output.
say is a great built-in TTS command, but once it starts talking there is no
built-in way to shut it up from the GUI. saystop runs say and shows a small,
always-on-top panel near the top of your screen for as long as speech is
playing. Click Stop or close the panel to kill the speech immediately, or
click Pause to suspend and resume it. The panel never steals keyboard
focus.
It is especially handy when scripts, agents, or voice-output rules call say
unattended and you want a kill switch.
- macOS 12.0+ (Apple Silicon and Intel, universal binary)
- No other dependencies: it wraps
/usr/bin/say
brew install DevArtsLab/tap/saystopcurl -fsSL https://raw.githubusercontent.com/DevArtsLab/saystop/main/install.sh | shThe release binary is unsigned, so the installer clears the quarantine
attribute after verifying the SHA-256 checksum. Options via env vars:
SAYSTOP_VERSION, SAYSTOP_PREFIX, SAYSTOP_SHIM=1.
git clone https://github.com/DevArtsLab/saystop.git
cd saystop
make # universal binary in build/saystop
make install # copies to /opt/homebrew/bin, /usr/local/bin, or ~/.local/binsaystop "Hello, I have a stop button now"All arguments are passed through to say, so -v, -f, -r, etc. all work.
Invocations that produce no audible speech (-o, -v ?) skip the panel.
saystop --install-shimThis writes a tiny say shell shim into the first writable PATH directory that
precedes /usr/bin (usually /opt/homebrew/bin or /usr/local/bin). After
that, plain say "..." from any terminal, script, or agent pops the stop
button. It never overwrites an existing say file that is not a saystop shim.
saystop --shim-status # check
saystop --uninstall-shim # remove
/usr/bin/say "..." # always bypasses the shimsaystop --mute # silence all speech until unmuted
saystop --unmute # re-enable
saystop --mute-status # checkMuting drops a flag file at ~/.config/saystop/muted. Both saystop
invocations and shimmed say calls check it and exit silently. Non-speaking
invocations (-o file output) still work while muted, and /usr/bin/say
always bypasses the mute. --mute/--unmute also post a macOS notification;
append --quiet to skip it.
extras/Stop Speaking.workflow is a macOS Quick Action that runs
killall say. extras/Toggle Speech.workflow toggles the mute flag and posts
a notification confirming the new state. Install either or both for Services
menu entries plus assignable global hotkeys:
cp -R "extras/Stop Speaking.workflow" ~/Library/Services/
cp -R "extras/Toggle Speech.workflow" ~/Library/Services/
/System/Library/CoreServices/pbs -flushThen find them under any app's App Name > Services menu, or bind hotkeys in System Settings > Keyboard > Keyboard Shortcuts > Services.
For plain speech (text plus -v, -r, -f), saystop speaks through
AVSpeechSynthesizer and displays a non-activating floating NSPanel. The
panel closes itself when speech ends. Clicking Stop or closing the window
stops speech immediately; Pause suspends at the next word boundary and
becomes Resume. Invocations saystop cannot speak itself run as a
/usr/bin/say child process with a Stop-only panel, and non-speaking
invocations (-o, -v ?) are exec'd with no panel at all.
saystop --uninstall-shim
brew uninstall saystop # or: rm the saystop binary from your bin dirMIT