feat: sandboxed claude session launcher scripts
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
346042f1c5
commit
1dea5c697c
3 changed files with 176 additions and 0 deletions
58
scripts/sandbox-claude.sh
Executable file
58
scripts/sandbox-claude.sh
Executable 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 "$@"
|
||||
Loading…
Add table
Add a link
Reference in a new issue