Files
coredesktop/sandbox/setup.sh
T
davidandClaude Opus 5.5 475b1d804e Restart Hermes' gateway after updating Hermes
The gateway reads its sandbox rules and loads new dependencies only when it
starts, and hermes update restarts it only for new code. Restart it at the end
of the sandbox update step instead of before hermes update runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 10:01:37 -06:00

78 lines
3.1 KiB
Bash

#!/bin/bash
#
# Purpose : Set up sandboxed AI agents (see sandbox/agent): install or update
# Anthropic's sandbox runtime (srt) and Hermes Agent, and turn on
# Claude Code's built-in sandbox. Run by install.sh and on every
# update (updates.d/72-sandbox.sh).
COREDESKTOP="$HOME/.local/share/coredesktop"
STATUS=0
# npm's global prefix is under /usr, so install to ~/.local; srt lands in ~/.local/bin
echo "Installing the sandbox runtime (srt)..."
npm install --global --prefix "$HOME/.local" --no-fund --no-audit @anthropic-ai/sandbox-runtime || STATUS=1
# --non-interactive skips Hermes' setup questions and its background gateway
# service; `configure hermes` chooses a model provider afterwards
if [ ! -x "$HOME/.local/bin/hermes" ]; then
echo "Installing Hermes Agent..."
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash -s -- --non-interactive || STATUS=1
fi
# Claude Code runs every command it starts in its own sandbox, also built on
# bubblewrap and socat; it can't run inside srt because bubblewrap can't be
# nested. Anything already in the sandbox section of your settings wins over
# these defaults.
CLAUDE_SETTINGS="$HOME/.claude/settings.json"
if [ -f "$CLAUDE_SETTINGS" ]; then
domains="$(jq '.network.allowedDomains' "$COREDESKTOP/sandbox/config/base.json")"
tmp="$(mktemp "$CLAUDE_SETTINGS.XXXXXX")"
if jq --argjson domains "$domains" \
'.sandbox = ({enabled: true, network: {allowedDomains: $domains}} * (.sandbox // {}))' \
"$CLAUDE_SETTINGS" > "$tmp"; then
if cmp -s "$tmp" "$CLAUDE_SETTINGS"; then
rm -f "$tmp"
else
echo "Turning on Claude Code's sandbox..."
mv -f "$tmp" "$CLAUDE_SETTINGS"
fi
else
echo "Couldn't read $CLAUDE_SETTINGS; Claude Code's sandbox was not turned on."
rm -f "$tmp"
STATUS=1
fi
fi
# Hermes' gateway acts on messages from outside this machine, so it runs in
# the sandbox too: a systemd drop-in starts it through sandbox/bin/hermes. It
# also needs to reach the Matrix server in Hermes' settings, which differs on
# each machine; for other messaging services, add their domains to
# ~/.config/coredesktop/sandbox/hermes.json.
GATEWAY_UNIT="$HOME/.config/systemd/user/hermes-gateway.service"
if [ -f "$GATEWAY_UNIT" ]; then
if [ -x "$HOME/.local/bin/srt" ]; then
homeserver="$(sed -nE "s#^MATRIX_HOMESERVER=[\"']?https?://([^/:\"']+).*#\1#p" "$HOME/.hermes/.env" 2> /dev/null | head -n 1)"
dropin="$GATEWAY_UNIT.d/coredesktop-sandbox.conf"
tmp="$(mktemp)"
cat > "$tmp" << EOF
# Written by CoreDesktop (sandbox/setup.sh): run Hermes' gateway in the sandbox
[Service]
Environment="COREDESKTOP_SANDBOX_DOMAINS=$homeserver"
ExecStart=
ExecStart=%h/.local/share/coredesktop/sandbox/bin/hermes gateway run
EOF
if cmp -s "$tmp" "$dropin"; then
rm -f "$tmp"
else
echo "Running Hermes' gateway in the sandbox..."
mkdir -p "$(dirname "$dropin")" && mv -f "$tmp" "$dropin" && chmod 644 "$dropin" \
&& systemctl --user daemon-reload || STATUS=1
fi
else
echo "Hermes' gateway isn't sandboxed yet: the sandbox (srt) isn't installed."
STATUS=1
fi
fi
exit $STATUS