Skip to content

Changing iTerm2 Tab Colors

Published: at 07:05 AM

Auto‑color your iTerm2 tabs by project (with zsh)

I’ve been having a lot of Claude Code terminal windows open and more than once typed into the wrong one. I wan’ted to color code each project for quick visual feedback. Next step is to maybe get around to syncing VS Code’s border color to match my Iterm2 tab color. Yeah, I guess I could use the integrated VS Code terminal, but I never got used to it.

If you juggle multiple repos at once, coloring each iTerm2 tab to match the project’s primary color makes context‑switching painless. This guide shows a tiny, shell‑only solution that automatically tints the tab/title bar when you cd into a project and resets it when you leave. Optional add‑ons let you tint the terminal background too, and even pull colors from Tailwind.

iTerm2 window showing multiple green colored tabs


What you’ll build


Requirements

Tip: If you use tmux, test the color change outside tmux first. Some tmux setups filter non‑standard escape sequences.


1) Quick sanity check: can iTerm2 tint tabs?

Run this once in a fresh iTerm2 tab. Your tab should turn red:

# Pure red tab chrome (top bar)
echo -e "\033]6;1;bg;red;brightness;255\a\033]6;1;bg;green;brightness;0\a\033]6;1;bg;blue;brightness;0\a"

If nothing happens, make sure you are actually in iTerm2 (not Terminal.app) and on a recent version.


2) Add the auto‑tint hook to ~/.zshrc

Paste this entire block into your ~/.zshrc, then source ~/.zshrc.

# ---------------------------------------------------------------------
# Auto‑color iTerm2 tab chrome based on nearest .iterm-color file
# ---------------------------------------------------------------------
autoload -Uz add-zsh-hook

# Find the closest .iterm-color by walking up from $PWD to /
_iterm_find_color_file() {
  local dir=$PWD
  while [[ $dir != "/" ]]; do
    [[ -f "$dir/.iterm-color" ]] && { echo "$dir/.iterm-color"; return 0; }
    dir=${dir:h}   # zsh dirname shorthand
  done
  return 1
}

# Apply either the project color (if found) or reset to profile default
_iterm_apply_tab_color() {
  local cfg=$(_iterm_find_color_file) || true

  if [[ -n $cfg ]]; then
    # Read first non-empty line, strip leading '#'
    local hex
    hex=$(grep -Eo '[#]?[0-9A-Fa-f]{6}' "$cfg" | head -n1)
    hex=${hex#\#}
    [[ ${#hex} -ne 6 ]] && return 0

    local r=$((16#${hex[1,2]}))
    local g=$((16#${hex[3,4]}))
    local b=$((16#${hex[5,6]}))

    # iTerm2 OSC 6; set tab/title-bar background by RGB channel (0–255)
    printf '\033]6;1;bg;red;brightness;%d\a'   $r
    printf '\033]6;1;bg;green;brightness;%d\a' $g
    printf '\033]6;1;bg;blue;brightness;%d\a'  $b
  else
    # Reset tab/title-bar to your profile default
    printf '\033]6;1;bg;*;default\a'
  fi
}

# Run after every directory change, and once on startup
add-zsh-hook chpwd _iterm_apply_tab_color
_iterm_apply_tab_color
# ---------------------------------------------------------------------

How it works


3) Mark projects with a color

Inside each repo (or at the monorepo root), create a .iterm-color file containing a single hex color:

echo "#22c55e" > ~/code/my-api/.iterm-color   # green

Now:

cd ~/code/my-api      # tab turns green
cd ~/                  # tab resets to default

Inheritance: The color applies to all subfolders until you leave the project tree.


Optional: also tint the text‑area background

If you want the terminal canvas (not just the tab) to match the project color, add this one line inside _iterm_apply_tab_color right after the three RGB writes:

# Also tint the terminal background (session‑local)
printf '\033]1337;SetColors=bg=%s\a' "$hex"

To reset when leaving a project, add a matching reset in the else branch:

# Reset terminal background to profile default
printf '\033]1337;SetColors=bg=default\a'

This uses iTerm2’s proprietary OSC 1337;SetColors escape. It affects only the current session/pane.


Optional: pull the color from Tailwind

If your projects define a primary color in tailwind.config.{js,cjs}, you can auto‑derive .iterm-color with a tiny Node helper.

  1. Create scripts/iterm-primary.js in the repo:
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");

const tryPaths = ["tailwind.config.js", "tailwind.config.cjs"].map(p =>
  path.join(process.cwd(), p)
);

const cfgPath = tryPaths.find(fs.existsSync);
let hex = null;

if (cfgPath) {
  const cfg = require(cfgPath);
  const colors =
    (cfg.theme && (cfg.theme.extend?.colors || cfg.theme.colors)) || {};
  const primary = colors.primary;
  if (typeof primary === "string") hex = primary;
  else if (primary && typeof primary.DEFAULT === "string")
    hex = primary.DEFAULT;
}

console.log((hex || "#2563eb").replace("#", ""));
  1. Generate the .iterm-color automatically:
node scripts/iterm-primary.js | awk '{print "#"$0}' > .iterm-color

Drop that into your build or a pre‑commit hook if you want the file kept in sync.


Troubleshooting


Extras & notes


Recap

  1. Confirm tab tinting works in your iTerm2 build.
  2. Add the zsh hook that emits tab‑color escape codes.
  3. Drop a .iterm-color file with a hex in any repo you want tinted.
  4. (Optional) Tint the terminal background too.

That’s it — now every project gets an at‑a‑glance color, and your brain gets fewer context switches.