Changelog
All notable changes to this project are documented here.
The format follows Keep a Changelog, and this project adheres to Semantic Versioning.
Each major version line is a different implementation:
- 4.x — Pure Rust + Zed gpui (current,
main) - 3.x — Tauri 2 + Rust + Svelte 5 (
tauri-versionbranch) - 2.x — Wails 2 + Go + Svelte 5 (
wails-versionbranch) - 1.x — Original Python implementation (
python-legacybranch)
[4.1.3] - 2026-06-02
Section titled “[4.1.3] - 2026-06-02”- Settings popover bottom row cut off in shortest window state.
The title-bar settings popover renders as an overlay anchored
to the hamburger button, and gpui-component’s
snap_to_window_with_marginconstrains the overlay to the window’s content bounds. In the shortest window state (no privilege banner, no capture result, no update pill ≈ 381 px tall on Windows) the popover’s ~410 px Main view overflowed the window’s bottom — theSettings folder/Log folderrow got clipped. The popover’son_open_changecallback now flips asettings_popover_openflag,desired_height()reads that flag as another input, and the existing per-render resize loop grows the window toHEIGHT_SETTINGS_POPOVER_MIN(440 px) when the popover opens. The window shrinks back to its state-dependent height when the popover closes. The callback also resets the popover’s sub-page state toMainon close so the next open lands on the settings list instead of the About / Language sub-page the user happened to leave on last time.
[4.1.2] - 2026-05-19
Section titled “[4.1.2] - 2026-05-19”- Windows installs on machines without the Visual C++
Redistributable now work. v4.1.0, v4.1.1, and every prior
Rust+MSVC build of PortFinder shipped binaries that dynamically
linked against
VCRUNTIME140.dll, part of the Visual C++ 2015+ Redistributable. On a freshly-imaged Windows install — including winget’s automated validator sandbox — that DLL isn’t present, so the Windows loader bailed withSTATUS_DLL_NOT_FOUND(0xC0000135) before any PortFinder code could run, and the user got Windows’ “code execution cannot proceed because VCRUNTIME140.dll was not found” loader dialog with no recovery hint from us. v4.1.2 static-links the MSVC C runtime into both binaries (PortFinder.exeandportfinder-cli.exe) via+crt-staticin a new.cargo/config.toml, so the.msiis self-contained at the CRT layer. ~200 KB binary growth per executable, no other behaviour change. Also unblocks the v4.1.0 winget submission (microsoft/winget-pkgs#376193) which has been failing the validator’s launch test on this exact issue (a fresh submission against v4.1.2 will replace it).
[4.1.1] - 2026-05-19
Section titled “[4.1.1] - 2026-05-19”Changed
Section titled “Changed”- Windows MSI is now built by cargo-wix + system WiX 3.14
instead of cargo-packager’s bundled WiX 3.11. The bundled
version predated
candle.exe -arch arm64(added in WiX 3.14), so the arm64 fallback in 4.1.0 was NSIS-only — and the half-machine / half-user registry shape of that NSIS install is what tripped winget’sValidation-Executable-Erroron PR microsoft/winget-pkgs#376193. The new setup produces a real.msion both x64 and arm64. The Windows release workflow picks upcargo-wixvia taiki-e/install-action and WiX 3.14 viachoco install wixtoolset --pre. - MSI now sets
ARPINSTALLLOCATIONexplicitly to[APPLICATIONFOLDER], written toHKLM\…\Uninstall\<ProductCode>\InstallLocation. winget’s executable-discovery step reads this value to findPortFinder.exepost-install — making it explicit avoids the validator’s heuristic fallback ever missing the binary. - Apps & Features icon for the MSI is now PortFinder’s
multi-resolution
icon.icoinstead of Windows Installer’s generic blue MSI glyph. Matches the icon onPortFinder.exein Explorer / taskbar / Alt-Tab.
[4.1.0] - 2026-05-18
Section titled “[4.1.0] - 2026-05-18”Consolidates the work shipped through 4.1.0-beta.1 and
4.1.0-beta.2. Highlights: capture-history popover with opt-in
disk persistence, three-stop log-level slider, Start/Stop
keyboard shortcut, Copy as JSON, About sub-page, seven shipped
UI locales, and a Linux .deb that finally passes lintian clean.
- Localised UI. Seven languages ship out of the box —
English, German, Spanish, French, Italian, Portuguese, and
Japanese — covering ~80 user-facing strings (status text,
result-row labels, settings popover, history popover,
privilege banner, menu items, relative-time labels). The
active locale follows the OS at startup (
sys-locale→ closest match against the shipped set, fallback English); a new Display language row at the top of the settings popover drills into a sub-page picker that switches immediately (no relaunch) and persists across runs. Translations are bundled into the binary byrust-i18n’si18n!()macro readinglocales/<code>.yml; missing keys in non-English locales fall through to the English source of truth automatically. - CLI logging flags.
portfinder-clinow accepts-v(debug level),-vv(trace),-q(warnings + errors only), and--log-file <PATH>(override the platform-default log path for this invocation). All four are global args, so they work alongside any subcommand. - Size-based log rotation. When the debug log is enabled
and the existing file is over 1 MiB, it’s renamed to
portfinder.log.1before the new session appends. Rotation happens at enable time (process start, UI toggle, CLI--log-file), not per-write. - Debug-level capture instrumentation.
capture::run,capture_blocking, andopen_capturenow log per-event diagnostics at debug + trace levels — useful for “I’m capturing but seeing no packets” bug reports. - Log-level slider in the settings popover. Three stops —
Normal (info), Verbose (debug), Trace — with hover-tooltip
descriptions for each level. Applies live via
log::set_max_leveland persists across restarts. CLI-v/-vv/-qstill override at runtime. - About section in the settings popover. Version, Repository (GitHub), License (GPL-3.0), and a platform- specific capture-privilege row (“BPF helper” on macOS, “Npcap” on Windows, “Capture access” on Linux).
- Start / Stop keyboard shortcut.
Cmd+Ron macOS,Ctrl+Ron Linux / Windows, scoped to the AppView so it doesn’t fire while a popover is open. PortFinder app menu gains a matching “Start/Stop Capture” entry; Start and Stop buttons show the bound keystroke in their hover tooltips. - Copy as JSON button on the result card. Right-aligned
below the seven value rows; serializes the result with the
same
serde_json::to_string_prettyshape the CLI’s--jsonflag produces. Flashes “Copied” for 1.2 s. - Capture history popover next to the Copy as JSON button. Last 10 successful captures with relative timestamps (“2m ago · LLDP on en0 · Gi1/0/24”) and the switch name + IP. Left-click restores an entry to the result card; right-click silently copies it as JSON.
- Opt-in disk persistence for history. New “Save capture
history” Switch at the top of the settings popover (default
off). When on, history is written to
history.jsonalongsidesettings.jsonand reloaded on startup. Flipping it off deletes the file; the in-memory deque stays for the rest of the session. - “Settings folder” button in the settings popover, next
to (renamed) “Log folder”. Reveals the config directory
where
settings.jsonandhistory.jsonlive.
Changed
Section titled “Changed”- Log levels audited.
render: resizeevents moved from info to debug (per-frame render-tick noise was the bulk of the log file). Settings-save failures and parser non-UTF-8-fallback warnings switched fromeprintln!tolog::warn!so they obey the in-app logger toggle instead of always hitting stderr. - Log startup banner now emits from
set_logging_enabledrather thaninit_logging, so the first line of every log file is the boot banner regardless of which enable path triggered it (persisted setting, CLI flag, UI toggle). - Main window is no longer resizable. AppView already
drives its own size via
window.resizewhenever the privilege banner or result card toggles state; a user- dragged corner used to snap back to the programmatic height on the next render, visible as a bounce. Disabling the resize handles outright (is_resizable: falseinWindowOptions) removes the snap-back path entirely. Window stays movable / minimisable / closeable as normal.
Removed
Section titled “Removed”- Stale
~/Desktop/portfinder-debug.logfrom alpha installs is auto-deleted on first launch of 4.1.0+ (capped at 10 MiB and gated to regular files only, so we don’t trash anything unrelated that happened to land at that path).
.deblintian cleanups for Ubuntu / Debian installers (gdebi’s “Lintian output” tab +lintian PortFinder_*.debnow report none of these):wrong-file-owner-uid-or-gidon every payload entry — cargo-packager’s tar preserved the GitHub runner’s uid/gid (1001/1001) so/usr/bin/PortFinderinstalled owned by whatever uid 1001 happened to be on the target. The .deb post-process step nowchown -R 0:0the unpacked tree before re-packing.malformed-contact Maintainer Will— Maintainer field was a bare name, nowWill Lehnertz <...>RFC822 form.missing-dependency-on-libc— addedlibc6to Depends.recommended-field Section— addedSection: net.no-changelog/no-copyright-file— package now ships/usr/share/doc/portfinder/copyright(DEP-5 machine- readable format) and/usr/share/doc/portfinder/ changelog.Debian.gz.
[4.0.1] - 2026-05-18
Section titled “[4.0.1] - 2026-05-18”- Opt-in debug logger with in-app toggle. New title-bar
hamburger menu opens a popover with a “Write debug log”
switch + an “Open log folder” button. Default is OFF — a
fresh install no longer drops
~/Desktop/portfinder-debug.logon launch (a leftover from alpha testing). When enabled, logs live at the platform-conventional location:~/Library/Logs/PortFinder/portfinder.logon macOS (Console.app indexes it),$XDG_STATE_HOME/portfinder/on Linux,%LOCALAPPDATA%\PortFinder\Logs\on Windows. Toggle is live — no restart needed.
Removed
Section titled “Removed”~/Desktop/portfinder-debug.logis no longer written. Existing files from alpha-era installs stay where they are (the new build just doesn’t touch them); delete manually if you don’t want them around.
[4.0.0] - 2026-05-17
Section titled “[4.0.0] - 2026-05-17”Graduates the gpui rewrite to stable. The major architectural
shift landed in 4.0.0-alpha.1 (Tauri + Svelte → pure Rust +
Zed gpui); this release captures the polish, cross-platform
fixes, and packaging work done across 16 alphas to make the
rewrite ship-ready. Per-alpha history is on the
Releases page.
- Dynamic window sizing. The gpui window auto-resizes to fit
the current state —
~310px tall in the idle state, growing for the privilege-warning banner, the result card, and the in-flight capture skeleton. Replaces the static420×560from alpha.1. - Live system theme follow. macOS / GNOME / KDE Light↔Dark
flips re-apply the brand palette without a relaunch via
observe_window_appearance. - “Update available” footer pill. Boot-time GitHub Releases
poll surfaces a one-line pill in the window footer when a
newer version is published. Click → opens the release page;
✕ → dismisses for the session. Respects channel policy
(alpha builds see newer alphas; stable sees stable). Legacy
calendar-style tags (
v2026.4.26from the pre-4.x era) are filtered out so they don’t perma-suggest as “newer”. - Native macOS auth prompt for the BPF helper install.
AuthorizationServices via
security-frameworkreplaces the 3.xosascript-shellout. Dialog shows “PortFinder wants to make changes” with the app icon instead of “osascript wants to make changes”. - Cmd+Q and red-traffic-light both quit on macOS. Explicit
QuitMode::LastWindowClosed+ a wired-up Application menu with a Quit action. gpui’s macOS default leaves the app running in the Dock after the last window closes; PortFinder is single-window so this matches user expectation. - Windows console-subsystem CLI sibling.
portfinder-cli.exeships alongsidePortFinder.exein the NSIS installer. PowerShell now waits forportfinder-cli capture …to exit and stdio routes correctly. PE subsystem byte is fixed at link time so a single binary can be GUI-friendly OR CLI- friendly but not both — two binaries is the only clean answer (wezterm + Zed land at the same shape). - AppStream metainfo on Linux. GNOME Software now shows “PortFinder / packetThrower / GPL-3.0-or-later” in the installed-apps view instead of falling back to filename parsing (“PortFinder-4 / Unknown author / unknown”).
- Lowercase
/usr/bin/portfindersymlink on Linux (.deb / .rpm / pacman) so the command matches the project name everyone types. The capitalisedPortFinderbinary is kept for the .desktop / dock label / process name. - CDP / LLDP / MNDP test-mode reproducibility. 20 capture- parser tests covering fixture frames for all three protocols.
Changed
Section titled “Changed”- Window decorations:
WindowDecorations::Clientrequested via xdg-decoration so KDE Plasma’s KWin doesn’t draw a server-side title bar on top of our in-window gpui-component TitleBar widget. GNOME (Mutter) was already CSD-only so the bug was invisible there. - macOS .dmg builds via cross-compile from a single Apple
Silicon CI runner. The retired
macos-15-intelrunner had a small / scarce pool and slower CPU — release wall-clock cut by ~20 minutes per tag. - Linux .rpm libpcap SONAME.
patchelf --replace-needed libpcap.so.0.8 libpcap.so.1rewrites the Ubuntu-build-time SONAME to what Fedora / RHEL / openSUSE / Arch actually ship. Without this the binary couldn’t load libpcap on Fedora — same bug existed in the 3.x .rpm but went unnoticed. - Linux launcher icon ships once (was duplicated as both
PortFinder.desktopandportfinder.desktopin the .deb). - CI matrix retired the
macos-15-intelrunner from both lint/test and build. Cross-compile onmacos-26is the Intel verification path now. - Release profile uses
lto = "thin"+codegen-units = 16on every target exceptaarch64-pc-windows-msvc(LTO disabled there — rustc thin-LTO crashes deterministically withSTATUS_ACCESS_VIOLATIONlinking the gpui dep graph on Windows ARM64).
- Local privilege escalation in the macOS BPF helper
installer. The pre-stable code wrote the bootstrap shell
script to a predictable
/tmp/portfinder-bpf-<pid>.shusingFile::create(noO_EXCL, follows symlinks) and then ran it as root via AuthorizationServices. A local unprivileged user able to predict the pid could pre-symlink the path and race the auth-dialog Allow click to land arbitrary script execution as root. Switched totempfile::NamedTempFile(mkstempunderneath:O_CREAT | O_EXCL, random suffix, owner-only mode). Reported internally during the 4.0.0 security pass. - Updater pill URL is allowlisted before being passed to
the OS URL handler. The GitHub Releases JSON’s
html_urlfield could in principle smuggle a non-https://github.com/ packetThrower/PortFinder/releases/URL through tocx.open_url; any release whosehtml_urldoesn’t match the prefix is now dropped. Defence in depth — HTTPS + rustls rules out network MITM, but this also covers a hypothetical supply-chain compromise of the JSON itself. - Help-text
Usage:line is consistent across platforms. Without an explicitbin_name, clap derived the program name fromargv[0], which on Windows becameportfinder-cli.exeeven when the user typedportfinderthrough a Scoop shim. Pinnedbin_name = "portfinder"so the displayed command name matches what the docs tell users to type. - Fedora
dnf install ./PortFinder-*.rpmactually runs the GUI now. Was failing withlibpcap.so.0.8: cannot open shared object fileregardless of whether libpcap was installed. - Ctrl+C from
portfinder captureexits. First press cancels gracefully, any subsequent press callsprocess::exit(130). Without the second-press escape hatch a wedged blocking pcap read made the process unkillable short of SIGKILL. - CSD content area on Wayland. Mutter reserves ~24 px for
shadow + resize handles that aren’t subtracted from
viewport_size()— addingHEIGHT_CSD_PADDINGkeeps the version footer from clipping on GNOME. - Win arm64 release builds no longer require a re-run. See “Release profile” above.
- macOS .dmg actually attaches to the GitHub Release.
Earlier alpha CI uploaded the
macos-packageartifact correctly but the release job’ssoftprops/action-gh-releasestep listed the old per-arch paths — silently dropped the macOS files. Hashes still showed up in SHA256SUMS because the SHA step globbed every artifact dir. Fixed in alpha.16’s pipeline.
Removed
Section titled “Removed”- The argv-dispatch CLI path through
PortFinder.exeon Windows is documented as ugly-but-still-works rather than the recommended CLI route. Useportfinder-cli.exeinstead. - The unsafe AttachConsole-without-stdio-reopen workaround is
no longer the primary CLI path on Windows. (Modern Rust
stdio doesn’t actually cache handles per
rust-lang/rust#40490
so the workaround was always less broken than folklore
claimed — the real issue was the async-shell-prompt UX
inherent to
windows_subsystem = "windows".)
[4.0.0-alpha.1] - 2026-05-16
Section titled “[4.0.0-alpha.1] - 2026-05-16”Major-version rewrite to pure Rust. Same product (still captures CDP / LLDP / MNDP, still shows you which switch port you’re on), new stack: Zed’s gpui replaces the Tauri 2 WebView + Svelte 5 frontend from the 3.x line. Single binary, no Node / pnpm / Vite in the build path, smaller install footprint.
- Pure-Rust GUI. gpui (GPU-accelerated UI framework from Zed) plus gpui-component for Button / Switch / Select / Theme. The window renders directly on Metal (macOS), DirectX 12 (Windows), and Vulkan + Wayland/X11 (Linux) — no embedded browser, no IPC bridge to JS, no separate frontend build.
PortFinder BPF Helperis the new macOS Background Items name. The 3.x helper installed itself asChmodBPFunder the legacycoop.otec.portfinder.ChmodBPFLaunchDaemon label, which showed up in System Settings → General → Login Items & Extensions as just “ChmodBPF”. 4.x installs the helper at/Library/Application Support/PortFinder/PortFinder BPF Helperunder the newio.github.packetThrower.PortFinder.BPFHelperlabel, so users see a recognisably-named entry instead of an opaque one. The installer (in-app button + standalone.pkg) unloads and removes the 3.x daemon on upgrade so there’s no overlap.
Changed
Section titled “Changed”- Reverse-DNS identifier scheme for the app bundle and helper
daemon.
com.packetthrower.portfinder(3.x bundle) →io.github.packetThrower.PortFinder, matching what Baudrun uses.coop.otec.portfinder.ChmodBPF(3.x daemon) →io.github.packetThrower.PortFinder.BPFHelper. Allcoop.otecreferences removed. - Build pipeline:
cargo build --releaseproduces the binary; cargo-packager wraps it into.dmg/.deb/.rpm/.AppImage/.pkg.tar.zst/ NSIS / WiX bundles. Replaces the Tauri CLI’stauri buildand the pnpm + Vite frontend build that fed it. - Linux post-install now sets
cap_net_raw,cap_net_admin=eipon the installed binary (3.x set onlycap_net_raw+ep). CAP_NET_ADMIN was needed for some interface-state queries thepcapcrate makes internally on newer libpcap versions. - Window size: 420×560 on every platform (was 400×460 / 500 in 3.x, with on-the-fly resize for the privilege banner). gpui’s cross-platform resize story doesn’t match Tauri’s, so the new build sizes for the banner up front — the trade-off is ~70 px of dead space below the result card when the banner isn’t there.
Removed
Section titled “Removed”- The 3.x
frontend/tree (Svelte 5 + TypeScript + Vite). - The 3.x
src-tauri/tree (Tauri 2 + tauri-specta bindings). package.json,pnpm-lock.yaml,node_modules/at the project root. The remainingdocs-next/Astro project keeps its own pnpm setup, but it’s no longer in the application build path.- The i18n surface (Spanish, French, German translations) — English- only at relaunch. Can return as Rust string tables if the contributor bandwidth’s there.
install-cli.sh/uninstall-cli.shat the project root. The in-app BPF helper install (and the standalone.pkg) already drop the/usr/local/bin/portfindersymlink; the standalone scripts were only useful for the BPF-less install path, which is now rarer than it was on 3.x.
Second alpha for the 3.3.0 cycle. Adds two field-tech UX moves to the
result card; design system context (PRODUCT.md, DESIGN.md,
DESIGN.json) lands in the repo for the first time.
- Click-to-copy on every captured value. Switch name, IP, port, VLAN, voice VLAN, MTU, and model each render as a chromeless inline button. Click once and the value is on your clipboard with a transient
✓checkmark for confirmation; nothing to highlight, nothing to right-click. Saves the cmd-c step when pasting switch IPs into tickets, Slack, or a notebook. Hover and focus-visible affordances tint subtly usingcolor-mix(CanvasText, …)so the styling reads correctly against any of the three per-OS card surfaces. - “Honest about absence” treatment. Result fields the parsers couldn’t find in the packet (voice VLAN on most non-Cisco gear, MTU on switches with LLDP-MED disabled, etc.) now render as italic-faded not advertised text instead of a bare em-dash. Translated in all four locales (en / es / fr / de).
PRODUCT.md+DESIGN.md+DESIGN.jsonat the repo root, capturing the strategic + visual design system. Future agents and contributors get a consistent baseline; the impeccable tooling reads them automatically.
Changed
Section titled “Changed”- The design system documents
Settings on Every Machineas the explicit visual North Star. Per-OS native chrome (macOS Tahoe / Windows Fluent / Linux Adwaita) is now a documented design choice, not an artifact.
Pre-release for cross-platform smoke testing of the i18n work and the batched backend / frontend infrastructure changes since 3.2.0. Not recommended for daily use — feedback welcome before the 3.3.0 GA.
- Localization scaffold — every user-facing string in the GUI now flows through
svelte-i18n. Bundles ship for English (authoritative), Spanish, French, and German; native-speaker review wanted before GA. Locale resolution: user override (footer picker, persisted inlocalStorage) → system locale viatauri-plugin-os→enfallback. Backend errors and CLI output stay English for now. frontend/src/bindings.tsis now auto-generated from the Rust IPC layer viatauri-specta. Every#[tauri::command]insrc-tauri/src/lib.rsand every#[derive(Type)]data struct flows through to a matching TypeScript declaration. Regenerated on everycargo test; a CI step fails if a contributor changed an IPC signature without committing the regenerated TS. Closes the class of bugs wherehasIp/switchIp/nativeVlancasing drifted between Rust and TypeScript (#16).
Changed
Section titled “Changed”- CDP / LLDP / MNDP TLV decoding now logs a one-line warning to stderr when a string TLV (system name, port description, board name, etc.) contains non-UTF-8 bytes that have to be substituted. The displayed result is unchanged — flaky-firmware diagnosis used to be silent (#24).
list_interfaces()(theget_interfacesTauri command andportfinder list) now caches results for 5 seconds. Tabs-away-and-back / fast double-clicks on the refresh button no longer re-scan via libpcap, which on slow hosts saves a few hundred milliseconds per call (#23).- Stop button now responds within ~60 ms instead of up to ~510 ms. The pcap blocking timeout dropped from 500 ms to 50 ms, so the capture loop checks the cancellation token an order of magnitude more often. Sniff-all mode also tears down the losing interface tasks 10× faster after a winner is found (#18).
3.2.0 - 2026-05-01
Section titled “3.2.0 - 2026-05-01”- MNDP (MikroTik Neighbor Discovery Protocol) as a third capture protocol alongside CDP and LLDP. RouterOS devices that ship with
discovery-protocol = mndpand never speak LLDP now show up with switch name, sender-side interface, board model, and IP populated. UDP/5678 broadcast; TLV parser handles Identity / Platform / Board / Interface / IPv4 / IPv6 (#26).
Changed
Section titled “Changed”- Resized the RJ-45 jack on the app icon to match the padding on Baudrun’s serial-port icon (610×392 box, ~207 px L/R padding instead of filling the canvas). Side-by-side the two apps now read as siblings on the dock / launcher / app grid.
3.1.4 - 2026-04-27
Section titled “3.1.4 - 2026-04-27”- Windows CLI printing two stray
System error 1376 has occurred. / The specified local group does not exist.blocks before the capture result. Thenet localgroup Npcapprobe used to detect non-admin Npcap installs now silences its stdout/stderr (and usesCREATE_NO_WINDOWso the GUI build doesn’t flash a console window).
3.1.3 - 2026-04-27
Section titled “3.1.3 - 2026-04-27”Changed
Section titled “Changed”- LLDP capture results now combine Port ID and Port Description when both are present (
"1/1/1 (Duty PC)"). Previously only the description was shown when both existed, which hid the actual port number.
- Windows ARM64 release build failing in CI:
pnpm/action-setup@v6writes broken.cmd.EXEsymlinks onwindows-11-armrunners. Pinned both workflows back topnpm/action-setup@v4until the upstream regression is resolved.
3.1.2 - 2026-04-27
Section titled “3.1.2 - 2026-04-27”- Windows binary refusing to launch when Npcap isn’t installed. The OS dialog
wpcap.dll was not foundappeared before the privilege-warning banner had a chance to render and direct users to the Npcap download.wpcap.dllis now marked as a delay-loaded import viabuild.rs, and pcap calls are gated onnpcap_installedso the app launches cleanly and shows the Download Npcap link instead.
- Linux ARM64 release build failing with
xdg-open binary not found—ubuntu-24.04-armrunners ship a more minimal package set thanubuntu-latestand don’t includexdg-utilsby default. Added it to the apt install step.
3.1.0 - 2026-04-26
Section titled “3.1.0 - 2026-04-26”- Linux ARM64 release artifacts:
_arm64.deb,_aarch64.AppImage,.aarch64.rpm. - Windows ARM64 release artifact:
_arm64-setup.exe. - macOS Liquid Glass effect:
NSVisualEffectViewvibrancy material applied to the window via thewindow-vibrancycrate. - Per-OS card layouts that adopt each platform’s surface conventions (macOS Tahoe, Windows 11 Fluent, GNOME Adwaita).
- iOS-style toggle switch for the “Only show interfaces with an IP” control.
- Refresh button next to the interface dropdown.
MTUfield in the captured-result display, parsed from LLDP’s IEEE 802.3 Maximum Frame Size TLV.Switch Modelpopulated for LLDP from the System Description TLV (CDP already had it via Platform).install-cli.shanduninstall-cli.shstandalone scripts at the repo root for users who want only theportfinderCLI symlink without the BPF helper.- BPF helper installer (and the in-app Install BPF Access button) now creates
/usr/local/bin/portfinderautomatically so the CLI is callable from any shell. - New app icon: navy gradient with a metallic RJ-45 jack (Baudrun-style aesthetic).
- MkDocs documentation site at https://packetthrower.github.io/PortFinder/, deployed automatically on push to main.
- Status / tech badges in the README (release, downloads, CI, docs, platforms, Tauri/Rust/Svelte).
- macOS screenshot embedded in the README.
- Branch protection on
mainwith a CI rollup status check that lets docs-only PRs through while gating code changes on the full build.
Changed
Section titled “Changed”- Native widget styling per platform — fonts, spacing, radii, button shapes track macOS / Windows / Linux native conventions.
- Window resized to 400×460 to fit the tightened layout.
- Card backgrounds inverted to gray-on-white in light mode (matching macOS Settings’ surface convention).
- Protocol selector is now a dropdown matching the interface dropdown style (was a segmented control).
- Wi-Fi capture on macOS:
BIOCPROMISC: Operation not supportednow triggers a fall-back to non-promiscuous mode instead of erroring out. - TypeScript field casing matched to Rust’s serde camelCase output (
hasIp,switchIp,nativeVlan,voiceVlan) — previously the IP filter checkbox silently failed and capture-result fields appeared empty.
3.0.0 - 2026-04-26
Section titled “3.0.0 - 2026-04-26”Changed
Section titled “Changed”- Complete rewrite from Wails 2 + Go to Tauri 2 + Rust. Frontend (Svelte 5 + TypeScript + Vite) is unchanged.
- Versioning switched from CalVer (
YYYY.M.D-PATCH) to SemVer. - Build system migrated from
Makefile+ NFPM + Wails CLI topackage.jsonscripts + Tauri’s bundler.
- Headless CLI mode — the same binary runs as a GUI when launched without args, or as a CLI with subcommands (
capture,list,privileges) when given any. Each supports--jsonfor scripting. - Hand-rolled CDP and LLDP parsers in Rust.
- Tokio-based capture cancellation with race-to-first across interfaces in sniff-all mode.
- macOS BPF helper installer rewritten in Rust (in-app Install BPF Access button, plus the standalone
PortFinder-BPF-*.pkg). - Per-platform privilege detection in Rust (
/proc/self/statuson Linux,/dev/bpf0+dseditgroupon macOS, Npcap registry + admin check on Windows). - macOS universal binary — the
.dmgruns on Apple Silicon and Intel from a single download.
2.x — Wails 2 + Go
Section titled “2.x — Wails 2 + Go”The 2.x line lived as 2026.4.x[-PATCH] CalVer tags. Highlights, in rough order:
- Migrated frontend from React to Svelte 5.
- Added IP-only interface filter.
- Added platform-specific window sizing.
- Added macOS BPF helper installer (Go).
- Added Linux
setcap CAP_NET_RAWpostinstall via NFPM. - Added Windows Npcap detection.
- Reformatted release artifacts to include the version in their filenames.
Detailed history and source on the wails-version branch and its tags.
1.x — Python
Section titled “1.x — Python”v0.2.0(2021-01-18) — Windows EXE and Linux binaryv0.1.0(2021-01-07) — Initial Python script
Source on the python-legacy branch.