Repository navigation
v0.23.6
What's Changed
Added
- OSC 52: a remote yank can reach the local clipboard (opt-in) — VTE parses
OSC 52 ; c ; <base64>and then drops it: through 0.84 itsXTERM_SET_XSELECTIONhandler is a no-op, so a yank in a remote Neovim — or in tmux withset-clipboard external— put the text nowhere. GNOME Terminal and xfce4-terminal inherit the same hole, so this was a missing capability rather than a RustConn bug, and RustConn needs its own because VTE has no API to switch the handler on. A newterminal::osc52::Osc52Filtersits on the session output path (TerminalNotebook::deliver_output_to), lifts the offers out of the PTY stream beforeTerminal::feedsees them, and writes them through the samedisplay().clipboard().set_text()call copy-on-select uses. It is a byte filter rather than a parser for its own sake: every other byte is passed through in order —OSC 0titles,OSC 133shell-integration marks, plainESCsequences — and a string the stream ends inside is handed back byfinish()instead of being kept, because an unterminated OSC left in the stream would make VTE swallow the rest of the session as body. A sequence can straddle PTY reads (8 KiBREAD_CHUNK), so the filter keeps state between chunks; one test feeds the same offer at every possible split point and one byte at a time and requires identical output. All three terminators (ESC \,BEL, C1ST) and both introducers (7-bit and C1) are recognised. Security: the switch is Settings → Terminal → "Remote clipboard (OSC 52)" and defaults to off, since a host that can write the clipboard can aim a pastejacking payload at the next terminal the user pastes into. Reads are never served in any configuration — anOSC 52 ; c ; ?query is dropped unanswered, so the local clipboard cannot be exfiltrated this way — only thec(CLIPBOARD) selection is honoured, withp(primary) ands(select) passed through untouched. A payload is capped at 1 MiB, is base64-decoded into aZeroizingbuffer so the plaintext is wiped on drop, must decode to valid UTF-8 to reach the clipboard, and the decoded text is never logged. The output filter runs before session-transcript observers too, so an enabled offer is lifted out of the saved log as well as the display; with the setting off the sequence reaches both untouched. Remote tmux needsset-clipboard external(andallow-passthrough on) to forward the sequence; a DCS-wrapped passthrough is not unwrapped yet. (PR #372, thanks @shafiev) - Save a terminal session's output to a text file — a new Save Output… entry in a terminal tab's right-click menu writes the session's full scrollback to a plain-text file through VTE's
write_contents_sync(requested in #371). A file chooser opens with a name derived from the session; the whole buffer is saved (its length is bounded by the Scrollback lines setting). The item is offered only for VTE terminal tabs — SSH, local shell, Telnet, Serial — gated on the session having a terminal widget, so embedded RDP/VNC/Web tabs and the Welcome tab, which have no text buffer, do not show it. In a split tab the focused pane is saved — the window wires a focused-session resolver into the notebook (keyed by the tab owner, mirroring the existing split-pane-box provider) so the save targets the pane the user clicked, not always the first one. A save failure is reported in a modal error dialog and a success in a toast, per the project's error-feedback rule; a cancelled chooser is silent.session_output_filenamesanitises the default name (every non-alphanumeric character becomes_, with aterminal-outputfallback) and is unit-tested. (#371)
Fixed
- RDP Performance Mode now reaches the external FreeRDP client — the per-connection Performance Mode (Quality/Balanced/Speed) was applied by the embedded IronRDP client and written into exported
.rdpfiles, but the external FreeRDP launch path dropped it entirely: a Speed profile reachedxfreerdpwith wallpaper, themes and full-window drag all on, visually identical to Quality (reported on #370). The user's choice was stored but never consumed on that path.FreeRdpConfignow carriesperformance_mode, threaded from the persisted model through both external launch sites (the direct External client and the embedded→external fallback), andbuild_freerdp_argsemits the matching experience flags —+window-drag +menu-animsfor Quality, nothing for Balanced (FreeRDP's own default),-wallpaper -themesfor Speed. The mapping mirrors the embedded client'sbuild_performance_flagsand the.rdpexporter'swrite_performance_settingsso the three paths cannot drift, pinned by a newfreerdp_experience_args_match_modetest. The remote server still has the final say (a group policy such as Enforce Removal of Remote Desktop Wallpaper overrides the client request). The editor's Performance Mode row subtitle now reads "…for image rendering and visual effects" to match the widened reach. (#370) - KeePass "Search from vault root" no longer crashes on a vault with non-ASCII entry names — the from-root matcher tested whether a listing line ended with
/<candidate>by byte-slicing the line atline.len() - candidate.len() - 1. On a database holding non-ASCII paths — a Cyrillic recycle-bin group (Смітник/…), a database titledПаролі— that index can fall inside a multi-byte UTF-8 character, so the slice panicked and took the whole root search (and the connect) down with it. The same byte-boundary class of bug as the hex-colour crash in #343. The tail test now usesends_withon the whole string with no byte indexing, so a credential kept outside the RustConn group is found whatever script the surrounding entries are named in. A regression test feeds the matcher a Cyrillic-laden listing. (#353) - The misleading "Bitwarden: CLI command path stored" log line no longer reads like a vault lookup — a KeePass user who turned on debug logging to diagnose a credential miss saw this line and reasonably concluded RustConn was querying Bitwarden for their secret (reported while investigating #353). It is nothing of the sort: it is the Settings page's backend-detection caching the resolved
bwbinary name, and with KeePass selected no Bitwarden backend is ever part of credential resolution. The line now says so explicitly ("cached CLI binary path from backend detection (not a vault lookup)"). (#353) rustconn-cli secret setnow marks the connection vault-backed — storing a vault secret for a connection created byrustconn-cli addleft its password source at theNonedefault, so a connect never consulted the vault and the password just stored was never used.secret setnow promotes aNonesource toVault(an explicit Prompt/Variable/Inherit/Script is left as the user's choice), so the add → set flow produces a connection that actually resolves its credential. (#353)
Changed
rustconn-cli secret getmirrors the GUI resolver's from-root search — with "Search from vault root" enabled,secret get --backend keepassnow applies the same whole-database fallback (keyed by the connection's scoped key, host and name) the connect path uses, instead of only the scopedRustConn/…lookup. The CLI can now diagnose exactly what a connect would find. (#353)- Added diagnostics for the KeePass "Search from vault root" path — when a scoped KeePass lookup misses, RustConn now logs the
kdbx_root_searchflag value and the preferred backend right before the from-root search gate, andcollect_secret_settingslogs the read-only / root-search toggle values it collected on save. This turns a "root search never ran" report into a one-line diagnosis of whether the flag reached the connect, while the underlying toggle-persistence issue is tracked. (#353)
Documentation
- API docs no longer point at code that is gone, and a gate keeps it that way — nothing ran
cargo doc, so rustdoc's own lints never fired and 106 warnings had piled up acrossrustconn-core,rustconn,rustconn-cliandrustconn-dock-sys; 67 of them were links to items that had been renamed, moved or removed. Where the prose had drifted with them it now matches the code: the KeePassXC helpers insecret/status.rsdocumented aSecretError::Backendvariant that does not exist (they returnSecretError::KeePassXC), andCairoBackedBuffer::copy_rectclaimed to mirror aVncPixelBufferthat is no longer in the tree. Doc examples in the GUI binary usedrustconn::paths, which a binary crate does not have, and now usecrate::. A new[workspace.lints.rustdoc]table denies broken intra-doc links and allows public-to-private links, since these docs are read with private items.scripts/verify.sh(default mode) and the CI clippy job now runcargo doc --no-deps --document-private-itemswithRUSTDOCFLAGS="-D warnings".
Dependencies
- Updated: dirs 6.0→7.0, tray-icon 0.25.1→0.26.1, muda 0.20.0→0.21.2.
dirs7.0's only breaking change ispreference_diron Windows (RoamingAppData instead of LocalAppData) — RustConn never callspreference_dirand does not target Windows, so the upgrade is a no-op here.tray-icon/mudaare macOS-only (behind thetray-macosfeature, not built by CI); the deprecatedTrayIconBuilder::with_icon_as_template(false)call was dropped in favour of the builder's non-template default (tray-icon 0.26 renamed it to thewith_icon_templatedopt-in), andmuda0.21's removedTextStyle/libxdoAPIs are not used here. All in-range cargo dependencies were already at their latest compatible versions (cargo updatechanged nothing);cargo deny check advisoriesis clean.
Installation
Flatpak (Recommended)
flatpak install flathub io.github.totoshko88.RustConnSnap
sudo snap install rustconnDebian/Ubuntu (.deb from this release)
sudo dpkg -i rustconn_0.23.6_amd64.deb
sudo apt-get install -f # Install dependencies if neededFedora (.rpm from this release)
sudo dnf install rustconn-0.23.6-1.fc44.x86_64.rpmAppImage
chmod +x RustConn-0.23.6-x86_64.AppImage
./RustConn-0.23.6-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.23.6-x86_64.AppImage --repo totoshko88/RustConn(The snap is signed by the Snap Store; the macOS build is delivered via the Homebrew tap.)