rclaude: keep tmux pane open on fast/nonzero claude exit

Wraps the inner claude invocation so a fast (under 2s) or nonzero exit shows
'[rclaude] claude exited in Ns with code N' and waits for enter, instead of
silently dying and dragging the whole tmux session + ssh transport down with
it (surfaces to user as bare 'Connection closed.'). Normal interactive exits
still close cleanly.
This commit is contained in:
Natalie 2026-04-26 00:17:14 -07:00
parent 77cd1c74b1
commit 509cdbbeec

View file

@ -207,6 +207,24 @@ case $perms in
*) flag="--permission-mode $perms" ;;
esac
# Inner command for the tmux pane. If claude exits nonzero OR ends in under
# 2 seconds (usually a misconfig: missing dir, locked session, crashed
# claude), the pane stays open with the exit code visible instead of
# silently dying and dragging the whole tmux session + ssh transport down
# with it. A real interactive session lasts much longer than 2s, so a clean
# /exit closes the pane normally.
build_inner() {
# Single-line, single-quote-safe. Variables prefixed with rc_ to avoid
# collision with anything in the user's shell.
printf '%s' \
"cd ${1} && rc_t=\$(date +%s); claude --continue ${flag}; rc_ec=\$?; " \
"rc_e=\$(date +%s); rc_d=\$((rc_e - rc_t)); " \
"if [ \$rc_ec -ne 0 ] || [ \$rc_d -lt 2 ]; then " \
"printf '\\n[rclaude] claude exited in %ds with code %d\\n' \$rc_d \$rc_ec; " \
"printf '[rclaude] press enter to close pane (or Ctrl-b d to detach)... '; " \
"read rc_; fi"
}
if is_local "$host"; then
if ! command -v tmux >/dev/null 2>&1; then
echo "rclaude: tmux not installed locally — install via 'brew install tmux' (macOS) or your package manager" >&2
@ -216,13 +234,12 @@ if is_local "$host"; then
echo "rclaude: local directory not found: $dir" >&2
exit 1
fi
exec tmux new-session -A -s "$session" "exec claude --continue ${flag}"
exec tmux new-session -A -s "$session" "$(build_inner "$dir")"
fi
# Remote: pre-flight the directory on the remote host so a typo or missing
# path fails loudly here instead of silently killing the tmux pane and
# closing the ssh transport (which looks like a generic "connection closed"
# error to the user).
# Remote: pre-flight the directory so a typo or missing path fails loudly
# here instead of silently killing the tmux pane and closing the ssh
# transport (which looks like a generic 'Connection closed' to the user).
if ! ssh -o BatchMode=yes -o ConnectTimeout=5 "$host" "test -d ${dir}" 2>/dev/null; then
echo "rclaude: directory not found on $host: $dir" >&2
case $dir in
@ -234,5 +251,5 @@ if ! ssh -o BatchMode=yes -o ConnectTimeout=5 "$host" "test -d ${dir}" 2>/dev/nu
exit 1
fi
inner="cd ${dir} && exec claude --continue ${flag}"
inner=$(build_inner "$dir")
exec ssh -t "$host" "tmux new-session -A -s '${session}' \"${inner}\""