CLI tool
vjeantet/alerter avatar
vjeantet/alerter

Alerter: macOS notifications from the command line

Send User Alert Notification on MacOS from the command-line.

1,247 stars75 forksHTMLMIT

At a glance

What is it?
Alerter is a small command line tool that raises a real macOS notification and waits for the user to answer it, with a reply field or action buttons, returning the answer as plain text or JSON so a script can act on it. It suits someone automating a deployment or a long job who needs a human in the loop, and the current release is a Swift rewrite.
Who is it for?
Adopt Alerter when a script on macOS needs a human decision, since the reply field and action buttons turn a terminal script into a prompt that can be answered by clicking. Skip it on Linux or Windows, since it is a macOS-only tool requiring macOS 13.0 or later.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 93 days ago.
What is it written in?
Mainly HTML, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What it does, and the human in the loop

Alerter is a command-line tool for sending macOS notifications, built with Swift and Swift Package Manager. The detail that makes it more than a notification sender is in the second sentence of the description: the program exits when the user interacts with the alert or when it is dismissed, printing the result to stdout as plain text or JSON. So the alert is not fire and forget, it is a prompt with a return value, and a shell script can read the answer and branch on it. The alerts are macOS notifications that stay on screen until dismissed, and the tool requires macOS 13.0 or later. The primary language is recorded as HTML because of the documentation site, the licence is MIT, the last push was on 2026-07-22, and the releases are v26.5 on 2026-02-19, v26.4 on 2026-02-17 and v26.3 on 2026-02-16.

Two kinds of alert, and what each one gives you

Two kinds of alert can be triggered. The Reply alert displays a notification with a Reply button that opens a text input field, which is the form to use when the answer is not one of a fixed set. The Actions alert displays a notification with one or more action buttons to click on, which is the form to use when the answer is a choice. The features list adds the details that make them scriptable, including the ability to capture text typed by the user in reply-type alerts, to customize the close button label, to customize the actions dropdown label, and to play a sound when delivering the notification. There is also a per-notification group, where specifying a group means that for any group only one notification will ever be shown, replacing previously posted notifications, which is how you get a status line rather than a pile of stale alerts.

The option set, and the rules between options

The options are documented one by one with their conflicts, and the conflicts are the part to read. At a minimum you must specify either `--message`, `--remove`, or `--list`. The `--reply TEXT` option displays the notification as a reply-type alert, with the text used as placeholder text in the input field. The `--actions VALUE1,VALUE2,"VALUE 3"` option sets the available actions, and when more than one value is provided a dropdown is displayed, with the label customizable by `--dropdown-label`, and it cannot be combined with `--reply`. The `--close-label` option sets a custom label for the Close button. The `--title` defaults to Terminal. Then there are the timing options, `--delay NUMBER` waits that many seconds before delivering, `--at TIME` delivers at a specific time in either `HH:mm` or `yyyy-MM-dd HH:mm` form interpreted in the system's local timezone, and `--timeout NUMBER` closes the alert automatically after a delay.

Scheduling, and the signal handling

The timing semantics are precise and worth copying, because a scheduled notification is a promise about when a machine will interrupt a person. The `--delay` option waits the given number of seconds before delivering, and if a SIGINT or SIGTERM arrives during the delay the process exits silently without delivering. The `--at` option takes `HH:mm` for the next occurrence of that time, delivering immediately if the time matches the current minute and scheduling for tomorrow if it has already passed today, or `yyyy-MM-dd HH:mm` for a specific date and time, which must be in the future. It cannot be combined with `--delay`, and when combined with `--timeout` the timeout starts after the notification is delivered rather than from the moment you invoked the command. The features list also records the broader behaviour, that the tool gracefully closes the notification on SIGINT and SIGTERM, and that it can ignore Do Not Disturb mode.

Using it, and reading the answer

The usage line is short, and the examples show the intended shapes. Piping data with a sound is one command:

bash
$ echo 'Piped Message Data!' | alerter --sound default

If `--message` is omitted and data is piped in, that data is used as the message instead, which is what makes the tool compose with the rest of a shell pipeline. A yes-or-no question sets the title, subtitle, message, a custom close label, a single action and an icon URL:

bash
./alerter --title ProjectX --subtitle "new tag detected" --message "Deploy now on UAT ?" --close-label No --actions Yes --app-icon http://vjeantet.fr/images/logo.png

And the reply form asks a question whose answer is free text:

bash
./alerter --reply "Type release name" --message "What is the name of this release?" --title "Deploy in progress..."

The `--json` option outputs the result as a JSON object describing the alert event, and the feature list names the events, including closed, timeout, replied and activated.

Installing it, three ways plus a source build

Homebrew is the recommended route and the command names the tap:

bash
brew install vjeantet/tap/alerter

MacPorts is the second:

bash
sudo port install alerter

And the manual route is to download the zipped precompiled binary from the releases section, extract it, and place it in a directory listed in your `$PATH`, for example `/usr/local/bin`. The source build is a clone and a Swift build:

bash
git clone https://github.com/vjeantet/alerter.git
cd alerter
swift build -c release
# Binary is at .build/release/alerter

The repository root shows the Swift package layout, with `Package.swift` and `Package.resolved` at the top, a `Sources/` directory for the code, `scripts/` for the release automation, `macports/` for the Portfile, `web/` for the site and `docs/` for the documentation.

The 26 rewrite, and the versioning scheme

The important note in the README is the one about version 26. Alerter has been completely rewritten in Swift with the Swift Package Manager, and the CLI syntax now uses double dashes such as `--message`, `--title` and `--json`, with installation done through Homebrew. The release notes for that version are in `docs/release-notes-26.2.md`. The versioning scheme itself is unusual, using the format `YY.N` such as `26.1` and `26.2`, and the version is bumped automatically. The release workflow is three scripts run in order. `./scripts/release.sh` bumps the version, builds, signs, notarizes, tags and creates the GitHub Release. `./scripts/update-homebrew-formula.sh` updates the formula in the vjeantet/homebrew-tap. And `./scripts/update-macports-portfile.sh` updates the local macports Portfile and then submits a pull request to macports-ports. Signing and notarization in the first step is what lets the binary run without a Gatekeeper warning on a modern macOS.

Editorial conclusion

Adopt Alerter when a script on macOS needs a human decision, since the reply field and action buttons turn a terminal script into a prompt that can be answered by clicking. Skip it on Linux or Windows, since it is a macOS-only tool requiring macOS 13.0 or later. Before you script against it, check the option rules, because `--actions` and `--dropdown-label` cannot be combined with `--reply`, and `--delay` cannot be combined with `--at`, and note the version 26 rewrite changed the CLI to double-dash syntax and moved installation to Homebrew.

Frequently asked questions

What does Alerter do and what does it return?

It raises a macOS notification that stays on screen until dismissed, and the program exits when the user interacts with the alert or dismisses it, printing the result to stdout as plain text or as a JSON object describing the event.

What is the difference between a reply alert and an actions alert?

A reply alert shows a Reply button that opens a text input field, and the typed text is captured. An actions alert shows one or more buttons to click, with a dropdown when several values are given and a label you can set with --dropdown-label. The two cannot be combined.

How do I install Alerter?

With `brew install vjeantet/tap/alerter`, with `sudo port install alerter`, or manually by downloading the zipped binary from the releases section and putting it in a directory on your PATH. From source, clone the repository and run `swift build -c release`.

Can Alerter schedule a notification for later?

Yes. The --delay option waits a number of seconds before delivering, and --at takes either HH:mm for the next occurrence of that time or yyyy-MM-dd HH:mm for a specific date and time, interpreted in the local timezone. The two cannot be combined, and a SIGINT or SIGTERM while waiting exits silently without delivering.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. vjeantet/alerter on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vjeantet-alerter.svg)](https://hysenlabs.com/projects/vjeantet-alerter)

Was this useful?