BLUETOOTHCTL-GATT(1)
π BLUETOOTHCTL-GATT β the generic attribute submenu, bestie
okay so this is bluetoothctl-gatt from the Linux System Administration manual, and it's literally the GATT girlie of the bluetoothctl family. Buckle up π
πΈ NAME πΈ
bluetoothctl-gatt β the Generic Attribute Submenu. that's her. that's the whole name. iconic, brief, no notes π
β¨ SYNOPSIS β¨
bluetoothctl [--options] [gatt.commands]
so like, this submenu is the one that talks to GATT services, characteristics, and descriptors β and it does it through the org.bluez.GattService(5), org.bluez.GattCharacteristic(5), org.bluez.GattDescriptor(5), and org.bluez.GattManager(5) interfaces. like those are the four besties she's always texting, ykwim? π«Ά
π GENERIC ATTRIBUTE COMMANDS π
π list-attributes
Lists the attributes of either the local device or a remote device, and it covers services, characteristics, and handles. basically a full read of the room β every Bluetooth attribute that's available, laid out so you can go poke at them with the other commands. main character energy for real β¨
Usage
> list-attributes [dev/local]
[dev/local] β device MAC address, object path, or "local" to list locally registered attributes (optional β omits = lists all of them, no cap)
Example: List attributes for specific service
> list-attributes /org/bluez/hci0/dev_00_11_22_33_44_55/service001a
Example: List attributes for specific characteristic
> list-attributes /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c
Example: List attributes for service on different device
> list-attributes /org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF/service0020
Example: List all Generic Access service attributes
> list-attributes 0x1800
Example: List all Battery Service attributes
> list-attributes 0x180F
Example: List all Device Name characteristic attributes
> list-attributes 0x2A00
Example: List attributes using full UUID
> list-attributes 00001801-0000-1000-8000-00805f9b34fb
Example: List attributes for custom service UUID
> list-attributes 12345678-1234-5678-9abc-123456789abc
π― select-attribute
Picks a specific attribute β local or remote β so everything you do next happens on that one. this is the whole vibe check of the workflow, because you literally cannot read or write to an attribute before you've selected it with this command. it sets the context for a bunch of other commands (read, write, notify, etc.) and tells them which attribute they're supposed to be operating on. no selection, no service π
Usage
> select-attribute <attribute/UUID/local> [attribute/UUID]
<attribute/UUID/local> β GATT attribute path, UUID, or "local" to select from the local attributes
[attribute/UUID] β an extra attribute path or UUID for when you're using "local" (optional)
Example: Select specific characteristic
> select-attribute /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c
Example: Select specific descriptor
> select-attribute /org/bluez/hci0/dev_00_11_22_33_44_55/service0020/char0022/desc0024
Example: Select service on different device
> select-attribute /org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF/service001a
Example: Select Device Name characteristic
> select-attribute 0x2A00
Example: Select Battery Level characteristic
> select-attribute 0x2A19
Example: Select Client Characteristic Configuration descriptor
> select-attribute 0x2902
Example: Select Temperature characteristic using full UUID
> select-attribute 00002a6e-0000-1000-8000-00805f9b34fb
Example: Select custom characteristic
> select-attribute 12345678-1234-5678-9abc-123456789abc
π attribute-info
Shows you the detailed tea on an attribute. if you don't hand it an attribute or UUID, it just spills about whatever attribute is currently selected. genuinely so useful for understanding an attribute's properties and capabilities β like reading their bio before you slide into their DMs π«Ά
Usage
> attribute-info [attribute/UUID]
[attribute/UUID] β GATT attribute path or UUID to get info for (optional β uses the current one if you omit it)
Example: Show information for currently selected attribute
> attribute-info
Example: Show info for specific characteristic
> attribute-info /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c
Example: Show info for Battery Level characteristic
> attribute-info 0x2A19
Example: Show info for Device Name characteristic
> attribute-info 0x2A00
Example: Show info for Temperature characteristic
> attribute-info 00002a6e-0000-1000-8000-00805f9b34fb
π read
Reads an attribute's value. β οΈ heads up bestie: it requires that you selected an attribute beforehand with select-attribute, or it's giving nothing. the optional offset parameter is there for attributes that allow partial reads β so you can start reading from somewhere other than the very beginning, slay β¨
Usage
> read [offset]
Uses org.bluez.GattCharacteristic(5) method ReadValue
[offset] β byte offset to start reading from (optional, defaults to 0)
Example: Read attribute value from offset 0
> read
Example: Read attribute value from offset 0 (explicit)
> read 0
Example: Read attribute value starting from offset 4
> read 4
Example: Read attribute value starting from offset 10
> read 10
Example: Read attribute value starting from offset 16
> read 16
βοΈ write
Writes a value into an attribute. β οΈ same rule as read: you must have selected an attribute in advance with select-attribute. data has to come in hexadecimal format β no vibes-based input, sorry π. the optional offset and type parameters are there for when your write has specific requirements.
Usage
> write <data="xx xx ..."> [offset] [type]
Uses org.bluez.GattCharacteristic(5) method WriteValue
<xx xx ...> β hexadecimal data bytes to write to the attribute
[offset] β byte offset to start writing at (optional, defaults to 0)
[type] β write type: request, command, or reliable (optional, defaults to request)
Example: Write Hello to attribute (ASCII bytes)
> write "48 65 6C 6C 6F"
Example: Write binary data to attribute
> write "01 02 03 04"
Example: Write single byte value
> write "FF"
Example: Write 2 bytes starting at offset 4
> write "01 02" 4
Example: Write with write request (default)
> write "48 65 6C 6C 6F" 0 request
Example: Write with write command (no response)
> write "01 02 03" 0 command
Example: Write with reliable write
> write "FF EE DD" 0 reliable
π acquire-write
Grabs a Write file descriptor for the attribute you already selected. super handy for apps that need a file descriptor to do their write operations. it's giving "hold my spot" π
Usage
> acquire-write
Uses org.bluez.GattCharacteristic(5) method AcquireWrite
Example: Acquire write file descriptor for current attribute
> acquire-write
π§Ή release-write
Releases the Write file descriptor you got from acquire-write. this is the cleanup step β you literally need it to free up resources once you're done writing. don't ghost your file descriptors, bestie, that's not the vibe π«Ά
Usage
> release-write
Example: Release write file descriptor for current attribute
> release-write
π acquire-notify
Grabs a Notify file descriptor for the attribute you selected earlier. this is what lets applications listen for notifications when an attribute's value changes. lowkey the most useful thing ever π
Usage
> acquire-notify
Uses org.bluez.GattCharacteristic(5) method AcquireNotify
Example: Acquire notify file descriptor for current attribute
> acquire-notify
π§Ό release-notify
Releases the Notify file descriptor you got with acquire-notify. frees the resources once you're done listening for notifications. closure is healthy β¨
Usage
> release-notify
Example: Release notify file descriptor for current attribute
> release-notify
π notify
Turns notifications for attribute value changes on or off. β οΈ the relevant attribute has to be selected before you can use this one. it means apps can get told about attribute changes without polling β no more refreshing like a feral person, we love to see it π
Usage
> notify <on/off>
Uses org.bluez.GattCharacteristic(5) methods StartNotify, StopNotify
<on/off> β enable or disable notifications for the current attribute
Example: Enable notifications for current attribute
> notify on
Example: Disable notifications for current attribute
> notify off
π― clone
Makes a clone of a device or attribute. useful for creating a backup, or for working with a copy when you're testing stuff. girlie said "I'll just duplicate myself" π
Usage
> clone [dev/attribute/UUID]
[dev/attribute/UUID] β device MAC address, attribute path, or UUID to clone (optional β clones the current one if omitted)
Example: Clone entire device GATT database
> clone 00:11:22:33:44:55
Example: Clone another device
> clone AA:BB:CC:DD:EE:FF
Example: Clone specific service
> clone /org/bluez/hci0/dev_00_11_22_33_44_55/service001a
Example: Clone specific characteristic
> clone /org/bluez/hci0/dev_00_11_22_33_44_55/service001a/char001c
Example: Clone Generic Access service
> clone 0x1800
Example: Clone Battery Service
> clone 0x180F
Example: Clone Battery Level characteristic
> clone 0x2A19
π register-application
Registers a new application with the Bluetooth system, so you can manage services, characteristics, and descriptors under that application. it's giving "signing the lease on your own little GATT apartment" π β¨
Usage
> register-application [UUID ...]
Uses org.bluez.GattManager(5) method RegisterApplication
[UUID ...] β optional list of service UUIDs to register with the application
Example: Register GATT application without specific UUIDs
> register-application
Example: Register application with Battery Service
> register-application 0x180F
Example: Register with Generic Access and Battery Service
> register-application 0x1800 0x180F
Example: Register application with custom service UUID
> register-application 12345678-1234-5678-9abc-123456789abc
Example: Register with multiple standard services
> register-application 0x1800 0x180F 0x180A
ποΈ unregister-application
Removes an application you previously registered from the Bluetooth system. bye bestie π no hard feelings, just cleanup.
Usage
> unregister-application
Uses org.bluez.GattManager(5) method UnregisterApplication
Example: Unregister current GATT application
> unregister-application
π register-service
Adds a new service under a registered application. genuinely crucial if you're defining new services that devices can offer β this is the "here's what I bring to the table" command π₯
Usage
> register-service <UUID> [handle]
<UUID> β service UUID to register (16-bit, 32-bit, or 128-bit format)
[handle] β specific attribute handle to assign (optional β auto-assigned if you omit it)
Example: Register Generic Access service (auto handle)
> register-service 0x1800
Example: Register Battery Service (auto handle)
> register-service 0x180F
Example: Register Device Information service (auto handle)
> register-service 0x180A
Example: Register Generic Access service at handle 1
> register-service 0x1800 0x0001
Example: Register Battery Service at handle 16
> register-service 0x180F 0x0010
okay so, the rest of the register-service examples are serving exact-handle realness, and you already know the vibe:
- Register Device Info service at handle 32 β
> register-service 0x180A 0x0020 - Register custom service (auto handle) β
> register-service 12345678-1234-5678-9abc-123456789abc - Register custom service at specific handle β
> register-service 12345678-1234-5678-9abc-123456789abc 0x0050
π unregister-service π
This one yanks a service out of a registered application, so it stops being available. Itβs giving βavailability revoked, periodt.β
Usage
> unregister-service <UUID/object>
<UUID/object>β the service UUID or object path of the service youβre unregistering, bestie.
Examples
- Unregister Generic Access service β
> unregister-service 0x1800 - Unregister Battery Service β
> unregister-service 0x180F - Unregister custom service β
> unregister-service 12345678-1234-5678-9abc-123456789abc - Unregister service by object path β
> unregister-service /org/bluez/example/service0 - Unregister another service β
> unregister-service /org/bluez/example/service1
π§ register-includes π§
Marks a service as included within another service, so you can build service hierarchies and complex service structures. Itβs lowkey giving nesting-doll energy.
Usage
> register-includes <UUID> [handle]
<UUID>β service UUID to register as an included service.[handle]β specific attribute handle to assign; itβs optional and auto-assigned if you omit it.
Examples
- Register Generic Access as included service β
> register-includes 0x1800 - Register Battery Service as included at handle 21 β
> register-includes 0x180F 0x0015 - Register custom service as included β
> register-includes 12345678-1234-5678-9abc-123456789abc
π¦ unregister-includes π¦
Removes an included service relationship, simplifying the service structure. Itβs the βokay weβre untangling this nowβ command.
Usage
> unregister-includes <Service-UUID> <Inc-UUID>
<Service-UUID>β parent service UUID that contains the included service.<Inc-UUID>β included service UUID to remove from the parent service.
Examples
- Unregister Battery Service inclusion from Generic Access β
> unregister-includes 0x1800 0x180F - Unregister Device Info inclusion from custom service β
> unregister-includes 12345678-1234-5678-9abc-123456789abc 0x180A
β¨ register-characteristic β¨
Introduces a new characteristic under a service, specifying its properties and access permissions with flags. This is where the GATT girlies really start customizing, no cap.
Usage
> register-characteristic <UUID> <Flags=read,write,notify...> [handle]
<UUID>β characteristic UUID to register; it can be 16-bit, 32-bit, or 128-bit format.<Flags=read,write,notify...>β comma-separated list of characteristic properties and permissions.[handle]β specific attribute handle to assign; optional, and auto-assigned if omitted.
Examples
- Register Device Name (read-only) β
> register-characteristic 0x2A00 read - Register Battery Level (read + notifications) β
> register-characteristic 0x2A19 read,notify - Register Heart Rate Measurement (notify-only) β
> register-characteristic 0x2A37 notify - Register Device Name (read + write) β
> register-characteristic 0x2A00 read,write - Register Battery Level (read + write + notify) β
> register-characteristic 0x2A19 read,write,notify - Register Temperature (read + indications) β
> register-characteristic 0x2A6E read,indicate - Register Device Name at handle 3 β
> register-characteristic 0x2A00 read 0x0003 - Register Battery Level at handle 19 β
> register-characteristic 0x2A19 read,notify 0x0013 - Register custom characteristic with full capabilities β
> register-characteristic 12345678-1234-5678-9abc-123456789abc read,write,notify - Register custom write-only characteristic β
> register-characteristic ABCD1234-ABCD-1234-ABCD-123456789ABC write-without-response - Register with all flags β
> register-characteristic 0x2A00 read,write,write-without-response,notify,indicate
π unregister-characteristic π
Eliminates a characteristic from a service, removing its functionality. Itβs the clean-girl removal arc.
Usage
> unregister-characteristic <UUID/object>
<UUID/object>β characteristic UUID or object path of the characteristic to unregister.
Examples
- Unregister Device Name characteristic β
> unregister-characteristic 0x2A00 - Unregister Battery Level characteristic β
> unregister-characteristic 0x2A19 - Unregister custom characteristic β
> unregister-characteristic 12345678-1234-5678-9abc-123456789abc - Unregister characteristic by object path β
> unregister-characteristic /org/bluez/example/service0/char0 - Unregister another characteristic β
> unregister-characteristic /org/bluez/example/service1/char1
πΈ register-descriptor πΈ
Adds a descriptor to a characteristic, further defining its behavior and access controls. Descriptors are literally the little accessories that finish the outfit.
Usage
> register-descriptor <UUID> <Flags=read,write...> [handle]
<UUID>β descriptor UUID to register; it can be 16-bit, 32-bit, or 128-bit format.<Flags=read,write...>β comma-separated list of descriptor properties and permissions.[handle]β specific attribute handle to assign; optional, and auto-assigned if omitted.
Examples
- Register Client Characteristic Configuration β
> register-descriptor 0x2902 read,write - Register Characteristic User Description β
> register-descriptor 0x2901 read - Register Characteristic Presentation Format β
> register-descriptor 0x2904 read - Register CCCD at handle 5 β
> register-descriptor 0x2902 read,write 0x0005 - Register User Description at handle 21 β
> register-descriptor 0x2901 read 0x0015 - Register custom descriptor β
> register-descriptor 12345678-1234-5678-9abc-123456789abc read,write - Register custom read-only descriptor β
> register-descriptor ABCD1234-ABCD-1234-ABCD-123456789ABC read - Register Valid Range descriptor β
> register-descriptor 0x2906 read - Register External Report Reference β
> register-descriptor 0x2907 read - Register Report Reference β
> register-descriptor 0x2908 read
π
unregister-descriptor π
Removes a descriptor from a characteristic, simplifying its behavior. Itβs giving βwe donβt need that accessory anymore, bestie.β
Usage
> unregister-descriptor <UUID/object>
<UUID/object>β descriptor UUID or object path of the descriptor to unregister.
Examples
- Unregister Client Characteristic Configuration β
> unregister-descriptor 0x2902 - Unregister Characteristic User Description β
> unregister-descriptor 0x2901 - Unregister custom descriptor β
> unregister-descriptor 12345678-1234-5678-9abc-123456789abc - Unregister descriptor by object path β
> unregister-descriptor /org/bluez/example/service0/char0/desc0 - Unregister another descriptor β
> unregister-descriptor /org/bluez/example/service1/char1/desc1
π RESOURCES π
The official BlueZ website is right here: http://www.bluez.org β iconic, honestly.
π REPORTING BUGS π
Bug reports go to linux-bluetooth@vger.kernel.org. Tell them what happened, bestie.
βοΈ COPYRIGHT βοΈ
Legal tea, served fresh: Free use of this software is granted under the terms of the GNU Lesser General Public Licenses (LGPL).
okay signing off β source/version is BlueZ, date is November 2022, and the manual is BLUETOOTHCTL-GATT(1). mwah πβ¨π«Ά
π¦ where this page comes from
- centos-stream 9: bluez 5.87+2.git8750129efca8-1.el9 Β· GPLv2+
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms