Ref Fresh
September 8, 2026 ยท View on GitHub
Ref Fresh keeps zsh prompts fresh while your shell is idle in a Git repository. When another terminal or program edits files, changes branches, rebases, or updates refs, Ref Fresh asks zsh to redraw the current prompt so your existing prompt logic can recalculate Git state.
It does not render a prompt, choose a branch format, calculate dirty state, or
cache Git status. It only watches the current repository and calls
zle .reset-prompt after repository filesystem changes.
Ref Fresh was inspired by Cobalt Spark's Live Git updates.
Requirements
- zsh
- Git
fswatch
Ref Fresh uses one fswatch process per current repository per shell. It watches
the worktree root, plus Git metadata directories when they live outside the
worktree, so branch switches and dirty-state changes use the same watcher.
If fswatch is not installed, Ref Fresh quietly does nothing.
Install
Manual
source /path/to/zsh-ref-fresh/zsh-ref-fresh.zsh
Oh My Zsh
Clone this repository into your custom plugins directory:
git clone https://github.com/evanthegrayt/zsh-ref-fresh \
${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/zsh-ref-fresh
Then enable it:
plugins=(... zsh-ref-fresh)
zinit
zinit light evanthegrayt/zsh-ref-fresh
zplug
zplug "evanthegrayt/zsh-ref-fresh"
Other
...or use your other favorite manager's instructions.
Setup
Set configuration variables in your zsh startup file before Ref Fresh loads when
you can. If you install Ref Fresh with a plugin manager, the plugin manager
usually sources the plugin for you; do not also source zsh-ref-fresh.zsh manually.
For a manual install, set variables and then source the plugin:
REF_FRESH_ENABLE=1
REF_FRESH_LATENCY=0.5
source /path/to/zsh-ref-fresh/zsh-ref-fresh.zsh
For a plugin manager, put the variables before the manager loads Ref Fresh:
REF_FRESH_ENABLE=1
REF_FRESH_LATENCY=0.5
# Your plugin manager loads evanthegrayt/zsh-ref-fresh here.
Most configuration is read dynamically. If you set REF_FRESH_ENABLE=0 after
Ref Fresh has already loaded, the active watcher stops on the next prompt check.
If you set it back to 1, watching resumes on the next prompt check.
REF_FRESH_LATENCY is read when a watcher starts. If you change latency while a
watcher is already running, call ref_fresh_restart or wait until you enter a
different repository.
Configuration uses environment variables:
| Variable | Default | Description |
|---|---|---|
REF_FRESH_ENABLE | 1 | Enable prompt redraws. Truthy values are 1, true, yes, and on. |
REF_FRESH_LATENCY | 0.5 | Seconds passed to fswatch --latency. |
REF_FRESH_BACKEND | fswatch | Watch backend. Only fswatch is supported today. |
REF_FRESH_DEBUG | 0 | Print debug messages to stderr when truthy. |
Disable Ref Fresh with:
REF_FRESH_ENABLE=0
You can also stop and restart it from an interactive shell:
ref_fresh_stop
ref_fresh_start
ref_fresh_restart
ref_fresh_check_pwd is the public hook function. It checks the current
directory, starts a watcher when you enter a Git worktree, reuses the active
watcher while you move inside the same worktree, and stops the watcher when you
leave the repository.
Use In A Prompt
Ref Fresh does not include Git prompt rendering code, and it does not pass branch or dirty-state information to your prompt. There is no hidden variable to read.
The flow is:
- Your prompt renders Git information however it normally does.
- Ref Fresh notices that files in the current repository changed.
- Ref Fresh calls
zle .reset-prompt. - zsh redraws the prompt.
- Your prompt's own Git code runs again during that redraw.
That means your prompt should calculate Git information during prompt expansion,
or call a function from PROMPT/RPROMPT while prompt_subst is enabled.
For example:
setopt prompt_subst
function my_git_prompt() {
command git rev-parse --is-inside-work-tree > /dev/null 2>&1 || return 0
local ref dirty
ref=$(command git symbolic-ref --short HEAD 2> /dev/null) \
|| ref=$(command git rev-parse --short HEAD 2> /dev/null) \
|| return 0
if [[ -n "$(command git status --porcelain 2> /dev/null)" ]]; then
dirty="*"
fi
print -r -- " [$ref$dirty]"
}
PROMPT='%~$(my_git_prompt) %# '
Ref Fresh will make that $(my_git_prompt) call happen again when another
terminal changes the repository. The plugin does not decide what my_git_prompt
returns.
For a full prompt example, see my personal theme.
If your prompt only calculates Git state in a precmd hook and stores it in a
variable, a prompt reset may redraw the old cached value. In that case, move the
Git calculation into a prompt-expansion function, or have your prompt expose a
function that recalculates the cache during redraw.
Prompt Compatibility
Ref Fresh works with any zsh prompt that recalculates its Git state during a
prompt redraw. The most direct pattern is a function called while rendering
PROMPT or RPROMPT.
Because Ref Fresh only triggers redraws, your prompt remains responsible for deciding what to show.
Contributing
See CONTRIBUTING.md for development notes, project boundaries, and test commands.