Skip to content

cmd.Hidden is not recursive #2372

Description

@TLINDEN

My urfave/cli version is

v3@f980ca8

Checklist

  • Are you running the latest v3 release? The list of releases is here.
  • Did you check the manual for your release? The v3 manual is here
  • Did you perform a search about this problem? Here's the GitHub guide about searching.

Dependency Management

  • My project is using go modules.

Describe the bug

I am using the new Walk() feature by @dearchap to generate a tree of supported commands of my tool. This works great.

However, I want to exclude Hidden commands from the output. I can query the Hidden flag and do that, however, subcommands of a hidden command show up anyway.

To reproduce

func Tree(cmd *cli.Command) error {
	max := 20

	cmd.Walk(func(cmd *cli.Command) error {
		path := cmd.Path()
		command := path[len(path)-1]

		if len(path) == 1 || command == "help" || cmd.Hidden {
			return nil
		}

		indent := strings.Repeat("  ", len(path[1:])-1)
		space := strings.Repeat(" ", max-(len(command)+len(indent)))

		fmt.Printf("%s%s %s - %s\n", indent, command, space, cmd.Usage)

		return nil
	})

	return nil
}

Observed behavior

This prints this at the end:

[..]
version               - show esctl version information
debug                 - developer only
help-jsonpath         - show jsonpath help
  bash                - Output bash completion script
  zsh                 - Output zsh completion script
  fish                - Output fish completion script
  pwsh                - Output pwsh completion script

So, the command completion has been skipped, but its subcommands are not hidden and show up anyway.

Expected behavior

I'd like to have a way to check the parent of a cmd if it's hidden, eg:

if len(path) == 1 || command == "help" || cmd.Hidden || cmd.Parent.Hidden {
	return nil
}

Additional context

Complete code can be found here, to generate the tree, run: esctl --show-command-tree

Run go version and paste its output here

go version go1.25.8 linux/amd64

Run go env and paste its output here

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/scip/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/scip/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3184483892=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/home/scip/dev/esctl/go.mod'
GOMODCACHE='/home/scip/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/scip/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/scip/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.8.linux-amd64'
GOSUMDB='sum.golang.org'
GOTELEMETRY='off'
GOTELEMETRYDIR='/home/scip/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/scip/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.25.8.linux-amd64/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.25.8'
GOWORK=''
PKG_CONFIG='pkg-config'

And many thanks for the cool Walk() and Path() feature, I'm loving it!

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/v3relates to / is being considered for v3kind/bugdescribes or fixes a bugstatus/triagemaintainers still need to look into this

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions