Bluefin CLI is a Go command-line application for shell configuration, package installation, and desktop customization. Cobra provides the command tree. The interactive interface is a persistent Bubble Tea v2 application.
The repository produces two binaries from the same source:
bluefin-cli, the standard build;bluefin-cli-plus, built with-tags extrato include wallpapers, fonts, sunset automation, and the complete interactive menu.
cmd/defines Cobra commands and assembles TUI destinations. Keep argument parsing and command wiring here; place reusable behavior underinternal/.internal/shell/manages the shell experience for Bash, Zsh, Fish, ash, Nushell, and PowerShell. The user-facing command is wired incmd/shell.go.shells.goholds the registry of managed shells: one entry per shell with its rc path, init line and syntax flavor. Add a shell there rather than in the functions that read it. Installation backends are separate from rendering:installers.goholds the shared entry points and the Homebrew path,windows_tools.gothe winget/PowerShell path,install_alpine.gothe coldbrew/apk path, andshell.gokeeps only enablement, init rendering and status. Do not name a new file with a_windows/_linux/_darwinsuffix unless you mean the GOOS build constraint that comes with it.internal/install/handles packages, bundles, and wallpaper collections. Brewfiles and wallpaper metadata are embedded frominternal/install/resources/; update them withjust update-resources, which also rewritesresources/PROVENANCE.json. That manifest pins each embedded file to an upstream commit and a digest, andprovenance_test.gofails if the tree and the manifest disagree -- so do not hand-edit an embedded resource.internal/tui/app/implements the persistent screen stack, shared header and footer, command palette, and runners for external or streaming operations. Menus and actions are registered fromcmd/menu.goand relatedcmd/menu_*files.internal/config/,internal/profile/, andinternal/update/own persisted configuration, portable profiles, and checksum-verified self-update.docs/commands/holds the generated command reference. Regenerate it withjust gen-docsafter changing commands or flags.
The module needs Go 1.26.0 or later -- the go directive in go.mod is the
source of truth for this number. CI now runs Go 1.27.
just build # build standard and plus binaries
go test ./... # run the local test suite
go test -tags extra -race ./... # exercise the CI build tag with race checks
just test # run the containerized integration suite
just gen-docs # regenerate docs/commandsUse just --list for the complete recipe list. Podman is required by the
container-based recipes.
Three shell suites sit under scripts/, and they check different things:
tui-smoke.sh asserts what appears on screen, tui-state.sh asserts what
lands in config files, and shell-experience.sh starts each supported shell
and asserts the experience the init script produces -- the aliases, the
prompt, PATH, and that startup stays silent. Run it with
scripts/shell-experience.sh <binary> [shell ...]; it covers bash, zsh, ash,
dash, fish, nushell and pwsh, and skips any shell that is not installed, so it
is useful locally with only bash. shell-experience.ps1 runs the PowerShell
half on Windows, where shell.ps1's executable lookup probes paths that exist
nowhere else.
Two scoping rules have already cost this repo silent breakage, and both are
easy to reintroduce: nushell's alias is parse-time, so one written inside an
if is scoped away (hence the generated aliases in nu_aliases.go), and
PowerShell scopes a function declared inside a function to its parent, so
the user-facing ones in shell.ps1 must be global:.
- Put shared behavior in the relevant
internal/package, and keep the functions for each Cobra command small. - Test both the standard and
extrabuild-tag paths after a change to a conditional feature. Stubs for the standard build live incmd/extra_stubs.go. - Add TUI destinations as
app.Screenimplementations or registeredapp.Actionvalues. Use the existing runner/external-process bridge for commands that must temporarily own the terminal. - Do not edit the generated command pages by hand. Change the Cobra definition and
run
just gen-docs. CI fails if a regeneration makes a diff. - Update the embedded package data with
just update-resources. Do not add a runtime download for a resource that must ship in the binary.