Skip to main content

Say "Hey Claude" and dispatch a Claude Code background agent — a fully local, on-device voice wake word for your Mac.

Project description

hey-claude

CI License: MIT Python 3.10–3.13 Platform: macOS (Apple Silicon)

Say "Hey Claude, fix the failing tests" out loud. A Claude Code agent spins up in the background and gets to work. Fully on-device — no cloud wake word, no API key to listen, no per-user signup.

hey-claude is an always-listening wake word for Claude Code on macOS. When it hears "hey claude," it captures what you say next, transcribes it locally, and dispatches it as a background agent with claude --bg. You keep talking; the agents keep stacking up in claude agents.

┌─────────┐   ┌───────────────┐   ┌──────────────┐   ┌──────────────────┐   ┌───────────────────┐
│   mic   │──▶│  openWakeWord │──▶│  endpoint by │──▶│   MLX Whisper    │──▶│ claude --bg       │
│ 16kHz   │   │ "hey claude"? │   │   silence    │   │ (transcribe cmd) │   │ "<your command>"  │
└─────────┘   └───────────────┘   └──────────────┘   └──────────────────┘   └───────────────────┘
   always-on    tiny on-device       VAD on the         Apple-Silicon GPU       detached agent,
   capture      classifier           command tail        local transcription    survives terminal

Everything before the final step stays on your machine. The only thing that leaves is the command you ask your agent to run — and that goes exactly where that agent already sends it.

The story behind it: I taught my Mac to launch coding agents when I say "Hey Claude" — the on-device pipeline, and how the wake words were trained on free cloud GPUs.


Work with us

hey-claude is built and maintained by Levelbrook Consulting, a senior software engineering practice. The same care that went into the on-device audio pipeline, the safe single-argv dispatch, and the trained-from-scratch wake words is the care we bring to client work: Ruby/Rails, Python, AWS, and AI tooling that has to survive production.

We take on contract work — corp-to-corp, remote, Pacific Time. If you're building agent-driven tooling, voice/ML features, or just need senior hands on a Rails or Python system, get in touch → or read how we work.


Requirements

hey-claude is macOS + Apple-Silicon only. It transcribes your speech locally with MLX Whisper, which runs on the Metal GPU of an Apple-Silicon chip — there's no Linux, Windows, or Intel-Mac build.

Need Why
macOS MLX + CoreAudio; no cross-platform build
Apple Silicon (M1 or newer) MLX Whisper runs on the Metal GPU
Python 3.10–3.13 ML wheels (MLX, onnxruntime)
Claude Code ≥ 2.1.139 the claude --bg agent it dispatches to (or point it at another agent)

You won't waste time finding out the hard way: hey-claude fails fast with a friendly message the moment you start it on an unsupported OS/CPU, or without MLX Whisper installed — before any model loads. Run hey-claude doctor any time for the full environment check.


Install

# PortAudio is the only system dependency
brew install portaudio

# recommended — installs the latest release in an isolated environment
pipx install git+https://github.com/tachyurgy/hey-claude@v0.3.0

Also on Homebrew and PyPI, but those can trail the newest tag — use the pinned git+…@v0.3.0 above for the latest:

brew install tachyurgy/tap/hey-claude   # Homebrew tap
pipx install hey-claude                  # or: pip install hey-claude  (PyPI)

Then run the first-run check, which tells you exactly what (if anything) is missing:

hey-claude doctor

Quickstart

It works the moment it's installed — a "hey claude" wake word ships in the box, so there's no training step to start:

hey-claude          # starts listening with the bundled "hey claude" model

Now say: "Hey Claude, add type hints to utils.py and run the tests." You'll hear a chime, then a confirmation, and a new row appears in claude agents.

Want a different trigger phrase? Several wake words ship bundled — switch with one command (see Bundled wake words):

hey-claude models             # list the bundled + installed models
hey-claude models use hey_computer

Microphone permission (the one macOS gotcha)

macOS grants microphone access to an app with a stable identity. There are two paths:

  • Running from Terminal: the first time you start hey-claude, macOS prompts for mic access for your terminal — click Allow. Done.

  • Running at login / headless: a bare CLI launched by launchd often can't raise that prompt. Build the bundled .app, which has its own identity macOS can grant:

    hey-claude app                 # builds ~/Applications/Hey Claude.app
    open "$HOME/Applications/Hey Claude.app"   # click Allow on the mic prompt
    

    Then add it to System Settings → General → Login Items to start at login.

Bundled wake words (mileage may vary)

Several openWakeWord models ship in the box, so you can pick a trigger phrase without training anything:

Model Say Notes
hey_claude (default) "hey claude" the phrase the tool is named for
okay_claude "okay claude" alternate Claude trigger
hey_computer "hey computer" Star-Trek style, distinct from any product name
hey_assistant "hey assistant" generic, agent-neutral
hey_agent "hey agent" generic, agent-neutral
hey-claude models                 # list bundled + installed, shows the active one
hey-claude models use hey_computer

Mileage may vary. These are small models trained on a modest synthetic-speech budget — they're speaker-independent, but real-world accuracy and the false-positive rate depend on your mic, room, and accent. If one fires too often, raise threshold; if it misses you, lower it. If none are reliable enough, train your own dialed-in model (next section).

Training your own wake word

openWakeWord models are trained on 100% synthetic speech — you never record your voice, and the result is speaker-independent. The fastest free path is the official Colab notebook:

hey-claude train        # opens the notebook + prints the steps

Set the phrase, pick a free T4 GPU, Run all (~10 min), download the .onnx, then hey-claude import-model <path>. See openWakeWord for details. There's a headless, scriptable version of the same recipe in training/train_wakewords.py.

No model at all? The fallback engine matches the phrase from a Whisper transcript with zero setup (slightly more CPU):

hey-claude config set engine whisper

Configuration

Everything is configurable two ways — the CLI, or by editing the config file directly. Config lives at ~/.config/hey-claude/config.toml (hey-claude config path):

hey-claude config show                       # print every setting
hey-claude config set threshold 0.6          # change one from the CLI
hey-claude config edit                       # open the TOML in $EDITOR

The file is plain TOML — hey-claude config edit just opens it; any key in the table below can be set there by hand and takes effect on next start.

Launch any agent — not just Claude

A wake doesn't have to run claude. It runs whatever agent you point it at. Switch with one command:

hey-claude agent list                # see the presets + which is active
hey-claude agent use codex           # now "hey claude, <task>" drives Codex
Preset What a heard command runs
claude-bg (default) claude --bg "<command>" — detached background agent, watch it in claude agents
claude-terminal a new Terminal running claude "<command>" so you can supervise/approve
claude-print claude -p "<command>" headless one-shot, output appended to the log
codex codex exec "<command>" — OpenAI Codex CLI
aider aider --yes --message "<command>"
opencode opencode run "<command>"
gemini gemini --prompt "<command>"

The external presets are honest starting points — third-party CLIs change their flags, so confirm yours and tune the template.

Fully custom — any command at all

Under the hood every preset just sets launch_template, which you can write yourself. It's a shell-style token list; placeholders are substituted per token, and the {command} token is always passed as a single argument, so a spoken command can never inject extra flags or shell metacharacters:

hey-claude config set launch_template 'my-agent --name {name} --prompt {command}'

Or in the file directly:

# ~/.config/hey-claude/config.toml
launch_template = 'claude --bg --name {name} --permission-mode acceptEdits --model opus {command}'

Placeholders: {command} {name} {permission_mode} {model} {claude_bin}. Leave launch_template empty to use the native claude launch modes (which keep full support for permission_mode, claude_model, and max_concurrent).

Configurable sounds

Each event plays a sound; override any of them with a file path or a macOS system-sound name (from /System/Library/Sounds), or none to silence one:

hey-claude config set sound_wake Hero            # system sound by name
hey-claude config set sound_dispatch ~/snd/go.wav
hey-claude config set sound_cancel none
hey-claude config set chime false                # disable all sounds

There are two listening cues, Siri-style: sound_wake when it starts listening and sound_endpoint the moment you stop talking and it begins transcribing.

Event Default When it plays
sound_wake Tink the wake word was detected — start talking
sound_endpoint Pop you stopped talking; capture ended, now transcribing
sound_dispatch Glass an agent was successfully dispatched
sound_cancel Funk wake fired but no command followed / you cancelled
sound_error Basso dispatch failed

Key settings

Key Default Notes
engine openwakeword or whisper (no model file needed)
wakeword_model "" bundled name (hey_claude…), a path, or empty for the default
wake_phrase hey claude also used by the whisper engine
threshold 0.5 openWakeWord score; higher = fewer false positives
whisper_model mlx-community/whisper-large-v3-turbo command transcription
launch_template "" run any agent; empty = native claude modes (see above)
permission_mode "" e.g. acceptEdits, plan for dispatched agents
claude_model "" model for dispatched agents
max_concurrent 0 0 = unlimited; else refuse to dispatch past N live bg sessions
confirm false require Enter before each dispatch

Run at login (launchd)

hey-claude install     # installs a launchd user agent (starts at login, restarts on crash)
hey-claude status
hey-claude stop / start / uninstall

Grant mic permission first (see above) or the service will receive silent audio.

Uninstalling

hey-claude keeps state in three places a package manager won't clean up: the launchd agent (~/Library/LaunchAgents), your config and trained wake-word models (~/.config/hey-claude), and the .app bundle (~/Applications). The teardown command removes all three:

hey-claude uninstall          # just the launchd agent
hey-claude uninstall --all    # + config, trained models, and the .app (asks first)

Run --all before removing the package, since brew/pipx/pip can't reach those paths. Two things it can't do for you: clear the macOS microphone grant (revoke it in System Settings → Privacy & Security → Microphone), and remove the package itself:

brew uninstall hey-claude   #  or:  pipx uninstall hey-claude  /  pip uninstall hey-claude

Safety

A voice trigger carries false-positive risk, so the defaults are conservative: the bg launch mode runs each agent in Claude Code's supervisor (with its normal permission prompts and per-session git worktree isolation). If you set a non-interactive permission mode like acceptEdits or bypassPermissions, an agent can act without you watching — scope it deliberately, and consider max_concurrent and confirm.

How it works

  1. Wake — openWakeWord runs a ~250 KB classifier over a frozen Google speech embedding on each 80 ms frame. A score above threshold (outside a short refractory window) is a wake. Lowest possible CPU for always-on listening.
  2. Endpoint — once woken (and after the wake cue plays), a small energy VAD records the command and stops after ~800 ms of trailing silence, keeping a short pre-roll so the first syllable isn't clipped. The moment it stops, the endpoint cue plays so you know it heard you and is now thinking.
  3. Transcribe — the command audio goes to MLX Whisper (Metal GPU), which returns text in well under a second on Apple Silicon.
  4. Dispatch — the text is passed verbatim as a single argument to claude --bg, which hands it to Claude Code's background-session supervisor.

Documentation

Development

git clone https://github.com/tachyurgy/hey-claude
cd hey-claude
brew install portaudio
python3.12 -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"
pytest

License

MIT. See LICENSE.


Built and maintained by Levelbrook Consulting — a senior software engineering practice (Rails · Python · AWS · AI tooling). Available for contract work, corp-to-corp. Get in touch →

Project details


Download files

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

Source Distribution

hey_claude-0.3.0.tar.gz (7.6 MB view details)

Uploaded Source

Built Distribution

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

hey_claude-0.3.0-py3-none-any.whl (7.6 MB view details)

Uploaded Python 3

File details

Details for the file hey_claude-0.3.0.tar.gz.

File metadata

  • Download URL: hey_claude-0.3.0.tar.gz
  • Upload date:
  • Size: 7.6 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for hey_claude-0.3.0.tar.gz
Algorithm Hash digest
SHA256 3cbcf35e3be6220765209e14bd9224f5da7126d1fc2c3471e7e9e7707468b453
MD5 15d189460099b3195d935b9778661360
BLAKE2b-256 ca003d13169622ce8307bfc705d63e085082b427a3b7209fc1d9d5210d382042

See more details on using hashes here.

File details

Details for the file hey_claude-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: hey_claude-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 7.6 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.5

File hashes

Hashes for hey_claude-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0aea58a8cbba09a496fa945b2f16e7a26e1d27f618841791364315b58d83fcf0
MD5 00514484fafff5d655650d83e83bd63f
BLAKE2b-256 6ec2b7fe95050878603fa9f8568214f539f5f8eca9bddc0102f727c511717085

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page