Skip to content

Commit e86e3cf

Browse files
cloinpatelspratik
andauthored
Restructure CLI Help Output with Improved Categorization (#265)
* Restructure CLI help output with improved categorization - Fix duplicate start command registration bug - Reorganize commands into semantic categories: - Workspace Commands: core workspace operations (create, start, stop, ls, etc.) - Workspace Access: tools for accessing workspaces (shell, open, copy, port-forward) - Organization Management: org-related commands with helpful subcommand hints - Configuration: settings, secrets, and account management - Quick Start: onboarding commands like ollama - Update command annotations from old categories (context, ssh, housekeeping) to new ones - Add inline tips and hints to guide users (e.g., 'Use brev org --help for subcommands') - Improve help text discoverability by showing common org subcommands in main help * Hide dev-only commands from help output - Move 'fu' command to hidden annotation (inappropriate name, dev-only) - Move 'env-vars' to hidden annotation (redundant with configure-env-vars) - These commands remain functional but won't appear in help text * Hide non-functional secret command from help output - Move 'secret' command to hidden annotation (non-functional) - Command remains available but won't appear in help text * Hide non-functional ollama command from help output - Move 'ollama' command to hidden annotation (non-functional) - Removes 'Quick Start' section from help (no longer needed) - Command remains available but won't appear in help text * Improve help text clarity and consistency - Fix typo: 'pulic' -> 'public' in ssh-key description - Standardize capitalization: all descriptions start with capital letter - Capitalize proper nouns: Brev, SSH, CLI - Improve command descriptions for clarity - Remove misplaced org tip from workspace commands section - Remove detailed subcommand list from org help - Add inline tip to org command description * Fix org subcommands not showing in help output - Set org command to use default Cobra template instead of custom filtered template - Update annotations for org subcommands to use consistent 'orgsubcommand' annotation - This ensures all org subcommands (create, invite, ls, set) are visible when running 'brev org -h' * Hide status command from help output * Document invite and set as aliases in help text - Update Short descriptions to indicate they are aliases for 'brev org invite' and 'brev org set' - This makes it clearer to users that these are convenience shortcuts * Capitalize flag descriptions for consistency - Capitalize first letter of --user flag description - Maintains consistency with command descriptions * Capitalize Brev in help flag description - Define help flag manually to override Cobra's default lowercase description - Ensures consistency with 'Help for Brev' instead of 'help for brev' * Hide internal commands and update workspace to instance in help text * Add provider-dependent support warning for start, stop, and reset commands * Update redeem command for new help structure and remove 'coupon' from descriptions * Update pkg/cmd/refresh/refresh.go Co-authored-by: Pratik Patel <patel.s.pratik@gmail.com> --------- Co-authored-by: Pratik Patel <patel.s.pratik@gmail.com>
1 parent 71cb57d commit e86e3cf

34 files changed

Lines changed: 174 additions & 117 deletions

File tree

pkg/cmd/background/background.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type BackgroundStore interface {
3030

3131
func NewCmdBackground(t *terminal.Terminal, s BackgroundStore) *cobra.Command {
3232
cmd := &cobra.Command{
33-
Annotations: map[string]string{"workspace": ""},
33+
Annotations: map[string]string{"hidden": ""},
3434
Use: "background [flags] [command]",
3535
Aliases: []string{"bg"},
3636
DisableFlagsInUseLine: true,

pkg/cmd/cmd.go

Lines changed: 89 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,14 @@ var (
6969

7070
func NewDefaultBrevCommand() *cobra.Command {
7171
cmd := NewBrevCommand()
72-
cmd.PersistentFlags().StringVar(&userFlag, "user", "", "non root user to use for per user configuration of commands run as root")
72+
73+
// Define help flag before Cobra does with proper capitalization
74+
cmd.PersistentFlags().BoolP("help", "h", false, "Help for Brev")
75+
76+
cmd.PersistentFlags().StringVar(&userFlag, "user", "", "Non root user to use for per user configuration of commands run as root")
7377
cmd.PersistentFlags().BoolVar(&printVersion, "version", false, "Print version output")
7478
cmd.PersistentFlags().BoolVar(&noCheckLatest, "no-check-latest", false, "Do not check for the latest version when printing version")
79+
7580
return cmd
7681
}
7782

@@ -213,19 +218,20 @@ func NewBrevCommand() *cobra.Command { //nolint:funlen,gocognit,gocyclo // defin
213218
}
214219
},
215220
}
216-
cobra.AddTemplateFunc("hasContextCommands", hasContextCommands)
217-
cobra.AddTemplateFunc("contextCommands", contextCommands)
218-
cobra.AddTemplateFunc("hasSSHCommands", hasSSHCommands)
219-
cobra.AddTemplateFunc("sshCommands", sshCommands)
220221
cobra.AddTemplateFunc("hasWorkspaceCommands", hasWorkspaceCommands)
221222
cobra.AddTemplateFunc("workspaceCommands", workspaceCommands)
222-
cobra.AddTemplateFunc("hasHousekeepingCommands", hasHousekeepingCommands)
223-
cobra.AddTemplateFunc("hasDebugCommands", hasDebugCommands)
224-
cobra.AddTemplateFunc("debugCommands", debugCommands)
225-
cobra.AddTemplateFunc("printCautiousMetaCmdMessage", printCautiousMetaCmdMessage)
226-
cobra.AddTemplateFunc("housekeepingCommands", housekeepingCommands)
223+
cobra.AddTemplateFunc("hasProviderDependentCommands", hasProviderDependentCommands)
224+
cobra.AddTemplateFunc("providerDependentCommands", providerDependentCommands)
225+
cobra.AddTemplateFunc("hasAccessCommands", hasAccessCommands)
226+
cobra.AddTemplateFunc("accessCommands", accessCommands)
227+
cobra.AddTemplateFunc("hasOrganizationCommands", hasOrganizationCommands)
228+
cobra.AddTemplateFunc("organizationCommands", organizationCommands)
229+
cobra.AddTemplateFunc("hasConfigurationCommands", hasConfigurationCommands)
230+
cobra.AddTemplateFunc("configurationCommands", configurationCommands)
227231
cobra.AddTemplateFunc("hasQuickstartCommands", hasQuickstartCommands)
228232
cobra.AddTemplateFunc("quickstartCommands", quickstartCommands)
233+
cobra.AddTemplateFunc("hasDebugCommands", hasDebugCommands)
234+
cobra.AddTemplateFunc("debugCommands", debugCommands)
229235

230236
cmds.SetUsageTemplate(usageTemplate)
231237

@@ -274,7 +280,6 @@ func createCmdTree(cmd *cobra.Command, t *terminal.Terminal, loginCmdStore *stor
274280
cmd.AddCommand(secret.NewCmdSecret(loginCmdStore, t))
275281
cmd.AddCommand(sshkeys.NewCmdSSHKeys(t, loginCmdStore))
276282
cmd.AddCommand(start.NewCmdStart(t, loginCmdStore, noLoginCmdStore))
277-
cmd.AddCommand(start.NewCmdStart(t, loginCmdStore, noLoginCmdStore))
278283
cmd.AddCommand(create.NewCmdCreate(t, loginCmdStore))
279284
cmd.AddCommand(stop.NewCmdStop(t, loginCmdStore, noLoginCmdStore))
280285
cmd.AddCommand(delete.NewCmdDelete(t, loginCmdStore, noLoginCmdStore))
@@ -291,122 +296,136 @@ func createCmdTree(cmd *cobra.Command, t *terminal.Terminal, loginCmdStore *stor
291296
cmd.AddCommand(updatemodel.NewCmdupdatemodel(t, loginCmdStore))
292297
}
293298

294-
func hasQuickstartCommands(cmd *cobra.Command) bool {
295-
return len(quickstartCommands(cmd)) > 0
299+
func hasWorkspaceCommands(cmd *cobra.Command) bool {
300+
return len(workspaceCommands(cmd)) > 0
296301
}
297302

298-
func hasHousekeepingCommands(cmd *cobra.Command) bool {
299-
return len(housekeepingCommands(cmd)) > 0
303+
func hasAccessCommands(cmd *cobra.Command) bool {
304+
return len(accessCommands(cmd)) > 0
300305
}
301306

302-
func hasDebugCommands(cmd *cobra.Command) bool {
303-
return len(debugCommands(cmd)) > 0
307+
func hasOrganizationCommands(cmd *cobra.Command) bool {
308+
return len(organizationCommands(cmd)) > 0
304309
}
305310

306-
func printCautiousMetaCmdMessage() string {
307-
yellow := color.New(color.FgYellow, color.Bold).SprintFunc()
308-
return yellow("(we're actively working on getting rid of these commands)")
311+
func hasConfigurationCommands(cmd *cobra.Command) bool {
312+
return len(configurationCommands(cmd)) > 0
309313
}
310314

311-
func hasSSHCommands(cmd *cobra.Command) bool {
312-
return len(sshCommands(cmd)) > 0
315+
func hasQuickstartCommands(cmd *cobra.Command) bool {
316+
return len(quickstartCommands(cmd)) > 0
313317
}
314318

315-
func hasWorkspaceCommands(cmd *cobra.Command) bool {
316-
return len(workspaceCommands(cmd)) > 0
319+
func hasDebugCommands(cmd *cobra.Command) bool {
320+
return len(debugCommands(cmd)) > 0
317321
}
318322

319-
func hasContextCommands(cmd *cobra.Command) bool {
320-
return len(contextCommands(cmd)) > 0
323+
func hasProviderDependentCommands(cmd *cobra.Command) bool {
324+
return len(providerDependentCommands(cmd)) > 0
321325
}
322326

323-
func quickstartCommands(cmd *cobra.Command) []*cobra.Command {
327+
func workspaceCommands(cmd *cobra.Command) []*cobra.Command {
324328
cmds := []*cobra.Command{}
325329
for _, sub := range cmd.Commands() {
326-
if isQuickstartCommand(sub) {
330+
if isWorkspaceCommand(sub) {
327331
cmds = append(cmds, sub)
328332
}
329333
}
330334
return cmds
331335
}
332336

333-
func housekeepingCommands(cmd *cobra.Command) []*cobra.Command {
337+
func accessCommands(cmd *cobra.Command) []*cobra.Command {
334338
cmds := []*cobra.Command{}
335339
for _, sub := range cmd.Commands() {
336-
if isHousekeepingCommand(sub) {
340+
if isAccessCommand(sub) {
337341
cmds = append(cmds, sub)
338342
}
339343
}
340344
return cmds
341345
}
342346

343-
func debugCommands(cmd *cobra.Command) []*cobra.Command {
347+
func organizationCommands(cmd *cobra.Command) []*cobra.Command {
344348
cmds := []*cobra.Command{}
345349
for _, sub := range cmd.Commands() {
346-
if isDebugCommand(sub) {
350+
if isOrganizationCommand(sub) {
347351
cmds = append(cmds, sub)
348352
}
349353
}
350354
return cmds
351355
}
352356

353-
func sshCommands(cmd *cobra.Command) []*cobra.Command {
357+
func configurationCommands(cmd *cobra.Command) []*cobra.Command {
354358
cmds := []*cobra.Command{}
355359
for _, sub := range cmd.Commands() {
356-
if isSSHCommand(sub) {
360+
if isConfigurationCommand(sub) {
357361
cmds = append(cmds, sub)
358362
}
359363
}
360364
return cmds
361365
}
362366

363-
func workspaceCommands(cmd *cobra.Command) []*cobra.Command {
367+
func quickstartCommands(cmd *cobra.Command) []*cobra.Command {
364368
cmds := []*cobra.Command{}
365369
for _, sub := range cmd.Commands() {
366-
if isWorkspaceCommand(sub) {
370+
if isQuickstartCommand(sub) {
371+
cmds = append(cmds, sub)
372+
}
373+
}
374+
return cmds
375+
}
376+
377+
func debugCommands(cmd *cobra.Command) []*cobra.Command {
378+
cmds := []*cobra.Command{}
379+
for _, sub := range cmd.Commands() {
380+
if isDebugCommand(sub) {
367381
cmds = append(cmds, sub)
368382
}
369383
}
370384
return cmds
371385
}
372386

373-
func contextCommands(cmd *cobra.Command) []*cobra.Command {
387+
func providerDependentCommands(cmd *cobra.Command) []*cobra.Command {
374388
cmds := []*cobra.Command{}
375389
for _, sub := range cmd.Commands() {
376-
if isContextCommand(sub) {
390+
if isProviderDependentCommand(sub) {
377391
cmds = append(cmds, sub)
378392
}
379393
}
380394
return cmds
381395
}
382396

383-
func isQuickstartCommand(cmd *cobra.Command) bool {
384-
_, ok := cmd.Annotations["quickstart"]
397+
func isWorkspaceCommand(cmd *cobra.Command) bool {
398+
_, ok := cmd.Annotations["workspace"]
385399
return ok
386400
}
387401

388-
func isHousekeepingCommand(cmd *cobra.Command) bool {
389-
_, ok := cmd.Annotations["housekeeping"]
402+
func isAccessCommand(cmd *cobra.Command) bool {
403+
_, ok := cmd.Annotations["access"]
390404
return ok
391405
}
392406

393-
func isDebugCommand(cmd *cobra.Command) bool {
394-
_, ok := cmd.Annotations["debug"]
407+
func isOrganizationCommand(cmd *cobra.Command) bool {
408+
_, ok := cmd.Annotations["organization"]
395409
return ok
396410
}
397411

398-
func isSSHCommand(cmd *cobra.Command) bool {
399-
_, ok := cmd.Annotations["ssh"]
412+
func isConfigurationCommand(cmd *cobra.Command) bool {
413+
_, ok := cmd.Annotations["configuration"]
400414
return ok
401415
}
402416

403-
func isWorkspaceCommand(cmd *cobra.Command) bool {
404-
_, ok := cmd.Annotations["workspace"]
417+
func isQuickstartCommand(cmd *cobra.Command) bool {
418+
_, ok := cmd.Annotations["quickstart"]
419+
return ok
420+
}
421+
422+
func isDebugCommand(cmd *cobra.Command) bool {
423+
_, ok := cmd.Annotations["debug"]
405424
return ok
406425
}
407426

408-
func isContextCommand(cmd *cobra.Command) bool {
409-
_, ok := cmd.Annotations["context"]
427+
func isProviderDependentCommand(cmd *cobra.Command) bool {
428+
_, ok := cmd.Annotations["provider-dependent"]
410429
return ok
411430
}
412431

@@ -420,38 +439,44 @@ Aliases:
420439
Examples:
421440
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
422441
423-
{{- if hasWorkspaceCommands . }}
442+
{{- if or (hasWorkspaceCommands .) (hasProviderDependentCommands .) }}
424443
425444
Instance Commands:
426445
{{- range workspaceCommands . }}
427446
{{rpad .Name .NamePadding }} {{.Short}}
428-
{{- end}}{{- end}}
447+
{{- end}}
448+
{{- if hasProviderDependentCommands . }}
429449
430-
{{- if hasSSHCommands . }}
450+
The following commands have provider-dependent support:
451+
{{- range providerDependentCommands . }}
452+
{{rpad .Name .NamePadding }} {{.Short}}
453+
{{- end}}{{- end}}{{- end}}
431454
432-
{{- if hasContextCommands . }}
455+
{{- if hasAccessCommands . }}
433456
434-
Context Commands:
435-
{{- range contextCommands . }}
457+
Instance Access:
458+
{{- range accessCommands . }}
436459
{{rpad .Name .NamePadding }} {{.Short}}
437460
{{- end}}{{- end}}
438461
439-
SSH Commands:
440-
{{- range sshCommands . }}
462+
{{- if hasOrganizationCommands . }}
463+
464+
Organization Management:
465+
{{- range organizationCommands . }}
441466
{{rpad .Name .NamePadding }} {{.Short}}
442467
{{- end}}{{- end}}
443468
444-
{{- if hasQuickstartCommands . }}
469+
{{- if hasConfigurationCommands . }}
445470
446-
Quickstart Commands:
447-
{{- range quickstartCommands . }}
471+
Configuration:
472+
{{- range configurationCommands . }}
448473
{{rpad .Name .NamePadding }} {{.Short}}
449474
{{- end}}{{- end}}
450475
451-
{{- if hasHousekeepingCommands . }}
476+
{{- if hasQuickstartCommands . }}
452477
453-
Housekeeping Commands:
454-
{{- range housekeepingCommands . }}
478+
Quick Start:
479+
{{- range quickstartCommands . }}
455480
{{rpad .Name .NamePadding }} {{.Short}}
456481
{{- end}}{{- end}}
457482

pkg/cmd/configureenvvars/configureenvvars.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ type ConfigureEnvVarsStore interface {
2626

2727
func NewCmdConfigureEnvVars(_ *terminal.Terminal, cevStore ConfigureEnvVarsStore) *cobra.Command {
2828
cmd := &cobra.Command{
29-
Annotations: map[string]string{"housekeeping": ""},
29+
Annotations: map[string]string{"hidden": ""},
3030
Use: "configure-env-vars",
3131
DisableFlagsInUseLine: true,
32-
Short: "configure env vars in supported shells",
32+
Short: "Configure environment variables in supported shells",
3333
Long: "configure env vars in supported shells",
3434
Example: "",
3535
RunE: func(cmd *cobra.Command, args []string) error {

pkg/cmd/copy/copy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ type CopyStore interface {
4040
func NewCmdCopy(t *terminal.Terminal, store CopyStore, noLoginStartStore CopyStore) *cobra.Command {
4141
var host bool
4242
cmd := &cobra.Command{
43-
Annotations: map[string]string{"ssh": ""},
43+
Annotations: map[string]string{"access": ""},
4444
Use: "copy",
4545
Aliases: []string{"cp", "scp"},
4646
DisableFlagsInUseLine: true,
47-
Short: "copy files and directories between local and remote instance",
47+
Short: "Copy files and directories between local and remote instance",
4848
Long: copyLong,
4949
Example: copyExample,
5050
Args: cmderrors.TransformToValidationError(cobra.ExactArgs(2)),

pkg/cmd/create/create.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func NewCmdCreate(t *terminal.Terminal, createStore CreateStore) *cobra.Command
4141
Annotations: map[string]string{"workspace": ""},
4242
Use: "create",
4343
DisableFlagsInUseLine: true,
44-
Short: "Create a new instance ",
44+
Short: "Create a new instance",
4545
Long: createLong,
4646
Example: createExample,
4747
RunE: func(cmd *cobra.Command, args []string) error {

pkg/cmd/delete/delete.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func NewCmdDelete(t *terminal.Terminal, loginDeleteStore DeleteStore, noLoginDel
3232
Annotations: map[string]string{"workspace": ""},
3333
Use: "delete",
3434
DisableFlagsInUseLine: true,
35-
Short: "Delete a Brev instance",
35+
Short: "Delete an instance",
3636
Long: stripmd.Strip(deleteLong),
3737
Example: deleteExample,
3838
ValidArgsFunction: completions.GetAllWorkspaceNameCompletionHandler(noLoginDeleteStore, t),

pkg/cmd/envvars/envvars.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type EnvVarsStore interface{}
1010

1111
func NewCmdEnvVars(_ *terminal.Terminal, evStore EnvVarsStore) *cobra.Command {
1212
cmd := &cobra.Command{
13-
Annotations: map[string]string{"housekeeping": ""},
13+
Annotations: map[string]string{"hidden": ""},
1414
Use: "env-vars",
1515
DisableFlagsInUseLine: true,
1616
Short: "configure env vars in supported shells",

pkg/cmd/fu/fu.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type FuStore interface {
3030

3131
func NewCmdFu(t *terminal.Terminal, loginFuStore FuStore, noLoginFuStore FuStore) *cobra.Command {
3232
cmd := &cobra.Command{
33-
Annotations: map[string]string{"workspace": ""},
33+
Annotations: map[string]string{"hidden": ""},
3434
Use: "fu",
3535
DisableFlagsInUseLine: true,
3636
Short: "Fetch all workspaces for a user and delete them",

pkg/cmd/healthcheck/healthcheck.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type HealthcheckStore interface {
1515

1616
func NewCmdHealthcheck(t *terminal.Terminal, store HealthcheckStore) *cobra.Command {
1717
cmd := &cobra.Command{
18-
Annotations: map[string]string{"housekeeping": ""},
18+
Annotations: map[string]string{"configuration": ""},
1919
Use: "healthcheck",
2020
Short: "Check backend to see if it's healthy",
2121
Long: "Check backend to see if it's healthy",

pkg/cmd/hello/hello.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type HelloStore interface {
2222

2323
func NewCmdHello(t *terminal.Terminal, store HelloStore) *cobra.Command {
2424
cmd := &cobra.Command{
25-
Annotations: map[string]string{"housekeeping": ""},
25+
Annotations: map[string]string{"configuration": ""},
2626
Use: "hello",
2727
DisableFlagsInUseLine: true,
2828
Long: "Get a quick onboarding of the Brev CLI",

0 commit comments

Comments
 (0)