Releases: msitarzewski/brew-browser
Release list
Brew Browser 0.7.2 / native 0.3.2
brew-browser 0.7.2 / Brew Browser native 0.3.2
A bug-fix patch. Signed + notarized; Tauri is the macOS 13+ / Linux build,
native is the macOS 26 SwiftUI build. Split-track versions track the same batch
(native 0.3.2 ≙ Tauri 0.7.2).
Fixes
Homebrew 6.0+ compatibility for vulnerability scanning
The headline fix. In Homebrew 6.0+, the vulns subcommand moved into core and
the standalone homebrew/brew-vulns tap/formula was deprecated and deleted. As
a result, on current Homebrew the vulnerability-scan feature was effectively
broken: detection failed and the "Install brew-vulns" button chased a
formula that no longer exists. Now:
- Detection falls back to
brew help vulns(the built-in subcommand) when the
legacy prefix check fails — both shells. - The install/remediation command is
brew update(which is how you get the
now-built-in subcommand) instead of installing a deleted formula. - Formula-name validation accepts 2-segment tap-qualified names (
user/name)
in addition touser/repo/name, while still rejecting shell metacharacters
and path traversal.
Thanks to @fallenmaverick (#152).
No more startup macOS Keychain prompts
The app read GitHub credential status eagerly on launch, which could trigger a
macOS Keychain access prompt for users who'd never signed in. Both shells now
gate that startup read behind a persisted "has signed in before" flag
(localStorage on Tauri via #152, UserDefaults on native via #155), so a user
who never touches GitHub sees no Keychain prompt on launch.
"59 minutes ago" scan time (WebKit)
Under WebKit, parsing the backend's nanosecond-precision ISO timestamps could
mis-parse the timezone and show a fresh scan as "59 minutes ago" / "1 hour ago".
Timestamps are now truncated to millisecond precision before parsing (#152).
Homebrew subprocess environment
- Native
VulnsServicesubprocesses now inherit the same Homebrew environment
($HOME, analytics-off flags) as the rest of the app, sobrewruns
correctly under the launchd GUI-app context (#152). - The Tauri backend prepends Homebrew bin paths to
PATHfor spawned commands,
now including Linuxbrew (/home/linuxbrew/.linuxbrew/{bin,sbin}) alongside
macOS/opt/homebrew+/usr/local(#152, #155).
Acknowledgments
- @fallenmaverick — the Homebrew 6.0+ vuln compatibility, startup Keychain
prompt, WebKit date-parsing, and Swift subprocess-env fixes (#152).
Issues & feedback
github.com/msitarzewski/brew-browser/issues.
Every error toast in the app has a "Report" button that pre-fills the issue with
your context.
Brew Browser 0.7.1 / native 0.3.1
brew-browser 0.7.1 / Brew Browser native 0.3.1
A small follow-up to 0.7.0 (Bundles). Signed + notarized; Tauri is the macOS
13+ / Linux build, native is the macOS 26 SwiftUI build. Split-track versions
track the same batch (native 0.3.1 ≙ Tauri 0.7.1).
What's new
Resizable Activity console
The bottom Activity console — the live brew output drawer — is now
resizable in both shells, so you can give a long install or upgrade as much
room as you want. Drag the divider to resize; the height persists across
launches (localStorage on Tauri, UserDefaults on native), clamped to a sensible
floor and 60% of the window. A community contribution by @cseelye (#136).
Fixes
- Linux CI produces artifacts again. The Linux bundle workflow was failing
at the updater-signing step (it tried to sign an updater artifact with a
private key CI doesn't hold), so no.deb/.rpm/.AppImagewere
published on tagged releases. The Linux auto-updater is unwired anyway, so the
build now skips that artifact and uploads the installers as intended (#149).
Note
The resizable Activity console was listed in the 0.7.0 notes but did not make
the 0.7.0 build — it landed just after. It ships here in 0.7.1.
Acknowledgments
Issues & feedback
github.com/msitarzewski/brew-browser/issues.
Every error toast in the app has a "Report" button that pre-fills the issue with
your context.
Brew Browser 0.7.0 / native 0.3.0 — Bundles
brew-browser 0.7.0 / Brew Browser native 0.3.0 — Bundles
Signed + notarized release. Tauri is the macOS 13+ / Linux build; native is the
macOS 26 SwiftUI build. The two version numbers track the same feature batch
(native 0.3.0 ≙ Tauri 0.7.0); they differ only because each shell versions by
its own release history.
Headline: Bundles
Install a whole working setup in one place, not one package at a time.
Bundles are curated one-click package stacks — a local-LLM rig, an image-gen
studio, a web-dev starter — each with the packages it needs and the post-install
steps to make them actually work. A new Bundles section lands in both shells.
- Nine recipes at launch, every token verified against
brew infoand
drawing only onhomebrew/coreandhomebrew/cask(zero third-party taps):
Local LLMs, Image Generation, Graphics & Design, Media Toolkit, Web Dev
Starter, Local Databases, Agentic Web Dev, LAMP Stack, and LEMP Stack. - Master list + Details pane. Bundles use the app's canonical master-list
and right-side Details pane, matching Library and Trending exactly — nothing
is auto-selected, the pane opens when you pick a bundle and closes when you
dismiss it or switch sections. - Readiness gating. A zero-install system profile (RAM, architecture, GPU,
disk) decides whether your Mac can actually run a stack, so an 8 GB machine
isn't told to install a local-LLM bundle it can't support. A single header
pill carries the verdict; a color-coded callout appears only when a bundle is
marginal or blocked. - Intent up front. Each bundle leads with a short description paragraph
explaining what the stack is for, rendered under the tagline. - Clickable inline package descriptions. Every package row is a disclosure
that lazily fetches its one-line summary (catalog first,brew info
fallback), cached, with multiple rows open at once. - Per-package Install. A "Not installed" package exposes an inline
Install action that installs just that package through the streamed
install path, keeps the Details pane open, and flips the row to Installed —
independent of the description toggle. - Setup guidance that knows what it can automate. brew-native install steps
run in-app and stream into the Activity drawer; external commands (model
pulls, service bootstrapping, and the like) are presented copy-only rather
than executed silently. - Contributor-friendly by design. Recipes are validated JSON files that
anyone can PR against a published contract, with CI enforcing the schema. The
long tail (Rails, Django, MEAN, and others) is open for community
contributions.
Also in this release
Pin / unpin packages
Hold a package back from "Update all." Pinning works in both shells for
formulae and casks, with a Pinned filter tab in the Library, a
cask-aware pinned count, and a bottom status bar that leads with the active
filter's count. Closes the long-standing pin/unpin requests (#141; closes #90,
#134).
Resizable Activity console
The Activity console is now resizable in both shells, so you can give live
brew output as much room as you want (#136).
In-app brew command options
A reactive recovery UI surfaces adopt / overwrite / force-remove choices when a
brew job needs them, with an Advanced disclosure for greedy upgrades and
autoremove (#109; addresses #98 reactive, #47, #13, #102, #100).
Brew Doctor + Cleanup on the Dashboard
The Storage card gains two actions, both streamed into the Activity drawer:
- Run brew doctor — runs
brew doctorand shows diagnostics live
(advisories are surfaced as info, not a failure). - Clean up cache… —
brew cleanup --prune=allto reclaim cached downloads,
with a "frees ~X" estimate and a confirm step.--scrub(which also clears
the current versions' downloads) is an opt-in toggle, off by default (#82,
#83; issue #80).
Vulnerability scanning hardening
- Exposure parity + native GHSA enrichment. The native build gains the
source: live/cachelabel and GHSA enrichment, and the Tauri over-count is
fixed, with unified card wording across both shells (#107). - Tap-name + JSON-salvage fixes.
brew vulnsnow accepts tap-qualified
formula names and salvages JSON from banner noise (#103; #62, #92). - Native catalog empty-response guard brings the native build to parity
(#108). - GHSA advisory
referencesshape fix. GHSAreferencesare a string
array, not[{url}]; the previous shape made enrichment a silent no-op. Now
repaired and verified end-to-end (#110).
UX and correctness fixes
- Native list scaling — content columns fit the narrow-window floor without
clipping the sidebar (#142). - Install-trend sparkline scale — the sparkline no longer mixes cumulative
and daily counts, removing the "cliff" artifact. Both shells (#143). - Tauri vulnerable-footer navigation — the vulnerable-count footer now jumps
to Library → Vulnerable instead of the Dashboard (#144). - Native outdated tap-name undercount — tap-installed outdated packages are
no longer dropped from the Outdated filter (#145).
Changes
- Package metadata and docs aligned to the release train: Tauri
0.7.0, native
0.3.0.
Acknowledgments
- @cseelye — the resizable Activity console, contributed to both shells
(#136). - @modeezie — the Brew Doctor / Cleanup cache-maintenance request, with a
well-scoped "show me what it's doing" ask and the safer non-scrub default
suggestion (#80). - @Arvuno — the catalog reject-empty-response fix that hardens the catalog
refresh against upstream returning nothing (#101). - Everyone who filed the pin/unpin, brew-options, and vulnerability-scanning
issues that shaped this batch.
Issues & feedback
github.com/msitarzewski/brew-browser/issues.
Every error toast in the app has a "Report" button that pre-fills the issue with
your context.
brew-browser 0.6.0 / native 0.2.0
brew-browser 0.6.0 / Brew Browser native 0.2.0 — feature-request batch
Signed + notarized release. Tauri is the macOS 13+ / Linux build; native is the
macOS 26 SwiftUI build. The two version numbers track the same feature batch
(native 0.2.0 ≙ Tauri 0.6.0); they differ only because each shell versions by
its own release history.
What's new
- Reverse dependencies in package detail. Package pages show which installed
packages require the selected formula ("Required by"). - Deprecated / disabled indicators. Rows and detail panels surface Homebrew's
deprecation and disablement metadata — with the upstream reason and any
replacement token — instead of hiding lifecycle state. - Manual vs Dependency Library filters. Library filtering separates packages
the user requested from formulae installed only as dependencies. - Per-package disk size. Package detail shows the on-disk Cellar/Caskroom
footprint for installed packages. - Discover sub-categories. Within a selected Discover category, members are
grouped by their co-assigned categories so broad buckets are easier to scan. - Friendlier failure notices. When a brew job fails, the Activity drawer now
shows a concise, actionable notice instead of a raw error code. Casks that
need an administrator password (e.g.docker-desktop) — which can't prompt
under brew-browser's non-interactive brew — now explain to run the upgrade in
Terminal, and name the cask.
Changes
- The Dashboard "Recent changes" card has been withdrawn for this release while
its presentation is reworked; it will return in a follow-up. No data is lost —
the full history remains in the Activity view. - Package metadata and docs aligned to the release train: Tauri
0.6.0,
native0.2.0.
Acknowledgments
- The Reddit feature-request feedback that shaped this batch.
brew-browser 0.5.1
brew-browser 0.5.1 — Reliability + a native sibling
Signed + notarized. macOS 13+, Apple Silicon. Auto-updates via the in-app updater.
This release also debuts a second build: a fully native Swift / SwiftUI
app for macOS 26 (Tahoe). Same features, samebrewintegration, same privacy
posture. See the README → "Two builds." The Tauri build below remains the
cross-platform one (macOS 13+ and Linux).
What's new
Live progress during installs and upgrades. Multi-package operations now show
a determinate progress bar with a per-package count — Pouring 10 of 32 — parsed
from brew's own ==> markers, instead of just a wall of streaming text. (#57)
The window remembers its size and position. Resize or move the window, quit,
and relaunch — it reopens exactly where and how you left it. (#17, #19)
The Dashboard fills in on launch. Your GitHub card, the vulnerability Exposure
card, and the sidebar badges now populate from cache on first paint, instead of
looking empty until you poked around.
Fresher catalog. The bundled Homebrew catalog was refreshed (8,404 formulae +
7,703 casks). Hit Refresh anytime for the latest.
Bug fixes
"Upgrade all" no longer cries failure when it succeeded. brew upgrade exits
non-zero on harmless post-install/link warnings even when every package upgraded;
the app treated that as a failure and nudged you to file an issue. Those non-fatal
cases are now reported as success — genuine failures still surface with a clear
message. (Resolves a large cluster of "[brew-browser] Upgrade-all failed" reports.)
"Top categories in your library" filters your library. Clicking a category in
that card now shows your installed packages in it, not the entire Discover
catalog. (#58)
GitHub sign-in is reliable and sticks. The credential is now stored as a single
Keychain item, so signing in is one prompt and the signed-in state persists across
launches (previously it could appear signed-in but not reflect in Settings). (#51)
Window stays draggable with Settings open. The Settings scrim no longer covers
the title bar's drag region. (#8, #10)
Acknowledgments
- @neodave — path-traversal hardening in Brewfile/snapshot handling (#46).
- @Arvuno — a friendly
brew serviceslaunchd-domain hint (#51). - @bytepl (Maciej Chojnacki) — window-state report (#17).
- @unluckyquote (Nik) — unmovable-window-with-Settings-open report (#8).
- Reddit feedback that shaped this release: u/arcadefx1 (operation progress
counts), u/HedgeHog2k and u/sikisabishii (library category filter).
v0.5.0 — Opt-in Vulnerability Scanning
brew-browser v0.5.0 — Opt-in vulnerability scanning
Signed + notarized. macOS 13+, Apple Silicon. Auto-updates from v0.4.0 via the in-app updater.
Highlights
You can now find out which of your installed Homebrew formulae have known CVEs — without leaving the app. v0.5.0 adds opt-in vulnerability scanning powered by the official brew vulns subcommand (Homebrew/homebrew-brew-vulns, by Andrew Nesbitt, published January 2026). When you turn it on, brew-browser shells out to brew vulns to query OSV.dev's GIT ecosystem for vulnerabilities matching your installed formula versions, then optionally enriches each finding with richer prose from the GitHub Advisories API.
Off by default. Both new toggles (vulnerability scanning + GitHub auth for enrichment) sit behind explicit consent in Settings → Network. No first-launch user generates a single OSV query without flipping the switch.
What's new
Opt-in vulnerability scanning. Settings → Network → Vulnerability Scanning toggles the feature on. When brew vulns isn't installed yet, the Settings card shows a one-click installer button that runs brew install homebrew/brew-vulns/brew-vulns for you and streams the output into the Activity drawer. After install, flip the toggle and the first scan kicks off automatically.
Dashboard Exposure card. A new card on the Dashboard shows your aggregate exposure: counts of critical / high / medium / low / unknown findings across all installed formulae, plus a "Scan now" button to force a refresh. When you're clean, the card shows a ✓ checkmark and "No known vulnerabilities" — the clean state IS the message, no collapsing.
Sidebar count badge. A small count badge on the Library nav item shows how many of your installed packages have at least one known CVE. The badge color tracks the highest severity (red for critical, orange for high, amber for medium, blue for low, grey for unknown). Hidden when the count is zero so the sidebar stays uncluttered.
PackageRow severity dots. Library rows get a small color-coded dot next to the installed pill when a package has known vulnerabilities. Hover for a tooltip; click through to the detail panel for the full list. The dots are synchronously hidden when the feature is off — no extra IPC chatter.
PackageDetail Security card. Open any installed formula's detail panel and you'll see a new Security card listing every CVE/GHSA finding for that package: severity pill, advisory ID (linked out to GHSA or OSV when there's a reference URL), summary text, and the version range where it's fixed. When the package is outdated AND at least one finding has a fixed_in range, an "Upgrade to fix" button is wired straight into the existing brew upgrade pipeline. A "Check vulnerabilities" button lets you force a per-package re-scan whenever you want.
Install-set fingerprint optimization. Daily scans on an unchanged install set serve from cache instantly. The backend records a SHA-256 fingerprint of your sorted kind:name:version lines alongside the scan results. On the next open, if nothing has changed, the cached report is returned without re-shelling brew vulns (which can take 60+ seconds with 200 packages). The "Scan now" button on the Dashboard Exposure card forces a full re-scan when you want the latest.
Refresh integration. When you click Refresh on the Dashboard or in Library — which now runs brew update, refreshes the catalog, AND reloads your installed list — the vuln scan re-runs as part of the same flow. So a refresh that learned about a new upstream version of openssl@3 and a new CVE for it shows you the security finding in the same beat as the new version number.
Post-mutation re-scans. Every install / upgrade / uninstall invalidates the affected cache entry and triggers a per-package re-scan, so the Security card and severity dot reflect reality immediately after you act — no stale ✓ from yesterday's pre-upgrade state.
How to enable
- Open Settings → Network → Vulnerability Scanning.
- If
brew vulnsisn't installed, click Installbrew vulns. The output streams into the Activity drawer. Takes ~10 seconds. - Flip the Enable vulnerability scanning toggle on.
- The first scan kicks off automatically. Larger install sets take longer; the Exposure card shows progress.
- Optional: in Settings → GitHub, sign in to GitHub if you want GHSA enrichment — richer summaries, patched-version ranges, and reference links from
api.github.com/advisories. Without GitHub auth, you still get full OSV data; GHSA is purely a UX upgrade.
To turn it off later: flip the same toggle. The on-disk cache stays around (in case you turn it back on) but no scans run and no UI surfaces show vulnerability information. Offline Mode hard-locks the feature regardless.
Trust boundary
This is the first feature that involves an outbound path opened by a subprocess, not by brew-browser itself. The architecture is explicit so the privacy story stays auditable:
api.osv.dev— OSV.dev's GIT-ecosystem query endpoint. POST'd bybrew vulns, not by brew-browser directly. We invoke the subprocess; the subprocess opens the socket. Same trust posture as every otherbrewcall (thebrew installyou ran yesterday also opens sockets to GitHub, OCI registries, and bottle mirrors — and you'd see them in the Activity drawer if you looked).github.com,gitlab.com,codeberg.org— source-URL and version-tag resolution bybrew vulnsso it can match your installed version against the vulnerable-version ranges OSV publishes. Same subprocess-as-origin posture.api.github.com/advisories/{GHSA_ID}— GHSA enrichment from brew-browser's own Rust code, only when both Vulnerability Scanning AND GitHub Sign-in are on. Three independent toggles must align for a single request to leave the box: master Offline Mode off, vulnerability-scanning toggle on, github-enabled toggle on. Failure (rate limit, network error) leaves the OSV record unchanged and logs without bothering you.
Full server-side audit in memory-bank/security.md §17. The gate-composition table, threat model, and pre-launch checklist all live there.
Known limitations (honest gaps)
- Casks aren't supported.
brew vulnsis formula-only. Cask packages render the same UI shell in the Security card but the body honestly says "Cask coverage isn't supported —brew vulnsis formula-only." This isn't fake clean state; we'd rather be honest about the gap than tell you a package is safe when we have no idea. - Formulae with tarball-only sources may show empty results.
brew vulnsresolves vulnerabilities by mapping source URLs to upstream version tags in OSV's GIT ecosystem. Formulae whose source is a tarball without a corresponding Git tag may not match cleanly. This is rare in practice (most Homebrew formulae point at GitHub/GitLab releases that have both tarball and tag), but worth knowing about if a formula you expected to see findings for shows none. - GHSA enrichment is best-effort. If you've enabled GitHub sign-in, GHSA gives you richer data than OSV alone. But if
api.github.comrate-limits you, throws a 5xx, or is unreachable, the enrichment quietly fails and you see the OSV record without the prose extras. No retry, no toast — the scan is reliable; the cherry on top isn't load-bearing.
What's NOT changed
- Without opting in, nothing changes about your outbound posture. No OSV traffic, no GHSA requests, no
brew vulnsinvocations. The previous ten outbound paths from v0.4.0 are unchanged. - The Settings UI keeps the same shape. The new Vulnerability Scanning section sits at the bottom of Network alongside the existing Updates and Enhanced Trending History subsections — same nested-subsection pattern, same "locked off" treatment when Offline Mode is on.
- No new dependencies in the frontend. The store, types, and components are pure additions.
- Two new Rust dependencies (
sha2,hex) for the install-set fingerprint. Both are widely used; SHA-256 is the right primitive here because Rust'sDefaultHasheris non-deterministic across process runs (its salt is randomized to defeat HashDoS) — a hash recorded to disk would mismatch every subsequent launch.
Under the hood
- +78 backend tests (507 → 585). Pin the new gates exhaustively: toggle off →
FeatureDisabled, paranoid on →ParanoidModeBlocked, FirstLaunch →FeatureDisabled(opt-in preserved), Corrupt settings →ParanoidModeBlocked(fail-closed), forward-compat for v0.4.x settings.json missing the new field, formula name validator rejects shell metas + empty + oversize, cache TTL is 6 hours, fingerprint is order-independent, GHSA enrichment short-circuits when github_enabled is off. +6 of those tests are a captured-fixture pin against realbrew vulns --jsonoutput — the live smoke test on a 326-package install caught five integration assumptions that were wrong (severity wire is UPPERCASE;fixed_versionsis an array not a string; install-detection neededbrew --prefix brew-vulns, notbrew commands;--include-aliasesneeds--quiet; brew-vulns exits 1 on findings per CI-scanner convention). All five are now regression-pinned and commented at the trap sites. - One new error variant
vulns_not_installedin the BrewError union, with a friendly message routing the user to the one-click installer (not a generic exit-non-zero toast). - Two on-disk caches at
~/Library/Application Support/brew-browser/:vulns_cache.json(1 MiB cap, 6h per-record TTL) for scan records + the install-set fingerprint;ghsa_cache.json(2 MiB cap) for the enrichment payloads. Both fail soft on corrupt + future-schema — no first-launch user can be wedged by a bad cache file.
Acknowledgements
brew vulnsby Andrew Nesbitt — [github.com/Homebrew/homebrew-brew-vulns](https://github.com/Homebrew/homeb...
v0.4.0 — Trending Velocity + Opt-in History Endpoint
brew-browser v0.4.0 — Velocity scoring + Star-History for Homebrew
Signed + notarized. macOS 13+, Apple Silicon. Auto-updates from v0.3.1 via the in-app updater.
Highlights
Trending now sorts by velocity, not raw count. The old Trending tab was a leaderboard of dep-pulled packages — ca-certificates, openssl@3, git always on top because everything depends on them. v0.4.0 fixes that by computing a per-package velocity index from the three rolling-window install counts Homebrew publishes (30d, 90d, 365d). The math is "this month's installs vs the prior eleven months' average month" — 1.0 is steady, 1.5+ is surging, 0.5 or below is cooling. The Trending tab defaults to sorting by velocity desc with 🔥 / ❄️ badges on each row. The result is what's actually accelerating right now, not what's already big — and packages with zero prior history are filtered out so a brand-new tap doesn't auto-pole-position the leaderboard.
install-on-request signal. The Trending tab now fetches Homebrew's install-on-request analytics endpoint in parallel with the primary install endpoint. The first counts installs users explicitly typed brew install <foo> for; the second includes everything pulled in as dependencies. Both numbers are available on each row internally, with the leaderboard-dominator metric (install) staying as the visible Installs column and the user-intent metric feeding the velocity computation underneath. Together they de-noise the trending signal dramatically.
Star-History for Homebrew (opt-in). When you enable Enhanced Trending History in Settings → Network, you get:
- Inline mini-sparklines on every Trending tab row, showing each package's install trajectory at a glance
- A full install-trend chart on each package's detail panel
- Server-precomputed velocity index that updates nightly (independent from the per-window-fetch computation)
This data comes from a new project-operated endpoint at brew-browser.zerologic.com/trending-history/*. It's the first outbound path in brew-browser's history that goes to infrastructure we control (rather than upstream Homebrew or GitHub), so it gets an explicit opt-in toggle and lives in its own section of the disclosure list at the bottom of Settings → Network. Off by default. Offline Mode hard-locks it off regardless. Only the package name you're viewing is sent (one HTTP GET per package); no IP is logged, no cookies, no fingerprinting. The Caddy log-redaction config that makes the privacy claim auditable is published in memory-bank/security.md §16.
The day-zero seed trick. When you opt in on day one, the historical chart isn't empty — the collector that runs on brew-browser.zerologic.com bootstraps three historical "buckets" per package from rolling-window subtraction (last 30 days, days 31–90, days 91–365). From that point forward, the nightly collector accumulates real daily snapshots; after ~30 days you have clean per-day install estimates. The historical bars fade into the background as the real daily resolution builds up on the right edge of every chart.
Settings → Network reorganization
New disclosure entry (10th in the list, was 9):
brew-browser.zerologic.com/trending-history
Enhanced trending history — opt-in, off by default
New nested subsection at the bottom of Network alongside the existing Updates panel. Single toggle, clear hint copy explaining what's sent, what's logged (nothing identifiable), what's not. Disabled with a "locked off" indicator when Offline Mode is on.
What's NOT changed
- Without opting in, nothing changes about your outbound posture. Velocity sorting and the 🔥/❄️ badges work entirely from the always-on Homebrew analytics endpoints. The only new behavior is "Trending sorts differently by default" — and you can still pick any other sort key from the column headers.
- The previous nine outbound paths are unchanged. README's disclosure section has been updated to enumerate all ten (path j = the new endpoint).
Under the hood
- +33 backend tests (473 → 506). Pin the new gates exhaustively: toggle off →
FeatureDisabled(distinct fromParanoidModeBlockedso toasts route correctly), paranoid on →ParanoidModeBlockedregardless of the per-feature toggle, FirstLaunch →FeatureDisabled(opt-in posture preserved), Corrupt settings →ParanoidModeBlocked(fail-closed via inner gate), URL builder for the per-package fetch rejects path traversal exhaustively (../, spaces,;, etc.). - One new dependency on the backend: none. Velocity math is pure Rust in
src-tauri/src/trending/velocity.rs; the parallelinstall+install-on-requestfetch reuses the existingreqwestclient. The history endpoint client is a thin GET wrapper. - One new dependency on the collector:
better-sqlite3. The collector is a separate Node 20+ ESM project attools/trending-collector/that ONLY runs onbrew-browser.zerologic.com— the brew-browser app itself doesn't pull this in. - New error variant
feature_disabledin the BrewError union, mirrored inBrewErrorPayloadwith a friendly message that routes the user to Settings → Network rather than the master Offline Mode switch.
Acknowledgements
Velocity-as-the-Trending-sort idea came from a user observation: "Trending needs more algo though. It's straight from the brew APIs. We need velocity, right?" The seed-from-rolling-windows bootstrap trick followed from "Use A to create B's first debut. Then we can watch with real data from then on?" — using the same three windows we already fetch to give the historical chart something to show on day zero.
Star-History inline-row sparkline aesthetic borrowed from star-history.com's trending repo list.
Issues & feedback
github.com/msitarzewski/brew-browser/issues. Every error toast in the app has a "Report" button that pre-fills the issue with your context. Use it liberally — it's literally what the button is for.
v0.3.1 — Magic search, real Refresh, cleaner identity
brew-browser v0.3.1 — Magic search, real Refresh, cleaner identity
Signed + notarized. macOS 13+, Apple Silicon. Auto-updates from v0.3.0 via the in-app updater.
Highlights
Magic search. Search now matches against everything brew-browser knows about — not just package names. Try queries like:
video player— finds VLC, mpv, MPlayer (matches AI summaries)password manager— finds 1Password, Bitwarden, KeePassXCAIorLLM— finds ollama, llm, openai-cli, llama.cppVideo & Audio— returns every package in that categoryterminal emulator— iTerm2, Alacritty, kitty, WezTerm
Behind the scenes: a new in-process local_search IPC scans the bundled catalog + AI summaries + friendly names + category labels + (eventually) Tier B tags, scores each hit by field weight (name > friendly > category > summary > desc > tag), and returns top results in well under 20ms — much faster than the previous brew search shell-out.
Unified Description + Version columns. Library, Discover, and Trending list views now share the same canonical row layout: (icon/rank) | NAME | DESCRIPTION | VERSION | TYPE | TRAIL. The Description column prefers the AI-generated summary when available, falls back to the upstream Homebrew desc. Friendly name still appears as a short subtitle below the token for scan-aid.
Curated Upgrade UX. The Updates card on the Dashboard gains a "Choose…" button next to "Upgrade all". Click it to see every outdated package with a checkbox, name, current → target version, and a pinned badge. Pick which ones to upgrade this round; the modal fires one batched brew upgrade <a> <b> ... streaming into the Activity drawer.
Refresh actually refreshes everything. The Refresh button now runs brew update (so brew learns about new upstream versions), refreshes the bundled catalog from formulae.brew.sh, AND reloads your installed list — in that order, streaming the brew update output to the Activity drawer. Previously Refresh only updated the catalog index, leaving outdated flags stale until you ran brew upgrade in a terminal.
Donut chart hover-with-counts. Hover any slice (or its matching legend row) on the Dashboard's "Top categories" donut: the slice fattens, the others dim, and the center text takes over with {count} / {label}. Click the legend row to jump straight to that category in Discover.
Report-to-brew-browser on every error. Error toasts now carry a "Report to brew-browser" button that opens a pre-filled GitHub new-issue URL with your brew-browser + Homebrew versions, the failing command, exit code, stderr excerpt, and the friendly message brew-browser tried to show you. Same button surfaces in the Activity drawer when a job fails.
Friendly error messages. Ten toast sites that previously rendered the raw error code (brew_exit_non_zero) now render the actual friendly message from the backend. Among other things, this means the shiva brew bundle dump topo-sort crash now surfaces with the "this is an upstream Homebrew bug, not a brew-browser issue" guidance it was always meant to.
Quieter improvements
- Bundle identifier cleaned up:
dev.openbrew.browser→com.zerologic.brew-browser. v0.3.0 users will be prompted to re-sign-in to GitHub once (Keychain ACLs are tied to the old identifier; no migration is possible without re-prompting anyway). One-click via the "Re-authorize" toast button that already ships. - Activity history is more durable. Cap raised from 50 jobs to 200.
startJobnow persists immediately instead of waiting for the 400ms debounce. Persist + hydrate failures now log to the console instead of silently swallowing. brew_listcache invalidation. Addingforce=trueto the IPC; the Refresh button uses it. Previously a staleinstalled_cachecould maskbrew upgraderuns from your terminal until process restart.- Stale "Paranoid mode is on" toast wording still slips through the central
brewErrorMessageforparanoid_mode_blocked. The rename to "Offline Mode" was applied everywhere else; this one was missed in Phase 15 and got carried forward — fix landed in this release.
Under the hood
- 473 backend tests passing.
CatalogEntrySummarygains aversion: Option<String>field so the new Version column can render without per-row IPC.- Activity drawer's failed-job footer gains a "Report to brew-browser" button next to the failure summary.
tauri-plugin-dialogwas already wired since v0.1.0 (catching up the realityCheck doc with a post-audit footnote).- Memory bank reorganized:
BUILD.md,PHILOSOPHY.md,PLAN.mdmoved from repo root todocs/;phase15-plan.mdmoved tomemory-bank/phases/now that Phase 15 has shipped.
Install
If you're on v0.3.0, click Refresh on the Dashboard or open Settings → Network → Updates → Check now. The in-app updater will pick this up, verify the signed .app.tar.gz against the embedded minisign pubkey, and replace your installed .app atomically. Click Relaunch now when it finishes.
For fresh installs, the .dmg is on the GitHub release page. Drag to Applications. macOS Gatekeeper accepts it cleanly (signed + notarized + stapled).
Acknowledgments
- @heyjawrsh for the issue-#1 flow that drove the friendly-message + Report-to-brew-browser work.
Full diff: v0.3.0...v0.3.1
v0.3.0 — In-app updater + GitHub coverage + issue #1 fixes
brew-browser v0.3.0 — In-app updater + GitHub coverage + issue #1 fixes
Signed + notarized. macOS 13+, Apple Silicon.
Highlights
In-app updater. brew-browser now tells you when a new version exists. A title-bar pill appears when a newer release is detected; Settings → Network → Updates owns the manual "Check now" button, the off-by-default daily auto-check, and the install action. Every artifact is verified against an embedded minisign public key before any on-disk side effect (sha256 first, then signature — mismatch aborts with no install). Skipping a version is per-release, so a future update re-triggers the notice.
"Offline Mode" instead of "Paranoid Mode." Same kill switch, friendlier name. Toggle in Settings → Network blocks every outbound feature: catalog refresh, trending, GitHub, updater. The internal field stays paranoid_mode to avoid migrating existing settings files.
GitHub coverage expansion. Packages like bat, fd, ripgrep, tealdeer — marketing-page homepages but GitHub-hosted source — now light up Star / Watch / File-issue / Stats. Backend walks homepage → urls.stable.url → urls.head.url (formula) or homepage → url (cask). The Dashboard's personal-stats card sees a bigger denominator.
GitHub Octocat status chip in the title bar. Green when signed in with required scopes, amber when a scope is missing (click → Settings → GitHub to re-authorize), hidden when signed out.
Actionable Re-authorize toast. If an action fails because your token doesn't carry the required scope (typical for tokens minted before v0.3.0 added notifications scope for Watch), the failure toast offers a one-click "Re-authorize" button. GitHub's consent screen shows only the missing scope. No sign-out needed.
Issue #1 fixes. Resolves the toast cascade on disconnect/reconnect that @heyjawrsh reported. Root cause was a cache loop in PackageDetail hammering Svelte's scheduler combined with a structural misuse of $effect for one-shot side effects. Star, Watch, File-issue, and the sign-in flow all work cleanly now.
Under the hood
- 473 backend tests passing (up from 411 in v0.2.1).
- Tauri 2 in-app updater plugin with embedded minisign pubkey + sha256 manifest verification.
- Per-action OAuth scope gating — Star/File-issue need
public_repo, Watch/Unwatch neednotifications. The gate runs server-side before any GitHub round-trip. - New
extract_github_repotolerant URL parser that handles archive + release URLs (.../archive/refs/tags/v1.2.3.tar.gz,.../releases/download/v1.2.3/foo.dmg) while applying every strict-parser defense (host, scheme, character set, path traversal). - Lazy Keychain probe preserved — fresh launches still don't trigger the macOS "wants to use your confidential information" prompt unless you actually use a GitHub feature.
Install
Download brew-browser_0.3.0_aarch64.dmg, double-click, drag to Applications. macOS Gatekeeper will accept the signed + notarized binary without warnings.
If you're on v0.2.1, the in-app updater will surface this release after you upgrade once — manual .dmg installs are still supported but the auto-updater path is the recommended cadence going forward.
Acknowledgments
- @heyjawrsh for filing issue #1 with a clear reproduction. Six hours of debugging surfaced two genuinely interesting Svelte 5 rabbit holes; the diagnosis is in
memory-bank/tasks/2026-05/14-issue-1-hunt-cache-loop.mdand15-github-integration-completion.mdfor the curious.
Full diff: v0.2.1...v0.3.0
brew-browser v0.2.1
brew-browser v0.2.1
Hotfix on top of v0.2.0 — addresses three GitHub-auth issues users hit immediately, plus a few quality-of-life touches.
Fixes
macOS Keychain prompt on every launch
v0.2.0 eagerly probed the Keychain on app start to know whether you were signed in to GitHub. macOS treats a new binary signature as a new app for ACL purposes, so fresh installs of v0.2.0 fired the "brew-browser wants to use your confidential information stored in dev.openbrew.browser" prompt on every launch — even users who'd never touched a GitHub feature.
v0.2.1 makes the Keychain probe lazy: the OS prompt only fires when you actually click Star / Watch / File-issue, or open Settings → GitHub. If you never use a GitHub feature, the Keychain is never touched, and the prompt never fires. When it does fire, it's contextual — you're about to use the token, the prompt is meaningful.
GitHub auth toast bugs
- "Signed in as @github user." — the post-sign-in success toast was reading
status.usernamebefore the username had been fetched. Fixed: status loads beforesigninStateflips to approved. - Stack of duplicate "Signed in to GitHub" toasts — the toast effect re-ran on every status hydration. Fixed:
untrack()wrapping in the Svelte 5 effect so it's pinned to one toast per real state transition.
Star / Watch / File-issue worked correctly when authed
v0.2.0 bounced authenticated users to Settings → GitHub instead of running the action. This is the same root cause as the Keychain prompt — fixed in the same patch (lazy probe in requireGithubSignIn).
Small things
- Real screenshots — the README and landing page now show actual product UI (Dashboard light/dark + Services). Landing's hero
<picture>usesprefers-color-schemeso visitors see the screenshot matching their system theme. - Accurate build credit — "Powered by Anthropic's Claude Opus 4.7 and the Claude Agent SDK" → "Powered by Claude Code in the terminal, running Opus 4.7 [1m]." Claude Code is the runtime (this CLI), Opus 4.7 [1m] is the model.
- gitleaks allowlist — added
.gitleaks.tomlallowlisting the public OAuth Device Flow client_id. Per RFC 8628 §3.1, Device Flow client_ids aren't credentials; the false-positive flag was the only thing gitleaks caught.
Security audit re-run
Full tool battery passed against the v0.2.0/v0.2.1 surface:
| Tool | Result |
|---|---|
cargo audit |
0 vulnerabilities |
cargo deny check |
advisories ok, bans ok, licenses ok, sources ok |
npm audit --omit=dev |
0 vulnerabilities |
semgrep (security-audit + OWASP-10 + Rust + TS, 113 rules, 104 targets) |
0 findings |
gitleaks |
0 leaks (after allowlist) |
Verdict: READY-FOR-SCRUTINY preserved. Full breakdown in memory-bank/security.md §14.
Install
Download the signed + notarized .dmg below, open, drag to Applications. No Gatekeeper warning. macOS 13 (Ventura) or newer · Apple Silicon.
Full changelog
Built with Agency Agents, by the creator of Agency Agents. Powered by Claude Code in the terminal, running Opus 4.7 [1m]. If brew-browser saves you time, sponsor on GitHub ♥.