package help import ( "fmt" "strings" "git.hangman-lab.top/zhi/HarborForge.Cli/internal/mode" ) type leafHelp struct { Summary string Usage []string Flags []string Notes []string } func RenderLeafHelp(group, cmd string) (string, bool) { spec, ok := leafHelpSpec(group, cmd) if !ok { return "", false } 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 { b.WriteString(" " + line + "\n") } if len(spec.Flags) > 0 { b.WriteString("\nFlags:\n") for _, line := range spec.Flags { b.WriteString(" " + line + "\n") } } if len(spec.Notes) > 0 { b.WriteString("\nNotes:\n") for _, line := range spec.Notes { b.WriteString(" - " + line + "\n") } } return b.String(), true } func authFlagHelp() []string { if mode.IsPaddedCell() { return []string{ "--json Output in JSON format", } } return []string{ "--token HarborForge API token (required in manual mode)", "--json Output in JSON format", } } func accountManagerFlagHelp() []string { flags := []string{ "--user Username to create", "--pass Initial password", "--email Email address (defaults to @harborforge.local)", "--full-name Full name", "--json Output in JSON format", } if mode.IsPaddedCell() { return flags } return append([]string{"--acc-mgr-token Account-manager token (required in manual mode)"}, flags...) } func leafHelpSpec(group, cmd string) (leafHelp, bool) { specs := map[string]leafHelp{ "config/show": { Summary: "View current CLI configuration", Usage: []string{"hf config"}, Flags: []string{"--json Output in JSON format"}, Notes: []string{ "Configuration is stored in .hf-config.json next to the hf binary.", }, }, "version": { Summary: "Show CLI version", Usage: []string{"hf version"}, Flags: []string{"--json Output in JSON format"}, }, "health": { Summary: "Check HarborForge API health", Usage: []string{"hf health", "hf health --json"}, Flags: authFlagHelp(), }, "config/url": { Summary: "Set HarborForge API base URL", Usage: []string{"hf config --url "}, Notes: []string{"Writes base-url into .hf-config.json next to the hf binary."}, }, "config/acc-mgr-token": { Summary: "Store the account-manager token via pass_mgr", Usage: []string{"hf config --acc-mgr-token "}, Notes: []string{"Only available in padded-cell mode with pass_mgr installed."}, }, "user/create": { Summary: "Create a user account", Usage: []string{"hf user create --user [--pass ] [--email ] [--full-name ]"}, Flags: accountManagerFlagHelp(), Notes: []string{ "This command uses the account-manager token flow, not the normal user token flow.", "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()}, "proposal/list": {Summary: "List proposals", Usage: []string{"hf proposal list --project <project-code> [--status <status>] [--order-by <created|name>] [--order-by <...>]"}, Flags: authFlagHelp()}, "proposal/get": {Summary: "Show a proposal by code", Usage: []string{"hf proposal get <proposal-code>"}, Flags: authFlagHelp()}, "proposal/create": {Summary: "Create a proposal", Usage: []string{"hf proposal create --project <project-code> --title <title> --desc <desc>"}, Flags: authFlagHelp()}, "proposal/update": {Summary: "Update a proposal", Usage: []string{"hf proposal update <proposal-code> [--title <title>] [--desc <desc>]"}, Flags: authFlagHelp()}, "proposal/accept": {Summary: "Accept a proposal and generate story tasks", Usage: []string{"hf proposal accept <proposal-code> --milestone <milestone-code>"}, Flags: authFlagHelp(), Notes: []string{"Accept generates story/* tasks from all essentials under the proposal."}}, "proposal/reject": {Summary: "Reject a proposal", Usage: []string{"hf proposal reject <proposal-code> [--reason <reason>]"}, Flags: authFlagHelp()}, "proposal/reopen": {Summary: "Reopen a proposal", Usage: []string{"hf proposal reopen <proposal-code>"}, Flags: authFlagHelp()}, "proposal/essential": {Summary: "Manage proposal essentials", Usage: []string{"hf proposal essential list --proposal <proposal-code>", "hf proposal essential create --proposal <proposal-code> --title <title> --type <feature|improvement|refactor> [--desc <desc>]", "hf proposal essential update <essential-code> --proposal <proposal-code> [--title <title>] [--type <type>] [--desc <desc>]", "hf proposal essential delete <essential-code> --proposal <proposal-code>"}, Flags: authFlagHelp()}, "proposal/essential/list": {Summary: "List essentials for a proposal", Usage: []string{"hf proposal essential list --proposal <proposal-code>"}, Flags: authFlagHelp()}, "proposal/essential/create": {Summary: "Create an essential", Usage: []string{"hf proposal essential create --proposal <proposal-code> --title <title> --type <feature|improvement|refactor> [--desc <desc>]"}, Flags: authFlagHelp()}, "proposal/essential/update": {Summary: "Update an essential", Usage: []string{"hf proposal essential update <essential-code> --proposal <proposal-code> [--title <title>] [--type <type>] [--desc <desc>]"}, Flags: authFlagHelp()}, "proposal/essential/delete": {Summary: "Delete an essential", Usage: []string{"hf proposal essential delete <essential-code> --proposal <proposal-code>"}, Flags: authFlagHelp()}, "comment/add": {Summary: "Add a comment to a task", Usage: []string{"hf comment add --task <task-code> --content <text>"}, Flags: authFlagHelp()}, "comment/list": {Summary: "List comments for a task", Usage: []string{"hf comment list --task <task-code>"}, Flags: authFlagHelp()}, "worklog/add": {Summary: "Add a work log entry", Usage: []string{"hf worklog add --task <task-code> --hours <n> [--desc <text>] [--date <yyyy-mm-dd>]"}, Flags: authFlagHelp()}, "worklog/list": {Summary: "List work logs by task or user", Usage: []string{"hf worklog list [--task <task-code>] [--user <username>]"}, 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 == "" { spec, ok := specs[cmd] return spec, ok } spec, ok := specs[group+"/"+cmd] return spec, ok }