session-tools/README.md
Natalie 79268d4db6 fix(@scripts): 🐛 update forge.black.local to forge.black.lan
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-06-10 03:38:19 -07:00

3.3 KiB

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 <host> <cmd...> — One-shot command runner. Spawns a detached tmux session on <host>, 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 <host> tmux ls then ssh <host> tmux attach -t <session>.

  • bin/tssh <host> — Interactive shell wrapper. Auto-attaches to (or creates) a per-user tmux session on <host> named claude-$(whoami). Detach with Ctrl-b d; transport drops don't kill the shell.

  • bin/rclaude <host> [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 <host> + <dir> always lands back in the same conversation. <host> 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 <h>|--match <pat>) [--yes] -- <text...> — 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 <text> cannot be interpreted by the target shell.

Install

On every host that should have these on $PATH:

git clone http://forge.black.lan/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 <host>
One-off command (build, test, query) remote-run <host> "<cmd>"
Claude Code session on a remote rclaude <host> [dir]
Broadcast a prompt to running Claudes rclaude send --all --yes -- "<text>"
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/:

# ~/bin/apricot-run
#!/bin/sh
exec remote-run apricot "$@"