Talon Voice Control
Talon Voice Control Setup
Custom voice control configuration for macOS using Talon.
Source code: github.com/ejfox/dotfiles/talon-overrides
Overview
Voice-driven workflow for terminal (Ghostty + tmux), macOS app switching, and window management. All config lives in ~/.dotfiles/talon-overrides/ (symlinked to ~/.talon/user/ejfox-overrides/).
The TTS feedback script (claude-say) lives at github.com/ejfox/dotfiles/bin/claude-say and the symlink setup is in sync-dotfiles.sh.
Architecture
- Community scripts:
~/.talon/user/community/(talonhub/community clone) - Custom overrides:
~/.talon/user/ejfox-overrides/(dotfiles-tracked) - Speech engine: Conformer (Talon's built-in, downloaded via Talon menu)
Files
| File | Purpose | Source |
|---|---|---|
settings.talon |
Global settings (tmux prefix, subtitle config) | github |
custom_keys.talon |
Mode switching (cmd/talk) and Enter aliases | github |
tmux.talon |
~30 tmux voice commands (windows, panes, sessions) | github |
terminal_commands.talon |
Ghostty-specific: line editing, nav, git, launchers | github |
macos_nav.talon |
App switching, Rectangle Pro, Spaces, general macOS | github |
ghostty.talon |
Ghostty terminal detection (too new for community) | github |
cursor.talon |
Cursor IDE detection | github |
apps.py |
App definitions for newer apps not in community | github |
nato_alphabet.py |
NATO phonetic alphabet override (Python Context) | github |
mode_line.py |
2px colored bar at screen bottom showing current mode | github |
ejfox_subtitles.py |
Right-aligned subtitles below sketchybar | github |
vocabulary.talon-list |
~250 custom vocabulary terms | github |
Key Design Decisions
NATO Alphabet via Python Override
The community .talon-list file takes priority over user overrides. The only reliable way to replace the letter list is a Python Context override.
tmux Prefix Timing
tmux needs sleep(100ms) between the prefix key and the command key. Without it, the command fires before tmux registers the prefix.
Anchored Rules for Dictation Mode
Commands must use ^...$ anchors to work in dictation mode. Without anchors, the prose capture engine swallows the command and types it as text.
Custom Subtitles
Community subtitles plugin is center-aligned with no horizontal position setting. Custom ejfox_subtitles.py renders right-aligned text below sketchybar (38px from top).
Mode Line
2px colored line at screen bottom replacing default circle indicator:
- Pink (
#e60067): Command mode - Teal (
#6eedf7): Dictation mode - Muted (
#735865): Sleep mode
Complete Voice Command Reference
Mode Switching
Source: custom_keys.talon
| Say | Does |
|---|---|
| cmd | Switch to command mode |
| talk | Switch to dictation mode |
| go ahead / go head / send it | Press Enter |
tmux Windows
Source: tmux.talon
| Say | Does |
|---|---|
| mux one thru mux nine | Jump to window N |
| mux next / mux previous | Next/prev window |
| mux last | Last used window |
| mux new | New window |
| mux rename | Rename window |
| mux close | Close window |
| mux alert / mux newest | Jump to window with bell |
| mux workspace | Session/window picker |
tmux Panes
Source: tmux.talon
| Say | Does |
|---|---|
| mux left / right / up / down | Navigate panes |
| mux move left / right / up / down | Move pane in direction |
| mux next pane | Cycle panes |
| mux split right / down | Split pane |
| mux pane right / down / left / up | Split + auto-focus new pane |
| mux close pane | Close current pane |
| mux zoom | Toggle pane fullscreen |
| mux sessions | Session picker |
| mux scroll | Enter scroll mode |
| mux detach | Detach from session |
Terminal Launchers
Source: terminal_commands.talon
| Say | Does |
|---|---|
| clear | Clear terminal |
| edit / run neovim | Open nvim |
| lazy / run lazygit | Open lazygit |
| files / run yazi | Open yazi file manager |
| run btop | Open btop system monitor |
| run claude | Launch Claude Code |
| run claude skip | Launch Claude Code (skip hooks) |
| run codex | Launch Codex CLI |
| tips | Search tips with fzf |
| refresh | Source .zshrc |
Terminal Line Editing
Source: terminal_commands.talon
| Say | Does |
|---|---|
| wipe | Clear line (ctrl-u) |
| wipe word | Delete last word (ctrl-w) |
| cancel / nope / bail | Ctrl-C |
| again | Re-run last command (up + enter) |
Directory Navigation
Source: terminal_commands.talon
| Say | Does |
|---|---|
| go home | cd ~
|
| go code | cd ~/code
|
| go smallweb | cd ~/smallweb
|
| go clients | cd ~/clients
|
| go dotfiles | cd ~/.dotfiles
|
| go back | cd -
|
| go up | cd ..
|
| go paperclip | cd ~/code/paperclip
|
| go website | cd ~/code/website
|
| go coach | cd ~/code/coach
|
| go connectology | cd ~/code/connectology
|
| go vulpes | cd ~/code/vulpes-theme-lab
|
| go subway | cd ~/code/subway-builder
|
| go newswell | cd ~/code/newswell
|
| go gem | cd ~/code/gem
|
| go ddhq | cd ~/code/ddhq
|
| list files | ls
|
| list all | ls -la
|
Git Commands
Source: terminal_commands.talon
| Say | Does |
|---|---|
| git status | git status
|
| git push | git push
|
| git pull | git pull
|
| git log | git log --oneline
|
| git diff | git diff
|
| git add all | git add -A
|
| git stash | git stash
|
| git pop | git stash pop
|
Dev Commands
Source: terminal_commands.talon
| Say | Does |
|---|---|
| dev server | npm run dev
|
| yarn dev | yarn dev
|
| install | npm install
|
| connect VPS / connect | SSH to VPS |
| note <text> | Quick note to Obsidian daily |
App Switching
Source: macos_nav.talon
open ghosty, open chrome, open safari, open messages, open slack, open discord, open signal, open obsidian, open claude, open figma, open finder, open music, open OBS
Window Management (Rectangle Pro)
Source: macos_nav.talon
| Say | Does |
|---|---|
| snap left / snap right | Half screen left/right |
| snap half left / snap half right | Half screen (alias) |
| snap up / snap full | Fullscreen |
| snap down / snap bottom | Bottom half |
| window bigger | Grow window (cmd-ctrl-=) |
| window smaller | Shrink window (cmd-ctrl--) |
| window grid | Grid overlay (F1) |
| window cascade | Cascade windows (F12) |
Spaces
Source: macos_nav.talon
| Say | Does |
|---|---|
| space left | Switch to left Space (cmd-ctrl-left) |
| space right | Switch to right Space (cmd-ctrl-right) |
General macOS
Source: macos_nav.talon
| Say | Does |
|---|---|
| hide this | Hide current app (cmd-h) |
| hide others | Hide other apps (cmd-alt-h) |
| quit this | Quit app (cmd-q) |
| close window | Close window (cmd-w) |
| close tab | Close tab (cmd-w) |
| new tab | New tab (cmd-t) |
| new window | New window (cmd-n) |
| next tab / previous tab | Switch tabs (cmd-shift-]/[) |
| spotlight | Spotlight search (cmd-space) |
| undo / redo | Undo/redo (cmd-z / cmd-shift-z) |
| save | Save (cmd-s) |
| select all | Select all (cmd-a) |
| copy / paste / cut | Clipboard (cmd-c/v/x) |
| find | Find (cmd-f) |
| screenshot | Screenshot region (cmd-shift-4) |
| screen record | Screen recording (cmd-shift-5) |
claude-say (TTS)
Script at ~/bin/claude-say lets Claude Code speak responses aloud:
- Mutes mic input before speaking (prevents Talon feedback loop)
- Restores mic volume after speaking
- Prefixes with tmux window number for voice navigation
- Uses macOS
say -v Samantha
Lessons Learned
.talon-listoverrides don't reliably replace community lists — use Python Context overrides- Ghostty is too new for community scripts — need custom app detection
sleep(100ms)between tmux prefix and command key is essential^...$anchors required for commands to work in dictation mode- Built-in Talon subtitle controlled by
speech._subtitlessetting (undocumented) - Community subtitles are a separate plugin with their own settings
- macOS
saytriggers Talon — must mute mic first viaclaude-saywrapper