Skip to content

Instantly share code, notes, and snippets.

@petethepig
Last active May 6, 2025 05:45
Show Gist options
  • Select an option

  • Save petethepig/2d29e8b7e2ebc808bfe760b632608966 to your computer and use it in GitHub Desktop.

Select an option

Save petethepig/2d29e8b7e2ebc808bfe760b632608966 to your computer and use it in GitHub Desktop.
Alert yourself after a long-running task in terminal

Alert yourself after a long-running task in terminal

For the last few months I've been working on pyroscope, I’ve often found myself getting distracted when I run any long tasks in the terminal (tests / docker builds).

This little snippet helps me get back to what I was doing in the terminal by alerting me via a sound message and also a macOS notification.

demo

Instructions

Step 1. Install terminal-notifier:

brew install terminal-notifier

Step 2. Add the following code to .bash_profile:

# Open ~/.bash_profile and add these functions:

function timer_start {
  timer=${timer:-$SECONDS}
}

# this makes bash run timer_start every time you run a command
trap 'timer_start' DEBUG

function notify_when_done {
  timer_show=$(($SECONDS - $timer))
  unset timer
  # 10 is the notification threshold in seconds
  if (( ${timer_show} > 10 )); then
    # modify this section to fit your needs:
    say "Done with task"
    terminal-notifier -title "Terminal" -message "Done with task! Exit status: $? Time: ${timer_show}s"
  fi
}

# this makes bash run notify_when_done command after every command
if [ "$PROMPT_COMMAND" == "" ]; then
  PROMPT_COMMAND="notify_when_done"
else
  PROMPT_COMMAND="$PROMPT_COMMAND; notify_when_done"
fi

Update: for information on how to set this up on Linux or with other shells (fish / zsh) see Hacker News comments.

@l0b0
Copy link
Copy Markdown

l0b0 commented Feb 25, 2021

Thanks for the tip! My implementation

@gitowiec
Copy link
Copy Markdown

Thanks for the tip! My implementation

Thanks for the Linux version, it is much more useful for me!

@figbux
Copy link
Copy Markdown

figbux commented Feb 25, 2021

Thanks for the tip! My implementation

How it behaves with vim, manpages etc? They take quite a long time but they shouldn't alert

@c02y
Copy link
Copy Markdown

c02y commented Feb 25, 2021

If anyone is using fish-shell, https://github.com/franciscolourenco/done can be used for the same purpose, works on Windows/macOS/Linux

@l0b0
Copy link
Copy Markdown

l0b0 commented Feb 25, 2021

How it behaves with vim, manpages etc? They take quite a long time but they shouldn't alert

@figbux It'll alert for those. I'm not sure what an elegant workaround would look like (is it possible to detect whether the command was interactive or not?), but you could of course do something like this (untested):

if [[ "$(("$SECONDS" - "$__bashrc_command_start"))" -gt 60 ]] \
    && ! grep --fixed-strings --line-regexp --quiet --regexp=man --regexp=vim <<< "$__bashrc_command"

@bertrand-caron
Copy link
Copy Markdown

bertrand-caron commented Feb 26, 2021

My version for zsh, that excludes long-running commands like vim, etc.:

### Source: https://gist.github.com/petethepig/2d29e8b7e2ebc808bfe760b632608966
function timer_start {
  timer=${timer:-$SECONDS}
}

# this makes bash run timer_start every time you run a command
trap 'timer_start' DEBUG

function notify_when_done {
  timer_show=$(($SECONDS - $timer))
  unset timer
  # 15 is the notification threshold in seconds
  if (( ${timer_show} > 15 )); then
    # modify this section to fit your needs:
    printf \\a
    terminal-notifier -title "Terminal" -message "Done with task $1! Exit status: $? Time: ${timer_show}s"
  fi
}

# export command we are about to run, so we can inject it in the notification once done
preexec() {
	export _CMD=$1
}
# this makes zsh run notify_when_done command after every command
precmd() {
    if ! [[ ${_CMD} =~ '^(v|vim|ssh|gc|gs|gd) ' ]] {
	    notify_when_done ${_CMD}
    }
}
### END

@mihirkhandekar
Copy link
Copy Markdown

Thanks for the gist. I created (Telert) to easily configure sound alerts, desktop popup, or even Telegram/Slack/Teams/Discord messages when a long-running command finishes. It also works in Python commands.

Setting it up is quick and easy

pip install telert
telert config audio --set-default  # for sound
telert config desktop --set-default  # for popup
telert config telegram --token "<token>" --chat-id "<chat-id>" --set-default # for telegram

You can then use it with your long running commands in your script.

long_running_command | telert # Option 1
telert run long_running_Command # Option 2

Telert will time the command and send a notification to the provider channel when it completes with the execution time and exit code.

https://github.com/navig-me/telert/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment