feat(ux): F1 toggles help, --user flag, connect.sh fresh-build
CI / rust client (hh) (macos-latest) (push) Waiting to run
CI / rust client (hh) (ubuntu-latest) (push) Waiting to run
CI / rust coverage (push) Waiting to run
CI / python server (3.10) (push) Waiting to run
CI / python server (3.11) (push) Waiting to run
CI / python server (3.12) (push) Waiting to run
CI / headless e2e smoke (push) Waiting to run
CI / dependency audit (push) Waiting to run
CI / secret scanning (push) Waiting to run

- app.rs: F1 now closes the help overlay (toggle), not just opens it
- host-house.sh: add --user/--name flag to override the $USER default seat
- connect.sh: incremental cargo build before launch so the UI is never a
  stale release binary; --no-build escape hatch for toolchain-less joiners

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
leetcrypt
2026-06-06 21:51:54 -07:00
parent d948cdb63e
commit 7624cb04f7
3 changed files with 28 additions and 11 deletions
+21 -8
View File
@@ -13,11 +13,12 @@
# so it is briefly visible in the process list (ps) to other *local* users for # so it is briefly visible in the process list (ps) to other *local* users for
# the lifetime of the session. Nothing is ever written to disk. # the lifetime of the session. Nothing is ever written to disk.
# #
# Usage: ./connect.sh [NAME] [HOST] [-p PASSWORD] [-P PORT] [--tls] [--insecure] # Usage: ./connect.sh [NAME] [HOST] [-p PASSWORD] [-P PORT] [--tls] [--insecure] [--no-build]
# NAME display handle; omit to be prompted for one on join # NAME display handle; omit to be prompted for one on join
# HOST server IP/host (default: 127.0.0.1) # HOST server IP/host (default: 127.0.0.1)
# -P port (default: 4173, or $HH_PORT) # -P port (default: 4173, or $HH_PORT)
# --tls use wss/https instead of the default plaintext-over-Tailscale # --tls use wss/https instead of the default plaintext-over-Tailscale
# --no-build run the prebuilt binary as-is (skip the fresh debug rebuild)
set -euo pipefail set -euo pipefail
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
@@ -30,6 +31,7 @@ PORT="${HH_PORT:-$DEFAULT_PORT}"
PASSWORD="${HH_PASSWORD:-}" PASSWORD="${HH_PASSWORD:-}"
NO_TLS=1 # rooms run --no-tls over Tailscale/LAN by default NO_TLS=1 # rooms run --no-tls over Tailscale/LAN by default
INSECURE=0 INSECURE=0
NO_BUILD=0 # rebuild a fresh debug binary first so the UI is never stale
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
@@ -37,6 +39,7 @@ while [[ $# -gt 0 ]]; do
-P|--port) PORT="$2"; shift 2 ;; -P|--port) PORT="$2"; shift 2 ;;
--tls) NO_TLS=0; shift ;; --tls) NO_TLS=0; shift ;;
--insecure) INSECURE=1; shift ;; --insecure) INSECURE=1; shift ;;
--no-build) NO_BUILD=1; shift ;;
-h|--help) sed -n '2,/^set /{/^set /d;s/^# \{0,1\}//;p}' "$0"; exit 0 ;; -h|--help) sed -n '2,/^set /{/^set /d;s/^# \{0,1\}//;p}' "$0"; exit 0 ;;
-*) echo "✖ unknown option: $1" >&2; exit 2 ;; -*) echo "✖ unknown option: $1" >&2; exit 2 ;;
*) *)
@@ -56,9 +59,19 @@ if [[ -z "$PASSWORD" ]]; then
fi fi
[[ -n "$PASSWORD" ]] || { echo "✖ a password is required" >&2; exit 1; } [[ -n "$PASSWORD" ]] || { echo "✖ a password is required" >&2; exit 1; }
BIN=./target/release/hack-house # Build a fresh debug binary so the UI always matches the current source — an
[[ -x "$BIN" ]] || BIN=./target/debug/hack-house # incremental build is ~instant when nothing changed. --no-build skips this and
[[ -x "$BIN" ]] || { echo "✖ no hack-house binary — run: cargo build --release" >&2; exit 1; } # runs a prebuilt binary as-is (handy for remote joiners without a toolchain),
# preferring release, then debug.
if [[ "$NO_BUILD" -eq 0 ]]; then
echo "⛧ building client (use --no-build to skip)…" >&2
cargo build --quiet || { echo "✖ build failed" >&2; exit 1; }
BIN=./target/debug/hack-house
else
BIN=./target/release/hack-house
[[ -x "$BIN" ]] || BIN=./target/debug/hack-house
fi
[[ -x "$BIN" ]] || { echo "✖ no hack-house binary — run: cargo build" >&2; exit 1; }
args=(connect "$HOST" "$PORT") args=(connect "$HOST" "$PORT")
[[ -n "$NAME" ]] && args+=("$NAME") # omit → client prompts for a handle [[ -n "$NAME" ]] && args+=("$NAME") # omit → client prompts for a handle
+4 -1
View File
@@ -25,7 +25,7 @@ usage() {
host-house.sh — host a room + open your GUI seat, all in one tmux session host-house.sh — host a room + open your GUI seat, all in one tmux session
usage: usage:
./host-house.sh [NAME] [PORT] [--host ADDR] [--theme NAME] ./host-house.sh [NAME] [PORT] [--user NAME] [--host ADDR] [--theme NAME]
./host-house.sh --tls --cert CERT --key KEY [NAME] [PORT] ./host-house.sh --tls --cert CERT --key KEY [NAME] [PORT]
./host-house.sh --kill ./host-house.sh --kill
./host-house.sh -h | --help ./host-house.sh -h | --help
@@ -35,6 +35,7 @@ arguments:
PORT listen port (positional) (default: 4173) PORT listen port (positional) (default: 4173)
flags: flags:
--user NAME your seat in the room (alias: --name; overrides positional NAME)
--host ADDR server bind address (default: 0.0.0.0 — all NICs) --host ADDR server bind address (default: 0.0.0.0 — all NICs)
--port PORT listen port (default: 4173) --port PORT listen port (default: 4173)
--password PW room password (default: random; or PW=…) --password PW room password (default: random; or PW=…)
@@ -88,6 +89,8 @@ while [[ $# -gt 0 ]]; do
case "$1" in case "$1" in
-h|--help|-help) usage; exit 0 ;; -h|--help|-help) usage; exit 0 ;;
--kill) DO_KILL=1; shift ;; --kill) DO_KILL=1; shift ;;
--user|--name) NAME="$2"; shift 2 ;;
--user=*|--name=*) NAME="${1#*=}"; shift ;;
--host) HOST="$2"; shift 2 ;; --host) HOST="$2"; shift 2 ;;
--host=*) HOST="${1#--host=}"; shift ;; --host=*) HOST="${1#--host=}"; shift ;;
--port) PORT="$2"; shift 2 ;; --port) PORT="$2"; shift 2 ;;
+3 -2
View File
@@ -1014,8 +1014,9 @@ pub async fn run(params: net::ConnParams, mut session: Session, mut theme: Theme
KeyCode::PageDown => app.help_scroll = (app.help_scroll + 10).min(max), KeyCode::PageDown => app.help_scroll = (app.help_scroll + 10).min(max),
KeyCode::Home => app.help_scroll = 0, KeyCode::Home => app.help_scroll = 0,
KeyCode::End => app.help_scroll = max, KeyCode::End => app.help_scroll = max,
KeyCode::Esc => { KeyCode::Esc | KeyCode::F(1) => {
app.show_help = false; // Esc dismisses the overlay // Esc dismisses; F1 toggles the overlay back shut
app.show_help = false;
app.help_scroll = 0; app.help_scroll = 0;
} }
_ => {} // ignore other keys so the menu stays put _ => {} // ignore other keys so the menu stays put