cyme: a modern cross-platform lsusb written in Rust
List system USB buses and devices. A modern cross-platform lsusb that attempts to maintain compatibility with, but also add new features
At a glance
- What is it?
- cyme lists the USB buses and devices on a machine with full device descriptors, and it does it in a way that suits a modern terminal, with a tree view, filters that work in tree mode, JSON output, hotplug watching and the option to drop lsusb in as an alias. The author built it because lsusb was too verbose, its tree view was not useful, and it barely worked outside Linux.
- Who is it for?
- Adopt cyme if you work with embedded hardware and live in a terminal, since the tree view, the filters, the JSON output and the watch mode are all better than what lsusb gives you, and the lsusb compatibility mode makes it a safe drop-in. Do not adopt it for scripting that depends on the exact lsusb output format on Linux, since the tree view excludes driver information outside Linux, and do not expect the libusb backend to be the default, because the native profiler is.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 42 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why lsusb was not enough
The description is precise about the ambition, a modern cross-platform lsusb that attempts to maintain compatibility with, but also add new features. It lists system USB buses and the devices on those buses, including full device descriptors.
The motivation is explained in the first person and it is worth quoting, because the list of complaints is a specification. The author is a developer of embedded devices who uses a USB list tool frequently. The verbose dump of lsusb is mostly too verbose. The tree view does not contain useful data on the whole. It barely works on non-Linux platforms. And modern terminals support features that make glancing through the data easier.
Those four points map onto four of the features. A tree that actually contains the data you need is the answer to the second complaint, the cross-platform targets answer the third, and the coloured output, the glyphs and the automatic terminal width answer the fourth.
The first complaint, verbosity, is answered by control rather than by a compact default. The display is configurable at the level of the device, the bus, the configurations, the interfaces and the endpoints, so a glance and a deep inspection are both one command with different flags.
And the project keeps lsusb compatibility, which is the pragmatic part. A tool that replaces a system utility without breaking the muscle memory is adopted; one that does not is left on a shelf.
From a macOS parser to a pure Rust profiler
The history in the README describes a project that grew, which is often the most honest description of how a tool ends up doing what it does.
It started as a quick replacement for the barely working lsusb script, and as a Rust project to keep the author up to date with the language. It started as a macOS system_profiler parser, evolved to include a libusb-based profiler for reading full device descriptors, and now defaults to a pure Rust profiler using the nusb crate.
The default changed with version 2.0.0, and the README says so: the native profiler is the default as of 2.0.0, and the libusb profiler was the default feature before that. The consequence for a user is that the profiling backend is a compile-time choice, and the two are supposed to produce the same output, since cyme reads the same underlying data as lsusb.
The native backend uses nusb and udevrs, and covers sysfs on Linux, IOKit on macOS and WinUSB on Windows. The libusb backend uses the rusb bindings and requires libusb 1.0.0 on the host, installed with brew install libusb or sudo apt install libusb-1.0-0-dev.
The name is a small piece of craft worth mentioning, because it explains the logo. Cyme is the technical term for the type of blossom on an apple tree, which is Apple related and also looks like a USB device tree.
Compatibility mode, and the tree that finally shows something
The compatibility switch is the first feature in the list. The --lsusb argument supports all the lsusb arguments including --verbose output with fully parsed device descriptors. The README claims the output is identical for the plain list, identical for the tree except for drivers on non-Linux, and should match for verbose with perhaps formatting differences.
That is the right level of claim. Identical is asserted where it can be, and the differences are named rather than glossed.
The tree mode is the improvement, and the README describes it as showing the device, the configurations, the interfaces and the endpoints as a tree, depending on the level of --verbose. In other words, the tree is not a decoration over a flat list, it is the object model, and the verbosity setting selects how much of it to show.
If you want to keep the old habit, the README gives the alias:
alias lsusb='cyme --lsusb'which is the sort of detail that decides whether a replacement gets used at all. And for anything that needs to be read by a program rather than a person, the --json output honours the filters and the tree, so a script can consume the same structure the terminal shows.
Filters, display levels, and the watch subcommand
The filters are described as like lsusb but that also work when printing the tree, and the difference matters. A filter that only applies to the flat listing is a filter you have to remember to re-apply in another mode. The switches are --filter-name, --filter-serial and --filter-class, with the option to hide empty buses or hubs through --hide-buses and --hide-hubs, and the whole set can be inverted with --filter-exclude.
The display controls are per level of the object model, with --blocks for the device, --bus-blocks for the bus, --config-blocks for configurations, --interface-blocks for interfaces and --endpoint-blocks for endpoints, and --more to see more by default.
Two options exist for the case where the data is being shared rather than read. --headers shows the meta data only when asked, so it does not take space otherwise. And --mask-serials either replaces the serial with an asterisk or randomises it, which is the feature to reach for when a dump is going into a ticket.
The watch subcommand is the one that changes how the tool is used day to day. It watches for USB device hotplug events and also live edits the display settings, and it works with all the global flags, so the same filters apply to the live view as to the one-shot listing.
Terminal craft, encoding choices and a usable library API
The modern terminal features are a cluster of small decisions, and each of them has a switch. The output is coloured and uses utf-8 characters, with icons looked up from the device data, and it can be turned off and customised.
The --encoding setting offers glyphs, which is the default, utf8 and ascii, and it matters for terminals that cannot render the icon set. The --color setting is auto by default, with always and never, and --icon is auto, always or never. The auto behaviour for icons is careful: icons are only shown if all the icons to be shown are supported by the chosen encoding, so a partially rendered set is avoided.
There is also automatic scaling to the terminal width, with variable length strings such as descriptors truncated and marked with a ..., and this can be turned off with the no-auto-width configuration option, with a fixed maximum set by max-variable-string-len.
The library side is not an afterthought. The project can be used as a library too, with a system profiler module, USB descriptor modules and a display module for printing among others. The examples directory in the repository reflects that, with files for printing devices, filtering devices, walking the system profiler data and handling extra data.
The crate dependencies match the features. clap for argument parsing with derive and wrap_help, clap_complete and clap_mangen optional for completions and the man page, colored and cansi for terminal escape handling, serde and serde_json for the JSON output, usb-ids for the USB ID database, fastrand for the serial randomisation, terminal_size for the width detection, dirs for the cross-platform configuration path and heck for case conversion.
udev, the hardware database, and where cyme is the wrong choice
On Linux there is an extra layer, and the README is clear that it is Linux only. The udev feature is a default and uses the udevrs crate to obtain device and interface driver information of the kind lsusb shows. To use the C FFI libudev library instead, build with --no-default-features --features udevlib, which uses the libudev crate and requires libudev-dev on the host machine.
There is a similar choice for the identifier database. To look up USB IDs from the udev hardware database as lsusb does, use --features udev_hwdb. Without hwdb, cyme uses the usb-ids crate, which is the same source as the hwdb binary data, but the bundled copy may differ because of customisations or because it was last updated at a different time, and the README notes the usb-ids crate is generally the most up to date.
As for where the tool is the wrong choice, a first candidate is a script that parses the exact lsusb output format on Linux and nothing else, since the compatibility mode is close but the README says should match for verbose with possible formatting differences, and the tree excludes drivers outside Linux. A second candidate is a machine where you do not want to compile anything, though pre-compiled binaries exist in the releases and use the native profiling backends with no extra dependencies.
The third is a task that is not about enumerating devices. Cyme lists what is attached, it does not capture traffic, and it does not tell you what a device does.
The last is a workflow that needs the tool to be on PATH everywhere, since the install routes are a cargo install, a Homebrew formula that also brings the man page, completions and the libusb dependency, an official Arch package, and Debian packages from the releases that need a Debian maintainer.
Editorial conclusion
Adopt cyme if you work with embedded hardware and live in a terminal, since the tree view, the filters, the JSON output and the watch mode are all better than what lsusb gives you, and the lsusb compatibility mode makes it a safe drop-in. Do not adopt it for scripting that depends on the exact lsusb output format on Linux, since the tree view excludes driver information outside Linux, and do not expect the libusb backend to be the default, because the native profiler is. Before you install, decide which backend you want, since the udev driver and the hardware database options are compile-time features, and check the version you pin, because the profiler default changed at 2.0.0 and the current release is 3.0.2.
Frequently asked questions
What is cyme and what does it replace?
It is a Rust tool that lists system USB buses and devices with full device descriptors, written as a modern cross-platform replacement for lsusb. It keeps an lsusb compatibility mode with the --lsusb argument, and adds a tree view, filters that work in tree mode, JSON output, a watch subcommand for hotplug events and configurable terminal output.
How do I install cyme?
With cargo install --locked cyme, or cargo install --locked --path . from a local clone. There are also pre-compiled binaries in the releases, a Homebrew formula that installs a man page, completions and the libusb dependency, an official Arch package, and Debian packages published with the releases.
Which profiling backend does cyme use by default?
A pure Rust profiler using nusb, which has been the default since version 2.0.0 and covers sysfs on Linux, IOKit on macOS and WinUSB on Windows. The libusb backend is still available and requires libusb 1.0.0 on the host, and the udev driver and hardware database lookups are compile-time features.
How do I use cyme as a drop-in lsusb?
The --lsusb argument supports the lsusb arguments including fully parsed verbose output. The README also suggests creating the alias lsusb='cyme --lsusb' in your environment, and notes that the tree view excludes driver information outside Linux.
What licence is cyme released under?
GPL-3.0-or-later, as recorded in the Cargo.toml metadata and the LICENSE file at the repository root. The current version is 3.0.2, released on 2026-09-11, after 3.0.1 in June 2026 and 3.0.0 in the same month, and the crate requires Rust 1.82 or newer.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tuna-f1sh-cyme)Was this useful?