In this article, we will see how to configure a button in our browser to launch external software by passing it the current URL
. This is especially useful when we want to use CLI
tools.
In my case, I’m going to automate video downloads. For this, we’ll use yt-dlp
, so let’s install it:
apt install yt-dlp
We prepare the script that the browser will call. As we can see, it’s just a bit of Zenity
asking for the path to save the file and some additional checks:
vi ~/.scripts/yt-dlp-auto.sh
#!/usr/bin/env bash
URL="$1"
if [ -z "$URL" ]; then
notify-send -t 8000 "yt-dlp" "No URL provided"
exit 1
fi
# Try to get video title with dump-json (10s timeout)
TITLE=$(timeout 10 yt-dlp --no-playlist --dump-json "$URL" 2>/dev/null | jq -r .title)
# Replace problematic characters (allow alnum, ., _, -, space → spaces → _)
SAFE_TITLE=$(echo "$TITLE" | sed 's/[^[:alnum:]._ -]//g; s/[ ]/_/g')
# Fallback if empty
if [ -z "$SAFE_TITLE" ]; then
SAFE_TITLE="video"
notify-send -t 5000 "yt-dlp" "⚠️ Could not fetch video title, using default name"
fi
# Ask where to save the file in a loop
while true; do
OUTPUT_PATH=$(zenity --file-selection --save --confirm-overwrite \
--filename="${SAFE_TITLE}.mp4" \
--title="Save video as:")
# Exit if user cancelled
if [ -z "$OUTPUT_PATH" ]; then
notify-send -t 8000 "yt-dlp" "Download cancelled"
exit 1
fi
# Check if partial file exists
if [ -f "${OUTPUT_PATH}.part" ]; then
zenity --warning --title="File exists" \
--text="An active download already exists:\n$OUTPUT_PATH\n\nPlease choose another name."
continue
fi
# If file already exists (not .part), remove it since user confirmed overwrite
if [ -f "$OUTPUT_PATH" ]; then
rm -f "$OUTPUT_PATH"
fi
# If path is safe, break loop
break
done
# Prepare yt-dlp output template (strip extension → yt-dlp adds real one)
OUTPUT_TEMPLATE="${OUTPUT_PATH%.*}.%(ext)s"
# Run yt-dlp and capture the final filename
FINAL_PATH=$(yt-dlp -f "bv*+ba/b" -o "$OUTPUT_TEMPLATE" \
--print after_move:filepath "$URL")
STATUS=$?
if [ $STATUS -eq 0 ]; then
notify-send -t 10000 "yt-dlp" "Download completed: $FINAL_PATH"
else
notify-send -t 10000 "yt-dlp" "Download failed: $URL"
fi
# Wait a moment to ensure process cleanup
sleep 2
# Check if there are any yt-dlp processes still running
if ! pgrep -x yt-dlp >/dev/null; then
notify-send -i dialog-ok -t 0 "yt-dlp" "All downloads finished ✅"
fi
We assign the necessary permissions:
chmod 700 ~/.scripts/yt-dlp-auto.sh
The browser extension we’ll use is External Application Launcher .
![]() |
![]() |
Clicking the new icon will show a form. Basically, we need to indicate the program or script to execute, the arguments, where to position the button, and an icon:
![]() |
![]() |
Now we’ll see a new button. If we press it, it will inform us that we need to install the NodeJS native client
:
![]() |
![]() |
We follow the instructions: download the archive, extract it, and run ./install.sh
after reviewing its content:
unzip linux.zip
cat install.sh
./install.sh
Installer is using your system NodeJS.
-> Root directory is /home/kr0m/.config
-> Creating a directory at /home/kr0m/.config/google-chrome/NativeMessagingHosts
-> Chrome Browser is supported
-> Creating a directory at /home/kr0m/.config/chromium/NativeMessagingHosts
-> Chromium Browser is supported
-> Creating a directory at /home/kr0m/.config/vivaldi/NativeMessagingHosts
-> Vivaldi Browser is supported
-> Creating a directory at /home/kr0m/.config/BraveSoftware/Brave-Browser/NativeMessagingHosts
-> Brave Browser is supported
-> Creating a directory at /home/kr0m/.config/microsoftedge/NativeMessagingHosts
-> Microsoft Edge Browser is supported
-> Creating a directory at /home/kr0m/.mozilla/native-messaging-hosts
-> Firefox Browser is supported
-> Creating a directory at /home/kr0m/.waterfox/native-messaging-hosts
-> Waterfox Browser is supported
-> Creating a directory at /home/kr0m/.tor-browser/app/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts
-> Tor Browser is supported
-> Creating a directory at /home/kr0m/.thunderbird/native-messaging-hosts
-> Thunderbird Email Client is supported
-> Creating a directory at /home/kr0m/.config/com.add0n.node
=> Native Host is installed in /home/kr0m/.config/com.add0n.node
>>> host is ready <<<
Now we click the Check Connection
button, and it should connect without problems:
![]() |
![]() |
Clicking the button again will execute our script:
![]() |
![]() |