I often switch my headphones between my phone (when I’m on the go) and my laptop (when I sit down to write, read or do other computer stuff outside home).

I’m also very lazy and annoyed by having to navigate the computer with a mouse.

Previously, after I disconnected my headphones from the phone, I’d have to click on my Mac toolbar to extend Ice, then find Bluetooth icon, click it, find headphones from the list and click it. Doesn’t sound too much but I hate it.

I discovered a command line utility tool blueutil and built a script to connect or disconnect a hard-coded device by its id:

#!/bin/bash
# Connect and disconnect bluetooth devices from command line.
#
# Dependencies: 
#   - jq (https://jqlang.org/)
#   - blueutil (http://github.com/toy/blueutil)
#
# Usage:
#   ,headphones [--disconnect]
#
# Configuration:
# Change `DEVICE_ID` below to match your device's address.
#
# License: MIT (https://opensource.org/license/MIT)
# Author: Juha-Matti Santala <juhis@hamatti.org>
 
## Configuration
 
# You can find your device's id with
# blueutil --paired --format json
DEVICE_ID='<your bluetooth device address>'
 
## Check for dependencies to be installed in the system
if ! command -v jq >/dev/null 2>&1
then
    echo "jq is required. See https://jqlang.org/."
    exit 1
fi
if ! command -v blueutil >/dev/null 2>&1
then
    echo "blueutil is required. See http://github.com/toy/blueutil."
    exit 1
fi
 
echo "Looking for device $DEVICE_ID..."
 
# Parse bluetooth information
device_info=$(blueutil --info "$DEVICE_ID" --format json)
is_paired=$(echo $device_info | jq '.paired' )
is_connected=$(echo $device_info | jq '.connected' )
device_name=$(echo $device_info | jq '.name' )
 
if [[ $* == --disconnect ]]
then
    echo "Disconnecting $DEVICE_ID..."
    blueutil --disconnect "$DEVICE_ID" --wait-disconnect "$DEVICE_ID" 1 >/dev/null
 
    device_info=$(blueutil --info "$DEVICE_ID" --format json)
    is_connected=$(echo $device_info | jq '.connected' )
 
    if ! $is_connected
    then
        echo -e "\033[32m$device_name ($DEVICE_ID) disconnected successfully.\033[0m"
        exit 0
    else
        echo -e "\033[31m$device_name ($DEVICE_ID) failed to disconnect.\033[0m"
    fi
    exit 1
fi
 
if $is_connected
then 
    echo "Device $DEVICE_ID is already connected";
    exit 1;
elif ! $is_paired
then
    echo "Device $DEVICE_ID is not paired";
    exit 1;
fi
 
echo "Connecting $device_name ($DEVICE_ID)..."
 
blueutil --connect "$DEVICE_ID" --wait-connect "$DEVICE_ID" 1 >/dev/null
 
device_info=$(blueutil --info "$DEVICE_ID" --format json)
is_connected=$(echo $device_info | jq '.connected' )
 
if $is_connected
then
    echo -e "\033[32m$device_name ($DEVICE_ID) connected successfully.\033[0m"
    exit 0
else
    echo -e "\033[31m$device_name ($DEVICE_ID) failed to connect.\033[0m"
fi

In the spirit of Pesky little scripts, I’ve named it ,headphones and placed it within my PATH. Once I sit down on my computer, I can tab into terminal, run ,headphones and be on my merry way listening to music and podcasts and when I’m done, I can do ,headphones --disconnect to free it to be connected to my other devices.

Simpler alternative through aliases

After I shared this note, Hugo shared his usage through shell aliases:

# brew install blueutil
alias bt="blueutil --connected --format json-pretty | jq -r '.[] | .name'"
alias bt-connect-sony="blueutil --connect the-sony-id; bt"
alias bt-disconnect-sony="blueutil --disconnect the-sony-id; bt"
alias bt-connect-sennheiser="blueutil --connect the-sennheiser-id; bt"
alias bt-disconnect-sennheiser="blueutil --disconnect the-sennheiser-id; bt"

It’s such an elegant and simple way!