refactor(cli): overhaul help output to match gh CLI style

- Add gh-style grouped help with CORE/RUNTIME/ADDITIONAL COMMANDS sections
- Use UPPERCASE section headers (USAGE, FLAGS, EXAMPLES, LEARN MORE)
- Format commands as "name:  description" with automatic alignment
- Add ENVIRONMENT VARIABLES and EXAMPLES sections to root help
- Apply consistent templates to root, subcommand, and leaf commands
- Update descriptions from "Manage X" to "Work with X" for gh parity

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Devv 2026-04-04 15:10:59 -07:00
parent 0771c15a59
commit 4afef09a03
12 changed files with 184 additions and 21 deletions

View file

@ -17,7 +17,7 @@ import (
var agentCmd = &cobra.Command{
Use: "agent",
Short: "Manage agents",
Short: "Work with agents",
}
var agentListCmd = &cobra.Command{

View file

@ -14,7 +14,7 @@ import (
var attachmentCmd = &cobra.Command{
Use: "attachment",
Short: "Manage attachments",
Short: "Work with attachments",
}
var attachmentDownloadCmd = &cobra.Command{

View file

@ -22,7 +22,7 @@ import (
var authCmd = &cobra.Command{
Use: "auth",
Short: "Manage authentication",
Short: "Authenticate multica with Multica",
}
var authLoginCmd = &cobra.Command{

View file

@ -11,7 +11,7 @@ import (
var configCmd = &cobra.Command{
Use: "config",
Short: "Show CLI configuration",
Short: "Manage configuration for multica",
RunE: runConfigShow,
}

View file

@ -23,7 +23,7 @@ import (
var daemonCmd = &cobra.Command{
Use: "daemon",
Short: "Manage the local agent runtime daemon",
Short: "Control the local agent runtime daemon",
}
var daemonStartCmd = &cobra.Command{

View file

@ -16,7 +16,7 @@ import (
var issueCmd = &cobra.Command{
Use: "issue",
Short: "Manage issues",
Short: "Work with issues",
}
var issueListCmd = &cobra.Command{
@ -63,7 +63,7 @@ var issueStatusCmd = &cobra.Command{
var issueCommentCmd = &cobra.Command{
Use: "comment",
Short: "Manage issue comments",
Short: "Work with issue comments",
}
var issueCommentListCmd = &cobra.Command{

View file

@ -14,7 +14,7 @@ import (
var repoCmd = &cobra.Command{
Use: "repo",
Short: "Manage repositories",
Short: "Work with repositories",
}
var repoCheckoutCmd = &cobra.Command{

View file

@ -13,7 +13,7 @@ import (
var runtimeCmd = &cobra.Command{
Use: "runtime",
Short: "Manage agent runtimes",
Short: "Work with agent runtimes",
}
var runtimeListCmd = &cobra.Command{

View file

@ -16,7 +16,7 @@ import (
var skillCmd = &cobra.Command{
Use: "skill",
Short: "Manage skills",
Short: "Work with skills",
}
var skillListCmd = &cobra.Command{
@ -62,7 +62,7 @@ var skillImportCmd = &cobra.Command{
var skillFilesCmd = &cobra.Command{
Use: "files",
Short: "Manage skill files",
Short: "Work with skill files",
}
var skillFilesListCmd = &cobra.Command{

View file

@ -15,7 +15,7 @@ import (
var workspaceCmd = &cobra.Command{
Use: "workspace",
Short: "Manage workspaces",
Short: "Work with workspaces",
}
var workspaceListCmd = &cobra.Command{

142
server/cmd/multica/help.go Normal file
View file

@ -0,0 +1,142 @@
package main
import (
"fmt"
"strings"
"text/template"
"github.com/spf13/cobra"
)
// Command group IDs used across the CLI.
const (
groupCore = "core"
groupRuntime = "runtime"
groupAdditional = "additional"
)
// initHelp configures the root command to use gh-style help output.
func initHelp(root *cobra.Command) {
root.SetHelpTemplate(rootHelpTemplate)
root.SetUsageTemplate(rootHelpTemplate)
root.CompletionOptions.HiddenDefaultCmd = true
root.AddGroup(
&cobra.Group{ID: groupCore, Title: "CORE COMMANDS"},
&cobra.Group{ID: groupRuntime, Title: "RUNTIME COMMANDS"},
&cobra.Group{ID: groupAdditional, Title: "ADDITIONAL COMMANDS"},
)
// Apply gh-style templates to all commands recursively.
applyTemplates(root)
}
func applyTemplates(cmd *cobra.Command) {
for _, c := range cmd.Commands() {
if c.HasSubCommands() {
c.SetHelpTemplate(subHelpTemplate)
c.SetUsageTemplate(subHelpTemplate)
} else {
c.SetHelpTemplate(leafHelpTemplate)
c.SetUsageTemplate(leafHelpTemplate)
}
applyTemplates(c)
}
}
// formatCommandList formats a list of commands in "name: description" style
// with automatic alignment, matching gh's output.
func formatCommandList(cmds []*cobra.Command) string {
if len(cmds) == 0 {
return ""
}
maxLen := 0
for _, c := range cmds {
if c.IsAvailableCommand() && len(c.Name()) > maxLen {
maxLen = len(c.Name())
}
}
var b strings.Builder
for _, c := range cmds {
if !c.IsAvailableCommand() {
continue
}
padding := strings.Repeat(" ", maxLen-len(c.Name()))
fmt.Fprintf(&b, " %s:%s %s\n", c.Name(), padding, c.Short)
}
return b.String()
}
// commandsInGroup returns commands that belong to a specific group.
func commandsInGroup(cmds []*cobra.Command, groupID string) []*cobra.Command {
var result []*cobra.Command
for _, c := range cmds {
if c.GroupID == groupID && c.IsAvailableCommand() {
result = append(result, c)
}
}
return result
}
func init() {
cobra.AddTemplateFuncs(template.FuncMap{
"formatCommandList": formatCommandList,
"commandsInGroup": commandsInGroup,
})
}
var rootHelpTemplate = `Work seamlessly with Multica from the command line.
USAGE
multica <command> <subcommand> [flags]
{{range .Groups}}
{{.Title}}
{{formatCommandList (commandsInGroup $.Commands .ID)}}
{{- end}}
FLAGS
{{.LocalFlags.FlagUsages}}
EXAMPLES
$ multica login
$ multica issue list --output json
$ multica daemon start
$ multica agent list --output json
ENVIRONMENT VARIABLES
MULTICA_SERVER_URL Override the default server URL
MULTICA_WORKSPACE_ID Set the active workspace
LEARN MORE
Use ` + "`multica <command> <subcommand> --help`" + ` for more information about a command.
`
var subHelpTemplate = `{{.Short}}
USAGE
{{.CommandPath}} <command> [flags]
COMMANDS
{{formatCommandList .Commands}}
INHERITED FLAGS
--help Show help for command
LEARN MORE
Use ` + "`{{.CommandPath}} <command> --help`" + ` for more information about a command.
`
var leafHelpTemplate = `{{if .Long}}{{.Long}}{{else}}{{.Short}}{{end}}
USAGE
{{.UseLine}}
{{- if .HasLocalFlags}}
FLAGS
{{.LocalFlags.FlagUsages}}
{{- end}}
INHERITED FLAGS
--help Show help for command
LEARN MORE
Use ` + "`multica <command> <subcommand> --help`" + ` for more information about a command.
`

View file

@ -15,7 +15,7 @@ var (
var rootCmd = &cobra.Command{
Use: "multica",
Short: "Multica CLI — local agent runtime and management tool",
Long: "multica manages local agent runtimes and provides control commands for the Multica platform.",
Long: "Work seamlessly with Multica from the command line.",
SilenceUsage: true,
SilenceErrors: true,
}
@ -25,19 +25,40 @@ func init() {
rootCmd.PersistentFlags().String("workspace-id", "", "Workspace ID (env: MULTICA_WORKSPACE_ID)")
rootCmd.PersistentFlags().String("profile", "", "Configuration profile name (e.g. dev) — isolates config, daemon state, and workspaces")
rootCmd.AddCommand(loginCmd)
rootCmd.AddCommand(authCmd)
rootCmd.AddCommand(daemonCmd)
// Core commands
issueCmd.GroupID = groupCore
agentCmd.GroupID = groupCore
workspaceCmd.GroupID = groupCore
repoCmd.GroupID = groupCore
skillCmd.GroupID = groupCore
// Runtime commands
daemonCmd.GroupID = groupRuntime
runtimeCmd.GroupID = groupRuntime
// Additional commands
authCmd.GroupID = groupAdditional
loginCmd.GroupID = groupAdditional
attachmentCmd.GroupID = groupAdditional
configCmd.GroupID = groupAdditional
updateCmd.GroupID = groupAdditional
versionCmd.GroupID = groupAdditional
rootCmd.AddCommand(issueCmd)
rootCmd.AddCommand(agentCmd)
rootCmd.AddCommand(workspaceCmd)
rootCmd.AddCommand(configCmd)
rootCmd.AddCommand(issueCmd)
rootCmd.AddCommand(attachmentCmd)
rootCmd.AddCommand(repoCmd)
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(updateCmd)
rootCmd.AddCommand(skillCmd)
rootCmd.AddCommand(daemonCmd)
rootCmd.AddCommand(runtimeCmd)
rootCmd.AddCommand(authCmd)
rootCmd.AddCommand(loginCmd)
rootCmd.AddCommand(attachmentCmd)
rootCmd.AddCommand(configCmd)
rootCmd.AddCommand(updateCmd)
rootCmd.AddCommand(versionCmd)
initHelp(rootCmd)
}
func main() {