RSS Amplifier

eshlox · May 6, 2026

A just wrapper for tmux and global recipes

0
Sign in to vote or save

Przemysław Kołodziejczyk · eshlox

I have a few posts about just already: the basic command runner, the global justfile, and tmux window names with just. The wrapper in my .zshrc rolls all three behaviors into one function so I do not have to think about them.

What the wrapper does

If a recipe is not in the project justfile but exists in ~/.config/just/justfile, the wrapper runs the global one with --working-directory $PWD, so it acts on the current directory. That way I can keep things like clean-docker or my-ip in one place and still call them from any project.

Before a recipe runs, the wrapper renames the tmux window to the recipe name. When it exits, the window goes back to zsh. Outside of tmux this part does nothing.

The third piece is --choose. Project and global recipes show up in one fuzzy picker. Globals are dimmed and prefixed with . If both files have a recipe with the same name, the project one wins.

The CLI is the same as plain just, so teammates who do not source the function get plain just and nothing breaks.

Why a wrapper, not a justfile change

I first tried doing the tmux rename inside each project justfile, with helper recipes that call tmux rename-window. It works, but it adds the same six lines to every project, and every recipe has to remember to call the restore. A wrapper does it once in my shell config, and project justfiles stay clean for teammates.

The global fallback is the same logic. I want my personal recipes everywhere, but I do not want to teach each project about them.

The code

# `just` wrapper — adds three things on top of plain `just`:

# 1. Falls back to the global justfile (~/.config/just/justfile) when the

# project doesn't define a recipe.

# 2. Renames the tmux window to the recipe name while it runs.

# 3. `--choose` shows project + global recipes in one fuzzy picker.

# Project justfiles are untouched; teammates without this function get plain

# `just`. Keep it identical to `just`'s CLI surface.

just() {

local global_justfile="${XDG_CONFIG_HOME:-$HOME/.config}/just/justfile"

# Detect whether $PWD (or any ancestor) has a project justfile.

local in_project=0

command just --show default &>/dev/null && in_project=1

if (( ! in_project )); then

command just --summary &>/dev/null && in_project=1

fi

# `--choose`: merged fuzzy picker over project + global recipes

if [[ "$1" == "--choose" ]]; then

local chooser="${JUST_CHOOSER:-fzf --ansi}"

local project_list="" global_list="" selected

if (( in_project )); then

project_list=$(command just --summary 2>/dev/null | tr ' ' '\n' | grep -v '^$')

fi

if [[ -f "$global_justfile" ]]; then

global_list=$(command just -g --summary 2>/dev/null | tr ' ' '\n' | grep -v '^$')

fi

selected=$(

{

[[ -n "$project_list" ]] && while IFS= read -r r; do

printf ' %s\n' "$r"

done <<< "$project_list"

while IFS= read -r r; do

[[ -z "$r" ]] && continue

if [[ -z "$project_list" ]] || ! echo "$project_list" | grep -qxF "$r"; then

printf '\033[2m∘\033[0m %s\n' "$r"

fi

done <<< "$global_list"

} | eval "$chooser" | awk '{print $NF}'

) || return

[[ -z "$selected" ]] && return

just "$selected"

return

fi

# First non-flag argument is the recipe name.

local recipe=""

for arg in "$@"; do

[[ "$arg" == -* ]] && continue

recipe="$arg"

break

done

# `--list` / `-l`: show project recipes (if any) followed by globals.

if [[ "$1" == "--list" || "$1" == "-l" ]]; then

if (( in_project )); then

command just "$@"

fi

if [[ -f "$global_justfile" ]] && command just -g --list &>/dev/null; then

(( in_project )) && echo ""

echo "Global recipes:"

command just -g "$@"

fi

return

fi

# Bare `just` outside any project: show globals instead of erroring.

if [[ $# -eq 0 ]] && (( ! in_project )) && [[ -f "$global_justfile" ]]; then

command just -g

return

fi

# Recipe missing in project but present globally: run the global one against $PWD.

local -a prefix=(command just)

if [[ -n "$recipe" ]] \

&& [[ -f "$global_justfile" ]] \

&& ! command just --show "$recipe" &>/dev/null \

&& command just --justfile "$global_justfile" --show "$recipe" &>/dev/null; then

prefix=(command just --justfile "$global_justfile" --working-directory "$PWD")

fi

# Rename the tmux window to the recipe while it runs, then back to "zsh".

if [[ -n "$TMUX" ]] && [[ -n "$recipe" ]]; then

tmux rename-window "$recipe"

"${prefix[@]}" "$@"

local exit_code=$?

tmux rename-window "zsh"

return $exit_code

fi

"${prefix[@]}" "$@"

}

alias j="just --choose"

Spot something wrong?

Found a typo, a broken link, or something that could be better? I would love to hear from you. Drop me a message and I will fix it.

Read the original on eshlox.net

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.