feat: sandboxed claude session launcher scripts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Padreug 2026-06-28 06:48:37 +02:00
commit 1dea5c697c
3 changed files with 176 additions and 0 deletions

58
scripts/sandbox-claude.sh Executable file
View file

@ -0,0 +1,58 @@
#!/usr/bin/env bash
# Launch claude under the sandbox allowlist+deny policy in a target dir.
#
# Usage:
# sandbox-claude.sh # target = parent of script dir
# # (the worktree containing the script)
# sandbox-claude.sh <dir> # target = <dir>
# sandbox-claude.sh <dir> <claude-args>...
# # remaining args pass to claude
#
# Behaviour:
# - cd to <target>
# - copy <script-dir>/sandbox-settings.json -> <target>/.claude/settings.json
# fresh on every launch (idempotent — policy evolves in main and
# propagates on next launch; hand-editing the runtime copy is pointless).
# - exec claude
#
# Safety model (from sandbox-settings.json):
# - defaultMode=acceptEdits — file edits silent
# - allow: narrow Bash set — nix build/check/eval, fmt/lint,
# in-worktree git, basic inspection
# - ask: rm/mv/cp/chmod/chown — prompt every time
# - deny: sudo, *-rebuild switch|test|boot, omni-rebuild, nh, git push,
# git remote, curl/wget/ssh, systemctl, docker/podman, WebFetch,
# WebSearch — hard reject, cannot be overridden
# mid-session
#
# To loosen the policy, edit sandbox-settings.json in the source checkout
# and relaunch — the runtime copy in <target>/.claude/ refreshes from it.
#
# <target> should have `.claude/` in its .gitignore so the runtime copy
# doesn't leak into commits. The script warns if it doesn't.
set -euo pipefail
SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
SETTINGS_SRC="$SCRIPT_DIR/sandbox-settings.json"
TARGET="$SCRIPT_DIR/.."
if [[ $# -gt 0 && -d "$1" ]]; then
TARGET="$1"
shift
fi
TARGET="$(readlink -f "$TARGET")"
[[ -d "$TARGET" ]] || { echo "sandbox-claude: target does not exist: $TARGET" >&2; exit 1; }
[[ -f "$SETTINGS_SRC" ]] || { echo "sandbox-claude: settings file not found: $SETTINGS_SRC" >&2; exit 1; }
cd "$TARGET"
mkdir -p .claude
cp -f "$SETTINGS_SRC" .claude/settings.json
if [[ -f .gitignore ]] && ! grep -qE '(^|/)\.claude/?$' .gitignore; then
echo "sandbox-claude: note — '.claude/' not found in $TARGET/.gitignore;" >&2
echo " the runtime settings.json may leak into commits." >&2
fi
exec claude "$@"