Skip to main content

Add a script to set the title of an iTerm 2 tab

ID
8c79ecb
date
2025-09-02 16:38:08+00:00
author
Alex Chan <alexc@tailscale.com>
parent
d6d94cd
message
Add a script to set the title of an iTerm 2 tab
changed files
4 files, 66 additions, 39 deletions

Changed files

macos/README.md (7352) → macos/README.md (7691)

diff --git a/macos/README.md b/macos/README.md
index 38bf6e1..467df21 100644
--- a/macos/README.md
+++ b/macos/README.md
@@ -73,6 +73,10 @@ scripts = [
         "description": "Set the Finder comment of a file, which will be indexed by Spotlight for searching"
     },
     {
+        "usage": "set_iterm_tab_title.py TITLE",
+        "description": "Set the title of a tab in iTerm 2"
+    },
+    {
         "usage": "sterilise [PATH]",
         "description": "alias for <code>xattr -d com.apple.quarantine</code>"
     },
@@ -222,6 +226,15 @@ cog_helpers.create_description_table(folder_name=folder_name, scripts=scripts)
   </dd>
 
   <dt>
+    <a href="https://github.com/alexwlchan/scripts/blob/main/macos/set_iterm_tab_title.py">
+      <code>set_iterm_tab_title.py TITLE</code>
+    </a>
+  </dt>
+  <dd>
+    Set the title of a tab in iTerm 2
+  </dd>
+
+  <dt>
     <a href="https://github.com/alexwlchan/scripts/blob/main/macos/sterilise">
       <code>sterilise [PATH]</code>
     </a>
@@ -251,4 +264,4 @@ cog_helpers.create_description_table(folder_name=folder_name, scripts=scripts)
     </p>
   </dd>
 </dl>
-<!-- [[[end]]] (sum: 04EuY3I563) -->
+<!-- [[[end]]] (sum: uJMF1iuiOs) -->

macos/set_iterm_tab_title.py (0) → macos/set_iterm_tab_title.py (638)

diff --git a/macos/set_iterm_tab_title.py b/macos/set_iterm_tab_title.py
new file mode 100755
index 0000000..247ad20
--- /dev/null
+++ b/macos/set_iterm_tab_title.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+"""
+Set the title of an iTerm 2 tab.
+"""
+
+import sys
+
+import iterm2
+
+
+def set_title(title: str):
+    async def main(connection: iterm2.connection.Connection) -> None:
+        app = await iterm2.async_get_app(connection)
+
+        window = app.current_window
+        if window is None:
+            return
+
+        tab = window.current_tab
+        if tab is None:
+            return
+
+        await tab.async_set_title(title)
+
+    iterm2.run_until_complete(main)
+
+
+if __name__ == "__main__":
+    try:
+        title = sys.argv[1]
+    except IndexError:
+        sys.exit(f"Usage: {__file__} TITLE")
+
+    set_title(title)

requirements.in (241) → requirements.in (248)

diff --git a/requirements.in b/requirements.in
index 16c0589..99ab26b 100644
--- a/requirements.in
+++ b/requirements.in
@@ -4,6 +4,7 @@ datasette
 httpx
 humanize
 hyperlink
+iterm2
 keyring
 naturalsort==1.5.1  # Used as 'natsort'
 Pillow

requirements.txt (3440) → requirements.txt (3076)

diff --git a/requirements.txt b/requirements.txt
index 3adc263..b7e4fb7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -10,17 +10,13 @@ asgi-csrf==0.11
     # via datasette
 asgiref==3.9.1
     # via datasette
-backports-tarfile==1.2.0
-    # via jaraco-context
 beautifulsoup4==4.13.5
     # via -r requirements.in
 certifi==2025.8.3
     # via
     #   httpcore
     #   httpx
-cffi==1.17.1
-    # via cryptography
-click==8.1.8
+click==8.2.1
     # via
     #   click-default-group
     #   datasette
@@ -33,14 +29,8 @@ click-default-group==1.2.4
     #   sqlite-utils
 cogapp==3.5.1
     # via -r requirements.in
-cryptography==45.0.6
-    # via secretstorage
 datasette==0.65.1
     # via -r requirements.in
-exceptiongroup==1.3.0
-    # via
-    #   anyio
-    #   pytest
 flexcache==0.3
     # via datasette
 flexparser==0.4
@@ -66,10 +56,10 @@ idna==3.10
     #   anyio
     #   httpx
     #   hyperlink
-importlib-metadata==8.7.0
-    # via keyring
 iniconfig==2.1.0
     # via pytest
+iterm2==2.10
+    # via -r requirements.in
 itsdangerous==2.2.0
     # via
     #   asgi-csrf
@@ -80,12 +70,8 @@ jaraco-classes==3.4.0
     # via keyring
 jaraco-context==6.0.1
     # via keyring
-jaraco-functools==4.2.1
+jaraco-functools==4.3.0
     # via keyring
-jeepney==0.9.0
-    # via
-    #   keyring
-    #   secretstorage
 jinja2==3.1.6
     # via datasette
 keyring==25.6.0
@@ -110,9 +96,11 @@ pillow==11.3.0
     #   pillow-heif
 pillow-heif==1.1.0
     # via -r requirements.in
+pip==25.2
+    # via datasette
 pipx==1.7.1
     # via -r requirements.in
-platformdirs==4.3.8
+platformdirs==4.4.0
     # via
     #   datasette
     #   pipx
@@ -121,8 +109,8 @@ pluggy==1.6.0
     #   datasette
     #   pytest
     #   sqlite-utils
-pycparser==2.22
-    # via cffi
+protobuf==6.32.0
+    # via iterm2
 pygments==2.19.2
     # via
     #   -r requirements.in
@@ -137,15 +125,15 @@ python-multipart==0.0.20
     # via asgi-csrf
 pyyaml==6.0.2
     # via datasette
-ruff==0.12.10
+ruff==0.12.11
     # via -r requirements.in
-secretstorage==3.3.3
-    # via keyring
+setuptools==80.9.0
+    # via datasette
 six==1.17.0
     # via python-dateutil
 sniffio==1.3.1
     # via anyio
-soupsieve==2.7
+soupsieve==2.8
     # via beautifulsoup4
 sqlite-fts4==1.0.3
     # via sqlite-utils
@@ -155,28 +143,19 @@ tabulate==0.9.0
     # via sqlite-utils
 termcolor==3.1.0
     # via -r requirements.in
-tomli==2.2.1
-    # via
-    #   pipx
-    #   pytest
 tqdm==4.67.1
     # via -r requirements.in
-typing-extensions==4.14.1
+typing-extensions==4.15.0
     # via
-    #   anyio
-    #   asgiref
     #   beautifulsoup4
     #   datasette
-    #   exceptiongroup
     #   flexcache
     #   flexparser
-    #   pypdf
-    #   uvicorn
 userpath==1.9.2
     # via pipx
 uvicorn==0.35.0
     # via datasette
-yt-dlp==2025.8.22
+websockets==15.0.1
+    # via iterm2
+yt-dlp==2025.8.27
     # via -r requirements.in
-zipp==3.23.0
-    # via importlib-metadata