From 3113014b58b64313de362175830d0b5bf08931f9 Mon Sep 17 00:00:00 2001 From: sneak Date: Wed, 17 Jun 2026 05:54:48 +0200 Subject: [PATCH] Print banner when vaultik is invoked with no subcommand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cobra's default 'no subcommand → print help' path bypasses fx, so the startup banner never ran for bare 'vaultik'. Add a Run handler on the root command that prints the banner and then calls Help. Extracted the banner-printing logic into writeStartupBanner() so both this path and the fx setupGlobals hook share one implementation. --- internal/cli/app.go | 19 +++++++++++++------ internal/cli/root.go | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/internal/cli/app.go b/internal/cli/app.go index 0dfa599..b66cd89 100644 --- a/internal/cli/app.go +++ b/internal/cli/app.go @@ -46,18 +46,25 @@ func setupGlobals(lc fx.Lifecycle, g *globals.Globals, v *vaultik.Vaultik, opts // user-facing output is suppressed. v.UI = ui.NewWithColor(io.Discard, false) } else { - v.UI.Banner("%s %s by %s (commit %s, built on %s) starting up at %s.", - g.Appname, g.Version, globals.Author, - g.ShortCommit(), g.CommitDate, - g.StartTime.Format(time.RFC3339)) - v.UI.Banner("%s", globals.Homepage) - v.UI.Banner("") + writeStartupBanner(v.UI, g.StartTime, g.ShortCommit()) } return nil }, }) } +// writeStartupBanner prints the two-line application banner followed by a +// blank line. Used both from the fx hook (for subcommand invocations) and +// from the root cobra Run handler (for `vaultik` with no subcommand). +func writeStartupBanner(w *ui.Writer, startTime time.Time, shortCommit string) { + w.Banner("%s %s by %s (commit %s, built on %s) starting up at %s.", + globals.Appname, globals.Version, globals.Author, + shortCommit, globals.CommitDate, + startTime.Format(time.RFC3339)) + w.Banner("%s", globals.Homepage) + w.Banner("") +} + // NewApp creates a new fx application with common modules. // It sets up the base modules (config, database, logging, globals) and // combines them with any additional modules specified in the options. diff --git a/internal/cli/root.go b/internal/cli/root.go index 59fe347..872f1b2 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -5,9 +5,12 @@ import ( "os" "path/filepath" "strings" + "time" "github.com/adrg/xdg" "github.com/spf13/cobra" + "sneak.berlin/go/vaultik/internal/globals" + "sneak.berlin/go/vaultik/internal/ui" ) // RootFlags holds global flags that apply to all commands. @@ -32,6 +35,18 @@ func NewRootCommand() *cobra.Command { public keys and uploads to S3-compatible storage. No private keys are needed on the source system.`, SilenceUsage: true, + // When invoked with no subcommand, print the banner then the + // usage/help. Cobra's default behavior (without a Run) just + // prints help, which skips the banner. + Run: func(cmd *cobra.Command, args []string) { + startTime := time.Now().UTC() + short := globals.Commit + if len(short) > 12 { + short = short[:12] + } + writeStartupBanner(ui.New(os.Stdout), startTime, short) + _ = cmd.Help() + }, } // Add global flags