Pretty, minimal and fast ZSH prompt; nix and jj ified
0

Configure Feed

Select the types of activity you want to include in your feed.

Shell 99.2%
Nix 0.8%
466 1 0

Clone this repository

https://git.vm.fail/dunkirk.sh/impure https://git.vm.fail/did:plc:oktm6ah6nht6cdizqnfqlqpd
ssh://git@knot.dunkirk.sh:2222/dunkirk.sh/impure ssh://git@knot.dunkirk.sh:2222/did:plc:oktm6ah6nht6cdizqnfqlqpd

For self-hosted knots, clone URLs may differ based on your setup.


README.md

impure#

A pretty, minimal and fast ZSH prompt — a fork of Pure with Jujutsu, nix-shell, and zmx awareness

The canonical repo for this is hosted on tangled over at dunkirk.sh/impure

Features#

  • Instant prompt. A minimal prompt (directory + symbol) appears immediately when you open a terminal, before plugins or completions load. The full prompt with git/jj data enriches asynchronously moments later. No cache files needed.
  • Async git status. Branch, dirty marker, and unpushed/unpulled arrows are computed in a background worker so the prompt never blocks.
  • Staging summary. Dirty repos show an oh-my-posh-style breakdown of the index, e.g. main (+2 ~1 -1)* — added, modified, deleted, plus a * when the working tree is dirty.
  • Jujutsu support. Inside a jj repo the prompt shows bookmarks, the short change ID (in cyan), and a working-copy change count. jj takes precedence over git when both are present.
  • nix-shell and virtualenv. The active environment name is shown on the right prompt.
  • zmx sessions. When $ZMX_SESSION is set the tag is shown in the preprompt.
  • Transient prompt. After you press Enter the two-line prompt collapses to a single in scrollback, keeping history clean.
  • Custom segments. Define prompt_impure_precustom to inject your own prefix and suffix segments.
  • Exec time, SSH/container detection, VI-mode indicator, suspended-jobs marker — all carried over from Pure.
  • Bracketed paste mode. Enabled automatically to prevent accidental execution of pasted text.
  • EOL marker. Commands that don't print a trailing newline show a % marker so output doesn't visually merge with the next prompt.

Requires Git 2.15.2+ and ZSH 5.8+ (for instant prompt). jujutsu is optional and only needed for jj status.

Install#

Nix flake#

Add impure as a flake input and source it in your home-manager config:

# flake.nix
{
  inputs.impure.url = "github:taciturnaxolotl/impure";
}
# home-manager module
programs.zsh.initContent = ''
  source ${inputs.impure}/async.zsh
  IMPURE_CMD_MAX_EXEC_TIME=3
  source ${inputs.impure}/impure.zsh
'';

For instant prompt, source instant-prompt.zsh before compinit and plugins:

programs.zsh.initContent = ''
  # Instant prompt — must be first
  source ${inputs.impure}/instant-prompt.zsh

  # Completions and plugins
  autoload -Uz compinit && compinit -C
  # ... your plugins ...

  # Impure prompt
  source ${inputs.impure}/async.zsh
  IMPURE_CMD_MAX_EXEC_TIME=3
  source ${inputs.impure}/impure.zsh
'';

Manual#

  1. Clone this repo somewhere, e.g. $HOME/.zsh/impure:

    mkdir -p "$HOME/.zsh"
    git clone https://tangled.org/dunkirk.sh/impure "$HOME/.zsh/impure"
    
  2. Source the files in $HOME/.zshrc. For instant prompt, instant-prompt.zsh must be sourced before compinit and plugins:

    # Instant prompt — must be first
    source "$HOME/.zsh/impure/instant-prompt.zsh"
    
    # Completions and plugins
    autoload -Uz compinit && compinit -C
    # ... your plugins ...
    
    # Impure prompt
    source "$HOME/.zsh/impure/async.zsh"
    IMPURE_CMD_MAX_EXEC_TIME=3
    source "$HOME/.zsh/impure/impure.zsh"
    

Via promptinit (no instant prompt)#

If you don't need instant prompt, you can use the traditional promptinit method:

fpath+=("$HOME/.zsh/impure")
autoload -U promptinit; promptinit
prompt impure

This method does not support instant prompt. Use the manual or nix install methods above for the full experience.

Configuration#

Environment variables#

Variable Default Description
IMPURE_CMD_MAX_EXEC_TIME 3 Seconds before a command's exec time is shown.
IMPURE_GIT_PULL 1 Set to 0 to disable the background git fetch.
IMPURE_GIT_UNTRACKED_DIRTY 1 Set to 0 to ignore untracked files when checking dirtiness.
IMPURE_GIT_DELAY_DIRTY_CHECK 1800 Seconds to cache a slow dirty check before re-running.
IMPURE_PROMPT_SYMBOL The prompt symbol.
IMPURE_PROMPT_VICMD_SYMBOL The prompt symbol in VI command mode.
IMPURE_GIT_UP_ARROW Symbol for unpushed commits.
IMPURE_GIT_DOWN_ARROW Symbol for unpulled commits.
IMPURE_GIT_STASH_SYMBOL Symbol shown when stashes exist.
IMPURE_SUSPENDED_JOBS_SYMBOL Symbol shown when jobs are suspended.

The prompt also reacts to these external variables when set:

  • ZMX_SESSION — renders a [session] tag in the preprompt.

zstyles#

All toggles default to on unless noted. Disable a feature by setting its style to no before prompt impure:

zstyle ':prompt:impure:git'                 show no   # disable git integration
zstyle ':prompt:impure:jj'                  show no   # disable jujutsu integration
zstyle ':prompt:impure:host'                show no   # hide hostname
zstyle ':prompt:impure:title'               show no   # stop managing the terminal title
zstyle ':prompt:impure:git:stash'           show yes  # show stash indicator
zstyle ':prompt:impure:git:fetch'   only_upstream yes # only fetch the current branch's upstream
zstyle ':prompt:impure:environment:nix-shell'  show no
zstyle ':prompt:impure:environment:virtualenv' show no
zstyle ':prompt:impure:path:separator'      dim  yes  # dim the path separators

Colors#

Override any segment color with the color style. Values are zsh color names or 256-color numbers:

zstyle ':prompt:impure:path' color blue
zstyle ':prompt:impure:git:branch' color 242
zstyle ':prompt:impure:prompt:success' color magenta

Available color keys: path, git:branch, git:branch:cached, git:dirty, git:action, git:arrow, git:stash, jj, host, user, user:root, zmx, nix-shell, virtualenv, execution_time, suspended_jobs, custom:prefix, custom:suffix, prompt:success, prompt:error, prompt:ssh, prompt:continuation.

Custom segments#

Define prompt_impure_precustom to add your own prefix/suffix segments. It runs on every render and can set psvar[22] (prefix) and psvar[23] (suffix):

prompt_impure_precustom() {
	psvar[22]="$(date +%H:%M)"   # rendered before the path
	psvar[23]=""                 # rendered after the git/jj segments
}

Preview#

Run prompt_impure_preview after loading the prompt to see every segment and color rendered at once.

Tests#

zsh tests/test.zsh

Each test file runs in its own subshell; the harness exits non-zero if any fail.

Credits#

Impure is a fork of Pure by Sindre Sorhus and Mathias Fredriksson, and bundles zsh-async. All of the hard work on the async core and the original prompt design is theirs; Impure adds the jj, nix, zmx and staging-summary layers on top.

© 2026-present Kieran Klukas