diff --git a/Library/Homebrew/cli/parser.rb b/Library/Homebrew/cli/parser.rb
index bda488b0c3f248d45ef55de7c7afd29047e87116..e43620a0cfb3be413bcfa051e011b46b90779471 100644
--- a/Library/Homebrew/cli/parser.rb
+++ b/Library/Homebrew/cli/parser.rb
@@ -34,6 +34,7 @@ module Homebrew
         @conflicts = []
         @switch_sources = {}
         @processed_options = []
+        @max_named_args = nil
         @hide_from_man_page = false
         instance_eval(&block)
         post_initialize
@@ -139,6 +140,7 @@ module Homebrew
           raise e
         end
         check_constraint_violations
+        check_named_args(remaining_args)
         @args[:remaining] = remaining_args
         @args.freeze_processed_options!(@processed_options)
         Homebrew.args = @args
@@ -178,6 +180,10 @@ module Homebrew
         []
       end
 
+      def max_named(count)
+        @max_named_args = count
+      end
+
       def hide_from_man_page!
         @hide_from_man_page = true
       end
@@ -269,6 +275,10 @@ module Homebrew
         check_constraints
       end
 
+      def check_named_args(args)
+        raise NamedArgumentsError, @max_named_args if !@max_named_args.nil? && args.size > @max_named_args
+      end
+
       def process_option(*args)
         option, = @parser.make_switch(args)
         @processed_options << [option.short.first, option.long.first, option.arg, option.desc.first]
@@ -277,14 +287,10 @@ module Homebrew
 
     class OptionConstraintError < RuntimeError
       def initialize(arg1, arg2, missing: false)
-        if !missing
-          message = <<~EOS
-            `#{arg1}` and `#{arg2}` should be passed together.
-          EOS
+        message = if !missing
+          "`#{arg1}` and `#{arg2}` should be passed together."
         else
-          message = <<~EOS
-            `#{arg2}` cannot be passed without `#{arg1}`.
-          EOS
+          "`#{arg2}` cannot be passed without `#{arg1}`."
         end
         super message
       end
@@ -294,17 +300,27 @@ module Homebrew
       def initialize(args)
         args_list = args.map(&Formatter.public_method(:option))
                         .join(" and ")
-        super <<~EOS
-          Options #{args_list} are mutually exclusive.
-        EOS
+        super "Options #{args_list} are mutually exclusive."
       end
     end
 
     class InvalidConstraintError < RuntimeError
       def initialize(arg1, arg2)
-        super <<~EOS
-          `#{arg1}` and `#{arg2}` cannot be mutually exclusive and mutually dependent simultaneously.
-        EOS
+        super "`#{arg1}` and `#{arg2}` cannot be mutually exclusive and mutually dependent simultaneously."
+      end
+    end
+
+    class NamedArgumentsError < UsageError
+      def initialize(maximum)
+        message = case maximum
+        when 0
+          "This command does not take named arguments."
+        when 1
+          "This command does not take multiple named arguments."
+        else
+          "This command does not take more than #{maximum} named arguments."
+        end
+        super message
       end
     end
   end
diff --git a/Library/Homebrew/cmd/--env.rb b/Library/Homebrew/cmd/--env.rb
index 8da098ea266dae4037f996a43f903abb50f4eb74..58cd433b0eda4593c5b097740f6e07068ba96549 100644
--- a/Library/Homebrew/cmd/--env.rb
+++ b/Library/Homebrew/cmd/--env.rb
@@ -11,7 +11,7 @@ module Homebrew
   def __env_args
     Homebrew::CLI::Parser.new do
       usage_banner <<~EOS
-        `--env` [<options>]
+        `--env` [<options>] [<formula>]
 
         Summarise Homebrew's build environment as a plain list.
 
diff --git a/Library/Homebrew/cmd/--version.rb b/Library/Homebrew/cmd/--version.rb
index 45666abbda800480818b08a06b4d598411f9dbd0..037a8cc7522851234dca410f097d54eebb6ab105 100644
--- a/Library/Homebrew/cmd/--version.rb
+++ b/Library/Homebrew/cmd/--version.rb
@@ -13,14 +13,13 @@ module Homebrew
         Print the version numbers of Homebrew, Homebrew/homebrew-core and Homebrew/homebrew-cask
         (if tapped) to standard output.
       EOS
+      max_named 0
     end
   end
 
   def __version
     __version_args.parse
 
-    odie "This command does not take arguments." if ARGV.any?
-
     puts "Homebrew #{HOMEBREW_VERSION}"
     puts "#{CoreTap.instance.full_name} #{CoreTap.instance.version_string}"
     puts "#{Tap.default_cask_tap.full_name} #{Tap.default_cask_tap.version_string}" if Tap.default_cask_tap.installed?
diff --git a/Library/Homebrew/cmd/analytics.rb b/Library/Homebrew/cmd/analytics.rb
index 17e225cec4e83bde68e4dae3ca36ac9fbe03ff57..6423caa753a3ee5bbcedfee056d6de4b12456f8d 100644
--- a/Library/Homebrew/cmd/analytics.rb
+++ b/Library/Homebrew/cmd/analytics.rb
@@ -19,14 +19,13 @@ module Homebrew
       EOS
       switch :verbose
       switch :debug
+      max_named 1
     end
   end
 
   def analytics
     analytics_args.parse
 
-    raise UsageError if args.remaining.size > 1
-
     case args.remaining.first
     when nil, "state"
       if Utils::Analytics.disabled?
@@ -42,7 +41,7 @@ module Homebrew
     when "regenerate-uuid"
       Utils::Analytics.regenerate_uuid!
     else
-      raise UsageError
+      raise UsageError, "Unknown subcommand."
     end
   end
 end
diff --git a/Library/Homebrew/cmd/cat.rb b/Library/Homebrew/cmd/cat.rb
index 1f2386da673423dce83382b605f4193394b4e64c..92f492e16613a07ff937519aeac62ead0e626c5d 100644
--- a/Library/Homebrew/cmd/cat.rb
+++ b/Library/Homebrew/cmd/cat.rb
@@ -12,17 +12,17 @@ module Homebrew
 
         Display the source of <formula>.
       EOS
+      max_named 1
     end
   end
 
   def cat
     cat_args.parse
     # do not "fix" this to support multiple arguments, the output would be
-    # unparsable, if the user wants to cat multiple formula they can call
-    # brew cat multiple times.
+    # unparsable; if the user wants to cat multiple formula they can call
+    # `brew cat` multiple times.
     formulae = Homebrew.args.formulae
     raise FormulaUnspecifiedError if formulae.empty?
-    raise "`brew cat` doesn't support multiple arguments" if args.remaining.size > 1
 
     cd HOMEBREW_REPOSITORY
     pager = if ENV["HOMEBREW_BAT"].nil?
diff --git a/Library/Homebrew/cmd/cleanup.rb b/Library/Homebrew/cmd/cleanup.rb
index 4a0837b82f33f63e49f664d8963ca799c11d58ea..4e690e8f9f4e992d8280c6b033d554c66b5f0706 100644
--- a/Library/Homebrew/cmd/cleanup.rb
+++ b/Library/Homebrew/cmd/cleanup.rb
@@ -21,7 +21,7 @@ module Homebrew
              description: "Show what would be removed, but do not actually remove anything."
       switch "-s",
              description: "Scrub the cache, including downloads for even the latest versions. "\
-                          "Note downloads for any installed formula or cask will still not be deleted. "\
+                          "Note downloads for any installed formulae or casks will still not be deleted. "\
                           "If you want to delete those too: `rm -rf \"$(brew --cache)\"`"
       switch "--prune-prefix",
              description: "Only prune the symlinks and directories from the prefix and remove no other files."
diff --git a/Library/Homebrew/cmd/command.rb b/Library/Homebrew/cmd/command.rb
index 291690ebe5bfffedb26fa0d9dd5d8dab07c110c0..a9db2cf6c3a9c90740e15f17b4d1babc7cd39609 100644
--- a/Library/Homebrew/cmd/command.rb
+++ b/Library/Homebrew/cmd/command.rb
@@ -20,17 +20,18 @@ module Homebrew
 
   def command
     command_args.parse
-    abort "This command requires a command argument" if args.remaining.empty?
 
-    cmd = HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(args.remaining.first, args.remaining.first)
+    raise UsageError, "This command requires a command argument" if args.remaining.empty?
 
-    path = Commands.path(cmd)
+    args.remaining.each do |c|
+      cmd = HOMEBREW_INTERNAL_COMMAND_ALIASES.fetch(c, c)
+      path = Commands.path(cmd)
+      cmd_paths = PATH.new(ENV["PATH"]).append(Tap.cmd_directories) unless path
+      path ||= which("brew-#{cmd}", cmd_paths)
+      path ||= which("brew-#{cmd}.rb", cmd_paths)
 
-    cmd_paths = PATH.new(ENV["PATH"]).append(Tap.cmd_directories) unless path
-    path ||= which("brew-#{cmd}", cmd_paths)
-    path ||= which("brew-#{cmd}.rb", cmd_paths)
-
-    odie "Unknown command: #{cmd}" unless path
-    puts path
+      odie "Unknown command: #{cmd}" unless path
+      puts path
+    end
   end
 end
diff --git a/Library/Homebrew/cmd/commands.rb b/Library/Homebrew/cmd/commands.rb
index c18f254e5b6c4e11c27b3e1ec615b928ce8586a5..a4c551ab86cf6235dadff86d60c9b639a9ca716d 100644
--- a/Library/Homebrew/cmd/commands.rb
+++ b/Library/Homebrew/cmd/commands.rb
@@ -19,6 +19,7 @@ module Homebrew
              description: "Include aliases of internal commands."
       switch :verbose
       switch :debug
+      max_named 0
     end
   end
 
diff --git a/Library/Homebrew/cmd/config.rb b/Library/Homebrew/cmd/config.rb
index 1bbdbdad427d7330a58b7c3be45b99e67613aadd..a95ab42f6fcb2e96dd6ce47088269924aeae5d88 100644
--- a/Library/Homebrew/cmd/config.rb
+++ b/Library/Homebrew/cmd/config.rb
@@ -16,12 +16,12 @@ module Homebrew
       EOS
       switch :verbose
       switch :debug
+      max_named 0
     end
   end
 
   def config
     config_args.parse
-    raise UsageError unless args.remaining.empty?
 
     SystemConfig.dump_verbose_config
   end
diff --git a/Library/Homebrew/cmd/desc.rb b/Library/Homebrew/cmd/desc.rb
index 46f50430a60a6988334385497722fc54be2afdfb..1e8293be21e9ed72cee9c02672d5f47a2bf696ce 100644
--- a/Library/Homebrew/cmd/desc.rb
+++ b/Library/Homebrew/cmd/desc.rb
@@ -40,11 +40,7 @@ module Homebrew
     search_type << :either if args.search
     search_type << :name   if args.name
     search_type << :desc   if args.description
-    if search_type.size > 1
-      odie "Pick one, and only one, of -s/--search, -n/--name, or -d/--description."
-    elsif search_type.present? && ARGV.named.empty?
-      odie "You must provide a search term."
-    end
+    odie "You must provide a search term." if search_type.present? && ARGV.named.empty?
 
     results = if search_type.empty?
       raise FormulaUnspecifiedError if ARGV.named.empty?
diff --git a/Library/Homebrew/cmd/diy.rb b/Library/Homebrew/cmd/diy.rb
index 70f8e636684424af4fcc13ec9b90c87b5a5e95a8..51a7ff4c2641345eb96b34f19142582c3b1909ae 100644
--- a/Library/Homebrew/cmd/diy.rb
+++ b/Library/Homebrew/cmd/diy.rb
@@ -21,6 +21,7 @@ module Homebrew
              description: "Explicitly set the <version> of the package being installed."
       switch :verbose
       switch :debug
+      max_named 0
     end
   end
 
@@ -47,7 +48,6 @@ module Homebrew
 
   def detect_version(path)
     version = path.version.to_s
-
     raise "Couldn't determine version, set it with --version=<version>" if version.empty?
 
     version
diff --git a/Library/Homebrew/cmd/doctor.rb b/Library/Homebrew/cmd/doctor.rb
index 4494dee7fbb25c051151cee17276c92f0102429b..884c14a23db5315282f8ac74649aa911c5e571c2 100644
--- a/Library/Homebrew/cmd/doctor.rb
+++ b/Library/Homebrew/cmd/doctor.rb
@@ -18,7 +18,8 @@ module Homebrew
         an issue; just ignore this.
       EOS
       switch "--list-checks",
-             description: "List all audit methods."
+             description: "List all audit methods, which can be run individually "\
+                          "if provided as arguments."
       switch "-D", "--audit-debug",
              description: "Enable debugging and profiling of audit methods."
       switch :verbose
diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb
index cd88d5f4f7f9d7d0767872bba9c87937805a9456..72e867d1332fdd83d4d9cbb19b4f1b17ab7d0a04 100644
--- a/Library/Homebrew/cmd/gist-logs.rb
+++ b/Library/Homebrew/cmd/gist-logs.rb
@@ -28,6 +28,7 @@ module Homebrew
                           "be accessible with its link."
       switch :verbose
       switch :debug
+      max_named 1
     end
   end
 
diff --git a/Library/Homebrew/cmd/info.rb b/Library/Homebrew/cmd/info.rb
index 94a82c68b0f4da33436727e91d55803d37a20e87..4077d7f3ee8c65908f4f22c376ed103b593b8284 100644
--- a/Library/Homebrew/cmd/info.rb
+++ b/Library/Homebrew/cmd/info.rb
@@ -61,25 +61,29 @@ module Homebrew
 
   def info
     info_args.parse
+
     if args.days.present?
-      raise UsageError, "days must be one of #{VALID_DAYS.join(", ")}" unless VALID_DAYS.include?(args.days)
+      raise UsageError, "--days must be one of #{VALID_DAYS.join(", ")}" unless VALID_DAYS.include?(args.days)
     end
 
     if args.category.present?
       if ARGV.named.present? && !VALID_FORMULA_CATEGORIES.include?(args.category)
-        raise UsageError, "category must be one of #{VALID_FORMULA_CATEGORIES.join(", ")} when querying formulae"
+        raise UsageError, "--category must be one of #{VALID_FORMULA_CATEGORIES.join(", ")} when querying formulae"
       end
 
       unless VALID_CATEGORIES.include?(args.category)
-        raise UsageError, "category must be one of #{VALID_CATEGORIES.join(", ")}"
+        raise UsageError, "--category must be one of #{VALID_CATEGORIES.join(", ")}"
       end
     end
 
     if args.json
-      raise UsageError, "invalid JSON version: #{args.json}" unless ["v1", true].include? args.json
+      raise UsageError, "Invalid JSON version: #{args.json}" unless ["v1", true].include? args.json
+      raise UsageError, "This command's option requires a formula argument" if ARGV.named.empty?
 
       print_json
     elsif args.github?
+      raise UsageError, "This command's option requires a formula argument" if ARGV.named.empty?
+
       exec_browser(*Homebrew.args.formulae.map { |f| github_info(f) })
     else
       print_info
diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb
index a3c428c7543a659ae52b5c023ff19b3cab83b70e..44fb8bd961b448c39a763d9e7a32f6e72db1ac52 100644
--- a/Library/Homebrew/cmd/install.rb
+++ b/Library/Homebrew/cmd/install.rb
@@ -101,6 +101,7 @@ module Homebrew
     end
 
     install_args.parse
+
     raise FormulaUnspecifiedError if args.remaining.empty?
 
     if args.ignore_dependencies?
diff --git a/Library/Homebrew/cmd/leaves.rb b/Library/Homebrew/cmd/leaves.rb
index 18de10098320a4d7edf88695eeb369d7f11d2efd..be4fcdf559131f10ad9525b37bf35376aa16179b 100644
--- a/Library/Homebrew/cmd/leaves.rb
+++ b/Library/Homebrew/cmd/leaves.rb
@@ -15,6 +15,7 @@ module Homebrew
         List installed formulae that are not dependencies of another installed formula.
       EOS
       switch :debug
+      max_named 0
     end
   end
 
diff --git a/Library/Homebrew/cmd/link.rb b/Library/Homebrew/cmd/link.rb
index 1697be6a6e833ee77e7439071d0c88680116f622..28e29331f466b86f858054fdf464b949ab79f28e 100644
--- a/Library/Homebrew/cmd/link.rb
+++ b/Library/Homebrew/cmd/link.rb
@@ -48,7 +48,10 @@ module Homebrew
         else
           keg.name
         end
-        puts "To relink: brew unlink #{keg.name} && brew link #{name_and_flag}"
+        puts <<~EOS
+          To relink:
+            brew unlink #{keg.name} && brew link #{name_and_flag}
+        EOS
         next
       end
 
diff --git a/Library/Homebrew/cmd/log.rb b/Library/Homebrew/cmd/log.rb
index 84dab11a106a564d5825682857770ccc6dbfa53a..89b75da8747c7ddb681dcfc32c8b7254ef296a66 100644
--- a/Library/Homebrew/cmd/log.rb
+++ b/Library/Homebrew/cmd/log.rb
@@ -22,6 +22,7 @@ module Homebrew
              description: "Print only one line per commit."
       flag   "-1", "--max-count",
              description: "Print only one or a specified number of commits."
+      max_named 1
     end
   end
 
diff --git a/Library/Homebrew/cmd/missing.rb b/Library/Homebrew/cmd/missing.rb
index e89fac4c58fddea091429ef6c329e4d4522b4c39..c8e41387f7be1c16cf1bb4cd854713898e5e325e 100644
--- a/Library/Homebrew/cmd/missing.rb
+++ b/Library/Homebrew/cmd/missing.rb
@@ -27,6 +27,7 @@ module Homebrew
 
   def missing
     missing_args.parse
+
     return unless HOMEBREW_CELLAR.exist?
 
     ff = if ARGV.named.empty?
diff --git a/Library/Homebrew/cmd/outdated.rb b/Library/Homebrew/cmd/outdated.rb
index 7043769b9fc7fd012956d23cd3992ea322b2d676..c6161d8707f406dfeddcb2ddd344280d2927a681 100644
--- a/Library/Homebrew/cmd/outdated.rb
+++ b/Library/Homebrew/cmd/outdated.rb
@@ -10,7 +10,7 @@ module Homebrew
   def outdated_args
     Homebrew::CLI::Parser.new do
       usage_banner <<~EOS
-        `outdated` [<options>]
+        `outdated` [<options>] [<formula>]
 
         List installed formulae that have an updated version available. By default, version
         information is displayed in interactive shells, and suppressed otherwise.
@@ -41,7 +41,7 @@ module Homebrew
       ARGV.resolved_formulae
     end
     if args.json
-      raise UsageError, "invalid JSON version: #{args.json}" unless ["v1", true].include? args.json
+      raise UsageError, "Invalid JSON version: #{args.json}" unless ["v1", true].include? args.json
 
       outdated = print_outdated_json(formulae)
     else
diff --git a/Library/Homebrew/cmd/postinstall.rb b/Library/Homebrew/cmd/postinstall.rb
index f22f8f628949f27e9f2f99125f20dd6e4a7a0d38..fd20bec0fb771a88a0dc0e4c1ddb8facaf160191 100644
--- a/Library/Homebrew/cmd/postinstall.rb
+++ b/Library/Homebrew/cmd/postinstall.rb
@@ -23,6 +23,8 @@ module Homebrew
   def postinstall
     postinstall_args.parse
 
+    raise KegUnspecifiedError if args.remaining.empty?
+
     ARGV.resolved_formulae.each do |f|
       ohai "Postinstalling #{f}"
       fi = FormulaInstaller.new(f)
diff --git a/Library/Homebrew/cmd/readall.rb b/Library/Homebrew/cmd/readall.rb
index 1cfe6d2f326c7e4f62e9223d771a912bcc4509d0..fcece51bffd314eac124b6664ede6fb064c67201 100644
--- a/Library/Homebrew/cmd/readall.rb
+++ b/Library/Homebrew/cmd/readall.rb
@@ -14,7 +14,7 @@ module Homebrew
         Import all formulae from the specified <tap>, or from all installed taps if none is provided.
         This can be useful for debugging issues across all formulae when making
         significant changes to `formula.rb`, testing the performance of loading
-        all formulae or to determine if any current formulae have Ruby issues.
+        all formulae or checking if any current formulae have Ruby issues.
       EOS
       switch "--aliases",
              description: "Verify any alias symlinks in each tap."
diff --git a/Library/Homebrew/cmd/reinstall.rb b/Library/Homebrew/cmd/reinstall.rb
index 126cb7242a22b11f29682a8ec98223db960d8492..67acf71b4d6075b049856f8a40fddff26cae0486 100644
--- a/Library/Homebrew/cmd/reinstall.rb
+++ b/Library/Homebrew/cmd/reinstall.rb
@@ -47,6 +47,8 @@ module Homebrew
   def reinstall
     reinstall_args.parse
 
+    raise FormulaUnspecifiedError if args.remaining.empty?
+
     FormulaInstaller.prevent_build_flags unless DevelopmentTools.installed?
 
     Install.perform_preinstall_checks
diff --git a/Library/Homebrew/cmd/sh.rb b/Library/Homebrew/cmd/sh.rb
index 3a082c86cc469344b57acd70e423c15c98233c71..00f0860965791c99c88f06d36e8d5158e101907f 100644
--- a/Library/Homebrew/cmd/sh.rb
+++ b/Library/Homebrew/cmd/sh.rb
@@ -22,11 +22,13 @@ module Homebrew
              description: "Use the standard `PATH` instead of superenv's when `std` is passed."
       switch :verbose
       switch :debug
+      max_named 0
     end
   end
 
   def sh
     sh_args.parse
+
     ENV.activate_extensions!
 
     if superenv?
diff --git a/Library/Homebrew/cmd/switch.rb b/Library/Homebrew/cmd/switch.rb
index c7e3a1850a8a906ea0e9f876042b58bdbf6bc173..9d458f58b0c4c7eb39577ab32c6831bb941e080c 100644
--- a/Library/Homebrew/cmd/switch.rb
+++ b/Library/Homebrew/cmd/switch.rb
@@ -14,46 +14,33 @@ module Homebrew
 
         Symlink all of the specified <version> of <formula>'s installation into Homebrew's prefix.
       EOS
-      switch_option :verbose
-      switch_option :debug
+      switch :verbose
+      switch :debug
+      max_named 2
     end
   end
 
   def switch
     switch_args.parse
-    name = args.remaining.first
-
-    usage = "Usage: brew switch <formula> <version>"
 
-    unless name
-      onoe usage
-      exit 1
-    end
+    raise FormulaUnspecifiedError if args.remaining.empty?
 
+    name = args.remaining.first
     rack = Formulary.to_rack(name)
 
-    unless rack.directory?
-      onoe "#{name} not found in the Cellar."
-      exit 2
-    end
+    odie "#{name} not found in the Cellar." unless rack.directory?
 
     versions = rack.subdirs
                    .map { |d| Keg.new(d).version }
                    .sort
                    .join(", ")
     version = args.remaining.second
+    raise UsageError, "Specify one of #{name}'s installed versions: #{versions}" unless version
 
-    if !version || args.remaining.length > 2
-      onoe usage
-      puts "#{name} installed versions: #{versions}"
-      exit 1
-    end
-
-    unless (rack/version).directory?
-      onoe "#{name} does not have a version \"#{version}\" in the Cellar."
-      puts "#{name} installed versions: #{versions}"
-      exit 3
-    end
+    odie <<~EOS unless (rack/version).directory?
+      #{name} does not have a version \"#{version}\" in the Cellar.
+      #{name}'s installed versions: #{versions}
+    EOS
 
     # Unlink all existing versions
     rack.subdirs.each do |v|
diff --git a/Library/Homebrew/cmd/tap-info.rb b/Library/Homebrew/cmd/tap-info.rb
index 1b0d9a212dffd6efdf6d741cd7774ebbbc44a6d7..73ff8097d45d79e9cdcca228cfb6777d8ba6b63b 100644
--- a/Library/Homebrew/cmd/tap-info.rb
+++ b/Library/Homebrew/cmd/tap-info.rb
@@ -36,7 +36,7 @@ module Homebrew
     end
 
     if args.json
-      raise UsageError, "invalid JSON version: #{args.json}" unless ["v1", true].include? args.json
+      raise UsageError, "Invalid JSON version: #{args.json}" unless ["v1", true].include? args.json
 
       print_tap_json(taps.sort_by(&:to_s))
     else
diff --git a/Library/Homebrew/cmd/tap.rb b/Library/Homebrew/cmd/tap.rb
index 09deddb5cf22147cd03602419ebe60418a7bdb39..656dc20768853ad7e92a3afb2195b19669ce9b13 100644
--- a/Library/Homebrew/cmd/tap.rb
+++ b/Library/Homebrew/cmd/tap.rb
@@ -38,6 +38,7 @@ module Homebrew
       switch "-q", "--quieter",
              description: "Suppress any warnings."
       switch :debug
+      max_named 2
     end
   end
 
diff --git a/Library/Homebrew/cmd/uninstall.rb b/Library/Homebrew/cmd/uninstall.rb
index a508f94d92b8d4c62af9a123ed3362065b826a54..0f4900069ff2d0ef316dd3599dc67ddd006255af 100644
--- a/Library/Homebrew/cmd/uninstall.rb
+++ b/Library/Homebrew/cmd/uninstall.rb
@@ -79,7 +79,7 @@ module Homebrew
             if rack.directory?
               versions = rack.subdirs.map(&:basename)
               puts "#{keg.name} #{versions.to_sentence} #{"is".pluralize(versions.count)} still installed."
-              puts "Remove all versions with `brew uninstall --force #{keg.name}`."
+              puts "Run `brew uninstall --force #{keg.name}` to remove all versions."
             end
           end
         end
@@ -87,7 +87,7 @@ module Homebrew
     end
   rescue MultipleVersionsInstalledError => e
     ofail e
-    puts "Use `brew uninstall --force #{e.name}` to remove all versions."
+    puts "Run `brew uninstall --force #{e.name}` to remove all versions."
   ensure
     # If we delete Cellar/newname, then Cellar/oldname symlink
     # can become broken and we have to remove it.
diff --git a/Library/Homebrew/cmd/untap.rb b/Library/Homebrew/cmd/untap.rb
index 96ce316d1d87542b4c2a0aec38807ac1fd14803e..5dd45a2bc1e24b780c4998726d449a745abe1319 100644
--- a/Library/Homebrew/cmd/untap.rb
+++ b/Library/Homebrew/cmd/untap.rb
@@ -19,11 +19,11 @@ module Homebrew
   def untap
     untap_args.parse
 
-    raise "Usage is `brew untap <tap-name>`" if args.remaining.empty?
+    raise UsageError, "This command requires a tap argument from `brew tap`'s list" if args.remaining.empty?
 
     ARGV.named.each do |tapname|
       tap = Tap.fetch(tapname)
-      raise "untapping #{tap} is not allowed" if tap.core_tap?
+      odie "Untapping #{tap} is not allowed" if tap.core_tap?
 
       tap.uninstall
     end
diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh
index 483f770080726cdc2b861697f30241ff447156f7..745ff6372b4160e647fc251093e281dc39160203 100644
--- a/Library/Homebrew/cmd/update.sh
+++ b/Library/Homebrew/cmd/update.sh
@@ -314,7 +314,7 @@ homebrew-update() {
       *)
         odie <<EOS
 This command updates brew itself, and does not take formula names.
-Use 'brew upgrade $@' instead.
+Use \`brew upgrade $@\` instead.
 EOS
         ;;
     esac
@@ -511,7 +511,7 @@ EOS
           if [[ "$UPSTREAM_SHA_HTTP_CODE" = "404" ]]
           then
             TAP="${DIR#$HOMEBREW_LIBRARY/Taps/}"
-            echo "$TAP does not exist! Run 'brew untap $TAP'" >>"$update_failed_file"
+            echo "$TAP does not exist! Run \`brew untap $TAP\` to remove it." >>"$update_failed_file"
           else
             echo "Fetching $DIR failed!" >>"$update_failed_file"
           fi
diff --git a/Library/Homebrew/dev-cmd/audit.rb b/Library/Homebrew/dev-cmd/audit.rb
index 1dda5cb067799309248af4e558c8cf26f4dc8388..2b43cba6cec7ba63d77a9f584801773b976f69b5 100644
--- a/Library/Homebrew/dev-cmd/audit.rb
+++ b/Library/Homebrew/dev-cmd/audit.rb
@@ -57,7 +57,8 @@ module Homebrew
       switch :verbose
       switch :debug
       conflicts "--only", "--except"
-      conflicts "--only-cops", "--except-cops"
+      conflicts "--only-cops", "--except-cops", "--strict"
+      conflicts "--only-cops", "--except-cops", "--only"
     end
   end
 
@@ -88,13 +89,6 @@ module Homebrew
 
     only_cops = args.only_cops
     except_cops = args.except_cops
-
-    if only_cops && except_cops
-      odie "--only-cops and --except-cops cannot be used simultaneously!"
-    elsif (only_cops || except_cops) && (strict || args.only)
-      odie "--only-cops/--except-cops and --strict/--only cannot be used simultaneously!"
-    end
-
     options = { fix: args.fix? }
 
     if only_cops
@@ -995,7 +989,6 @@ module Homebrew
     def audit
       only_audits = @only
       except_audits = @except
-      odie "--only and --except cannot be used simultaneously!" if only_audits && except_audits
 
       methods.map(&:to_s).grep(/^audit_/).each do |audit_method_name|
         name = audit_method_name.gsub(/^audit_/, "")
diff --git a/Library/Homebrew/dev-cmd/bottle.rb b/Library/Homebrew/dev-cmd/bottle.rb
index 8f1f8c81f5ed75a6bfbd6cc2549f0a23abaafb59..25d073e8a82a7fb7ac61150da0d1242605cce23d 100644
--- a/Library/Homebrew/dev-cmd/bottle.rb
+++ b/Library/Homebrew/dev-cmd/bottle.rb
@@ -86,6 +86,7 @@ module Homebrew
     bottle_args.parse
 
     return merge if args.merge?
+    raise KegUnspecifiedError if args.remaining.empty?
 
     ensure_relocation_formulae_installed! unless args.skip_relocation?
     ARGV.resolved_formulae.each do |f|
@@ -219,7 +220,7 @@ module Homebrew
       return
     end
 
-    return ofail "Formula not installed with '--build-bottle': #{f.full_name}" unless Utils::Bottles.built_as? f
+    return ofail "Formula was not installed with --build-bottle: #{f.full_name}" unless Utils::Bottles.built_as? f
 
     return ofail "Formula has no stable version: #{f.full_name}" unless f.stable
 
@@ -426,6 +427,7 @@ module Homebrew
 
   def merge
     write = args.write?
+    raise UsageError, "--merge requires a JSON file path argument" if ARGV.named.empty?
 
     bottles_hash = ARGV.named.reduce({}) do |hash, json_file|
       hash.deep_merge(JSON.parse(IO.read(json_file)))
diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb
index e984152e78d12e4e455c4edd7cd8a41b5e2fb8da..2b16fb8c225e31fc31b8d3d18472677a6552af8d 100644
--- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb
+++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb
@@ -65,6 +65,7 @@ module Homebrew
       switch :debug
       conflicts "--no-audit", "--strict"
       conflicts "--url", "--tag"
+      max_named 1
     end
   end
 
@@ -504,6 +505,6 @@ module Homebrew
 
     formula.path.atomic_write(backup_file)
     FileUtils.mv alias_rename.last, alias_rename.first if alias_rename.present?
-    odie "brew audit failed!"
+    odie "`brew audit` failed!"
   end
 end
diff --git a/Library/Homebrew/dev-cmd/bump-revision.rb b/Library/Homebrew/dev-cmd/bump-revision.rb
index ef5f4aee7bab7aec04152a265355b34603489bc6..8c186fe47a7f4c5df6a3fc4225f66d8a863f3685 100644
--- a/Library/Homebrew/dev-cmd/bump-revision.rb
+++ b/Library/Homebrew/dev-cmd/bump-revision.rb
@@ -22,6 +22,7 @@ module Homebrew
       switch :quiet
       switch :verbose
       switch :debug
+      max_named 1
     end
   end
 
@@ -34,7 +35,6 @@ module Homebrew
 
     formulae = Homebrew.args.formulae
     raise FormulaUnspecifiedError if formulae.empty?
-    raise "Multiple formulae given, only one is allowed." if formulae.length > 1
 
     formula = formulae.first
     current_revision = formula.revision
diff --git a/Library/Homebrew/dev-cmd/create.rb b/Library/Homebrew/dev-cmd/create.rb
index 9c56aa8f164f79762b5c5f823786bc40b5164b0f..c3e4c660acd817b069a88b26877357f631125efc 100644
--- a/Library/Homebrew/dev-cmd/create.rb
+++ b/Library/Homebrew/dev-cmd/create.rb
@@ -49,6 +49,7 @@ module Homebrew
       switch :verbose
       switch :debug
       conflicts "--autotools", "--cmake", "--go", "--meson", "--perl", "--python", "--rust"
+      max_named 1
     end
   end
 
diff --git a/Library/Homebrew/dev-cmd/extract.rb b/Library/Homebrew/dev-cmd/extract.rb
index a5a8443cd91b8ce904321913dd5e4cda37103884..4a511a8184d85af3c2b245770dbbf74eb8c27b0f 100644
--- a/Library/Homebrew/dev-cmd/extract.rb
+++ b/Library/Homebrew/dev-cmd/extract.rb
@@ -91,6 +91,7 @@ module Homebrew
              description: "Extract the specified <version> of <formula> instead of the most recent."
       switch :force
       switch :debug
+      max_named 2
     end
   end
 
@@ -98,7 +99,7 @@ module Homebrew
     extract_args.parse
 
     # Expect exactly two named arguments: formula and tap
-    raise UsageError if args.remaining.length != 2
+    raise UsageError, "This command requires formula and tap arguments" if args.remaining.length != 2
 
     if args.remaining.first !~ HOMEBREW_TAP_FORMULA_REGEX
       name = args.remaining.first.downcase
diff --git a/Library/Homebrew/dev-cmd/install-bundler-gems.rb b/Library/Homebrew/dev-cmd/install-bundler-gems.rb
index 421b94207432ea79092f6ecc7671a74f8d797172..66aeb1087d13a74952a61fd3a2885d72de605ee6 100644
--- a/Library/Homebrew/dev-cmd/install-bundler-gems.rb
+++ b/Library/Homebrew/dev-cmd/install-bundler-gems.rb
@@ -14,6 +14,7 @@ module Homebrew
         Install Homebrew's Bundler gems.
       EOS
       switch :debug
+      max_named 0
     end
   end
 
diff --git a/Library/Homebrew/dev-cmd/man.rb b/Library/Homebrew/dev-cmd/man.rb
index e453cc2ffb7c313d80e5f8d59f709e8affac4666..db541ed9ae1d290619b1606a474f57802cd01fd0 100644
--- a/Library/Homebrew/dev-cmd/man.rb
+++ b/Library/Homebrew/dev-cmd/man.rb
@@ -28,14 +28,13 @@ module Homebrew
                           "comparison without factoring in the date)."
       switch "--link",
              description: "This is now done automatically by `brew update`."
+      max_named 0
     end
   end
 
   def man
     man_args.parse
 
-    raise UsageError unless ARGV.named.empty?
-
     odie "`brew man --link` is now done automatically by `brew update`." if args.link?
 
     regenerate_man_pages
diff --git a/Library/Homebrew/dev-cmd/mirror.rb b/Library/Homebrew/dev-cmd/mirror.rb
index 464d96b5b1cd8213e47c51dda42e21b0e5fc84e7..d042367d4b26f72296d63c0ef0ce4dd0b236d250 100644
--- a/Library/Homebrew/dev-cmd/mirror.rb
+++ b/Library/Homebrew/dev-cmd/mirror.rb
@@ -21,7 +21,7 @@ module Homebrew
   def mirror
     mirror_args.parse
 
-    odie "This command requires at least one formula argument!" if ARGV.named.empty?
+    raise FormulaUnspecifiedError if args.remaining.empty?
 
     bintray_user = ENV["HOMEBREW_BINTRAY_USER"]
     bintray_key = ENV["HOMEBREW_BINTRAY_KEY"]
diff --git a/Library/Homebrew/dev-cmd/pull.rb b/Library/Homebrew/dev-cmd/pull.rb
index 2233659189ec61f4bd433791c057648f186741be..93505328e5771614642c83ddef2dc48124dbf53a 100644
--- a/Library/Homebrew/dev-cmd/pull.rb
+++ b/Library/Homebrew/dev-cmd/pull.rb
@@ -70,7 +70,9 @@ module Homebrew
 
     pull_args.parse
 
-    odie "This command requires at least one argument containing a URL or pull request number" if ARGV.named.empty?
+    if ARGV.named.empty?
+      raise UsageError, "This command requires at least one argument containing a URL or pull request number"
+    end
 
     # Passthrough Git environment variables for e.g. git am
     ENV["GIT_COMMITTER_NAME"] = ENV["HOMEBREW_GIT_NAME"] if ENV["HOMEBREW_GIT_NAME"]
@@ -107,7 +109,7 @@ module Homebrew
         end
         _, testing_job = *testing_match
         url = "https://github.com/Homebrew/homebrew-#{tap.repo}/compare/master...BrewTestBot:testing-#{testing_job}"
-        odie "Testing URLs require `--bottle`!" unless args.bottle?
+        odie "--bottle is required for testing job URLs!" unless args.bottle?
       elsif (api_match = arg.match HOMEBREW_PULL_API_REGEX)
         _, user, repo, issue = *api_match
         url = "https://github.com/#{user}/#{repo}/pull/#{issue}"
@@ -277,7 +279,7 @@ module Homebrew
     elsif patch_changes[:formulae].length > 1
       odie "Can only bump one changed formula; bumped #{patch_changes[:formulae]}"
     elsif !patch_changes[:others].empty?
-      odie "Can not bump if non-formula files are changed"
+      odie "Cannot bump if non-formula files are changed"
     end
   end
 
diff --git a/Library/Homebrew/dev-cmd/release-notes.rb b/Library/Homebrew/dev-cmd/release-notes.rb
index 337147d28b79a1f92f7fa34f402d4a950bb3d404..5a806e4906124c6879f1bdb914ccd8d5e13e30e3 100644
--- a/Library/Homebrew/dev-cmd/release-notes.rb
+++ b/Library/Homebrew/dev-cmd/release-notes.rb
@@ -16,6 +16,7 @@ module Homebrew
       EOS
       switch "--markdown",
              description: "Print as a Markdown list."
+      max_named 2
     end
   end
 
diff --git a/Library/Homebrew/dev-cmd/tap-new.rb b/Library/Homebrew/dev-cmd/tap-new.rb
index 23d4a9fe64830f4f10d09330e0d062bb00f41691..e4e9e268f29862c3ef5a04e83eaf9ffd07462227 100644
--- a/Library/Homebrew/dev-cmd/tap-new.rb
+++ b/Library/Homebrew/dev-cmd/tap-new.rb
@@ -15,13 +15,14 @@ module Homebrew
       EOS
       switch :verbose
       switch :debug
+      max_named 1
     end
   end
 
   def tap_new
     tap_new_args.parse
 
-    raise "A tap argument is required" if ARGV.named.empty?
+    raise UsageError, "This command requires a tap argument" if ARGV.named.empty?
 
     tap = Tap.fetch(ARGV.named.first)
     titleized_user = tap.user.dup
diff --git a/Library/Homebrew/dev-cmd/tests.rb b/Library/Homebrew/dev-cmd/tests.rb
index 96ceaef4892333040e239766167e0f8944215b74..18bff0c88b51ae3ca1045154659fa11701b80ba5 100644
--- a/Library/Homebrew/dev-cmd/tests.rb
+++ b/Library/Homebrew/dev-cmd/tests.rb
@@ -29,6 +29,7 @@ module Homebrew
              description: "Randomise tests with the specified <value> instead of a random seed."
       switch :verbose
       switch :debug
+      max_named 0
     end
   end
 
diff --git a/Library/Homebrew/dev-cmd/update-test.rb b/Library/Homebrew/dev-cmd/update-test.rb
index 8f1acd3b4dae3e6823fbe54d0166307d23822f33..fdf208dd4946ef85fbf95b71d537a15b95fa77c8 100644
--- a/Library/Homebrew/dev-cmd/update-test.rb
+++ b/Library/Homebrew/dev-cmd/update-test.rb
@@ -23,6 +23,7 @@ module Homebrew
              description: "Use the commit at the specified <date> as the start commit."
       switch :verbose
       switch :debug
+      max_named 0
     end
   end
 
@@ -88,7 +89,7 @@ module Homebrew
     chdir "update-test" do
       curdir = Pathname.new(Dir.pwd)
 
-      oh1 "Setup test environment..."
+      oh1 "Preparing test environment..."
       # copy Homebrew installation
       safe_system "git", "clone", "#{HOMEBREW_REPOSITORY}/.git", ".",
                   "--branch", "master", "--single-branch"
diff --git a/Library/Homebrew/dev-cmd/vendor-gems.rb b/Library/Homebrew/dev-cmd/vendor-gems.rb
index b5f720af92c0b5dab8e3d5843f470caaede8a8da..428223e38a27be0fdb1135b209322f8551c80a84 100644
--- a/Library/Homebrew/dev-cmd/vendor-gems.rb
+++ b/Library/Homebrew/dev-cmd/vendor-gems.rb
@@ -14,6 +14,7 @@ module Homebrew
         Install and commit Homebrew's vendored gems.
       EOS
       switch :debug
+      max_named 0
     end
   end
 
diff --git a/docs/Manpage.md b/docs/Manpage.md
index f8ce7fd0c67d8849d771afbf211a56a9070b8d9a..0c664701d218c65e48aedca494103c4f5481169e 100644
--- a/docs/Manpage.md
+++ b/docs/Manpage.md
@@ -67,7 +67,7 @@ this for the given formulae and casks.
 * `-n`, `--dry-run`:
   Show what would be removed, but do not actually remove anything.
 * `-s`:
-  Scrub the cache, including downloads for even the latest versions. Note downloads for any installed formula or cask will still not be deleted. If you want to delete those too: `rm -rf "$(brew --cache)"`
+  Scrub the cache, including downloads for even the latest versions. Note downloads for any installed formulae or casks will still not be deleted. If you want to delete those too: `rm -rf "$(brew --cache)"`
 * `--prune-prefix`:
   Only prune the symlinks and directories from the prefix and remove no other files.
 
@@ -157,7 +157,7 @@ everything you use Homebrew for is working fine: please don't worry or file an
 issue; just ignore this.
 
 * `--list-checks`:
-  List all audit methods.
+  List all audit methods, which can be run individually if provided as arguments.
 * `-D`, `--audit-debug`:
   Enable debugging and profiling of audit methods.
 
@@ -355,7 +355,7 @@ Show install options specific to *`formula`*.
 * `--all`:
   Show options for all available formulae.
 
-### `outdated` [*`options`*]
+### `outdated` [*`options`*] [*`formula`*]
 
 List installed formulae that have an updated version available. By default,
 version information is displayed in interactive shells, and suppressed
@@ -384,7 +384,7 @@ Rerun the post-install steps for *`formula`*.
 Import all formulae from the specified *`tap`*, or from all installed taps if none
 is provided. This can be useful for debugging issues across all formulae when
 making significant changes to `formula.rb`, testing the performance of loading
-all formulae or to determine if any current formulae have Ruby issues.
+all formulae or checking if any current formulae have Ruby issues.
 
 * `--aliases`:
   Verify any alias symlinks in each tap.
@@ -644,7 +644,7 @@ directory doesn't exist, `$(brew --repository)/Cellar`.
 If *`formula`* is provided, display the location in the cellar where *`formula`*
 would be installed, without any sort of versioned directory as the last path.
 
-### `--env` [*`options`*]
+### `--env` [*`options`*] [*`formula`*]
 
 Summarise Homebrew's build environment as a plain list.
 
diff --git a/manpages/brew-cask.1 b/manpages/brew-cask.1
index 4abd0bad838cc1f0e119d2441a7cf56e3e798170..eb0c37fa05b63f34018a3a8fa458483722ae73b9 100644
--- a/manpages/brew-cask.1
+++ b/manpages/brew-cask.1
@@ -1,7 +1,7 @@
 .\" generated with Ronn/v0.7.3
 .\" http://github.com/rtomayko/ronn/tree/0.7.3
 .
-.TH "BREW\-CASK" "1" "November 2019" "Homebrew" "brew-cask"
+.TH "BREW\-CASK" "1" "December 2019" "Homebrew" "brew-cask"
 .
 .SH "NAME"
 \fBbrew\-cask\fR \- a friendly binary installer for macOS
diff --git a/manpages/brew.1 b/manpages/brew.1
index 9b7d29e5b441c27d0ed2d5626726c720b220101e..7cca55a2eb888203f1010714e8a3e904c9a97cb6 100644
--- a/manpages/brew.1
+++ b/manpages/brew.1
@@ -1,7 +1,7 @@
 .\" generated with Ronn/v0.7.3
 .\" http://github.com/rtomayko/ronn/tree/0.7.3
 .
-.TH "BREW" "1" "November 2019" "Homebrew" "brew"
+.TH "BREW" "1" "December 2019" "Homebrew" "brew"
 .
 .SH "NAME"
 \fBbrew\fR \- The missing package manager for macOS
@@ -63,7 +63,7 @@ Show what would be removed, but do not actually remove anything\.
 .
 .TP
 \fB\-s\fR
-Scrub the cache, including downloads for even the latest versions\. Note downloads for any installed formula or cask will still not be deleted\. If you want to delete those too: \fBrm \-rf "$(brew \-\-cache)"\fR
+Scrub the cache, including downloads for even the latest versions\. Note downloads for any installed formulae or casks will still not be deleted\. If you want to delete those too: \fBrm \-rf "$(brew \-\-cache)"\fR
 .
 .TP
 \fB\-\-prune\-prefix\fR
@@ -176,7 +176,7 @@ Check your system for potential problems\. Will exit with a non\-zero status if
 .
 .TP
 \fB\-\-list\-checks\fR
-List all audit methods\.
+List all audit methods, which can be run individually if provided as arguments\.
 .
 .TP
 \fB\-D\fR, \fB\-\-audit\-debug\fR
@@ -467,7 +467,7 @@ Show options for formulae that are currently installed\.
 \fB\-\-all\fR
 Show options for all available formulae\.
 .
-.SS "\fBoutdated\fR [\fIoptions\fR]"
+.SS "\fBoutdated\fR [\fIoptions\fR] [\fIformula\fR]"
 List installed formulae that have an updated version available\. By default, version information is displayed in interactive shells, and suppressed otherwise\.
 .
 .TP
@@ -493,7 +493,7 @@ Pin the specified \fIformula\fR, preventing them from being upgraded when issuin
 Rerun the post\-install steps for \fIformula\fR\.
 .
 .SS "\fBreadall\fR [\fIoptions\fR] [\fItap\fR]"
-Import all formulae from the specified \fItap\fR, or from all installed taps if none is provided\. This can be useful for debugging issues across all formulae when making significant changes to \fBformula\.rb\fR, testing the performance of loading all formulae or to determine if any current formulae have Ruby issues\.
+Import all formulae from the specified \fItap\fR, or from all installed taps if none is provided\. This can be useful for debugging issues across all formulae when making significant changes to \fBformula\.rb\fR, testing the performance of loading all formulae or checking if any current formulae have Ruby issues\.
 .
 .TP
 \fB\-\-aliases\fR
@@ -812,7 +812,7 @@ Display Homebrew\'s Cellar path\. \fIDefault:\fR \fB$(brew \-\-prefix)/Cellar\fR
 .P
 If \fIformula\fR is provided, display the location in the cellar where \fIformula\fR would be installed, without any sort of versioned directory as the last path\.
 .
-.SS "\fB\-\-env\fR [\fIoptions\fR]"
+.SS "\fB\-\-env\fR [\fIoptions\fR] [\fIformula\fR]"
 Summarise Homebrew\'s build environment as a plain list\.
 .
 .P