diff --git skinr.api.php skinr.api.php
index 4372c9a..7a3d522 100644
--- skinr.api.php
+++ skinr.api.php
@@ -94,15 +94,31 @@ function hook_skinr_config() {
 
 /**
  * Register Skinr API information. This is required for your module to have
- * its include files loaded.
+ * its module plugins loaded.
  *
  * The full documentation for this hook is in the advanced help.
  */
 function hook_skinr_api() {
-  return array(
-    'api' => 1,
-    'path' => drupal_get_path('module', 'modulename'),
-  );
+  return TRUE;
+}
+
+/**
+ * Register a directory containing skinr plugins.
+ *
+ * @param $type
+ *   The type of a plugin being collected; can be 'skins' or 'modules'.
+ *
+ * @return
+ *   The path where skinr should search for plugin files, relative to your
+ *   module's root. Omit leading and trailing slashes.
+ */
+function hook_skinr_include_directory($type) {
+  switch ($type) {
+    case 'skins':
+      // You can just return $type, if you place your skin plugins into a
+      // sub-directory named 'skins'.
+      return $type;
+  }
 }
 
 /**
diff --git skinr.handlers.inc skinr.handlers.inc
index d78d468..db1a36d 100644
--- skinr.handlers.inc
+++ skinr.handlers.inc
@@ -148,10 +148,7 @@ function skinr_submit_handler(&$form, $form_state, $module, $form_settings) {
  * This one is used as the base to reduce errors when updating.
  */
 function skinr_skinr_api() {
-  return array(
-    'api' => 1,
-    'path' => drupal_get_path('module', 'skinr') . '/modules',
-  );
+  return TRUE;
 }
 
 function block_skinr_api() { return skinr_skinr_api(); }
diff --git skinr.module skinr.module
index 1fe0538..39bd416 100644
--- skinr.module
+++ skinr.module
@@ -39,7 +39,8 @@ function skinr_module_implements_alter(&$implementations, $hook) {
  */
 function skinr_init() {
   module_load_include('inc', 'skinr', 'skinr.handlers');
-  skinr_module_load_all_includes();
+  // Load module plugins, but make sure we only load *.skinr.inc files.
+  skinr_load_plugins('modules', '.skinr');
 }
 
 /**
@@ -421,38 +422,123 @@ function skinr_rule_visible($rid) {
 // Include file helpers.
 
 /**
- * Includes $module.skinr.inc files.
+ * Load plugins for Skinr.
+ *
+ * @param $type
+ *   The type of a plugin; can be 'skins' or 'modules'. A skin plugin allows
+ *   you to define groups and skins. A module plugin adds functionality to
+ *   make a module work with Skinr.
+ * @param $filter
+ *   An optional include file name without .inc extension to limit the
+ *   search.
+ *
+ * @return
+ *   An array of plugin details keyed by hook name. The plugin details contain
+ *   the following keys:
+ *   - 'type': Available options are 'module' or 'theme'.
+ *   - 'name': The name of the owner module or theme of this plugin.
+ *   - 'plugin': The name of this plugin.
+ *   - 'path': This plugin's path.
+ *
+ * @see skinr_get_directories()
  */
-function skinr_module_load_all_includes() {
-  foreach (skinr_get_module_apis() as $module => $info) {
-    $file = DRUPAL_ROOT . "/$info[path]/$module.skinr.inc";
-    if (is_file($file)) {
-      require_once $file;
+function skinr_load_plugins($type = 'skins', $filter = NULL) {
+  // Store plugin info statically because the files can't be reincluded, so
+  // there's no use in being able to clear them when using drupal_static().
+  static $plugins = array();
+
+  if (!isset($plugins[$type])) {
+    $plugins[$type] = array();
+
+    // When doing an API check, only check for hook_skinr_api(). Existence of
+    // this function indicates API version 1. API version 2 would require
+    // hook_skinr_api_2() to be implemented.
+    $api = module_implements('skinr_api');
+
+    // Get a list of plugins.
+    $directories = skinr_get_directories($type);
+    foreach ($directories as $source_type => $type_directories) {
+      $file_list = array();
+      foreach ($type_directories as $source => $path) {
+        $file_list[$source] = drupal_system_listing("/{$filter}.inc\$/", $path, 'name', 0);
+      }
+
+      // Load plugins.
+      foreach (array_filter($file_list) as $source => $files) {
+        foreach ($files as $file) {
+          // If $filter was provided, strip that part from $file->name.
+          if (!empty($filter)) {
+            list($file->name) = explode($filter, $file->name, 2);
+          }
+
+          // Do some API checking for module plugins.
+          if ($type == 'modules') {
+            if (!in_array($file->name, $api)) {
+              // API check failed. Don't include this file.
+              continue;
+            }
+          }
+
+          include_once './' . $file->uri;
+          $plugins[$type][$source . '_' . $file->name] = array(
+            'type' => $source_type,
+            'name' => $source,
+            'plugin' => $file->name,
+            'path' => dirname($file->uri),
+          );
+        }
+      }
     }
   }
+
+  return $plugins[$type];
 }
 
 /**
- * Get a list of modules that support skinr.
+ * Return a list of directories by modules and themes implementing hook_skinr_api_2().
+ *
+ * @param $plugintype
+ *   The type of a plugin; can be 'skins' or 'modules'.
+ *
+ * @return
+ *   An array containing a 'module' and/or 'theme' key. Eah of those is
+ *   an array of module/theme names suffixed with '_' and their defined
+ *   directory as key, and full path as value.
+ *
+ * @see skinr_load_plugins()
+ * @see hook_skinr_api_2()
  */
-function skinr_get_module_apis() {
-  $cache = &drupal_static(__FUNCTION__);
-
-  if (!isset($cache)) {
-    $cache = array();
-    foreach (module_implements('skinr_api') as $module) {
-      $function = $module . '_skinr_api';
-      $info = $function();
-      if (isset($info['api']) && $info['api'] == 1.000) {
-        if (!isset($info['path'])) {
-          $info['path'] = drupal_get_path('module', $module);
-        }
-        $cache[$module] = $info;
+function skinr_get_directories($plugintype) {
+  $directories = array();
+
+  // Fetch directory paths for modules.
+  foreach (module_implements('skinr_include_directory') as $module) {
+    // Fetch the path where these plugins can be found.
+    $result = module_invoke($module, 'skinr_include_directory', $plugintype);
+    if (isset($result) && is_string($result)) {
+      $directories['module'][$module] = drupal_get_path('module', $module) . '/' . $result;
+    }
+  }
+
+  // Fetch directory paths for themes.
+  foreach (list_themes() as $theme) {
+    if (!empty($theme->status) && !empty($theme->info['skinr'][$plugintype])) {
+      // Fetch the path where these plugins can be found.
+      $result = $theme->info['skinr'][$plugintype];
+      if (isset($result) && is_string($result)) {
+        $directories['theme'][$theme->name] = drupal_get_path('theme', $theme->name) . '/' . $result;
       }
     }
   }
 
-  return $cache;
+  return $directories;
+}
+
+/**
+ * Implements hook_skinr_include_directory().
+ */
+function skinr_skinr_include_directory($type) {
+  return $type;
 }
 
 // -----------------------------------------------------------------------
@@ -758,24 +844,6 @@ function skinr_skin_info_status_default($default_status = 0) {
 }
 
 /**
- * Get a list of plugin hooks.
- *
- * @return
- *   An array of hook details keyed by hook name. The hook details contain the
- *   following keys:
- *   - 'type': Available options are 'module' or 'theme'.
- *   - 'name': The name of the owner module or theme of this plugin.
- *   - 'plugin': The name of the skins plugin.
- *   - 'path': This plugin's path.
- */
-function skinr_plugin_hooks() {
-  // @todo Load the include files and get an array of hooks; we need to
-  //   know which module and which plugin comprises the hook.
-  $hooks = array();
-  return $hooks;
-}
-
-/**
  * Helper function to prepend a path to an array of stylesheet or script filenames.
  *
  * If the url is absolute (e.g. the url start with 'http://' or 'https://')
@@ -881,19 +949,21 @@ function skinr_get_skin_info() {
     $skin_infos = array();
 
     // Load skins from hook_skinr_skins().
-    $hooks = skinr_plugin_hooks();
-    foreach ($hooks as $hook => $source) {
+    $plugins = skinr_load_plugins('skins');
+    foreach ($plugins as $hook => $source) {
       $function = $hook . '_skinr_skin_info';
-      $result = $function();
-      if (isset($result)) {
-        if (!is_array($result)) {
-          $result = array($result);
-        }
+      if (function_exists($function)) {
+        $result = $function();
+        if (isset($result)) {
+          if (!is_array($result)) {
+            $result = array($result);
+          }
 
-        // Make any programatic changes.
-        skinr_skin_info_process($result, $source);
+          // Make any programatic changes.
+          skinr_skin_info_process($result, $source);
 
-        $skin_infos = array_merge_recursive($skin_infos, $result);
+          $skin_infos = array_merge_recursive($skin_infos, $result);
+        }
       }
     }
 
@@ -919,22 +989,24 @@ function skinr_get_group_info() {
     $group_infos = array();
 
     // Load skins from hook_skinr_groups().
-    $hooks = skinr_plugin_hooks();
-    foreach ($hooks as $hook => $source) {
+    $plugins = skinr_load_plugins('skins');
+    foreach ($plugins as $hook => $source) {
       $function = $hook . '_skinr_group_info';
-      $result = $function();
-      if (isset($result)) {
-        if (!is_array($result)) {
-          $result = array($result);
-        }
+      if (function_exists($function)) {
+        $result = $function();
+        if (isset($result)) {
+          if (!is_array($result)) {
+            $result = array($result);
+          }
 
-        // Make any programatic changes.
-        // Merge in defaults.
-        foreach ($result as $group_name => $group_info) {
-          $result[$group_name] = array_merge(skinr_group_info_default(), $group_info);
-        }
+          // Make any programatic changes.
+          // Merge in defaults.
+          foreach ($result as $group_name => $group_info) {
+            $result[$group_name] = array_merge(skinr_group_info_default(), $group_info);
+          }
 
-        $group_infos = array_merge_recursive($group_infos, $result);
+          $group_infos = array_merge_recursive($group_infos, $result);
+        }
       }
     }
