Making M2 MacBook Sleep When Closed : Disabling Clamshell Mode

This is a note on how to disable clamshell mode on M2 MacBook.

Introduction

When you close the lid of your MacBook while it's connected to an external display (and power), it enters clamshell mode instead of going to sleep. In this mode, the external display stays active and you can continue working.

I wanted to disable this clamshell mode, but after some research, it appears that macOS doesn't provide this as a built-in feature. (It seems there was a configuration command available in the Intel Mac.)

I found a simple method to disable clamshell mode, so I'm sharing it here.

# Working environment
M2 MacBook Air
macOS Sonoma 14.7.3

Note: This article was translated from my original post.

How to Disable Clamshell Mode

Using noclamshell

You can disable clamshell mode by using an open-source small script called noclamshell.

github.com

This noclamshell isn't a complex external tool—it's a minimal script of just about 20 lines.

You can install noclamshell by opening Terminal and running the following commands:

brew install pirj/noclamshell/noclamshell
brew services start noclamshell

Once these commands run successfully, you're done. When you close your MacBook, it will now enter sleep mode instead of clamshell mode (in my case, it goes to sleep about 1 sec after closing).

This achieved exactly the behavior I was looking for. Pretty simple, right?

Appendix: Understanding How noclamshell Works

This noclamshell is a small 20-line script. Let's take a look at what it does.

#!/usr/bin/env bash

LID_CLOSED=$(ioreg -r -k AppleClamshellState | grep AppleClamshellState | grep Yes)
if [ "$LID_CLOSED" ]; then
  EXTERNAL_DISPLAY_CONNECTED=$(pmset -g powerstate | grep AppleDisplay | grep USEABLE)
  if [ "$EXTERNAL_DISPLAY_CONNECTED" ]; then
    AWAKE=$(pmset -g powerstate | grep IODisplayWrangler | grep USEABLE)
    if [ "$AWAKE" ]; then
      pmset sleepnow
    fi
  fi

  NUM_DEVICE_PROXY=$(pmset -g powerstate | grep -c DCPDPDeviceProxy)
  NUM_SERVICE_PROXY=$(pmset -g powerstate | grep -c DCPDPServiceProxy)
  ARM_AWAKE=$(( 0 < NUM_DEVICE_PROXY && NUM_DEVICE_PROXY < 4 ||
        0 < NUM_SERVICE_PROXY && NUM_SERVICE_PROXY < 4 ))
  if [ "$ARM_AWAKE" ]; then
    pmset sleepnow
  fi
fi

Overall, the script performs the following process for both Intel Macs and Apple Silicon Macs: if the PC lid is closed and the system is awake, put it to sleep.

Let's look at each part individually.

LID_CLOSED=$(ioreg -r -k AppleClamshellState | grep AppleClamshellState | grep Yes)
if [ "$LID_CLOSED" ]; then

First, this detects whether the PC lid is closed. If the lid is closed, it proceeds to the subsequent processes; if it's open, nothing happens.

After that, separate processes are provided for Intel Macs and Apple Silicon Macs.

Here's the process for Intel Macs:

  EXTERNAL_DISPLAY_CONNECTED=$(pmset -g powerstate | grep AppleDisplay | grep USEABLE)
  if [ "$EXTERNAL_DISPLAY_CONNECTED" ]; then
    AWAKE=$(pmset -g powerstate | grep IODisplayWrangler | grep USEABLE)
    if [ "$AWAKE" ]; then
      pmset sleepnow
    fi
  fi

This performs a simple process: if an external display is connected and the system is awake, put it to sleep.

Next, here's the process for Apple Silicon Macs:

  NUM_DEVICE_PROXY=$(pmset -g powerstate | grep -c DCPDPDeviceProxy)
  NUM_SERVICE_PROXY=$(pmset -g powerstate | grep -c DCPDPServiceProxy)
  ARM_AWAKE=$(( 0 < NUM_DEVICE_PROXY && NUM_DEVICE_PROXY < 4 ||
        0 < NUM_SERVICE_PROXY && NUM_SERVICE_PROXY < 4 ))
  if [ "$ARM_AWAKE" ]; then
    pmset sleepnow
  fi

This determines whether the system is awake based on the values of device proxy and service proxy. If it's awake, it puts it to sleep.

There are discussions about this detection method in the issues, so check those out if you're interested.


Then, you install and run this script as a background process using the following installation commands.

brew install pirj/noclamshell/noclamshell # Download the script
brew services start noclamshell # Start as a background process

Appendix: Uninstalling noclamshell

If you want to uninstall noclamshell, run the following commands in Terminal.

brew services stop noclamshell
brew uninstall pirj/noclamshell/noclamshell

This stops the configured background process and uninstalls noclamshell.

Conclusion

That's how you can make your MacBook sleep when you close the lid / disable clamshell mode.

I'm glad I was able to achieve this using a simple script without installing any elaborate external tools.

I hope this is helpful to someone.

[Related Articles]

en.bioerrorlog.work

References