From 1e8437d0b1b73b227f91cd93ea3d3a1ca4e50982 Mon Sep 17 00:00:00 2001 From: zhi Date: Sat, 21 Mar 2026 16:37:47 +0000 Subject: [PATCH] Improve nested CLI help coverage --- README.md | 1 + cmd/hf/main.go | 69 +++++++++++++++++++++-- internal/help/leaf.go | 127 ++++++++++++++++++++++-------------------- 3 files changed, 132 insertions(+), 65 deletions(-) diff --git a/README.md b/README.md index 868b346..befc87a 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ internal/ - Top-level and group/leaf help rendering (`--help` / `--help-brief`) - Permission-aware command visibility via `/auth/me/permissions` - Detailed leaf help text for all commands, with padded-cell/manual auth flag differences +- Nested help coverage for `config`, `monitor server`, and `monitor api-key` subtrees - `(not permitted)` rendering for unauthorized commands **Core commands:** diff --git a/cmd/hf/main.go b/cmd/hf/main.go index 09b3b43..cb0b04a 100644 --- a/cmd/hf/main.go +++ b/cmd/hf/main.go @@ -73,7 +73,7 @@ func handleLeafOrRun(name string, args []string, run func()) { } func handleConfig(args []string) { - if isHelpFlagOnly(args) { + if isLeafHelpFlagOnly(args) || isHelpFlagOnly(args) { if text, ok := help.RenderLeafHelp("config", "show"); ok { fmt.Print(text) return @@ -131,6 +131,17 @@ func handleGroup(group help.Group, args []string) { output.Errorf("unknown %s subcommand: %s", group.Name, args[0]) } + if group.Name == "monitor" && (sub.Name == "server" || sub.Name == "api-key") { + if len(args) == 1 { + handleMonitorCommand(sub.Name, nil) + return + } + if isHelpLikePath(args[1:]) || sub.Permitted { + handleMonitorCommand(sub.Name, args[1:]) + return + } + } + if len(args) > 1 && isLeafHelpFlagOnly(args[1:]) { if !sub.Permitted { fmt.Println(help.RenderNotPermitted(group.Name, sub.Name)) @@ -282,6 +293,16 @@ func isLeafHelpFlagOnly(args []string) bool { return len(args) == 1 && (args[0] == "--help" || args[0] == "-h" || args[0] == "--help-brief") } +func isHelpLikePath(args []string) bool { + if len(args) == 0 { + return true + } + if len(args) == 1 { + return args[0] == "--help" || args[0] == "-h" || args[0] == "--help-brief" + } + return isLeafHelpFlagOnly(args[len(args)-1:]) +} + func findGroup(name string) (help.Group, bool) { for _, group := range help.CommandSurface() { if group.Name == name { @@ -742,12 +763,32 @@ func handleMonitorCommand(subCmd string, args []string) { } func handleMonitorServerCommand(args []string, tokenFlag string) { - if len(args) == 0 { - output.Error("usage: hf monitor server ...") + serverCommands := []help.Command{ + {Name: "list", Description: "List monitor servers", Permitted: true}, + {Name: "get", Description: "Show a monitor server by identifier", Permitted: true}, + {Name: "create", Description: "Create a monitor server", Permitted: true}, + {Name: "delete", Description: "Delete a monitor server", Permitted: true}, + } + + if len(args) == 0 || isHelpFlagOnly(args) { + fmt.Print(help.RenderGroupHelp("monitor server", serverCommands)) + return + } + if len(args) == 1 && args[0] == "--help-brief" { + fmt.Print(help.RenderGroupHelpBrief("monitor server", serverCommands)) + return } subCmd := args[0] remaining := args[1:] + if isLeafHelpFlagOnly(remaining) { + if text, ok := help.RenderLeafHelp("monitor/server", subCmd); ok { + fmt.Print(text) + return + } + fmt.Printf("hf monitor server %s\n", subCmd) + return + } switch subCmd { case "list": @@ -770,12 +811,30 @@ func handleMonitorServerCommand(args []string, tokenFlag string) { } func handleMonitorAPIKeyCommand(args []string, tokenFlag string) { - if len(args) == 0 { - output.Error("usage: hf monitor api-key ") + apiKeyCommands := []help.Command{ + {Name: "generate", Description: "Generate a monitor API key", Permitted: true}, + {Name: "revoke", Description: "Revoke a monitor API key", Permitted: true}, + } + + if len(args) == 0 || isHelpFlagOnly(args) { + fmt.Print(help.RenderGroupHelp("monitor api-key", apiKeyCommands)) + return + } + if len(args) == 1 && args[0] == "--help-brief" { + fmt.Print(help.RenderGroupHelpBrief("monitor api-key", apiKeyCommands)) + return } subCmd := args[0] remaining := args[1:] + if isLeafHelpFlagOnly(remaining) { + if text, ok := help.RenderLeafHelp("monitor/api-key", subCmd); ok { + fmt.Print(text) + return + } + fmt.Printf("hf monitor api-key %s\n", subCmd) + return + } switch subCmd { case "generate": diff --git a/internal/help/leaf.go b/internal/help/leaf.go index 6610f78..6a26baf 100644 --- a/internal/help/leaf.go +++ b/internal/help/leaf.go @@ -22,6 +22,7 @@ func RenderLeafHelp(group, cmd string) (string, bool) { var b strings.Builder name := strings.TrimSpace(strings.TrimSpace(group + " " + cmd)) + name = strings.ReplaceAll(name, "/", " ") b.WriteString(fmt.Sprintf("hf %s - %s\n", name, spec.Summary)) b.WriteString("\nUsage:\n") for _, line := range spec.Usage { @@ -107,66 +108,72 @@ func leafHelpSpec(group, cmd string) (leafHelp, bool) { "In padded-cell mode, --acc-mgr-token is hidden and password generation can fall back to pass_mgr.", }, }, - "user/list": {Summary: "List users", Usage: []string{"hf user list"}, Flags: authFlagHelp()}, - "user/get": {Summary: "Show a user by username", Usage: []string{"hf user get "}, Flags: authFlagHelp()}, - "user/update": {Summary: "Update a user", Usage: []string{"hf user update [--email ] [--full-name ] [--pass ] [--active ]"}, Flags: authFlagHelp()}, - "user/activate": {Summary: "Activate a user", Usage: []string{"hf user activate "}, Flags: authFlagHelp()}, - "user/deactivate": {Summary: "Deactivate a user", Usage: []string{"hf user deactivate "}, Flags: authFlagHelp()}, - "user/delete": {Summary: "Delete a user", Usage: []string{"hf user delete "}, Flags: authFlagHelp()}, - "role/list": {Summary: "List roles", Usage: []string{"hf role list"}, Flags: authFlagHelp()}, - "role/get": {Summary: "Show a role by name", Usage: []string{"hf role get "}, Flags: authFlagHelp()}, - "role/create": {Summary: "Create a role", Usage: []string{"hf role create --name [--desc ] [--global ]"}, Flags: authFlagHelp()}, - "role/update": {Summary: "Update a role", Usage: []string{"hf role update [--desc ]"}, Flags: authFlagHelp()}, - "role/delete": {Summary: "Delete a role", Usage: []string{"hf role delete "}, Flags: authFlagHelp()}, - "role/set-permissions": {Summary: "Replace role permissions", Usage: []string{"hf role set-permissions --permission [--permission ...]"}, Flags: authFlagHelp()}, - "role/add-permissions": {Summary: "Add permissions to a role", Usage: []string{"hf role add-permissions --permission [--permission ...]"}, Flags: authFlagHelp()}, - "role/remove-permissions": {Summary: "Remove permissions from a role", Usage: []string{"hf role remove-permissions --permission [--permission ...]"}, Flags: authFlagHelp()}, - "permission/list": {Summary: "List permissions", Usage: []string{"hf permission list"}, Flags: authFlagHelp()}, - "project/list": {Summary: "List projects", Usage: []string{"hf project list [--owner ] [--order-by ] [--order-by <...>]"}, Flags: authFlagHelp()}, - "project/get": {Summary: "Show a project by code", Usage: []string{"hf project get "}, Flags: authFlagHelp()}, - "project/create": {Summary: "Create a project", Usage: []string{"hf project create --name [--desc ] [--repo ]"}, Flags: authFlagHelp()}, - "project/update": {Summary: "Update a project", Usage: []string{"hf project update [--name ] [--desc ] [--repo ]"}, Flags: authFlagHelp()}, - "project/delete": {Summary: "Delete a project", Usage: []string{"hf project delete "}, Flags: authFlagHelp()}, - "project/members": {Summary: "List project members", Usage: []string{"hf project members "}, Flags: authFlagHelp()}, - "project/add-member": {Summary: "Add a member to a project", Usage: []string{"hf project add-member --user --role "}, Flags: authFlagHelp()}, - "project/remove-member": {Summary: "Remove a member from a project", Usage: []string{"hf project remove-member --user "}, Flags: authFlagHelp()}, - "milestone/list": {Summary: "List milestones", Usage: []string{"hf milestone list --project [--status ] [--order-by ] [--order-by <...>]"}, Flags: authFlagHelp()}, - "milestone/get": {Summary: "Show a milestone by code", Usage: []string{"hf milestone get "}, Flags: authFlagHelp()}, - "milestone/create": {Summary: "Create a milestone", Usage: []string{"hf milestone create --project --title [--desc <desc>] [--due <date>]"}, Flags: authFlagHelp()}, - "milestone/update": {Summary: "Update a milestone", Usage: []string{"hf milestone update <milestone-code> [--title <title>] [--desc <desc>] [--status <status>] [--due <date>]"}, Flags: authFlagHelp()}, - "milestone/delete": {Summary: "Delete a milestone", Usage: []string{"hf milestone delete <milestone-code>"}, Flags: authFlagHelp()}, - "milestone/progress": {Summary: "Show milestone progress", Usage: []string{"hf milestone progress <milestone-code>"}, Flags: authFlagHelp()}, - "task/list": {Summary: "List tasks", Usage: []string{"hf task list [--project <project-code>] [--milestone <milestone-code>] [--status <status>] [--taken-by <me|null|username>] [--due-today <true|false>] [--order-by <due-date|priority|created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, - "task/get": {Summary: "Show a task by code", Usage: []string{"hf task get <task-code>"}, Flags: authFlagHelp()}, - "task/create": {Summary: "Create a task", Usage: []string{"hf task create --project <project-code> --title <title> [--milestone <milestone-code>] [--type <type>] [--priority <priority>] [--desc <desc>]"}, Flags: authFlagHelp()}, - "task/update": {Summary: "Update a task", Usage: []string{"hf task update <task-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>] [--assignee <username|null>]"}, Flags: authFlagHelp()}, - "task/transition": {Summary: "Transition a task to a new status", Usage: []string{"hf task transition <task-code> <status>"}, Flags: authFlagHelp()}, - "task/take": {Summary: "Assign a task to the current user", Usage: []string{"hf task take <task-code>"}, Flags: authFlagHelp()}, - "task/delete": {Summary: "Delete a task", Usage: []string{"hf task delete <task-code>"}, Flags: authFlagHelp()}, - "task/search": {Summary: "Search tasks", Usage: []string{"hf task search --query <text> [--project <project-code>] [--status <status>]"}, Flags: authFlagHelp()}, - "meeting/list": {Summary: "List meetings", Usage: []string{"hf meeting list [--project <project-code>] [--status <status>] [--order-by <created|due-date|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, - "meeting/get": {Summary: "Show a meeting by code", Usage: []string{"hf meeting get <meeting-code>"}, Flags: authFlagHelp()}, - "meeting/create": {Summary: "Create a meeting", Usage: []string{"hf meeting create --project <project-code> --title <title> [--milestone <milestone-code>] [--desc <desc>] [--time <datetime>]"}, Flags: authFlagHelp()}, - "meeting/update": {Summary: "Update a meeting", Usage: []string{"hf meeting update <meeting-code> [--title <title>] [--desc <desc>] [--status <status>] [--time <datetime>]"}, Flags: authFlagHelp()}, - "meeting/attend": {Summary: "Attend a meeting", Usage: []string{"hf meeting attend <meeting-code>"}, Flags: authFlagHelp()}, - "meeting/delete": {Summary: "Delete a meeting", Usage: []string{"hf meeting delete <meeting-code>"}, Flags: authFlagHelp()}, - "support/list": {Summary: "List support tickets", Usage: []string{"hf support list [--taken-by <me|null|username>] [--status <status>] [--order-by <due-date|priority|created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, - "support/get": {Summary: "Show a support ticket by code", Usage: []string{"hf support get <support-code>"}, Flags: authFlagHelp()}, - "support/create": {Summary: "Create a support ticket", Usage: []string{"hf support create --title <title> [--project <project-code>] [--desc <desc>] [--priority <priority>]"}, Flags: authFlagHelp()}, - "support/update": {Summary: "Update a support ticket", Usage: []string{"hf support update <support-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>]"}, Flags: authFlagHelp()}, - "support/take": {Summary: "Assign a support ticket to the current user", Usage: []string{"hf support take <support-code>"}, Flags: authFlagHelp()}, - "support/transition": {Summary: "Transition a support ticket to a new status", Usage: []string{"hf support transition <support-code> <status>"}, Flags: authFlagHelp()}, - "support/delete": {Summary: "Delete a support ticket", Usage: []string{"hf support delete <support-code>"}, Flags: authFlagHelp()}, - "propose/list": {Summary: "List proposals", Usage: []string{"hf propose list --project <project-code> [--status <status>] [--order-by <created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, - "propose/get": {Summary: "Show a proposal by code", Usage: []string{"hf propose get <propose-code>"}, Flags: authFlagHelp()}, - "propose/create": {Summary: "Create a proposal", Usage: []string{"hf propose create --project <project-code> --title <title> --desc <desc>"}, Flags: authFlagHelp()}, - "propose/update": {Summary: "Update a proposal", Usage: []string{"hf propose update <propose-code> [--title <title>] [--desc <desc>]"}, Flags: authFlagHelp()}, - "propose/accept": {Summary: "Accept a proposal", Usage: []string{"hf propose accept <propose-code> --milestone <milestone-code>"}, Flags: authFlagHelp()}, - "propose/reject": {Summary: "Reject a proposal", Usage: []string{"hf propose reject <propose-code> [--reason <reason>]"}, Flags: authFlagHelp()}, - "propose/reopen": {Summary: "Reopen a proposal", Usage: []string{"hf propose reopen <propose-code>"}, Flags: authFlagHelp()}, - "monitor/overview": {Summary: "Show monitor overview", Usage: []string{"hf monitor overview"}, Flags: authFlagHelp()}, - "monitor/server": {Summary: "Manage monitor servers", Usage: []string{"hf monitor server list", "hf monitor server get <identifier>", "hf monitor server create --identifier <identifier> [--name <display-name>]", "hf monitor server delete <identifier>"}, Flags: authFlagHelp()}, - "monitor/api-key": {Summary: "Manage monitor API keys", Usage: []string{"hf monitor api-key generate <identifier>", "hf monitor api-key revoke <identifier>"}, Flags: authFlagHelp()}, + "user/list": {Summary: "List users", Usage: []string{"hf user list"}, Flags: authFlagHelp()}, + "user/get": {Summary: "Show a user by username", Usage: []string{"hf user get <username>"}, Flags: authFlagHelp()}, + "user/update": {Summary: "Update a user", Usage: []string{"hf user update <username> [--email <email>] [--full-name <name>] [--pass <password>] [--active <true|false>]"}, Flags: authFlagHelp()}, + "user/activate": {Summary: "Activate a user", Usage: []string{"hf user activate <username>"}, Flags: authFlagHelp()}, + "user/deactivate": {Summary: "Deactivate a user", Usage: []string{"hf user deactivate <username>"}, Flags: authFlagHelp()}, + "user/delete": {Summary: "Delete a user", Usage: []string{"hf user delete <username>"}, Flags: authFlagHelp()}, + "role/list": {Summary: "List roles", Usage: []string{"hf role list"}, Flags: authFlagHelp()}, + "role/get": {Summary: "Show a role by name", Usage: []string{"hf role get <role-name>"}, Flags: authFlagHelp()}, + "role/create": {Summary: "Create a role", Usage: []string{"hf role create --name <role-name> [--desc <desc>] [--global <true|false>]"}, Flags: authFlagHelp()}, + "role/update": {Summary: "Update a role", Usage: []string{"hf role update <role-name> [--desc <desc>]"}, Flags: authFlagHelp()}, + "role/delete": {Summary: "Delete a role", Usage: []string{"hf role delete <role-name>"}, Flags: authFlagHelp()}, + "role/set-permissions": {Summary: "Replace role permissions", Usage: []string{"hf role set-permissions <role-name> --permission <perm> [--permission <perm> ...]"}, Flags: authFlagHelp()}, + "role/add-permissions": {Summary: "Add permissions to a role", Usage: []string{"hf role add-permissions <role-name> --permission <perm> [--permission <perm> ...]"}, Flags: authFlagHelp()}, + "role/remove-permissions": {Summary: "Remove permissions from a role", Usage: []string{"hf role remove-permissions <role-name> --permission <perm> [--permission <perm> ...]"}, Flags: authFlagHelp()}, + "permission/list": {Summary: "List permissions", Usage: []string{"hf permission list"}, Flags: authFlagHelp()}, + "project/list": {Summary: "List projects", Usage: []string{"hf project list [--owner <username>] [--order-by <created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, + "project/get": {Summary: "Show a project by code", Usage: []string{"hf project get <project-code>"}, Flags: authFlagHelp()}, + "project/create": {Summary: "Create a project", Usage: []string{"hf project create --name <name> [--desc <desc>] [--repo <repo>]"}, Flags: authFlagHelp()}, + "project/update": {Summary: "Update a project", Usage: []string{"hf project update <project-code> [--name <name>] [--desc <desc>] [--repo <repo>]"}, Flags: authFlagHelp()}, + "project/delete": {Summary: "Delete a project", Usage: []string{"hf project delete <project-code>"}, Flags: authFlagHelp()}, + "project/members": {Summary: "List project members", Usage: []string{"hf project members <project-code>"}, Flags: authFlagHelp()}, + "project/add-member": {Summary: "Add a member to a project", Usage: []string{"hf project add-member <project-code> --user <username> --role <role-name>"}, Flags: authFlagHelp()}, + "project/remove-member": {Summary: "Remove a member from a project", Usage: []string{"hf project remove-member <project-code> --user <username>"}, Flags: authFlagHelp()}, + "milestone/list": {Summary: "List milestones", Usage: []string{"hf milestone list --project <project-code> [--status <status>] [--order-by <due-date|created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, + "milestone/get": {Summary: "Show a milestone by code", Usage: []string{"hf milestone get <milestone-code>"}, Flags: authFlagHelp()}, + "milestone/create": {Summary: "Create a milestone", Usage: []string{"hf milestone create --project <project-code> --title <title> [--desc <desc>] [--due <date>]"}, Flags: authFlagHelp()}, + "milestone/update": {Summary: "Update a milestone", Usage: []string{"hf milestone update <milestone-code> [--title <title>] [--desc <desc>] [--status <status>] [--due <date>]"}, Flags: authFlagHelp()}, + "milestone/delete": {Summary: "Delete a milestone", Usage: []string{"hf milestone delete <milestone-code>"}, Flags: authFlagHelp()}, + "milestone/progress": {Summary: "Show milestone progress", Usage: []string{"hf milestone progress <milestone-code>"}, Flags: authFlagHelp()}, + "task/list": {Summary: "List tasks", Usage: []string{"hf task list [--project <project-code>] [--milestone <milestone-code>] [--status <status>] [--taken-by <me|null|username>] [--due-today <true|false>] [--order-by <due-date|priority|created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, + "task/get": {Summary: "Show a task by code", Usage: []string{"hf task get <task-code>"}, Flags: authFlagHelp()}, + "task/create": {Summary: "Create a task", Usage: []string{"hf task create --project <project-code> --title <title> [--milestone <milestone-code>] [--type <type>] [--priority <priority>] [--desc <desc>]"}, Flags: authFlagHelp()}, + "task/update": {Summary: "Update a task", Usage: []string{"hf task update <task-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>] [--assignee <username|null>]"}, Flags: authFlagHelp()}, + "task/transition": {Summary: "Transition a task to a new status", Usage: []string{"hf task transition <task-code> <status>"}, Flags: authFlagHelp()}, + "task/take": {Summary: "Assign a task to the current user", Usage: []string{"hf task take <task-code>"}, Flags: authFlagHelp()}, + "task/delete": {Summary: "Delete a task", Usage: []string{"hf task delete <task-code>"}, Flags: authFlagHelp()}, + "task/search": {Summary: "Search tasks", Usage: []string{"hf task search --query <text> [--project <project-code>] [--status <status>]"}, Flags: authFlagHelp()}, + "meeting/list": {Summary: "List meetings", Usage: []string{"hf meeting list [--project <project-code>] [--status <status>] [--order-by <created|due-date|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, + "meeting/get": {Summary: "Show a meeting by code", Usage: []string{"hf meeting get <meeting-code>"}, Flags: authFlagHelp()}, + "meeting/create": {Summary: "Create a meeting", Usage: []string{"hf meeting create --project <project-code> --title <title> [--milestone <milestone-code>] [--desc <desc>] [--time <datetime>]"}, Flags: authFlagHelp()}, + "meeting/update": {Summary: "Update a meeting", Usage: []string{"hf meeting update <meeting-code> [--title <title>] [--desc <desc>] [--status <status>] [--time <datetime>]"}, Flags: authFlagHelp()}, + "meeting/attend": {Summary: "Attend a meeting", Usage: []string{"hf meeting attend <meeting-code>"}, Flags: authFlagHelp()}, + "meeting/delete": {Summary: "Delete a meeting", Usage: []string{"hf meeting delete <meeting-code>"}, Flags: authFlagHelp()}, + "support/list": {Summary: "List support tickets", Usage: []string{"hf support list [--taken-by <me|null|username>] [--status <status>] [--order-by <due-date|priority|created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, + "support/get": {Summary: "Show a support ticket by code", Usage: []string{"hf support get <support-code>"}, Flags: authFlagHelp()}, + "support/create": {Summary: "Create a support ticket", Usage: []string{"hf support create --title <title> [--project <project-code>] [--desc <desc>] [--priority <priority>]"}, Flags: authFlagHelp()}, + "support/update": {Summary: "Update a support ticket", Usage: []string{"hf support update <support-code> [--title <title>] [--desc <desc>] [--status <status>] [--priority <priority>]"}, Flags: authFlagHelp()}, + "support/take": {Summary: "Assign a support ticket to the current user", Usage: []string{"hf support take <support-code>"}, Flags: authFlagHelp()}, + "support/transition": {Summary: "Transition a support ticket to a new status", Usage: []string{"hf support transition <support-code> <status>"}, Flags: authFlagHelp()}, + "support/delete": {Summary: "Delete a support ticket", Usage: []string{"hf support delete <support-code>"}, Flags: authFlagHelp()}, + "propose/list": {Summary: "List proposals", Usage: []string{"hf propose list --project <project-code> [--status <status>] [--order-by <created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, + "propose/get": {Summary: "Show a proposal by code", Usage: []string{"hf propose get <propose-code>"}, Flags: authFlagHelp()}, + "propose/create": {Summary: "Create a proposal", Usage: []string{"hf propose create --project <project-code> --title <title> --desc <desc>"}, Flags: authFlagHelp()}, + "propose/update": {Summary: "Update a proposal", Usage: []string{"hf propose update <propose-code> [--title <title>] [--desc <desc>]"}, Flags: authFlagHelp()}, + "propose/accept": {Summary: "Accept a proposal", Usage: []string{"hf propose accept <propose-code> --milestone <milestone-code>"}, Flags: authFlagHelp()}, + "propose/reject": {Summary: "Reject a proposal", Usage: []string{"hf propose reject <propose-code> [--reason <reason>]"}, Flags: authFlagHelp()}, + "propose/reopen": {Summary: "Reopen a proposal", Usage: []string{"hf propose reopen <propose-code>"}, Flags: authFlagHelp()}, + "monitor/overview": {Summary: "Show monitor overview", Usage: []string{"hf monitor overview"}, Flags: authFlagHelp()}, + "monitor/server": {Summary: "Manage monitor servers", Usage: []string{"hf monitor server list", "hf monitor server get <identifier>", "hf monitor server create --identifier <identifier> [--name <display-name>]", "hf monitor server delete <identifier>"}, Flags: authFlagHelp()}, + "monitor/server/list": {Summary: "List monitor servers", Usage: []string{"hf monitor server list"}, Flags: authFlagHelp()}, + "monitor/server/get": {Summary: "Show a monitor server by identifier", Usage: []string{"hf monitor server get <identifier>"}, Flags: authFlagHelp()}, + "monitor/server/create": {Summary: "Create a monitor server", Usage: []string{"hf monitor server create --identifier <identifier> [--name <display-name>]"}, Flags: authFlagHelp()}, + "monitor/server/delete": {Summary: "Delete a monitor server", Usage: []string{"hf monitor server delete <identifier>"}, Flags: authFlagHelp()}, + "monitor/api-key": {Summary: "Manage monitor API keys", Usage: []string{"hf monitor api-key generate <identifier>", "hf monitor api-key revoke <identifier>"}, Flags: authFlagHelp()}, + "monitor/api-key/generate": {Summary: "Generate a monitor API key", Usage: []string{"hf monitor api-key generate <identifier>"}, Flags: authFlagHelp()}, + "monitor/api-key/revoke": {Summary: "Revoke a monitor API key", Usage: []string{"hf monitor api-key revoke <identifier>"}, Flags: authFlagHelp()}, } if group == "" {