diff --git a/Library/Homebrew/cask/lib/hbc.rb b/Library/Homebrew/cask/lib/hbc.rb
index 9c8c67f518b517e1630afa92a09b85273265e4ad..737c930d10704f805929e8e0c766b14cd0c5ead3 100644
--- a/Library/Homebrew/cask/lib/hbc.rb
+++ b/Library/Homebrew/cask/lib/hbc.rb
@@ -15,13 +15,11 @@ require "hbc/download"
 require "hbc/download_strategy"
 require "hbc/exceptions"
 require "hbc/installer"
-require "hbc/config"
 require "hbc/macos"
 require "hbc/pkg"
 require "hbc/staged"
 require "hbc/system_command"
 require "hbc/topological_hash"
-require "hbc/url"
 require "hbc/utils"
 require "hbc/verify"
 require "hbc/version"
diff --git a/Library/Homebrew/cask/lib/hbc/cask.rb b/Library/Homebrew/cask/lib/hbc/cask.rb
index d41e2d52217054d2886f2af37512399998b70512..ca8e51db0dc42af7c87afb7cb677d9b15dac5a98 100644
--- a/Library/Homebrew/cask/lib/hbc/cask.rb
+++ b/Library/Homebrew/cask/lib/hbc/cask.rb
@@ -1,4 +1,5 @@
 require "hbc/cask_loader"
+require "hbc/config"
 require "hbc/dsl"
 require "hbc/metadata"
 require "searchable"
diff --git a/Library/Homebrew/cask/lib/hbc/cli.rb b/Library/Homebrew/cask/lib/hbc/cli.rb
index 975f8a7dfd6366e06d4f2f73e2d81ca2baba6174..df3271a5d992be2b746943de86ddc1f39cd225f3 100644
--- a/Library/Homebrew/cask/lib/hbc/cli.rb
+++ b/Library/Homebrew/cask/lib/hbc/cli.rb
@@ -2,6 +2,9 @@ require "optparse"
 require "shellwords"
 
 require "extend/optparse"
+
+require "hbc/config"
+
 require "hbc/cli/options"
 
 require "hbc/cli/abstract_command"
diff --git a/Library/Homebrew/cask/lib/hbc/container.rb b/Library/Homebrew/cask/lib/hbc/container.rb
index fab3a3c1c36c6e8e5ee30d0b8b60d353b7344735..3806df33f65998ec6cb46d73f2f34830c40347f4 100644
--- a/Library/Homebrew/cask/lib/hbc/container.rb
+++ b/Library/Homebrew/cask/lib/hbc/container.rb
@@ -1,3 +1,5 @@
+require "hbc/utils"
+
 require "hbc/container/base"
 require "hbc/container/air"
 require "hbc/container/bzip2"
diff --git a/Library/Homebrew/cask/lib/hbc/dsl.rb b/Library/Homebrew/cask/lib/hbc/dsl.rb
index 7492b59017d7b18fb673e2299673ac1ac0eb3324..5ed0fb5e99c6df649df24f00547b9e31949cf5f9 100644
--- a/Library/Homebrew/cask/lib/hbc/dsl.rb
+++ b/Library/Homebrew/cask/lib/hbc/dsl.rb
@@ -2,6 +2,9 @@ require "locale"
 
 require "hbc/artifact"
 
+require "hbc/caskroom"
+require "hbc/exceptions"
+
 require "hbc/dsl/appcast"
 require "hbc/dsl/base"
 require "hbc/dsl/caveats"
@@ -16,6 +19,8 @@ require "hbc/dsl/uninstall_postflight"
 require "hbc/dsl/uninstall_preflight"
 require "hbc/dsl/version"
 
+require "hbc/url"
+
 module Hbc
   class DSL
     ORDINARY_ARTIFACT_CLASSES = [
diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb
index dd45fe63adfd2d98a2de41d6c729b90c0204ffcf..a6117b5029c6d1d38151bffb031e9166b41d7cc3 100644
--- a/Library/Homebrew/cmd/search.rb
+++ b/Library/Homebrew/cmd/search.rb
@@ -18,6 +18,7 @@ require "missing_formula"
 require "descriptions"
 require "cli_parser"
 require "search"
+require "hbc/cask_loader"
 
 module Homebrew
   module_function
@@ -58,32 +59,57 @@ module Homebrew
       query = args.remaining.join(" ")
       string_or_regex = query_regexp(query)
       Descriptions.search(string_or_regex, :desc).print
-    elsif args.remaining.first =~ HOMEBREW_TAP_FORMULA_REGEX
-      query = args.remaining.first
+    else
+      query = args.remaining.join(" ")
+      string_or_regex = query_regexp(query)
 
-      results = begin
-        [Formulary.factory(query).name]
-      rescue FormulaUnavailableError
+      remote_results = if query.match?(HOMEBREW_TAP_FORMULA_REGEX) || query.match?(HOMEBREW_TAP_CASK_REGEX)
         _, _, name = query.split("/", 3)
-        remote_results = search_taps(name)
-        [*remote_results[:formulae], *remote_results[:casks]].sort
+        search_taps(name, silent: true)
+      else
+        search_taps(query, silent: true)
       end
 
-      puts Formatter.columns(results) unless results.empty?
-    else
-      query = args.remaining.join(" ")
-      string_or_regex = query_regexp(query)
-      local_results = search_formulae(string_or_regex)
-      puts Formatter.columns(local_results.sort) unless local_results.empty?
+      local_formulae = if query.match?(HOMEBREW_TAP_FORMULA_REGEX)
+        begin
+          [Formulary.factory(query).name]
+        rescue FormulaUnavailableError
+          []
+        end
+      else
+        search_formulae(string_or_regex)
+      end
 
-      remote_results = search_taps(query)
-      tap_results = [*remote_results[:formulae], *remote_results[:casks]].sort
-      puts Formatter.columns(tap_results) unless tap_results.empty?
+      remote_formulae = remote_results[:formulae]
+      all_formulae = local_formulae + remote_formulae
+
+      local_casks = if query.match?(HOMEBREW_TAP_CASK_REGEX)
+        begin
+          [Hbc::CaskLoader.load(query).token]
+        rescue Hbc::CaskUnavailableError
+          []
+        end
+      else
+        search_casks(string_or_regex)
+      end
+
+      remote_casks = remote_results[:casks]
+      all_casks = local_casks + remote_casks
+
+      if all_formulae.any?
+        ohai "Formulae"
+        puts Formatter.columns(all_formulae)
+      end
+
+      if all_casks.any?
+        puts if all_formulae.any?
+        ohai "Casks"
+        puts Formatter.columns(all_casks)
+      end
 
       if $stdout.tty?
-        count = local_results.length + tap_results.length
+        count = all_formulae.count + all_casks.count
 
-        ohai "Searching blacklisted, migrated and deleted formulae..."
         if reason = MissingFormula.reason(query, silent: true)
           if count.positive?
             puts
@@ -91,7 +117,7 @@ module Homebrew
           end
           puts reason
         elsif count.zero?
-          puts "No formula found for #{query.inspect}."
+          puts "No formula or cask found for #{query.inspect}."
           GitHub.print_pull_requests_matching(query)
         end
       end
diff --git a/Library/Homebrew/search.rb b/Library/Homebrew/search.rb
index 736a854f81d5a245d435f886ec5a6b43fabbddb3..f43edaf87199920bbc75daca812443b551275e5f 100644
--- a/Library/Homebrew/search.rb
+++ b/Library/Homebrew/search.rb
@@ -40,7 +40,7 @@ module Homebrew
         tap = Tap.fetch(match["repository"]["full_name"])
         full_name = "#{tap.name}/#{name}"
 
-        next if tap.installed? && !match["path"].start_with?("Casks/")
+        next if tap.installed?
 
         if match["path"].start_with?("Casks/")
           results[:casks] = [*results[:casks], full_name].sort
@@ -53,9 +53,6 @@ module Homebrew
     end
 
     def search_formulae(string_or_regex)
-      # Use stderr to avoid breaking parsed output
-      $stderr.puts Formatter.headline("Searching local taps...", color: :blue)
-
       aliases = Formula.alias_full_names
       results = (Formula.full_names + aliases)
                 .extend(Searchable)
diff --git a/Library/Homebrew/test/cmd/search_spec.rb b/Library/Homebrew/test/cmd/search_spec.rb
index 556c863ca210f3295ade8f2b260dce74ea5346cf..cae8e97fdcc8fa67a987fc48b49ba32744aef499 100644
--- a/Library/Homebrew/test/cmd/search_spec.rb
+++ b/Library/Homebrew/test/cmd/search_spec.rb
@@ -15,7 +15,6 @@ describe "brew search", :integration_test do
   it "supports searching by name" do
     expect { brew "search", "testball" }
       .to output(/testball/).to_stdout
-      .and output(/Searching/).to_stderr
       .and be_a_success
   end
 
@@ -26,12 +25,11 @@ describe "brew search", :integration_test do
       .and be_a_success
   end
 
-  it "falls back to a GitHub tap search when no formula is found", :needs_network, retry: 3 do
+  it "falls back to a GitHub tap search when no formula is found", :needs_macos, :needs_network, retry: 3 do
     setup_remote_tap "homebrew/cask"
 
     expect { brew "search", "homebrew/cask/firefox" }
       .to output(/firefox/).to_stdout
-      .and output(/Searching/).to_stderr
       .and be_a_success
   end