Pass a custom template and mixin kits through to sbx
Sandboxes ignore the host ~/.claude by design: the agent runs as a separate user with HOME elsewhere, so even a read-only mount is not picked up. Skills can be shared with sbx skills import, but plugins carry commands, hooks and MCP servers that only a custom image can deliver. Adds --template, --stock-template and a repeatable --kit, persisted per repository so run and refresh reuse them. AI_SBX_TEMPLATE supplies the default image, so one custom template can be declared once in the user's mise config and apply to every repository, with --template overriding it per repository and --stock-template opting out. save_config now packs two arrays into one argument list separated by a count, so it ships with a round-trip test covering empty arrays, values containing spaces, and the boundary between kits and AWS profiles.
This commit is contained in:
+69
-3
@@ -6,6 +6,7 @@ CONFIG_ROOT="${XDG_CONFIG_HOME:-$HOME/.config}/ai-sbx"
|
||||
DEFAULT_AGENT="${AI_SBX_AGENT:-codex}"
|
||||
DEFAULT_MODE="${AI_SBX_MODE:-clone}"
|
||||
DEFAULT_TOKEN_DAYS="${AI_SBX_TOKEN_DAYS:-30}"
|
||||
DEFAULT_TEMPLATE="${AI_SBX_TEMPLATE:-}"
|
||||
|
||||
# GitHub accepts these as query parameters on the token creation form. A write
|
||||
# level implies read, so only the highest level is listed. "workflows" is
|
||||
@@ -43,6 +44,9 @@ Usage:
|
||||
Setup opens a pre-filled GitHub token form in your browser. Use "token" on
|
||||
its own to replace an expired or revoked token later.
|
||||
|
||||
Set AI_SBX_TEMPLATE in your mise config to reuse one custom image across
|
||||
every repository without repeating --template.
|
||||
|
||||
Setup options:
|
||||
--aws-profile NAME Host AWS profile to expose inside the sandbox.
|
||||
May be supplied more than once. A trailing
|
||||
@@ -54,6 +58,12 @@ Setup options:
|
||||
of the repository, mounted read-only.
|
||||
Its commits reach the host through the
|
||||
sandbox-<name> git remote. This is the default.
|
||||
--template REF Custom sandbox image. Defaults to
|
||||
AI_SBX_TEMPLATE when set.
|
||||
--stock-template Ignore AI_SBX_TEMPLATE and use the agent's
|
||||
stock image.
|
||||
--kit PATH Mixin kit to apply. May be supplied more
|
||||
than once.
|
||||
--replace Replace the existing sandbox.
|
||||
|
||||
Examples:
|
||||
@@ -292,13 +302,22 @@ load_config() {
|
||||
|
||||
declare -p CONFIG_AWS_PROFILES >/dev/null 2>&1 ||
|
||||
CONFIG_AWS_PROFILES=()
|
||||
|
||||
declare -p CONFIG_KITS >/dev/null 2>&1 ||
|
||||
CONFIG_KITS=()
|
||||
|
||||
CONFIG_TEMPLATE="${CONFIG_TEMPLATE:-}"
|
||||
}
|
||||
|
||||
save_config() {
|
||||
local agent="$1"
|
||||
local mode="$2"
|
||||
shift 2
|
||||
local -a profiles=("$@")
|
||||
local template="$3"
|
||||
local kit_count="$4"
|
||||
shift 4
|
||||
|
||||
local -a kits=("${@:1:kit_count}")
|
||||
local -a profiles=("${@:kit_count + 1}")
|
||||
|
||||
mkdir -p "$REPO_CONFIG_DIR"
|
||||
chmod 700 "$CONFIG_ROOT" "$CONFIG_ROOT/repos" "$REPO_CONFIG_DIR" 2>/dev/null || true
|
||||
@@ -308,6 +327,14 @@ save_config() {
|
||||
printf 'CONFIG_SANDBOX=%q\n' "$SANDBOX_NAME"
|
||||
printf 'CONFIG_AGENT=%q\n' "$agent"
|
||||
printf 'CONFIG_MODE=%q\n' "$mode"
|
||||
printf 'CONFIG_TEMPLATE=%q\n' "$template"
|
||||
|
||||
printf 'CONFIG_KITS=('
|
||||
local kit
|
||||
for kit in ${kits[@]+"${kits[@]}"}; do
|
||||
printf ' %q' "$kit"
|
||||
done
|
||||
printf ' )\n'
|
||||
|
||||
printf 'CONFIG_AWS_PROFILES=('
|
||||
local profile
|
||||
@@ -517,6 +544,15 @@ create_sandbox() {
|
||||
create_args+=(--clone)
|
||||
fi
|
||||
|
||||
if [[ -n "$CONFIG_TEMPLATE" ]]; then
|
||||
create_args+=(--template "$CONFIG_TEMPLATE")
|
||||
fi
|
||||
|
||||
local kit
|
||||
for kit in ${CONFIG_KITS[@]+"${CONFIG_KITS[@]}"}; do
|
||||
create_args+=(--kit "$kit")
|
||||
done
|
||||
|
||||
create_args+=(
|
||||
"$CONFIG_AGENT"
|
||||
"$REPO_ROOT"
|
||||
@@ -528,8 +564,10 @@ create_sandbox() {
|
||||
setup_command() {
|
||||
local agent="$DEFAULT_AGENT"
|
||||
local mode="$DEFAULT_MODE"
|
||||
local template="$DEFAULT_TEMPLATE"
|
||||
local replace=false
|
||||
local -a aws_profiles=()
|
||||
local -a kits=()
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
@@ -551,6 +589,20 @@ setup_command() {
|
||||
mode="direct"
|
||||
shift
|
||||
;;
|
||||
--template)
|
||||
(($# >= 2)) || die "--template requires a value"
|
||||
template="$2"
|
||||
shift 2
|
||||
;;
|
||||
--stock-template)
|
||||
template=""
|
||||
shift
|
||||
;;
|
||||
--kit)
|
||||
(($# >= 2)) || die "--kit requires a value"
|
||||
kits+=("$2")
|
||||
shift 2
|
||||
;;
|
||||
--replace)
|
||||
replace=true
|
||||
shift
|
||||
@@ -572,7 +624,14 @@ setup_command() {
|
||||
validate_aws_profile "$profile"
|
||||
done
|
||||
|
||||
save_config "$agent" "$mode" "${aws_profiles[@]}"
|
||||
local kit
|
||||
for kit in ${kits[@]+"${kits[@]}"}; do
|
||||
[[ -e "$kit" ]] ||
|
||||
die "Kit does not exist: $kit"
|
||||
done
|
||||
|
||||
save_config "$agent" "$mode" "$template" "${#kits[@]}" \
|
||||
${kits[@]+"${kits[@]}"} ${aws_profiles[@]+"${aws_profiles[@]}"}
|
||||
|
||||
if sandbox_exists; then
|
||||
if [[ "$replace" == true ]]; then
|
||||
@@ -656,6 +715,13 @@ status_command() {
|
||||
printf 'Agent: %s\n' "$CONFIG_AGENT"
|
||||
printf 'Mode: %s\n' "$CONFIG_MODE"
|
||||
|
||||
printf 'Template: %s\n' "${CONFIG_TEMPLATE:-stock}"
|
||||
|
||||
if ((${#CONFIG_KITS[@]})); then
|
||||
printf 'Kits:\n'
|
||||
printf ' %s\n' "${CONFIG_KITS[@]}"
|
||||
fi
|
||||
|
||||
printf 'Token days: %s\n' "$DEFAULT_TOKEN_DAYS"
|
||||
|
||||
printf 'AWS profiles (host -> sandbox):\n'
|
||||
|
||||
Reference in New Issue
Block a user