chore: consolidate all shell scripts into hh/scripts/
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

Move the 14 hack-house scripts (bootstrap, lets-hack, host-room, smoke,
demo/film harnesses, connect/join, ensure-docker/vbox) into hh/scripts/
and fix their path resolution for the deeper location. Update cross-refs:
sbx.rs script consts, app.rs hints, CI, direnv .envrc, README, and docs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
leetcrypt
2026-06-06 17:49:32 -07:00
parent 9f7ab92270
commit 1fa8c332ed
21 changed files with 57 additions and 57 deletions
+1 -1
View File
@@ -97,7 +97,7 @@ jobs:
run: cargo build run: cargo build
working-directory: hh working-directory: hh
- name: run cross-stack smoke test - name: run cross-stack smoke test
run: bash hh/smoke-e2e.sh run: bash hh/scripts/smoke-e2e.sh
audit: audit:
name: dependency audit name: dependency audit
+20 -20
View File
@@ -50,8 +50,8 @@ Encrypted chat that runs in your terminal. You host the server, you control the
| `cmd_chat/agent/` | The model-agnostic AI agent bridge (joins a room as an encrypted client) | | `cmd_chat/agent/` | The model-agnostic AI agent bridge (joins a room as an encrypted client) |
| `models.toml` | Named provider profiles for `/ai start <profile>` (see `docs/providers.md`) | | `models.toml` | Named provider profiles for `/ai start <profile>` (see `docs/providers.md`) |
| `docs/providers.md` | Connect any model — profiles, flags, discovery, bring-your-own-provider | | `docs/providers.md` | Connect any model — profiles, flags, discovery, bring-your-own-provider |
| `hh/lets-hack.sh` | Spin up a local test "clergy" in tmux (server + N client panes) | | `hh/scripts/lets-hack.sh` | Spin up a local test "clergy" in tmux (server + N client panes) |
| `bootstrap-ai.sh` | Optional: install Ollama + pull a model for the local `/ai` agent | | `hh/scripts/bootstrap-ai.sh` | Optional: install Ollama + pull a model for the local `/ai` agent |
| `hh/direnv-autostart/` | `cd` into a directory to auto-launch a session (direnv) | | `hh/direnv-autostart/` | `cd` into a directory to auto-launch a session (direnv) |
## Quick start ## Quick start
@@ -61,42 +61,42 @@ git clone https://github.com/leetcrypt/hack-house.git
cd hack-house cd hack-house
``` ```
### 1. One-shot setup (`bootstrap.sh`) ### 1. One-shot setup (`hh/scripts/bootstrap.sh`)
Checks prerequisites, creates the Python venv, installs the server's Checks prerequisites, creates the Python venv, installs the server's
dependencies, and builds the Rust client: dependencies, and builds the Rust client:
```bash ```bash
./bootstrap.sh # venv + deps + debug build hh/scripts/bootstrap.sh # venv + deps + debug build
./bootstrap.sh --release # release build hh/scripts/bootstrap.sh --release # release build
./bootstrap.sh --check # report tooling only, change nothing hh/scripts/bootstrap.sh --check # report tooling only, change nothing
``` ```
> `bootstrap.sh` does **not** touch direnv — the autostart in step 4 is a > `bootstrap.sh` does **not** touch direnv — the autostart in step 4 is a
> separate, opt-in convenience. > separate, opt-in convenience.
**Optional AI layer (`bootstrap-ai.sh`).** Want the local `/ai` agent? This runs **Optional AI layer (`hh/scripts/bootstrap-ai.sh`).** Want the local `/ai` agent? This runs
the baseline setup first, then installs Ollama (if missing) and pulls a default the baseline setup first, then installs Ollama (if missing) and pulls a default
model — nothing here changes the AI-free baseline above: model — nothing here changes the AI-free baseline above:
```bash ```bash
./bootstrap-ai.sh # baseline + Ollama + qwen2.5:3b hh/scripts/bootstrap-ai.sh # baseline + Ollama + qwen2.5:3b
./bootstrap-ai.sh --check # report only, change nothing hh/scripts/bootstrap-ai.sh --check # report only, change nothing
HH_AI_MODEL=llama3 ./bootstrap-ai.sh # pull a different model HH_AI_MODEL=llama3 hh/scripts/bootstrap-ai.sh # pull a different model
``` ```
### 2. Try it in tmux (`lets-hack.sh`) ### 2. Try it in tmux (`scripts/lets-hack.sh`)
The fastest way to see it working: builds the client, boots a fresh `--no-tls` The fastest way to see it working: builds the client, boots a fresh `--no-tls`
server on `127.0.0.1:4173`, and opens a pane per user. server on `127.0.0.1:4173`, and opens a pane per user.
```bash ```bash
cd hh cd hh
./lets-hack.sh # alice + bob, tiled in tmux ./scripts/lets-hack.sh # alice + bob, tiled in tmux
./lets-hack.sh neo trinity # custom users ./scripts/lets-hack.sh neo trinity # custom users
./lets-hack.sh --theme neon # pick vestments ./scripts/lets-hack.sh --theme neon # pick vestments
./lets-hack.sh --reuse # keep a live server (reconnect tests) ./scripts/lets-hack.sh --reuse # keep a live server (reconnect tests)
./lets-hack.sh --kill # tear it all down ./scripts/lets-hack.sh --kill # tear it all down
``` ```
### 3. Manual setup ### 3. Manual setup
@@ -180,7 +180,7 @@ server only ever sees ciphertext (same trust model as chat).
| Backend | Isolation | Notes | | Backend | Isolation | Notes |
|---|---|---| |---|---|---|
| `local` | none | a `bash` shell on the host — fast, for dev/testing only | | `local` | none | a `bash` shell on the host — fast, for dev/testing only |
| `docker` | container | `ubuntu:24.04` by default; `/sbx launch docker --start` boots the daemon (or run `./ensure-docker.sh`) | | `docker` | container | `ubuntu:24.04` by default; `/sbx launch docker --start` boots the daemon (or run `hh/scripts/ensure-docker.sh`) |
| `multipass` | full VM | `24.04` by default; strongest isolation, ~30 s to boot, the choice for real use | | `multipass` | full VM | `24.04` by default; strongest isolation, ~30 s to boot, the choice for real use |
Tear it down with `/sbx stop` (purges the VM/container). Tear it down with `/sbx stop` (purges the VM/container).
@@ -247,7 +247,7 @@ when you quit). Pick a model at summon time with `/ai start <model>`.
- **Runs on *your* machine.** The default provider is [Ollama](https://ollama.com) - **Runs on *your* machine.** The default provider is [Ollama](https://ollama.com)
— a local model (default `qwen2.5:3b`), no API key, nothing leaves your host. — a local model (default `qwen2.5:3b`), no API key, nothing leaves your host.
Run `./bootstrap-ai.sh` once to install it and pull the model. Run `hh/scripts/bootstrap-ai.sh` once to install it and pull the model.
- **Addressed-only.** The agent reads room traffic like any client but forwards - **Addressed-only.** The agent reads room traffic like any client but forwards
to the model *only* the messages that trigger it (`/ai …`) — no passive to the model *only* the messages that trigger it (`/ai …`) — no passive
surveillance, no cost or noise when idle. surveillance, no cost or noise when idle.
@@ -301,8 +301,8 @@ to ~4000 lines of scrollback; the sandbox terminal keeps 2000.
| Variable | Where | Effect | | Variable | Where | Effect |
|---|---|---| |---|---|---|
| `CMD_CHAT_MAX_USERS` | server | Room capacity (default `4`) | | `CMD_CHAT_MAX_USERS` | server | Room capacity (default `4`) |
| `PORT` · `PW` · `HOST` | `lets-hack.sh` | Override the test server's port / password / bind host | | `PORT` · `PW` · `HOST` | `scripts/lets-hack.sh` | Override the test server's port / password / bind host |
| `THEME` | `lets-hack.sh` | Vestments for every pane (`church` · `neon` · `crypt`) | | `THEME` | `scripts/lets-hack.sh` | Vestments for every pane (`church` · `neon` · `crypt`) |
| `HH_SESSION` · `HH_USER` | direnv autostart | tmux session name / your in-session name | | `HH_SESSION` · `HH_USER` | direnv autostart | tmux session name / your in-session name |
## Securing your connection ## Securing your connection
+1 -1
View File
@@ -63,7 +63,7 @@ the chat provider is Ollama and a `qwen2.5-coder` is present (it is — pulled).
## Execution ## Execution
`hh/demo-save-load.sh` drives the whole thing headlessly over tmux (per the `hh/scripts/demo-save-load.sh` drives the whole thing headlessly over tmux (per the
TUI-tmux test recipe): boots the server, runs client **session A**, injects the TUI-tmux test recipe): boots the server, runs client **session A**, injects the
beats with `send-keys`, verifies via `capture-pane` + `docker exec`, then quits beats with `send-keys`, verifies via `capture-pane` + `docker exec`, then quits
session A and opens client **session B** to load and confirm. It is a PoC / session A and opens client **session B** to load and confirm. It is a PoC /
+4 -4
View File
@@ -87,7 +87,7 @@ documented fallback for images without sshd.
Each headless VM needs a unique host loopback port for its SSH forward. Reuse the Each headless VM needs a unique host loopback port for its SSH forward. Reuse the
free-port discovery already used by the save/load PoC (see free-port discovery already used by the save/load PoC (see
`docs/demo-save-load-poc.md` / `hh/demo-save-load.sh`) so two sandboxes on one `docs/demo-save-load-poc.md` / `hh/scripts/demo-save-load.sh`) so two sandboxes on one
host don't collide. The owner is the only one who ever connects to it host don't collide. The owner is the only one who ever connects to it
(`127.0.0.1:<port>`), so it never leaves the host. (`127.0.0.1:<port>`), so it never leaves the host.
@@ -146,7 +146,7 @@ desktop" become two ends of one workflow.
## 4. Installation handling — `ensure-vbox.sh` (detect first) ## 4. Installation handling — `ensure-vbox.sh` (detect first)
Mirror `hh/ensure-docker.sh` exactly in spirit: **a backend never installs Mirror `hh/scripts/ensure-docker.sh` exactly in spirit: **a backend never installs
anything silently.** anything silently.**
### 4.1 Detection (always first, zero side effects) ### 4.1 Detection (always first, zero side effects)
@@ -166,7 +166,7 @@ loud with the remedy**, exactly like the Docker daemon message at `app.rs:1206`:
### 4.2 The installer script ### 4.2 The installer script
`hh/ensure-vbox.sh`, invoked as `bash ensure-vbox.sh --yes` only when the user `hh/scripts/ensure-vbox.sh`, invoked as `bash ensure-vbox.sh --yes` only when the user
passed `--install` (matching how `prepare` shells `ensure-docker.sh --yes` at passed `--install` (matching how `prepare` shells `ensure-docker.sh --yes` at
`sbx.rs:31`). It: `sbx.rs:31`). It:
@@ -229,7 +229,7 @@ sudo delegation, and save/load machinery are all backend-agnostic already.
|---|---| |---|---|
| `hh/src/sbx.rs` | `Backend::VirtualBox` variant; arms in `parse`/`label`/`default_image`/`prepare`/`command_for`/`provision`/`set_sudo`/`save_state`/`list_snapshots`/`teardown`; `vbox_installed()`, `vbx()` SSH helper; `export_ova()` + `open_local()` (Mode B, local-only). | | `hh/src/sbx.rs` | `Backend::VirtualBox` variant; arms in `parse`/`label`/`default_image`/`prepare`/`command_for`/`provision`/`set_sudo`/`save_state`/`list_snapshots`/`teardown`; `vbox_installed()`, `vbx()` SSH helper; `export_ova()` + `open_local()` (Mode B, local-only). |
| `hh/src/app.rs` | accept `virtualbox`/`vbox` in `/sbx launch`; generalize `/sbx load` off hardcoded Docker (`:1282`) to the broker backend; new `/sbx export`, `/sbx open`, `/sbx gui` arms; extend usage string (`:1309`); install-missing error mirroring `:1206`. | | `hh/src/app.rs` | accept `virtualbox`/`vbox` in `/sbx launch`; generalize `/sbx load` off hardcoded Docker (`:1282`) to the broker backend; new `/sbx export`, `/sbx open`, `/sbx gui` arms; extend usage string (`:1309`); install-missing error mirroring `:1206`. |
| `hh/ensure-vbox.sh` (new) | detect-first installer, per `§4`. | | `hh/scripts/ensure-vbox.sh` (new) | detect-first installer, per `§4`. |
| `hh/src/ui.rs` | add the three new commands to the clustered help menu. | | `hh/src/ui.rs` | add the three new commands to the clustered help menu. |
| `README.MD` | backend table (`:175`) gains a `virtualbox` row; a short "share a VM, run it locally" subsection. | | `README.MD` | backend table (`:175`) gains a `virtualbox` row; a short "share a VM, run it locally" subsection. |
| `models.toml` / docs | none. | | `models.toml` / docs | none. |
+1 -1
View File
@@ -31,5 +31,5 @@ if ! command -v tmux >/dev/null 2>&1; then
elif tmux has-session -t "$SESSION" 2>/dev/null; then elif tmux has-session -t "$SESSION" 2>/dev/null; then
echo "'$SESSION' already live — tmux attach -t $SESSION (reveal its password in-app with /pw)" echo "'$SESSION' already live — tmux attach -t $SESSION (reveal its password in-app with /pw)"
else else
PW="${PW:-$(gen_pw)}" "$HH_DIR/lets-hack.sh" "$HH_USER" PW="${PW:-$(gen_pw)}" "$HH_DIR/scripts/lets-hack.sh" "$HH_USER"
fi fi
@@ -21,7 +21,7 @@
# OLLAMA_HOST daemon URL (default: http://localhost:11434) # OLLAMA_HOST daemon URL (default: http://localhost:11434)
set -uo pipefail set -uo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)" ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
MODEL="${HH_AI_MODEL:-qwen2.5:3b}" MODEL="${HH_AI_MODEL:-qwen2.5:3b}"
OLLAMA_HOST="${OLLAMA_HOST:-http://localhost:11434}" OLLAMA_HOST="${OLLAMA_HOST:-http://localhost:11434}"
INSTALLER_URL="https://ollama.com/install.sh" INSTALLER_URL="https://ollama.com/install.sh"
@@ -51,9 +51,9 @@ ollama_up() { curl -s --max-time 3 "$OLLAMA_HOST/api/tags" >/dev/null 2>&1; }
# by default). --ai-only skips the baseline entirely (caller already ran it). # by default). --ai-only skips the baseline entirely (caller already ran it).
if [[ $AI_ONLY -ne 1 ]]; then if [[ $AI_ONLY -ne 1 ]]; then
if [[ $CHECK_ONLY -eq 1 ]]; then if [[ $CHECK_ONLY -eq 1 ]]; then
"$ROOT/bootstrap.sh" --no-ai --check || exit $? "$ROOT/hh/scripts/bootstrap.sh" --no-ai --check || exit $?
else else
"$ROOT/bootstrap.sh" --no-ai "${RELEASE_ARGS[@]}" || exit $? "$ROOT/hh/scripts/bootstrap.sh" --no-ai "${RELEASE_ARGS[@]}" || exit $?
fi fi
fi fi
+5 -5
View File
@@ -17,10 +17,10 @@
# It still prompts before installing/pulling on an interactive terminal — skip # It still prompts before installing/pulling on an interactive terminal — skip
# the whole thing with --no-ai, or skip the prompts with --yes. # the whole thing with --no-ai, or skip the prompts with --yes.
# #
# After it finishes, spin up a local test session with: cd hh && ./lets-hack.sh # After it finishes, spin up a local test session with: cd hh && ./scripts/lets-hack.sh
set -uo pipefail set -uo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)" ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
VENV="$ROOT/.venv" VENV="$ROOT/.venv"
HH_DIR="$ROOT/hh" HH_DIR="$ROOT/hh"
@@ -92,14 +92,14 @@ fi
if [[ $DO_AI -eq 1 ]]; then if [[ $DO_AI -eq 1 ]]; then
ai_args=(--ai-only) ai_args=(--ai-only)
[[ $ASSUME_YES -eq 1 ]] && ai_args+=(--yes) [[ $ASSUME_YES -eq 1 ]] && ai_args+=(--yes)
"$ROOT/bootstrap-ai.sh" "${ai_args[@]}" \ "$ROOT/hh/scripts/bootstrap-ai.sh" "${ai_args[@]}" \
|| echo "⚠ AI layer not completed — re-run ./bootstrap-ai.sh when ready" >&2 || echo "⚠ AI layer not completed — re-run ./bootstrap-ai.sh when ready" >&2
fi fi
echo echo
echo "ready. next steps:" echo "ready. next steps:"
echo " cd hh && ./lets-hack.sh # local test session (server + clients in tmux)" echo " cd hh && ./scripts/lets-hack.sh # local test session (server + clients in tmux)"
echo " # or run the server + client by hand — see README.MD" echo " # or run the server + client by hand — see README.MD"
if [[ $DO_AI -eq 0 ]]; then if [[ $DO_AI -eq 0 ]]; then
echo " # AI layer skipped (--no-ai); add it later with ./bootstrap-ai.sh" echo " # AI layer skipped (--no-ai); add it later with hh/scripts/bootstrap-ai.sh"
fi fi
+1 -1
View File
@@ -19,7 +19,7 @@
# -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
set -euo pipefail set -euo pipefail
cd "$(dirname "$0")" cd "$(dirname "$0")/.."
DEFAULT_PORT=4173 DEFAULT_PORT=4173
DEFAULT_HOST=127.0.0.1 DEFAULT_HOST=127.0.0.1
@@ -10,12 +10,12 @@
# Headless: drives the ratatui client over tmux send-keys, asserts via # Headless: drives the ratatui client over tmux send-keys, asserts via
# capture-pane + `docker exec`. PoC/correctness first; feeds video-toolkit later. # capture-pane + `docker exec`. PoC/correctness first; feeds video-toolkit later.
# #
# Usage: hh/demo-save-load.sh [--keep] # Usage: hh/scripts/demo-save-load.sh [--keep]
# --keep leave the server, container, image and tmux sessions up afterwards # --keep leave the server, container, image and tmux sessions up afterwards
set -uo pipefail set -uo pipefail
# ---- config ----------------------------------------------------------------- # ---- config -----------------------------------------------------------------
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# Pick a free TCP port so we never collide with a stale server from another # Pick a free TCP port so we never collide with a stale server from another
# session (a leftover server on a fixed port answers SRP with its own password # session (a leftover server on a fixed port answers SRP with its own password
# → spurious 401s). Honour an explicit $PORT if the caller forces one. # → spurious 401s). Honour an explicit $PORT if the caller forces one.
@@ -12,13 +12,13 @@
# session; `asciinema rec` runs in its own detached session that `tmux attach`es # session; `asciinema rec` runs in its own detached session that `tmux attach`es
# to the inner one, so it mirrors exactly what we drive with send-keys. # to the inner one, so it mirrors exactly what we drive with send-keys.
# #
# Usage: hh/film-save-load.sh [--keep] [--no-render] # Usage: hh/scripts/film-save-load.sh [--keep] [--no-render]
# --keep leave server/sessions/container/image up afterwards # --keep leave server/sessions/container/image up afterwards
# --no-render stop after writing the .cast (skip the mp4 render) # --no-render stop after writing the .cast (skip the mp4 render)
set -uo pipefail set -uo pipefail
# ---- config ----------------------------------------------------------------- # ---- config -----------------------------------------------------------------
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
pick_port() { local p; for p in $(seq 4200 4280); do ss -ltn 2>/dev/null | grep -q ":$p " || { echo "$p"; return; }; done; echo 4173; } pick_port() { local p; for p in $(seq 4200 4280); do ss -ltn 2>/dev/null | grep -q ":$p " || { echo "$p"; return; }; done; echo 4173; }
PORT="${PORT:-$(pick_port)}" PORT="${PORT:-$(pick_port)}"
PW="${PW:-malware-bless}" PW="${PW:-malware-bless}"
@@ -11,13 +11,13 @@
# stitches title→terminal→gui→result; edge-tts narration + an SRT are muxed/burned # stitches title→terminal→gui→result; edge-tts narration + an SRT are muxed/burned
# on top. # on top.
# #
# Usage: hh/film-virtualbox.sh [--keep] [--no-render] [--no-vm] # Usage: hh/scripts/film-virtualbox.sh [--keep] [--no-render] [--no-vm]
# --keep leave server/sessions up; don't power off the VM # --keep leave server/sessions up; don't power off the VM
# --no-render stop after the captures (skip compose) # --no-render stop after the captures (skip compose)
# --no-vm skip booting the VM (reuse an already-running one for GUI grab) # --no-vm skip booting the VM (reuse an already-running one for GUI grab)
set -uo pipefail set -uo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
VTK="$HOME/coding/video-toolkit" VTK="$HOME/coding/video-toolkit"
FORGE_PY="$HOME/anaconda3/bin/python3" FORGE_PY="$HOME/anaconda3/bin/python3"
pick_port() { local p; for p in $(seq 4240 4290); do ss -ltn 2>/dev/null | grep -q ":$p " || { echo "$p"; return; }; done; echo 4173; } pick_port() { local p; for p in $(seq 4240 4290); do ss -ltn 2>/dev/null | grep -q ":$p " || { echo "$p"; return; }; done; echo 4173; }
+1 -1
View File
@@ -54,7 +54,7 @@ examples:
EOF EOF
} }
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # repo root (where this lives) ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" # repo root
PY="$ROOT/.venv/bin/python" PY="$ROOT/.venv/bin/python"
[[ -x "$PY" ]] || PY="$(command -v python3 || command -v python)" [[ -x "$PY" ]] || PY="$(command -v python3 || command -v python)"
+1 -1
View File
@@ -6,7 +6,7 @@
# prompt — never hardcoded, so it can't drift from the room's random password. # prompt — never hardcoded, so it can't drift from the room's random password.
NAME="${1:-guest}" NAME="${1:-guest}"
HOST="${2:-127.0.0.1}" HOST="${2:-127.0.0.1}"
cd "$(dirname "$0")" cd "$(dirname "$0")/.."
# Sync the latest code before joining, then rebuild so it takes effect. Pulls # Sync the latest code before joining, then rebuild so it takes effect. Pulls
# are best-effort and fast-forward only: an unreachable remote or diverged # are best-effort and fast-forward only: an unreachable remote or diverged
+1 -1
View File
@@ -65,7 +65,7 @@ examples:
EOF EOF
} }
HERE="$(cd "$(dirname "$0")" && pwd)" # .../hh HERE="$(cd "$(dirname "$0")/.." && pwd)" # .../hh
ROOT="$(cd "$HERE/.." && pwd)" # repo root ROOT="$(cd "$HERE/.." && pwd)" # repo root
PY="$ROOT/.venv/bin/python" # venv always from the real checkout PY="$ROOT/.venv/bin/python" # venv always from the real checkout
BIN="$HERE/target/debug/hack-house" BIN="$HERE/target/debug/hack-house"
+1 -1
View File
@@ -15,7 +15,7 @@
# Env overrides: PY=<python> BIN=<client binary> PORT=<port> PW=<password> # Env overrides: PY=<python> BIN=<client binary> PORT=<port> PW=<password>
set -uo pipefail set -uo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# Python: prefer the repo venv locally, fall back to PATH (CI installs into the # Python: prefer the repo venv locally, fall back to PATH (CI installs into the
# job's own interpreter). # job's own interpreter).
if [[ -z "${PY:-}" ]]; then if [[ -z "${PY:-}" ]]; then
+2 -2
View File
@@ -3,10 +3,10 @@
# Exercises the full use-case path end to end against a live server: # Exercises the full use-case path end to end against a live server:
# rust unit tests → SRP self-test → boot server → rust client handshake + # rust unit tests → SRP self-test → boot server → rust client handshake +
# round-trip → cross-language (python decrypts what the rust client sent). # round-trip → cross-language (python decrypts what the rust client sent).
# Run from anywhere: hh/smoke.sh # Run from anywhere: hh/scripts/smoke.sh
set -uo pipefail set -uo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)" # .../hh HERE="$(cd "$(dirname "$0")/.." && pwd)" # .../hh
ROOT="$(cd "$HERE/.." && pwd)" # repo root ROOT="$(cd "$HERE/.." && pwd)" # repo root
PY="$ROOT/.venv/bin/python" PY="$ROOT/.venv/bin/python"
BIN="$HERE/target/debug/hack-house" BIN="$HERE/target/debug/hack-house"
@@ -14,7 +14,7 @@
# tmux attach -t hh-autotest # tmux attach -t hh-autotest
set -uo pipefail set -uo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)" # .../hh HERE="$(cd "$(dirname "$0")/.." && pwd)" # .../hh
ROOT="$(cd "$HERE/.." && pwd)" # repo root ROOT="$(cd "$HERE/.." && pwd)" # repo root
PY="$ROOT/.venv/bin/python" PY="$ROOT/.venv/bin/python"
BIN="$HERE/target/debug/hack-house" BIN="$HERE/target/debug/hack-house"
+4 -4
View File
@@ -1397,7 +1397,7 @@ fn handle_command(
&& !start_daemon && !start_daemon
&& !sbx::docker_daemon_up() && !sbx::docker_daemon_up()
{ {
app.err("docker daemon is not running — retry with `/sbx launch docker --start` to boot it (sudo), or run ./ensure-docker.sh in a terminal first"); app.err("docker daemon is not running — retry with `/sbx launch docker --start` to boot it (sudo), or run ./scripts/ensure-docker.sh in a terminal first");
} else { } else {
let sz = term.size().map(|s| (s.width, s.height)).unwrap_or((80, 24)); let sz = term.size().map(|s| (s.width, s.height)).unwrap_or((80, 24));
let (rows, cols) = sbx_dims(sz.0, sz.1); let (rows, cols) = sbx_dims(sz.0, sz.1);
@@ -1518,7 +1518,7 @@ fn handle_command(
tokio::spawn(async move { tokio::spawn(async move {
let res = tokio::task::spawn_blocking(|| { let res = tokio::task::spawn_blocking(|| {
let ver = sbx::vbox_version().ok_or_else(|| { let ver = sbx::vbox_version().ok_or_else(|| {
"VirtualBox isn't installed — install it with `/sbx gui <vm> --install`, or run ./ensure-vbox.sh".to_string() "VirtualBox isn't installed — install it with `/sbx gui <vm> --install`, or run ./scripts/ensure-vbox.sh".to_string()
})?; })?;
let vms = sbx::list_vms().map_err(|e| e.to_string())?; let vms = sbx::list_vms().map_err(|e| e.to_string())?;
Ok::<_, String>((ver, vms)) Ok::<_, String>((ver, vms))
@@ -1821,10 +1821,10 @@ fn handle_command(
ms.join(", ") ms.join(", ")
), ),
Ok(_) => "ollama is reachable but has no models pulled — \ Ok(_) => "ollama is reachable but has no models pulled — \
`ollama pull qwen2.5:3b` or run ./bootstrap-ai.sh" `ollama pull qwen2.5:3b` or run ./scripts/bootstrap-ai.sh"
.to_string(), .to_string(),
Err(_) => "ollama not reachable at localhost:11434 — run \ Err(_) => "ollama not reachable at localhost:11434 — run \
./bootstrap-ai.sh, or `/ai start <profile>` for a cloud model" ./scripts/bootstrap-ai.sh, or `/ai start <profile>` for a cloud model"
.to_string(), .to_string(),
}; };
let _ = tx.send(Net::Sys(msg)); let _ = tx.send(Net::Sys(msg));
+4 -4
View File
@@ -12,10 +12,10 @@ use std::io::{Read, Write};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::mpsc; use std::sync::mpsc;
/// Helper that ensures the Docker daemon is running (ships beside this source). /// Helper that ensures the Docker daemon is running (ships in hh/scripts/).
const ENSURE_DOCKER: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/ensure-docker.sh"); const ENSURE_DOCKER: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/scripts/ensure-docker.sh");
/// Detect-first VirtualBox installer (ships beside this source). /// Detect-first VirtualBox installer (ships in hh/scripts/).
const ENSURE_VBOX: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/ensure-vbox.sh"); const ENSURE_VBOX: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/scripts/ensure-vbox.sh");
/// Is the Docker daemon accepting connections? (`docker info` succeeds.) /// Is the Docker daemon accepting connections? (`docker info` succeeds.)
pub fn docker_daemon_up() -> bool { pub fn docker_daemon_up() -> bool {