From f00ffbcceb575112ce2ca278959bc4fb7c0849ca Mon Sep 17 00:00:00 2001 From: amtbsl <147152854+amtbsl@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:37:50 +0800 Subject: [PATCH 1/2] fix: show inherited persistent flags --- command.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/command.go b/command.go index d24cd87792..210e1d82d4 100644 --- a/command.go +++ b/command.go @@ -300,18 +300,21 @@ func (cmd *Command) appendFlag(fl Flag) { } } -// VisiblePersistentFlags returns a slice of [LocalFlag] with Persistent=true and Hidden=false. +// VisiblePersistentFlags returns inherited persistent flags with Hidden=false. func (cmd *Command) VisiblePersistentFlags() []Flag { if cmd.isCompletionCommand { return nil } var flags []Flag - for _, fl := range cmd.Root().Flags { - pfl, ok := fl.(LocalFlag) - if !ok || pfl.IsLocal() { - continue + lineage := cmd.Lineage() + for i := len(lineage) - 1; i > 0; i-- { + for _, fl := range lineage[i].allFlags() { + pfl, ok := fl.(LocalFlag) + if !ok || pfl.IsLocal() { + continue + } + flags = append(flags, fl) } - flags = append(flags, fl) } return visibleFlags(flags) } From 82d0696155e138f8509fa7371b58c69dc93d760b Mon Sep 17 00:00:00 2001 From: amtbsl <147152854+amtbsl@users.noreply.github.com> Date: Sat, 29 Aug 2026 13:38:03 +0800 Subject: [PATCH 2/2] test: cover inherited persistent flags --- help_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/help_test.go b/help_test.go index 49f70db0aa..c0e7712493 100644 --- a/help_test.go +++ b/help_test.go @@ -858,6 +858,52 @@ GLOBAL OPTIONS: assert.Contains(t, output.String(), expected, "expected output to include global options") } +func TestShowNestedSubcommandHelp_InheritedPersistentFlags(t *testing.T) { + cmd := &Command{ + Flags: []Flag{ + &StringFlag{ + Name: "root-persistent", + Local: false, + }, + }, + Commands: []*Command{ + { + Name: "mid", + Flags: []Flag{ + &StringFlag{ + Name: "mid-persistent", + Local: false, + }, + &StringFlag{ + Name: "mid-local", + Local: true, + }, + }, + Commands: []*Command{ + { + Name: "leaf", + Flags: []Flag{ + &StringFlag{Name: "leaf-local"}, + }, + }, + }, + }, + }, + } + + output := &bytes.Buffer{} + cmd.Writer = output + + _ = cmd.Run(buildTestContext(t), []string{"root", "mid", "leaf", "--help"}) + + assert.Contains(t, output.String(), "GLOBAL OPTIONS:", + "expected help to include a global options section") + assert.Contains(t, output.String(), "--root-persistent string", + "expected help to include the root persistent flag") + assert.Contains(t, output.String(), "--mid-persistent string", + "expected help to include the intermediate persistent flag") +} + func TestShowSubcommandHelp_GlobalOptions_HideHelpCommand(t *testing.T) { cmd := &Command{ Flags: []Flag{