# feat(cli): group root help by user journey

`2311c87`→[main](/content/gh/entireio/cli/commits/main/index.html)·

gtrrz-victor·3d ago·2 files·+119 added/-25 removed

Root help rendered 26 visible commands as one flat alphabetical list.
Add cobra Groups so help shows Entire Setup, Sessions & Checkpoints,
Account, and Control Plane sections; version/labs/agent-help stay in
Additional Commands on purpose. Pure help presentation — no command
paths, flags, or behavior change. agent-help ignores GroupID.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

## Sessions

01KXG9WXCXE55FFMK3564NA5R7View transcript

[?\
Organize CLI Commands into User Journey GroupsClaude Code·Fable 5·7 steps](/content/gh/entireio/cli/session/5d2c2b72-89da-4e39-b763-c4f08b98aea8#timeline-01KXG9WXCXE55FFMK3564NA5R7/index.html) [?\
Cobra CLI Command Grouping and GatingClaude Code·4 steps](/content/gh/entireio/cli/session/ad57b47f-bbe3-4801-879d-635952769b85#timeline-01KXG9WXCXE55FFMK3564NA5R7/index.html)

## Changes

2

- cmd/entire/cli

- Mroot.go+50/-25

- Mroot_test.go+69

```
30 unmodified lines

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
47 unmodified lines

101
102
103
104
105
106
107
108
109
110
111
112
88
89
90
91
92
93
94
95
96
97
98
99
100
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
105
106
107
108
109
130
131
132
133
134
135
136
112
113
137
138
139
115
116
117
118
119
140
141
142
143
144
145
146
147

30 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'
	cmd.AddCommand(newTokensGroupCmd())     // 'tokens'
	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)
	cmd.AddCommand(newImportCmd())          // 'import' (hidden; 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'
	cmd.AddCommand(newTokensGroupCmd())                             // 'tokens'
	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)
	cmd.AddCommand(newImportCmd())                                  // 'import' (hidden; 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.
	cmd.AddCommand(cliReview.NewCommand(buildReviewDeps()))        // `review`; hidden during maturation
	cmd.AddCommand(investigate.NewCommand(buildInvestigateDeps())) // hidden during maturation; runs a 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))
	cmd.AddCommand(newBlameCmd())
	cmd.AddCommand(newWhyCmd())
	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

```
255 unmodified lines

256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330

255 unmodified lines

}
}

func TestRoot_VisibleCommandsAreGrouped(t *testing.T) {
	t.Parallel()

// Commands intentionally left out of any group; cobra renders them
	// under "Additional Commands".
	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
		}
		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 {
