Users can now load Brewfiles from remote URLs:
bbrew -f https://example.com/Brewfile
Remote files are downloaded to a temp file and auto-cleaned on exit.
Only HTTPS URLs are supported for security.
- Truncate version strings to max 15 chars with ellipsis
- Adjust layout proportions: left 75%, right 25%
- Prevents overly wide version columns from breaking layout
* refactor(services): split brew.go into focused modules
Reorganize the services package for better maintainability:
- brew.go: Interface and struct definitions
- data.go: Data loading, caching, and tap package management
- cache.go: Low-level cache I/O helpers
- packages.go: Package retrieval (GetFormulae, GetPackages)
- operations.go: Package operations (install, update, remove)
- parser.go: Brewfile parsing
- brewfile.go: Brewfile-specific app logic (extracted from app.go)
This reduces the largest file from 1124 to 322 lines and improves
separation of concerns across the codebase.
* refactor(services): introduce DataProvider pattern for data loading
Extract data loading logic into a dedicated DataProvider service that
handles all data retrieval operations (formulae, casks, analytics, cache).
BrewService now delegates to DataProvider via interface for better
testability and separation of concerns.
Also centralizes cache file name constants in dataprovider.go for
maintainability.
* refactor(services): centralize data in DataProvider and improve naming consistency
Move all data-related fields and retrieval methods from BrewService to DataProvider, making BrewService focused solely on brew operations. Rename formula fields (all, installed, remote, analytics) to be consistent with cask naming convention (allFormulae, installedFormulae, etc.). Remove redundant data.go and packages.go files.
* refactor(services): consolidate code and fix shared dependencies
- IOService now receives BrewService as parameter instead of creating new instance
- Move API URL constants from brew.go to dataprovider.go (now private)
- Move getCacheDir to cache.go where it belongs
- Remove unused GetPrefixPath from BrewService interface
- Consolidate Brewfile parsing into brewfile.go as standalone function
- Delete parser.go (logic merged into brewfile.go)
* fix(brewfile): prevent duplicate packages in list after refresh
Add duplicate detection checks in loadBrewfilePackages to ensure each package appears only once in the Brewfile package list, even when refreshing after install/remove operations.
* refactor(services): extract search methods to dedicated file
Move search(), setResults(), and forceRefreshResults() from app.go
to search.go for better code organization and separation of concerns.
* refactor(services): remove dead code and unify helpers
Remove unused methods and fields:
- GetFormulae(), IsPackageInstalled() from DataProvider
- InstallAllPackages(), RemoveAllPackages() from BrewService
- allFormulae, allCasks fields from DataProvider
Unify GetInstalledCaskNames and GetInstalledFormulaNames with
a common getInstalledNames helper to reduce code duplication.
* docs(brewfile): add package documentation with execution sequence
Document Brewfile mode functionality including parsing, tap installation,
and package loading. Add execution sequence diagram and note that methods
are only active in Brewfile mode (bbrew -f <file>).
* refactor(services): move fetchFromAPI to dataprovider
Move HTTP fetch function from cache.go to dataprovider.go where it
belongs semantically. cache.go now contains only cache I/O operations.
* refactor(dataprovider): improve method naming consistency
Rename Load* methods to Get* with forceRefresh parameter for clarity:
- LoadInstalledFormulae → GetInstalledFormulae
- LoadRemoteFormulae → GetRemoteFormulae
- LoadTapPackages → GetTapPackages (and similar)
Rename Get* methods that execute commands to Fetch* for accuracy:
- GetInstalledCaskNames → FetchInstalledCaskNames
- GetInstalledFormulaNames → FetchInstalledFormulaNames
Replace forceDownload parameter with forceRefresh throughout.
* refactor(input): rename io.go to input.go and simplify code
Rename IOService/IOAction to InputService/InputAction for semantic
correctness (io in Go refers to file I/O, not keyboard input).
Simplify handleFilterEvent with helper methods: isFilterActive(),
setFilterActive(), updateFilterUI() reducing ~30 lines of repetitive code.
Extract handleBatchPackageOperation() helper for InstallAll/RemoveAll
operations, reducing ~90 lines of duplicate code with a configurable
batchOperation struct.
* refactor(filters): replace 4 booleans with FilterType enum
Replace showOnlyInstalled, showOnlyOutdated, showOnlyLeaves, showOnlyCasks
with a single activeFilter field of type FilterType.
Add FilterNone constant for no active filter state.
Simplify handleFilterEvent to simple toggle logic.
Extract applyFilter method with clean switch statement.
Remove redundant isFilterActive and setFilterActive helpers.
* refactor(brew): merge operations.go into brew.go
Consolidate all BrewService methods into a single file.
Add section comments to organize code into logical groups:
- Core info (GetBrewVersion)
- Package operations (Update/Install/Remove)
- Tap support (InstallTap/IsTapInstalled)
- Internal helpers (executeCommand)
* fix(dataprovider): suppress gosec G107 false positive
The URL passed to http.Get comes from internal constants (Homebrew API URLs),
not from user input.
* feat(legend): add HideFromLegend flag to reduce legend size
Hide Back and Quit actions from legend bar as they are intuitive keys. This prepares for a more compact legend with a dedicated help screen.
* feat(ui): add help screen with keyboard shortcuts overlay
Add a help modal accessible via '?' key that displays all keyboard shortcuts organized by category (Navigation, Filters, Actions, Brewfile). Reduce legend bar clutter by hiding less common actions and showing only essential shortcuts. Add HideFromLegend flag to IOAction struct for flexible legend management.
Add support for parsing and installing taps from Brewfile entries. Taps are automatically installed at startup before updating Homebrew data. Tap package information is cached for faster subsequent startups. Also fixes thread safety issues with UI notifications in background goroutines and improves error handling for brew command execution.
- Cache all Homebrew data (installed packages, remote formulae/casks, analytics)
- Reduce startup time from 1-2s to ~50-100ms with populated cache
- Add cache validation to prevent corrupted data usage
- Make boot process resilient to cache corruption and network failures
- Background update ensures data freshness after startup
Cache files stored in ~/Library/Caches/bbrew/ following XDG standards:
- installed.json, installed-casks.json (local packages)
- formula.json, cask.json (remote packages)
- analytics.json, cask-analytics.json (download stats)
The app now starts instantly using cached data, then updates in background
without blocking the UI. Falls back gracefully if cache is corrupted or
network is unavailable.
Updates the UI theme system and improves visual consistency and accessibility across different terminal themes. The main changes include refactoring how colors are handled, updating component styles for better visibility, and ensuring that global styles adapt to the user's terminal settings.
* feat: add Brewfile mode for curated package collections
This commit introduces Brewfile mode, allowing users to launch bbrew with
a curated list of packages using the -f flag. When a Brewfile is provided,
the application displays only those packages, enabling themed collections
like IDE choosers or developer tool sets.
The implementation includes a Brewfile parser for brew and cask entries,
automatic filtering of the package catalog, and a refactored API with the
IsBrewfileMode() method for cleaner code. Critical bugs were fixed including
a synchronization issue between the displayed table and the filtered packages
array that caused incorrect package selection.
This feature is designed for Project Bluefin integration, providing curated
package experiences where users can browse predefined collections. Includes
example Brewfiles and comprehensive documentation.
* feat: add Install All functionality for Brewfile mode
Add ctrl+a keybinding to install all packages from a Brewfile at once,
available exclusively in Brewfile mode.
* feat: add Remove All for Brewfile mode
Add ctrl+r keybinding to batch remove all installed packages from
Brewfile with real-time progress counter. Validates packages are
installed before proceeding and skips non-installed packages.
Available only in Brewfile mode
* feat: add leaves filter to show explicitly installed packages (#25)
Add new filter [L] to display only "leaf" packages - those installed
explicitly by the user and not as dependencies of other packages.
* refactor: Migrate to Podman with OCI Containerfile and enhanced Makefile (#26)
* refactor: migrate from Docker to Podman with OCI Containerfile
Replace Docker with Podman for better security and OCI compliance.
Switch from Dockerfile to standard Containerfile format.
* chore: upgrade Go from 1.24 to 1.25
Update Go version to 1.25 to support latest goreleaser v2 and benefit from improved performance and language features.
* refactor: migrate to Podman and enhance Makefile
Replace Docker with Podman and upgrade Makefile with help system and new developer-friendly targets.
* chore: upgrade to Go 1.25 and golangci-lint v2.5.0
Update Go to 1.25 and golangci-lint to v2.5.0 for better tooling support.
* feat: add security scanning with govulncheck and gosec (#27)
Add comprehensive security scanning to the project with vulnerability checks and static analysis tools.
* feat: Add complete Casks support with unified UI (#28)
* feat(cask): add backend support for Homebrew casks
Implement complete backend infrastructure for managing Homebrew casks alongside formulae, preparing for unified UI.
* feat(cask): add complete Homebrew casks support with unified UI
Implement full backend and UI support for managing Homebrew casks alongside formulae in a unified interface.
* fix(cask): parse cask analytics correctly
Fix cask analytics not being displayed (showing 0 for all casks).
* feat(cask): add complete Homebrew casks support with unified UI
Implement full backend and UI support for managing Homebrew casks alongside formulae in a unified interface.
* fix: create copy to avoid implicit memory aliasing
* feat: implement XDG Base Directory Specification with github.com/adrg/xdg (#29)
Implement XDG Base Directory Specification using the github.com/adrg/xdg package for robust cross-platform support.
* refactored move formatting logic to Details ui component
* refactored the setContent for details formatting and remove setFormula
* refactor: clean up LocalPath handling and improve details formatting