diff --git a/ccl.features.inc b/ccl.features.inc
index e69de29..90e3e19 100644
--- a/ccl.features.inc
+++ b/ccl.features.inc
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ *
+ * Integrates Features for Custom Contextual Links.
+ **/
+
+/**
+ * Implements hook_features_export_options. [component_hook]
+ */
+function ccl_features_export_options() {
+  foreach (ccl_get_presets() as $preset) {
+    $presets[$preset->title] = $preset->title;
+  }
+
+  return $presets;
+}
+
+/**
+ * Implements hook_features_export [component hook]
+ */
+function ccl_features_export($data, &$export, $module_name = '') {
+  $export['dependencies']['features'] = 'features';
+  $export['dependencies']['ccl'] = 'ccl';
+
+  foreach (ccl_get_presets() as $preset) {
+    if (in_array($preset->title, $data)) {
+
+      // Make the submodule required.
+      if ($preset->type != 'node') {
+        $export['dependencies']['ccl_' . $preset->type] = 'ccl_' . $preset->type;
+      }
+
+      $export['features']['ccl'][$preset->title] = $preset->title;
+    }
+  }
+
+  return $export;
+}
+
+/**
+ * Implements hook_features_export_render. [component hook]
+ */
+function ccl_features_export_render($module, $data) {
+  $code = array();
+  $presets = ccl_get_presets();
+
+  foreach ($data as $title) {
+    foreach ($presets as $preset) {
+      if ($preset->title == $title) {
+        // We don't want to break the entity cache, so we need to clone the
+        // presetting before unsetting the id.
+        $preset = clone $preset;
+        unset($preset->clid);
+        $code[$title] = $preset;
+      }
+    }
+  }
+  $code = "  return " . features_var_export($code, '  ') . ";";
+  return array('ccl_features_preset' => $code);
+}
+
+/**
+ * Implements hook_features_revert().
+ */
+function ccl_features_revert($module) {
+  ccl_features_rebuild($module);
+}
+
+/**
+ * Implements hook_features_rebuild().
+ *
+ * Rebuilds Custom Contextual Links from code defaults.
+ */
+function ccl_features_rebuild($module) {
+  $presets = module_invoke($module, 'ccl_features_preset');
+  foreach ($presets as $key => $preset) {
+    $preset = (object) $preset;
+
+    $current_record = current(ccl_get_presets($preset->title));
+    if (!empty($current_record)) {
+      $preset->clid = $current_record->clid;
+      drupal_write_record('ccl', $preset, 'clid');
+    }
+    else {
+      drupal_write_record('ccl', $preset);
+    }
+  }
+}
diff --git a/ccl.module b/ccl.module
index dd64c76..fef236f 100644
--- a/ccl.module
+++ b/ccl.module
@@ -59,6 +59,35 @@ function ccl_menu() {
   return $items;
 }
 
+/**
+ * Implements hook_features_api().
+ */
+function ccl_features_api() {
+  return array(
+    'ccl' => array(
+      'name' => 'Custom Contextual Links',
+      'file' => drupal_get_path('module', 'ccl') . '/ccl.features.inc',
+      'default_hook' => 'ccl_features_preset',
+      'feature_source' => TRUE,
+    ),
+  );
+}
+
+function ccl_get_presets($title = NULL) {
+  $presets = array();
+  if ($title) {
+    $results = db_query('SELECT * FROM {ccl} WHERE title = :title;', array(':title' => $title));
+  }
+  else {
+    $results = db_query('SELECT * FROM {ccl};');
+  }
+
+  while ($result = $results->fetchObject()) {
+    $presets[] = $result;
+  }
+  return $presets;
+}
+
 /*
  * Implements hook_contextual_links_view_alter().
  *
