spf13/cobraApache-2.0adbc881Report / request removal

Flag Parsing & Persistent Flags

Cobra gives each command several views over its flags so command-local options, reusable parent options, and inherited options can coexist. These views are backed by pflag flag.FlagSet values and are combined before argument parsing.

This layering exists so a child command can accept its own options while also recognizing flags declared by ancestors, without forcing every command to redefine global behavior. The same merged view also supports help, usage, completion, and flag lookup.

Sources: command.go:1688-1698, command.go:1775-1784, command.go:1716-1740, command.go:1744-1766, command.go:1868-1889

Core concepts

Command-local flags

A command-local flag is an option stored in the command’s ordinary Flags() set; Flags() lazily creates that set with the command display name and a continue-on-error parser.

Sources: command.go:1688-1698

Persistent flags

A persistent flag is an option stored in PersistentFlags() and intended to remain available to descendant commands; that set is also created lazily and uses the command’s shared flag error buffer.

Sources: command.go:1775-1784

Inherited flags

An inherited flag is a parent persistent flag copied into a child’s InheritedFlags() view when it does not collide with a child-local flag.

Sources: command.go:1744-1766

Merged parsing set

The merged parsing set is the command’s Flags() set after Cobra adds the command’s persistent flags and accumulated parent persistent flags.

These views answer different questions:

ViewSource flagsMain purpose
Flags()The command’s ordinary flag setThe mutable set Cobra parses after merging.
PersistentFlags()Flags declared persistent on this commandFlags that descendants may inherit.
LocalFlags()The command’s flags plus its own persistent flags, excluding parent flagsDisplay and inspect options belonging to this command.
InheritedFlags()Persistent flags collected from ancestorsDisplay and inspect options inherited from parents.

LocalFlags() calls mergePersistentFlags() first, then adds ordinary and own persistent flags unless they are parent flags; InheritedFlags() separately adds parent flags only when they do not collide with local flags.

Sources: command.go:1898-1902, command.go:1716-1740, command.go:1744-1766

How flags are layered across a command tree

A command points to its parent through Parent(), and VisitParents() walks upward by invoking the callback for the immediate parent and then continuing recursively. The command tree is established when AddCommand assigns each child’s parent field.

The parent aggregate is maintained by updateParentsPflags(). It lazily creates parentsPflags, applies the global normalization function when configured, adds the root command’s PersistentFlags() together with flag.CommandLine, and then adds each visited parent’s PersistentFlags().

The resulting relationship is:

Flag ownership and inheritance — Where does a child command get the flags it can see?

Evidence

The important boundary is that inherited flags are not simply all parent flags appended blindly: InheritedFlags() checks both its own lookup and LocalFlags() before adding each parent flag, allowing a local flag to take precedence in the child’s view.

Sources: command.go:1892-1894, command.go:884-889, command.go:1342-1368, command.go:1907-1923, command.go:1744-1766

When merging happens before parsing

Cobra merges persistent flags immediately before parsing arguments. ParseFlags() first creates the error buffer if necessary, records its current length, calls mergePersistentFlags(), configures ParseErrorsAllowlist, and finally calls Flags().Parse(args).

mergePersistentFlags() refreshes the parent aggregate, then adds the command’s own PersistentFlags() and parentsPflags into Flags(). This ordering matters because parsing must see the complete flag namespace, including flags declared on ancestors, while still allowing the command’s own set to be the object that receives parsed values.

The execution path reaches this merge during normal command execution: ExecuteC() selects or traverses to a command and then calls execute(flags), while execute() initializes default flags and calls ParseFlags(a).

Merge before parse — What happens immediately before Cobra parses command arguments?

Evidence

The same merge is also required before Cobra creates the local and inherited display views, and before default help and version flags are installed. Therefore help output can distinguish local flags from inherited flags only after the flag layers have been assembled.

Sources: command.go:1868-1889, command.go:1898-1902, command.go:1084-1170, command.go:905-1045, command.go:1716-1740, command.go:1744-1766, command.go:1219-1232, command.go:1238-1258, command.go:1974-2040

How Cobra keeps pflag and command-line flags together

Cobra’s parsing APIs use pflag’s flag.FlagSet abstraction throughout the shown code, including NewFlagSet, AddFlagSet, VisitAll, and Parse. The parent-update path additionally adds flag.CommandLine to the root persistent set before walking parent commands.

This gives the visible fallback boundary: flags already registered in flag.CommandLine are incorporated into the aggregate that later feeds the command’s merged Flags() set. The excerpts do not show registration or conversion details beyond that AddFlagSet hand-off, so the safe interpretation is that Cobra includes that command-line flag set alongside its pflag-managed command sets.

Flag lookup follows the same layering. Flag(name) checks Flags() first and then calls persistentFlag(name); that helper checks the command’s persistent set and, if needed, refreshes and searches parentsPflags.

Sources: command.go:1688-1698, command.go:1868-1889, command.go:1907-1923, command.go:1898-1902, command.go:1844-1852, command.go:1855-1865

How it connects

Command construction supplies the parent links that make inheritance possible: AddCommand assigns parent, and Parent() exposes it. See Command Tree & Registration for the tree-building model.

Execution supplies the timing boundary: ExecuteC() finds the target command, then execute() initializes and parses its flags. See Command Execution Flow for the full execution sequence.

Help and usage consume the separated views: default usage prints LocalFlags() under “Flags” and InheritedFlags() under “Global Flags.” See Help, Usage & Templates for rendering behavior.

Completion and generated documentation also use non-inherited and inherited views separately. See Dynamic Completion Engine and Man Page & Markdown Doc Generation for those consumers.

Sources: command.go:1342-1368, command.go:1892-1894, command.go:1084-1170, command.go:905-1045, command.go:1974-2040, completions.go:462-474, doc/md_docs.go:32-47

Key takeaways

  • Flags() is the parsing set; PersistentFlags() holds flags intended for descendants.
  • InheritedFlags() is built from ancestor persistent flags and avoids names already present locally.
  • Cobra refreshes parent flags and merges them before calling Flags().Parse(args).
  • The parent aggregate also incorporates flag.CommandLine through AddFlagSet.
  • Help, completion, and documentation rely on separate local and inherited flag views.

Sources: command.go:1688-1698, command.go:1775-1784, command.go:1744-1766, command.go:1868-1889, command.go:1898-1902, command.go:1907-1923, command.go:1974-2040, completions.go:462-474, doc/md_docs.go:32-47

Want this for your repos?

Try Angada AI Wiki