<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sui Yang</title>
    <description>The latest articles on DEV Community by Sui Yang (@jaspersui).</description>
    <link>https://dev.to/jaspersui</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F880303%2Faeae87f2-da5e-485a-a7e6-213c7c17fad9.jpeg</url>
      <title>DEV Community: Sui Yang</title>
      <link>https://dev.to/jaspersui</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jaspersui"/>
    <language>en</language>
    <item>
      <title>I kept losing track of my Claude Code tabs. So I fixed it.</title>
      <dc:creator>Sui Yang</dc:creator>
      <pubDate>Sat, 07 Mar 2026 13:33:39 +0000</pubDate>
      <link>https://dev.to/jaspersui/i-kept-losing-track-of-my-claude-code-tabs-so-i-fixed-it-3mc7</link>
      <guid>https://dev.to/jaspersui/i-kept-losing-track-of-my-claude-code-tabs-so-i-fixed-it-3mc7</guid>
      <description>&lt;p&gt;I run Claude Code for almost everything now. On a typical day I have five or six iTerm2 tabs open — one refactoring a module, one writing tests, one scaffolding something new.&lt;/p&gt;

&lt;p&gt;Here's the thing nobody warns you about: when one session finishes, you have no idea which tab it is.&lt;/p&gt;

&lt;p&gt;So you click through them. One by one. Like scratching lottery tickets, except the prize is just finding which Claude is sitting there waiting for you. Meanwhile, the other sessions keep running, and you've just wasted five minutes of parallelism you'll never get back.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I tried first
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;iTerm2's built-in idle notification.&lt;/strong&gt; It tells you "a session went idle." Great — but &lt;em&gt;which one&lt;/em&gt;? With six tabs open, you're still guessing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;terminal-notifier&lt;/code&gt; via Claude Code hooks.&lt;/strong&gt; Better — you can show the project name in a macOS banner. But banners disappear in a few seconds. If you're heads-down in another tab, you miss it. Gone. Back to clicking through tabs.&lt;/p&gt;

&lt;p&gt;What I actually wanted was dumb simple: make the tab itself tell me. Visually. In a way I literally cannot miss.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/JasperSui/claude-code-iterm2-tab-status" rel="noopener noreferrer"&gt;claude-code-iterm2-tab-status&lt;/a&gt;&lt;/strong&gt; — a Claude Code plugin that puts a live status prefix on each iTerm2 tab.&lt;/p&gt;

&lt;p&gt;Three states:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;State&lt;/th&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Running&lt;/strong&gt; — Claude is working&lt;/td&gt;
&lt;td&gt;⚡&lt;/td&gt;
&lt;td&gt;Quiet prefix, that's it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Idle&lt;/strong&gt; — Claude finished&lt;/td&gt;
&lt;td&gt;💤&lt;/td&gt;
&lt;td&gt;Quiet prefix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Attention&lt;/strong&gt; — needs your permission&lt;/td&gt;
&lt;td&gt;🔴&lt;/td&gt;
&lt;td&gt;Tab flashes orange + shows a badge&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Only the attention state actually flashes. Running and idle are just quiet indicators. Glance at your tab bar and you know exactly what's happening everywhere.&lt;/p&gt;

&lt;p&gt;When you click on a flashing tab, it stops. When you type your next prompt, it goes back to ⚡. Your original tab color, title, and badge are saved and restored.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Claude Code hooks → JSON signal file → iTerm2 adapter → tab status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things made this possible:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Claude Code has a hooks API.&lt;/strong&gt; &lt;code&gt;Notification&lt;/code&gt; hooks fire on &lt;code&gt;idle_prompt&lt;/code&gt; and &lt;code&gt;permission_prompt&lt;/code&gt;. &lt;code&gt;UserPromptSubmit&lt;/code&gt; fires when you send a new message. They're official, documented, and run a shell command with event data on stdin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;iTerm2 has a Python API.&lt;/strong&gt; You can set tab colors, titles, badges — all programmatically, per-session. And you can match sessions by TTY.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The bridge is a signal file. When Claude's state changes, the hook writes a small JSON file to &lt;code&gt;/tmp/claude-tab-status/&lt;/code&gt; with the session's TTY and current state. On the iTerm2 side, a Python script runs as an AutoLaunch script, polls that directory every second, matches TTY → tab, and updates accordingly.&lt;/p&gt;

&lt;p&gt;No screen scraping. No regex on terminal output. No fragile hacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;

&lt;p&gt;It's a Claude Code plugin. Two commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Register the marketplace&lt;/span&gt;
/plugin marketplace add JasperSui/jaspersui-marketplace

&lt;span class="c"&gt;# Install&lt;/span&gt;
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;iterm2-tab-status@jaspersui-marketplace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On first session start, the plugin automatically sets up the iTerm2 Python runtime and deploys the adapter. Just restart iTerm2 once and you're done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;/iterm2-tab-status:config&lt;/code&gt; inside Claude Code — it walks you through everything interactively. Flash color, prefixes, badge text, macOS notifications. Settings live in &lt;code&gt;~/.config/claude-tab-status/config.json&lt;/code&gt; and hot-reload within about a second.&lt;/p&gt;

&lt;p&gt;If you prefer env vars:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_ITERM2_TAB_STATUS_COLOR_G&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0    &lt;span class="c"&gt;# red flash instead of orange&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_ITERM2_TAB_STATUS_NOTIFY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;   &lt;span class="c"&gt;# also send macOS notifications&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;The signal file approach turned out to be a good call. It keeps the Claude Code side and the iTerm2 side completely decoupled. If someone wants to write an adapter for Kitty or WezTerm, they just need to read the same JSON files. The signal format is stable and documented.&lt;/p&gt;

&lt;p&gt;What I underestimated was TTY matching edge cases. If you split panes or rearrange sessions, the TTY mapping can get stale. A restart fixes it, but I'd like to make that more robust.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/JasperSui/claude-code-iterm2-tab-status" rel="noopener noreferrer"&gt;github.com/JasperSui/claude-code-iterm2-tab-status&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're running multiple Claude Code sessions in iTerm2, give it a shot. I'd genuinely like to know if the TTY matching holds up on setups other than mine — I've only tested on macOS with iTerm2 3.6.x so far.&lt;/p&gt;

&lt;p&gt;And if you use a different terminal with a scriptable API, PRs for new adapters are very welcome!&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>terminal</category>
    </item>
  </channel>
</rss>
