1. The Core Architecture: Asynchronous and Event-DrivenAt its heart, the iTerm2 Python API is built on asyncio. This is the most critical concept to grasp.Asynchronous Communication: Every interaction with iTerm2—creating a tab, sending text, getting a variable—is a remote procedure call (RPC) over a WebSocket. These operations are not instantaneous. The async and await keywords are mandatory for almost every API call to handle this network latency without freezing your script.Event Loop: The iterm2.run_until_complete() and iterm2.run_forever() functions manage the asyncio event loop for you.run_until_complete(main): For simple scripts that perform a set of actions and then exit.run_forever(main): For daemons—long-running scripts that must continuously listen for events. This is the foundation for most advanced scripts.The Connection Object: Your main(connection) function receives a connection object. This is your lifeline to the iTerm2 application. If this connection is lost, your script will terminate.2. The Object Hierarchy: App -> Window -> Tab -> SessionYou'll interact with iTerm2 through a logical hierarchy of objects.iterm2.App: The root object, obtained via app = await iterm2.async_get_app(connection). It's your entry point to everything else.app.terminal_windows: A list of all open terminal windows.app.current_terminal_window: The window that currently has focus.iterm2.Window: Represents an OS-level window.window.tabs: A list of the tabs within that window.await window.async_create_tab(): Creates a new tab.iterm2.Tab: Represents a tab.tab.sessions: A list of sessions (panes) within that tab.tab.current_session: The active pane in that tab.await tab.async_activate(): Brings focus to this tab.iterm2.Session: This is the most important object—it represents a single terminal pane where your shell runs.await session.async_send_text("some command\n"): Sends text to the session as if you typed it.await session.async_split_pane(): Splits the pane, creating a new session.await session.async_get_screen_contents(): Reads text directly from the terminal buffer.await session.async_get_variable("pid"): Gets the process ID of the foreground job in the session.3. Advanced Capabilities: Beyond Simple ScriptsThis is where the true power of the API lies. To create truly useful automations, you must master these concepts.a. RPCs (Remote Procedure Calls): Making Your Code CallableThe @iterm2.RPC decorator lets you expose your Python functions to be called from iTerm2, for instance, via a key binding, a trigger, or even another script.Registration: An RPC is a two-step process: decorate the function, then register it.@iterm2.RPC
async def say_hello(name="World"):
print(f"Hello, {name}")
# Don't forget to register it!
await say_hello.async_register(connection)
Context with iterm2.Reference: How does your function know which session to act on? You use iterm2.Reference to get contextual information at the time of invocation. This is a fundamental pattern.@iterm2.RPC
async def clear_current_session(session_id=iterm2.Reference("id")):
# 'id' is a built-in variable for the session's unique ID
session = app.get_session_by_id(session_id)
if session:
# Inject a "Clear Scrollback" escape sequence
await session.async_inject(b'\x1b]1337;ClearScrollback\x07')
await clear_current_session.async_register(connection)
You would then bind a key in iTerm2's preferences to the action Invoke Script Function with the invocation clear_current_session().b. Monitors: The Event-Driven CoreMonitors are asyncio context managers that allow your script to react to events happening within iTerm2. They are the heart of any long-running daemon.iterm2.PromptMonitor: Essential for shell-aware scripts. It notifies you when a new prompt appears, a command starts, or a command ends. This is how you can time long-running jobs or read the output of a command.iterm2.VariableMonitor: The most important monitor. It allows you to watch for changes to any iTerm2 variable. This is the primary mechanism for triggering actions. For example, a custom status bar component will re-render when a variable it's watching changes.iterm2.KeystrokeMonitor: Watches for keystrokes, allowing you to create custom keyboard handlers.iterm2.FocusMonitor: Notifies you when the active window, tab, or session changes.iterm2.NewSessionMonitor & iterm2.SessionTerminationMonitor: Lets you run code when sessions are created or destroyed.c. Hooks: Customizing the iTerm2 UI and BehaviorHooks are specialized RPCs that integrate your script directly into the iTerm2 interface. They almost always work in conjunction with VariableMonitor to update dynamically.@iterm2.StatusBarRPC: Create custom components for the status bar. The decorated function returns the text to display. It automatically re-runs when any iterm2.Reference variable it depends on changes.@iterm2.TitleProviderRPC: Programmatically set the title of a tab or window. A perfect example is displaying the current Git branch in the title.@iterm2.ContextMenuProviderRPC: Add custom items to the right-click context menu.d. Variables: The Glue for a Reactive SystemVariables are the communication backbone of the API. Understanding them is non-negotiable for advanced development.Scopes: Variables exist in different scopes: APP, WINDOW, TAB, and SESSION.Built-in Variables: iTerm2 provides many useful variables out of the box, such as id, pid, path, hostname, and autoName.User-Defined Variables: You can create your own variables, which must be prefixed with user.. For example, user.gitBranch. This is the standard way to pass information from your shell to your Python script.Example: Shell -> Script CommunicationIn your .zshrc or .bashrc (requires Shell Integration):function iterm2_print_user_vars() {
iterm2_set_user_var gitBranch $(git branch 2>/dev/null | grep '*' | cut -c3-)
}
In your Python script:@iterm2.TitleProviderRPC
async def git_branch_title(
auto_name=iterm2.Reference("autoName?"),
branch=iterm2.Reference("user.gitBranch?") # Watch the user variable
):
if branch:
return f"{auto_name} ({branch})"
return auto_name or "Shell"
await git_branch_title.async_register(connection, "Git Branch Title", "com.example.git-title")
4. Essential Best PracticesUse AutoLaunch for Daemons: Place any script that uses monitors or registers hooks in ~/Library/Application Support/iTerm2/Scripts/AutoLaunch/.Isolate Profile Changes: When you want to change a setting (like tab color) for just one session, do not modify the full profile. Instead, create an iterm2.LocalWriteOnlyProfile() object, set the desired property on it, and apply it with await session.async_set_profile_properties(change). This prevents you from accidentally modifying the base profile shared by other sessions.Run Tasks Concurrently: A daemon often needs to do multiple things at once (e.g., monitor keystrokes and watch for focus changes). Use asyncio.create_task() to run multiple monitors in the background without blocking each other.Error Handling: Wrap the code inside your asyncio tasks in try...except blocks and print() the exception. Uncaught exceptions in background tasks can fail silently, making debugging a nightmare.Use the Script Console: The Script Console (Scripts -> Manage -> Console) is your best friend. Use print() statements liberally during development to see output, check variable values, and diagnose errors.By mastering this combination of core objects, advanced hooks, event-driven monitors, and the variable system that glues it all together, you can extend iTerm2 to behave exactly as you wish, creating a truly personalized and powerful development environment.
This guide provides a detailed breakdown of the key classes, methods, and decorators in the iTerm2 Python API, functioning as a comprehensive endpoint reference for developers.1. The Application: iterm2.AppThe App object is the root of the hierarchy. It's your gateway to all windows, tabs, and application-level functions.How to get it:app = await iterm2.async_get_app(connection)Key Methods & Propertiesapp.terminal_windows: A list of all open iterm2.Window objects.app.current_terminal_window: The iterm2.Window that currently has keyboard focus.await app.async_activate(): Activates iTerm2, bringing it to the foreground.app.get_session_by_id(session_id): Finds a specific iterm2.Session by its unique ID.await app.async_get_variable(name): Gets the value of a global (App-scoped) variable (e.g., "effectiveTheme").await app.async_set_variable(name, value): Sets a global user-defined variable (name must start with user.).2. The Window: iterm2.WindowRepresents an OS-level window containing tabs.Key Methods & Propertieswindow.tabs: A list of the iterm2.Tab objects within this window.window.current_tab: The currently active iterm2.Tab in this window.await window.async_create_tab(...): Creates a new tab.Parameters: profile (Optional[str]), command (Optional[str]).static async Window.async_create(connection, ...): Creates a new iTerm2 window.3. The Tab: iterm2.TabRepresents a tab within a window, containing one or more panes.Key Methods & Propertiestab.sessions: A list of all iterm2.Session objects (panes) in this tab.tab.current_session: The currently active iterm2.Session in this tab.await tab.async_activate(): Selects this tab.await tab.async_set_title(title): Changes the tab's title using an interpolated string.4. The Session: iterm2.SessionThe most important object, representing a single terminal pane.Key Methods & Propertiessession.session_id: The globally unique identifier for this session.await session.async_send_text(text): Sends text to the session as if typed.await session.async_split_pane(...): Splits the pane.Parameters: vertical (bool), before (bool), profile (Optional[str]).await session.async_get_variable(name): Fetches a session-scoped variable (e.g., "pid", "path").await session.async_inject(data): Injects raw byte data as program output (useful for escape codes).5. Profiles & PreferencesThis is how you programmatically change iTerm2's appearance and behavior.await session.async_get_profile()Description: Fetches the full iterm2.Profile object for a session.Returns: Optional[iterm2.profile.Profile]await profile.async_set_...()Description: The returned Profile object has numerous async_set_* methods to change settings, such as async_set_background_color(), async_set_font(), or async_set_color_preset(). Warning: This modifies the shared profile.Usage:preset = await iterm2.ColorPreset.async_get(connection, "Solarized Dark")
profile = await session.async_get_profile()
if profile and preset:
await profile.async_set_color_preset(preset)
await session.async_set_profile_properties(change)Description: (Best Practice) Modifies properties for only the specified session without altering the base profile that other sessions might use.Parameters:change (iterm2.LocalWriteOnlyProfile): An object where you set desired changes.Usage:change = iterm2.LocalWriteOnlyProfile()
change.set_tab_color(iterm2.Color(255, 0, 0))
change.set_use_tab_color(True)
await session.async_set_profile_properties(change)
await iterm2.preferences.async_get_preference(key)Description: Gets a global (non-profile) preference value.Parameters: key (iterm2.preferences.PreferenceKey).6. RPCs & Registration (Hooks)This is the core of creating interactive scripts. You decorate a function to make it callable from iTerm2, then register it.@iterm2.RPCDescription: A decorator that makes a Python function callable from iTerm2 (e.g., via a key binding).Registration: await my_function.async_register(connection)Context with iterm2.Reference: To get information about the context where the RPC was invoked (like the active session), you use iterm2.Reference as a default value for an argument.Usage:@iterm2.RPC
async def change_font_size(session_id=iterm2.Reference("id"), delta=1):
session = app.get_session_by_id(session_id)
# ... logic to change font size ...
await change_font_size.async_register(connection)
# In iTerm2 Keys prefs, invoke with: change_font_size(delta=1)
@iterm2.StatusBarRPCDescription: A decorator for a function that provides the text for a custom status bar component. The function is automatically re-run when any of its iterm2.Reference variables change.Registration: await component.async_register(connection, coro_function)@iterm2.TitleProviderRPCDescription: A decorator for a function that returns a string to be used as the tab/window title.7. Advanced UI Interactioniterm2.Alert(title, subtitle)Description: Creates a modal alert box.Key Method: await alert.async_run(connection) shows the alert and returns the index of the button clicked.Usage:alert = iterm2.Alert("Action Complete", "The process has finished successfully.")
await alert.async_run(connection)
iterm2.TextInputAlert(title, subtitle, placeholder, default_value)Description: Creates a modal alert with a text input field.Key Method: await alert.async_run(connection) returns the string entered by the user, or None if canceled.iterm2.MainMenu (Class)Description: A class with static methods to interact with the main iTerm2 menu bar.Key Method: await iterm2.MainMenu.async_select_menu_item(connection, identifier)Parameters: identifier (str): The unique ID for the menu item (e.g., "Toggle Full Screen").8. Specialized APIsiterm2.TmuxConnectionDescription: Represents a tmux -CC integration connection. Get a list of them via await iterm2.async_get_tmux_connections(connection).Key Method: await tmux_conn.async_send_command("select-layout tile") sends a command to the tmux server.iterm2.KeystrokeMonitor & iterm2.KeystrokeFilterDescription: Monitors allow you to react to keystrokes, while filters allow you to intercept and prevent them from being processed by iTerm2, enabling custom keyboard handling.Monitors (General)Monitors are the core of event-driven scripts and are used as async with context managers.iterm2.VariableMonitor: Reacts to variable changes. The most important monitor.iterm2.PromptMonitor: Reacts to shell prompt state changes.iterm2.FocusMonitor: Reacts to changes in active window/tab/session.iterm2.NewSessionMonitor: Runs code when a new session is created.