diff --git a/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php b/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php
index 4c4eed85b9..ed2e1df3e2 100644
--- a/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php
+++ b/src/applications/repository/management/PhabricatorRepositoryManagementThawWorkflow.php
@@ -1,224 +1,278 @@
 <?php
 
 final class PhabricatorRepositoryManagementThawWorkflow
   extends PhabricatorRepositoryManagementWorkflow {
 
   protected function didConstruct() {
     $this
       ->setName('thaw')
       ->setExamples('**thaw** [options] __repository__ ...')
       ->setSynopsis(
         pht(
           'Resolve issues with frozen cluster repositories. Very advanced '.
           'and dangerous.'))
       ->setArguments(
         array(
           array(
             'name' => 'demote',
             'param' => 'device',
             'help' => pht(
               'Demote a device, discarding local changes. Clears stuck '.
               'write locks and recovers from lost leaders.'),
           ),
           array(
             'name' => 'promote',
             'param' => 'device',
             'help' => pht(
               'Promote a device, discarding changes on other devices. '.
               'Resolves ambiguous leadership and recovers from demotion '.
               'mistakes.'),
           ),
           array(
             'name' => 'force',
             'help' => pht('Run operations without asking for confirmation.'),
           ),
+          array(
+            'name' => 'all-repositories',
+            'help' => pht(
+              'Apply the promotion or demotion to all repositories hosted '.
+              'on the device.'),
+          ),
           array(
             'name' => 'repositories',
             'wildcard' => true,
           ),
         ));
   }
 
   public function execute(PhutilArgumentParser $args) {
     $viewer = $this->getViewer();
 
-    $repositories = $this->loadRepositories($args, 'repositories');
-    if (!$repositories) {
-      throw new PhutilArgumentUsageException(
-        pht('Specify one or more repositories to thaw.'));
-    }
-
     $promote = $args->getArg('promote');
     $demote = $args->getArg('demote');
 
     if (!$promote && !$demote) {
       throw new PhutilArgumentUsageException(
         pht('You must choose a device to --promote or --demote.'));
     }
 
     if ($promote && $demote) {
       throw new PhutilArgumentUsageException(
         pht('Specify either --promote or --demote, but not both.'));
     }
 
     $device_name = nonempty($promote, $demote);
 
     $device = id(new AlmanacDeviceQuery())
       ->setViewer($viewer)
       ->withNames(array($device_name))
       ->executeOne();
     if (!$device) {
       throw new PhutilArgumentUsageException(
         pht('No device "%s" exists.', $device_name));
     }
 
+    $repository_names = $args->getArg('repositories');
+    $all_repositories = $args->getArg('all-repositories');
+    if ($repository_names && $all_repositories) {
+      throw new PhutilArgumentUsageException(
+        pht(
+          'Specify a list of repositories or "--all-repositories", '.
+          'but not both.'));
+    } else if (!$repository_names && !$all_repositories) {
+      throw new PhutilArgumentUsageException(
+        pht(
+          'Select repositories to affect by providing a list of repositories '.
+          'or using the "--all-repositories" flag.'));
+    }
+
+    if ($repository_names) {
+      $repositories = $this->loadRepositories($args, 'repositories');
+      if (!$repositories) {
+        throw new PhutilArgumentUsageException(
+          pht('Specify one or more repositories to thaw.'));
+      }
+    } else {
+      $repositories = array();
+
+      $services = id(new AlmanacServiceQuery())
+        ->setViewer($viewer)
+        ->withDevicePHIDs(array($device->getPHID()))
+        ->execute();
+      if ($services) {
+        $repositories = id(new PhabricatorRepositoryQuery())
+          ->setViewer($viewer)
+          ->withAlmanacServicePHIDs(mpull($services, 'getPHID'))
+          ->execute();
+      }
+
+      if (!$repositories) {
+        throw new PhutilArgumentUsageException(
+          pht('There are no repositories on the selected device.'));
+      }
+    }
+
+    $display_list = new PhutilConsoleList();
+    foreach ($repositories as $repository) {
+      $display_list->addItem(
+        pht(
+          '%s %s',
+          $repository->getMonogram(),
+          $repository->getName()));
+    }
+
+    echo tsprintf(
+      "%s\n\n%B\n",
+      pht('These repositories will be thawed:'),
+      $display_list->drawConsoleString());
+
     if ($promote) {
       $risk_message = pht(
         'Promoting a device can cause the loss of any repository data which '.
         'only exists on other devices. The version of the repository on the '.
         'promoted device will become authoritative.');
     } else {
       $risk_message = pht(
         'Demoting a device can cause the loss of any repository data which '.
         'only exists on the demoted device. The version of the repository '.
         'on some other device will become authoritative.');
     }
 
     echo tsprintf(
       "**<bg:red> %s </bg>** %s\n",
       pht('DATA AT RISK'),
       $risk_message);
 
     $is_force = $args->getArg('force');
     $prompt = pht('Accept the possibility of permanent data loss?');
     if (!$is_force && !phutil_console_confirm($prompt)) {
       throw new PhutilArgumentUsageException(
         pht('User aborted the workflow.'));
     }
 
     foreach ($repositories as $repository) {
       $repository_phid = $repository->getPHID();
 
       $write_lock = PhabricatorRepositoryWorkingCopyVersion::getWriteLock(
         $repository_phid);
 
       echo tsprintf(
         "%s\n",
         pht(
           'Waiting to acquire write lock for "%s"...',
           $repository->getDisplayName()));
 
       $write_lock->lock(phutil_units('5 minutes in seconds'));
       try {
 
         $service = $repository->loadAlmanacService();
         if (!$service) {
           throw new PhutilArgumentUsageException(
             pht(
               'Repository "%s" is not a cluster repository: it is not '.
               'bound to an Almanac service.',
               $repository->getDisplayName()));
         }
 
         if ($promote) {
           // You can only promote active devices. (You may demote active or
           // inactive devices.)
           $bindings = $service->getActiveBindings();
           $bindings = mpull($bindings, null, 'getDevicePHID');
           if (empty($bindings[$device->getPHID()])) {
             throw new PhutilArgumentUsageException(
               pht(
                 'Repository "%s" has no active binding to device "%s". Only '.
                 'actively bound devices can be promoted.',
                 $repository->getDisplayName(),
                 $device->getName()));
           }
 
           $versions = PhabricatorRepositoryWorkingCopyVersion::loadVersions(
             $repository->getPHID());
           $versions = mpull($versions, null, 'getDevicePHID');
 
           // Before we promote, make sure there are no outstanding versions on
           // devices with inactive bindings. If there are, you need to demote
           // these first.
           $inactive = array();
           foreach ($versions as $device_phid => $version) {
             if (isset($bindings[$device_phid])) {
               continue;
             }
             $inactive[$device_phid] = $version;
           }
 
           if ($inactive) {
             $handles = $viewer->loadHandles(array_keys($inactive));
 
             $handle_list = iterator_to_array($handles);
             $handle_list = mpull($handle_list, 'getName');
             $handle_list = implode(', ', $handle_list);
 
             throw new PhutilArgumentUsageException(
               pht(
                 'Repository "%s" has versions on inactive devices. Demote '.
                 '(or reactivate) these devices before promoting a new '.
                 'leader: %s.',
                 $repository->getDisplayName(),
                 $handle_list));
           }
 
           // Now, make sure there are no outstanding versions on devices with
           // active bindings. These also need to be demoted (or promoting is a
           // mistake or already happened).
           $active = array_select_keys($versions, array_keys($bindings));
           if ($active) {
             $handles = $viewer->loadHandles(array_keys($active));
 
             $handle_list = iterator_to_array($handles);
             $handle_list = mpull($handle_list, 'getName');
             $handle_list = implode(', ', $handle_list);
 
             throw new PhutilArgumentUsageException(
               pht(
                 'Unable to promote "%s" for repository "%s" because this '.
                 'cluster already has one or more unambiguous leaders: %s.',
                 $device->getName(),
                 $repository->getDisplayName(),
                 $handle_list));
           }
 
           PhabricatorRepositoryWorkingCopyVersion::updateVersion(
             $repository->getPHID(),
             $device->getPHID(),
             0);
 
           echo tsprintf(
             "%s\n",
             pht(
               'Promoted "%s" to become a leader for "%s".',
               $device->getName(),
               $repository->getDisplayName()));
         }
 
         if ($demote) {
           PhabricatorRepositoryWorkingCopyVersion::demoteDevice(
             $repository->getPHID(),
             $device->getPHID());
 
           echo tsprintf(
             "%s\n",
             pht(
               'Demoted "%s" from leadership of repository "%s".',
               $device->getName(),
               $repository->getDisplayName()));
         }
       } catch (Exception $ex) {
         $write_lock->unlock();
         throw $ex;
       }
 
       $write_lock->unlock();
     }
 
     return 0;
   }
 
 }