Skip to content

Instantly share code, notes, and snippets.

@scjudd
Created January 21, 2026 19:53
Show Gist options
  • Select an option

  • Save scjudd/927f74bb348a7b636c3c07165ebb03d0 to your computer and use it in GitHub Desktop.

Select an option

Save scjudd/927f74bb348a7b636c3c07165ebb03d0 to your computer and use it in GitHub Desktop.
iTerm2 script to automatically adjust font size and window dimensions when entering/exiting fullscreen
#!/usr/bin/env python3
"""
iTerm2 Fullscreen Font Size Automation
Automatically sets font size to 18pt when entering fullscreen and 12pt when
exiting fullscreen. Resets window to 80x25 when exiting fullscreen.
Setup:
1. Enable Python API in iTerm2:
Preferences > General > Magic > Enable Python API
2. Install Python Runtime (if not already installed):
Scripts > Manage > Install Python Runtime
3. Create the AutoLaunch folder (if it doesn't exist):
mkdir -p ~/Library/Application\ Support/iTerm2/Scripts/AutoLaunch
4. Copy this script to the AutoLaunch folder:
cp fullscreen_font_size.py ~/Library/Application\ Support/iTerm2/Scripts/AutoLaunch/
5. Restart iTerm2 or run the script manually:
Scripts > AutoLaunch > fullscreen_font_size
Verification:
- Check script is running: Scripts > Manage > Console
- Press Cmd+Enter to toggle fullscreen and verify font size changes
- Works independently for multiple windows
Configuration:
Adjust the constants below to customize font sizes and window dimensions.
"""
import asyncio
import iterm2
import re
FULLSCREEN_FONT_SIZE = 18
WINDOWED_FONT_SIZE = 12
WINDOWED_COLUMNS = 80
WINDOWED_ROWS = 25
FONT_REGEX = re.compile(r'^(.*) (\d+)(.*)$')
# Track which windows are currently in fullscreen
fullscreen_windows: dict[str, bool] = {}
def set_font_size(font_string: str, new_size: int) -> str:
"""Replace the font size in an iTerm2 font string."""
match = FONT_REGEX.match(font_string)
if match:
return f"{match.group(1)} {new_size}{match.group(3)}"
return font_string
async def is_fullscreen(window: iterm2.Window) -> bool:
"""Check if window is in fullscreen mode."""
style = await window.async_get_variable("style")
return style in ("native full screen", "non-native full screen")
async def set_window_font_size(window: iterm2.Window, size: int):
"""Set font size for all sessions in a window."""
for tab in window.tabs:
for session in tab.sessions:
profile = await session.async_get_profile()
current_font = profile.normal_font
new_font = set_font_size(current_font, size)
await profile.async_set_normal_font(new_font)
async def set_window_grid_size(window: iterm2.Window, columns: int, rows: int):
"""Set window size to specified columns and rows."""
for tab in window.tabs:
for session in tab.sessions:
await session.async_set_grid_size(iterm2.Size(columns, rows))
async def check_window_fullscreen(window: iterm2.Window):
"""Check and update fullscreen state for a window."""
window_id = window.window_id
currently_fullscreen = await is_fullscreen(window)
was_fullscreen = fullscreen_windows.get(window_id, False)
if currently_fullscreen and not was_fullscreen:
await set_window_font_size(window, FULLSCREEN_FONT_SIZE)
fullscreen_windows[window_id] = True
elif not currently_fullscreen and was_fullscreen:
await set_window_font_size(window, WINDOWED_FONT_SIZE)
await set_window_grid_size(window, WINDOWED_COLUMNS, WINDOWED_ROWS)
fullscreen_windows[window_id] = False
async def monitor_window(connection: iterm2.Connection, window: iterm2.Window):
"""Monitor a single window for style changes."""
window_id = window.window_id
# Initialize state
fullscreen_windows[window_id] = await is_fullscreen(window)
try:
async with iterm2.VariableMonitor(
connection,
iterm2.VariableScopes.WINDOW,
"style",
window_id
) as monitor:
while True:
await monitor.async_get()
app = await iterm2.async_get_app(connection)
window = app.get_window_by_id(window_id)
if window is None:
break
await check_window_fullscreen(window)
except asyncio.CancelledError:
pass
finally:
fullscreen_windows.pop(window_id, None)
async def main(connection: iterm2.Connection):
app = await iterm2.async_get_app(connection)
# Track monitor tasks for each window
monitor_tasks: dict[str, asyncio.Task] = {}
def start_monitoring_window(window: iterm2.Window):
"""Start monitoring a window if not already monitoring."""
window_id = window.window_id
if window_id not in monitor_tasks:
task = asyncio.create_task(monitor_window(connection, window))
monitor_tasks[window_id] = task
# Start monitoring existing windows
for window in app.windows:
start_monitoring_window(window)
# Monitor for new windows
async with iterm2.FocusMonitor(connection) as monitor:
while True:
update = await monitor.async_get_next_update()
# Check for new windows when focus changes
app = await iterm2.async_get_app(connection)
current_window_ids = {w.window_id for w in app.windows}
# Start monitoring any new windows
for window in app.windows:
start_monitoring_window(window)
# Clean up tasks for closed windows
closed_windows = set(monitor_tasks.keys()) - current_window_ids
for window_id in closed_windows:
task = monitor_tasks.pop(window_id, None)
if task:
task.cancel()
iterm2.run_forever(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment