Install plugin runtimes into the sandbox

Claude plugins bring their own runtime requirements. claude-mem and others run
their hooks under bun, which the sandbox image does not carry, so installing
plugins left every prompt in the sandbox failing with a Bun not found hook
error - after setup had reported success, since the dependency only surfaces
when a hook fires.

AI_SBX_TOOLS lists mise tools to install globally in the sandbox and defaults
to bun. mise is already present and resolves these from GitHub releases, which
the default network policy allows. Setting the variable to an empty string
installs nothing.
This commit is contained in:
2026-07-31 09:12:00 -05:00
parent 6f4ba117b4
commit c195a82b82
2 changed files with 49 additions and 0 deletions
+32
View File
@@ -7,6 +7,7 @@ DEFAULT_AGENT="${AI_SBX_AGENT:-claude}"
DEFAULT_MODE="${AI_SBX_MODE:-clone}"
DEFAULT_TOKEN_DAYS="${AI_SBX_TOKEN_DAYS:-30}"
DEFAULT_TEMPLATE="${AI_SBX_TEMPLATE:-}"
DEFAULT_TOOLS="${AI_SBX_TOOLS:-bun}"
CLAUDE_HOME="${CLAUDE_HOME:-$HOME/.claude}"
# Only these leave the host. ~/.claude also holds OAuth credentials, shell
@@ -71,6 +72,10 @@ AGENTS.md, agents, commands, hooks, skills) into the sandbox and installs the
marketplaces and plugins your host has enabled. Credentials, transcripts and
history are never copied. Use "config" to re-apply after the host changes.
AI_SBX_TOOLS lists mise tools installed globally in the sandbox, defaulting
to bun because several Claude plugins run their hooks under it. Set it to an
empty string to install none.
Setup and run install mise in the sandbox and resolve the repository's
pinned tools, so the agent runs the same versions you do. A personal
mise config that must stay out of the repository goes in the per-repository
@@ -727,6 +732,31 @@ install_sandbox_claude_plugins() {
done < <(host_enabled_plugins "$settings")
}
# Plugins bring their own runtime requirements - claude-mem and others run
# their hooks under bun, which the sandbox image does not carry - and a missing
# one surfaces as a hook error on every prompt rather than at install time.
install_sandbox_tools() {
local sandbox_home="$1"
[[ -n "$DEFAULT_TOOLS" ]] || return 0
local -a tools
read -r -a tools <<<"$DEFAULT_TOOLS"
((${#tools[@]})) || return 0
printf 'Installing sandbox tools: %s\n' "${tools[*]}"
# mise resolves these from GitHub releases, which the default network
# policy already allows. $HOME and $@ belong to the sandbox shell.
# shellcheck disable=SC2016
sbx exec "$SANDBOX_NAME" bash -lc '
export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"
mise use -g "$@" && mise reshim
' _ "${tools[@]}" </dev/null >/dev/null 2>&1 ||
printf 'Could not install sandbox tools: %s\n' "${tools[*]}" >&2
}
install_sandbox_mise() {
local sandbox_home
# shellcheck disable=SC2016
@@ -753,6 +783,8 @@ install_sandbox_mise() {
sbx cp "$host_mise" "$SANDBOX_NAME:$sandbox_home/.local/bin/mise"
fi
install_sandbox_tools "$sandbox_home"
local personal="$REPO_CONFIG_DIR/mise.local.toml"
if [[ -f "$personal" ]]; then
sbx cp "$personal" "$SANDBOX_NAME:$REPO_ROOT/mise.local.toml"