diff --git ctools.module ctools.module
index 1255b04..ac205bb 100644
--- ctools.module
+++ ctools.module
@@ -284,7 +284,7 @@ function _ctools_passthrough(&$items, $type = 'theme') {
     require_once './' . $file->filename;
     list($tool) = explode('.', $file->name, 2);
 
-    $function = 'ctools_' . $tool . '_' . $type;
+    $function = 'ctools_' . str_replace ('-', '_', $tool) . '_' . $type;
     if (function_exists($function)) {
       $function($items);
     }
@@ -760,3 +760,37 @@ function ctools_file_check_directory(&$directory, $mode = 0, $form_item = NULL)
 
   return TRUE;
 }
+
+/**
+ * Menu loader; Load exportables when used with export-ui.
+ */
+function ctools_export_ui_load($export_name, $map_array) {
+  ctools_include('export-ui');
+  // Create a dummy menu item, to be passed to
+  // ctools_export_ui_get_plugin_by_menu().
+  $item = array();
+  $item['path'] = implode('/', $map_array);
+
+  $plugin = ctools_export_ui_get_plugin_by_menu($item, array('export id' => $export_name));
+  return $plugin->load($export_name);
+}
+
+/**
+ * Menu access callback for various tasks of export-ui.
+ */
+function ctools_export_ui_task_access($export, $op) {
+  if (!user_access('administer site configuration')) {
+    return FALSE;
+  }
+  switch ($op) {
+    case 'revert':
+      return ($export->export_type & EXPORT_IN_DATABASE) && ($export->export_type & EXPORT_IN_CODE);
+    case 'delete':
+      return ($export->export_type & EXPORT_IN_DATABASE) && !($export->export_type & EXPORT_IN_CODE);
+    case 'disable':
+      return empty($export->disabled);
+    case 'enable':
+      return !empty($export->disabled);
+  }
+  return TRUE;
+}
diff --git includes/export-ui.admin.inc includes/export-ui.admin.inc
new file mode 100644
index 0000000..0f1f3b3
--- /dev/null
+++ includes/export-ui.admin.inc
@@ -0,0 +1,325 @@
+<?php
+// $Id: message_ui.admin.inc,v 1.2 2010/04/11 18:04:15 amitaibu Exp $
+
+ctools_include('export-ui');
+
+/**
+ * Exportables listing form.
+ */
+function ctools_export_ui_admin() {
+  ctools_include('export');
+  $plugin = ctools_export_ui_get_plugin_by_menu();
+
+  ctools_export_load_object_reset($plugin->name);
+  $exports = ctools_export_load_object($plugin->name, 'all');
+
+  $form = array(
+    '#theme' => 'ctools_export_ui_admin',
+    '#exports' => $exports,
+    '#plugin' => $plugin,
+  );
+
+  return $form;
+}
+
+
+/**
+ * Generates the omnibus export definition editing form.
+ *
+ * @param $op
+ *   The type of form to build. Either "add", "view" or "edit"
+ * @param $export
+ *   The export.
+ *
+ * @return
+ *   A Drupal form array.
+ */
+function ctools_export_ui_form(&$form_state, $op, $export = NULL) {
+  ctools_include('export');
+
+  // We might get the export from import. @see ctools_export_ui_import_submit().
+  $plugin = ctools_export_ui_get_plugin_by_menu(NULL, array('export' => $export), TRUE);
+  $id = $plugin->id;
+
+  $export = !$export ? ctools_export_new_object($plugin->$id) : $export;
+  switch ($op) {
+    case 'add':
+      drupal_set_title(t('Add a new @plugin', array('@plugin' => $plugin->title)));
+      break;
+    case 'edit':
+      if ($export->export_type & EXPORT_IN_DATABASE) {
+        drupal_set_title(t('Editing @plugin %title', array('@plugin' => $plugin->title, '%title' => $export->$id)));
+      }
+      else {
+        drupal_set_title(t('Viewing @plugin %title', array('@plugin' => $plugin->title, '%title' => $export->$id)));
+      }
+      break;
+    case 'clone':
+      drupal_set_title(t('Cloning @plugin %title', array('@plugin' => $plugin->title, '%title' => $export->$id)));
+      break;
+  }
+
+  $form['export'] = array(
+    '#type' => 'value',
+    '#value' => $export,
+  );
+
+  $form['plugin'] = array(
+    '#type' => 'value',
+    '#value' => $plugin,
+  );
+
+  $form['op'] = array(
+    '#type' => 'value',
+    '#value' => $op,
+  );
+
+  // Add plugin's definition.
+  $plugin->options_form($form, $form_state, $op, $export);
+
+  // Buttons
+  $form['buttons']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+  );
+  $form['buttons']['delete'] = array(
+    '#type' => 'submit',
+    '#value' => t('Delete'),
+    '#access' => $op === 'edit',
+  );
+
+  // TODO: Add validation and submit handlers.
+
+  return $form;
+}
+
+/**
+ * Provide a form to confirm one of the provided actions.
+ */
+function ctools_export_ui_confirm(&$form_state, $op = 'delete', $export) {
+  $form = array();
+  $form['export'] = array('#type' => 'value', '#value' => $export);
+  $form['action'] = array('#type' => 'value', '#value' => $op);
+  switch ($op) {
+    case 'revert':
+      $action = t('revert');
+      $description = t('This action will permanently remove any customizations made to this export.');
+      break;
+    case 'delete':
+      $action = t('delete');
+      $description = t('This action will remove this export permanently from your site.');
+      break;
+    case 'disable':
+      $action = t('disable');
+      $description = '';
+      break;
+    case 'enable':
+      $action = t('enable');
+      $description = '';
+      break;
+  }
+  $plugin = ctools_export_ui_get_plugin_by_menu();
+  $id = $plugin->id;
+
+  $form = confirm_form($form,
+    t('Are you sure you want to !action the @plugin %title?', array('!action' => $action, '@plugin' => $plugin->title, '%title' => $export->$id,)),
+    $plugin->options['menu']['menu prefix'] .'/'. $plugin->options['menu']['menu item'],
+    $description,
+    drupal_ucfirst($action), t('Cancel')
+  );
+  return $form;
+}
+
+/**
+ * Submit handler for the ctools_export_ui_confirm form.
+ */
+function ctools_export_ui_confirm_submit($form, &$form_state) {
+  $plugin = ctools_export_ui_get_plugin_by_menu();
+
+  ctools_include('export');
+  $export = $form_state['values']['export'];
+  switch ($form_state['values']['action']) {
+    case 'revert':
+    case 'delete':
+      $plugin->delete($export);
+      break;
+    case 'disable':
+      ctools_export_set_object_status($export);
+      break;
+    case 'enable':
+      ctools_export_set_object_status($export, FALSE);
+      break;
+  }
+  $form_state['redirect'] = _ctools_export_ui_redirect($plugin);
+}
+
+/**
+ * Page callback for import form. Switches form output to export form
+ * if import submission has occurred.
+ */
+function ctools_export_ui_import_page() {
+  if (!empty($_POST) && $_POST['form_id'] == 'ctools_export_ui_form') {
+    return drupal_get_form('ctools_export_ui_form', 'add');
+  }
+  return drupal_get_form('ctools_export_ui_import');
+}
+
+/**
+ * Import form. Provides simple helptext instructions and textarea for
+ * pasting a export definition.
+ */
+function ctools_export_ui_import() {
+  $plugin = ctools_export_ui_get_plugin_by_menu();
+
+  drupal_set_title(t('Import @plugin', array('@plugin' => $plugin->title)));
+  $help = t('You can import a export definition by pasting the exported export object code into the field below.');
+
+  $form = array();
+  $form['plugin'] = array(
+    '#type' => 'value',
+    '#value' => $plugin,
+  );
+
+  $form['help'] = array(
+    '#type' => 'item',
+    '#value' => $help,
+  );
+  $form['import'] = array(
+    '#title' => t('@plugin object', array('@plugin' => $plugin->title)),
+    '#type' => 'textarea',
+    '#rows' => 10,
+    '#required' => TRUE,
+  );
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Import'),
+  );
+  return $form;
+}
+
+/**
+ * Import form submit handler. Evaluates import code and transfers to
+ * export definition form.
+ */
+function ctools_export_ui_import_submit($form, &$form_state) {
+  $plugin = $form['plugin']['#value'];
+  $id = $plugin->id;
+
+  $items = array();
+  if ($import = $form_state['values']['import']) {
+    ob_start();
+    $export = eval($import);
+    ob_end_clean();
+  }
+
+  if (is_object($export)) {
+    if (isset($export->$id) && $exists = ctools_export_load_object($plugin->name, 'names', array($export->$id))) {
+      drupal_set_message(t('A @plugin with this name already exists. Please remove the existing export before importing this definition.', array('@plugin' => $plugin->title)), 'error');
+      $form_state['redirect'] = _ctools_export_ui_redirect($plugin);
+    }
+    else {
+      drupal_set_title(t('Export @plugin', array('@plugin' => $plugin->title)));
+      $output = drupal_get_form('ctools_export_ui_form', 'add', (object) $export);
+      print theme('page', $output);
+      exit;
+    }
+  }
+  else {
+    drupal_set_message(t('An error occurred while importing. Please check your export definition.', 'error'));
+
+    $form_state['redirect'] = _ctools_export_ui_redirect($plugin);
+  }
+}
+
+/**
+ * Provides a form with an exported export definition for use in modules.
+ *
+ * @param $cid
+ *   A export id.
+ *
+ * @return
+ *   A FormAPI array.
+ */
+function ctools_export_ui_export(&$form_state, $export) {
+  ctools_include('export');
+  $plugin = ctools_export_ui_get_plugin_by_menu();
+  $id = $plugin->id;
+
+  drupal_set_title(t('Export %title', array('%title' => $export->$id)));
+
+  return ctools_export_form($form_state, ctools_export_ui_export_object($plugin, $export), t('Export'));
+}
+
+/**
+ * Validate export id values.
+ */
+function ctools_export_ui_form_name_validate($element, &$form_state) {
+  $plugin = $element['#plugin'];
+  // Check for string identifier sanity
+  if (!preg_match('!^[a-z0-9_-]+$!', $element['#value'])) {
+    form_set_error('name', t('The export id can only consist of lowercase letters, dashes, underscores, and numbers.'));
+  }
+  // Check for name collision
+  else if ($exists = ctools_export_load_object($plugin->name, 'names', array($element['#value']))) {
+    form_set_error('name', t('A @plugin with this name already exists. Please choose another name or delete the existing export before creating a new one.', array('@plugin' => $pluin->title)));
+  }
+}
+
+/**
+ * Produces a export object from submitted form values.
+ *
+ * @param $form
+ *   A form array with submitted values
+ *
+ * @return
+ *   A export object
+ */
+function ctools_export_ui_form_process($form, $form_state) {
+  ctools_include('export');
+  $plugin = $form['plugin']['#value'];
+  $id = $plugin->id;
+
+
+  $values = $form_state['values'];
+
+  $export = ctools_export_new_object($plugin->name);
+  $export->$id = isset($values[$id]) ? $values[$id] : NULL;
+  $export->tag = isset($values['tag']) ? $values['tag'] : NULL;
+
+  foreach ($plugin->option_definition() as $key => $value) {
+    $export->{$key} = isset($values[$key]) ? $values[$key] : NULL;
+  }
+
+  return $export;
+}
+
+/**
+ * Submit handler for main ctools_export_ui form.
+ */
+function ctools_export_ui_form_submit($form, &$form_state) {
+  $plugin = ctools_export_ui_get_plugin_by_menu();
+  $id = $plugin->id;
+
+  switch ($form_state['clicked_button']['#id']) {
+    // Send user to delete confirmation page
+    case 'edit-delete':
+      if (isset($form_state['values']['export']->$id)) {
+        $menu_prefix = _ctools_export_ui_redirect($plugin);
+        $form_state['redirect'] = "$menu_prefix/list/{$form_state['values']['export']->$id}/delete";
+      }
+      return;
+    // Process form values and save and/or update the export in the db
+    case 'edit-submit':
+      $export = ctools_export_ui_form_process($form, $form_state);
+
+      $result = $plugin->save($export);
+      if ($result) {
+        drupal_set_message(t('Saved @plugin %title.', array('@plugin' => $plugin->title, '%title' =>  $export->$id)));
+      }
+      else {
+        drupal_set_message(t('Could not save @plugin %title.', array('@plugin' => $plugin->title, '%title' =>  $export->$id)), 'error');
+      }
+      break;
+  }
+  $form_state['redirect'] = _ctools_export_ui_redirect($plugin);
+}
\ No newline at end of file
diff --git includes/export-ui.css includes/export-ui.css
new file mode 100644
index 0000000..ce4b429
--- /dev/null
+++ includes/export-ui.css
@@ -0,0 +1,29 @@
+/**
+ * Admin listing page.
+ */
+table.export-admin td.export-name {
+  width: 75%;
+  padding-left: 20px;
+}
+
+table.export-admin td.tag {
+  font-style: italic;
+}
+
+table.export-admin td.export-links {
+  white-space: nowrap;
+}
+
+table.export-admin em.storage,table.export-admin tr.disabled td.export-name
+  {
+  color: #999;
+}
+
+table.export-admin div.description {
+  padding-left: 10px;
+  margin: 0px;
+}
+
+table.export-admin input.form-text {
+  width: 90%;
+}
\ No newline at end of file
diff --git includes/export-ui.inc includes/export-ui.inc
new file mode 100644
index 0000000..d1a4e67
--- /dev/null
+++ includes/export-ui.inc
@@ -0,0 +1,102 @@
+<?php
+// $Id: export_ui.module,v 1.13.2.48.2.1.2.11 2010/02/28 19:30:48 yhahn Exp $
+
+/**
+ * Implementation of hook_help().
+ *
+ * TODO: Add plugin's hook_help().
+ */
+function ctools_export_ui_help($path, $arg) {
+  switch ($path) {
+    case 'admin/build/export':
+      break;
+  }
+}
+
+/**
+ * Get a plugin handler.
+ */
+function ctools_export_ui_get_plugin($key, $info = array()) {
+  global $user;
+  $cache = &ctools_static(__FUNCTION__, array());
+  if (empty($cache[$key])) {
+    ctools_include('plugins');
+    $plugin = ctools_get_plugins('ctools', 'export_ui', $key);
+
+    if ($class = ctools_plugin_get_class($plugin, 'handler')) {
+      $cache[$key] = new $class($plugin, $info);
+    }
+  }
+  return !empty($cache[$key]) ? $cache[$key] : FALSE;
+}
+
+/**
+ * Return a plugin by the menu item.
+ *
+ * @param $item
+ *   Optional; A menu item as returned from menu_get_item().
+ * @param $info
+ *   Optional; The $info that will be passed to the plugin constructor.
+ *
+ * @return
+ *   A loaded plugin, or False if none found.
+ */
+function ctools_export_ui_get_plugin_by_menu($item = NULL, $info = array()) {
+  // $plugin is static, as the first one to call it on page load is
+  // ctools_export_ui_load().
+  $plugin = &ctools_static(__FUNCTION__, FALSE);
+  if (empty($plugin)) {
+    if (empty($item)) {
+      $item = menu_get_item();
+    }
+
+    ctools_include('plugins');
+    $plugins = ctools_get_plugins('ctools', 'export_ui');
+    foreach ($plugins as $key => $plugin) {
+      // Add default menu prefix.
+      // If menu item isn't specified use the plugin name.
+      $menu_item = !empty($plugin['menu item']) ? $plugin['menu item'] : $plugin['name'];
+      $plugin += array(
+        'has menu' => TRUE,
+        'menu prefix' => 'admin/build',
+        'menu item' => str_replace(' ', '-', $plugin['menu item']),
+      );
+      if ($plugin['has menu']  && strpos($item['path'], $plugin['menu prefix'] .'/'. $plugin['menu item']) === 0) {
+        $plugin = ctools_export_ui_get_plugin($plugin['handler']['class'], $info);
+      }
+    }
+  }
+
+  return $plugin;
+}
+
+/**
+ * CTools export function.
+ */
+function ctools_export_ui_export_object($plugin, $export, $indent = '') {
+  $strings = array();
+  foreach ($plugin->option_definition() as $id) {
+    if (!empty($id['translatable']) && !empty($export->$id)) {
+      $strings[] = $indent . "  t('" . str_replace("'", "\'", $export->$id) . "'),";
+    }
+  }
+  sort($strings);
+  $extra = implode("\n", array_unique($strings));
+  $extra = "\n". $indent ."\$translatables['" . $export->name . "'] = array(\n". $extra . "\n" . $indent . ");";
+  $extra .="\nreturn \$". $plugin->name .";\n";
+
+  return ctools_export_object($plugin->name, $export, $indent) . $extra;
+}
+
+/**
+ * Get redirection path from a plugin.
+ *
+ * @param $plguin
+ *   The plugin object.
+ *
+ * @return
+ *   The menu path to the plugin's list.
+ */
+function _ctools_export_ui_redirect($plugin) {
+  return $plugin->options['menu']['menu prefix'] .'/'. $plugin->options['menu']['menu item'];
+}
\ No newline at end of file
diff --git includes/export-ui.menu.inc includes/export-ui.menu.inc
new file mode 100644
index 0000000..c5db1b0
--- /dev/null
+++ includes/export-ui.menu.inc
@@ -0,0 +1,18 @@
+<?php
+// $Id: export_ui.module,v 1.13.2.48.2.1.2.11 2010/02/28 19:30:48 yhahn Exp $
+
+
+/**
+ * Delegated implementation of hook_menu().
+ */
+function ctools_export_ui_menu(&$items) {
+  ctools_include('export-ui');
+  ctools_include('plugins');
+
+  $plugins = ctools_get_plugins('ctools', 'export_ui');
+  foreach ($plugins as $key => $plugin) {
+    $plugin = ctools_export_ui_get_plugin($key);
+
+    $items = array_merge($items, $plugin->hook_menu());
+  }
+}
\ No newline at end of file
diff --git includes/export-ui.theme.inc includes/export-ui.theme.inc
new file mode 100644
index 0000000..95d1c90
--- /dev/null
+++ includes/export-ui.theme.inc
@@ -0,0 +1,87 @@
+<?php
+
+
+/**
+ * Delegated implementation of hook_theme().
+ */
+function ctools_export_ui_theme(&$items) {
+  $items['ctools_export_ui_admin'] = array(
+    'arguments' => array('form' => array()),
+    'file' => 'export-ui.theme.inc',
+    'path' => drupal_get_path('module', 'ctools') .'/includes',
+  );
+}
+
+/**
+ * Generates the main export_ui admin page with a tiered export listing.
+ */
+function theme_ctools_export_ui_admin($form) {
+  ctools_include('export-ui');
+
+  drupal_add_css(drupal_get_path('module', 'ctools') .'/includes/export-ui.css');
+
+  $plugin = $form['#plugin'];
+  $id = $plugin->id;
+
+  // Iterate once to group by tag.
+  $by_tag = array();
+  foreach ($form['#exports'] as $export) {
+    if (!empty($export->tag)) {
+      $by_tag[$export->tag][$export->$id] = $export;
+    }
+    else {
+      $by_tag[''][$export->$id] = $export;
+    }
+  }
+
+  // Generate listing of existing exports
+  ksort($by_tag);
+  $rows = array();
+  foreach ($by_tag as $tag => $exports) {
+    if (!empty($tag)) {
+      $rows[] = array(array('data' => check_plain($tag), 'colspan' => 3, 'class' => 'tag'));
+    }
+    ksort($exports);
+    foreach ($exports as $export) {
+      $row = array('data' => array());
+
+      // Exportable info
+      $storage = t('Default');
+      if ($export->export_type & EXPORT_IN_DATABASE) {
+        $storage = $export->export_type & EXPORT_IN_CODE ? t('Overridden') : t('Normal');
+      }
+      $data = "<strong>{$export->$id}</strong> <em class='storage'>({$storage})</em>";
+      $data .= !empty($export->description) ? '<div class="description">'. filter_xss_admin($export->description) .'</div>' : '';
+      $row['data'][] = array('data' => $data, 'colspan' => 2, 'class' => 'export-name');
+
+      $menu_prefix = _ctools_export_ui_redirect($plugin);
+
+      // Exportable actions
+      $links = array(
+        'edit'    => l(t('Edit'), "$menu_prefix/list/{$export->$id}"),
+        'delete'  => l(t('Delete'), "$menu_prefix/list/{$export->$id}/delete"),
+        'revert'  => l(t('Revert'), "$menu_prefix/list/{$export->$id}/revert"),
+        'export'  => l(t('Export'), "$menu_prefix/list/{$export->$id}/export"),
+        'clone'   => l(t('Clone'), "$menu_prefix/list/{$export->$id}/clone"),
+        'disable' => l(t('Disable'), "$menu_prefix/list/{$export->$id}/disable"),
+        'enable'  => l(t('Enable'), "$menu_prefix/list/{$export->$id}/enable"),
+      );
+      foreach (array_keys($links) as $key) {
+        if (!ctools_export_ui_task_access($export, $key)) {
+          unset($links[$key]);
+        }
+      }
+      $row['data'][] = array('data' => implode(' | ', $links), 'class' => 'export-links');
+      $row['class'] = empty($export->disabled) ? 'enabled' : 'disabled';
+      $rows[] = $row;
+    }
+  }
+  $rows[] = array(
+    drupal_render($form['tag']),
+    drupal_render($form[$id]),
+    drupal_render($form['submit']),
+  );
+  $output = theme('table', array($plugin->title, '', t('Operations')), $rows, array('class' => 'export-admin'));
+  $output .= drupal_render($form);
+  return $output;
+}
diff --git plugins/export_ui/ctools_export_ui.class.php plugins/export_ui/ctools_export_ui.class.php
new file mode 100644
index 0000000..0267306
--- /dev/null
+++ plugins/export_ui/ctools_export_ui.class.php
@@ -0,0 +1,288 @@
+<?php
+// $Id: context_condition.inc,v 1.1.2.3 2010/03/03 19:42:06 yhahn Exp $
+
+/**
+ * Base class for export UI.
+ */
+class ctools_export_ui {
+  var $plugin;
+  var $name;
+  var $title;
+  var $id;
+  var $options = array();
+
+  /**
+   * Constructor. Do not override.
+   */
+  function __construct($plugin, $info = array()) {
+    ctools_include('export');
+
+    // Initialize values.
+    $plugin += array ('has menu' => TRUE);
+
+    $this->plugin = $plugin;
+    $this->name = $plugin['name'];
+    $this->title = !empty($plugin['title']) ? filter_xss_admin($plugin['title']) : filter_xss_admin($plugin['name']);
+
+    // Get the unique ID of the export.
+    $schema = ctools_export_get_schema($this->name);
+    $this->id = $schema['export']['key'];
+
+    $this->options = array();
+
+    if (!empty($info['export'])) {
+      $export = $info['export'];
+    }
+    elseif (!empty($info['export id'])) {
+      // Add the exportable object values if we got only it's ID.
+      $export = (array)$this->load($info['export id']);
+    }
+    if (!empty($export)) {
+      foreach ($export as $key => $value) {
+        $this->options[$key] = $value;
+      }
+    }
+
+    $this->set_default_options();
+  }
+
+  /**
+   * Information about options for all kinds of purposes will be held here.
+   */
+  function option_definition() {
+    $options[$this->id] = array('default' => '', 'translatable' => FALSE);
+    $options['tag'] = array('default' => '', 'translatable' => FALSE);
+    return $options;
+  }
+
+  /**
+   * Provide a form to edit options for this plugin.
+   */
+  function options_form(&$form, &$form_state) {
+    $form['info'] = array(
+      '#type' => 'fieldset',
+    );
+     $form['info'][$this->id] = array(
+      // TODO: See how to translate this key.
+      '#title' => ucfirst($this->id),
+      '#type' => 'textfield',
+      '#default_value' => $this->options[$this->id],
+      '#description' => t('The unique ID for this @export', array('@export' => $this->title)),
+      '#required' => TRUE,
+      '#maxlength' => 255,
+    );
+
+    if ($form['op'] === 'edit') {
+      $form['info'][$this->id]['#disabled'] = TRUE;
+      $form['info'][$this->id]['#value'] = $this->options[$this->id];
+    }
+
+    $form['info']['tag'] = array(
+      '#title' => t('Tag'),
+      '#type' => 'textfield',
+      '#default_value' => $this->options['tag'],
+      '#description' => t('Tag for this @export', array('@export' => $this->title)),
+    );
+  }
+
+  /**
+   * Validate the options form.
+   */
+  function options_validate(&$form, &$form_state) { }
+
+  /**
+   * Handle any special handling on the validate form.
+   */
+  function options_submit(&$form, &$form_state) { }
+
+  /**
+   * Declares the options this plugin supports, and their default values.
+   *
+   * Derived classes should want to override this.
+   */
+  function set_default_options() {
+    if ($this->plugin['has menu']) {
+
+      $this->options['menu'] = array(
+        'menu item' => !empty($this->plugin['menu item']) ? $this->plugin['menu item'] : str_replace(' ', '-', $this->plugin['name']),
+        'menu prefix' => !empty($this->plugin['menu prefix']) ? $this->plugin['menu prefix'] : 'admin/build',
+
+        // Menu items are translated by the menu system.
+        'menu list title' => 'List '. $this->title,
+
+        'menu add title' => 'Add',
+        'menu add description' => 'Add a new '. $this->title,
+
+        'menu import title' => 'Import',
+        'menu import description' => 'Import '. $this->title .' to your site.',
+        // We allow permissions to import only to users that are allowed to
+        // execute php.
+        'menu import access callback' => 'ctools_access_multiperm',
+        'menu import access arguments' => array('use PHP for block visibility'),
+
+        'menu export page argument' => 4,
+        'menu export title' => 'Export',
+        'menu export description' => 'Export '. $this->title,
+      );
+    }
+
+    // Populate defaults values if export object isn't populated.
+    foreach ($this->option_definition() as $key => $value) {
+      if (!isset($this->options[$key]) && isset($value['default'])) {
+        $this->options[$key] = $value['default'];
+      }
+    }
+  }
+
+  /**
+   * Add menu items per plugin.
+   */
+  function hook_menu() {
+    $options = $this->options['menu'];
+
+    if (empty($options['menu item'])) {
+      // No menu should be defined.
+      return array();
+    }
+
+    $prefix = $options['menu prefix'] .'/'. $options['menu item'];
+
+    $items[$prefix] = array(
+      'title' => $this->title,
+      'description' => $options['menu list description'],
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_admin'),
+      'type' => MENU_NORMAL_ITEM,
+    );
+    $items["$prefix/list"] = array(
+      'title' => 'List',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_admin'),
+      'type' => MENU_DEFAULT_LOCAL_TASK,
+      'weight' => 0,
+    );
+    $items["$prefix/add"] = array(
+      'title' => $options['menu add title'],
+      'description' => $options['menu add description'],
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_form', 'add'),
+      'type' => MENU_LOCAL_TASK,
+      'weight' => 1,
+    );
+    $items["$prefix/import"] = array(
+      'title' => 'Import',
+      'description' => $options['menu import description'],
+      'page callback' => 'ctools_export_ui_import_page',
+      'access callback' => $options['menu import access callback'],
+      'access arguments' => $options['menu import access arguments'],
+      'type' => MENU_LOCAL_TASK,
+      'weight' => 2,
+    );
+    $items["$prefix/list/%ctools_export_ui"] = array(
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_form', 'edit', $options['menu export page argument']),
+      'type' => MENU_CALLBACK,
+    );
+    $items["$prefix/list/%ctools_export_ui/edit"] = array(
+      'title' => 'Edit',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_form', 'edit', 4),
+      'type' => MENU_DEFAULT_LOCAL_TASK,
+      'weight' => -1,
+    );
+    $items["$prefix/list/%ctools_export_ui/clone"] = array(
+      'title' => 'Clone',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_form', 'clone', 4),
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items["$prefix/list/%ctools_export_ui/export"] = array(
+      'title' => $options['menu export title'],
+      'description' => $options['menu export description'],
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_export', 4),
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items["$prefix/list/%ctools_export_ui/revert"] = array(
+      'title' => 'Revert',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_confirm', 'revert', 4),
+      'access callback' => 'ctools_export_ui_task_access',
+      'access arguments' => array(4, 'revert'),
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items["$prefix/list/%ctools_export_ui/delete"] = array(
+      'title' => 'Delete',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_confirm', 'delete', 4),
+      'access callback' => 'ctools_export_ui_task_access',
+      'access arguments' => array(4, 'delete'),
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items["$prefix/list/%ctools_export_ui/disable"] = array(
+      'title' => 'Disable',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_confirm', 'disable', 4),
+      'access callback' => 'ctools_export_ui_task_access',
+      'access arguments' => array(4, 'disable'),
+      'type' => MENU_LOCAL_TASK,
+    );
+    $items["$prefix/list/%ctools_export_ui/enable"] = array(
+      'title' => 'Enable',
+      'page callback' => 'drupal_get_form',
+      'page arguments' => array('ctools_export_ui_confirm', 'enable', 4),
+      'access callback' => 'ctools_export_ui_task_access',
+      'access arguments' => array(4, 'enable'),
+      'type' => MENU_LOCAL_TASK,
+    );
+
+    foreach ($items as $path => $item) {
+      $items[$path]['access callback'] = !empty($items[$path]['access callback']) ? $items[$path]['access callback'] : 'user_access';
+      $items[$path]['access arguments'] = !empty($items[$path]['access arguments']) ? $items[$path]['access arguments'] : array('administer site configuration');
+      $items[$path]['file'] = !empty($items[$path]['file']) ? $items[$path]['file'] : 'export-ui.admin.inc';
+      $items[$path]['file path'] = !empty($items[$path]['file path']) ? $items[$path]['file path'] : drupal_get_path('module', 'ctools') .'/includes';
+      // Add the map, so we can get the plugin in export_ui_load().
+      $items[$path]['load arguments'] = array('%map');
+    }
+
+
+    return $items;
+  }
+
+  /**
+   * Load a single exportable.
+   *
+   * Derived class must implement this.
+   *
+   * @param $id
+   *   The unique ID of the exportable.
+   */
+  function load($id, $reset = FALSE) {
+   return;
+  }
+
+  /**
+   * Save an exportable.
+   *
+   * Derived class must implement this.
+   *
+   * @param $export
+   *   The exportale object.
+   */
+  function save($export) {
+    return;
+  }
+
+  /**
+   * Delete an exportable.
+   *
+   * Derived class must implement this.
+   *
+   * @param $export
+   *   The exportale object.
+   */
+  function delete($export) {
+    return;
+  }
+
+}
diff --git plugins/export_ui/ctools_export_ui.inc plugins/export_ui/ctools_export_ui.inc
new file mode 100644
index 0000000..8b355a9
--- /dev/null
+++ plugins/export_ui/ctools_export_ui.inc
@@ -0,0 +1,20 @@
+<?php
+// $Id: export_ui.module,v 1.13.2.48.2.1.2.11 2010/02/28 19:30:48 yhahn Exp $
+
+/**
+ * TODO: Document plugin keys:
+ * - name: The name of the plugin.
+ * - has menu: Deterimne if hook_menu() should delcare items of this plugin.
+ *   Defaults to TRUE?
+ * - menu item: Optional; The menu item that should be used. For example if the
+ *   value is set to 'foo', then the URL will admin/build/foo. If no value is
+ *   defined then the plugin name will be used.
+ */
+$plugin = array(
+  'name' => 'export_ui',
+  'handler' => array(
+    'class' => 'ctools_export_ui',
+  ),
+  // As this is the base class plugin, it shouldn't declare any menu items.
+  'has menu' => FALSE,
+);
