Skip to content

Commit a7e372b

Browse files
committed
new post about terminal titles
1 parent ef69aba commit a7e372b

File tree

4 files changed

+282
-2
lines changed

4 files changed

+282
-2
lines changed

.tool-versions

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
ruby 3.4.1
2-
nodejs 22.12.0
2+
nodejs 22.14.0

_posts/2025-02-05-bug-in-programming-language.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ date: 2025-03-08 22:30:00 +1100
44
tags: Erlang OTP
55
header:
66
image: /assets/images/2025-03-08/red_bug.jpg
7-
image_description: "Banff National Park"
7+
image_description: "Red bug on green leafed plant"
88
teaser: /assets/images/2025-03-08/red_bug.jpg
99
overlay_image: /assets/images/2025-03-08/red_bug.jpg
1010
overlay_filter: 0.4
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
---
2+
title: "Taking Control of Terminal Titles"
3+
date: 2025-08-24 21:55:00 +1000
4+
tags: iTerm2 terminal
5+
header:
6+
image: /assets/images/2025-08-24/terminal.jpg
7+
image_description: ""
8+
teaser: /assets/images/2025-08-24/terminal.jpg
9+
overlay_image: /assets/images/2025-08-24/terminal.jpg
10+
overlay_filter: 0.5
11+
caption: >
12+
Photo by [Sean Wang](https://unsplash.com/@maooooozaizi)
13+
on [Unsplash](https://unsplash.com/photos/an-escalator-in-a-large-building-with-lots-of-windows-DZSbsJHadH0)
14+
excerpt: One simple command to rule them all
15+
---
16+
17+
## The Background
18+
19+
As a developer, I use the terminal extensively and often SSH into remote machines
20+
for management tasks. When I connect via SSH, iTerm2 automatically updates both
21+
the window and tab titles to something like `user@machine-ip:directory-name`,
22+
which provides helpful context about where I'm working. The problem? These titles
23+
don't automatically revert when I disconnect, leaving me with stale information
24+
in my terminal tabs.
25+
26+
For years, I had no idea what was happening under the hood, let alone how to fix
27+
it. My workaround was crude but effective: close the tab and open a new one.
28+
Eventually, I got fed up and decided to take some actions. After some research,
29+
I added this mysterious snippet to my `.zshrc`:
30+
31+
```bash
32+
precmd() {
33+
# sets the tab title to current dir
34+
echo -ne "\e]1;${PWD##*/}\a"
35+
}
36+
```
37+
38+
I'll be honest—I didn't fully understand how it worked, but it did the job. This
39+
function "forced" my tab title to always display the current directory name,
40+
even after disconnecting from SSH sessions.
41+
42+
Later, I discovered [Prezto][], a configuration framework for Zsh that includes
43+
a handy `set-tab-title` function. This gave me more flexible control over tab
44+
titles, so I happily retired my hacky `precmd` solution.
45+
46+
You might have noticed that the window title remained untouched throughout this
47+
journey. It simply wasn't annoying enough to warrant investigation—until Claude
48+
Code came along.
49+
50+
Since its public launch in February, Claude Code has become my go-to tool for
51+
AI-assisted coding. Like SSH, it helpfully sets custom tab and window titles to
52+
show what it's working on. Also like SSH, these titles stick around after Claude
53+
Code exits, cluttering my terminal with outdated information like "Building
54+
Feature X..." or "Optimising test performance..." long after those tasks
55+
completed.
56+
57+
Since I was using Claude Code across multiple projects every day, these stale
58+
titles were starting to get on my nerves and that was the final straw. It was
59+
time to properly understand how terminal titles work and build a comprehensive
60+
solution.
61+
62+
## Understanding Terminal Titles in iTerm2
63+
64+
Before diving into solutions, let's understand what we're dealing with. iTerm2
65+
(and most terminal emulators) recognize two distinct title types:
66+
67+
1. **Tab Title** - Displayed on the individual tab
68+
2. **Window Title** - Shown in the center of the window's title bar
69+
70+
These titles are controlled through ANSI escape sequences - special character
71+
combinations that terminals interpret as commands rather than text to display.
72+
73+
### The Magic Behind Terminal Titles
74+
75+
Here's how escape sequences work for setting titles:
76+
77+
```bash
78+
# Set window title only (shows in title bar)
79+
echo -ne "\033]2;Your Window Title\007"
80+
81+
# Set tab title only (shows in tab)
82+
echo -ne "\033]1;Your Tab Title\007"
83+
84+
# Set both window and tab to the same title
85+
echo -ne "\033]0;Your Title\007"
86+
```
87+
88+
The cryptic `\033]` starts the escape sequence, the number (0, 1, or 2)
89+
specifies which title to set, and `\007` (the bell character) ends it.
90+
91+
Quick note on escape characters: You might see these written as `\e` (instead of
92+
`\033`) and `\a` (instead of `\007`) in some scripts—they're equivalent, just
93+
different representations of the same ASCII characters. I'm using the octal
94+
format (`\033` and `\007`) here for maximum compatibility across different
95+
shells and systems.
96+
97+
Simple, right? Well, not exactly intuitive and quite cumbersome to use, which is
98+
why we're building a better interface.
99+
100+
## The Solution: A Simple Title Manager
101+
102+
Let's create a user-friendly function that makes title management a breeze. Add
103+
this to your `~/.zshrc` (or `~/.bashrc` for Bash users):
104+
105+
```bash
106+
# Terminal title management functions
107+
terminal_titles() {
108+
case "$1" in
109+
window)
110+
echo -ne "\033]2;$2\007"
111+
;;
112+
tab)
113+
echo -ne "\033]1;$2\007"
114+
;;
115+
both)
116+
echo -ne "\033]0;$2\007"
117+
;;
118+
help)
119+
echo "Usage: terminal_titles [window|tab|both|reset|help] [title]"
120+
echo " window [title] - Set window title only"
121+
echo " tab [title] - Set tab title only"
122+
echo " both [title] - Set both window and tab to same title"
123+
echo " reset - Reset to default titles"
124+
echo " help - Show this help message"
125+
echo " (no args) - Same as reset"
126+
;;
127+
reset|"")
128+
# Window title: full path with ~ for home
129+
echo -ne "\033]2;${PWD/#$HOME/~}\007"
130+
# Tab title: last portion of the full path
131+
echo -ne "\033]1;${PWD##*/}\007"
132+
;;
133+
*)
134+
echo "Unknown command: $1"
135+
echo "Use 'terminal_titles help' for usage"
136+
;;
137+
esac
138+
}
139+
140+
# Alias for convenience
141+
alias tt='terminal_titles'
142+
```
143+
144+
### How to Use It
145+
146+
Now you have a simple `tt` command at your disposal:
147+
148+
```bash
149+
# Reset titles to show current directory info
150+
tt
151+
152+
# Set a custom window title
153+
tt window "Development Server"
154+
155+
# Set a custom tab title
156+
tt tab "logs"
157+
158+
# Set both to the same title
159+
tt both "Project X"
160+
161+
# Get help
162+
tt help
163+
```
164+
165+
The default behavior (`tt` with no arguments) resets your titles to something
166+
useful:
167+
168+
- **Window title**: Full path of current directory (with `~` for home)
169+
- **Tab title**: Just the current folder name
170+
171+
For example, if you're in `/Users/you/projects/awesome-app`, the window shows
172+
`~/projects/awesome-app` and the tab shows `awesome-app`.
173+
174+
## Conclusion
175+
176+
After years of closing and reopening tabs to clear stale SSH titles, and more
177+
recently dealing with Claude Code's persistent status messages, I finally have a
178+
solution that just works. The `tt` command is now muscle memory—quick to type,
179+
easy to remember, and does exactly what I need.
180+
181+
The beauty of this solution is its simplicity. No complex configurations, no
182+
heavyweight terminal managers—just a few lines of shell script that give you
183+
complete control. Whether you're jumping between SSH sessions, running Claude
184+
Code throughout the day, or just want cleaner tab organization, you now have the
185+
tools to keep your terminal titles under control.
186+
187+
Happy terminal customizing! 🚀
188+
189+
---
190+
191+
> **Note**: After building this solution, I discovered that Prezto actually has
192+
> a `set-window-title` command hiding alongside the `set-tab-title` function I'd
193+
> been using for years. Had I found it earlier, this entire journey into the
194+
> depths of ANSI escape sequences might never have happened. But you know what?
195+
> I'm okay with missing it. Sometimes the scenic route teaches you more than the
196+
> shortcut ever could, and now I truly understand what's happening under the
197+
> hood rather than just blindly using a command.
198+
199+
## Appendix: Auto-Reset with Smart Persistence
200+
201+
If you want titles to automatically reset after commands like Claude Code exit,
202+
but keep your manually-set titles, here's an enhanced version with intelligent
203+
auto-reset. This adds more complexity but offers finer control:
204+
205+
```bash
206+
# Terminal title management functions with smart auto-reset
207+
terminal_titles() {
208+
case "$1" in
209+
window)
210+
echo -ne "\033]2;$2\007"
211+
export TERMINAL_TITLE_MANUAL=1
212+
;;
213+
tab)
214+
echo -ne "\033]1;$2\007"
215+
export TERMINAL_TITLE_MANUAL=1
216+
;;
217+
both)
218+
echo -ne "\033]0;$2\007"
219+
export TERMINAL_TITLE_MANUAL=1
220+
;;
221+
help)
222+
echo "Usage: terminal_titles [window|tab|both|reset|auto|help] [title]"
223+
echo " window [title] - Set window title only"
224+
echo " tab [title] - Set tab title only"
225+
echo " both [title] - Set both window and tab to same title"
226+
echo " reset - Reset to default titles"
227+
echo " auto - Enable auto-reset after commands"
228+
echo " help - Show this help message"
229+
echo " (no args) - Same as reset"
230+
;;
231+
auto)
232+
unset TERMINAL_TITLE_MANUAL
233+
terminal_titles reset
234+
echo "Auto-reset enabled"
235+
;;
236+
reset|"")
237+
# Window title: full path with ~ for home
238+
echo -ne "\033]2;${PWD/#$HOME/~}\007"
239+
# Tab title: last portion of the full path
240+
echo -ne "\033]1;${PWD##*/}\007"
241+
unset TERMINAL_TITLE_MANUAL
242+
;;
243+
*)
244+
echo "Unknown command: $1"
245+
echo "Use 'terminal_titles help' for usage"
246+
;;
247+
esac
248+
}
249+
250+
# Alias for convenience
251+
alias tt='terminal_titles'
252+
253+
# Auto-reset after commands ONLY if not manually set (for zsh)
254+
if [[ -n "$ZSH_VERSION" ]]; then
255+
precmd() {
256+
# Only reset if titles weren't manually set
257+
if [[ -z "$TERMINAL_TITLE_MANUAL" ]]; then
258+
# Window title: full path with ~ for home
259+
echo -ne "\033]2;${PWD/#$HOME/~}\007"
260+
# Tab title: last portion of the full path
261+
echo -ne "\033]1;${PWD##*/}\007"
262+
fi
263+
}
264+
fi
265+
```
266+
267+
This enhanced version adds:
268+
269+
- **Smart persistence**: Manually-set titles survive command execution
270+
- **Auto-reset mode**: Titles automatically update after commands (when not
271+
manually set)
272+
- **Flexible control**: Switch between manual and automatic modes with `tt auto`
273+
274+
### The Smart Workflow
275+
276+
1. **Normal operation**: Titles auto-update to show your current directory
277+
2. **Set custom title**: `tt tab "server logs"` - This persists across commands
278+
3. **Return to auto-mode**: `tt auto` or `tt reset`
279+
280+
[Prezto]: https://github.com/sorin-ionescu/prezto
150 KB
Loading

0 commit comments

Comments
 (0)