diff --git a/internal/cli/cluster.go b/internal/cli/cluster.go index ca12976..021327b 100644 --- a/internal/cli/cluster.go +++ b/internal/cli/cluster.go @@ -117,6 +117,8 @@ func runClusterInfo( ingestorSAOverride string, tokenExpiry int64, ) error { + p.Banner("tracebloc", "cluster diagnostics") + resolved, err := cluster.Load(cluster.KubeconfigOptions{ Path: kubeconfigPath, Context: contextOverride, diff --git a/internal/cli/root.go b/internal/cli/root.go index e2b8205..7f725d0 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -80,6 +80,23 @@ what's planned next.`, root.AddCommand(newClusterCmd()) root.AddCommand(newDatasetCmd()) + // Bare `tracebloc` (no subcommand) renders a friendly home screen + // instead of cobra's raw usage dump. Subcommands and --help are + // unaffected — cobra dispatches those before this RunE runs. + root.RunE = func(cmd *cobra.Command, args []string) error { + if len(args) > 0 { + return cmd.Help() // an arg that wasn't a known subcommand + } + p := printerFor(cmd) + p.Banner("tracebloc", "declarative data ingestion for your cluster") + p.Section("Get started") + p.Infof("tracebloc dataset push ./data — stage + ingest a dataset (guided if you omit flags)") + p.Infof("tracebloc cluster info — check the CLI can reach your cluster") + p.Infof("tracebloc ingest validate f.yaml — validate an ingest.yaml locally") + p.Hintf("Add --help to any command for the full flag list.") + return nil + } + return root } diff --git a/internal/cli/root_test.go b/internal/cli/root_test.go index 331682f..a7c0a21 100644 --- a/internal/cli/root_test.go +++ b/internal/cli/root_test.go @@ -28,6 +28,26 @@ func TestRootCmd_HelpMentionsBinary(t *testing.T) { } } +// TestRootCmd_HomeScreen: a bare `tracebloc` (no subcommand) renders +// the branded home screen pointing at the key commands, rather than +// erroring or dumping raw usage. +func TestRootCmd_HomeScreen(t *testing.T) { + root := NewRootCmd(BuildInfo{Version: "test"}) + var out bytes.Buffer + root.SetOut(&out) + root.SetErr(&out) + root.SetArgs([]string{}) + + if err := root.Execute(); err != nil { + t.Fatalf("bare root failed: %v\n%s", err, out.String()) + } + for _, want := range []string{"tracebloc", "dataset push", "cluster info"} { + if !strings.Contains(out.String(), want) { + t.Errorf("home screen missing %q:\n%s", want, out.String()) + } + } +} + // `completion` is auto-registered by cobra, but it's load-bearing // for shell autocomplete UX. Verify it's reachable so a future // refactor that accidentally disables it (e.g. by setting