diff --git a/src/applications/drydock/management/DrydockManagementReleaseLeaseWorkflow.php b/src/applications/drydock/management/DrydockManagementReleaseLeaseWorkflow.php
--- a/src/applications/drydock/management/DrydockManagementReleaseLeaseWorkflow.php
+++ b/src/applications/drydock/management/DrydockManagementReleaseLeaseWorkflow.php
@@ -15,40 +15,71 @@
             'repeat' => true,
             'help' => pht('Lease ID to release.'),
           ),
+          array(
+            'name' => 'all',
+            'help' => pht('Release all leases. Dangerous!'),
+          ),
         ));
   }
 
   public function execute(PhutilArgumentParser $args) {
+    $is_all = $args->getArg('all');
     $ids = $args->getArg('id');
-    if (!$ids) {
+
+    if (!$ids && !$is_all) {
       throw new PhutilArgumentUsageException(
         pht(
-          'Specify one or more lease IDs to release with "%s".',
-          '--id'));
+          'Select which leases you want to release. See "--help" for '.
+          'guidance.'));
     }
 
     $viewer = $this->getViewer();
-    $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
 
-    $leases = id(new DrydockLeaseQuery())
+    $statuses = $this->getReleaseableLeaseStatuses();
+
+    $query = id(new DrydockLeaseQuery())
       ->setViewer($viewer)
-      ->withIDs($ids)
-      ->execute();
+      ->withStatuses(mpull($statuses, 'getKey'));
 
-    PhabricatorWorker::setRunAllTasksInProcess(true);
-    foreach ($ids as $id) {
-      $lease = idx($leases, $id);
-      if (!$lease) {
-        echo tsprintf(
-          "%s\n",
-          pht('Lease "%s" does not exist.', $id));
-        continue;
+    if ($ids) {
+      $query->withIDs($ids);
+    }
+
+    $leases = $query->execute();
+
+    if ($ids) {
+      $id_map = mpull($leases, null, 'getID');
+
+      foreach ($ids as $id) {
+        $lease = idx($id_map, $id);
+        if (!$lease) {
+          throw new PhutilArgumentUsageException(
+            pht('Lease "%s" does not exist.', $id));
+        }
       }
 
+      $leases = array_select_keys($id_map, $ids);
+    }
+
+    if (!$leases) {
+      echo tsprintf(
+        "%s\n",
+        pht('No leases selected for release.'));
+
+      return 0;
+    }
+
+    $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
+
+    PhabricatorWorker::setRunAllTasksInProcess(true);
+
+    foreach ($leases as $lease) {
       if (!$lease->canRelease()) {
         echo tsprintf(
           "%s\n",
-          pht('Lease "%s" is not releasable.', $id));
+          pht(
+            'Lease "%s" is not releasable.',
+            $lease->getDisplayName()));
         continue;
       }
 
@@ -62,9 +93,26 @@
 
       echo tsprintf(
         "%s\n",
-        pht('Scheduled release of lease "%s".', $id));
+        pht(
+          'Scheduled release of lease "%s".',
+          $lease->getDisplayName()));
+    }
+
+  }
+
+  private function getReleaseableLeaseStatuses() {
+    $statuses = DrydockLeaseStatus::getAllStatuses();
+    foreach ($statuses as $key => $status) {
+      $statuses[$key] = DrydockLeaseStatus::newStatusObject($status);
+    }
+
+    foreach ($statuses as $key => $status) {
+      if (!$status->canRelease()) {
+        unset($statuses[$key]);
+      }
     }
 
+    return $statuses;
   }
 
 }
diff --git a/src/applications/drydock/management/DrydockManagementReleaseResourceWorkflow.php b/src/applications/drydock/management/DrydockManagementReleaseResourceWorkflow.php
--- a/src/applications/drydock/management/DrydockManagementReleaseResourceWorkflow.php
+++ b/src/applications/drydock/management/DrydockManagementReleaseResourceWorkflow.php
@@ -15,41 +15,70 @@
             'repeat' => true,
             'help' => pht('Resource ID to release.'),
           ),
+          array(
+            'name' => 'all',
+            'help' => pht('Release all resources. Dangerous!'),
+          ),
         ));
   }
 
   public function execute(PhutilArgumentParser $args) {
+    $is_all = $args->getArg('all');
     $ids = $args->getArg('id');
-    if (!$ids) {
+    if (!$ids && !$is_all) {
       throw new PhutilArgumentUsageException(
         pht(
-          'Specify one or more resource IDs to release with "%s".',
-          '--id'));
+          'Specify which resources you want to release. See "--help" for '.
+          'guidance.'));
     }
 
     $viewer = $this->getViewer();
-    $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
+    $statuses = $this->getReleaseableResourceStatuses();
 
-    $resources = id(new DrydockResourceQuery())
+    $query = id(new DrydockResourceQuery())
       ->setViewer($viewer)
-      ->withIDs($ids)
-      ->execute();
+      ->withStatuses(mpull($statuses, 'getKey'));
 
-    PhabricatorWorker::setRunAllTasksInProcess(true);
-    foreach ($ids as $id) {
-      $resource = idx($resources, $id);
+    if ($ids) {
+      $query->withIDs($ids);
+    }
 
-      if (!$resource) {
-        echo tsprintf(
-          "%s\n",
-          pht('Resource "%s" does not exist.', $id));
-        continue;
+    $resources = $query->execute();
+
+    if ($ids) {
+      $id_map = mpull($resources, null, 'getID');
+
+      foreach ($ids as $id) {
+        $resource = idx($resources, $id);
+
+        if (!$resource) {
+          throw new PhutilArgumentUsageException(
+            pht('Resource "%s" does not exist.', $id));
+        }
       }
 
+      $resources = array_select_keys($id_map, $ids);
+    }
+
+    if (!$resources) {
+      echo tsprintf(
+        "%s\n",
+        pht('No resources selected for release.'));
+
+      return 0;
+    }
+
+    $drydock_phid = id(new PhabricatorDrydockApplication())->getPHID();
+
+    PhabricatorWorker::setRunAllTasksInProcess(true);
+
+    foreach ($resources as $resource) {
       if (!$resource->canRelease()) {
         echo tsprintf(
           "%s\n",
-          pht('Resource "%s" is not releasable.', $id));
+          pht(
+            'Resource "%s" is not releasable.',
+            $resource->getDisplayName()));
         continue;
       }
 
@@ -63,9 +92,26 @@
 
       echo tsprintf(
         "%s\n",
-        pht('Scheduled release of resource "%s".', $id));
+        pht(
+          'Scheduled release of resource "%s".',
+          $resource->getDisplayName()));
     }
 
+    return 0;
   }
 
+  private function getReleaseableResourceStatuses() {
+    $statuses = DrydockResourceStatus::getAllStatuses();
+    foreach ($statuses as $key => $status) {
+      $statuses[$key] = DrydockResourceStatus::newStatusObject($status);
+    }
+
+    foreach ($statuses as $key => $status) {
+      if (!$status->canRelease()) {
+        unset($statuses[$key]);
+      }
+    }
+
+    return $statuses;
+  }
 }
diff --git a/src/applications/drydock/storage/DrydockLease.php b/src/applications/drydock/storage/DrydockLease.php
--- a/src/applications/drydock/storage/DrydockLease.php
+++ b/src/applications/drydock/storage/DrydockLease.php
@@ -471,6 +471,10 @@
     return "/drydock/lease/{$id}/";
   }
 
+  public function getDisplayName() {
+    return pht('Drydock Lease %d', $this->getID());
+  }
+
 
 /* -(  Status  )------------------------------------------------------------- */
 
diff --git a/src/applications/drydock/storage/DrydockResource.php b/src/applications/drydock/storage/DrydockResource.php
--- a/src/applications/drydock/storage/DrydockResource.php
+++ b/src/applications/drydock/storage/DrydockResource.php
@@ -286,6 +286,10 @@
     return $log->save();
   }
 
+  public function getDisplayName() {
+    return pht('Drydock Resource %d', $this->getID());
+  }
+
 
 /* -(  Status  )------------------------------------------------------------- */