Run this:
chimeThat’s the sound of a command being done. Drop it at the end of anything you were about to stare at — a build, a backup, a brew upgrade, a twenty-minute encode — and walk away.
On macOS it plays a short completion chime. Add --notify (or --message)
and it also pops a Notification Center banner, so you see it even if the
terminal is buried.
chime --message "Hello, world!"Chime is just a command. The shell decides whether it runs. That one choice is the whole product.
| You write | When it rings | What it means |
|---|---|---|
cmd && chime |
Only if cmd succeeded |
“You’re clear.” |
cmd; chime |
Always, after cmd |
“Come look.” |
cmd | chime |
As output arrives, then at the end | “I’m listening.” |
Success is the news. Silence means something still needs you.
make -j && chime
pytest && chime --message "Tests passed"
ffmpeg -i talk.mov talk.mp4 && chime --message "Export ready"
brew upgrade && chime --notify
ssh build-box './deploy.sh' && chime --message "Deployed"false && chime stays quiet. That’s the point.
You left. You want the doorbell, not a verdict. Look at the terminal to see how it went.
rsync -a ~/Projects /Volumes/Backup ; chime --message "Backup finished"
make -j ; chime --notify
long-job ; chime --message "Done — check the exit"false; chime still rings.
A pipe puts Chime inside the command. Stdout still prints exactly as before. Each new line gets a short tick; when the stream ends you get the longer complete sound.
./slow-job | chime
make -j 2>&1 | chime
docker pull ghcr.io/org/huge-image | chime
for i in 5 4 3 2 1; do echo "$i"; sleep 1; done | chime --message "GO"A tick is progress. Completion means the pipe closed — not that the producer
succeeded. cmd | chime always runs Chime.
Progress bars that rewrite the same line with \r do not tick. Empty input
still plays the complete sound.
Sounds are enough at your desk. For banners, run this once, then --notify
or --message:
chime --setup-notifications
sleep 25m && chime --message "Tea is ready"
echo "TIME TO GOOOO" | chime --notify--message sets the text and turns notifications on, so you never write a
message nobody will see. On a pipe without --message, the banner is the last
nonempty line of output — that’s why the example above shows TIME TO GOOOO
instead of a generic “Complete.”
{ echo "compiling…"; sleep 2; echo "Build succeeded"; } | chime --notify
{ echo "compiling…"; sleep 2; echo "Build succeeded"; } | chime --message "Ship it"User-local — no administrator privileges. You need macOS 13+, Xcode command-line tools, CMake 3.20+, and Apple Clang.
cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build build -j
cmake --install build --prefix ~/.local
mkdir -p ~/Applications
cp -R ~/.local/libexec/Chime.app ~/Applications/ # or: cp -R build/Chime.app ~/Applications/
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
chime --setup-notifications # only needed for bannersAllow the macOS prompt and confirm Chime in System Settings → Notifications. Sound-only use works without the helper app.
Keep Chime.app at ~/Applications. Notification permission follows that
bundle; moving or re-signing it can look like a new app. The build ad-hoc
signs it — a stable Apple Development identity avoids the prompt returning
after every rebuild.
Universal binary: -DCHIME_UNIVERSAL=ON.
# uninstall
rm -f ~/.local/bin/chime
rm -rf ~/.local/libexec/Chime.app ~/.local/share/chime
rm -rf ~/Applications/Chime.app
rm -rf ~/Library/Application\ Support/Chime
rm -f ~/.chime.json # optionalYou can also remove Chime from System Settings → Notifications.
chime --help is the full list. These are the ones worth knowing:
chime --volume 0.3 # quieter; never touches system volume
chime --no-sound --message "Meeting in 5" # banner only
printf 'secret\n' | chime --no-passthrough # eat the pipe, print nothing
yes | head -n 200 | chime --sound-cooldown-ms 250 # don’t machine-gun ticks
make -j 2>&1 | chime --line-sound ~/Sounds/tick.wav
chime --title Kitchen --message "Tea is ready"
chime --notify-on all # banners on every line (usually too much)--title changes the banner heading. Custom --line-sound and
--completion-sound take a built-in name (tick, complete) or a path to
a .wav / .aiff.
Optional ~/.chime.json. Missing is normal — the defaults are enough.
chime --init-config # write ~/.chime.json (refuses to overwrite)
chime --print-config # show what will actually run
chime --no-config # ignore the file for this invocationCLI flags always win. A quiet, notify-on-by-default setup looks like examples/chime.json:
{
"version": 1,
"sound": {
"volume": 0.4,
"cooldown_ms": 250
},
"notifications": {
"enabled": true,
"events": "completion"
}
}Omitted keys keep their defaults. Nested objects merge.
A small macOS 13+ CLI in C++17 with a little Objective-C++. NSSound plays
the bundled tick and complete tones (or your own files). Banners go through
Notification Center via a tiny accessory app, Chime.app, that the CLI talks
to over a local socket. There is no background daemon.
Piped bytes are forwarded unchanged. Chime works in any macOS terminal.
MIT. Copyright 2026 Daxliar.
No third-party runtime libraries. Sounds (tick.wav, complete.wav) and the
helper icon are generated at build time (tools/gen_sounds.c,
tools/gen_icon.mm). docs/icon.png is a snapshot of that icon. Audio and
banners use Apple’s Foundation, AppKit, and UserNotifications.