From b7bb444f3d464d843df57c4ea621a0d556ad2790 Mon Sep 17 00:00:00 2001 From: randogoth Date: Sat, 11 Jul 2026 16:13:30 +0300 Subject: [PATCH] fix(shell): let bash-preexec install last so atuin preexec fires Eagerly calling __bp_install at source time made bash-preexec install before starship/atuin/zoxide/ghostty modified PROMPT_COMMAND, so their hooks landed after __bp_interactive_mode. bash-preexec then never marked typed commands as interactive and skipped preexec_functions, so atuin's __atuin_preexec never fired and history stopped recording (ATUIN_PREEXEC_BACKEND stuck at ":none"). Remove the eager __bp_install and the manual PROMPT_COMMAND/array wiring for starship, atuin and zoxide; each tool registers with bash-preexec itself, and deferred install on the first prompt keeps __bp_interactive_mode last (verified against bash-preexec 0.6.0). Co-Authored-By: Claude Opus 4.8 --- scripts/shell-init.sh | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/scripts/shell-init.sh b/scripts/shell-init.sh index 0135a6a..0a3f4d1 100644 --- a/scripts/shell-init.sh +++ b/scripts/shell-init.sh @@ -19,20 +19,6 @@ is_interactive() { [[ -t 1 || -n ${PS1:-} ]] } -append_unique() { - local var="$1" val="$2" - [[ ";${!var:-};" == *";$val;"* ]] && return - printf -v "$var" '%s' "${!var:+${!var%;};}$val" -} - -prepend_unique_array() { - local name="$1" val="$2" - local -n arr="$name" - local out=("$val") - for f in "${arr[@]}"; do [[ $f != "$val" ]] && out+=("$f"); done - arr=("${out[@]}") -} - # ---- environment sanity ---------------------------------------------------- if [[ -z ${TERM:-} || $TERM == dumb ]]; then @@ -56,7 +42,10 @@ fi if [[ -n ${BASH_VERSION:-} && -z ${bash_preexec_imported:-} && -r "@BASHPREEXEC@" ]]; then # shellcheck disable=SC1090 . "@BASHPREEXEC@" - have __bp_install && __bp_install + # Do NOT call __bp_install here. bash-preexec must install on the FIRST prompt, + # after starship/atuin/zoxide/ghostty have modified PROMPT_COMMAND, so that + # __bp_interactive_mode stays the LAST PROMPT_COMMAND entry. Installing eagerly + # lets later hooks land after it and silently breaks preexec (atuin recording). log_shell_init "bash-preexec loaded" fi @@ -68,7 +57,8 @@ if have @STARSHIP@; then */bash) eval "$(@STARSHIP@ init bash)" ;; */zsh) eval "$(@STARSHIP@ init zsh)" ;; esac - append_unique PROMPT_COMMAND starship_precmd + # starship's bash init registers starship_precmd/starship_preexec_all with + # bash-preexec directly; no manual PROMPT_COMMAND wiring needed. else log_shell_init "starship skipped" fi @@ -87,10 +77,8 @@ if have @ATUIN@; then */bash) eval "$(@ATUIN@ init bash)" ;; */zsh) eval "$(@ATUIN@ init zsh)" ;; esac - - declare -a preexec_functions precmd_functions - prepend_unique_array preexec_functions __atuin_preexec - prepend_unique_array precmd_functions __atuin_precmd + # atuin's init registers __atuin_preexec/__atuin_precmd with bash-preexec + # itself; manual array wiring only caused duplicate hook entries. else log_shell_init "atuin skipped" fi @@ -103,16 +91,13 @@ if have zoxide; then */bash) eval "$(zoxide init bash)" ;; */zsh) eval "$(zoxide init zsh)" ;; esac - have __zoxide_hook && append_unique PROMPT_COMMAND __zoxide_hook + # zoxide's bash init hooks into bash-preexec (precmd_functions) when it is + # present; manual PROMPT_COMMAND wiring only pushed hooks past + # __bp_interactive_mode and broke preexec ordering. else log_shell_init "zoxide skipped" fi -# ---- bash-preexec PROMPT_COMMAND safety ----------------------------------- - -have __bp_precmd_invoke_cmd && append_unique PROMPT_COMMAND __bp_precmd_invoke_cmd -have __bp_interactive_mode && append_unique PROMPT_COMMAND __bp_interactive_mode - # ---- aliases -------------------------------------------------------------- if have eza; then