#!/bin/sh
# rclaude — durable Claude Code sessions, local or remote.
#
# Two layers of resilience:
#   1. tmux on <host> survives terminal/transport drops.
#   2. `claude --continue` resumes the per-directory session from disk after
#      the host itself dies (reboot, crash, OOM).
#
# Re-running with the same target lands you back in the same conversation:
# tmux reattaches if alive; claude --continue picks up from
# ~/.claude/projects/<encoded-cwd>/ otherwise.
#
# Permission mode: --dangerously-skip-permissions is on by default. Override
# with RCLAUDE_PERMS=default (or any --permission-mode value).
#
# Hosts scanned by `list`/`resume` default to: local + apricot. Override with
# RCLAUDE_HOSTS="apricot black quinn-vps".
#
# Usage:
#   rclaude                                  # local, $PWD
#   rclaude .                                # local, $PWD
#   rclaude <host>                           # remote $HOME on <host>
#   rclaude <host> <dir>                     # remote (or local) at <dir>
#   rclaude list                             # show active sessions across hosts
#   rclaude resume [pattern]                 # reattach (interactive if pattern matches >1)

set -eu

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

is_local() {
    case $1 in
        local|localhost|127.0.0.1|::1) return 0 ;;
    esac
    [ "$1" = "$(hostname)" ] && return 0
    [ "$1" = "$(hostname -s 2>/dev/null)" ] && return 0
    return 1
}

# List claude-* tmux sessions on a host. Output: one line per session,
# format: "<host>\t<session_name>\t<rest_from_tmux_ls>"
list_sessions_on() {
    _host=$1
    if is_local "$_host"; then
        command -v tmux >/dev/null 2>&1 || return 0   # no local tmux: nothing to list
        _raw=$(tmux ls 2>/dev/null || true)
    else
        _raw=$(ssh -o BatchMode=yes -o ConnectTimeout=3 "$_host" 'tmux ls 2>/dev/null' || true)
    fi
    # tmux ls lines look like:  claude-foo: 1 windows (created ...) [80x24]
    printf %s "$_raw" | awk -v host="$_host" '
        /^claude-/ {
            name=$1; sub(/:$/, "", name);
            $1="";
            sub(/^[[:space:]]+/, "");
            printf "%s\t%s\t%s\n", host, name, $0
        }
    '
}

# All hosts to scan for list/resume.
scan_hosts() {
    printf "local\n"
    for h in ${RCLAUDE_HOSTS:-apricot}; do
        printf "%s\n" "$h"
    done
}

# ---------------------------------------------------------------------------
# Subcommands
# ---------------------------------------------------------------------------

cmd_list() {
    _any=0
    printf "%-10s  %-50s  %s\n" "HOST" "SESSION" "DETAIL"
    scan_hosts | while IFS= read -r h; do
        list_sessions_on "$h" | while IFS="$(printf '\t')" read -r host name detail; do
            printf "%-10s  %-50s  %s\n" "$host" "$name" "$detail"
            _any=1
        done
    done
}

cmd_resume() {
    _pattern=${1:-}
    _matches=$(scan_hosts | while IFS= read -r h; do list_sessions_on "$h"; done)
    if [ -n "$_pattern" ]; then
        _matches=$(printf '%s\n' "$_matches" | grep -F -- "$_pattern" || true)
    fi
    _count=0
    [ -n "$_matches" ] && _count=$(printf '%s\n' "$_matches" | wc -l | tr -d ' ')
    if [ "$_count" -eq 0 ]; then
        echo "no matching sessions${_pattern:+ for pattern '$_pattern'}" >&2
        exit 1
    fi
    if [ "$_count" -gt 1 ]; then
        echo "multiple matches; refine pattern:" >&2
        printf '%s\n' "$_matches" | awk -F'\t' '{printf "  %-10s  %s\n", $1, $2}' >&2
        exit 1
    fi
    _host=$(printf '%s\n' "$_matches" | awk -F'\t' 'NR==1{print $1}')
    _name=$(printf '%s\n' "$_matches" | awk -F'\t' 'NR==1{print $2}')
    if is_local "$_host"; then
        exec tmux attach -t "$_name"
    else
        exec ssh -t "$_host" tmux attach -t "$_name"
    fi
}

# ---------------------------------------------------------------------------
# Dispatch
# ---------------------------------------------------------------------------

case ${1:-} in
    list)   shift; cmd_list   "$@"; exit ;;
    resume) shift; cmd_resume "$@"; exit ;;
esac

# ---------------------------------------------------------------------------
# Default behavior: launch (or reattach to) a session.
# ---------------------------------------------------------------------------

# Argument resolution:
#   `rclaude`        → local, $PWD
#   `rclaude .`      → local, $PWD
#   `rclaude <host>` → host, default dir (~ remote, $PWD local)
#   `rclaude <host> <dir>` → host, dir (with `.` resolving to $PWD)
if [ $# -eq 0 ] || [ "${1:-}" = "." ]; then
    host=local
    dir=$PWD
else
    host=$1
    dir=${2:-}
fi

# Defaults + `.` expansion now that we know whether we're local or remote.
if is_local "$host"; then
    case ${dir:-.} in
        .|"") dir=$PWD ;;
    esac
else
    if [ "$dir" = "." ]; then
        echo "error: '.' as dir requires a local target; pass an explicit remote path" >&2
        exit 2
    fi
    [ -z "$dir" ] && dir=\~
fi

slug=$(printf %s "$dir" | sed -e 's|^[~/]*||' -e 's|[^A-Za-z0-9]|-|g')
[ -z "$slug" ] && slug=home
session="claude-$(whoami)-${slug}"

perms=${RCLAUDE_PERMS:-bypass}
case $perms in
    bypass) flag="--dangerously-skip-permissions" ;;
    *)      flag="--permission-mode $perms" ;;
esac

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
        exit 1
    fi
    cd "$dir"
    exec tmux new-session -A -s "$session" "exec claude --continue ${flag}"
fi

inner="cd ${dir} && exec claude --continue ${flag}"
exec ssh -t "$host" "tmux new-session -A -s '${session}' \"${inner}\""
