com.github.paolostivanin.OTPClient.desktop CC-BY-4.0 GPL-3.0+ OTPClient Application for managing TOTP/HOTP tokens with built-in encryption otp totp hotp 2fa 2factor 2fa-client 2step twostep

OTPClient is a secure and easy-to-use desktop client for TOTP and HOTP one-time passwords, built with GTK4 and libadwaita. Features:

com.github.paolostivanin.OTPClient.desktop Empty main window https://raw.githubusercontent.com/paolostivanin/OTPClient/master/data/screenshots/emptymain.png Add menu https://raw.githubusercontent.com/paolostivanin/OTPClient/master/data/screenshots/addmenu.png General menu https://raw.githubusercontent.com/paolostivanin/OTPClient/master/data/screenshots/hambmenu.png Settings menu https://raw.githubusercontent.com/paolostivanin/OTPClient/master/data/screenshots/settings.png https://github.com/paolostivanin/OTPClient https://github.com/paolostivanin/OTPClient/issues info@paolostivanin.com Paolo Stivanin Paolo Stivanin otpclient none none none none none none none none none none none none none none none none none none none none

The tray menu was empty on every desktop except KDE Plasma, and has been since the tray was rewritten: right-clicking the icon opened a blank rectangle on GNOME, Cinnamon, MATE, Xfce and Waybar alike. That is fixed. OTPClient can now also start minimized to the tray and start at login. Alongside those, a round of fixes for things that never worked inside the Flatpak sandbox: webcam QR scanning (which was in fact broken everywhere), the search provider's clipboard copy and its notification, database locking for databases picked from outside the sandbox, and the command line failing whenever the GUI happened to be running.

  • FIX: the tray menu was an empty rectangle on every host built on libdbusmenu, which is GNOME with AppIndicator, Cinnamon, MATE, Xfce, Ayatana and Waybar. The tray declared dbusmenu version 3, which makes clients fetch labels with GetGroupProperties and dispatch clicks through EventGroup, and neither method existed, so both menu entries were silently dropped. The group methods are now implemented, and clicking an entry works rather than doing nothing (#470, Flathub #81)
  • NEW: start minimized to the tray, from Settings under Integration or with otpclient --start-minimized. It needs minimize-to-tray and a real system tray, and is ignored with the window shown normally when either is missing. The database is deliberately left locked, so the first time you bring the window up it asks for the password (#471)
  • NEW: start at login, from Settings under Integration. Native builds write an autostart entry; the Flatpak asks the desktop through the background portal, which a few desktops do not implement, and there the setting is greyed out. The entry follows the start-minimized preference
  • FIX: webcam QR scanning has never worked in the GTK4 rewrite, on any platform. The scanner opened a zbar preview window instead of the camera, then failed on every frame and reported a timeout. It now opens the camera, and no longer needs an X display to do it
  • FIX: in the Flatpak, activating a search result copied nothing. The daemon shells out to a clipboard tool and the runtime shipped none, so every candidate failed silently. The tools are now bundled, the Wayland session is detected from WAYLAND_DISPLAY rather than a variable the sandbox may not set, every available tool is tried instead of committing to one, and a failure is reported instead of being swallowed
  • FIX: otpclient-cli failed with "Application does not handle command line arguments" whenever the GUI was running, because both registered the same application id and the CLI became a remote of the GUI. This mattered rarely before and would have become permanent with start-at-login
  • FIX: databases opened from outside the Flatpak's own data directory were saved without any lock held. The document portal implements POSIX record locks and refuses flock outright, which is what the code used, so the "Database lock not supported on this filesystem" warning was reached on every save. Locking works again for those databases
  • FIX: a database picked from outside the sandbox could stop opening after a reboot, on btrfs and other filesystems whose device numbers are not stable, and the dialog then suggested two things that could not recover it. The dialog now says the sandbox lost access rather than that the file is missing, and offers to re-pick it
  • FIX: turning minimize-to-tray off inside the Flatpak left a dead icon in the panel until the app exited, because the sandboxed tray had no bus name it could release
  • FIX: the tray icon now says so when the database is locked, and the "Show OTPClient" entry raises the window on Wayland instead of being blocked by focus-stealing prevention
  • FIX: every Flatpak launch logged a warning about not being able to subscribe to suspend events. The system bus is not there to be reached, so the attempt is no longer made and no longer complained about. Locking on screen lock is unaffected
  • NOTE: the search provider is a separate process with its own lock state. A hidden or locked GUI does not stop search from working, and using search does not unlock or reveal the GUI
  • NOTE: if you use the system keyring to unlock automatically and turn start-minimized on, OTPClient will sit in the tray over a locked database rather than an open one. That is intentional, and it is the reason the first show asks for the password

Bug-fix release. Minimize-to-tray did not work in the Flatpak: the switch was greyed out as if the desktop had no system tray, and granting the missing permission by hand still produced no icon. The sandbox refuses the process-derived bus name the tray asks to own, so the tray now registers with the tray host under its unique connection name instead, which needs no permission and works in any sandbox. The Flatpak was also missing the permissions Auto-Lock needs, so locking on screen lock silently did nothing; that is fixed in the Flathub packaging, though locking on suspend stays unavailable there.

  • FIX: no tray icon appeared in sandboxed builds even with a tray host present, because the session bus refused the process-derived StatusNotifierItem name and the tray gave up. It now falls back to registering under its unique bus connection name, which is what Qt applications do, so the icon appears regardless of what the sandbox grants (Flathub #79)
  • FIX: two sandboxed applications could not both show a tray icon: every Flatpak process sees itself as pid 2, so the process-derived StatusNotifierItem names collided and whichever lost the race silently got none. Both now get an icon (Flathub #79)
  • PACKAGING: the Flatpak lacked the D-Bus permissions the tray and Auto-Lock need. Access to the StatusNotifierWatcher name un-greys the minimize-to-tray switch, which had reported "No system tray was detected on this desktop" on desktops that do run one, and access to the desktop screensaver services makes Auto-Lock on screen lock work, which had been a no-op. Auto-Lock on suspend stays unavailable in the Flatpak because it needs logind, which Flathub does not permit, so the "Could not subscribe to suspend events" warning remains there (Flathub #79)

Minimize-to-tray is now offered in default builds. It had been an opt-in build flag because turning it on could strand the application: on a desktop with no system tray, closing the window hid it anyway and left OTPClient running invisibly, holding a decrypted database, with no icon to bring it back. The app now confirms a tray host is really there before it will hide to one, and restores the window if the tray goes away. The feature itself is still off by default in Settings.

  • FIX: with minimize-to-tray enabled on a desktop that has no system tray (stock GNOME without the AppIndicator extension, i3bar, polybar), closing the window hid it with no icon to restore it, leaving an invisible process holding a decrypted database that only killall could stop. The window is now hidden only once a tray host has accepted the icon, and if the tray disappears while the window is hidden the window comes back (#405)
  • BUILD: ENABLE_MINIMIZE_TO_TRAY now defaults to ON, so distribution packages offer the feature without a custom build. The tray has not needed libayatana-appindicator since it moved to a direct StatusNotifierItem implementation over GDBus, so this adds no dependency. The minimize-to-tray setting itself is unchanged and still defaults to off, and its switch is greyed out where no tray was detected (#405)

Bug-fix release. Auto-Lock was effectively unusable: on any profile that enabled it without changing the timeout, the database re-locked about five seconds after every unlock, and the unlock prompt could not be dismissed and quit the whole application when closed, leaving Settings unreachable. The timeout now defaults to five minutes, and the unlock prompt is dismissable and returns to a locked screen instead of quitting.

  • FIX: with Auto-Lock enabled but the timeout left at its default, the database re-locked roughly five seconds after each unlock. The idle timer counts seconds, but the default was 5 and documented as minutes; the default is now 300 seconds (five minutes), so profiles that never set a timeout pick up a sane value automatically (#467)
  • FIX: the unlock prompt could not be dismissed and closing it quit the whole application, so Settings could not be reached while locked. Dismissing it (Escape, the dialog close button, clicking outside, or the window close button) now drops to the locked screen and keeps the toolbar reachable; the toolbar lock button doubles as an unlock button while locked, and an explicit Quit button remains on the prompt (#467)

Bug-fix release. A database stored on a filesystem that does not implement POSIX file locks, most notably the Flatpak XDG document-portal path (/run/user/UID/doc/) that the file chooser hands back, could not be opened or created and failed with "Failed to acquire database lock: Function not implemented"; the lock file added in 5.1.4 is now treated as best-effort. This release also stops the secure-memory pool from reserving the whole locked-memory budget, which had left the GTK password entry unable to lock its own buffer on every unlock.

  • FIX: a database stored on a filesystem without lock support (the Flatpak document portal, and some NFS/SMB mounts) could not be opened or created, failing with "Failed to acquire database lock: Function not implemented". Locking is now best-effort so the database opens normally on those filesystems, while real locking is unchanged everywhere else (#466)
  • FIX: the secure-memory pool consumed the whole RLIMIT_MEMLOCK budget, so the GTK password entry could not lock its own buffer and warned "couldn't lock 16384 bytes of memory (gtk): Cannot allocate memory", falling back to unlocked memory for the typed password on every unlock; the pool now leaves headroom for it (Debian #1141809)

Bug-fix release. Following the anonymous-token fix in 5.1.3, a database containing a token with an out-of-range digit count still refused to open, again locking users out of every other token. The load-time validator was stricter than the OTP engine and the app's own UI; the accepted ranges now match the engine (digits 4 to 10, period 1 to 120 seconds). Any token the engine still cannot use is set aside so the rest of the database opens, and is preserved for repair rather than dropped.

  • FIX: a database containing a token with an out-of-range digit count (or period) refused to open, locking users out of all their tokens. Accepted ranges now match the OTP engine (digits 4 to 10, period 1 to 120), and any token that still cannot be loaded is kept aside and preserved instead of bricking the whole database (#464, follow-up to #458/#462)
  • FIX: right-click context menus on tokens and databases were clipped to the scrolled area and needed scrolling to reach lower items such as "Set Group"; they now size to their contents (#465)

Bug-fix release. Following 5.1.1, which restored issuer-only tokens, a database containing a token with neither an account name nor an issuer still refused to open, and a single such token blocked every other token from loading. These anonymous tokens, common in databases created before 5.1.0 added load-time validation, now load with a synthesized placeholder label instead of being rejected.

  • FIX: a database (or import) containing a token with neither an account name nor an issuer refused to open on 5.1.x, locking users out of all their tokens. Such tokens now load with a synthesized "Unknown N" label; interactive manual entry and editing still require a name (#462, follow-up to #458)

Bug-fix release. Screen and session locking, and locking on system suspend, now honor the Auto-Lock setting the same way the inactivity timer already did, so with Auto-Lock off the database is no longer locked on every screen lock. The mutual exclusivity between Auto-Lock and the Secret Service integration is restored.

  • FIX: screensaver, session lock, and suspend now respect the Auto-Lock setting, so with Auto-Lock off the app no longer locks and then prompts for a password on every screen lock; Auto-Lock and Secret Service are mutually exclusive again, including reconciliation of a legacy both-on profile (#460, re-report of #279)

Bug-fix release. Databases containing a token with an issuer but no account name (for example some ProtonMail or Steam entries) failed to open on 5.1.0 with "Could not open database: Token has a missing label", locking users out of the entire database. Such tokens are valid again.

  • FIX: databases with issuer-only tokens (no account name) refused to open on 5.1.0. A token is now valid as long as it has either an account name or an issuer; the same rule applies to imports and manual token entry (#458)

Feature and hardening release. Webcam QR scanning now runs on a worker thread so the UI no longer freezes while the camera warms up or while frames are decoded. You can quit the app while the database is locked. The database file format is bumped to v3 with a portable big-endian header; v1 and v2 databases are still read transparently and upgraded on next save. Locking now wipes the decrypted database and master key from memory, and the app also locks automatically when the system suspends. Search-provider results use single-use, time-bounded capability tokens instead of predictable indices. Plus a broad security and correctness pass across the core, GUI, importers, and CLI, a reworked Google Authenticator migration importer, memory-leak fixes, and a new test suite with ASan/UBSan CI.

  • NEW: webcam QR scanning runs on a worker thread, no more main-thread freeze while the camera initializes or while frames are decoded
  • NEW: you can quit OTPClient while the database is locked (#456)
  • NEW: the app locks automatically when the system suspends (via logind), so the database is never left decrypted across sleep
  • IMPROVEMENT: database file format bumped to v3 with a portable, byte-addressable big-endian header. v1 and v2 databases are read transparently and upgraded to v3 on next save
  • IMPROVEMENT: cross-process write serialization via a bounded-wait .lock sidecar, prevents two OTPClient instances from clobbering each other on save
  • IMPROVEMENT: search-filter cache, large token lists filter without re-walking the model on every keystroke
  • IMPROVEMENT: changing the password now requires verifying the current one before the change is applied
  • IMPROVEMENT: CLI plain imports dispatch by file type automatically, no longer prompt for a password on unencrypted formats
  • IMPROVEMENT: Google Authenticator migration import was rewritten with bounded payload/token/batch limits and now reports multi-batch progress, across the file, screen, and webcam paths
  • SECURITY: locking wipes the decrypted database and master key from memory; unlocking re-derives the key instead of comparing a copy held in RAM
  • SECURITY: generated codes, notification text, clipboard contents, and per-token values are wiped after use, and live codes are kept in libgcrypt secure memory
  • SECURITY: search-provider activation IDs are now random 128-bit capability tokens with a 30-second TTL and single-use enforcement, replacing the predictable db_index:json_index scheme
  • SECURITY: HOTP entries are excluded from the search provider at load time, advancing a counter from a desktop search result is too easy to do by accident
  • SECURITY: transient password buffers are wiped after use across the GUI and CLI, including on password-dialog cancel and dispose
  • SECURITY: search-provider derived-key cache + rate limit on OTP delivery, using a single global rate bucket with no per-connection bypass and an idle-wipe timer for keys and caches
  • SECURITY: 2FAS encrypted import now surfaces decryption errors instead of silently swallowing them
  • SECURITY: broad correctness and hardening pass across src/ (core, GUI, importers, CLI), including a parse-uri double-error fix, an authpro stream check, a bytes_to_hexstr overflow guard, and NULL-checked secure-memory allocations
  • SECURITY: tightened Argon2id parameter bounds (MAX_ITER 100 -> 64, MAX_MC 4 GiB -> 1 GiB, MAX_PARAL 64 -> 16) to reject pathological configurations
  • FIX: v2 databases were misread as a far-future format version and refused to open; both v2 and v3 headers are now read correctly
  • FIX: the window no longer gets stuck on the "Unlocking..." page when a database fails to load for a reason other than a missing file or wrong password; it drops back to the no-database view so you can retry
  • FIX: the desktop search provider copies the OTP to the clipboard asynchronously on KDE; the synchronous Klipper D-Bus call could block every activation for up to a second when Klipper did not reply in time, delaying the copy and the notification
  • FIX: CLI HOTP counter is now persisted before the code is printed, the counter upper bound is exclusive everywhere, the terminal is restored on interrupt, and CR/LF is stripped from piped input
  • FIX: memory leaks in database and OTP handling paths
  • FIX: freeotp importer secmem budget and GError-overwrite bug that also affected other importers
  • FIX: in-memory database state is now restored if an encrypt-on-save fails, instead of being left half-mutated
  • FIX: debianStable CI build and the JPEG sanitizers test

Bug-fix release in the 5.0.x line. Headline fix is an unlock-loop affecting users who upgraded from 4.x: with the correct password, the unlock dialog would re-prompt forever until the app was restarted. Also restores auto-unlock via the system keyring for upgraders, fixes the Backup/Restore buttons on distros shipping libadwaita 1.5 (Ubuntu 24.04, Pop!_OS 24.04, Linux Mint 22.3), and several smaller GUI fixes.

  • FIX: unlock dialog re-prompting forever with the correct password. A wrong-password attempt was poisoning the in-memory key cache, so even the correct password kept being rejected until the app was restarted (#448)
  • FIX: auto-unlock via the system keyring stopped working after upgrading from 4.x. On first launch, OTPClient now picks up the old keyring entry, uses it to unlock, and re-saves it under the new format so it keeps working (#448)
  • FIX: Backup and Restore buttons in Settings did nothing on Ubuntu 24.04, Pop!_OS 24.04, Linux Mint 22.3, and other distros shipping libadwaita 1.5 (#449)
  • FIX: a revealed OTP could fall out of sync with the clipboard near the end of a 30-second window, leaving you unsure which code you actually pasted. Reveal now ends cleanly when the code rotates, and the clipboard rolls to the new code if "Show next OTP" is on (#450)
  • FIX: "Hide OTPs by default" only took effect after restarting the app. Toggling it now updates the visible list immediately (#450)
  • FIX: re-clicking an already-selected token did nothing, so it could not be copied or advance the HOTP counter a second time. Re-clicks now re-trigger the copy and counter-advance action (#451)
  • FIX: window close/minimize/maximize buttons were forced to the right side, ignoring the system setting. They now follow the desktop's decoration layout, e.g. left-side buttons on macOS-style KDE setups (#452)
  • FIX: switching to a different database (sidebar click, Open DB, or New DB) while an unlock was still in progress could corrupt memory. The app now shows a toast and waits for the unlock to finish
  • IMPROVEMENT: saving the database after a fresh unlock is noticeably faster. The password-derivation result is now cached on save just like on unlock, so the first save no longer re-runs the slow key derivation

Bug-fix release in the 5.0.x line. Headline fix is a hardening of the auto-lock flow: dismissing the unlock dialog (Esc, X, or click-outside) previously left the token list visible and interactive, so a single click would still copy an OTP - and "Show QR" would render the secret as a scannable image. The unlock dialog is now non-dismissable and a dedicated locked page hides the token list across every code path. Also recovers gracefully on systems where the registered Secret Service provider is broken (e.g. KDE Plasma with KWallet disabled): the setting is pre-flighted before being enabled and auto-disabled on runtime failure, instead of looping every launch.

  • FIX: lock bypass via unlock dialog dismissal - the token list was still clickable, allowing OTP copy and QR render while the app was "locked" (#447)
  • FIX: per-launch loop when the system Secret Service is unavailable; the toggle now pre-flights the keyring before being enabled, and auto-disables on runtime failure rather than nagging on every start (#446)
  • FIX: keyboard focus did not land on the token list after unlock, so Up/Down/Enter required a mouse click first; restored the 4.x default and extended it to the empty and no-database pages (#445)

Small bug-fix release in the 5.0.x line. The headline fix is a Flatpak-only data-loss-prevention hotfix: the GSettings schema XML was installed but never compiled into gschemas.compiled, so the schema lookup failed at runtime and every GSettings write was a silent no-op. As a result, the sidebar appeared empty on each launch (db-list never persisted) and preference changes did not stick. Existing databases were never lost - the .enc files remained on disk and the last-used path was still being written to otpclient.cfg via the GKeyFile fallback. On first launch after upgrading to 5.0.4, the v4 migration path rebuilds the sidebar from that fallback automatically. Non-Flatpak builds are unaffected by the schema fix.

  • FIX: Flatpak GSettings schema not compiled at install time, causing the sidebar to appear empty and preferences to reset on every restart (#442)
  • FIX: Welcome dialog Back/Next/page-indicator row got pushed below the visible area when the page's status description was tall enough to overflow; now pinned via AdwToolbarView's bottom bar (#441)

Small bug-fix release in the 5.0.x line. Fixes a startup crash on systems where the XDG portal cannot auto-report a color scheme (typically XFCE) and the user has the dark-theme GSetting enabled. The dark-theme preference was being applied before AdwApplication's startup chain ran, so adw_style_manager_get_default() reached into an uninitialized GDK display and aborted.

  • FIX: startup crash "gdk_display_manager_get() was called before gtk_init()" when use-dark-theme is enabled on environments without a portal-reported color scheme (#440)

Restores the "Scan QR from Clipboard" workflow that existed in 4.5.0 and was dropped in the GTK4 rewrite. Reads an image directly from the clipboard via the GTK4 clipboard API and feeds it into the existing zbar pipeline, sidestepping the file-roundtrip needed for browser-copied or screenshot-captured QR codes.

  • NEW: Add -> Scan QR from Clipboard (#438)
  • FIX: scanning a QR that does not encode an otpauth:// URI now surfaces a toast instead of silently doing nothing (applies to file and webcam scans too)

Bug-fix release for 5.0.0. Importing a QR code into a database that already contained tokens left the previously-imported entries duplicated in the array; the duplicates also caused delete and group actions to appear to target the wrong row. Existing 5.0.0 databases that were corrupted by repeated QR imports can be cleaned up by removing the duplicate entries.

  • FIX: QR import no longer duplicates pre-existing tokens (#435)
  • FIX: Set Group / Remove from Group / New Group act on the right token when a group filter or column sort is active (#437)
  • FIX: token actions (delete, edit, show QR, move to database) act on the right token when a filter or column sort is active
  • FIX: clicking a database in the sidebar now actually loads it (#436)
  • NEW: sidebar marks the default database (loaded on startup) with a star and the currently open one in bold
  • NEW: creating or opening additional databases no longer changes which one loads on startup - only right-click "Set as Primary" does, and that choice now persists across restarts

OTPClient 5.0.0 - first stable release of the GTK4 / libadwaita rewrite, with multi-database support, token grouping, an opt-in trigger keyword for the desktop search provider, and a sweeping crypto and import-path hardening pass. Existing v2 databases unlock and migrate automatically.

  • NEW: complete GUI rewrite on GTK4 + libadwaita
  • NEW: persistent multi-database support with sidebar and right-click "Move to…" between databases
  • NEW: token grouping with header-bar dropdown and "group:" / "#" search prefix; groups round-trip through Aegis / AuthPro / 2FAS
  • NEW: cross-database search with auto-select-and-copy on a single result
  • NEW: hidden-by-default OTPs with click-to-reveal and auto-hide
  • NEW: async unlock with KDF spinner
  • NEW: search-provider trigger keyword (default "otp"); KRunner subtitle no longer leaks live codes; activation copies the OTP
  • NEW: Settings -> Backup is the unified entry point for native (encrypted) backup and restore; format-specific export becomes migration-only with a plaintext warning
  • NEW: settings import/export, Welcome and What's New dialogs, KDF presets, paste-to-fill otpauth:// URI, backup-age banner, lock-time clipboard wipe
  • NEW: scriptable CLI output (--output=table|json|csv), translated CLI strings, --list-databases, HOTP counter in CSV, bash/zsh/fish completions
  • NEW: native StatusNotifierItem tray (libayatana-appindicator dependency removed)
  • SECURITY: Argon2id header validation refuses out-of-bounds parameters on unlock
  • SECURITY: KDF byte-length fix - gcry_kdf_* was passed character count instead of byte count, weakening keys for non-ASCII passwords; transparent retry plus opportunistic re-encryption on the next write
  • SECURITY: O_NOFOLLOW + fstat S_ISREG on every importer and database read site, closing the symlink-swap TOCTOU window
  • SECURITY: 0600 mode on backup files; PR_SET_DUMPABLE=0 + RLIMIT_CORE=0 to suppress core dumps
  • SECURITY: AEAD validation tightened across decrypt paths; 2FAS no longer accepts plaintext on tag mismatch
  • SECURITY: search provider refuses every D-Bus method when the keyword is empty (closes arbitrary local enumeration of accounts)
  • SECURITY: otpauth:// URI capped at 4 KB, HOTP counter capped at 2^48, PNG QR capped at 4096×4096, settings import capped at 1 MiB
  • SECURITY: signal-safe clipboard wipe on SIGINT/SIGTERM/SIGHUP; CLI --password-file refuses group/world-readable files; secret service disabled by default
  • SECURITY: HOTP counter increment is transactional (rolled back if save fails)
  • FIX: NULL-deref crashes across Aegis, AuthPro, 2FAS, FreeOTP+, and otpauth importers on malformed input
  • FIX: use-after-free in async secret lookup; double-free of filter_model in window dispose; DBus assertion on exit
  • FIX: notification spam during store rebuilds and search-bar close
  • FIX: window size and group dropdown restored across sessions; schema and icon cache updated on install
  • PERF: KDF-derived key cache, lazy cross-DB OTP, deferred HOTP writes, pre-folded labels in search provider
  • BREAKING: GTK 4.10+ and libadwaita 1.5+ required; configuration migrated to GSettings (GKeyFile not migrated automatically)

OTPClient 5.0.0-beta3 - Hide-by-default OTPs, unified backup flow, and fresh-install polish

  • NEW: OTPs are hidden by default - click a row to copy and briefly reveal, then auto-hide (toggle in Settings -> Display)
  • NEW: Settings -> Backup is now the unified entry point for native (encrypted) database backup and restore
  • NEW: Export dialog is migration-only and warns when choosing a plaintext format
  • NEW: dedicated "No database yet" empty-state page on fresh install with Create / Open call-to-action
  • NEW: search-provider requires a trigger keyword (default "otp") to surface results above runner clutter
  • FIX: AdwSpinner template crash on libadwaita 1.5
  • FIX: hide-OTP startup race that left the validity bar frozen
  • FIX: hidden OTP cell is now blank instead of showing partial digits; validity bar hides with the OTP
  • FIX: Add and Import are enabled immediately after first-run create-or-open
  • FIX: "Unlocking…" no longer flashes on fresh install with no database
  • FIX: graceful recovery when the database file is missing on disk (e.g. removed externally)
  • FIX: AdwDialog forms have explicit content sizing; long forms scroll on overflow instead of clipping
  • FIX: import/export hardened against malformed backups; fsync failures are surfaced
  • FIX: weak-ref window in export dialog

OTPClient 5.0.0-beta2 - Hardening, performance, and quality-of-life improvements

  • NEW: backup-age banner reminds you to take periodic backups, with snooze and dismiss-on-export
  • NEW: empty-state page with Add/Import call-to-action
  • NEW: async unlock with spinner so the window no longer freezes during Argon2id
  • NEW: scriptable CLI output (table/json/csv) for --show, --list, --list-databases
  • NEW: refreshed manpages and bash/zsh/fish shell completions
  • NEW: import summary toast and per-format file-picker filters
  • NEW: paste-to-fill otpauth:// in manual-add; KDF presets (Standard/Strong/Paranoid/Custom)
  • NEW: technical-field tooltips in manual-add and KDF dialogs
  • NEW: AdwToast surfacing for previously silent failures
  • NEW: keyboard shortcut to snooze backup reminder via main menu
  • SECURITY: bounds-checked Argon2id parameters on database open
  • SECURITY: KRunner Match no longer leaks live OTP codes via subtitles
  • SECURITY: PR_SET_DUMPABLE=0 + RLIMIT_CORE=0 to prevent secret leaks via core dumps
  • SECURITY: O_NOFOLLOW + fstat on importer paths; refuses symlinks and non-regular files
  • SECURITY: backup files (.bak) created with 0600 mode regardless of umask
  • SECURITY: signal-safe clipboard wipe on SIGINT/SIGTERM/SIGHUP and shutdown
  • SECURITY: CLI --password-file refuses group/world-readable files
  • FIX: KDF byte-length bug - passwords with non-ASCII chars now derive the correct key (with one-shot legacy fallback + opportunistic re-encryption)
  • FIX: HOTP click no longer triggers a full re-encrypt; debounced flush coalesces bursts
  • FIX: search-provider monitors are diffed across reloads instead of torn down and re-armed
  • FIX: token move rolls back on partial failure; cross-DB move invalidates the target KDF cache
  • FIX: import dialog no longer leaks the parsed OTP list on update_db failure
  • FIX: edit-token-dialog JSON refcount leaks
  • FIX: backup-age banner handles clock skew correctly
  • FIX: empty-state CTAs disabled when no database is loaded
  • FIX: signal-quit explicitly flushes pending HOTP writes
  • PERF: KDF-derived key cached across saves; per-save random IV preserves AES-GCM nonce uniqueness
  • PERF: search filter uses pre-folded labels - one casefold per term per query instead of per-entry
  • PERF: search-provider cache TTL extended (5s -> 60s) with per-DB GFileMonitor invalidation
  • PERF: pre-warm search-provider cache after bus ownership so first query avoids Argon2id cost
  • PERF: cross-DB OTP computation is lazy - computed on first row bind rather than upfront
  • BUILD: probes -fcf-protection=full, -fzero-call-used-regs, -fstrict-flex-arrays=2, -ftrivial-auto-var-init=zero
  • BUILD: defaults to Release with LTO when supported

OTPClient 5.0.0-alpha2 - Multi-database support, UI improvements, and bug fixes

  • NEW: persistent multi-database support with sidebar management
  • NEW: sidebar uses AdwOverlaySplitView with toggle button
  • NEW: checkmark indicator for primary database in sidebar
  • NEW: auto-select and copy OTP when search narrows to one result
  • NEW: countdown color pickers in settings
  • NEW: keyboard shortcuts dialog
  • NEW: CLI and search provider migrated to GSettings
  • NEW: CLI --list-databases option
  • NEW: show level bar instead of seconds when show-validity-seconds is disabled
  • NEW: tooltips for sidebar and toolbar buttons
  • FIX: window size not persisted across sessions
  • FIX: context menu crash
  • FIX: use-after-free in async secret lookup
  • FIX: double-free of filter_model in window dispose
  • FIX: DBus assertion on exit
  • FIX: schema not compiled on install
  • FIX: secret service key mismatch
  • FIX: search provider install path
  • FIX: markup parsing warning for shortcuts dialog entry

OTPClient 5.0.0-alpha1 brings a new UI

  • NEW: now using GTK4 and libadwaita

OTPClient 4.4.1 includes the following fixes:

  • FIXED: Ctrl+F search not working due to premature key controller destruction.
  • FIXED: GTK-CRITICAL assertions on close caused by accessing the tree view after widget destruction.

OTPClient 4.4.0 includes the following improvements and fixes:

  • ADDED: cross-desktop search provider for GNOME Shell and KDE KRunner.
  • ADDED: --password-file option for CLI to read password from an external file.
  • IMPROVED: hardened password input by bypassing libc buffering.
  • IMPROVED: modernised application and window layer to GTK idioms.
  • IMPROVED: adapted to libcotp v4 API changes.
  • FIXED: HOTP counter initialisation off by 10^6x.
  • FIXED: is_steam flag leak, GError misuse, and multiple memory leaks.
  • FIXED: memory leaks, NULL dereferences, and security issues across the codebase.
  • FIXED: multiple bugs in search provider (memory leaks, missing gcrypt init).
  • FIXED: --password-file error handling and terminal detection.

OTPClient 4.3.1 includes the following improvements and fixes:

  • IMPROVED: Added configurable colors for the countdown display.
  • IMPROVED: Added support for selecting the countdown display type (numeric value or cake-style).
  • IMPROVED: Automatically disable countdown color pickers when displaying countdown as seconds.
  • IMPROVED: Updated color picker sensitivity dynamically when the display mode changes.
  • IMPROVED: Persisted tree view column widths across application restarts.
  • IMPROVED: Renamed the “OTP Value” column to “OTP” and added column IDs for width tracking.

OTPClient 4.3.0 includes the following improvements and fixes:

  • IMPROVED: Refactored the codebase to follow proper GTK coding patterns and lifecycle management
  • IMPROVED: Added an explicit shutdown event and hardened cleanup to safely handle partially initialized state
  • IMPROVED: Prevented GTK critical warnings on close while still persisting window size when available
  • IMPROVED: Added a main-window empty-state view with a clear call-to-action wired to the manual add flow
  • IMPROVED: Normalized Add menu labels to title case for improved consistency
  • IMPROVED: Enhanced treeview readability with resizable and expanding columns, ellipsized text, and monospace OTP formatting
  • IMPROVED: Replaced the validity text column with a progress bar renderer showing remaining seconds for TOTP entries
  • IMPROVED: Switched visual indicators from bar-based charts to a filled pie for clearer status representation
  • IMPROVED: Clarified header bar actions with labeled icon buttons for add and reorder controls
  • IMPROVED: Grouped export formats into app-specific submenus and clarified password dialog warning text
  • IMPROVED: Improved CLI UX for clearer and more user-friendly interactions
  • REMOVED: Legacy option-migration code that is no longer needed

OTPClient 4.2.0 the followin improvements:

  • ADDED: interactive search (ctrl-f)
  • IMPROVED: search now matches query against type, account label, and issuer uniformly
  • IMPROVED: Streamlined treeview model population to read JSON directly with safe defaults
  • IMPROVED: Simplified OTP update flow and tightened reorder/delete safety and cleanup
  • IMPROVED: Centralized app/db default initialization and early cleanup paths in app.c
  • IMPROVED: Tightened error handling by clearing config migration errors and freeing the config path
  • IMPROVED: Made early-exit cleanup safer by avoiding double-freeing the database key
  • IMPROVED: Added a helper to clear password entries and reset visibility on successful submit
  • IMPROVED: Cleared old/new password fields before the dialog closes to avoid brief exposure
  • IMPROVED: Initialized settings defaults when the config load fails and persisted them to otpclient.cfg
  • IMPROVED: Added warning dialog only when saving fallback defaults fails
  • IMPROVED: cli: improve robustness and correctness in string and file handling
  • FIXED: duplicate windows and tray icons on re-activation (#409)

OTPClient 4.1.1 the following improvements:

  • FIXED: build issue on Flatpak

OTPClient 4.1.0 the following improvements:

  • ADDED: minimize to tray with ayatana-appindicator3 (#386 thanks a lot @len-foss)
  • IMPROVED: only show memlock warning dialog when secure memory is unavailable (#397)
  • IMPROVED: allow creating a database via CLI (#392)
  • FIX: allow using different databases in flatpak (#372)
  • CHANGED: removed andOTP support

OTPClient 4.0.2 brings an important fix:

  • FIX: importing data on a first run (#376)

OTPClient 4.0.1 brings a small fix:

  • FIX: add missing ui file to CMakeLists.txt

OTPClient 4.0.0 brings the following changes:

  • CHANGE: switch from PBKDF2 to Argon2id (#358)
  • NEW: make Argon2id parameters configurable (#358)
  • NEW: add support for importing plain Aegis txt
  • FIX: various issues related to importing Aegis backups (#371)
  • FIX: improving handling of json files (#369)
  • FIX: show db parameters dynamically

OTPClient 3.7.0 brings the following changes:

  • CHANGE: deleting a row, editing a row and showing the qr code is now done via right click on the target row (#359)
  • FIX: multiple fixes to QR handling (#364)
  • FIX: exporting to FreeOTP+ format (#367))
  • FIX: updated otpclient and otpclient-cli man pages (thanks @fvcr)
  • FIX: code more readable thanks to macros

OTPClient 3.6.0 brings a new feature and internal improvements:

  • NEW: add possibility to import plain/encrypted backups using the CLI
  • FIX: make GUI and CLI independent, so that CLI only can be built and installed without GTK.
  • FIX: check file size against memlock before importing a backup
  • FIX: code cleanup and internal refactoring

OTPClient 3.5.2 brings some small improvements:

  • NEW: add possibility to export plain/encrypted Authenticator Pro/2FAS backups using the CLI
  • FIX: improve popover layout
  • FIX: exporting plaing Aegis via CLI
  • FIX: cleanup code

OTPClient 3.5.1 brings a small improvement and some code clean-up:

  • NEW: add back buttons to the various popover menus
  • FIX: split popovers into their own UI files
  • FIX: remove upgrade message when upgrading from a version older than 2.6.0

OTPClient 3.5.0 brings some new features and improvements:

  • NEW: add support for importing and exporting plain/encrypted 2FAS backups (#322)
  • NEW: add support for importing and exporting plain/encrypted AuthenticatorPro backups (#322)
  • CHANGE: show warning when exporting a plain backup
  • CHANGE: remove support for older Glib and GCrypt
  • FIX: add 2fa keyword to the desktop file (#349)
  • FIX: remove custom keywords from metadata file (#348)
  • FIX: returning to a dialog won't crash the widget

OTPClient 3.4.1 brings a single fix::

  • FIX: fix FreeOTP+ export (thanks @hubnut)

OTPClient 3.4.0 brings the following changes:

  • NEW: you can now specify a database when calling the CLI (#340)
  • FIX: handling errors when path and/or password is incorrect (#336)
  • FIX: prompt for file again, if needed (#335)
  • FIX: prevent about dialog from hiding
  • FIX: use system RNG as source of entropy

OTPClient 3.3.0 brings the following changes:

  • NEW: set background to red when delete mode is entered (#323)
  • FIX: handling of base32 string (#328)

OTPClient 3.2.1 fixes a couple of issues.

  • FIX: increase secure memory pool to 64 MB, if possible
  • FIX: parsing of big aegis encrypted json

OTPClient 3.2.0 fixes a couple of issues.

  • NEW: add file chooser dialog on export (#305)
  • FIX: overwrite exported file instead of appending it (#305)
  • FIX: exported file will be accessible only by the current user (#305)
  • FIX: multiple issues related to failed first launch (#303)
  • FIX: couple of issues with secret-service

OTPClient 3.1.9 brings a couple of fixes:

  • fix db corruption (#301)
  • fix crash when user changes db multiple times

OTPClient 3.1.8 brings a single fix

  • Fix importing Aegis plain json

OTPClient 3.1.7 brings many fixes

  • Add new Database info dialog
  • Fix crash when no row is selected (#295)
  • Fix UI when creating/changing a database
  • Multiple fixes when creating a new database
  • Use current db folder when creating/changing database
  • Fix memory leak in case of error when opening the settings dialog

OTPClient 3.1.6 fixes a security issue.

  • quit the password dialog when either the cancel or close button is pressed

OTPClient 3.1.5 fixes an issue when dealing with symlink

  • allow the db to be a symlink and follow it correctly (#289)

OTPClient 3.1.4 brings some fixes

  • make auto-lock and secret service mutually exclusive (#279)
  • fix importing plain AEGIS (#281)
  • fix importing encrypted AEGIS on some distros (#281)
  • rename disable_secret_service setting to use_secret_service

OTPClient 3.1.3 brings some fixes

  • Fix Aegis import/export when using long pwds (>64 chars)
  • Fix secret service cleanup
  • Show the correct error message when import fails
  • Use g_utf8_strlen instead of strlen

OTPClient 3.1.2 brings compatibility with newer cotp.

  • Add compatibility with libcotp >= 2.0.0

OTPClient 3.1.1 brings lots of small under-the-hood changes:

  • Fixed some memory leaks
  • Improved error handling
  • Use secure functions instead of standard ones

OTPClient 3.1.0 the following feature and fixes:

  • New feature (#258): entries can be displayed as a QR-Code
  • Updated the artwork credits in the about dialog
  • All keyboard shortcuts have been revised, be sure to check them (Ctrl-k)
  • Code cleanup

OTPClient 3.0.0 brings some exciting news:

  • New feature (#263): OTPClient is now translatable (open a GitHub issue if you want to help translating it in your language).
  • New feature (#259): it's now possible to edit also the secret.
  • Improved: an About dialog has been added in the settings menu.
  • Removed (#257): Authenticator Plus support has been removed.
  • Various small fixes.

OTPClient 2.6.4 fixes an import issue

  • fix issue when importing encrypted AEGIS backup.

OTPClient 2.6.3 fixes an issue when setting the migration flag

  • fix ternary operator logic that would incorrectly set the migration flag

OTPClient 2.6.2 add an upgrade message

  • warn user about new secret service behavior

OTPClient 2.6.1 some fixes and a new feature

  • add ability to import Google migration QR also via webcam
  • fix double free in case of error

OTPClient 2.6.0 brings lots of new features

  • add support for importing SVG tokens
  • add support for importing and exporting Aegis encrypted backups
  • add support for importing Google otpauth-migration QR codes
  • improve enetry deletion workflow
  • add support for libsecret
  • show video feed when importing a token using the webcam
  • fix andOTP import bug

OTPClient 2.5.1

  • Fix markup on change database dialog

OTPClient 2.5.0 brings load of new features

  • NEW: rows can now be sorted. Enable the sorting mode by using the "up down" arrows button on the top, then drag and drop rows where you want (#184).
  • NEW: added a dark theme (enable it settings) (#207)
  • NEW: allow to switch database. This is useful if you have multiple OTPClient databases (e.g. work, personal, etc) (#186)
  • NEW: add a button to lock the app (#236)
  • FIX: when app is locked, the content is now hidden (#235)
  • FIX: it's now possible to change the database, if the wrong one was selected during the first run (#196)

OTPClient 2.4.9.1 fix a regression

  • fix importing QR code both when URI contains and doesn't contain one or more UTF-8 chars.

OTPClient 2.4.9 fix an import issue

  • fix importing QR code (issue#240)
  • better error when importing a QR fails

OTPClient 2.4.8 brings a couple of fixes

  • fix show next OTP option (issue#234)
  • correctly decode URIs from QR codes

OTPClient 2.4.7 implements some small code optimization

  • do not use strlen in for loop
  • do not use strlen to check for empty string

OTPClient 2.4.6 fixes some small issues

  • check for NULL when comparing account and issuer
  • use secure_strdup when trimming the account key
  • fix account/issuer when importing andOTP db (tested with latest available version)
  • use g_memdup2 when available

OTPClient 2.4.4 disabled a broken feature

  • remove possibility to sort columns by either account or issuer due to GtkTreeView issues. This feature will come back with 3.0.0

OTPClient 2.4.3 contains some small fixes

  • fix a small andOTP export bug
  • fix wrong icon in taskbar
  • remove hard-coded paths from get-builder.c

OTPClient 2.4.2 contains a small fix to andOTP handling

  • fix handling of andOTP data when importing/exporting, thanks to Michal Borek for the contribution

OTPClient 2.4.1 bring a new feature to the CLI

  • add export command to otpclient-cli

OTPClient 2.3.2 brings a small fix and a new icon

  • fix incorrect code is shown when sorting by label/issuer
  • new icon, thanks a lot @bertob

OTPClient 2.3.1 brings a security fix

  • fix a memory leak when exporting to freeotp format

OTPClient 2.3.0 brings support for a new provider

  • add support for importing and exporting plain json Aegis backups

OTPClient 2.2.1 fixes a long standing bug

  • fixed a bug that prevented andotp backups generated with a long password to be correctly imported

OTPClient 2.2.0 brings support for FreeOTP+

  • it's now possible to import and export FreeOTP+ backup (key URI format only)
  • minor fixes to the first startup dialog

OTPClient 2.1.0 brings some minor enhancements to the UX

  • save sort order on exit and allow user to reset it to the default value using the button located in the settings menu
  • on first start, allow user select whether a new database has to be created or an existing one has to be imported

OTPClient 2.0.1 is a minor release that brings some fixes

  • show dialog if memlock value is too low
  • fix memory leak on parse-uri
  • fix a double free in case of a crash
  • better error handling
  • multiple fixes to db handling

OTPClient 2.0.0 is a major release that brings tons of new features

  • add plain text import/export for andOTP
  • add lock feature
  • add CLI (currently supports list and show commands)
  • support import/export of encrypted andOTP backups generated with version >=0.6.3
  • treeview can now be sorted by clicking on the account/issuer column header
  • QR code can be added from clipboard (supports both gnome and kde)
  • minor fixes

OTPClient 1.5.1 brings some small flatpak related fixes

OTPClient 1.5.0

  • add shortcut to quit the application
  • use native dialog for open and save actions
  • show error dialog if database is missing
  • rename "label" to "account name"
  • correctly handle empty label and/or issuer when editing a row
  • respect XDG_CONFIG_HOME

OTPClient 1.4.1 brings some fixes to the flatpak version.

  • fix setting menu not being accessible
  • fix window size not being remembered

OTPClient 1.4.0 brings full support to andOTP.

  • it's now possible to export encrypted andOTP backups
  • use monospace to show the database path on startup

OTPClient 1.3.1 brings some fixes to bugs that were introduced with the previous version.

  • fixed a bug that caused a row with an empty issuer to be treated as a steam code
  • fixed an issue that prevented the same item to be deleted and added again
  • the correct password dialog is displayed when importing something while the local db is empty

OTPClient 1.3.0 brings a lot of new features and fixes.

  • reworked UI
  • support for custom digits (between 4 and 10 inclusive)
  • support for custo period (between 10 and 120 seconds inclusive)
  • support for Steam tokens
  • add keyboard shortcuts
  • add settings menu
  • search by either label or issuer

OTPClient 1.2.2 brings some small fixes.

  • add "native" support for Ubuntu 16.04
  • add shippable support

OTPClient 1.2.2 brings some minor fixes.

OTPClient 1.2.2 brings some minor fixes.

  • it's now possible to edit the label and issuer fields
  • when a row is ticked, the otp value is automatically copied to the clipboard (which is erased before terminating the program)
  • a small help is shown on the first start
  • 3 new ways to add a token in addition to Manually (screenshot, using webcam and by selecting a qrcode)
  • some bugs fixed
  • cmake related improvements