413

I'd love to be able to take advantage of 10.8's Notification Center features in AppleScripts and shell scripts I write.

Is there a built-in command or a third-party library I can use from either an AppleScript or shell script?

Ideally the type and icon of the notification could be controlled, but even just the ability to trigger a basic banner with a stock icon (but custom text) would be appreciated.

4
  • stackoverflow.com/questions/24606225/…
    – Pat
    Commented Jul 22, 2015 at 20:14
  • Just to add that this is also possible in Apple's Shortcuts and Automator apps with, respectively, the Show Notification and Display Notification actions. Commented Dec 26, 2023 at 18:22
  • @LouieLouie correct, but is there a neat way to hide the automator app icon if doing an automator notification? Like I'd like to create my own icon to use in the notification.
    – AVelj
    Commented May 4 at 3:33
  • 1
    @AVelj Not that I know of, but it's something I've never needed to delve into. I kinda doubt there is a neat way, but there just might be an extremely hacky way. Commented May 13 at 22:51

13 Answers 13

564

With Mavericks and later, you can do this using AppleScript's 'display notification':

display notification "Lorem ipsum dolor sit amet" with title "Title"

                          

That's it—literally that simple! No 3rd-party libraries or apps required and is completely portable for use on other systems. 10.9 notification on the top, 10.10 DP in the middle, 10.10 on the bottom.

AppleScript can be run from the shell using /usr/bin/osascript:

osascript -e 'display notification "Lorem ipsum dolor sit amet" with title "Title"'

You can also customise the alert further by adding…

  • a subtitle

    Append 'subtitle' followed by the string or variable containing the subtitle.

    display notification "message" with title "title" subtitle "subtitle"
    

    The above example produces the following notification:

  • sound

    Append 'sound name' followed by the name of a sound that will be played along with the notification.

    display notification "message" sound name "Sound Name"
    

    Valid sound names are the names of sounds located in…

    • ~/Library/Sounds
    • /System/Library/Sounds

Posting notifications can be wrapped as a command-line script. The following code can be run in Terminal and will add a script to /usr/local/bin (must exist, add to $PATH) called notify.

cd /usr/local/bin && echo -e "#!/bin/bash\n/usr/bin/osascript -e \"display notification \\\"\$*\\\"\"" > notify && chmod +x notify;cd -

This is the script that the above will add to notify.

#!/bin/bash
/usr/bin/osascript -e "display notification \"$*\""

Now to display a notification:

notify Lorem ipsum dolor sit amet
sleep 5; notify Slow command finished
21
  • 9
    @ceilingcat This is AppleScript. To run it in Terminal, use osascript (see answer).
    – grg
    Commented May 2, 2014 at 18:32
  • 16
    The only problem with display notification is that when you click on it, the open file dialog appears.
    – ɹoƃı
    Commented Aug 13, 2014 at 20:57
  • 9
    Is it possible to make the notificatiop popup exist forever (not auto-hide after N seconds) until explicitly clicked by the user? Commented Apr 1, 2015 at 22:15
  • 45
    Ladies and gentlemen, after an hour of investigation on the world wide web, I have found out how to let the notification window stay until dismissed by user! It was actually controlled by a setting in System Preference, rather than some parameter in the script written. These two images should explain it all i.imgur.com/cNOqFyX.jpg i.imgur.com/i8oyoan.jpg Have fun guys, and thanks @grgarside for the great answer.
    – Vic Jang
    Commented Nov 7, 2015 at 0:31
  • 6
    Note that the text has to be in double quotes. Single quotes don't work. So if you need a variable in the text, you cannot write "display ... '$mytext' ...", but need escaped double quotes: "display notification \"$mytext\" ...".
    – mivk
    Commented Dec 12, 2015 at 11:14
116
+100

terminal-notifier

From the README:

terminal-notifier is a command-line tool to send Mac OS X User Notifications, which are available in Mac OS X 10.8.

It is currently packaged as an application bundle, because NSUserNotification does not work from a ‘Foundation tool’. radar://11956694

This tool will be used by Kicker to show the status of commands which are executed due to filesystem changes. (v3.0.0)

Download

Prebuilt binaries, which are code-signed and ready to use, are available from the downloads section.

Usage

$ ./terminal-notifier.app/Contents/MacOS/terminal-notifier group-ID sender-name message [bundle-ID]

In order to use terminal-notifier, you have to call the binary inside the app bundle.

The first argument specifies the ‘group’ a notification belongs to. For any ‘group’ only one notification will ever be shown, replacing previously posted notifications. Examples are: the sender’s process ID to scope the notifications by a unique process, or the current working directory to scope notifications by a project.

The second and third arguments describe the notification itself and are its ‘title’ and ‘message’ respectively. For example, to communicate the sender of a notification to the user, you could specify the sender’s name as the title.

The fourth and last argument is an optional one. It specifies which application should be activated when the user clicks the notification. By default this will activate Terminal.app, to launch another application instead specify the application’s bundle identifier. For example, to launch Safari.app use: com.apple.Safari.

5
  • Sweet, a great library! Would love to see it updated with control over the icon and alert vs banner, but definitely useful. Thanks for the link! i.imgur.com/tsCeK.png Commented Jul 25, 2012 at 20:27
  • 2
    Great little app, I created a launcher and put in /usr/local/bin so that I can use it anywhere from a terminal etc. Launcher script: #!/bin/bash cd /Applications/terminal-notifier.app/Contents/MacOS ./terminal-notifier $* Commented Jul 26, 2012 at 7:13
  • 4
    Launcher is helpful, if you change it a bit it works with quoted text with spaces: #!/bin/bash cd /Applications/terminal-notifier.app/Contents/MacOS ./terminal-notifier "$@"
    – Redbeard
    Commented Jul 31, 2012 at 1:34
  • Easy to use. But does not work in cronjobs for some reason. I am getting sh: terminal-notifier: command not found
    – Nabin
    Commented Sep 12, 2021 at 8:13
  • 1
    @Nabin does the user who runs the cron have brew bin directory in the `$PATH variable? By default it does not... Commented Apr 13, 2022 at 13:48
47

I just want to add a note to @grgarside's answer, because I know many people want to have a notification popup that can only be dismissed by button click.

Comparison

I have found the solution for you:

It was actually controlled by a setting in System Preference, rather than some parameter in the script written. These two images should explain it all

Thanks @grgarside for the great answer.

System Preference

6
  • 9
    Note that the specific app will vary. Script Editor is only for Script Editor.app and osascript. In a service workflow, it's Automator Runner. When inside Automator.app, it's Automator.
    – cde
    Commented Mar 22, 2016 at 19:29
  • 2
    I find it annoying that if I click on the Banner, it brings up the Script Editor application. I'd like for it to just disappear on click, but this post points out you can hover over it and trackpad-swipe right to make it go away quietly: osxdaily.com/2012/09/05/… Commented Mar 31, 2016 at 14:24
  • @JoshuaGoldberg Thanks for adding that! I found that out intuitively one day, which is one thing I like about Mac OS X, it works the way you expect it do work :)
    – Vic Jang
    Commented Apr 1, 2016 at 7:46
  • Trying to use the osascript command was suddenly not working, neither in iTerm nor in Terminal, until I went to the Notifications settings for Script Editor and changed it from “None” to “Banners”! Commented Sep 10, 2020 at 21:06
  • I had intermittent problems with getting the display notification to run successfully; sometimes it would work, other times it would just be silent. After months of this frustrating behavior, I finally discovered it was caused by Do Not Disturb, which I had scheduled to activate after 8pm. 🤦‍♂️ Commented Oct 14, 2020 at 1:36
23

You can now do this with Growl2 (available from the App Store). Install Growl and enable "OS X Notifications" (screenshot)

enter image description here

Additionally, you'll need to install GrowlNotify for a command-line tool to send Growl notifications. You can download this tool for free on the Download page.

You can now generate Growl notifications from the command line, which will be forwarded to the Notification Center. For example:

growlnotify -n "My App" -m "Hello world"

enter image description here

Note that it currently doesn't seem possible to change the application icon.

3
  • 1
    Nice approach especially if growl is installed already.
    – Besi
    Commented Oct 25, 2012 at 12:34
  • 1
    I think you might be able to use the option --icon path/to/icon.png for icons.
    – Will
    Commented Feb 12, 2014 at 17:37
  • 1
    Deprecated/no longer maintained? Last update was for macos 10.9 mavericks
    – Seamus
    Commented Apr 11, 2019 at 17:48
19

I recently forked terminal-notifier to build a command line tool to display notification Alerts (with actions) and Reply Type Alerts.

I use it with my shell scripts and golang apps to get interactive answers from users.

https://github.com/vjeantet/alerter

enter image description here

2
  • 1
    Also apparently deprecated/abandoned.
    – Seamus
    Commented Apr 11, 2019 at 17:54
  • 2
    Looks alive and well now. Commented May 27, 2020 at 23:36
19

@grgarside's solution is nice, but it is vulnerable to script injection, which can be a major security issue when this is used to e.g. display log file contents or something similar.

This should be safer:

#!/bin/bash
X="$*" /usr/bin/osascript -e 'display notification system attribute "X"'
8
  • 2
    this is interesting, but can you describe a scenario where a script I run on my system that is only user-executable is vulnerable to script injection?
    – iconoclast
    Commented Dec 18, 2015 at 15:49
  • 1
    If you display user content that is not from you, you are vulnerable. For example if you run this on a system with a public web server, or when some app logs strings it got from the net which you read and display, e.g. a browser, mail program or a Twitter client. It could have a " to end the string and statement, then have code and then restart a string.
    – Arc
    Commented Dec 18, 2015 at 21:54
  • 1
    okay, that's true. it's just hard for me to imagine ever putting content from web forms into my notifications, but your point is taken.
    – iconoclast
    Commented Dec 18, 2015 at 23:30
  • 1
    Well, maybe you'd just like to say something like I have a "laser" without being told you're having a syntax error by "quoting" your "words". With escaping, you can: script 'I have a "laser"'
    – Arc
    Commented Dec 19, 2015 at 8:47
  • 1
    Upvote because it's always good to keep security in mind. Someone could copy-pasta solutions and use them in ways the person posting the solution hadn't considered. Commented Jul 22, 2016 at 19:06
18

(This is an alternative implementation based on @grgarside's excellent answer.)

AppleScript can be interpreted directly by putting osascript in the shebang line.

#!/usr/bin/osascript

on run argv
    if length of argv = 1 then
        display notification (item 1 of argv) with title "Notification"
    else if length of argv > 1 then
        display notification (item 1 of argv) with title (item 2 of argv)
    else
        return "<message> is required\nUsage: notify <message> [<title>]"
    end if
end run

Save this as notify somewhere in your path, e.g., /usr/local/bin/notify, and make it executable (chmod +x notify). It accepts a message and an optional title. If either has whitespace, wrap it in quotes so the shell interprets it as a single argument.

$ notify "Lorem ipsum dolor sit amet" "Testing Notifications"
4
  • 1
    This avoids the injection attacks that all the other answers are vulnerable to Commented Aug 10, 2018 at 16:22
  • Nice script, thanks! Note that "notify" is a built-in shell command in some commands (like mine, tcsh), so you might need to use a different name, as I did.
    – jimtut
    Commented Nov 30, 2020 at 15:29
  • 2
    Is there a way to make the notification sticky, so it requires a click to dismiss? Commented Jun 4, 2021 at 16:08
  • @CraigS.Anderson - one of the other answers (by Vic Jang) indicates that this is determined by the user's System Preferences (under Notifications > Script Editor). I'm not aware of a scripted way to do one or the other.
    – Steve
    Commented Jun 4, 2021 at 16:40
16

Since Growl is not free, and terminal-notifier is not available on pre-10.8 systems, I tend to use cocoaDialog. It is free and open source, so you can probably also distribute along with your scripts.

If you don't need a lot of customization, you can also use AppleScript's display notification which you can also call from the shell as others have already mentioned.

But beware that AppleScript seems to require double-quotes. So if you need variables, this will not work:

osascript -e "display notification '$text' with title '$title'" #WRONG

You will have to use escaped double-quotes. This is ugly but works:

osascript -e "display notification \"$text\" with title \"$title\""
2
  • 1
    This also works: osascript -e 'display notification "Lorem ipsum dolor sit amet" with title "Title"' Commented May 12, 2017 at 6:11
  • Also deprecated. Link yields "There isn't a GitHub Pages site here."
    – Seamus
    Commented Apr 11, 2019 at 17:54
9

Here's a cool one that I use in a ruby script on OS X (so that I can start a script and get an update even after toggling away from the window):

cmd = %Q|osascript -e 'display notification "Server was reset" with title "Posted Update"'|
system ( cmd )
4
  • 3
    wow... so the chain is something like User -> Ruby -> Shell -> AppleScript -> Objective-C -> Assembly -> CPU?
    – iconoclast
    Commented Dec 18, 2015 at 15:52
  • 1
    Coming at this late, but for the record, for convenience, I wrote a LISP wrapper for the Ruby command, and I typed it in with the mechanical arms from one of those giant P-5000 Powered Work Loader mechanical exoskeletons like Ripley wore in Aliens.
    – John Smith
    Commented Jul 24, 2021 at 2:56
  • @JohnSmith This is precisely why I read all the comments on SE posts.
    – davidavr
    Commented Oct 31, 2021 at 15:01
  • @johnsmith good point. We obviously should be wrapping this in a docker container, then deploying it with Kubernetes using a CI/CD pipeline. :) Commented Nov 1, 2021 at 16:14
8

An alternative:

In .bash_profile:

function _sys_notify() {
    local notification_command="display notification \"$2\" with title \"$1\""
    osascript -e "$notification_command"
}
alias sys-notify="_sys_notify $1 $2"

Use command: sys-notify "title" "message"

0
6

Thank you, this was just what I needed for some user scripts. I made a slight modification to add a subtitle and sound. If a value is not provided, it is ignored.

function _sys_notify() {
local notification_command="display notification \"$2\" with title \"$1\" subtitle \"$3\" sound name \"$4\""
osascript -e "$notification_command"
}

alias sys-notify="_sys_notify $1 $2 $3 $4"

For the sound, use a sound filename without the extension from /System/Library/Sounds. For example, to use the file Ping.aiff, use Ping for $4

5

Official documentation

https://developer.apple.com/library/content/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/DisplayNotifications.html

Copying the text here, in case the document is moved or removed.

To show a notification, provide the display notification command with a string to display. Optionally, provide values for the with title, subtitle, and sound name parameters to provide additional information and an audible alert when the notification appears

display notification "All graphics have been converted." with title "My Graphic Processing Script" subtitle "Processing is complete." sound name "Frog"

NOTE

After using a script to display a notification, the script or Script Editor (if the script is run from within Script Editor) is added to the list of notifying apps in System Preferences > Notifications. There, you can configure options, such as whether to display notifications as alerts or banners.

Clicking the Show button in an alert-style notification opens the app that displayed the notification. For a script app, the action of opening the app again triggers the run handler of the script, potentially causing the script to begin processing a second time. Keep this in mind, and add code to your script to handle this scenario, if appropriate.

5

If you want sticky notifications (Vic Jang's comment seems to no longer work, at least in Big Sur), here's a kind of way, use dialog instead of notification:

osascript -e 'display dialog "Lorem ipsum dolor sit amet" with title "Title"'

So you could do one display notification then follow it up with the dialog.

Also alerter does sticky.

$ brew install alerter
$ alerter -message "hi"
1
  • 2
    Good solution, and you can prevent the dialog from blocking your terminal by running in the 'background' : osascript -e 'display dialog "Lorem ipsum dolor sit amet" with title "Title"' &
    – Seamus
    Commented Mar 16, 2022 at 12:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .