Skip to content

Instantly share code, notes, and snippets.

Created June 7, 2022 14:02
Show Gist options
  • Save doublethefish/c339b659738fdb652e820e3b40f97f36 to your computer and use it in GitHub Desktop.
Save doublethefish/c339b659738fdb652e820e3b40f97f36 to your computer and use it in GitHub Desktop.

A script to update the color presets used by iTerm when the System Preferences -> General -> Apperance setting changes (either manually or via Automator).

Inspired by

How to use

  1. In iTerm2, in the menu bar go to Scripts > Manage > New Python Script
  2. Select Basic.
  3. Select Long-Running Daemon
  4. Give the script a decent name (I also chose
  5. Save and open the script in your editor of choice.
  6. Copy and paste the script below and save
  7. Go back to iTerm2, go to Scripts in the menu bar and select the script you just saved.
  8. Try toggling Dark mode to see what happens! Reminder it's under Appearance in the System Settings

Changing what themes this uses

Update the THEME_DARK and THEME_LIGHT variables at the top of the script.


After you change the script you'll have to restart the script if it's running already.

  1. Open the scipts maneger: Scripts -> Manage -> Console
  2. Click the script auto_dark_mode
  3. Click the Restart button

Trouble shooting

Chose Scripts -> Manage -> Console at look at the latest log for auto_dark_mode

#!/usr/bin/env python3.
"""Sets the Color Preset on all sessions and profiles when changed in the System Preferences"""
import asyncio
import iterm2
# This script works in the "basic" iTerm environment.
# The themes to use:
# The options are (at time of writing):
# - 'Dark Background'
# - 'Tango Light'
# - 'Smoooooth'
# - 'Light Background'
# - 'Pastel (Dark Background)'
# - 'Solarized Dark'
# - 'Tango Dark'
# - 'Solarized Light'
THEME_DARK = "Dark Background"
THEME_LIGHT = "Light Background"
async def set_color_preset_on_all_profiles(connection, color_preset):
profiles = await iterm2.PartialProfile.async_query(connection)
for partial in profiles:
# Fetch the full profile and then set the color color_preset in it.
profile = await partial.async_get_full_profile()
await profile.async_set_color_preset(color_preset)
async def set_color_preset_on_all_sessions(app, color_preset):
for window in app.terminal_windows:
for tab in window.tabs:
for session in tab.sessions:
profile = await session.async_get_profile()
await profile.async_set_color_preset(color_preset)
async def get_preset_for_theme(connection, theme):
"""Updates the Color Preset for all profiles and across all sessions."""
theme_to_use = THEME_DARK if "dark" in theme else THEME_LIGHT
color_preset = await iterm2.ColorPreset.async_get(connection, theme_to_use)
available_themes = await iterm2.ColorPreset.async_get_list(connection)
f"Failed to set theme to '{theme_to_use}', available are: {available_themes}"
return color_preset
async def set_theme_everywhere(app, connection, cur_osx_theme):
"""Updates the Color Preset for all profiles and across all sessions."""
color_preset = await get_preset_for_theme(connection, cur_osx_theme)
await set_color_preset_on_all_profiles(connection, color_preset)
await set_color_preset_on_all_sessions(app, color_preset)
async def main(connection):
"""Updates the current theme on load, and monitors os-level theme changes.
Updates *all* sessions and profiles to match one of the given themes."""
# First set the Color Preset when we load iTerm
app = await iterm2.async_get_app(connection)
initial_theme = await app.async_get_theme()
await set_theme_everywhere(app, connection, initial_theme)
# Now monitor for system-level events (e.g. manual System Preferences changes or
# Automator-triggered changes) and update the Color Preset.
async with iterm2.VariableMonitor(
connection, iterm2.VariableScopes.APP, "effectiveTheme", None
) as mon:
while True:
# Block until theme changes
theme = await mon.async_get()
await set_theme_everywhere(app, connection, theme)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment