diff --git admin_menu.js admin_menu.js
index 0ba62de..718db26 100644
--- admin_menu.js
+++ admin_menu.js
@@ -16,6 +16,7 @@ Drupal.behaviors.adminMenu = {
     // Initialize settings.
     settings.admin_menu = $.extend({
       suppress: false,
+      overlay_child: false,
       margin_top: false,
       position_fixed: false,
       tweak_modules: false,
@@ -33,7 +34,7 @@ Drupal.behaviors.adminMenu = {
     var $adminMenu = $('#admin-menu:not(.admin-menu-processed)', context);
     // Client-side caching; if administration menu is not in the output, it is
     // fetched from the server and cached in the browser.
-    if (!$adminMenu.length && settings.admin_menu.hash) {
+    if (!$adminMenu.length && settings.admin_menu.hash && !settings.admin_menu.overlay_child) {
       Drupal.admin.getCache(settings.admin_menu.hash, function (response) {
           if (typeof response == 'string' && response.length > 0) {
             $('body', context).prepend(response);
diff --git admin_menu.module admin_menu.module
index 123faa4..1f30820 100644
--- admin_menu.module
+++ admin_menu.module
@@ -139,6 +139,11 @@ function admin_menu_init() {
   // Destination query strings are applied via JS.
   $settings['destination'] = drupal_http_build_query(drupal_get_destination());
 
+  // Tell JS if we're an overlay child so it won't create a duplicate menu
+  if (module_exists('overlay') && overlay_get_mode() == 'child') {
+    $settings['overlay_child'] = TRUE;
+  }
+
   // Hash for client-side HTTP/AJAX caching.
   $cid = 'admin_menu:' . $user->uid . ':' . $language->language;
   if (!empty($_COOKIE['has_js']) && ($hash = admin_menu_cache_get($cid))) {
