Automatic tmux window names with just

· Tech

I use just as a command runner for my projects. I also use tmux. When I run just dev or just claude, I want the tmux window to show what is running. When the command exits, I want the name to go back to zsh.

The setup

Two private helper recipes handle the renaming:

[private]
_tmux name:
@test -n "$TMUX" && tmux rename-window "{{ name }}" || true
[private]
_tmux-restore:
@test -n "$TMUX" && tmux rename-window "zsh" || true

_tmux renames the window before the command starts. _tmux-restore sets it back to zsh after the command finishes. Both check for $TMUX first, so they do nothing outside of tmux.

Each recipe uses _tmux as a dependency and calls _tmux-restore at the end:

dev: (_tmux "dev")
docker compose up --build; just _tmux-restore
claude *args: (_tmux "claude")
sbx run --name project-claude claude . -- {{ args }}; just _tmux-restore
lazygit: (_tmux "lazygit")
lazygit; just _tmux-restore

The ; between the command and just _tmux-restore is important. Using && would skip the restore if the command fails or gets interrupted with Ctrl+C. ; runs the restore regardless of the exit code.

Why not move it to the global justfile

just supports a global justfile (just -g or just --global-justfile). I use it for personal recipes that are not tied to any project. The tmux helpers could live there, and I would get them everywhere without copying anything.

The problem is teammates. If the project justfile calls just _tmux-restore and the recipe only exists in my global justfile, it breaks for everyone else. The _tmux dependency would also not resolve.

I also considered tmux hooks (pane-focus-in and similar). They fire globally and are hard to scope to specific commands. You end up fighting tmux more than helping it.

The tmux helpers are six lines total. Copying them into a new project takes seconds. Teammates who do not use tmux are not affected because of the $TMUX check. For something this small, keeping it in the project justfile is the simpler option.

The initial attempt with automatic-rename

My first approach was to restore the window name by turning automatic-rename back on:

_tmux-restore:
@test -n "$TMUX" && tmux set-option -w automatic-rename on || true

The idea was that tmux would figure out the correct name on its own. It did not. Because the just process was still the active process in the shell when tmux re-evaluated the window name, it showed “just” instead of “zsh”. Setting the name explicitly to “zsh” was simpler and predictable.