Repository navigation
v0.25.0
What's Changed
Added
- New Subgroup in a folder's context menu — right-click a group, then New Subgroup, opens the New Group dialog titled "New Subgroup" with that group already chosen as the parent (change it in the dialog if needed). Until now a subgroup meant opening New Group and picking the parent from the dropdown. Hidden on Cloud Sync import groups, like New Connection in Group, since their content mirrors the source. Translated in all 19 catalogues. (
rustconn/src/sidebar_ui.rs,rustconn/src/window/connection_actions.rs,rustconn/src/window/connection_dialogs.rs,po/) - Duplicate and Move to Group on a folder's context menu — Duplicate copies a group with its subgroups and connections beside the original as "name (copy)", and selects the copy. The copy is a plain folder tree: Cloud Sync links (
sync_mode, file,sync_origin_id) are dropped, so a Master copies as an ordinary group; a group's saved vault password is not copied (the copy's password source becomes None; username and domain stay); connections' own vault passwords are copied as a single Duplicate does; dynamic connections are left to the next refresh. Hidden on Cloud Sync import groups and dynamic folders, whose content is generated. Move to Group…, which already handled folders, is now offered on the menu too (not on import groups). (rustconn-core/src/connection/group_copy.rs,rustconn/src/window/operations.rs,rustconn/src/window/edit_actions.rs,rustconn/src/sidebar_ui.rs) - Create Another in the New Group dialog — a Create Another switch keeps the dialog open after a group is created: the name is cleared and focused, a toast names the group just made, and the parent, credentials and description stay for the next one. Applies to New Subgroup too. (
rustconn/src/window/connection_dialogs.rs) - Split a whole set of tabs in one step — the tab context menu has Split with Other Tabs… (#423): tick the tabs to bring along and they fill a balanced grid on the right-clicked tab, instead of splitting once and picking each tab with Select Tab…. Also on Ctrl+Shift+K (rebindable), so it works from the keyboard (then Tab/Space/Enter in the dialog), the dialog labels every row for screen readers, and the sessions are moved, not reconnected. The balanced-grid planner is now shared with workspace restore (
rustconn_core::split::balanced_split_plan, with unit tests). (rustconn/src/dialogs/split_tabs.rs,rustconn/src/window/split_view_actions.rs,rustconn/src/terminal/tab_menu.rs,rustconn-core/src/split/balanced.rs,docs/USER_GUIDE.md) - Choose the monitors of an external RDP window — the connection dialog has a Monitors row under External Window: FreeRDP monitor numbers, comma-separated, with the screens GTK reports listed in its subtitle. They become
/monitors:(plus/multimon, which FreeRDP needs outside single-monitor fullscreen); empty keeps FreeRDP's current-monitor default and All monitors keeps/multimon. Stored asmonitor_ids, omitted when empty, so older connections load unchanged and older versions ignore it. A list with something that is not a number is marked in the dialog and refused on save, instead of being dropped. External FreeRDP only; embedded sessions can still go fullscreen on one screen from the tab menu. (rustconn-core/src/models/protocol.rs,rustconn-core/src/protocol/freerdp.rs,rustconn/src/dialogs/connection/rdp.rs,docs/USER_GUIDE.md) rustconn-cli importreads PuTTY and mRemoteNG files —-f puttytakes a PuTTY / KiTTY.regRegistry export and-f mremotengtakes an mRemoteNGconfCons.xml, through the same importers the GUI uses, so the README's import list is now true for the CLI too. (rustconn-cli/src/cli.rs,rustconn-cli/src/commands/export_import.rs,docs/CLI_REFERENCE.md)- Saved searches in the sidebar — the Filter menu now lists named searches: Save current search… stores the search text together with the ticked protocols, a click applies it (the same text in the search field, so the same list as typing it), and pencil / bin buttons rename or delete it. Kept in the settings file (
ui.saved_searches, up to 50), not inconnections.toml; older versions ignore the key. (rustconn-core/src/search/saved.rs,rustconn/src/sidebar/saved_searches.rs,docs/USER_GUIDE.md) - CI runs the ignored GTK tests — new
gui-testsjob executes all 18 under Xvfb, one process per test (scripts/run-ignored-gui-tests.sh) - CI launches the GUI headlessly — new
gui-smokejob runsrustconn --versionand a 10 s start under Xvfb, failing on a panic or early exit (scripts/gui-smoke.sh) - CI lints the RPM spec — new
rpm-specjob runsrpmspec -Pandrpmlint; the filtered warnings are documented inpackaging/obs/rustconn.rpmlint.toml - A missing desktop portal is reported — at startup RustConn asks
xdg-desktop-portalfor its file-chooser backend (3 s limit) and shows one warning toast, plus a log line, when the service or the backend (xdg-desktop-portal-kde/-gnome/-gtk) is absent, instead of file dialogs silently failing - More terminals for the 1Password sign-in button — it tries
xdg-terminal-exec,ptyxis,kitty,footandalacrittybeforegnome-terminal,konsole,xfce4-terminalandxterm - Pulsing indicators respect "reduce animations" — the tunnel "starting" dot and the active broadcast icon stay still when the desktop turns
gtk-enable-animationsoff, and follow the setting live - Empty Trash action —
win.empty-trashasks for confirmation, then permanently removes everything in the trash (and its vault credentials), now that deleted items stay there until it runs. It is reached from the Trash row in the sidebar. The vault credentials are removed on a worker thread (about 0.7 s each with a KeePass file), so the window stays responsive: the Trash row and the "Trash emptied" toast appear at once, and the header-bar spinner shows until the cleanup ends. The group hierarchy used to rebuild the credential keys includes the trashed groups, so a credential under a deleted group is found. (rustconn/src/state/connections.rs,rustconn/src/window/edit_actions.rs) - Trash row in the sidebar — like Favorites, but at the bottom of the tree and only while the trash holds a deleted connection or group. It expands to the deleted items; right-click an item → Restore (the same
win.undo-deleteas the Undo toast) or Delete Permanently…, right-click the row → Empty Trash. The row updates after a delete, an undo, a restore and an empty, without a restart; it has an accessible label with the item count. Trashed rows carry non-UUID ids, so connect, edit, delete and drag skip them. The context menu of the row is sized to its items, with a scrollbar only for a menu taller than the cap. (rustconn/src/sidebar/trash.rs,rustconn/src/sidebar/mod.rs,rustconn/src/window/sorting.rs,docs/USER_GUIDE.md) - Delete Permanently… on a trashed item — right-click a connection or group under the Trash row → Delete Permanently… asks for confirmation, then removes only that entry from the trash, the single-item counterpart of Empty Trash. Its saved vault credential is deleted on a worker thread with the header-bar spinner showing, unless a live connection or another connection still in the trash resolves to the same vault entry; a deleted Web connection's browser data goes too. A group's own trashed connections stay in the trash; restoring one after its group was deleted permanently puts it at the top level instead of under a missing group, where the sidebar never showed it, so its vault key no longer includes that group's path. A connection restored while its group is still in the trash keeps the group, and appears with it when the group is restored. The item menu no longer offers Empty Trash next to it; the Trash row still does. (
rustconn/src/sidebar_ui.rs,rustconn/src/sidebar/trash.rs,rustconn/src/window/edit_actions.rs,rustconn/src/state/connections.rs,rustconn-core/src/connection/manager.rs,po/) - Settings → Clients keeps detection results for five minutes and has a Refresh button — reopening the dialog no longer re-runs every client probe; the refresh button in the Core Clients header forces a new scan. (
rustconn/src/dialogs/settings/clients_tab.rs,rustconn-core/src/protocol/detection.rs) - Invalid saved entries are reported, never removed — loading connections, groups, snippets, clusters and templates now logs a warning for each entry that fails validation (empty name, empty host, port 0) and keeps the data exactly as saved. A test checks that such a config loads and stays byte-identical on disk. (
rustconn-core/src/config/manager.rs) - CodeQL skips
rustconn-cli/testsandtests.rsfiles — CodeQL for Rust has no way to exclude inline#[cfg(test)]modules, so those stay in scope. (.github/codeql/codeql-config.yml)
Fixed
- Clear Session Data in the embedded browser asks first — the browser menu item, now Clear Session Data…, erased the site's cookies and saved logins at once. It opens a confirmation that says what will be lost, with Cancel as the default and Escape response and a destructive Clear; only Clear erases the data. (
rustconn/src/embedded_web/navigation.rs,po/) rustconn-cli run-scriptreads a.kdbxset on a connection or group (#411) — it read saved passwords from the global KeePass database only, so a host with its own database got no saved password and fell back to its keys. It now opens the database the GUI does: the connection's own, else its nearest group's, else the global one, with the same database password and key file; an inherited password is read from the group's database. (rustconn-cli/src/commands/run_script.rs)- A subgroup made inside a Cloud Sync Master tree is exported — creating a group under a parent never told the export channel, so the new subgroup waited for an unrelated change to the tree before the Master wrote it. (
rustconn-core/src/connection/manager.rs) - A save no longer drops connections another process wrote — the window saved its whole in-memory list over
connections.toml,groups.tomlandtrash.toml, so arustconn-cli add(or a second instance) made while the window was open vanished at the window's next save. Every save now reads the file under the write locks and merges it with the window's list by id against the state it last saw: an entry the other process added is kept, one it removed is removed here too, an edit on one side only is taken, and when both sides edited the same entry the newerupdated_atwins (this window on a tie). A deletion made in the window is honoured. A file that cannot be parsed is replaced as before, and a file that already matches the merge is not rewritten. (rustconn-core/src/config/merge.rs,rustconn-core/src/config/manager.rs,rustconn-core/src/connection/manager.rs) - Connections added with
rustconn-cliappear in a running window — the window watches the three files and, a moment after another process rewrites one, merges the change in (ConnectionManager::reload_from_disk) and refreshes the sidebar, with no restart. A reload never waits for a disk write: if a save is running it tries again a second later. If the directory cannot be watched the window still merges on save and only loses the live update. (rustconn-core/src/config/watch.rs,rustconn/src/app.rs) - A WinRM or Telnet connection now turns green in the sidebar — a fresh connect never counted the session, so the row stayed on "connecting" while the shell was already open; only reconnect, SSH and Zero Trust did. It now uses the same established-check as an in-place reconnect, counted from below the connect banner. (
rustconn/src/window/protocols.rs) - A jump host or key path with a shell metacharacter could run a command — the
ProxyCommandthat ssh hands tosh -cfor a jump host (a hop with its own password, an identity file, PKCS#11, or Flatpak) took the hop address and the-ikey path as written, so a host such asbastion;cmdfrom an imported or synced connection ran locally when the connection was opened. Every such value is now one shell word (single-quoted when it holds anything but letters, digits and@:./-_%,=+[]), a hop that starts with-is no longer read as an ssh option, and a PKCS#11 provider path with a space or metacharacter is left out, as the tunnel route already did. (rustconn-core/src/ssh_tunnel.rs,rustconn-core/src/jump_route.rs) -f puttyon a realregeditexport —regeditwrites UTF-16 with a byte-order mark, which the importer rejected as unreadable text; UTF-16 (either byte order) and UTF-8 with or without a BOM are now read, in the GUI and the CLI. (rustconn-core/src/import/putty.rs)- CLI downloads over HTTPS only, with timeouts — a redirect to
http://could swap a download whose vendor publishes no checksum (AWS CLI, SSM plugin, gcloud, cloudflared, 1Password CLI), and a stalled server hung the download. Redirects must stay on HTTPS, connecting is limited to 30 s and each stalled read to 60 s. (rustconn-core/src/cli_download/download.rs) passandgpgstay behind after a timeout — the caller drops the call on timeout, and the child kept waiting on pinentry; it is now killed with the call. (rustconn-core/src/secret/pass.rs)- A damaged machine-bound credential store no longer quotes its content in the error — the parse error names no value. (
rustconn-core/src/secret/encrypted_file.rs) - Tray click now hands the window its activation token on Wayland — the tray library hands over the compositor's activation token with each click, but
present()never received it, so KWin treated the raise as focus stealing and only flashed the taskbar entry. The token is now passed to the window before it is presented (rustconn/src/tray.rs,app.rs) - PTY descriptors leaked into every child process —
openptydoes not set close-on-exec, so the master and slave of each terminal session were inherited by anything spawned afterwards, from any tab; a process that kept the master open could stop a closed session from ever seeing its hangup.rustconn-pty-sys::open_pty_pairnow setsFD_CLOEXECon both, keeps the OSerrnoin its error, andpty_wait_readablereports a closed descriptor (POLLNVAL) asEBADFinstead of "not ready", which made the reader loop spin. (rustconn-pty-sys/src/lib.rs) - Sync exports were briefly world-readable and not crash-safe — Simple Sync files were created with the umask and set to
0600only after the rename (ignoring a failure), with a fixed temp name and nofsync; the machine-bound credential store also skippedfsyncbefore its rename, so a power loss could leave it empty. All eight temp-and-rename writers (config, both credential stores, sync exports, custom themes, recordings, OpenH264) now sharerustconn_core::fs_atomic::atomic_write, which creates the temp file with its final mode,fsyncs it, removes it on any failure and syncs the directory. (rustconn-core/src/fs_atomic.rs) - An invalid custom log-sanitize pattern was silently ignored —
SanitizeConfig::with_custom_patterndropped a regex that did not compile while keeping it in the list, so a pattern meant to hide a secret hid nothing. It now returnsLogError::InvalidPattern. (rustconn-core/src/session/logger.rs) - Passbolt passphrase visible in the process list — the GPG passphrase went to
go-passbolt-clias--userPassword, readable by any user in/proc/PID/cmdline. It now goes through the child's environment (USERPASSWORD), which only the owner can read. The resource password still has to be an argument; this and the RDP gatewayZeroizingexception are now documented inAGENTS.md,docs/ARCHITECTURE.mdandSECURITY.md. (rustconn-core/src/secret/passbolt.rs) - Six CLI downloads installed without any integrity check — kubectl, Teleport, Tailscale, Boundary and Hoop are now checked against the SHA256 their vendor publishes for that exact release, and the Bitwarden CLI against GitHub's asset digest; a missing or wrong hash stops the install. The Bitwarden and 1Password installers had not consulted the checksum policy at all. (
rustconn-core/src/cli_download/) - A WinRM argument could be lost in release builds —
WinRmClient::commanddropped the first argument whatever it was, guarded only by adebug_assert. It now replaces only a leadingevil-winrm. (rustconn-core/src/protocol/winrm.rs) - A host name or option with a line break can no longer add directives to the ssh configuration Midnight Commander uses — the generated
ssh_configtook the host, jump hosts,ProxyJump, custom options and key paths as written, so an imported connection or a Dynamic Folder script could slip in aProxyCommandof its own. A connection with such a value now opens mc without the wrapper, so it gets no jump host and no saved password, and the log names the option (not its value). - Known-hosts and key paths with an apostrophe,
${VAR}or%reach ssh as written — an apostrophe in the Flatpakknown_hostspath made ssh fail on the option,${HOME}in it was expanded, and the mc ssh configuration read%din a key path as a token. A path ssh cannot be given is left out, as before. The remote clean-up after a session recording quotes its paths as well. rustconn-cli completionsandman-pageno longer panic in a debug build — the global--configand several subcommands (--connectioningroup,cluster,tag,history;--commandinsnippet add/edit;--categoryinsnippet list) all claimed-c, andsnippet run --varclaimed the global-v. Release builds skip clap's check, so only debug builds crashed. A test now validates the whole command tree. (rustconn-cli/src/cli.rs,rustconn-cli/tests/integration_tests.rs)packaging/obs/rustconn.specmacros in comments and%changelog—%description,%prep,%build,%find_lang,%checkand%{?fedora}in prose were expanded by rpm (rpmspec warned "Macro expanded in comment"); now escaped as%%start <name> cluster=<name>in a script stopped silently ignoring the cluster — the script engine parses the option but the GUI never implemented it, so the session started as a plain connection. The script now ends with "cluster= is not supported", and the script reference and User Guide no longer list the option.- Bitwarden Unlock no longer freezes the window on a slow keyring — the saved master password is read from (and, after a typed password unlocks the vault, written to) the system keyring on the worker thread instead of the GTK thread, where a hung Secret Service blocked the whole application for up to 5 s.
- Monitoring and scripts are stopped when they should be — closing the main window now stops every monitoring collector (
MonitoringCoordinator::stop_all), and closing a tab cancels a script still running on it, which used to keep its timer and entry alive. (rustconn/src/window/mod.rs) - A permanently deleted connection leaves workspaces — once a deletion is final (Empty Trash) the connection is dropped from every workspace profile that listed it; Undo still restores it with its workspace entries. (
rustconn/src/state/connections.rs) - The Smart Cards switch says when it does nothing — with the Embedded RDP client the switch now reads "Not used in Embedded mode. Set Client Mode to External RDP client." The saved value is untouched. (
rustconn/src/dialogs/connection/rdp.rs)
Changed
- A deleted connection or group stays in the Trash until you empty it — until now a deletion was made permanent when its Undo toast closed (or at once for a bulk delete, which has no Undo), so the Trash row held items only for a few seconds. They now stay in the trash, which is saved across restarts, and the Trash row restores them at any time; only Empty Trash removes them and their saved vault credentials. The Undo toast remains as a shortcut, and a bulk delete of several selected items also lands in the Trash. Until the trash is emptied, the password of a deleted connection stays in your vault, and the trash has no size or age limit. (
rustconn/src/toast.rs,rustconn/src/window/edit_actions.rs,rustconn/src/window/operations.rs,rustconn/src/state/connections.rs,docs/USER_GUIDE.md) - Secret Service client updated to oo7 0.7 (ashpd 0.14) — the GNOME Keyring / KWallet backend and the Flatpak portal path use the new client. The calls RustConn makes are unchanged. oo7 0.7 matches items stored without an
xdg:schemaattribute against the generic schema, and handles unencrypted keyrings. (Cargo.toml) - Screen-lock and suspend listener moved to zbus 6 — it needs no code change in behaviour. zbus 6 no longer depends on the unmaintained
zvariantandzbus_namescrates, so only the tray library still pulls them. (rustconn-core/src/lock_events/dbus.rs,Cargo.toml) - Config file locking uses the standard library —
File::try_lockreplaces thefs2crate; the lock is the same advisoryflock. (rustconn-core/src/config/manager.rs) rustconn-cli --confighas no-cshort form any more, andsnippet run --varhas no-v— after a subcommand-calready meant that subcommand's own flag, and the docs use-c <connection>throughout, so the global short was the one to drop. Use--config <dir>orRUSTCONN_CONFIG_DIR, and--var key=value. (rustconn-cli/src/cli.rs,docs/CLI_REFERENCE.md)scripts/verify.shnames the tools it could not run — a closing "NOT CHECKED" line lists every gate skipped for a missing tool, so a green run no longer hides them- Translated desktop entry — the desktop entry now carries
Name,GenericName,CommentandKeywordsin every language ofpo/, merged in withmsgfmt --desktopwhen the Flatpak, Snap, RPM, Debian, AppImage,.deb/.rpmrelease and Nix packages are built. Before, the translations were extracted into the catalogues but never reached the installed file, and only five hand-writtenComment[xx]lines were shipped. Adds a translatedGenericName("Connection Manager"). (rustconn/assets/io.github.totoshko88.RustConn.desktop,po/*.po) scripts/release.shvalidates the Nix flake — whennixis installed it runsnix flake check --no-buildand evaluatespackages.default; withoutnixthe gate is listed as skipped.packaging/nixpkgs/package.nixjoinsPKG_FILES, so its version is bumped byscripts/bump-version.shand checked at release.- Saving the connection lists no longer copies them — every
save_*inConfigManagercloned the whole list into a wrapper just to serialize it; the wrappers now borrow (Cow), so a save no longer doubles the memory of a large connection list - Fewer processes spawned for detection —
virsh(libvirt import dialog) and theop,passboltandpasssecret backends are found by an in-processPATHlookup instead of running--versionbefore every secret operation - Group sync applies updates by index —
GroupSyncPlan::apply_tolooked every updated item up with a linear scan and every deletion withVec::contains; it now builds an index once, so large groups no longer cost O(N·U) - RDP printer discovery no longer parks the runtime — the
lpstatqueries run inspawn_blocking(still bounded by the 2 s limit) rustconn-cli monitor metricshelp says it shows the effective monitoring configuration, not live metrics;cluster create/edit --broadcastis hidden and documented as the no-op it has been since 0.14.8 (still accepted)- Fewer main-loop wake-ups —
spawn_blocking_with_callback/spawn_blocking_with_timeout(68 call sites) and three start-up waits (tray creation, Bitwarden auto-unlock, secret-backend probe) now wait on a one-shot future instead of a 16 / 50 / 100 ms polling timer. - Sidebar search no longer deep-clones every group per keystroke —
SearchEngine::search_refsandDebouncedSearchEngine::search_debouncedtake&[&ConnectionGroup];searchkeeps its signature. (rustconn-core/src/search/mod.rs,rustconn/src/window/mod.rs)
Removed
- Nine unused credential-resolver methods —
CredentialResolver::{needs_keepass_migration, migrate_to_keepass, store_unified, resolve_verified, store, retrieve, delete}_with_hierarchy,move_credential_on_group_changeandrename_credentialhad no callers (the GUI uses its ownvault_ops);resolve_with_hierarchystays. (rustconn-core/src/secret/resolver.rs) - Unused connection-string interner —
StringInterner,interner(),InternerStatsand theintern_*/*_interning_statsfunctions are gone fromrustconn-core: the interned strings were thrown away, so the global set only grew and took a lock on every connection add or update. (rustconn-core/src/performance/,rustconn-core/src/connection/) - Unused core modules —
rustconn_core::cache(Cached,CacheRef,LoadCacheObject) andrustconn_core::drag_drop(DropConfig,calculate_*,ItemType; the GUI has its own insidebar) had no callers and are gone - Dead GUI code — the window actions
copy-username,copy-password,cluster-from-selectionandselect-item-by-id(no menu, shortcut or palette entry used them), thedialogs::keyboardanddialogs::adw_dialogsmodules,block_on_async/ensure_main_thread/is_main_thread, the unused tab activity/silence indicator CSS classes, and about 40 functions that nothing called (FreeRDP detection helpers, formatting and accessibility helpers, terminal and dialog getters). - Unused
HistorySettings.track_quick_connect— nothing read it; configs that still contain the key load unchanged (covered by a test) and it is dropped on the next save. (rustconn-core/src/models/history.rs) - Unused
SearchEngine::fuzzy_score_optimizedand its two private helpers — nothing called it outside its own unit tests;fuzzy_scoreis what search uses.search::benchmarkstays (integration tests and saved-search tests use it). (rustconn-core/src/search/mod.rs)
Improved
- Every group picker has a search field — Move to Group, Move Selected, the New Group / New Subgroup parent, the connection editor's Group, the Edit Group parent, Batch Edit's Group, the smart folder's Filter by Group and the export dialog's Group scope now filter as you type, the way the jump-host pickers already did. Matching is case-insensitive substring, so typing
RubyStudiofindsImport/Dev/AimSmarter/RubyStudio; the jump-host, tunnel and On startup pickers switch from prefix to substring matching too. Theadw::ComboRowpickers (Edit Group parent, Batch Edit Group, Settings' On startup) need libadwaita 1.6 for substring matching and keep prefix matching in builds withoutadw-1-6. (rustconn/src/dialogs/widgets.rsenable_string_search,enable_combo_row_search) - Tests for the lock listener, the SSH key unlock dialog and the failed-command marker, with the dialog's outcome decision and the marker's bar placement moved out of GTK code; the keyring save helpers in Settings share one timed helper, and the client version checks use
rustconn_core::proc::wait_bounded. (rustconn-core/src/lock_events/dbus.rs,rustconn/src/dialogs/key_unlock.rs,rustconn/src/terminal/failed_marker.rs,rustconn/src/dialogs/settings/secrets_tab/keyring.rs,rustconn/src/dialogs/settings/clients_tab.rs) - One tested rule for when mc's ssh gets the saved password —
mc_ssh::password_planreplaces checks that were spread over GUI code with no tests. Behavior is unchanged. - A jump host's password travels with its hop — the route builder takes hops that carry their own password instead of two parallel lists, and the tunnel's jump-host route lives in
rustconn-core(jump_route::tunnel_jump_args). Behavior is unchanged. - Packaging metadata descriptions — the AppStream metainfo and
RustConn.doapnow mention WinRM, Web, SOCKS5 and Run Local Script. - Packaging fixes —
packaging/nixpkgs/package.nixwas stuck at 0.19.4 and now follows the release version; 60%changelogentries inpackaging/obs/rustconn.specnamed the wrong weekday (rpmspec"bogus date"), and the ignored GTK testfractional_scroll_position_is_kept, which failed on VTE 0.84 because it read the scroll adjustment of a terminal that was never placed in a window, now presents it in one first. Nobody noticed the test because no CI job ran the ignored tests. - CI — new
Nix flakejob (runs on pull requests that touchflake.nix,Cargo.toml,Cargo.lock) andDesktop and AppStream metadatajob (desktop-file-validateon the source and merged desktop file,appstreamcli validate --strict).
Documentation
- The async helpers section of
docs/ARCHITECTURE.mdandrustconn/AGENTS.mdnames the helpers that exist —spawn_async,with_runtime,spawn_blocking_with_callbackandspawn_blocking_with_timeout;spawn_async_with_callback,block_on_async_with_timeout,is_main_threadandensure_main_threadare gone. codec download-h264is in the CLI reference, andscripts/check-cli-docs.sh(run byscripts/verify.sh) fails when any subcommand from--helphas no entry indocs/CLI_REFERENCE.md. (docs/CLI_REFERENCE.md,scripts/check-cli-docs.sh,scripts/verify.sh)- Docs match the code again — feature tables in
docs/BUILD.md,docs/ARCHITECTURE.mdand therustconn-corecrate docs listweb-embedded,bitwarden-serve,lock-eventsandadw-1-10; the Protocol trait section shows the realcapabilities()default and all sixteenProtocolCapabilitiesfields, and names WinRM and Zero Trust; the split-view note no longer mentions an embedded SPICE widget that was removed in 0.18.0;rustconn-pty-sysis documented with itsnixdependency and as used for every VTE session;-syscomments no longer say no CI job builds macOS; theunsafesection ofdocs/ARCHITECTURE.mdnow points at each crate's own contract instead of repeating it; the attestation example indocs/INSTALL.mduses<version>. (docs/ARCHITECTURE.md,docs/BUILD.md,docs/INSTALL.md,rustconn-core/src/lib.rs,rustconn-core/src/performance/mod.rs,rustconn-pty-sys/AGENTS.md,rustconn-pty-sys/src/lib.rs,rustconn-dock-sys/src/lib.rs,rustconn-env-sys/src/lib.rs) - Local tooling —
CONTRIBUTING.mdlists typos, cargo-machete, cargo-nextest, cargo-deny, cargo-audit, rpmlint and Xvfb with what uses them, and the ~23 GB debugtarget/size - Nix
flake.lockpolicy documented indocs/INSTALL.mdandflake.nix: no lock is committed on purpose. The release-verification example no longer names a fixed version. - Accessibility and KDE/Wayland in the User Guide — new Accessibility section (keyboard-only use, screen-reader limits, leaving an embedded session with the keyboard, reduced motion) and a "KDE Plasma and Wayland" troubleshooting entry (tray, portals, external terminal, Flatpak on a KDE host)
Ctrl+Shift+Y(Reconnect Session) is in the User Guide shortcut table.tmux_controlis marked experimental in its module docs anddocs/ARCHITECTURE.md: a tested parser and model that the GUI does not use yet.- Workspace
split_directionsis documented as not read on restore — restore always builds a balanced grid; old profiles that carry the field still load.
Dependencies
- resvg 0.49 → 0.50 (tray icon renderer; also usvg 0.50, harfrust 0.15, read-fonts 0.46, skrifa 0.49)
- oo7 0.6 → 0.7.1, ashpd 0.13 → 0.14, zbus 5 → 6 (direct dependency); removed
fs2, and the older duplicate copies ofcbc,hkdf,pbkdf2andblock-paddingthat oo7 0.6 needed (cbcstays as a direct dependency) - Semver-compatible updates: rustls-webpki 0.103.16 → 0.103.17, vnc-rs 0.6.0 → 0.6.1, zstd 0.14.3 → 0.14.4 (zstd-safe 8.3.0, zstd-sys 2.1.3), cc 1.11.1 → 1.11.2, cfg-expr 0.20.10 → 0.20.11, mio 1.2.4 → 1.2.5, zbus and zbus_macros 6.2.1 → 6.3.0, zruntime 0.2.2 → 0.2.3. tokio was already at 1.54.1
cargo auditreports no vulnerabilities; the six "unmaintained" warnings areatomic-polyfill,pin-utils,unsafe-libyamland, through the tray library,zvariant,zvariant_deriveandzbus_names.cargo-sources.jsonregenerated for the Flatpak and Flathub manifests. GNOME runtime 51, FreeRDP 3.33.1, cJSON 1.7.19, OpenH264 2.7.0, the Snap oncore26and every pinned CLI download (TigerVNC 1.16.2) are current- Flatpak: fast_float 8.3.0 → 8.3.3 (VTE build dependency) and waypipe 0.11.2 → 0.11.3, with their
sha256 nix,libcandsocket2are declared once in[workspace.dependencies]- RUSTSEC-2023-0071 (
rsa) stays ignored: sspi 0.23.1, winscard 0.4.1 and picky 7.0.0-rc.29 still pin rsa 0.10.0-rc.18
Installation
Flatpak (Recommended)
flatpak install flathub io.github.totoshko88.RustConnSnap
sudo snap install rustconnDebian/Ubuntu (.deb from this release)
sudo dpkg -i rustconn_0.25.0_amd64.deb
sudo apt-get install -f # Install dependencies if neededFedora (.rpm from this release)
sudo dnf install rustconn-0.25.0-1.fc44.x86_64.rpmAppImage
chmod +x RustConn-0.25.0-x86_64.AppImage
./RustConn-0.25.0-x86_64.AppImagemacOS (Homebrew)
brew tap totoshko88/rustconn
brew install rustconn
open $(brew --prefix)/opt/rustconn/RustConn.appAll dependencies (GTK4, libadwaita, VTE, Adwaita icons) are installed automatically.
Requires macOS 13 (Ventura) or later.
OBS Repositories
Packages available at: https://build.opensuse.org/package/show/home:totoshko88:rustconn/rustconn
# Debian 13 (Trixie)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/ /' \
| sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/Release.key \
| gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn
# Ubuntu 24.04 LTS (Noble)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/ /' \
| sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/Release.key \
| gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn
# Ubuntu 26.04 LTS (Resolute)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/ /' \
| sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/Release.key \
| gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn
# Fedora 44
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_44/home:totoshko88:rustconn.repo
sudo dnf install rustconn
# Fedora 43
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_43/home:totoshko88:rustconn.repo
sudo dnf install rustconn
# openSUSE Tumbleweed
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Tumbleweed/ rustconn
sudo zypper ref && sudo zypper in rustconn
# openSUSE Leap 16.0
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Leap_16.0/ rustconn
sudo zypper ref && sudo zypper in rustconnArch Linux (AUR)
yay -S rustconnFreeBSD (Ports)
pkg install rustconnFull installation guide: https://github.com/totoshko88/RustConn/blob/main/docs/INSTALL.md
Verifying your download
Every binary on this release (deb, rpm, AppImage, Flatpak) is covered two ways.
Plain checksums — download SHA256SUMS alongside the asset, then:
sha256sum -c SHA256SUMSSigned build provenance (SLSA, via Sigstore) — proves the file was built by this
workflow from this commit:
gh attestation verify RustConn-0.25.0-x86_64.AppImage --repo totoshko88/RustConn(The snap is signed by the Snap Store; the macOS build is delivered via the Homebrew tap.)