diff --git clone/hosting.feature.drush.inc clone/hosting.feature.drush.inc
new file mode 100644
index 0000000..363b15f
--- /dev/null
+++ clone/hosting.feature.drush.inc
@@ -0,0 +1,12 @@
+<?php
+
+function hosting_clone_hosting_feature() {
+  $features['clone'] = array(
+    'title' => t('Site cloning'),
+    'description' => t('Clone sites to platforms of the same or later version.'),
+    'status' => HOSTING_FEATURE_ENABLED,
+    'module' => 'hosting_clone',
+    );
+  return $features;
+}
+
diff --git clone/hosting_clone.drush.inc clone/hosting_clone.drush.inc
new file mode 100644
index 0000000..ea9d27c
--- /dev/null
+++ clone/hosting_clone.drush.inc
@@ -0,0 +1,28 @@
+<?php
+// $Id: hosting_clone.drush.inc,v 1.2 2009/05/07 22:04:10 adrian Exp $
+
+function drush_hosting_clone_pre_hosting_task($task) {
+  $task =& drush_get_context('HOSTING_TASK');
+  if ($task->ref->type == 'site' && $task->task_type == 'clone') {
+    $task->args[2] = $task->task_args['new_name'];
+    $platform = node_load($task->task_args['target_platform']);
+    $task->args[3] = $platform->publish_path;
+  }
+}
+
+
+function hosting_clone_post_hosting_clone_task($task, $data) {
+  if ($task->ref->type == 'site') {
+    $target = $task->task_args['target_platform'];
+    $clone = new stdClass();
+    # copy some of the settings of the cloned site ($task->ref) to $clone
+    foreach (array('type', 'status', 'uid', 'comment', 'promote', 'moderate', 'sticky', 'name', 'format', 'client', 'db_server', 'profile', 'site_status') as $field) {
+      $clone->$field = $task->ref->$field;
+    }
+    $clone->title = $task->task_args['new_name'];
+    $clone->platform = $target;
+    $clone->import = 1; # make sure the site doesn't reinstall...
+    $clone->verified = 0; # ... and it does verify
+    node_save($clone);
+  }
+}
diff --git clone/hosting_clone.info clone/hosting_clone.info
new file mode 100755
index 0000000..6f8097e
--- /dev/null
+++ clone/hosting_clone.info
@@ -0,0 +1,7 @@
+name = Site cloning
+description = Clone sites between platforms, performing upgrades when necessary.
+package = Hosting
+dependencies[] = hosting
+dependencies[] = hosting_migrate
+
+core = 6.x
diff --git clone/hosting_clone.module clone/hosting_clone.module
new file mode 100755
index 0000000..009d87e
--- /dev/null
+++ clone/hosting_clone.module
@@ -0,0 +1,55 @@
+<?php
+
+function hosting_clone_hosting_tasks($type, $task = null) {
+  $options = array();
+
+  if ($type == 'site') {
+    $options['clone'] = array(
+      'title' => t('Clone'),
+      'description' => t('Copy the site to a new platform.'),
+      'weight' => 7
+    );
+  }
+  return $options;
+}
+
+function hosting_clone_perm() {
+  return array(
+    'create clone task',
+  );
+}
+
+function hosting_task_clone_form_validate($form, &$form_state) {
+  if (!$form_state['values']['parameters']['hidden'] && !$form_state['values']['parameters']['target_platform']) {
+    form_set_error('parameters][target_platform', t('You need to select a valid platform to migrate your site to.'));
+  }
+  $url = strtolower($form_state['values']['parameters']['new_name']); // domain names are case-insensitive
+  if (!_hosting_valid_fqdn($url)) {
+    form_set_error('title', t("You have not specified a valid url for this site."));
+  }
+  if (hosting_site_exists($url)) {
+    form_set_error('title', t("The domain name you have specified is not unique."));
+  }
+
+}
+
+function hosting_clone_theme($existing, $type, $theme, $path) {
+  return array('hosting_task_clone_form' => array('arguments' => array('form' => NULL)));
+}
+
+function hosting_task_clone_form($node) {
+  $form = hosting_task_migrate_form($node);
+  $form['new_name'] = array (
+    '#title' => t('New site name'),
+    '#type' => 'textfield',
+    '#weight' => '-1',
+    '#required' => TRUE,
+    '#default_value' => $node->title
+  );
+  return $form;
+}
+
+function theme_hosting_task_clone_form(&$form) {
+  return theme_hosting_task_migrate_form($form);
+}
+
