npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tekmidian/itermtabs

v1.1.0

Published

Rename iTerm2 tabs programmatically via iTerm2's native WebSocket API

Downloads

105

Readme

itermtabs

Rename iTerm2 tabs programmatically — the reliable way.

Why

iTerm2's tab title system has multiple layers (session name, tab name, title override), and most programmatic approaches fail:

  • Escape sequences (ESC ]1;title BEL) get overwritten by the shell prompt within milliseconds
  • AppleScript set name on a session changes the session name, not the tab title
  • AppleScript tab name is read-only — set name of tab throws an error
  • tabset / iterm2-tab-set use escape sequences under the hood — same problem

The only reliable method is iTerm2's native WebSocket API, which sets the titleOverride property — the same mechanism used when you double-click a tab to rename it.

This project provides three standalone implementations:

| Version | File | Dependencies | |---------|------|-------------| | Node.js | itermtabs.mjs | ws (WebSocket library) | | Python | itermtabs.py | iterm2, typer, rich | | Rust | rust/ | tungstenite, clap (zero runtime deps when compiled) |

Node.js Version

The Node.js version connects directly to iTerm2's WebSocket API using a hand-rolled Protocol Buffer encoder/decoder. No protobuf library needed — just the ws package.

Install

npm install -g @tekmidian/itermtabs

Usage

# List all tabs
./itermtabs.mjs --list

# Rename by tab ID
./itermtabs.mjs 77 "My Project"

# Rename by name substring (case-insensitive, must be unique)
./itermtabs.mjs "jobs" "Job Search"

The target can be a tab ID (number), a tab name substring (case-insensitive, must match exactly one tab), or a session UUID.

How It Works

  1. Requests an auth cookie from iTerm2 via AppleScript
  2. Connects to iTerm2's unix socket (~/Library/Application Support/iTerm2/private/socket) or TCP port 1912
  3. Sends a ListSessions request and GetVariable requests to resolve the target tab
  4. Sends an InvokeFunction request with iterm2.set_title() to set the title override

The protobuf encoding is hand-rolled for the specific messages needed — field tags, varints, length-delimited strings, and doubles. No protobuf compiler or library required.

Python Version

The Python version uses the official iterm2 module, which handles the WebSocket protocol internally.

Install

# With uv (recommended)
uv pip install iterm2 typer rich

# Or with pip
pip install iterm2 typer rich

Usage

# List all tabs
python itermtabs.py list

# Rename by tab ID
python itermtabs.py rename 77 "My Project"

# Rename by name substring
python itermtabs.py rename "jobs" "Job Search"

# Generate README
python itermtabs.py doc > README.md

Rust Version

The Rust version compiles to a single static binary with no runtime dependencies. It uses the same hand-rolled protobuf approach as the Node.js version.

Build

cd rust
cargo build --release
# Binary at rust/target/release/itermtabs

Usage

# List all tabs
./itermtabs list

# Rename by tab ID
./itermtabs rename 77 "My Project"

# Rename by name substring
./itermtabs rename "jobs" "Job Search"

iTerm2 Configuration

For the API connection to work, iTerm2 must have its Python API enabled:

  1. Open iTerm2 → Preferences → General → Magic
  2. Check "Enable Python API"

The first time you run either version, iTerm2 may show a dialog asking permission for the app to connect.

How Tab Titles Work in iTerm2

iTerm2 has a layered title system:

Display title = titleOverrideFormat ?? titleOverride ?? (profile title format applied to session name)
  • session.name — The session's name (settable via AppleScript, but doesn't control the tab title)
  • tab.titleOverride — Set by double-click rename or the WebSocket API's set_title() function
  • tab.titleOverrideFormat — Format string for the override (usually empty)
  • Profile title components — The profile's "Title" setting (General tab) with variables like \(session.name)

This tool sets titleOverride, which takes precedence over everything except titleOverrideFormat.

Credits

The Python version uses the iterm2 Python module by George Nachman (creator of iTerm2). The Node.js and Rust versions were built by reverse-engineering the same WebSocket protocol that the Python module uses, implementing just the minimal protobuf encoding needed for session listing and title setting.

License

MIT