mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-15 14:22:43 +00:00
scripts/desktop-sandbox.sh runs a Hermes desktop instance in an isolated sandbox — separate HERMES_HOME, separate Electron userData, and a distinct app name (HERMES_DESKTOP_APP_NAME) so it doesn't compete with the main desktop instance's single-instance lock. Two modes: - Ephemeral (default): temp dir, cleaned up on exit - --persistent: stored under .hermes-sandbox/ in the worktree git root, survives restarts for repeat testing In the Nix devShell the script is available as 'sandbox'. Also makes APP_NAME overridable via HERMES_DESKTOP_APP_NAME in main.ts — app.setName() runs before requestSingleInstanceLock(), so the overridden name changes the lock key. collectRelaunchEnv already preserves HERMES_DESKTOP_* vars through self-update relaunches; test updated to cover the new env var.
152 lines
4.3 KiB
Bash
Executable file
152 lines
4.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Run a Hermes instance in an isolated sandbox — separate HERMES_HOME,
|
|
# separate Electron userData, and a distinct Desktop app name so it doesn't compete
|
|
# with your main desktop instance's single-instance lock.
|
|
#
|
|
# By default the sandbox is throwaway: a temp dir is created and removed on
|
|
# exit. Use --persistent to keep the sandbox across restarts (stored under
|
|
# .hermes-sandbox/ in the worktree git root).
|
|
#
|
|
# Usage:
|
|
# scripts/dev-sandbox.sh python -m hermes_cli.main
|
|
# scripts/dev-sandbox.sh hermes desktop
|
|
# scripts/dev-sandbox.sh electron .
|
|
# scripts/dev-sandbox.sh -- npm run dev # from apps/desktop/
|
|
# scripts/dev-sandbox.sh --persistent hermes desktop
|
|
# scripts/dev-sandbox.sh --persistent -- npm run dev
|
|
#
|
|
# Override the app name (default: HermesSandbox):
|
|
# HERMES_DEV_SANDBOX_NAME=Staging scripts/dev-sandbox.sh hermes desktop
|
|
#
|
|
# Override the persistent sandbox dir name (default: .hermes-sandbox):
|
|
# HERMES_DEV_SANDBOX_DIR=.staging-sandbox scripts/dev-sandbox.sh --persistent hermes desktop
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
print_help() {
|
|
cat <<'EOF'
|
|
Usage: dev-sandbox.sh [--persistent] [--] <command...>
|
|
|
|
Run a Hermes instance in an isolated sandbox.
|
|
|
|
Options:
|
|
--persistent Keep the sandbox dir across restarts (under the worktree
|
|
git root, in .hermes-sandbox/). Without this flag the
|
|
sandbox is a temp dir that is removed on exit.
|
|
--delete Delete the existing persistent sandbox in .hermes-sandbox.
|
|
-h, --help Show this help message.
|
|
|
|
Environment:
|
|
HERMES_DEV_SANDBOX_NAME Override the app name (default: HermesSandbox)
|
|
HERMES_DEV_SANDBOX_DIR Override the persistent dir name (default: .hermes-sandbox)
|
|
|
|
Examples:
|
|
dev-sandbox.sh hermes desktop
|
|
dev-sandbox.sh --persistent hermes desktop
|
|
dev-sandbox.sh -- npm run dev
|
|
EOF
|
|
}
|
|
|
|
PERSISTENT=false
|
|
DELETE=false
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--persistent)
|
|
PERSISTENT=true
|
|
shift
|
|
;;
|
|
--delete)
|
|
DELETE=true
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
print_help
|
|
exit 0
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
*)
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ "$#" -eq 0 ]; then
|
|
print_help >&2
|
|
exit 1
|
|
fi
|
|
|
|
|
|
SANDBOX_DIR_NAME="${HERMES_DEV_SANDBOX_DIR:-.hermes-sandbox}"
|
|
GIT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR/..")"
|
|
GIT_ROOT="$(cd "$GIT_ROOT" && pwd)"
|
|
PERSISTENT_SANDBOX_ROOT="$GIT_ROOT/$SANDBOX_DIR_NAME"
|
|
|
|
if [ "$DELETE" = true ]; then
|
|
if [ -d "$PERSISTENT_SANDBOX_ROOT" ]; then
|
|
read -r -p "[sandbox] delete $PERSISTENT_SANDBOX_ROOT? [y/N] " REPLY
|
|
case "$REPLY" in
|
|
[yY]|[yY][eE][sS])
|
|
echo "[sandbox] deleting $PERSISTENT_SANDBOX_ROOT" >&2
|
|
rm -rf -- "$PERSISTENT_SANDBOX_ROOT"
|
|
;;
|
|
*)
|
|
echo "[sandbox] aborted" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
else
|
|
echo "[sandbox] nothing to delete at $PERSISTENT_SANDBOX_ROOT" >&2
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
# Derive a per-worktree app name so multiple checkouts don't collide.
|
|
# Each worktree has its own toplevel path even though they share one repo,
|
|
# so we hash that path into a short, stable suffix.
|
|
WORKTREE_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR/..")"
|
|
WORKTREE_ROOT="$(cd "$WORKTREE_ROOT" && pwd)"
|
|
WORKTREE_HASH="$(printf '%s' "$WORKTREE_ROOT" | cksum | cut -d' ' -f1)"
|
|
WORKTREE_NAME="$(basename "$WORKTREE_ROOT")"
|
|
DEFAULT_SANDBOX_NAME="HermesSandbox-${WORKTREE_NAME}-${WORKTREE_HASH}"
|
|
|
|
SANDBOX_NAME="${HERMES_DEV_SANDBOX_NAME:-$DEFAULT_SANDBOX_NAME}"
|
|
|
|
if [ "$PERSISTENT" = true ]; then
|
|
SANDBOX_ROOT="$PERSISTENT_SANDBOX_ROOT"
|
|
else
|
|
SANDBOX_ROOT="$(mktemp -d -t hermes-sandbox.XXXXXX)"
|
|
fi
|
|
|
|
export HERMES_HOME="$SANDBOX_ROOT/hermes-home"
|
|
export HERMES_DESKTOP_USER_DATA_DIR="$SANDBOX_ROOT/user-data"
|
|
export HERMES_DESKTOP_APP_NAME="$SANDBOX_NAME"
|
|
|
|
mkdir -p "$HERMES_HOME" "$HERMES_DESKTOP_USER_DATA_DIR"
|
|
|
|
echo "[sandbox] HERMES_HOME=$HERMES_HOME" >&2
|
|
echo "[sandbox] userData=$HERMES_DESKTOP_USER_DATA_DIR" >&2
|
|
echo "[sandbox] appName=$HERMES_DESKTOP_APP_NAME" >&2
|
|
if [ "$PERSISTENT" = true ]; then
|
|
echo "[sandbox] persistent: $SANDBOX_ROOT" >&2
|
|
else
|
|
echo "[sandbox] ephemeral (will be cleaned up on exit)" >&2
|
|
fi
|
|
|
|
if [ "$PERSISTENT" = false ]; then
|
|
cleanup() {
|
|
chmod -R u+w "$SANDBOX_ROOT"
|
|
rm -rf -- "$SANDBOX_ROOT"
|
|
}
|
|
trap cleanup EXIT
|
|
trap 'cleanup; exit 130' INT TERM
|
|
fi
|
|
|
|
"$@"
|
|
rc=$?
|
|
exit $rc
|