189 lines
5.4 KiB
Bash
189 lines
5.4 KiB
Bash
# Parse claudebox flags
|
|
SKIP_AUDIT=false
|
|
DRY_RUN=false
|
|
CHECK_MODE=false
|
|
SHELL_MODE=false
|
|
CLAUDE_ARGS=()
|
|
|
|
while (( $# > 0 )); do
|
|
case "$1" in
|
|
--yes|-y) SKIP_AUDIT=true ;;
|
|
--dry-run) DRY_RUN=true ;;
|
|
--check) CHECK_MODE=true ;;
|
|
--shell) SHELL_MODE=true ;;
|
|
--) shift; CLAUDE_ARGS+=("$@"); break ;;
|
|
*) CLAUDE_ARGS+=("$1") ;;
|
|
esac
|
|
shift
|
|
done
|
|
export SKIP_AUDIT # consumed by Plan 02 audit display
|
|
|
|
# --check: verify prerequisites and exit (D-10, UX-05)
|
|
if [[ "$CHECK_MODE" == true ]]; then
|
|
pass=true
|
|
green=$'\033[32m' red=$'\033[31m' yellow=$'\033[33m' reset=$'\033[0m'
|
|
|
|
check_cmd() {
|
|
if command -v "$1" &>/dev/null; then
|
|
echo "${green}OK${reset} $1" >&2
|
|
else
|
|
echo "${red}FAIL${reset} $1 -- not found" >&2
|
|
pass=false
|
|
fi
|
|
}
|
|
|
|
echo "claudebox prerequisites:" >&2
|
|
echo "" >&2
|
|
check_cmd bwrap
|
|
check_cmd claude
|
|
check_cmd git
|
|
check_cmd curl
|
|
check_cmd nix
|
|
|
|
if [[ -d "$HOME/.claudebox" ]]; then
|
|
echo "${green}OK${reset} ~/.claudebox exists" >&2
|
|
else
|
|
echo "${red}FAIL${reset} ~/.claudebox -- not found (will be created on first run)" >&2
|
|
fi
|
|
|
|
if [[ -v ANTHROPIC_API_KEY ]]; then
|
|
echo "${green}OK${reset} ANTHROPIC_API_KEY is set" >&2
|
|
else
|
|
echo "${yellow}WARN${reset} ANTHROPIC_API_KEY is not set" >&2
|
|
fi
|
|
|
|
echo "" >&2
|
|
if [[ "$pass" == true ]]; then
|
|
echo "${green}All checks passed.${reset}" >&2
|
|
exit 0
|
|
else
|
|
echo "${red}Some checks failed.${reset}" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# SANDBOX_PATH is injected by flake.nix via makeBinPath (only runtimeInputs, no host PATH)
|
|
# Resolve binary paths from runtimeInputs
|
|
SANDBOX_BASH="$(command -v bash)"
|
|
CLAUDE_BIN="$(command -v claude)"
|
|
|
|
# Record CWD
|
|
CWD=$(pwd)
|
|
|
|
# Ensure ~/.claudebox exists
|
|
mkdir -p "$HOME/.claudebox"
|
|
|
|
# Generate minimal .gitconfig (D-05)
|
|
GIT_NAME=$(git config --global user.name 2>/dev/null || echo "Claude User")
|
|
GIT_EMAIL=$(git config --global user.email 2>/dev/null || echo "claude@localhost")
|
|
|
|
GITCONFIG_TMP=$(mktemp)
|
|
trap 'rm -f "$GITCONFIG_TMP"' EXIT
|
|
|
|
cat > "$GITCONFIG_TMP" <<GITEOF
|
|
[user]
|
|
name = $GIT_NAME
|
|
email = $GIT_EMAIL
|
|
[safe]
|
|
directory = *
|
|
GITEOF
|
|
|
|
# Build environment --setenv args array (D-03, D-04, SAND-02, SAND-03)
|
|
# Sandbox-generated vars -- set directly, never from host
|
|
ENV_ARGS=(
|
|
--setenv HOME "$HOME"
|
|
--setenv USER "$USER"
|
|
--setenv PATH "$SANDBOX_PATH"
|
|
--setenv SHELL "$SANDBOX_BASH"
|
|
--setenv TMPDIR /tmp
|
|
--setenv XDG_RUNTIME_DIR /tmp
|
|
--setenv NIX_SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt
|
|
--setenv SSL_CERT_FILE /etc/ssl/certs/ca-certificates.crt
|
|
)
|
|
|
|
# Allowlisted host vars -- only pass if set on host
|
|
HOST_ALLOWLIST=(TERM EDITOR LANG LC_ALL ANTHROPIC_API_KEY)
|
|
for var in "${HOST_ALLOWLIST[@]}"; do
|
|
if [[ -v "$var" ]]; then
|
|
ENV_ARGS+=(--setenv "$var" "${!var}")
|
|
fi
|
|
done
|
|
|
|
# CLAUDEBOX_EXTRA_ENV escape hatch (D-03, comma-separated)
|
|
if [[ -v CLAUDEBOX_EXTRA_ENV ]]; then
|
|
IFS=',' read -ra EXTRAS <<< "$CLAUDEBOX_EXTRA_ENV"
|
|
for var in "${EXTRAS[@]}"; do
|
|
var="${var// /}" # trim whitespace
|
|
if [[ -n "$var" ]] && [[ -v "$var" ]]; then
|
|
ENV_ARGS+=(--setenv "$var" "${!var}")
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Build sandbox command
|
|
if [[ "$SHELL_MODE" == true ]]; then
|
|
SANDBOX_CMD=("$SANDBOX_BASH" "${CLAUDE_ARGS[@]}")
|
|
else
|
|
SANDBOX_CMD=("$CLAUDE_BIN" --dangerously-skip-permissions "${CLAUDE_ARGS[@]}")
|
|
fi
|
|
|
|
# --dry-run: print the bwrap command without executing (D-09, UX-04)
|
|
if [[ "$DRY_RUN" == true ]]; then
|
|
{
|
|
echo "bwrap \\"
|
|
echo " --clearenv \\"
|
|
dry_run_i=0
|
|
while (( dry_run_i < ${#ENV_ARGS[@]} )); do
|
|
printf ' %s %s %q \\\n' "${ENV_ARGS[$dry_run_i]}" "${ENV_ARGS[$((dry_run_i+1))]}" "${ENV_ARGS[$((dry_run_i+2))]}"
|
|
(( dry_run_i += 3 ))
|
|
done
|
|
echo " --tmpfs / \\"
|
|
echo " --proc /proc \\"
|
|
echo " --dev /dev \\"
|
|
echo " --tmpfs /tmp \\"
|
|
echo " --ro-bind /nix/store /nix/store \\"
|
|
echo " --bind /nix/var/nix /nix/var/nix \\"
|
|
echo " --ro-bind /etc/resolv.conf /etc/resolv.conf \\"
|
|
echo " --ro-bind /etc/ssl /etc/ssl \\"
|
|
echo " --ro-bind /etc/static /etc/static \\"
|
|
echo " --ro-bind /etc/passwd /etc/passwd \\"
|
|
echo " --ro-bind /etc/group /etc/group \\"
|
|
echo " --ro-bind /etc/hosts /etc/hosts \\"
|
|
echo " --ro-bind /etc/nsswitch.conf /etc/nsswitch.conf \\"
|
|
echo " --ro-bind /etc/nix /etc/nix \\"
|
|
printf ' --symlink %q /usr/bin/env \\\n' "$(readlink -f "$(command -v env)")"
|
|
echo " --tmpfs $HOME \\"
|
|
echo " --bind $HOME/.claudebox $HOME/.claude \\"
|
|
printf ' --ro-bind %q %s/.gitconfig \\\n' "$GITCONFIG_TMP" "$HOME"
|
|
echo " --bind $CWD $CWD \\"
|
|
echo " --chdir $CWD \\"
|
|
printf ' -- %s\n' "${SANDBOX_CMD[*]}"
|
|
} >&2
|
|
exit 0
|
|
fi
|
|
|
|
# exec bwrap (SAND-04 through SAND-15, UX-06, D-01)
|
|
exec bwrap \
|
|
--clearenv \
|
|
"${ENV_ARGS[@]}" \
|
|
--tmpfs / \
|
|
--proc /proc \
|
|
--dev /dev \
|
|
--tmpfs /tmp \
|
|
--ro-bind /nix/store /nix/store \
|
|
--bind /nix/var/nix /nix/var/nix \
|
|
--ro-bind /etc/resolv.conf /etc/resolv.conf \
|
|
--ro-bind /etc/ssl /etc/ssl \
|
|
--ro-bind /etc/static /etc/static \
|
|
--ro-bind /etc/passwd /etc/passwd \
|
|
--ro-bind /etc/group /etc/group \
|
|
--ro-bind /etc/hosts /etc/hosts \
|
|
--ro-bind /etc/nsswitch.conf /etc/nsswitch.conf \
|
|
--ro-bind /etc/nix /etc/nix \
|
|
--symlink "$(readlink -f "$(command -v env)")" /usr/bin/env \
|
|
--tmpfs "$HOME" \
|
|
--bind "$HOME/.claudebox" "$HOME/.claude" \
|
|
--ro-bind "$GITCONFIG_TMP" "$HOME/.gitconfig" \
|
|
--bind "$CWD" "$CWD" \
|
|
--chdir "$CWD" \
|
|
-- "${SANDBOX_CMD[@]}"
|