# session-tools Resilient remote-execution wrappers for SSH/tmux patterns across the lilith host fleet (plum, apricot, black, quinn-vps, ...). The premise: a bare `ssh host cmd` dies the moment the transport hiccups, killing whatever was running on the remote. These wrappers run commands inside a detached tmux session on the remote so the work survives the SSH drop. ## Tools - **`bin/remote-run `** — One-shot command runner. Spawns a detached tmux session on ``, streams stdout/stderr back to your terminal, propagates the exit code. If the local ssh dies mid-run, the tmux session continues; reattach with `ssh tmux ls` then `ssh tmux attach -t `. - **`bin/tssh `** — Interactive shell wrapper. Auto-attaches to (or creates) a per-user tmux session on `` named `claude-$(whoami)`. Detach with `Ctrl-b d`; transport drops don't kill the shell. - **`bin/rclaude [dir]`** — Durable Claude Code session, local or remote. Stacks two resilience layers: tmux survives terminal/transport drops, and `claude --continue` resumes the per-directory session from `~/.claude/projects/` after anything kills the host itself. Re-running with the same `` + `` always lands back in the same conversation. `` can be any ssh target, or `local`/`localhost`/the local hostname to skip ssh and use a local tmux session (still detachable for terminal/network resilience). Defaults to `--dangerously-skip-permissions`; override with `RCLAUDE_PERMS=default`. - **`bin/rclaude send (--all|--host |--match ) [--yes] -- `** — Broadcast a prompt to live `claude-*` tmux sessions across `scan_hosts`. Dry-run by default: prints the resolved target list and exits. Pass `--yes` to actually deliver. Selectors are mutually exclusive — `--all` hits every live session, `--host` scopes to one host, `--match` substring-matches the session name (which embeds a slugified cwd via `claude_slug()`) or the cwd column. Delivery uses `tmux send-keys -l` (literal mode) so control sequences in `` cannot be interpreted by the target shell. ## Install On every host that should have these on `$PATH`: ```sh git clone http://forge.black.local/lilith/session-tools.git ~/Code/@scripts/session-tools ~/Code/@scripts/session-tools/install.sh ``` Symlinks `bin/remote-run` and `bin/tssh` into `~/bin`. Pulls future updates via plain `git pull` — symlinks track the repo automatically. ## When to use what | Scenario | Use | |--------------------------------------------|----------------------------------------------| | Interactive shell on a remote | `tssh ` | | One-off command (build, test, query) | `remote-run ""` | | Claude Code session on a remote | `rclaude [dir]` | | Broadcast a prompt to running Claudes | `rclaude send --all --yes -- ""` | | Long-running job (>1h, must survive reboot)| `systemd --user` unit on the remote, not ssh | ## Per-host shims (optional) If a particular host gets used a lot, drop a one-liner into `~/bin/`: ```sh # ~/bin/apricot-run #!/bin/sh exec remote-run apricot "$@" ```