diff --git a/hacked.drush.inc b/hacked.drush.inc
index 6997ca1..2276759 100644
--- a/hacked.drush.inc
+++ b/hacked.drush.inc
@@ -1,6 +1,5 @@
 <?php
 
-
 /**
  * @file
  *   Hacked drush command.
@@ -19,7 +18,6 @@ function hacked_drush_help($section) {
       return dt('Show details of the files in one project, and the hacked/unhacked status of those files.');
     case 'drush:hacked-diff':
       return dt('Output a unified diff of the specified project.');
-
   }
 }
 
@@ -36,7 +34,6 @@ function hacked_drush_command() {
 
   $items['hacked-list-projects'] = array(
     'description' => "List all projects that can be analysed by Hacked! ",
-    'drupal dependencies' => array('hacked'),
     'options' => array(
       'force-rebuild' => 'Rebuild the Hacked! report instead of getting a cached version.'
     ),
@@ -45,12 +42,10 @@ function hacked_drush_command() {
 
   $items['hacked-lock-modified'] = array(
     'description' => "Lock all projects that Hacked! detects are modified, so that drush pm-updatecode will not touch them. (drush-4.x+ only)",
-    'drupal dependencies' => array('hacked'),
   );
 
   $items['hacked-details'] = array(
     'description' => "Show the Hacked! report about a specific project.",
-    'drupal dependencies' => array('hacked'),
     'arguments' => array(
       'project' => 'The machine name of the project to report on.',
     ),
@@ -62,7 +57,6 @@ function hacked_drush_command() {
 
   $items['hacked-diff'] = array(
     'description' => "Output a unified diff of the project specified.",
-    'drupal dependencies' => array('hacked'),
     'arguments' => array(
       'project' => 'The machine name of the project to report on.',
     ),
@@ -81,10 +75,11 @@ function hacked_drush_command() {
  * So you'll want to be very careful if you call this!
  */
 function hacked_calculate_project_data_drush($projects, $force = FALSE, $redirect = NULL) {
+  hacked_load_dependencies();
   include_once './includes/batch.inc';
 
   // Try to get the report form cache if we can.
-  $cache = cache_get('hacked:drush:full-report', HACKED_CACHE_TABLE);
+  $cache = drush_cache_get('hacked:drush:full-report', HACKED_CACHE_TABLE);
   if (!empty($cache->data) && !$force) {
     return $cache->data;
   }
@@ -93,15 +88,16 @@ function hacked_calculate_project_data_drush($projects, $force = FALSE, $redirec
   $operations = array();
   foreach ($projects as $project) {
     $operations[] = array(
-      'hacked_build_report_batch',
+      'hacked_build_report_batch_drush',
       array($project['name']),
     );
   }
 
+  drush_log(print_r($operations), 'warning');
+
   $batch = array(
     'operations' => $operations,
     'finished' => 'hacked_build_report_batch_finished_drush',
-    'file' => drupal_get_path('module', 'hacked') . '/hacked.report.inc',
     'title' => t('Building report'),
   );
 
@@ -113,13 +109,27 @@ function hacked_calculate_project_data_drush($projects, $force = FALSE, $redirec
   drush_print('Done.');
 
   // Now we can get the data from the cache.
-  $cache = cache_get('hacked:drush:full-report', HACKED_CACHE_TABLE);
+  $cache = drush_cache_get('hacked:drush:full-report', HACKED_CACHE_TABLE);
   if (!empty($cache->data)) {
     return $cache->data;
   }
 }
 
 /**
+ * Batch callback to build the hacked report.
+ */
+function hacked_build_report_batch_drush($project_name, &$context) {
+  hacked_load_dependencies();
+  if (!isset($context['results']['report'])) {
+    $context['results']['report'] = array();
+  }
+
+  $project = new hackedProject($project_name);
+  $context['results']['report'][$project_name] = $project->compute_report();
+  $context['message'] = t('Finished processing: @name', array('@name' => $project->title()));
+}
+
+/**
  * Completion callback for the report batch.
  */
 function hacked_build_report_batch_finished_drush($success, $results, $operations) {
@@ -127,7 +137,7 @@ function hacked_build_report_batch_finished_drush($success, $results, $operation
     // Sort the results.
     usort($results['report'], '_hacked_project_report_sort_by_status');
     // Store them.
-    cache_set('hacked:drush:full-report', $results['report'], HACKED_CACHE_TABLE, strtotime('+1 day'));
+    drush_cache_set('hacked:drush:full-report', $results['report'], HACKED_CACHE_TABLE, strtotime('+1 day'));
   }
 }
 
@@ -135,6 +145,10 @@ function hacked_build_report_batch_finished_drush($success, $results, $operation
  * Drush command callback that shows the listing of changed/unchanged projects.
  */
 function drush_hacked_list_projects() {
+  if (!function_exists('update_get_available')) {
+    return drush_set_error('HACKED_UPDATE_DISABLED', 'Cannot list projects without the Drupal core update module enabled.');
+  }
+  hacked_load_dependencies();
 
   // Go get the data:
   module_load_include('inc', 'update', 'update.report');
@@ -190,6 +204,7 @@ function drush_hacked_list_projects() {
  * touch them.
  */
 function drush_hacked_lock_modified() {
+  hacked_load_dependencies();
   $drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
   module_load_include('inc', 'update', 'update.report');
   if (isset($drupal_root) && ($available = update_get_available(TRUE))) {
@@ -258,8 +273,9 @@ function drush_hacked_details_validate($short_name = '') {
  * Validate hook for the hacked drush commands that need a project.
  */
 function drush_hacked_drush_command_validate($short_name = '') {
+  hacked_load_dependencies();
   if (empty($short_name)) {
-    return drush_set_error('HACKED_PROJECT_NOT_FOUND', dt('A valid project must be specified', array('@project' => $short_name)));
+    return drush_set_error('HACKED_PROJECT_NOT_FOUND', dt('A valid project must be specified.'));
   }
 
   $project = hacked_project_load($short_name);
@@ -381,3 +397,15 @@ function drush_hacked_diff($short_name) {
   }
 
 }
+
+/**
+ * Allow Hacked! to be used without being enabled, like a drush command
+ * installed on a platform.
+ */
+function hacked_load_dependencies() {
+  if (!module_exists('hacked')) {
+    include_once 'hacked.module';
+    include_once 'includes/hacked_project.inc';
+    include_once 'hacked.report.inc';
+  }
+}
diff --git a/hacked.module b/hacked.module
index d51f97f..117f7c7 100644
--- a/hacked.module
+++ b/hacked.module
@@ -339,7 +339,12 @@ function hacked_get_file_hasher($name = NULL) {
   if (is_null($name)) {
     $name = variable_get('hacked_selected_file_hasher', HACKED_DEFAULT_FILE_HASHER);
   }
-  $hashers = hacked_get_file_hashers();
+  if (!module_exists('hacked')) {
+    $hashers = hacked_hacked_file_hashers_info();
+  }
+  else {
+    $hashers = hacked_get_file_hashers();
+  }
   $class_name = $hashers[$name]['class'];
   return new $class_name;
 }
diff --git a/hacked.report.inc b/hacked.report.inc
index 20659a8..70eb089 100644
--- a/hacked.report.inc
+++ b/hacked.report.inc
@@ -35,10 +35,12 @@ function hacked_reports_rebuild() {
  * Batch callback to build the hacked report.
  */
 function hacked_build_report_batch($project_name, &$context) {
+  hacked_load_dependencies();
+
   if (!isset($context['results']['report'])) {
     $context['results']['report'] = array();
   }
-  module_load_include('inc', 'hacked', 'includes/hacked_project');
+
   $project = new hackedProject($project_name);
   $context['results']['report'][$project_name] = $project->compute_report();
   $context['message'] = t('Finished processing: @name', array('@name' => $project->title()));
