Repository: spf13/cobra
Pull request #1779 (2022-08-18 19:28:16)

Document option to hide the default completion cmd
When adding the option to hide the default `completion` command in #1541, I forgot to document it!

This PR simply adds that option to the documentation.


Patch:
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index a63518f..8f8c739 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -39,8 +39,8 @@ jobs:
         days-before-close: 30
         stale-issue-label: 'lifecycle/stale'
         stale-pr-label: 'lifecycle/stale'
-        exempt-issue-label: 'lifecycle/frozen'
-        exempt-pr-label: 'lifecycle/frozen'
+        exempt-issue-labels: 'lifecycle/frozen'
+        exempt-pr-labels: 'lifecycle/frozen'
         close-issue-label: 'lifecycle/rotten'
         close-pr-label: 'lifecycle/rotten'
 
diff --git a/.golangci.yml b/.golangci.yml
index 0d6e617..439d3e1 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,3 +1,17 @@
+# Copyright 2013-2022 The Cobra Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 run:
   deadline: 5m
 
diff --git a/Makefile b/Makefile
index 443ef1a..c433a01 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@ $(warning "could not find golangci-lint in $(PATH), run: curl -sfL https://insta
 endif
 
 ifeq (, $(shell which richgo))
-$(warning "could not find richgo in $(PATH), run: go get github.com/kyoh86/richgo")
+$(warning "could not find richgo in $(PATH), run: go install github.com/kyoh86/richgo@latest")
 endif
 
 .PHONY: fmt lint test install_deps clean
diff --git a/README.md b/README.md
index a672c23..08e4fa5 100644
--- a/README.md
+++ b/README.md
@@ -40,9 +40,9 @@ The best applications read like sentences when used, and as a result, users
 intuitively know how to interact with them.
 
 The pattern to follow is
-`APPNAME VERB NOUN --ADJECTIVE.`
+`APPNAME VERB NOUN --ADJECTIVE`
     or
-`APPNAME COMMAND ARG --FLAG`
+`APPNAME COMMAND ARG --FLAG`.
 
 A few good real world examples may better illustrate this point.
 
diff --git a/active_help.go b/active_help.go
index 0c63191..95e03ae 100644
--- a/active_help.go
+++ b/active_help.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/args.go b/args.go
index 20a022b..2c1f99e 100644
--- a/args.go
+++ b/args.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
@@ -32,7 +46,8 @@ func NoArgs(cmd *Command, args []string) error {
 	return nil
 }
 
-// OnlyValidArgs returns an error if any args are not in the list of ValidArgs.
+// OnlyValidArgs returns an error if there are any positional args that are not in
+// the `ValidArgs` field of `Command`
 func OnlyValidArgs(cmd *Command, args []string) error {
 	if len(cmd.ValidArgs) > 0 {
 		// Remove any description that may be included in ValidArgs.
@@ -41,7 +56,6 @@ func OnlyValidArgs(cmd *Command, args []string) error {
 		for _, v := range cmd.ValidArgs {
 			validArgs = append(validArgs, strings.Split(v, "\t")[0])
 		}
-
 		for _, v := range args {
 			if !stringInSlice(v, validArgs) {
 				return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0]))
@@ -86,18 +100,6 @@ func ExactArgs(n int) PositionalArgs {
 	}
 }
 
-// ExactValidArgs returns an error if
-// there are not exactly N positional args OR
-// there are any positional args that are not in the `ValidArgs` field of `Command`
-func ExactValidArgs(n int) PositionalArgs {
-	return func(cmd *Command, args []string) error {
-		if err := ExactArgs(n)(cmd, args); err != nil {
-			return err
-		}
-		return OnlyValidArgs(cmd, args)
-	}
-}
-
 // RangeArgs returns an error if the number of args is not within the expected range.
 func RangeArgs(min int, max int) PositionalArgs {
 	return func(cmd *Command, args []string) error {
@@ -119,3 +121,11 @@ func MatchAll(pargs ...PositionalArgs) PositionalArgs {
 		return nil
 	}
 }
+
+// ExactValidArgs returns an error if there are not exactly N positional args OR
+// there are any positional args that are not in the `ValidArgs` field of `Command`
+//
+// Deprecated: use MatchAll(ExactArgs(n), OnlyValidArgs) instead
+func ExactValidArgs(n int) PositionalArgs {
+	return MatchAll(ExactArgs(n), OnlyValidArgs)
+}
diff --git a/bash_completions.go b/bash_completions.go
index cb7e195..3acdb27 100644
--- a/bash_completions.go
+++ b/bash_completions.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/bash_completionsV2.go b/bash_completionsV2.go
index 351391a..bb4b718 100644
--- a/bash_completionsV2.go
+++ b/bash_completionsV2.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/cobra.go b/cobra.go
index d6cbfd7..1a95c3c 100644
--- a/cobra.go
+++ b/cobra.go
@@ -1,9 +1,10 @@
-// Copyright © 2013 Steve Francia <spf@spf13.com>.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
@@ -40,14 +41,23 @@ var templateFuncs = template.FuncMap{
 
 var initializers []func()
 
+const (
+	defaultPrefixMatching  = false
+	defaultCommandSorting  = true
+	defaultCaseInsensitive = false
+)
+
 // EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing
 // to automatically enable in CLI tools.
 // Set this to true to enable it.
-var EnablePrefixMatching = false
+var EnablePrefixMatching = defaultPrefixMatching
 
 // EnableCommandSorting controls sorting of the slice of commands, which is turned on by default.
 // To disable sorting, set it to false.
-var EnableCommandSorting = true
+var EnableCommandSorting = defaultCommandSorting
+
+// EnableCaseInsensitive allows case-insensitive commands names. (case sensitive by default)
+var EnableCaseInsensitive = defaultCaseInsensitive
 
 // MousetrapHelpText enables an information splash screen on Windows
 // if the CLI is started from explorer.exe.
diff --git a/command.go b/command.go
index 5fca7dc..cdfd360 100644
--- a/command.go
+++ b/command.go
@@ -1,9 +1,10 @@
-// Copyright © 2013 Steve Francia <spf@spf13.com>.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
@@ -236,8 +237,8 @@ func (c *Command) Context() context.Context {
 	return c.ctx
 }
 
-// SetContext sets context for the command. It is set to context.Background by default and will be overwritten by
-// Command.ExecuteContext or Command.ExecuteContextC
+// SetContext sets context for the command. This context will be overwritten by
+// Command.ExecuteContext or Command.ExecuteContextC.
 func (c *Command) SetContext(ctx context.Context) {
 	c.ctx = ctx
 }
@@ -676,7 +677,7 @@ func (c *Command) findSuggestions(arg string) string {
 func (c *Command) findNext(next string) *Command {
 	matches := make([]*Command, 0)
 	for _, cmd := range c.commands {
-		if cmd.Name() == next || cmd.HasAlias(next) {
+		if commandNameMatches(cmd.Name(), next) || cmd.HasAlias(next) {
 			cmd.commandCalledAs.name = next
 			return cmd
 		}
@@ -1328,7 +1329,7 @@ func (c *Command) Name() string {
 // HasAlias determines if a given string is an alias of the command.
 func (c *Command) HasAlias(s string) bool {
 	for _, a := range c.Aliases {
-		if a == s {
+		if commandNameMatches(a, s) {
 			return true
 		}
 	}
@@ -1695,3 +1696,14 @@ func (c *Command) updateParentsPflags() {
 		c.parentsPflags.AddFlagSet(parent.PersistentFlags())
 	})
 }
+
+// commandNameMatches checks if two command names are equal
+// taking into account case sensitivity according to
+// EnableCaseInsensitive global configuration.
+func commandNameMatches(s string, t string) bool {
+	if EnableCaseInsensitive {
+		return strings.EqualFold(s, t)
+	}
+
+	return s == t
+}
diff --git a/command_notwin.go b/command_notwin.go
index bb5dad9..2b77f8f 100644
--- a/command_notwin.go
+++ b/command_notwin.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 //go:build !windows
 // +build !windows
 
diff --git a/command_win.go b/command_win.go
index a84f5a8..520f23a 100644
--- a/command_win.go
+++ b/command_win.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 //go:build windows
 // +build windows
 
diff --git a/completions.go b/completions.go
index 2c24839..f8bf4f6 100644
--- a/completions.go
+++ b/completions.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/doc/man_docs.go b/doc/man_docs.go
index 8dbce35..b5a2c59 100644
--- a/doc/man_docs.go
+++ b/doc/man_docs.go
@@ -1,9 +1,10 @@
-// Copyright 2015 Red Hat Inc. All rights reserved.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/doc/md_docs.go b/doc/md_docs.go
index 19d7e93..bab4b49 100644
--- a/doc/md_docs.go
+++ b/doc/md_docs.go
@@ -1,9 +1,10 @@
-//Copyright 2015 Red Hat Inc. All rights reserved.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/doc/rest_docs.go b/doc/rest_docs.go
index 23dca16..d658906 100644
--- a/doc/rest_docs.go
+++ b/doc/rest_docs.go
@@ -1,9 +1,10 @@
-//Copyright 2015 Red Hat Inc. All rights reserved.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/doc/util.go b/doc/util.go
index bffde94..499ecdd 100644
--- a/doc/util.go
+++ b/doc/util.go
@@ -1,9 +1,10 @@
-// Copyright 2015 Red Hat Inc. All rights reserved.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/doc/yaml_docs.go b/doc/yaml_docs.go
index 784c387..12f8cf3 100644
--- a/doc/yaml_docs.go
+++ b/doc/yaml_docs.go
@@ -1,9 +1,10 @@
-// Copyright 2016 French Ben. All rights reserved.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/fish_completions.go b/fish_completions.go
index 005ee6b..97112a1 100644
--- a/fish_completions.go
+++ b/fish_completions.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/flag_groups.go b/flag_groups.go
index dc78431..b09236f 100644
--- a/flag_groups.go
+++ b/flag_groups.go
@@ -1,9 +1,10 @@
-// Copyright © 2022 Steve Francia <spf@spf13.com>.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/powershell_completions.go b/powershell_completions.go
index 379e7c0..351ded6 100644
--- a/powershell_completions.go
+++ b/powershell_completions.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 // The generated scripts require PowerShell v5.0+ (which comes Windows 10, but
 // can be downloaded separately for windows 7 or 8.1).
 
diff --git a/shell_completions.go b/shell_completions.go
index d99bf91..126e83c 100644
--- a/shell_completions.go
+++ b/shell_completions.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/shell_completions.md b/shell_completions.md
index 1e2058e..a0957b4 100644
--- a/shell_completions.md
+++ b/shell_completions.md
@@ -99,6 +99,11 @@ To tell Cobra *not* to provide the default `completion` command:
 rootCmd.CompletionOptions.DisableDefaultCmd = true
 ```
 
+To tell Cobra to mark the default `completion` command as *hidden*:
+```
+rootCmd.CompletionOptions.HiddenDefaultCmd = true
+```
+
 To tell Cobra *not* to provide the user with the `--no-descriptions` flag to the completion sub-commands:
 ```
 rootCmd.CompletionOptions.DisableNoDescFlag = true
diff --git a/user_guide.md b/user_guide.md
index 5a7acf8..c694d87 100644
--- a/user_guide.md
+++ b/user_guide.md
@@ -302,15 +302,15 @@ rootCmd.MarkPersistentFlagRequired("region")
 
 ### Flag Groups
 
-If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then 
+If you have different flags that must be provided together (e.g. if they provide the `--username` flag they MUST provide the `--password` flag as well) then
 Cobra can enforce that requirement:
 ```go
 rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)")
 rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)")
 rootCmd.MarkFlagsRequiredTogether("username", "password")
-``` 
+```
 
-You can also prevent different flags from being provided together if they represent mutually 
+You can also prevent different flags from being provided together if they represent mutually
 exclusive options such as specifying an output format as either `--json` or `--yaml` but never both:
 ```go
 rootCmd.Flags().BoolVar(&u, "json", false, "Output in JSON")
@@ -327,29 +327,47 @@ In both of these cases:
 ## Positional and Custom Arguments
 
 Validation of positional arguments can be specified using the `Args` field of `Command`.
+The following validators are built in:
+
+- Number of arguments:
+  - `NoArgs` - report an error if there are any positional args.
+  - `ArbitraryArgs` - accept any number of args.
+  - `MinimumNArgs(int)` - report an error if less than N positional args are provided.
+  - `MaximumNArgs(int)` - report an error if more than N positional args are provided.
+  - `ExactArgs(int)` - report an error if there are not exactly N positional args.
+  - `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`.
+- Content of the arguments:
+  - `OnlyValidArgs` - report an error if there are any positional args not specified in the `ValidArgs` field of `Command`, which can optionally be set to a list of valid values for positional args.
+
 If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`.
 
-The following validators are built in:
+Moreover, `MatchAll(pargs ...PositionalArgs)` enables combining existing checks with arbitrary other checks.
+For instance, if you want to report an error if there are not exactly N positional args OR if there are any positional
+args that are not in the `ValidArgs` field of `Command`, you can call `MatchAll` on `ExactArgs` and `OnlyValidArgs`, as
+shown below:
 
-- `NoArgs` - the command will report an error if there are any positional args.
-- `ArbitraryArgs` - the command will accept any args.
-- `OnlyValidArgs` - the command will report an error if there are any positional args that are not in the `ValidArgs` field of `Command`.
-- `MinimumNArgs(int)` - the command will report an error if there are not at least N positional args.
-- `MaximumNArgs(int)` - the command will report an error if there are more than N positional args.
-- `ExactArgs(int)` - the command will report an error if there are not exactly N positional args.
-- `ExactValidArgs(int)` - the command will report an error if there are not exactly N positional args OR if there are any positional args that are not in the `ValidArgs` field of `Command`
-- `RangeArgs(min, max)` - the command will report an error if the number of args is not between the minimum and maximum number of expected args.
-- `MatchAll(pargs ...PositionalArgs)` - enables combining existing checks with arbitrary other checks (e.g. you want to check the ExactArgs length along with other qualities).
+```go
+var cmd = &cobra.Command{
+  Short: "hello",
+  Args: MatchAll(ExactArgs(2), OnlyValidArgs),
+  Run: func(cmd *cobra.Command, args []string) {
+    fmt.Println("Hello, World!")
+  },
+}
+```
 
-An example of setting the custom validator:
+It is possible to set any custom validator that satisfies `func(cmd *cobra.Command, args []string) error`.
+For example:
 
 ```go
 var cmd = &cobra.Command{
   Short: "hello",
   Args: func(cmd *cobra.Command, args []string) error {
-    if len(args) < 1 {
-      return errors.New("requires a color argument")
+    // Optionally run one of the validators provided by cobra
+    if err := cobra.MinimumNArgs(1)(cmd, args); err != nil {
+        return err
     }
+    // Run the custom validation logic
     if myapp.IsValidColor(args[0]) {
       return nil
     }
@@ -444,28 +462,29 @@ create' is called.  Every command will automatically have the '--help' flag adde
 The following output is automatically generated by Cobra. Nothing beyond the
 command and flag definitions are needed.
 
-    $ cobra help
+    $ cobra-cli help
 
     Cobra is a CLI library for Go that empowers applications.
     This application is a tool to generate the needed files
     to quickly create a Cobra application.
 
     Usage:
-      cobra [command]
+      cobra-cli [command]
 
     Available Commands:
       add         Add a command to a Cobra Application
+      completion  Generate the autocompletion script for the specified shell
       help        Help about any command
       init        Initialize a Cobra Application
 
     Flags:
       -a, --author string    author name for copyright attribution (default "YOUR NAME")
           --config string    config file (default is $HOME/.cobra.yaml)
-      -h, --help             help for cobra
+      -h, --help             help for cobra-cli
       -l, --license string   name of license for the project
-          --viper            use Viper for configuration (default true)
+          --viper            use Viper for configuration
 
-    Use "cobra [command] --help" for more information about a command.
+    Use "cobra-cli [command] --help" for more information about a command.
 
 
 Help is just a command like any other. There is no special logic or behavior
@@ -474,7 +493,7 @@ around it. In fact, you can provide your own if you want.
 ### Defining your own help
 
 You can provide your own Help command or your own template for the default command to use
-with following functions:
+with the following functions:
 
 ```go
 cmd.SetHelpCommand(cmd *Command)
@@ -493,22 +512,23 @@ showing the user the 'usage'.
 You may recognize this from the help above. That's because the default help
 embeds the usage as part of its output.
 
-    $ cobra --invalid
+    $ cobra-cli --invalid
     Error: unknown flag: --invalid
     Usage:
-      cobra [command]
+      cobra-cli [command]
 
     Available Commands:
       add         Add a command to a Cobra Application
+      completion  Generate the autocompletion script for the specified shell
       help        Help about any command
       init        Initialize a Cobra Application
 
     Flags:
       -a, --author string    author name for copyright attribution (default "YOUR NAME")
           --config string    config file (default is $HOME/.cobra.yaml)
-      -h, --help             help for cobra
+      -h, --help             help for cobra-cli
       -l, --license string   name of license for the project
-          --viper            use Viper for configuration (default true)
+          --viper            use Viper for configuration
 
     Use "cobra [command] --help" for more information about a command.
 
@@ -627,7 +647,7 @@ Did you mean this?
 Run 'hugo --help' for usage.
 ```
 
-Suggestions are automatic based on every subcommand registered and use an implementation of [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion.
+Suggestions are automatically generated based on existing subcommands and use an implementation of [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance). Every registered command that matches a minimum distance of 2 (ignoring case) will be displayed as a suggestion.
 
 If you need to disable suggestions or tweak the string distance in your command, use:
 
@@ -641,7 +661,8 @@ or
 command.SuggestionsMinimumDistance = 1
 ```
 
-You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but makes sense in your set of commands and for some which you don't want aliases. Example:
+You can also explicitly set names for which a given command will be suggested using the `SuggestFor` attribute. This allows suggestions for strings that are not close in terms of string distance, but make sense in your set of commands but for which
+you don't want aliases. Example:
 
 ```
 $ kubectl remove
diff --git a/zsh_completions.go b/zsh_completions.go
index 65cd94c..84cec76 100644
--- a/zsh_completions.go
+++ b/zsh_completions.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (


Test patch:
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e0c2f15..7865add 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -3,20 +3,43 @@ name: Test
 on:
   push:
   pull_request:
+  workflow_dispatch:
 
 env:
   GO111MODULE: on
 
 jobs:
 
+
+  lic-headers:
+    runs-on: ubuntu-latest
+    steps:
+
+      - uses: actions/checkout@v3
+
+      - run: >-
+          docker run
+          -v $(pwd):/wrk -w /wrk
+          ghcr.io/google/addlicense
+          -c 'The Cobra Authors'
+          -y '2013-2022'
+          -l apache
+          -ignore '.github/**'
+          -check
+          .
+
+
   golangci-lint:
     runs-on: ubuntu-latest
     steps:
 
+      - uses: actions/checkout@v3
+
       - uses: actions/setup-go@v3
         with:
           go-version: '^1.19'
           check-latest: true
+          cache: true
 
       - uses: actions/checkout@v3
 
@@ -25,6 +48,7 @@ jobs:
           version: latest
           args: --verbose
 
+
   test-unix:
     strategy:
       fail-fast: false
@@ -33,7 +57,6 @@ jobs:
         - ubuntu
         - macOS
         go:
-        - 14
         - 15
         - 16
         - 17
@@ -43,17 +66,12 @@ jobs:
     runs-on: ${{ matrix.platform }}-latest
     steps:
 
-    - uses: actions/setup-go@v3
-      with:
-        go-version: 1.${{ matrix.go }}.x
-
     - uses: actions/checkout@v3
 
-    - uses: actions/cache@v3
+    - uses: actions/setup-go@v3
       with:
-        path: ~/go/pkg/mod
-        key: ${{ runner.os }}-1.${{ matrix.go }}.x-${{ hashFiles('**/go.sum') }}
-        restore-keys: ${{ runner.os }}-1.${{ matrix.go }}.x-
+        go-version: 1.${{ matrix.go }}.x
+        cache: true
 
     - run: |
         export GOBIN=$HOME/go/bin
@@ -66,6 +84,7 @@ jobs:
 
     - run: RICHGO_FORCE_COLOR=1 PATH=$HOME/go/bin/:$PATH make test
 
+
   test-win:
     name: MINGW64
     defaults:
diff --git a/active_help_test.go b/active_help_test.go
index 524be88..3653dd8 100644
--- a/active_help_test.go
+++ b/active_help_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/args_test.go b/args_test.go
index 6bd41c8..fd2c3b4 100644
--- a/args_test.go
+++ b/args_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
@@ -27,7 +41,7 @@ func expectSuccess(output string, err error, t *testing.T) {
 	}
 }
 
-func validWithInvalidArgs(err error, t *testing.T) {
+func validOnlyWithInvalidArgs(err error, t *testing.T) {
 	if err == nil {
 		t.Fatal("Expected an error")
 	}
@@ -38,12 +52,12 @@ func validWithInvalidArgs(err error, t *testing.T) {
 	}
 }
 
-func noArgsWithArgs(err error, t *testing.T) {
+func noArgsWithArgs(err error, t *testing.T, arg string) {
 	if err == nil {
 		t.Fatal("Expected an error")
 	}
 	got := err.Error()
-	expected := `unknown command "illegal" for "c"`
+	expected := `unknown command "` + arg + `" for "c"`
 	if got != expected {
 		t.Errorf("Expected: %q, got: %q", expected, got)
 	}
@@ -93,102 +107,280 @@ func rangeArgsWithInvalidCount(err error, t *testing.T) {
 	}
 }
 
+// NoArgs
+
 func TestNoArgs(t *testing.T) {
 	c := getCommand(NoArgs, false)
 	output, err := executeCommand(c)
 	expectSuccess(output, err, t)
 }
 
-func TestNoArgsWithArgs(t *testing.T) {
+func TestNoArgs_WithArgs(t *testing.T) {
 	c := getCommand(NoArgs, false)
-	_, err := executeCommand(c, "illegal")
-	noArgsWithArgs(err, t)
+	_, err := executeCommand(c, "one")
+	noArgsWithArgs(err, t, "one")
+}
+
+func TestNoArgs_WithValid_WithArgs(t *testing.T) {
+	c := getCommand(NoArgs, true)
+	_, err := executeCommand(c, "one")
+	noArgsWithArgs(err, t, "one")
+}
+
+func TestNoArgs_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(NoArgs, true)
+	_, err := executeCommand(c, "a")
+	noArgsWithArgs(err, t, "a")
+}
+
+func TestNoArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, NoArgs), true)
+	_, err := executeCommand(c, "a")
+	validOnlyWithInvalidArgs(err, t)
 }
 
+// OnlyValidArgs
+
 func TestOnlyValidArgs(t *testing.T) {
 	c := getCommand(OnlyValidArgs, true)
 	output, err := executeCommand(c, "one", "two")
 	expectSuccess(output, err, t)
 }
 
-func TestOnlyValidArgsWithInvalidArgs(t *testing.T) {
+func TestOnlyValidArgs_WithInvalidArgs(t *testing.T) {
 	c := getCommand(OnlyValidArgs, true)
 	_, err := executeCommand(c, "a")
-	validWithInvalidArgs(err, t)
+	validOnlyWithInvalidArgs(err, t)
 }
 
+// ArbitraryArgs
+
 func TestArbitraryArgs(t *testing.T) {
 	c := getCommand(ArbitraryArgs, false)
 	output, err := executeCommand(c, "a", "b")
 	expectSuccess(output, err, t)
 }
 
+func TestArbitraryArgs_WithValid(t *testing.T) {
+	c := getCommand(ArbitraryArgs, true)
+	output, err := executeCommand(c, "one", "two")
+	expectSuccess(output, err, t)
+}
+
+func TestArbitraryArgs_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(ArbitraryArgs, true)
+	output, err := executeCommand(c, "a")
+	expectSuccess(output, err, t)
+}
+
+func TestArbitraryArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, ArbitraryArgs), true)
+	_, err := executeCommand(c, "a")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+// MinimumNArgs
+
 func TestMinimumNArgs(t *testing.T) {
 	c := getCommand(MinimumNArgs(2), false)
 	output, err := executeCommand(c, "a", "b", "c")
 	expectSuccess(output, err, t)
 }
 
-func TestMinimumNArgsWithLessArgs(t *testing.T) {
+func TestMinimumNArgs_WithValid(t *testing.T) {
+	c := getCommand(MinimumNArgs(2), true)
+	output, err := executeCommand(c, "one", "three")
+	expectSuccess(output, err, t)
+}
+
+func TestMinimumNArgs_WithValid__WithInvalidArgs(t *testing.T) {
+	c := getCommand(MinimumNArgs(2), true)
+	output, err := executeCommand(c, "a", "b")
+	expectSuccess(output, err, t)
+}
+
+func TestMinimumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true)
+	_, err := executeCommand(c, "a", "b")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+func TestMinimumNArgs_WithLessArgs(t *testing.T) {
 	c := getCommand(MinimumNArgs(2), false)
 	_, err := executeCommand(c, "a")
 	minimumNArgsWithLessArgs(err, t)
 }
 
+func TestMinimumNArgs_WithLessArgs_WithValid(t *testing.T) {
+	c := getCommand(MinimumNArgs(2), true)
+	_, err := executeCommand(c, "one")
+	minimumNArgsWithLessArgs(err, t)
+}
+
+func TestMinimumNArgs_WithLessArgs_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MinimumNArgs(2), true)
+	_, err := executeCommand(c, "a")
+	minimumNArgsWithLessArgs(err, t)
+}
+
+func TestMinimumNArgs_WithLessArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true)
+	_, err := executeCommand(c, "a")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+// MaximumNArgs
+
 func TestMaximumNArgs(t *testing.T) {
 	c := getCommand(MaximumNArgs(3), false)
 	output, err := executeCommand(c, "a", "b")
 	expectSuccess(output, err, t)
 }
 
-func TestMaximumNArgsWithMoreArgs(t *testing.T) {
+func TestMaximumNArgs_WithValid(t *testing.T) {
+	c := getCommand(MaximumNArgs(2), true)
+	output, err := executeCommand(c, "one", "three")
+	expectSuccess(output, err, t)
+}
+
+func TestMaximumNArgs_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MaximumNArgs(2), true)
+	output, err := executeCommand(c, "a", "b")
+	expectSuccess(output, err, t)
+}
+
+func TestMaximumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true)
+	_, err := executeCommand(c, "a", "b")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+func TestMaximumNArgs_WithMoreArgs(t *testing.T) {
 	c := getCommand(MaximumNArgs(2), false)
 	_, err := executeCommand(c, "a", "b", "c")
 	maximumNArgsWithMoreArgs(err, t)
 }
 
+func TestMaximumNArgs_WithMoreArgs_WithValid(t *testing.T) {
+	c := getCommand(MaximumNArgs(2), true)
+	_, err := executeCommand(c, "one", "three", "two")
+	maximumNArgsWithMoreArgs(err, t)
+}
+
+func TestMaximumNArgs_WithMoreArgs_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MaximumNArgs(2), true)
+	_, err := executeCommand(c, "a", "b", "c")
+	maximumNArgsWithMoreArgs(err, t)
+}
+
+func TestMaximumNArgs_WithMoreArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true)
+	_, err := executeCommand(c, "a", "b", "c")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+// ExactArgs
+
 func TestExactArgs(t *testing.T) {
 	c := getCommand(ExactArgs(3), false)
 	output, err := executeCommand(c, "a", "b", "c")
 	expectSuccess(output, err, t)
 }
 
-func TestExactArgsWithInvalidCount(t *testing.T) {
+func TestExactArgs_WithValid(t *testing.T) {
+	c := getCommand(ExactArgs(3), true)
+	output, err := executeCommand(c, "three", "one", "two")
+	expectSuccess(output, err, t)
+}
+
+func TestExactArgs_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(ExactArgs(3), true)
+	output, err := executeCommand(c, "three", "a", "two")
+	expectSuccess(output, err, t)
+}
+
+func TestExactArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(3)), true)
+	_, err := executeCommand(c, "three", "a", "two")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+func TestExactArgs_WithInvalidCount(t *testing.T) {
 	c := getCommand(ExactArgs(2), false)
 	_, err := executeCommand(c, "a", "b", "c")
 	exactArgsWithInvalidCount(err, t)
 }
 
-func TestExactValidArgs(t *testing.T) {
-	c := getCommand(ExactValidArgs(3), true)
-	output, err := executeCommand(c, "three", "one", "two")
-	expectSuccess(output, err, t)
+func TestExactArgs_WithInvalidCount_WithValid(t *testing.T) {
+	c := getCommand(ExactArgs(2), true)
+	_, err := executeCommand(c, "three", "one", "two")
+	exactArgsWithInvalidCount(err, t)
 }
 
-func TestExactValidArgsWithInvalidCount(t *testing.T) {
-	c := getCommand(ExactValidArgs(2), false)
-	_, err := executeCommand(c, "three", "one", "two")
+func TestExactArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(ExactArgs(2), true)
+	_, err := executeCommand(c, "three", "a", "two")
 	exactArgsWithInvalidCount(err, t)
 }
 
-func TestExactValidArgsWithInvalidArgs(t *testing.T) {
-	c := getCommand(ExactValidArgs(3), true)
+func TestExactArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(2)), true)
 	_, err := executeCommand(c, "three", "a", "two")
-	validWithInvalidArgs(err, t)
+	validOnlyWithInvalidArgs(err, t)
 }
 
+// RangeArgs
+
 func TestRangeArgs(t *testing.T) {
 	c := getCommand(RangeArgs(2, 4), false)
 	output, err := executeCommand(c, "a", "b", "c")
 	expectSuccess(output, err, t)
 }
 
-func TestRangeArgsWithInvalidCount(t *testing.T) {
+func TestRangeArgs_WithValid(t *testing.T) {
+	c := getCommand(RangeArgs(2, 4), true)
+	output, err := executeCommand(c, "three", "one", "two")
+	expectSuccess(output, err, t)
+}
+
+func TestRangeArgs_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(RangeArgs(2, 4), true)
+	output, err := executeCommand(c, "three", "a", "two")
+	expectSuccess(output, err, t)
+}
+
+func TestRangeArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true)
+	_, err := executeCommand(c, "three", "a", "two")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+func TestRangeArgs_WithInvalidCount(t *testing.T) {
 	c := getCommand(RangeArgs(2, 4), false)
 	_, err := executeCommand(c, "a")
 	rangeArgsWithInvalidCount(err, t)
 }
 
+func TestRangeArgs_WithInvalidCount_WithValid(t *testing.T) {
+	c := getCommand(RangeArgs(2, 4), true)
+	_, err := executeCommand(c, "two")
+	rangeArgsWithInvalidCount(err, t)
+}
+
+func TestRangeArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) {
+	c := getCommand(RangeArgs(2, 4), true)
+	_, err := executeCommand(c, "a")
+	rangeArgsWithInvalidCount(err, t)
+}
+
+func TestRangeArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) {
+	c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true)
+	_, err := executeCommand(c, "a")
+	validOnlyWithInvalidArgs(err, t)
+}
+
+// Takes(No)Args
+
 func TestRootTakesNoArgs(t *testing.T) {
 	rootCmd := &Command{Use: "root", Run: emptyRun}
 	childCmd := &Command{Use: "child", Run: emptyRun}
@@ -293,6 +485,32 @@ func TestMatchAll(t *testing.T) {
 	}
 }
 
+// DEPRECATED
+
+func TestExactValidArgs(t *testing.T) {
+	c := getCommand(ExactValidArgs(3), true)
+	output, err := executeCommand(c, "three", "one", "two")
+	expectSuccess(output, err, t)
+}
+
+func TestExactValidArgs_WithInvalidCount(t *testing.T) {
+	c := getCommand(ExactValidArgs(2), false)
+	_, err := executeCommand(c, "three", "one", "two")
+	exactArgsWithInvalidCount(err, t)
+}
+
+func TestExactValidArgs_WithInvalidCount_WithInvalidArgs(t *testing.T) {
+	c := getCommand(ExactValidArgs(2), true)
+	_, err := executeCommand(c, "three", "a", "two")
+	exactArgsWithInvalidCount(err, t)
+}
+
+func TestExactValidArgs_WithInvalidArgs(t *testing.T) {
+	c := getCommand(ExactValidArgs(2), true)
+	_, err := executeCommand(c, "three", "a")
+	validOnlyWithInvalidArgs(err, t)
+}
+
 // This test make sure we keep backwards-compatibility with respect
 // to the legacyArgs() function.
 // It makes sure the root command accepts arguments if it does not have
diff --git a/bash_completionsV2_test.go b/bash_completionsV2_test.go
index a9a277e..9302baf 100644
--- a/bash_completionsV2_test.go
+++ b/bash_completionsV2_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/bash_completions_test.go b/bash_completions_test.go
index 6896e91..5c32306 100644
--- a/bash_completions_test.go
+++ b/bash_completions_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/cobra_test.go b/cobra_test.go
index 1219cc0..71353c9 100644
--- a/cobra_test.go
+++ b/cobra_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/command_test.go b/command_test.go
index 0b0b821..a4b7366 100644
--- a/command_test.go
+++ b/command_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
@@ -314,7 +328,7 @@ func TestEnablePrefixMatching(t *testing.T) {
 		t.Errorf("aCmdArgs expected: %q, got: %q", onetwo, got)
 	}
 
-	EnablePrefixMatching = false
+	EnablePrefixMatching = defaultPrefixMatching
 }
 
 func TestAliasPrefixMatching(t *testing.T) {
@@ -349,7 +363,7 @@ func TestAliasPrefixMatching(t *testing.T) {
 		t.Errorf("timesCmdArgs expected: %v, got: %v", onetwo, got)
 	}
 
-	EnablePrefixMatching = false
+	EnablePrefixMatching = defaultPrefixMatching
 }
 
 // TestChildSameName checks the correct behaviour of cobra in cases,
@@ -1263,6 +1277,113 @@ func TestSuggestions(t *testing.T) {
 	}
 }
 
+func TestCaseInsensitive(t *testing.T) {
+	rootCmd := &Command{Use: "root", Run: emptyRun}
+	childCmd := &Command{Use: "child", Run: emptyRun, Aliases: []string{"alternative"}}
+	granchildCmd := &Command{Use: "GRANDCHILD", Run: emptyRun, Aliases: []string{"ALIAS"}}
+
+	childCmd.AddCommand(granchildCmd)
+	rootCmd.AddCommand(childCmd)
+
+	tests := []struct {
+		args                []string
+		failWithoutEnabling bool
+	}{
+		{
+			args:                []string{"child"},
+			failWithoutEnabling: false,
+		},
+		{
+			args:                []string{"CHILD"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"chILD"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"CHIld"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"alternative"},
+			failWithoutEnabling: false,
+		},
+		{
+			args:                []string{"ALTERNATIVE"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"ALTernatIVE"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"alternatiVE"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"child", "GRANDCHILD"},
+			failWithoutEnabling: false,
+		},
+		{
+			args:                []string{"child", "grandchild"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"CHIld", "GRANdchild"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"alternative", "ALIAS"},
+			failWithoutEnabling: false,
+		},
+		{
+			args:                []string{"alternative", "alias"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"CHILD", "alias"},
+			failWithoutEnabling: true,
+		},
+		{
+			args:                []string{"CHIld", "aliAS"},
+			failWithoutEnabling: true,
+		},
+	}
+
+	for _, test := range tests {
+		for _, enableCaseInsensitivity := range []bool{true, false} {
+			EnableCaseInsensitive = enableCaseInsensitivity
+
+			output, err := executeCommand(rootCmd, test.args...)
+			expectedFailure := test.failWithoutEnabling && !enableCaseInsensitivity
+
+			if !expectedFailure && output != "" {
+				t.Errorf("Unexpected output: %v", output)
+			}
+			if !expectedFailure && err != nil {
+				t.Errorf("Unexpected error: %v", err)
+			}
+		}
+	}
+
+	EnableCaseInsensitive = defaultCaseInsensitive
+}
+
+// This test make sure we keep backwards-compatibility with respect
+// to command names case sensitivity behavior.
+func TestCaseSensitivityBackwardCompatibility(t *testing.T) {
+	rootCmd := &Command{Use: "root", Run: emptyRun}
+	childCmd := &Command{Use: "child", Run: emptyRun}
+
+	rootCmd.AddCommand(childCmd)
+	_, err := executeCommand(rootCmd, strings.ToUpper(childCmd.Use))
+	if err == nil {
+		t.Error("Expected error on calling a command in upper case while command names are case sensitive. Got nil.")
+	}
+
+}
+
 func TestRemoveCommand(t *testing.T) {
 	rootCmd := &Command{Use: "root", Args: NoArgs, Run: emptyRun}
 	childCmd := &Command{Use: "child", Run: emptyRun}
@@ -1622,7 +1743,7 @@ func TestCommandsAreSorted(t *testing.T) {
 		}
 	}
 
-	EnableCommandSorting = true
+	EnableCommandSorting = defaultCommandSorting
 }
 
 func TestEnableCommandSortingIsDisabled(t *testing.T) {
@@ -1643,7 +1764,7 @@ func TestEnableCommandSortingIsDisabled(t *testing.T) {
 		}
 	}
 
-	EnableCommandSorting = true
+	EnableCommandSorting = defaultCommandSorting
 }
 
 func TestSetOutput(t *testing.T) {
diff --git a/completions_test.go b/completions_test.go
index fa087fd..c5f11fa 100644
--- a/completions_test.go
+++ b/completions_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/doc/cmd_test.go b/doc/cmd_test.go
index 0917d60..4f2a0f5 100644
--- a/doc/cmd_test.go
+++ b/doc/cmd_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package doc
 
 import (
diff --git a/doc/man_docs_test.go b/doc/man_docs_test.go
index f7994f8..d296eeb 100644
--- a/doc/man_docs_test.go
+++ b/doc/man_docs_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package doc
 
 import (
diff --git a/doc/man_examples_test.go b/doc/man_examples_test.go
index e20a34c..b995bf6 100644
--- a/doc/man_examples_test.go
+++ b/doc/man_examples_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package doc_test
 
 import (
diff --git a/doc/md_docs_test.go b/doc/md_docs_test.go
index f325167..b1632e9 100644
--- a/doc/md_docs_test.go
+++ b/doc/md_docs_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package doc
 
 import (
diff --git a/doc/rest_docs_test.go b/doc/rest_docs_test.go
index 330a2e5..0c197f8 100644
--- a/doc/rest_docs_test.go
+++ b/doc/rest_docs_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package doc
 
 import (
diff --git a/doc/yaml_docs_test.go b/doc/yaml_docs_test.go
index 9bf5aa6..c552077 100644
--- a/doc/yaml_docs_test.go
+++ b/doc/yaml_docs_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package doc
 
 import (
diff --git a/fish_completions_test.go b/fish_completions_test.go
index 381c667..935f554 100644
--- a/fish_completions_test.go
+++ b/fish_completions_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (
diff --git a/flag_groups_test.go b/flag_groups_test.go
index 404ede5..b4b65ac 100644
--- a/flag_groups_test.go
+++ b/flag_groups_test.go
@@ -1,9 +1,10 @@
-// Copyright © 2022 Steve Francia <spf@spf13.com>.
+// Copyright 2013-2022 The Cobra Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
diff --git a/power_completions_test.go b/power_completions_test.go
deleted file mode 100644
index 7713835..0000000
--- a/power_completions_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package cobra
-
-import (
-	"bytes"
-	"fmt"
-	"testing"
-)
-
-func TestPwshCompletionNoActiveHelp(t *testing.T) {
-	c := &Command{Use: "c", Run: emptyRun}
-
-	buf := new(bytes.Buffer)
-	assertNoErr(t, c.GenPowerShellCompletion(buf))
-	output := buf.String()
-
-	// check that active help is being disabled
-	activeHelpVar := activeHelpEnvVar(c.Name())
-	check(t, output, fmt.Sprintf("%s=0", activeHelpVar))
-}
diff --git a/powershell_completions_test.go b/powershell_completions_test.go
new file mode 100644
index 0000000..3d3d103
--- /dev/null
+++ b/powershell_completions_test.go
@@ -0,0 +1,33 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package cobra
+
+import (
+	"bytes"
+	"fmt"
+	"testing"
+)
+
+func TestPwshCompletionNoActiveHelp(t *testing.T) {
+	c := &Command{Use: "c", Run: emptyRun}
+
+	buf := new(bytes.Buffer)
+	assertNoErr(t, c.GenPowerShellCompletion(buf))
+	output := buf.String()
+
+	// check that active help is being disabled
+	activeHelpVar := activeHelpEnvVar(c.Name())
+	check(t, output, fmt.Sprintf("%s=0", activeHelpVar))
+}
diff --git a/zsh_completions_test.go b/zsh_completions_test.go
index b7addb4..258b1f7 100644
--- a/zsh_completions_test.go
+++ b/zsh_completions_test.go
@@ -1,3 +1,17 @@
+// Copyright 2013-2022 The Cobra Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 package cobra
 
 import (