Merge pull request #1745 from entireio/group-root-help-commands · Entire
Merge pull request #1745 from entireio/group-root-help-commands
62f8779→main·
pjbgf·2d ago·2 files·+126 added/-25 removed
cli: group root help output by user journey
Changes
2
cmd/entire/cli
Mroot.go+50/-25
Mroot_test.go+76
31 unmodified lines
TUI elements, which works better with screen readers.
// Help groups for the root command. AddGroup order is display order. // Visible commands without a GroupID render under "Additional Commands" // (version, labs, agent-help, help) — that placement is intentional. const ( groupSetup = "setup" groupSessions = "sessions" groupAccount = "account" groupControlPlane = "controlplane" )
// inGroup assigns a help group to a command at registration time so all // grouping stays visible in NewRootCmd rather than spread across constructors. func inGroup(c *cobra.Command, groupID string) *cobra.Command { c.GroupID = groupID return c }
func NewRootCmd() *cobra.Command { cmd := &cobra.Command{ Use: "entire", , }
// Help groups; AddGroup order is display order in entire --help.
cmd.AddGroup(
&cobra.Group{ID: groupSetup, Title: "Entire Setup:"},
&cobra.Group{ID: groupSessions, Title: "Sessions & Checkpoints:"},
&cobra.Group{ID: groupAccount, Title: "Account:"},
&cobra.Group{ID: groupControlPlane, Title: "Control Plane:"},
)
// Noun groups (canonical homes for subcommands). cmd.AddCommand(newSessionsCmd()) // 'session' (with 'sessions' as Cobra alias) cmd.AddCommand(newCheckpointGroupCmd()) // 'checkpoint' / 'cp' / 'checkpoints' experimental.Register(cmd, newTokensGroupCmd()) // 'tokens' (experimental) cmd.AddCommand(newAgentGroupCmd()) // 'agent' cmd.AddCommand(newAuthCmd()) // 'auth' cmd.AddCommand(newDoctorCmd()) // 'doctor' (group: trace/logs/bundle) cmd.AddCommand(newLabsCmd()) // 'labs' (experimental workflow discovery) cmd.AddCommand(newPluginGroupCmd()) // 'plugin' (managed install/list/remove) experimental.Register(cmd, newImportCmd()) // 'import' (experimental; import pre-existing agent history) cmd.AddCommand(newOrgCmd()) // 'org' — control-plane org management cmd.AddCommand(newProjectCmd()) // 'project' — control-plane project management cmd.AddCommand(newRepoCmd()) // 'repo' — control-plane repo lifecycle cmd.AddCommand(newGrantCmd()) // 'grant' — control-plane access grants cmd.AddCommand(inGroup(newSessionsCmd(), groupSessions)) // 'session' (with 'sessions' as Cobra alias) cmd.AddCommand(inGroup(newCheckpointGroupCmd(), groupSessions)) // 'checkpoint' / 'cp' / 'checkpoints' experimental.Register(cmd, newTokensGroupCmd()) // 'tokens' (experimental) cmd.AddCommand(inGroup(newAgentGroupCmd(), groupSetup)) // 'agent' cmd.AddCommand(inGroup(newAuthCmd(), groupAccount)) // 'auth' cmd.AddCommand(inGroup(newDoctorCmd(), groupSetup)) // 'doctor' (group: trace/logs/bundle) cmd.AddCommand(newLabsCmd()) // 'labs' (experimental workflow discovery) cmd.AddCommand(inGroup(newPluginGroupCmd(), groupSetup)) // 'plugin' (managed install/list/remove) experimental.Register(cmd, newImportCmd()) // 'import' (experimental; import pre-existing agent history) cmd.AddCommand(inGroup(newOrgCmd(), groupControlPlane)) // 'org' — control-plane org management cmd.AddCommand(inGroup(newProjectCmd(), groupControlPlane)) // 'project' — control-plane project management cmd.AddCommand(inGroup(newRepoCmd(), groupControlPlane)) // 'repo' — control-plane repo lifecycle cmd.AddCommand(inGroup(newGrantCmd(), groupControlPlane)) // 'grant' — control-plane access grants
// Top-level lifecycle and standalone commands.
experimental.Register(cmd, cliReview.NewCommand(buildReviewDeps())) // review (experimental)
experimental.Register(cmd, investigate.NewCommand(buildInvestigateDeps())) // investigate (experimental); multi-agent investigation
cmd.AddCommand(newCleanCmd())
cmd.AddCommand(newSetupCmd()) // 'configure' — non-agent settings; agent CRUD lives under 'agent'
cmd.AddCommand(newEnableCmd())
cmd.AddCommand(newDisableCmd())
cmd.AddCommand(newStatusCmd())
cmd.AddCommand(inGroup(newCleanCmd(), groupSetup))
cmd.AddCommand(inGroup(newSetupCmd(), groupSetup)) // 'configure' — non-agent settings; agent CRUD lives under 'agent'
cmd.AddCommand(inGroup(newEnableCmd(), groupSetup))
cmd.AddCommand(inGroup(newDisableCmd(), groupSetup))
cmd.AddCommand(inGroup(newStatusCmd(), groupSetup))
experimental.Register(cmd, newBlameCmd()) // 'blame' (experimental)
experimental.Register(cmd, newWhyCmd()) // 'why' (experimental)
cmd.AddCommand(newLoginCmd())
cmd.AddCommand(newLogoutCmd())
cmd.AddCommand(inGroup(newLoginCmd(), groupAccount))
cmd.AddCommand(inGroup(newLogoutCmd(), groupAccount))
cmd.AddCommand(newVersionCmd())
cmd.AddCommand(newDispatchCmd())
cmd.AddCommand(newActivityCmd())
cmd.AddCommand(newRecapCmd())
cmd.AddCommand(newAPICmd()) // authenticated passthrough to core/cell APIs
cmd.AddCommand(newAgentHelpCmd(cmd)) // visible: agents on transports without context injection discover it via entire help
cmd.AddCommand(inGroup(newDispatchCmd(), groupSessions))
cmd.AddCommand(inGroup(newActivityCmd(), groupSessions))
cmd.AddCommand(inGroup(newRecapCmd(), groupSessions))
cmd.AddCommand(inGroup(newAPICmd(), groupControlPlane)) // authenticated passthrough to core/cell APIs
cmd.AddCommand(newAgentHelpCmd(cmd)) // visible: agents on transports without context injection discover it via entire help
// Hidden top-level shortcuts. Functional but print a deprecation hint. cmd.AddCommand(hideAsAlias(newResumeCmd(), "entire session resume"))
Mcmd/entire/cli/root.go+50/-25
261 unmodified lines
...
func TestRoot_VisibleCommandsAreGrouped(t *testing.T) {
t.Parallel()
// Commands intentionally left out of any group. version, labs, agent-help,
// and help render under cobra's "Additional Commands"; completion is
// allowlisted for completeness but never renders (hidden via
// CompletionOptions.HiddenDefaultCmd in NewRootCmd).
ungrouped := map[string]bool{
"version": true,
"labs": true,
"agent-help": true,
"help": true,
"completion": true,
}
wantGroups := map[string]string{
"enable": groupSetup,
"disable": groupSetup,
"configure": groupSetup,
"agent": groupSetup,
"plugin": groupSetup,
"status": groupSetup,
"doctor": groupSetup,
"clean": groupSetup,
"session": groupSessions,
"checkpoint": groupSessions,
"recap": groupSessions,
"activity": groupSessions,
"dispatch": groupSessions,
"login": groupAccount,
"logout": groupAccount,
"auth": groupAccount,
"org": groupControlPlane,
"project": groupControlPlane,
"repo": groupControlPlane,
"grant": groupControlPlane,
"api": groupControlPlane,
}
root := NewRootCmd()
registered := make(map[string]bool)
for _, g := range root.Groups() {
registered[g.ID] = true
}
for _, c := range root.Commands() {
if c.Hidden || c.Deprecated != "" {
continue
}
// Experimental commands are grouped by experimental.Register (visible
// only in developer/nightly builds) — not part of this table.
if c.GroupID == experimental.GroupID {
continue
}
name := c.Name()
if ungrouped[name] {
if c.GroupID != "" {
t.Errorf(%q should stay ungrouped, got GroupID %q", name, c.GroupID)
}
continue
}
want, ok := wantGroups[name]
if !ok {
t.Errorf("visible command %q missing from group table; assign it a group or add it to the ungrouped allowlist", name)
continue
}
if c.GroupID != want {
t.Errorf(%q GroupID = %q, want %q", name, c.GroupID, want)
}
if !registered[want] {
t.Errorf("group %q used by %q is not registered on root (cobra panics at Execute)", want, name)
}
}
}
func containsString(values []string, want string) bool {
for _, value := range values {
if value == want {
return true
}
}
return false
}