Skip to content

v0.21.5

Latest

Choose a tag to compare

@github-actions github-actions released this 03 Sep 20:16
· 5 commits to main since this release

What's Changed

Two features and an audit that turned into the larger half of the release.

The features: terminal colours can now follow the desktop's light/dark preference,
and a monitoring mode that fires on an actual shell event — the command finished,
with its exit code — rather than on a timing heuristic over raw output.

The audit began as a question about raising the GTK, libadwaita and VTE baselines
for 0.22.0 and produced an uncomfortable answer: the version features this project
already had were reaching almost nobody. The Flatpak passed one of them, the OBS
Debian rules computed three and then discarded two through a make quirk, the RPM
spec chose from a hand-written distro table that had gone stale, the release RPM and
the Homebrew formula passed none or one, and the three gtk-4-* features had zero
consumers the day they landed. Every channel now asks pkg-config what it can
actually back. Nothing here raises a baseline; it makes the existing tiers work,
which is what the 0.22.0 question was really waiting on.

Added

  • A monitoring mode that fires when the remote shell reports a command finished — Preferences ▸ Monitoring ▸ Default Mode and the connection editor's Activity Monitor section gain Command finished, alongside Off, Activity and Silence, and the per-tab Monitor menu cycles into it. The three existing modes are timing heuristics over raw output: "Activity" means bytes arrived after a quiet period, which cannot tell a finished build from a progress bar. This one is an actual event — VTE's vte.shell.postexec termprop, which the remote shell sets through OSC 133 and which carries the command's exit code, so the notification distinguishes "Command finished" from "Command failed with status 1". It is delivered through the same three channels the other modes use, including the toast landing on the window a detached session actually lives in (issue #236). Two conditions, both stated in the mode row's subtitle and the debug log: shell integration has to be sourced on the remote host, and the build needs VTE 0.78 (the new vte-0-78 feature — debian.rules now detects the version with pkg-config, the way it already did for libadwaita). Consecutive commands each notify rather than being collapsed, which is deliberate: several commands finishing while you are on another tab is the case the mode exists for.

  • Tabs keep a persistent mark after a notification — every monitoring notification now also sets AdwTabPage:needs-attention, so libadwaita draws a line under the tab, highlights the tab-bar edge when the tab is scrolled out of view, and puts a dot on the Tab Overview thumbnail and the tab-switcher button. This also repairs a latent gap in the existing Activity and Silence modes: their only tab-level signal was indicator-icon, a single slot that five different meanings write to — split-pane colour, protocol colour, offline, pinned, and the notification itself — with a priority guard between only two of them, so a notification's icon could be overwritten by apply_protocol_color moments later and the user would never learn anything had happened. needs-attention is a separate property nothing else touches. It is cleared when the tab is selected, since libadwaita does not clear it and looking at the tab is the acknowledgement.

  • Terminal colours can follow the desktop's light/dark appearance — a new Follow System entry at the top of Preferences ▸ Terminal ▸ Theme. Until now the "System" colour scheme reached only the GTK chrome: apply_color_scheme() handed the choice to AdwStyleManager, but VTE's palette was looked up by name with a hardcoded dark_theme() fallback, and nothing connected the two. A light desktop therefore produced light window decoration around a dark terminal, with no setting that could pair them — the app never once asked libadwaita what it had resolved to, so the information was not available to the terminal at all. TerminalTheme::resolve(name, system_dark) in rustconn-core now resolves the new sentinel against that resolved state, which the GUI reads through app::system_is_dark() (AdwStyleManager::is_dark(), and so the settings portal on Wayland and in Flatpak). A theme picked by name is unaffected and stays put whatever the desktop does.

  • Terminals repaint when the desktop switches light/dark mid-session — with Follow System selected the resolved palette changes while settings.toml does not, so no existing path repainted: switching the desktop to dark left every open terminal light until it was reconnected. A notify::dark handler on the process-wide AdwStyleManager now drives TerminalNotebook::reapply_colors() across every live terminal, layering per-connection colour overrides back on for the same reason reapply_theme_overrides() already does after a settings save (issue #99). It touches colours only, so unlike apply_settings() it cannot undo a per-session Backspace/Delete choice and needs no reapply_erase_modes() chaser (issue #271). Both the notebook and the app state are held weakly, mirroring the neighbouring gtk-fontconfig-timestamp handler: the signal lives on a manager that outlives every window, so a strong reference would leak the window and its sessions.

Fixed

  • Every tray menu item that opens a session did nothing — Local Shell, Quick Connect and all of Recent Connections — the item highlighted on click and then nothing happened, on KDE's StatusNotifier and on the macOS tray alike, since both feed the same dispatch in setup_tray_handling. Show/Hide, About and Quit worked throughout, which is what made the shape of this hard to see: they take different routes — the first calls present()/set_visible() directly, the other two activate an action on the application, where names are unprefixed by definition. The three broken items went through WidgetExt::activate_action, which resolves a name through the widget action muxer by splitting it on the first . to pick a group. They passed "local-shell", "quick-connect" and "connect" with no prefix, so there was no group to find, the call returned FALSE, and let _ = discarded it. Recent Connections was broken twice over: even with the prefix corrected it named connect, which is declared with no parameter and acts on the sidebar selection, so the connection the user picked in the tray had nowhere to arrive and GTK would have rejected the activation for supplying a parameter at all. All three now activate on the window's own GActionGroup with verbatim names, matching what window/mod.rs already did for connect-to and the command palette, and the connect path uses the parameterised connect-to that takes a connection id. The names are constants with a test pinning both decisions, because the two activation functions cannot share one spelling and the difference is invisible at the call site. A tracing::debug! now records each tray message on arrival: this path had no logging whatsoever, so an item that silently failed was indistinguishable from a click that never reached the app, and the absence of log output proved neither.

  • Local shell tabs never took part in activity monitoring, in any moderesolve_activity_config looked the session's connection up with get_connection(id)? and gave up when there was none, which is every local shell and anything else opened without a connection record. The caller reads that as "do not monitor this session", so it returned before wiring connect_command_finished: the new Command mode could not fire on a local shell whatever the shell emitted, Activity and Silence were equally absent, and because the whole setup aborted there was no Activity monitoring started line either — the one signal that would have shown any of it. The global defaults exist precisely for a session with no per-connection override, so a connection-less session now takes them, and notifications use the tab's own name when there is no connection to name. The resolution moved into a free effective_activity_config so all three branches are covered by tests that need no display. Found while trying to exercise Command mode from a Local Shell tab, which is also why the per-tab Monitor menu's comment is corrected here: it still described the pre-Command cycle Off → Activity → Silence → Off, and since the menu advances one mode per activation, reaching Command from Off actually takes three — a stale list makes that look like a menu that does nothing.

  • Five icon names had been dropped by adwaita-icon-theme 50, and one of them was the new Command mode's success mark — the tab indicator for a command that finished cleanly asked for emblem-ok-symbolic, which no longer exists in the theme, so it drew as a missing-image placeholder on the very notification the mode exists to deliver. There is no fallback behind it: the app forces the Adwaita theme at startup for consistent availability, so a name Adwaita has dropped resolves nowhere, and GTK reports nothing — the failure surfaces only as a broken glyph at draw time. Auditing every *-symbolic literal in both crates against the installed theme found four more in the same position: emblem-synchronizing-symbolic on all four sync indicators (Cloud Sync preferences, the sidebar, the welcome panel and the group editor), chart-line-symbolic on the Statistics empty state, and utilities-system-monitor-symbolic / preferences-desktop-peripherals-symbolic on the Task Manager and Device Manager RDP quick actions. All nine call sites now use names verified present in the theme — object-select-symbolic for the success mark, view-refresh-symbolic for sync, view-list-ordered-symbolic for statistics, view-list-symbolic and input-mouse-symbolic for the two quick actions. Theme 50 ships no chart or graph glyph at all, which is why the statistics page settles for an ordered list.

  • Closing a tab logged a warning about a teardown the app had just performed itself — the child-exited handler asks the session manager to terminate the session whose exit it is reacting to, but on tab close the widget side has already killed the process group, so the manager answers "Session not found". That outcome was recognised as benign only when the app was shutting down, so an ordinary tab close produced WARN Failed to terminate session two milliseconds after the Killed VTE child process group on tab close line that caused it. Both routes are now recognised by the session already being absent, rather than by matching the error text — it crosses that boundary as a formatted String, and classifying an error by its prose is the bug fixed in the KeePassXC handling below. Any other failure still warns.

  • KeePassXC reported "Could not read the password" for a database that was open and healthy, in every non-English interface languagekeepassxc-cli exits 1 for "entry not found", "wrong database key" and "database unreadable" alike, so classify_show_failure in rustconn-core/src/secret/status.rs tells them apart by matching the CLI's English prose. But it is a Qt program and translates that prose, and RustConn itself exports LANGUAGE at startup to honour its own language setting — so with the interface in Ukrainian the CLI answered Неможливо знайти запис із шляхом …, no needle matched, and a merely missing entry was classified as an unreadable database. Two consequences, and the misleading wording was the smaller one: the connection got the modal "it may be locked, not logged in, or not set up on this computer" while Preferences ▸ Secrets correctly showed the backend Ready, and because that path returns Err instead of Ok(None) it also skipped Also read from the encrypted file, so a password sitting in credentials.enc became unreachable. The child now gets LC_MESSAGES=C with LANGUAGE cleared, set in keepassxc_command — the one place all three readers, the save path, the group-create path and the rename path build their command, so the four other stderr matchers in that file which had the same latent bug are fixed by the same two lines. The character encoding is deliberately left as the user had it: entry paths and the database path travel as argv and a Qt 5 build takes its codec from the locale charset, so pinning LC_ALL=C would have traded this bug for a worse one, mangling a non-ASCII group name or a database named Паролі.kdbx. Where LC_ALL is set its value is copied to LC_CTYPE before it is dropped, since it would otherwise outrank LC_MESSAGES.

  • The .deb and .rpm attached to a GitHub release named three fewer libraries than the binary loads, so the .deb died in the dynamic linker before reaching main() (issue #313, reported by @philclifford)rustconn: error while loading shared libraries: libwebkitgtk-6.0.so.4, on a package that installed without complaint. Both artifacts are assembled by hand in the release workflow — the .deb with a control file written inline and packed by dpkg-deb --build, the .rpm by fpm with an explicit --depends list — so neither ran the dependency machinery a normal build provides, and both lists fell behind the binary when web-embedded entered the crate's default features. Measured against the recursive closure of the old Depends (266 packages), three were unreachable: libwebkitgtk-6.0-4, libjavascriptcoregtk-6.0-1 and libasound2t64 — the last from the RDP audio feature, which had simply not bitten anyone because ALSA is usually already installed. The lists are now derived rather than remembered: the .deb runs dpkg-shlibdeps over the staged binaries, which maps each soname to its package and takes a minimum version from the symbols actually referenced, and the .rpm passes --rpm-autoreqprov, since fpm writes AutoReqProv: no unless told otherwise — the published 0.21.4 RPM carried zero soname requires. Both steps then fail the build if WebKitGTK is absent from what they derived, so this cannot regress quietly. Two things stay declared by hand because neither tool can know them: openssh-client is a program rather than a library, and gtk4 >= 4.14 is the floor the v4_14 bindings assert while no referenced symbol proves it. dpkg-shlibdeps reads debian/control — which is what makes that file matter again: a version in its Build-Depends raises the derived floor, and libgtk-4-dev (>= 4.14) there is why the package asks for libgtk-4-1 (>= 4.14) rather than the 4.12 the symbols alone would justify. The other channels were never affected and for a reason worth recording: OBS builds its Debian package through dh, so dh_shlibdeps derives the list, its RPM gets rpmbuild's generator, and the AppImage bundles what linuxdeploy finds through ldd. Every channel that hand-maintained a list had this bug; no channel that derived one did. The released .deb also gains the two Recommends its inline list had dropped, picocom among them — the helper serial connections need.

  • Five of this release's own fixes were missing from every distro changelog, and every release gate was green while they were — the tray dispatch, the local-shell monitoring, the dropped icon names, the KeePassXC locale misread and the 0.21.4 untranslated strings all reached CHANGELOG.md after the release-prep commit had already derived the five other formats from it. release.sh checks that debian/changelog, both OBS changelogs, the spec's %changelog and the metainfo <release> lead with the release version, which they did — the header is identical whether the body has thirteen entries or eighteen. So the notes shown by apt changelog, by dnf, and as the AppStream description in GNOME Software would have omitted five user-facing fixes, including the one where a stored password became unreachable. All five are now propagated. A new gate compares commits rather than prose: if the last commit touching a derived changelog is an ancestor of the last commit touching CHANGELOG.md, that file was written from an older CHANGELOG and the release stops. Matching wording across five formats would have meant a fuzzy comparison that can be argued with, and a gate nobody trusts is the one that gets skipped; a derived file touched later is deliberately not flagged, since fixing a typo in one of them alone is legitimate.

  • The RPM on every GitHub release, and every Homebrew install on macOS, shipped the libadwaita 1.5 baseline — the last two channels that chose features by hand. The build-rpm job runs in a fedora:44 container, which carries GTK 4.20+ and libadwaita 1.9, and passed no version feature at all; the Homebrew formula wrote out adw-1-8 and selected no GTK or VTE feature, so the Command monitoring mode could not appear on macOS whatever VTE Homebrew had installed. Both now ask pkg-config --atleast-version, the same comparator and the same newest-first ladders as the OBS spec, with package-qualified feature names because both invocations select two packages. Both fail safe: a missing .pc file yields nothing and the build is what it was. The formula asks pkg-config rather than Homebrew's formula metadata so the answer comes from the files the compiler will read — verified as syntactically valid Ruby, which is worth doing by hand because the release workflow copies this file into the tap without parsing it.

  • Every OBS Debian and Ubuntu package was built without any libadwaita feature and without the in-tab browser, and the build log said so all alongdebian.rules detected libadwaita and WebKitGTK correctly and then threw the answers away. In a make recipe a comment line without a trailing backslash ends the continuation chain, and each chain gets its own shell, so ADW_FEATURES and WEB_FEATURES — assigned above the comment that introduced the VTE block — were empty by the time the cargo line ran. Running the recipe as committed on a host with libadwaita 1.9.1 and WebKitGTK 6.0 installed printed === libadwaita => features: | web: | vte 0.84 =>,vte-0-78 ===: three empty fields and one populated one, VTE having survived only because it was detected after the last comment and so shared a shell with the build. Debian 13 and Ubuntu 26.04 therefore shipped the libadwaita 1.5 baseline — GtkSpinner instead of AdwSpinner, linked buttons instead of AdwToggleGroup, the legacy shortcuts dialog — and Web connections had no embedded browser on any of them. All four detections now reach cargo, verified by running the recipe with cargo swapped for echo. The comment block is now anchored at the top of the recipe with a note saying why nothing may follow it, since the failure is invisible: the build succeeds, and only that one log line ever said anything was wrong.

  • The RPM spec chose features from a hand-written distro table that had gone stale, and never enabled VTE termprops at allrustconn.spec mapped %fedora and %suse_version to a libadwaita version by hand, so it needed an edit for every new distro release, and it had no VTE branch whatsoever: the Command monitoring mode could not appear in any RPM regardless of the VTE installed. It now asks pkg-config the way debian.rules does, for libadwaita, GTK, VTE and WebKitGTK together. Both files use --atleast-version rather than a glob over --modversion, which closes a second trap in the same area: a case pattern of 1.8*|1.9* does not match libadwaita 1.10, so the first distro to ship 1.10 would have dropped to the 1.5 baseline for an unrelated reason. Checked on this host (GTK 4.22.4, libadwaita 1.9.1, VTE 0.84.0, WebKitGTK 6.0 present): both files select adw-1-8,gtk-4-22,vte-0-78,web-embedded, and rpmspec --parse still parses the spec.

  • The Flatpak and Flathub builds could not reach the Command monitoring mode, or anything else gated behind a version feature — the manifests passed --features adw-1-8 and nothing more, so vte-0-78 was never enabled and the mode was hidden from the picker and inert, in the one channel most users install from, from the moment it was added. The gtk-4-18 / gtk-4-20 / gtk-4-22 features were in the same position but worse: no packaging file in the repository passed any of them, so all three had zero consumers the day they landed. Both manifests now build with adw-1-8,vte-0-78,gtk-4-22, which the runtime backs — measured with pkg-config inside org.gnome.Sdk//50 rather than taken from documentation: GTK 4.22.4, libadwaita 1.9.3, GLib 2.88.3, WebKitGTK 6.0 2.52.5, with VTE coming from the manifest's own 0.80.5 module because the runtime ships none. vte-0-80 is deliberately left out: by the feature ladder it implies vte-0-78 and adds only the image termprops, which vte4 0.10 does not bind and VTE never populates, so naming it would claim a capability nothing reads. The VTE ceiling below 0.81 is unchanged.

  • A KDE and XFCE workaround disappeared depending on which GTK the build targeted — the one-shot clear of gtk-application-prefer-dark-theme before adw::init() was compiled out on any build with gtk-4-20 or newer, on the reasoning that such a build links libadwaita 1.8+, which no longer warns about the legacy property. That reasoning holds for the warning and not for the behaviour: what the clear actually buys is that libadwaita starts from a property it did not set, which is true of every libadwaita. Tying it to a GTK feature meant enabling gtk-4-22 for the Flatpak would have silently dropped the workaround on the desktops it exists for, and this project tests neither. The guard is now the condition the workaround was written for — the property being true this early, which only a desktop that set it through xsettings or gtk-4.0/settings.ini does, and never GNOME, which expresses the preference through org.gnome.desktop.interface color-scheme. The deprecation is suppressed instead, narrowly, on the builds that raise it.

  • Four declarations in the application stylesheet had never applied, and the app was hiding the reason.monitoring-bar and its compact variant set margin-start / margin-end, which GTK's CSS does not have; it uses the physical margin-left / margin-right, and the rule ten lines further down in the same file used those correctly. GTK discarded all four as unknown properties, so the monitoring bar's horizontal margins were absent in both layouts. What kept this invisible is install_glib_css_warning_filter in main.rs: it drops every GLib message containing "Theme parser" or "gtk.css", which was added for a real flood from a libadwaita stylesheet newer than the GTK parser reading it — but the predicate matches on wording, not on origin, so it silenced complaints about our own file too. Fixing the spelling makes the margins appear, which is a small visible change and the one originally intended. Two things now stop it recurring: RUSTCONN_CSS_WARNINGS=1 disables the filter for a live session, and scripts/check-css.sh loads the stylesheet through the installed GTK and fails on any parser complaint — no display needed, so it runs as a CI gate and in release.sh alongside the i18n checks. Measured on this stack, incidentally, the flood the filter exists for no longer occurs at all: GTK 4.22.4 with libadwaita 1.9.1 emits nothing, so the filter was suppressing only our own errors.

  • The window rendered light on a dark desktop whenever the theme was set to Systemgtk-application-prefer-dark-theme is how AdwStyleManager tells GTK it has resolved the colour scheme to dark. RustConn cleared that property from a notify::gtk-application-prefer-dark-theme handler installed at startup, and cleared it a second time in build_ui(), so every time libadwaita set it the app unset it again within milliseconds — on a dark desktop the window came out light and stayed light. Both clears were written for an "xsettings race" on KDE/XFCE, where older libadwaita warned when it found the legacy property already true; the flaw is that a notify handler cannot tell that daemon apart from libadwaita, and libadwaita is what sets the property on every dark desktop. Reproduced on GNOME 50 with the desktop set to dark: the debug log showed Re-cleared deprecated gtk-application-prefer-dark-theme (xsettings race) twice during startup. Only the one-shot clear before adw::init() is kept, which is the case the workaround was genuinely for — libadwaita has no opinion at that point and sets the property itself immediately afterwards. On KDE this trades a possible libadwaita log warning for a window that matches the desktop. The startup log now carries a dark= field with what libadwaita actually resolved, since the stored preference never said what came out of it — which is a large part of why this went unnoticed.

  • The monitoring mode picker no longer needs editing when a mode is added — seven hand-written index maps across four files translated between MonitorMode and a combo-row position, in the shape match combo.selected() { 1 => Activity, 2 => Silence, _ => Off }. A copy that was missed silently mapped the new mode onto Off, and nothing failed until a user noticed their setting would not stick — which is exactly what happened while adding Command mode. The list now comes from MonitorMode::all() and the mapping from one helper (crate::monitor_mode), and the visibility rules for the quiet-period and silence-timeout rows are keyed on the mode rather than on a bare index, so a future variant cannot land in a _ arm. Two property tests were rewritten for the same reason: mode_cycling_is_three_cycle hard-coded the number of variants, and the prop_oneof! strategy listed them by hand, so every property in that file would have gone on passing without ever seeing the new mode.

  • Two strings added in 0.21.4 shipped untranslated in all 17 languages — the Login Timeout (seconds) row and its subtitle reached the UI without po/rustconn.pot being regenerated, so the catalogues never learned about them and scripts/check-po-complete.sh passed by comparing against a template that was missing the strings too. Both are now translated everywhere. Worth noting for next time: scripts/check-pot-current.sh exists and does catch exactly this, so the gap is that it did not run, not that it is absent.

Changed

  • Packagers can build against GTK 4.18, 4.20 and 4.22 — new gtk-4-18, gtk-4-20 and gtk-4-22 features, opt-in per channel like adw-1-8 and vte-0-78, with GNOME 50 as the target platform. Worth being precise about what they do: a newer GTK's runtime behaviour — portals for file dialogs by default in 4.18, the accessibility work on entries and file choosers in 4.20, GtkSvg in 4.22 — arrives with the linked library and needs no feature at all. What the feature adds is access to API introduced in that version and deprecation warnings for what it retired, and the second half is the immediate value: enabling gtk-4-22 surfaced exactly three deprecations, all now resolved. gdk::Texture::for_pixbuf became gdk::MemoryTexture::new, which takes the RGBA buffer the split-colour tab icons already build and drops the intermediate GdkPixbuf entirely — shorter than it was, and off the gdk-pixbuf image path GTK 4.20 moved away from. The other two were the remaining gtk-application-prefer-dark-theme accessors, where the deprecation is now suppressed on the builds that raise it rather than the code being compiled out: the clear is guarded at runtime by whether the desktop had already set the property, which only KDE and XFCE do, and that is true of every libadwaita regardless of which GTK the bindings target. No adw-1-9 feature was added — libadwaita 1.9's automatic gains already apply through the linked library, and AdwSidebar, the one widget that would justify the bindings, does not fit a sidebar built on TreeListModel with drag-and-drop and multi-selection.

  • New installations default to the Follow System terminal themedefault_color_theme() returned "Dark". It is reached only when color_theme is absent from settings.toml, so this applies to a fresh install or a config written before the field existed; anyone who has ever saved Preferences has an explicit value stored and keeps it. An unrecognised theme name still falls back to Dark rather than starting to track the desktop, which is deliberate: a custom theme the user deleted is a different situation from one they asked to follow the system, and quietly conflating the two would repaint terminals nobody asked about.

Documentation

  • packaging/obs/README.md no longer keeps a table of other projects' version numbers — it listed a GTK4 and a libadwaita version for each of eight distros, needed an edit whenever any of them moved, and was wrong about half of them: it claimed GTK 4.18 for Fedora 43/44, Tumbleweed and Ubuntu 26.04, which carry 4.20 or 4.22. Both columns are gone. In their place the feature-flag table states the pkg-config condition that actually selects each flag, since that is now what the spec and the rules file do, and the two traps that had already fired in this area — the glob that misses libadwaita 1.10, and the comment that breaks a make continuation chain — are written down next to the flags rather than left to be rediscovered.

Dependencies

  • Updated: mio 1.2.2 → 1.2.3, open 5.4.2 → 5.4.3, toml 1.1.4 → 1.1.5. Patch
    releases behind existing requirements, taken with cargo update; 13 further
    dependencies are behind their latest but held by a semver requirement and were
    left alone. The GTK stack is already at the newest published bindings — gtk4
    0.11.4, libadwaita 0.9.2, vte4 0.10.0, webkit6 0.6.1 — and their version features
    are what this release finally routes to the channels that can use them.

Installation

Flatpak (Recommended)

flatpak install flathub io.github.totoshko88.RustConn

Snap

sudo snap install rustconn

Debian/Ubuntu (.deb from this release)

sudo dpkg -i rustconn_0.21.5_amd64.deb
sudo apt-get install -f  # Install dependencies if needed

Fedora (.rpm from this release)

sudo dnf install rustconn-0.21.5-1.fc44.x86_64.rpm

AppImage

chmod +x RustConn-0.21.5-x86_64.AppImage
./RustConn-0.21.5-x86_64.AppImage

macOS (Homebrew)

brew tap totoshko88/rustconn
brew install rustconn
open $(brew --prefix)/opt/rustconn/RustConn.app

All 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 rustconn

Arch Linux (AUR)

yay -S rustconn

FreeBSD (Ports)

pkg install rustconn

Full installation guide: https://github.com/totoshko88/RustConn/blob/main/docs/INSTALL.md