# YubiKey Manager: scripting a security key across every application it holds

> YubiKey Manager is a Python library and command line tool for configuring a YubiKey over all of its USB interfaces, with subcommands for the FIDO, OATH, OpenPGP, YubiOTP and PIV applications. It is BSD-2-Clause licensed, the current release is 5.9.2 from 2026-06-30, and the version range guidance in the readme is unusually precise for a project of its size.

**Yubico/yubikey-manager** — Python library and command line tool for configuring any YubiKey over all USB interfaces.

- Repository: https://github.com/Yubico/yubikey-manager
- Website: https://developers.yubico.com/yubikey-manager/
- Stars: 1,207 · Forks: 159
- Language: Python
- License: BSD-2-Clause
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/yubico-yubikey-manager

## One tool across five applications, and one command per application

YubiKey Manager is a Python 3.10 or later library and command line tool for configuring a YubiKey, and if you are looking for a graphical application the readme points you at Yubico Authenticator instead.

That split is the whole design decision. A YubiKey is not one thing, it is a device that presents several independent applications to the host, and each has its own protocol, its own credential store and its own security model. The command list reflects that:

```
Usage: ykman [OPTIONS] COMMAND [ARGS]...

  Configure your YubiKey via the command line.

  Examples:

    List connected YubiKeys, only output serial number:
    $ ykman list --serials

    Show information about YubiKey with serial number 0123456:
    $ ykman --device 0123456 info

Options:
  -d, --device SERIAL             specify which YubiKey to interact with by serial number
  -r, --reader NAME               specify a YubiKey by smart card reader name (can't be used with --device or list)
  -l, --log-level [ERROR|WARNING|INFO|DEBUG|TRAFFIC]
                                  enable logging at given verbosity level
  --log-file FILE                 write log to FILE instead of printing to stderr (requires --log-level)
  --diagnose                      show diagnostics information useful for troubleshooting
```

The commands are `info` to show general information, `list` to list connected YubiKeys, `config` to enable or disable applications, and then one per application: `fido` to manage the FIDO applications, `oath` for the OATH application, `openpgp`, `otp` for the YubiOTP application and `piv`.

Two options are worth pausing on. The `--device SERIAL` flag selects a specific key when several are plugged in, which is what makes batch scripting safe. And the log levels include `TRAFFIC`, which logs the raw protocol exchange, plus a `--log-file` option to write it to a file instead of stderr, and a `--diagnose` flag for troubleshooting. On a device with several USB interfaces and a half dozen security-sensitive operations, being able to dump the traffic is a legitimate debugging tool rather than a curiosity.

There is a `--full-help` flag that shows hidden commands, and the `--help` argument works per subcommand, for example `ykman oath --help`.

## Version ranges are a first-class concern in the readme

The versioning section is short and unusually emphatic, and it tells you a lot about how the project expects to be consumed.

The project follows Semantic Versioning. Any project depending on yubikey-manager should take care when specifying version ranges to not include any untested major version, as it is likely to have backwards incompatible changes. The example given is that you should NOT depend on `>=5`, as it has no upper bound, and instead should depend on `>=5, <6`, as any release before 6 will be compatible.

That is a precise and unusual thing to put in a readme, and it is a reasonable position for a library whose surface is a set of commands and a Python API over a device. A major release here can change how a credential is written, and the consequences of an untested major version are not a broken import but a subtly different configuration on a security device.

The second sentence is the other half of it. Any private variable, meaning a name that begins with a low line, is not part of the public API, and may be changed between versions at any time. For a library that grows by accretion, an explicit statement of what is not API prevents a whole class of downstream breakage, and it matches the class of tool this is, where a private attribute leaking into a user's script is a maintenance obligation rather than a feature.

The version in the manifest is 5.9.3-dev.0, so the development line is already on the next patch after the 5.9.2 release from 2026-06-30, with 5.9.1 from 2026-04-15 and 5.9.0 from 2026-01-22 before it. The release cadence is regular, roughly every two to three months across the 5.9 line, and the last push was on 2026-10-14.

## Installing it, and the per-platform friction

The installation section opens with the platform-independent route, which is the simplest one.

```bash
pip install --user yubikey-manager
```

Or the equivalent, and the readme notes that on Linux you will need `pcscd` installed and running to communicate with a YubiKey over the SmartCard interface, and that you may need to set permissions for your user to access YubiKeys via the HID interfaces.

The `pcscd` requirement is the one that catches Linux users out. The tool talks to the key over the smart card interface, which means a PC/SC daemon has to be running, and if it is not, the tool appears to find no device. The HID permission issue is the same problem for the keyboard-style interface, and the readme points at a `Device_Permissions.adoc` document for the details.

There is also a build dependency note. Some of the libraries used by yubikey-manager have C extensions and may require additional dependencies to build, such as swig and potentially PCSC lite. So a source install on an unusual platform is not just a pip install.

Pre-built packages are the comfortable path where they exist. There is a Windows installer and a macOS installer on the releases page, and on macOS there are also packages from Homebrew and MacPorts. Linux packages come from several third-party maintainers, and the readme says that Python-specific tools such as pip, pipx or uv can be used directly to install and manage yubikey-manager, and that this is generally the recommended approach.

FreeBSD is handled with a specific warning. Although not officially supported, it can be installed via the ports tree or as a pre-built package, and if you do use it you should be aware that it is NOT maintained by Yubico. The `pkg install pyXY-yubikey-manager` form takes the Python version, and the OTP commands need a `usbconfig` quirk so that the `uhid(4)` driver attaches to the device, or, on FreeBSD 13 and higher, the more modern `hidraw(4)` driver, which allows non-exclusive access so the key still works as a USB keyboard.

## macOS needs a terminal permission, not an application permission

There is a whole section of the readme about macOS Input Monitoring, and the detail in it is the kind of thing that costs an afternoon if you do not know it.

When running one of the `ykman otp` commands you may run into an error such as `Failed to open device for communication: -536870174`, which indicates a problem with the permission to access the OTP, keyboard, USB interface. To access a YubiKey over this interface the application needs the Input Monitoring permission, and if you are not automatically prompted you may have to do so manually.

The last sentence is the one that matters. It is the terminal you are using that needs the permission, not the ykman executable.

That is a macOS security model detail that catches everybody once. The permission is granted per application, and the application that opens the HID keyboard interface is the terminal emulator, because that is the process that actually talks to the USB device. Granting Input Monitoring to the terminal feels wrong, because the terminal is not the thing you are trying to make work, and the permission prompt names the wrong binary.

The fix is in System Preferences, under Security and Privacy, Privacy, Input Monitoring. And there is an uninstall note for the macOS package installer, which is worth reading because it removes two paths by hand:

```bash
sudo rm -rf /usr/local/bin/ykman /usr/local/ykman
```

The readme also distinguishes the graphical path from the CLI path early on, pointing at Yubico Authenticator for graphical use, and the command line tool is the one that gets the Input Monitoring problem because only it touches the OTP interface.

## The library and the CLI are two layers of the same project

The repository layout shows a library and a tool built on it, and the packaging makes the boundary explicit.

The two Python packages are `yubikit` and `ykman`, and the manifest ships both. `yubikit` is the underlying library, the one you would depend on if you are writing your own provisioning script, and `ykman` is the command line application on top of it. The `ykman` console script is `ykman = "ykman._cli.__main__:main"`.

The `yubikit` name is the important clue about the layering. It is the kit, the toolkit, the pieces, and it is what a script author uses. So a team that wants to enrol fifty YubiKeys with the same resident credential in a CI job depends on `yubikit` directly, while a person at a terminal uses `ykman`.

The dependencies explain what each layer needs. `cryptography` for the crypto, `pyscard` for the PC/SC smart card interface, `fido2` for the FIDO applications, `click` for the command line, `keyring` for storing secrets, `python-pskc` for the portable symmetric key container format, and `pywin32` on Windows only. The `keyring` dependency is the notable one, because it means the tool can put a generated credential into the operating system's credential store rather than onto a disk.

The `examples/` directory shows what the library is for in practice. There is `piv_certificate.py`, `yubiotp_batch.py` and `yubiotp_batch_nfc.py`, and a `README.adoc`. The batch example is the one that tells you the intended use, because programming a YubiOTP credential in a loop over many keys is the task that a command line tool exists for and a graphical application does not.

The rest of the tree is the usual packaging for a project that ships binaries as well as a library. There is a `ykman.spec` for a Linux package, a `ykman.exe.manifest` for Windows, a `man/` directory with generated man pages and a `generate-man.py` script to produce them, a `resources/` directory, a `version_info.txt.in` template, and a `uv.lock` for dependency pinning.

## Where YubiKey Manager is the wrong tool

The first case is a single key with a single credential. The graphical application is the right tool for one person managing one device, and it exists precisely because the command line is the wrong shape for that job. The readme points at it in the first paragraph, and that pointer is the answer to whether you need this project at all.

The second case is a platform the project does not support well. FreeBSD works but is explicitly not maintained by Yubico, and macOS has the Input Monitoring permission dance. A team with a heterogeneous fleet of developer machines will spend more time on permissions than on the actual key configuration.

The third case is a workflow that needs the vendor's cloud. YubiKey Manager configures a device locally, which is the right model for self-hosted secrets and credentials, and it means there is no central policy server, no device inventory and no remote revoke. If your requirement includes knowing which of two thousand keys has which credential, that is a different product.

The fourth case is a project that needs an unmaintained surface. The version guidance is unusually blunt for a reason, and a team that pins `>=5` will get a major version it never tested, with credential-writing behaviour that may have changed. The fix is cheap, and the readme tells you exactly what to write, but it is a sign that the project expects careful consumption.

A final note on the credentials themselves. The tool writes real secrets onto real hardware, and the `yubiotp_batch.py` example is a loop that programmes the same one-time password into many keys. That is a legitimate provisioning job, and it is also a script that needs the source credential to be handled properly, which is why `keyring` is in the dependency list. Read the example before adapting it.

## Conclusion

YubiKey Manager fits a team that manages YubiKeys in bulk, where a fleet of keys needs the same FIDO resident credentials, the same OATH secrets and the same PIV slot layout applied consistently, and it fits anyone who needs a scripted path where the graphical authenticator has none. It does not fit a user who only has one key and one credential, since the graphical application is the better tool there. Before you depend on it, pin the version range as the readme instructs, with an upper bound, because the project is explicit that a major release may carry backwards incompatible changes and that private names are not part of the public API.

## FAQ

### How do I install YubiKey Manager?

The platform-independent route is `pip install --user yubikey-manager`, and pip, pipx or uv are the generally recommended tools. Pre-built installers for Windows and macOS are on the releases page, with Homebrew and MacPorts packages for macOS and third-party packages for several Linux distributions.

### What can the ykman command line tool do?

It configures a YubiKey, with commands for general information, listing connected keys, enabling or disabling applications, and one per application: `fido` for the FIDO applications, `oath`, `openpgp`, `otp` for YubiOTP and `piv`. The `--device SERIAL` option selects a specific key when several are connected.

### Why does ykman otp fail on macOS with a communication error?

The error `Failed to open device for communication: -536870174` indicates a problem with the permission to access the OTP keyboard USB interface, which needs the Input Monitoring permission. It is the terminal application that needs the permission, not the ykman executable, and it is granted under System Preferences, Security and Privacy, Privacy, Input Monitoring.

### How should I specify the yubikey-manager version range?

The project follows Semantic Versioning and asks you not to depend on an untested major version. Do not depend on `>=5`, since it has no upper bound, and depend on `>=5, <6` instead, as any release before 6 will be compatible. Names beginning with a low line character are private and may change between versions.

## Sources

- [License: BSD-2-Clause](https://github.com/Yubico/yubikey-manager/blob/main/LICENSE)
- [Project website](https://developers.yubico.com/yubikey-manager/)
- [README](https://github.com/Yubico/yubikey-manager/blob/main/README.md)
- [Releases](https://github.com/Yubico/yubikey-manager/releases)
- [Yubico/yubikey-manager on GitHub](https://github.com/Yubico/yubikey-manager)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/yubico-yubikey-manager
