feat(@scripts): improve resume cross-host sync logic

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-05-17 05:53:07 -07:00
parent 94621a28df
commit 13ff01a997

View file

@ -659,7 +659,12 @@ cmd_resume() {
exit 1 ;;
esac
migrate_session "$_host" "$_dst" "$_target" "$_session_cwd" "$_dst_cwd" || exit
RCLAUDE_RESUME_ID=$_target exec "$0" "$_dst" "$_dst_cwd"
# Pass src + src_cwd to the launch path so it can rsync the project
# tree if the dst dir doesn't exist (set RCLAUDE_MIGRATE_SYNC=none
# to skip and just mkdir).
RCLAUDE_MIGRATE_FROM=$_host RCLAUDE_MIGRATE_FROM_CWD=$_session_cwd \
RCLAUDE_RESUME_ID=$_target \
exec "$0" "$_dst" "$_dst_cwd"
;;
esac
}
@ -778,15 +783,53 @@ fi
# 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).
#
# Cross-host mirror exception: when invoked via `resume --on`, we've just
# migrated the session JSONL but the project files may not exist on the
# target. In that case auto-mkdir so the conversation can be resumed; the
# user can sync project files separately (rsync / git clone). The session
# state is what matters most for resume.
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
*@proj/*|*@apps/*|*@pkg/*)
echo " hint: '@proj/@apps/@pkg' are Claude-instruction aliases, not real shell paths." >&2
echo " See ~/.claude/instructions/project-paths.md for the real ~/Code/<bucket>/<project> mapping." >&2
;;
esac
exit 1
if [ -n "${RCLAUDE_RESUME_ID:-}" ] && [ -n "${RCLAUDE_MIGRATE_FROM:-}" ]; then
# Cross-host mirror landing: try to rsync the project tree from
# source to dst so claude has the files it expects. Falls back to
# mkdir-only when sync is disabled or rsync fails. Both endpoints
# being remote is unsupported (no two-hop relay).
_sync_mode=${RCLAUDE_MIGRATE_SYNC:-rsync}
_src_host=$RCLAUDE_MIGRATE_FROM
_src_dir=$RCLAUDE_MIGRATE_FROM_CWD
_did_rsync=0
if [ "$_sync_mode" = "rsync" ] && command -v rsync >/dev/null 2>&1; then
_src_local=0; _dst_local=0
is_local "$_src_host" && _src_local=1
is_local "$host" && _dst_local=1
if [ $((_src_local + _dst_local)) -ge 1 ]; then
_src_arg=$([ "$_src_local" = 1 ] && printf '%s/' "$_src_dir" || printf '%s:%s/' "$_src_host" "$_src_dir")
_dst_arg=$([ "$_dst_local" = 1 ] && printf '%s/' "$dir" || printf '%s:%s/' "$host" "$dir")
printf 'rclaude: rsyncing %s → %s ...\n' "$_src_arg" "$_dst_arg" >&2
if rsync -a --info=stats1 "$_src_arg" "$_dst_arg" >&2; then
_did_rsync=1
else
echo "rclaude: rsync failed; falling back to empty mkdir" >&2
fi
fi
fi
if [ "$_did_rsync" = 0 ]; then
echo "rclaude: $dir doesn't exist on $host — creating empty dir for session resume." >&2
echo " (sync separately if needed: rsync -a $_src_dir/ $host:$dir/)" >&2
ssh -o BatchMode=yes -o ConnectTimeout=5 "$host" "mkdir -p ${dir}" 2>/dev/null || {
echo "rclaude: mkdir failed on $host: $dir" >&2; exit 1; }
fi
else
echo "rclaude: directory not found on $host: $dir" >&2
case $dir in
*@proj/*|*@apps/*|*@pkg/*)
echo " hint: '@proj/@apps/@pkg' are Claude-instruction aliases, not real shell paths." >&2
echo " See ~/.claude/instructions/project-paths.md for the real ~/Code/<bucket>/<project> mapping." >&2
;;
esac
exit 1
fi
fi
sync_tmux_conf "$host"