Ctrl K

Bluetooth Pairing with bluetoothctl

Pair and reconnect Bluetooth mice, keyboards, and headphones on a minimal Arch/i3 setup with bluez and bluetoothctl, without a GUI like Blueman.

Pair and reconnect Bluetooth devices on a minimal Arch/i3 setup using bluez and the bluetoothctl CLI, with no GUI client (Blueman is intentionally left out). The pairing flow is the same for a mouse, keyboard, or headphones; only a few device-specific steps differ. Replace AA:BB:CC:DD:EE:FF with the device MAC address that appears during scanning.

Quick reference

# one-time install and enable
sudo pacman -S --needed bluez bluez-utils
sudo systemctl enable --now bluetooth

# pair a device (inside bluetoothctl)
bluetoothctl
power on
agent on
default-agent
pairable on
scan on
pair AA:BB:CC:DD:EE:FF
trust AA:BB:CC:DD:EE:FF
connect AA:BB:CC:DD:EE:FF
scan off
quit

# daily checks
bluetoothctl devices Paired
bluetoothctl devices Connected

Install and enable

bluez provides the stack and bluez-utils provides bluetoothctl. Install them, then enable and start the service so it also comes up on future boots.

sudo pacman -S --needed bluez bluez-utils
sudo systemctl enable --now bluetooth
systemctl status bluetooth

Active: active (running) confirms the service is up.

Check the controller is ready

If scanning or powering on fails, confirm Bluetooth is not blocked by rfkill and that the controller is powered.

# unblock if Soft/Hard blocked shows yes
rfkill list
rfkill unblock bluetooth

# confirm "Powered: yes", or turn it on
bluetoothctl show
bluetoothctl power on

Pair a device

Start the CLI and bring up the agent and scanner, then put the device into pairing mode so it appears in the scan.

bluetoothctl
power on
agent on
default-agent
pairable on
scan on

Watch for the device in the scan output, then copy its MAC address.

[NEW] Device AA:BB:CC:DD:EE:FF Device Name

Pair, trust (so it reconnects automatically later), and connect. Stop scanning once paired, and confirm the result with info.

pair AA:BB:CC:DD:EE:FF
trust AA:BB:CC:DD:EE:FF
connect AA:BB:CC:DD:EE:FF
scan off
info AA:BB:CC:DD:EE:FF
quit

A good state shows Paired: yes, Trusted: yes, Connected: yes.

Device-specific notes

Keyboard. After pair, the agent may show a passkey. Type that number on the Bluetooth keyboard itself and press Enter there, then continue with trust and connect.

[agent] Passkey: 123456

Mouse (Logitech MX and similar). Press the Easy-Switch button to choose a channel, then hold it until the LED blinks fast before scanning. After connecting, confirm X registered it as an input device.

xinput list | grep -i -E "mouse|logitech|mx|bluetooth"

# if xinput is missing
sudo pacman -S --needed xorg-xinput

Headphones. After connecting, confirm the audio stack sees the device and use the A2DP profile for listening. The HFP/headset profile adds microphone support but at lower audio quality.

wpctl status
pavucontrol   # optional, for selecting the A2DP Sink profile

Daily use

Once a device is paired and trusted you do not repeat the agent/scan steps. Turn the device on (and select its paired channel if it has several) and it should reconnect on its own. Connect or disconnect manually when needed.

bluetoothctl devices Paired
bluetoothctl devices Connected
bluetoothctl connect AA:BB:CC:DD:EE:FF
bluetoothctl disconnect AA:BB:CC:DD:EE:FF

Pairings are local machine state and should not be committed to a setup repo. Only the packages (bluez, bluez-utils) and the service-enable command belong in a rebuild script.

Troubleshooting

"Failed to start discovery: org.bluez.Error.InProgress". A scan is already running. Toggle it off and on; if still stuck, restart the service and retry.

# inside bluetoothctl
scan off
scan on
# if it stays stuck
sudo systemctl restart bluetooth
sleep 3

Broken pairing. Remove the device, restart Bluetooth, then pair again with the normal flow.

bluetoothctl remove AA:BB:CC:DD:EE:FF
sudo systemctl restart bluetooth
sleep 3