Home / Alt manpages / notify-send(1)

  • notify-send(1)
  • User command
  • linux

Send Useful Desktop Notifications from the Linux Shell

By the end of this guide, you will be able to send a desktop notification from a shell script, choose an appropriate urgency, and verify whether the local notification service accepted it. The examples target the installed Ubuntu package libnotify-bin, version 0.8.3-1build2, and the notify-send command documented by its local manpage.

Before you start

You need a graphical desktop session with a notification daemon running, plus the notify-send executable. No root access is required. Allow about five minutes for the basic examples, or longer if you are adding notifications to a script and need to test the script's session environment.

Check the package and command first:

command -v notify-send
dpkg-query -W libnotify-bin

Expected output includes a path such as /usr/bin/notify-send and the installed package version:

libnotify-bin 0.8.3-1build2

Checkpoint

If command -v prints nothing, install the distribution package through your normal software-management process. Do not copy a binary from an untrusted download.

1. Send a notification with a summary and body

The summary is required. The body is optional and should contain the useful detail. Put the summary and body in separate arguments so spaces remain part of the text:

notify-send 'Backup finished' 'The documents backup completed successfully.'

The command normally prints no output. A notification should appear through the desktop notification daemon. The daemon controls the visual layout, so the same command can look different in GNOME, Plasma, or another desktop environment.

To test only the command-line interface without sending a notification, ask it for help:

notify-send --help | sed -n '1,25p'

If the send command reports that it cannot connect to a notification service, you are probably outside the graphical session, using a remote shell, or running a service without the session's D-Bus environment. Re-running it with sudo usually makes this worse by changing the user and session context. Use the command as the logged-in desktop user.

2. Choose urgency and an icon

Use --urgency when the notification should be classified as low, normal, or critical:

notify-send --urgency=low 'Sync complete' 'No files needed attention.'
notify-send --urgency=critical 'Disk check failed' 'Review the service log before continuing.'

Reserve critical for events that genuinely need attention. It can affect how a desktop presents the notification, and Plasma may ignore an expiry time for critical notifications. Add an icon by giving --icon a stock icon name or an icon filename that exists on the machine:

notify-send --icon=dialog-information 'Deployment' 'The staging deployment is ready.'

Icon names are interpreted by the notification service and installed icon theme. If the alert appears without an icon, the message may still be correct; test the chosen name on the target desktop before depending on it.

3. Set a lifetime, but do not assume it is enforced

--expire-time takes milliseconds:

notify-send --expire-time=5000 'Reminder' 'This notification requests five seconds on screen.'

This is a request to the notification daemon, not a guarantee. The local manpage specifically warns that GNOME Shell and Notify OSD ignore the value, and that Plasma ignores it for critical notifications. The freedesktop.org notification specification also allows a server to apply its own policy.

Use --wait when a script must remain running until the notification closes:

notify-send --wait --expire-time=5000 'Job finished' 'The report is ready.'

With an expiry time, it is used as the maximum wait on implementations that honour it. Without one, the command may wait for the daemon's chosen lifetime or until the user closes the notification. Do not put --wait in a long-running service unless that pause is deliberate.

4. Replace an earlier notification

Ask the daemon for an ID with --print-id, then pass that ID to --replace-id. This is useful for progress-style status where one alert should be updated instead of creating a stack of alerts:

notification_id=$(notify-send --print-id 'Build' 'Starting...')
notify-send --replace-id="$notification_id" 'Build' 'Finished.'

The first command writes the notification ID to standard output. The ID is meaningful only while the notification service's session is running. If the first command fails, the variable may be empty, so a script should check the exit status before attempting replacement:

if notification_id=$(notify-send --print-id 'Build' 'Starting...'); then
    notify-send --replace-id="$notification_id" 'Build' 'Finished.'
else
    printf '%s' 'Notification service unavailable' >&2
fi

Replacement is not a durable record of progress. Keep logging important state separately, because a notification daemon may close alerts or restart.

5. Add an action only when a user response is useful

An action adds a labelled choice and implies --wait. Give it a stable name before the equals sign so the name can be read from standard output:

action=$(notify-send --action=open='Open report' 'Report ready' 'Choose Open report to continue.')
printf 'Selected action: %s' "$action"

The name printed when the user activates the action is open. Notification servers may ignore actions, so scripts should handle an empty result, an interrupted wait, or a service failure. Do not use an action as the only way to expose a security-sensitive decision or an irreversible operation.

Common traps and safe boundaries

  • Notification text is not a terminal. Quote shell variables, especially when they contain spaces or punctuation: notify-send 'Status' "$message".
  • Do not treat --expire-time as a scheduling mechanism. It controls a requested display duration, not when a command runs.
  • --transient asks for a notification that is not kept by a server's persistence capability. Use it for ephemeral status, not for an alert that must be recoverable later.
  • Notification bodies can support a small markup subset, but do not insert untrusted input as markup. Plain text is the least surprising choice.
  • These examples change no files and require no elevated privileges. There is therefore no undo command; close a displayed notification through the desktop or let its daemon remove it.

Done means

  • notify-send is installed and belongs to the expected package.
  • A quoted summary and body produce a notification in the intended desktop session.
  • Urgency, icon and expiry choices match the importance of the message, with daemon limitations understood.
  • Scripts check failures before using a printed notification ID or waiting for an action.