Skip to content

Instantly share code, notes, and snippets.

@jamesmacfie
Created October 22, 2019 02:53
Show Gist options
  • Save jamesmacfie/2061023e5365e8b6bfbbc20792ac90f8 to your computer and use it in GitHub Desktop.
Save jamesmacfie/2061023e5365e8b6bfbbc20792ac90f8 to your computer and use it in GitHub Desktop.
iTerm 2 - script to change theme depending on Mac OS dark mode

How to use

In iTerm2, in the menu bar go to Scripts > Manage > New Python Script

Select Basic. Select Long-Running Daemon

Give the script a decent name (I chose auto_dark_mode.py)

Save and open the script in your editor of choice.

Copy and paste the script below and save

Go back to iTerm2, go to Scripts in the menu bar and select the script you just saved.

Try toggling Dark mode to see what happens! Reminder it's under Appearance in the System Settings

Changing what themes this uses

Note in the script below on lines 15 and 17 that we have a string that we're passing to iTerm2. Change these to whatever you like. The text is whatever appears in the dropdown in the iTerm2 settings under Profile/Color for when you'd want to change the theme manually.

After you change the script you'll have to stop and start the script if it's running already

#!/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, "Solarized Dark")
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)
@majutsushi
Copy link

Since the mode is based on the system-wide mode you can use defaults read -g AppleInterfaceStyle to determine if dark mode is enabled. The command will return Dark when in dark mode and nothing when not in dark mode.

@fosemberg
Copy link

fosemberg commented Sep 14, 2022

If you want the script to run itself when opening iterm2, you need to put it in the folder, that is not exist by default:
~/Library/ApplicationSupport/iTerm2/Scripts/AutoLaunch

mkdir -p ~/Library/ApplicationSupport/iTerm2/Scripts/AutoLaunch
mv ~/Library/ApplicationSupport/iTerm2/Scripts/auto_dark_mode.py ~/Library/ApplicationSupport/iTerm2/Scripts/AutoLaunch/auto_dark_mode.py

https://iterm2.com/python-api/tutorial/running.html#auto-run-scripts

@lpolon
Copy link

lpolon commented Dec 4, 2023

Thank you!

@wotori
Copy link

wotori commented Mar 20, 2024

Thank you for sharing. I managed to make it work.

For the first time, I encountered this error:

iterm2.colorpresets.ListPresetsException: PRESET_NOT_FOUND

However, since I had created custom profiles before, I was surprised by this occurrence. I decided to list all the presets:

presets = await iterm2.ColorPreset.async_get_list(connection)
print("Presets: ", [preset for preset in presets])

To my surprise, I discovered that my custom presets were missing. The list of I obtained was:

Presets: ['Dark Background', 'Tango Light', 'Smoooooth', 'Light Background', 'Pastel (Dark Background)', 'Solarized Dark', 'Tango Dark', 'Solarized Light']

Now, I understand that this issue is related to color presets rather than the profile, which allows for hot reloading without restarting the console. This feature is truly cool!

@malaiam
Copy link

malaiam commented Mar 20, 2024

Guys, this is an integrated feature in v3.5 (official beta release currently). So this script is not necessary anymore.

image

@MartinDelille
Copy link

MartinDelille commented Apr 16, 2024

This code runs automatically. How could I adapt it to switch to light or dark on demand ?

I would like the script to run with a parameter like:

$ switch_iterm_theme dark

@MartinDelille
Copy link

This script use the desired color preset as argument:

import asyncio
import iterm2
import sys

async def main(connection):
    async with iterm2.VariableMonitor(connection, iterm2.VariableScopes.APP, "effectiveTheme", None) as mon:
        preset = await iterm2.ColorPreset.async_get(connection, sys.argv[1])

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

iterm2.run_forever(main)

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