From eb6de16033d88dc9b6a2125fcfc90a3804d9185a Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Nov 2026 15:23:59 +0000 Subject: [PATCH] fix(hooks): register the bash hook functions only once The bash hook appended preexec_invoke_cmd and precmd_invoke_cmd to the bash-preexec arrays without checking whether they were already there. Sourcing it again in the same shell (source ~/.bashrc, which the installer suggests to reload) registered both twice: every command then sent two pre events, the first precmd consumed LAST_COMMAND, and the second sent no post, so pre and post no longer paired up. Append each function only when its array doesn't already contain it. The zsh and fish hooks define their hooks as functions, so sourcing them again only redefines them; they are unchanged. Same file as model/hooks/bash.bash in shelltime/cli, which carries the regression test. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014EpZRfDAbFPp8o8CM7ED6j --- hooks/bash.bash | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/hooks/bash.bash b/hooks/bash.bash index 86a6274..73a8528 100644 --- a/hooks/bash.bash +++ b/hooks/bash.bash @@ -69,6 +69,25 @@ precmd_invoke_cmd() { shelltime track -s=bash -id=$SESSION_ID -cmd="$CMD" -p=post -r=$LAST_RESULT --ppid=$PPID &> /dev/null } -# Set the functions for bash-preexec -preexec_functions+=(preexec_invoke_cmd) -precmd_functions+=(precmd_invoke_cmd) +# Succeeds when the function name in $1 is one of the other arguments. +_shelltime_has_hook() { + local fn="$1" hook + shift + for hook in "$@"; do + if [ "$hook" == "$fn" ]; then + return 0 + fi + done + return 1 +} + +# Set the functions for bash-preexec, once. Sourcing this file again (as +# `source ~/.bashrc` does) would otherwise register them twice and every +# command would be tracked twice. +if ! _shelltime_has_hook preexec_invoke_cmd "${preexec_functions[@]:-}"; then + preexec_functions+=(preexec_invoke_cmd) +fi +if ! _shelltime_has_hook precmd_invoke_cmd "${precmd_functions[@]:-}"; then + precmd_functions+=(precmd_invoke_cmd) +fi +unset -f _shelltime_has_hook