Bluetooth CLI (bluetoothctl)

Quick Reference

# Connect first paired device
bluetoothctl connect $(bluetoothctl paired-devices | awk '{print $2}' | head -1)

# Connect by name pattern
bluetoothctl connect $(bluetoothctl devices | awk '/Adv360/{print $2}')

# Status
bluetoothctl devices Connected

Controller Operations

# List controllers
bluetoothctl list

# Show controller info
bluetoothctl show

# Power on/off
bluetoothctl power on
bluetoothctl power off

# Make discoverable (for pairing FROM another device)
bluetoothctl discoverable on

Device Discovery

# Scan for devices (15 second timeout)
timeout 15 bluetoothctl scan on

# List all discovered devices
bluetoothctl devices

# List only paired devices
bluetoothctl paired-devices

# List only connected devices
bluetoothctl devices Connected

Connection Management

# Connect to device
bluetoothctl connect XX:XX:XX:XX:XX:XX

# Disconnect
bluetoothctl disconnect XX:XX:XX:XX:XX:XX

# Show device info
bluetoothctl info XX:XX:XX:XX:XX:XX

Pairing Workflow

# Full pairing workflow (one-time setup)
bluetoothctl scan on              # Find device
bluetoothctl pair XX:XX:XX:XX:XX  # Pair (may prompt for PIN)
bluetoothctl trust XX:XX:XX:XX:XX # Enable auto-connect
bluetoothctl connect XX:XX:XX:XX  # Connect now

# Remove pairing
bluetoothctl remove XX:XX:XX:XX:XX

One-Liners

# Connect first paired device
bluetoothctl connect $(bluetoothctl paired-devices | awk '{print $2}' | head -1)

# Connect by name pattern (e.g., "Adv360", "Sony", "AirPods")
bluetoothctl connect $(bluetoothctl devices | awk '/Adv360/{print $2}')

# Connect ALL paired devices
bluetoothctl paired-devices | awk '{print $2}' | xargs -I{} bluetoothctl connect {}

# Disconnect all
bluetoothctl devices Connected | awk '{print $2}' | xargs -I{} bluetoothctl disconnect {}

# Battery level (if supported)
bluetoothctl info | awk '/Battery/'

# Reconnect cycle (troubleshooting)
MAC="XX:XX:XX:XX:XX:XX"; bluetoothctl disconnect $MAC && sleep 2 && bluetoothctl connect $MAC

Add to ~/.zshrc:

# Connect by name pattern: btc Adv360, btc Sony
btc() { bluetoothctl connect $(bluetoothctl devices | awk "/$1/{print \$2}"); }

# Connect first paired device (fastest emergency command)
alias bt1='bluetoothctl connect $(bluetoothctl paired-devices | awk "{print \$2}" | head -1)'

# Connect all paired devices
alias btall='bluetoothctl paired-devices | awk "{print \$2}" | xargs -I{} bluetoothctl connect {}'

# Status: what's connected + battery
alias bts='bluetoothctl devices Connected && bluetoothctl info 2>/dev/null | awk "/Name|Battery/"'

# Scan for new devices (15s timeout)
alias btscan='timeout 15 bluetoothctl scan on'

# Disconnect all
alias btoff='bluetoothctl devices Connected | awk "{print \$2}" | xargs -I{} bluetoothctl disconnect {}'

Troubleshooting

# Check controller is powered
bluetoothctl show | grep Powered

# Check service status
systemctl status bluetooth

# Restart Bluetooth service
sudo systemctl restart bluetooth

# Check kernel module loaded
lsmod | grep btusb

# Kernel messages
dmesg | grep -i bluetooth | tail -20

# D-Bus introspection (advanced)
busctl tree org.bluez

Audio Devices

# Check PipeWire sees device
wpctl status

# Check PulseAudio sees device
pactl list cards short

# Set default sink to Bluetooth device
wpctl set-default $(wpctl status | awk '/bluez/{print $1}' | head -1)

Architecture

User Space:    bluetoothctl ──► D-Bus ──► bluetoothd (BlueZ daemon)
                                              │
Kernel:                                  btusb module
                                              │
Hardware:                             Bluetooth Controller

Key paths:

  • Service: systemctl status bluetooth

  • Config: /etc/bluetooth/main.conf

  • Device cache: /var/lib/bluetooth/<adapter>/<device>/