Allow optional subcommands
diff --git a/command.go b/command.go
index 5e99cd6..b55597f 100644
--- a/command.go
+++ b/command.go
@@ -14,6 +14,9 @@
 	// The active sub command (set by parsing) or nil
 	Active *Command
 
+	// Whether subcommands are optional
+	SubcommandsOptional bool
+
 	commands            []*Command
 	hasBuiltinHelpGroup bool
 }
diff --git a/command_private.go b/command_private.go
index 0195a46..2cc7fbc 100644
--- a/command_private.go
+++ b/command_private.go
@@ -37,11 +37,18 @@
 
 			shortDescription := mtag.Get("description")
 			longDescription := mtag.Get("long-description")
+			subcommandsOptional := mtag.Get("subcommands-optional")
 
-			if _, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface()); err != nil {
+			subc, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface())
+
+			if err != nil {
 				return true, err
 			}
 
+			if len(subcommandsOptional) > 0 {
+				subc.SubcommandsOptional = true
+			}
+
 			return true, nil
 		}
 
diff --git a/command_test.go b/command_test.go
index 9b903a2..230f981 100644
--- a/command_test.go
+++ b/command_test.go
@@ -293,3 +293,28 @@
 	}
 }
 
+func TestSubcommandsOptional(t *testing.T) {
+	var opts = struct {
+		Value bool `short:"v"`
+
+		Cmd1 struct {
+		} `command:"remove"`
+
+		Cmd2 struct {
+		} `command:"add"`
+	}{}
+
+	p := NewParser(&opts, None)
+	p.SubcommandsOptional = true
+
+	_, err := p.ParseArgs([]string{"-v"})
+
+	if err != nil {
+		t.Fatalf("Unexpected error: %v", err)
+		return
+	}
+
+	if !opts.Value {
+		t.Errorf("Expected Value to be true")
+	}
+}
diff --git a/flags.go b/flags.go
index 9b77286..ef81991 100644
--- a/flags.go
+++ b/flags.go
@@ -87,6 +87,9 @@
 //     command:        when specified on a struct field, makes the struct field
 //                     a (sub)command with the given name (optional).
 //
+//     subcommands-optional: when specified on a command struct field, makes
+//                           any subcommands of that command optional.
+//
 // Either short: or long: must be specified to make the field eligible as an
 // option.
 //
diff --git a/help.go b/help.go
index c2192ed..04540d2 100644
--- a/help.go
+++ b/help.go
@@ -237,8 +237,16 @@
 			}
 
 			if allcmd.Active == nil && len(allcmd.commands) > 0 {
+				var co, cc string
+
+				if allcmd.SubcommandsOptional {
+					co, cc = "[", "]"
+				} else {
+					co, cc = "<", ">"
+				}
+
 				if len(allcmd.commands) > 3 {
-					fmt.Fprintf(wr, " <command>")
+					fmt.Fprintf(wr, " %scommand%s", co, cc)
 				} else {
 					subcommands := allcmd.sortedCommands()
 					names := make([]string, len(subcommands))
@@ -247,7 +255,7 @@
 						names[i] = subc.Name
 					}
 
-					fmt.Fprintf(wr, " <%s>", strings.Join(names, " | "))
+					fmt.Fprintf(wr, " %s%s%s", co, strings.Join(names, " | "), cc)
 				}
 			}
 
diff --git a/parser.go b/parser.go
index b453866..677455b 100644
--- a/parser.go
+++ b/parser.go
@@ -202,7 +202,7 @@
 		return nil, p.printError(s.err)
 	}
 
-	if len(s.command.commands) != 0 {
+	if len(s.command.commands) != 0 && !s.command.SubcommandsOptional {
 		return nil, p.printError(s.estimateCommand())
 	} else if cmd, ok := s.command.data.(Commander); ok {
 		return nil, p.printError(cmd.Execute(s.retargs))