Skip to content

Instantly share code, notes, and snippets.

@FradSer
Last active October 8, 2024 12:39
Show Gist options
  • Save FradSer/de1ca0989a9d615bd15dc6eaf712eb93 to your computer and use it in GitHub Desktop.
Save FradSer/de1ca0989a9d615bd15dc6eaf712eb93 to your computer and use it in GitHub Desktop.
Switch iTerm2 color preset automatic base on macOS dark mode.

The latest beta (3.5) includes separate color settings for light & dark mode. Toggling dark mode automatically switches colors.

Vist iTerm2 homepage or use brew install iterm2-beta to download the beta. Thanks @stefanwascoding.


  1. Add switch_automatic.py to ~/Library/ApplicationSupport/iTerm2/Scripts/AutoLaunch with:
#!/usr/bin/env python3

import asyncio
import iterm2

async def main(connection):
    async with iterm2.VariableMonitor(connection, iterm2.VariableScopes.APP, "effectiveTheme", None) as mon:
        while True:
            # Block until theme changes
            theme = await mon.async_get()

            # Themes have space-delimited attributes, one of which will be light or dark.
            parts = theme.split(" ")
            if "dark" in parts:
                preset = await iterm2.ColorPreset.async_get(connection, "Dark Background")
            else:
                preset = await iterm2.ColorPreset.async_get(connection, "Light Background")

            # Update the list of all profiles and iterate over them.
            profiles=await iterm2.PartialProfile.async_query(connection)
            for partial in profiles:
                # Fetch the full profile and then set the color preset in it.
                profile = await partial.async_get_full_profile()
                await profile.async_set_color_preset(preset)

iterm2.run_forever(main)

Change Dark Background and Light Background to color presets you like.

  1. Enabled switch_automatic.py from Scripts menu.
@jirikrepl
Copy link

jirikrepl commented Jun 2, 2020

@iodic
Copy link

iodic commented Jan 28, 2021

Thanks a lot! :) Working great for me on MacOS Big Sur and iTerm v3.4.4beta4.

Copy link

ghost commented Feb 22, 2021

Thank you!

@d9i
Copy link

d9i commented Mar 1, 2021

Thank you so much for this!

I noticed that this script doesn't check if iTerm is the correct color when the app is started, meaning that you could get the wrong colors if you quit iTerm2 during the day and opened it at night, after the theme switch.

I added a check on app start to the script to address this:

#!/usr/bin/env python3

import asyncio
import iterm2

async def changeTheme(theme_parts, connection):
    # Themes have space-delimited attributes, one of which will be light or dark.
    if "dark" in theme_parts:
        preset = await iterm2.ColorPreset.async_get(connection, "Dark Background")
    else:
        preset = await iterm2.ColorPreset.async_get(connection, "Light Background")

    # Update the list of all profiles and iterate over them.
    profiles=await iterm2.PartialProfile.async_query(connection)
    for partial in profiles:
        # Fetch the full profile and then set the color preset in it.
        profile = await partial.async_get_full_profile()
        await profile.async_set_color_preset(preset)

async def main(connection):
    # Set color scheme correctly at app start
    app = await iterm2.async_get_app(connection)
    parts = await app.async_get_theme()
    await changeTheme(parts, connection)


    async with iterm2.VariableMonitor(connection, iterm2.VariableScopes.APP, "effectiveTheme", None) as mon:
        while True:
            # Block until theme changes
            theme = await mon.async_get()
            parts = theme.split(" ")
            await changeTheme(parts, connection)


iterm2.run_forever(main)

Hope this is helpful!

@FradSer
Copy link
Author

FradSer commented Mar 2, 2021

👍Really helpful, thanks.

@jirikrepl
Copy link

👍 @d9i seems to be working great!

@mtzrmzia
Copy link

i got this error... why?
ended unexpectedly
image

@kazlauskis
Copy link

@d9i thanks!

@thomashexton
Copy link

i got this error... why?
ended unexpectedly
image

I was getting this error too. However I resolved it by choosing some of the base themes. Solarized Light and Solarized Dark. See if that fixes it for you too? They may not be the exact themes you want though, but at least my eyes aren't blown out at night now.

@pxlshpr
Copy link

pxlshpr commented Jun 2, 2021

@d9i thank you, works like a charm

@arosca
Copy link

arosca commented Jun 12, 2021

👍 thanks

@SinisterStairs
Copy link

SinisterStairs commented Jun 18, 2021

There seems to be a bug with this script, where it spawns multiple processes that don't go away after iTerm2 has ended.

My laptop fans were constantly running and I saw bash was consuming 99% of a CPU. Looking more carefully I saw a screenful of this script running. After manually killing them all, CPU returned to normal.

I notice when I start up iTerm2, it launches two processes using ~/.config/iterm2/AppSupport/Scripts/AutoLaunch/auto_dark_mode.py. (I think that's normal, because one is the child of the other?)

But when you completely exit the iTerm2 application, those processes remain running. Then, if you launch iTerm2 again, two more processes are spawned for 4 total, and so on.

These processes aren't exiting when iTerm2 exits. I'm using iTerm2 on Mojave; I'll test it on M1/Big Sur as well.

[Edited for formatting.]

@SinisterStairs
Copy link

SinisterStairs commented Jun 18, 2021

If I open the script console and close my sessions (i.e. iTerm2 hasn't exited because the console is open) then quit, the processes get cleaned up.

But if I don't have the script console open and close my sessions (iTerm2 exits) or quit, the processes hang around.

EDIT2: I thought it might be related to my preferences, but disabling them didn't seem to fix it:

  • General | Closing | Quit when all windows are closed
  • Profiles | Session | After a session ends No Action

@plivox
Copy link

plivox commented Jun 19, 2021

Hello, here is my version if anyone is interested.

Automatic iTerm2 preset switching on MacOS

#!/usr/bin/env python3

import asyncio
import iterm2

THEME_LIGHT = "Tango Light"
THEME_DARK = "Tango Dark"


class AutoSwtichTheme:
    def __init__(self, connection, light="Light Background", dark="Dark Background"):
        self.connection = connection
        self.light = light
        self.dark = dark

    async def get_app(self):
        return await iterm2.async_get_app(self.connection)

    async def get_theme(self) -> str:
        parts = await (await self.get_app()).async_get_theme()
        if len(parts) <= 1:
            return parts[0]
        return ""

    async def set_color_preset(self, theme):
        preset = await iterm2.ColorPreset.async_get(
            self.connection, self.light if theme == "light" else self.dark
        )

        profiles = await iterm2.PartialProfile.async_query(self.connection)
        for partial in profiles:
            await (await partial.async_get_full_profile()).async_set_color_preset(
                preset
            )


async def quit(connection):
    while True:
        if not connection.websocket.open:
            exit(0)
        await asyncio.sleep(1)


async def main(connection):
    asyncio.ensure_future(quit(connection), loop=asyncio.get_event_loop())

    ast = AutoSwtichTheme(connection, THEME_LIGHT, THEME_DARK)
    await ast.set_color_preset(await ast.get_theme())

    async with iterm2.VariableMonitor(
        connection, iterm2.VariableScopes.APP, "effectiveTheme", None
    ) as mon:
        while True:
            # Block until theme changes
            theme = await mon.async_get()

            # Set preset if theme has changed
            await ast.set_color_preset(theme)


try:
    iterm2.run_forever(main)
except:
    print("Unable to connect on iTerm2 application")

@stefanwascoding
Copy link

The latest beta (3.5) includes separate color settings for light & dark mode. Toggling dark mode automatically switches colors.

@plivox
Copy link

plivox commented Oct 3, 2021

The latest beta (3.5) includes separate color settings for light & dark mode. Toggling dark mode automatically switches colors.

Great!

@xplosionmind
Copy link

Hello everybody, this script is really helpful, but I find myself having to click on “Scripts > switch_automatic.py” when the system theme switches in order to make the iTerm theme change… shouldn’t it happen automatically as soon as the system theme changes? Am I doing something wrong?

@FradSer
Copy link
Author

FradSer commented Dec 29, 2021

@xplosionmind in ~/Library/ApplicationSupport/iTerm2/Scripts folder you can create a new folder AutoLaunch, then put the script into it, it will work always.
But the official solution is download latest beta (3.5) as @stefanwascoding said.

@xplosionmind
Copy link

in ~/Library/ApplicationSupport/iTerm2/Scripts folder you can create a new folder AutoLaunch, then put the script into it, it will work always.

Thanks! It now works wonderfully.


But the official solution is download latest beta (3.5) as @stefanwascoding said.

Does this mean that since 3.5 there won’t be any necessity for this script to be used?

@FradSer
Copy link
Author

FradSer commented Dec 30, 2021

@aravinds92
Copy link

Hello folks - I was able to get the background switching from dark to light whenever the system settings toggle. But the text color seems to reset to white every time. Is there a command I can use to set the text to different rgb combinations?

@rtauziac
Copy link

The latest beta (3.5) includes separate color settings for light & dark mode. Toggling dark mode automatically switches colors.

Works like a charm. Hope this will be included in future stable versions.

the text color seems to reset to white every time.

Maybe this has been fixed since I don’t experience this 🤷‍♀️

@johnnyutahh
Copy link

Can anyone share why this feature (of "matching" macOS system light/dark theme/mode for foreground-and-background of terminal windows) is not already "built in" to iTerm2?

-Maybe- said feature has already been added since this discussion thread started?

@pdostal
Copy link

pdostal commented Feb 15, 2023

@johnnyutahh It appears that it's still in beta. So please use the beta 😄

@fauzan-n
Copy link

fauzan-n commented May 5, 2023

Screenshot 2023-05-05 at 1 42 41 PM
Working well Thanks!

@johnnyutahh
Copy link

Works well for me, too, just at it looks per @fauzan-n's above screenshot. Thank you @pdostal and iTerm2 team!

@stevo-knievo
Copy link

First of all, thanks for adding the feature!!

I can't install the beta version via brew...

Any advice? Thank you!

brew install iterm2-beta
Warning: No available formula with the name "iterm2-beta".
==> Searching for similarly named formulae and casks...
==> Casks
iterm2

To install iterm2, run:
  brew install --cask iterm2

@Moulick
Copy link

Moulick commented Mar 19, 2024

@stevo-knievo it's available as homebrew/cask-versions/iterm2-beta

@henryiii
Copy link

Released! :)

@FradSer
Copy link
Author

FradSer commented Jun 6, 2024

Released! :)

🎉🎉🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment