Bluetooth Pairing with bluetoothctl
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
Section titled “Quick reference”# one-time install and enablesudo pacman -S --needed bluez bluez-utilssudo systemctl enable --now bluetooth
# pair a device (inside bluetoothctl)bluetoothctlpower onagent ondefault-agentpairable onscan onpair AA:BB:CC:DD:EE:FFtrust AA:BB:CC:DD:EE:FFconnect AA:BB:CC:DD:EE:FFscan offquit
# daily checksbluetoothctl devices Pairedbluetoothctl devices ConnectedInstall and enable
Section titled “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-utilssudo systemctl enable --now bluetoothsystemctl status bluetoothActive: active (running) confirms the service is up.
Check the controller is ready
Section titled “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 yesrfkill listrfkill unblock bluetooth
# confirm "Powered: yes", or turn it onbluetoothctl showbluetoothctl power onPair a device
Section titled “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.
bluetoothctlpower onagent ondefault-agentpairable onscan onWatch for the device in the scan output, then copy its MAC address.
[NEW] Device AA:BB:CC:DD:EE:FF Device NamePair, trust (so it reconnects automatically later), and connect. Stop scanning
once paired, and confirm the result with info.
pair AA:BB:CC:DD:EE:FFtrust AA:BB:CC:DD:EE:FFconnect AA:BB:CC:DD:EE:FFscan offinfo AA:BB:CC:DD:EE:FFquitA good state shows Paired: yes, Trusted: yes, Connected: yes.
Device-specific notes
Section titled “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: 123456Mouse (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 missingsudo pacman -S --needed xorg-xinputHeadphones. 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 statuspavucontrol # optional, for selecting the A2DP Sink profileDaily use
Section titled “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 Pairedbluetoothctl devices Connectedbluetoothctl connect AA:BB:CC:DD:EE:FFbluetoothctl disconnect AA:BB:CC:DD:EE:FFPairings 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
Section titled “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 bluetoothctlscan offscan on# if it stays stucksudo systemctl restart bluetoothsleep 3Broken pairing. Remove the device, restart Bluetooth, then pair again with the normal flow.
bluetoothctl remove AA:BB:CC:DD:EE:FFsudo systemctl restart bluetoothsleep 3