Install Claude configuration, plugins and mise into sandboxes
Custom templates are the documented way to carry user-level configuration into a sandbox, but sbx v0.37.x silently drops every layer stacked on the base image (docker/sbx-releases#366), so nothing baked into an image arrives. This installs the same material into a stock sandbox after creation instead. setup copies an allowlist of ~/.claude into the sandbox, imports skills into the shared store, and adds each known marketplace before installing every enabled plugin. Enablement survives here precisely because it happens after creation: claude plugin install writes enabledPlugins itself, whereas sbx recreates settings.json when the sandbox is created. Tools come from mise, copied from the host because mise.jdx.dev is outside the default network policy. Tools resolve through shims rather than mise activate, which only fires for interactive shells and would leave the agent silently using system versions. sbx exec drains stdin, which truncated both install loops to their first entry, and tab is an IFS whitespace character, which collapsed the empty repo field and shifted the URL into it for git-sourced marketplaces. Both are handled.
This commit is contained in:
@@ -244,10 +244,11 @@ provider "aws" {
|
|||||||
|
|
||||||
| Command | Effect |
|
| Command | Effect |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| `setup [options]` | Configure the repository, create the sandbox, open the token form, install AWS profiles |
|
| `setup [options]` | Configure the repository, create the sandbox, open the token form, install AWS profiles, Claude configuration and plugins, and mise |
|
||||||
| `token` | Replace the GitHub token for this repository — expiry, revocation, permission change |
|
| `token` | Replace the GitHub token for this repository — expiry, revocation, permission change |
|
||||||
| `run [-- args...]` | Refresh AWS credentials and attach to the agent |
|
| `run [-- args...]` | Refresh AWS credentials and the repository's mise tools, then attach to the agent |
|
||||||
| `refresh` | Same, without attaching |
|
| `refresh` | Refresh AWS credentials, without attaching |
|
||||||
|
| `config` | Re-apply your Claude configuration and plugins after the host changes, without recreating the sandbox |
|
||||||
| `status` | Show repository, sandbox, agent, mode, token expiry setting, profile mapping, stored secrets |
|
| `status` | Show repository, sandbox, agent, mode, token expiry setting, profile mapping, stored secrets |
|
||||||
| `remove` | Remove the sandbox and this repository's local configuration |
|
| `remove` | Remove the sandbox and this repository's local configuration |
|
||||||
|
|
||||||
@@ -296,10 +297,27 @@ under `~/.claude/plugins/` are **not** scanned — only the top-level skills dir
|
|||||||
mise run ai:sbx -- setup --kit ~/kits/my-kit
|
mise run ai:sbx -- setup --kit ~/kits/my-kit
|
||||||
```
|
```
|
||||||
|
|
||||||
**Templates — for anything else, including plugins:**
|
**`setup` — configuration and plugins, no image required:**
|
||||||
|
|
||||||
Plugins carry commands, hooks, agents, and MCP servers, none of which `skills import`
|
For the `claude` agent, `setup` copies `CLAUDE.md`, `AGENTS.md`, `agents`, `commands`
|
||||||
or a kit will move. A custom image is the only mechanism that does.
|
and `hooks` from `~/.claude` into the sandbox, runs `sbx skills import`, then adds
|
||||||
|
every marketplace in `~/.claude/plugins/known_marketplaces.json` and installs every
|
||||||
|
plugin your host has enabled. `config` re-applies all of it without recreating the
|
||||||
|
sandbox.
|
||||||
|
|
||||||
|
The copy is an allowlist. Credentials, conversation transcripts, `history.jsonl` and
|
||||||
|
shell snapshots are never copied, and anything added to `~/.claude` later stays on the
|
||||||
|
host until the allowlist names it.
|
||||||
|
|
||||||
|
A marketplace on a host other than `github.com` gets a matching network policy rule,
|
||||||
|
scoped to that sandbox — the default policy denies it otherwise.
|
||||||
|
|
||||||
|
Plugin *enablement* survives here because `claude plugin install` writes
|
||||||
|
`enabledPlugins` itself, after the sandbox has been created. Baking plugins into an
|
||||||
|
image does not survive: sbx recreates `~/.claude/settings.json` at creation, which
|
||||||
|
drops enablement while leaving the plugin files in place.
|
||||||
|
|
||||||
|
**Templates — for toolchains and anything else the base image lacks:**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
export AI_SBX_TEMPLATE=ghcr.io/you/claude-sbx:v1
|
export AI_SBX_TEMPLATE=ghcr.io/you/claude-sbx:v1
|
||||||
@@ -314,9 +332,34 @@ Two constraints worth knowing before building one:
|
|||||||
- The sandbox's Docker daemon pulls templates **from a registry** and does not share
|
- The sandbox's Docker daemon pulls templates **from a registry** and does not share
|
||||||
your host image store, so the image must be pushed somewhere reachable. Docker Hub
|
your host image store, so the image must be pushed somewhere reachable. Docker Hub
|
||||||
reuses your `sbx login`; for other registries use `sbx secret set --registry`.
|
reuses your `sbx login`; for other registries use `sbx secret set --registry`.
|
||||||
- Claude overwrites `~/.claude/settings.json` at startup, so plugin *enablement*
|
- **sbx v0.37.0 and v0.37.1 cannot consume custom templates.** Every layer stacked on
|
||||||
baked into the image may not survive. Bake the plugin files in, and pass
|
the base image is silently dropped: the sandbox boots with base content only and
|
||||||
`--settings` to the agent if enablement is lost.
|
`sbx create` still exits 0. This is upstream
|
||||||
|
[#366](https://github.com/docker/sbx-releases/issues/366) — the erofs snapshotter
|
||||||
|
stopped building the merged `fsmeta`. v0.35.0 is unaffected. Until it is fixed, a
|
||||||
|
template is an expensive no-op and `setup` is the mechanism that works.
|
||||||
|
|
||||||
|
## Repository toolchains
|
||||||
|
|
||||||
|
`setup` and `run` install mise in the sandbox and resolve the repository's pinned
|
||||||
|
tools, so the agent runs the versions the project specifies rather than whatever the
|
||||||
|
base image ships.
|
||||||
|
|
||||||
|
The mise binary is copied from the host: `mise.jdx.dev` is outside the default network
|
||||||
|
policy, so the network installer fails at the tarball step. Tools resolve through
|
||||||
|
**shims** rather than `mise activate` — the agent runs non-interactive shells, which
|
||||||
|
never fire the activation hook and would otherwise silently get system versions.
|
||||||
|
|
||||||
|
A personal mise config that must stay out of the repository goes in the repository's
|
||||||
|
config directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$XDG_CONFIG_HOME/ai-sbx/repos/<digest>/mise.local.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
It is copied to the workspace root on every run. This matters under `--clone`, where
|
||||||
|
the agent gets a fresh git clone and an untracked `mise.local.toml` on the host would
|
||||||
|
not reach it. Repositories with no mise configuration are left alone.
|
||||||
|
|
||||||
## AWS profile naming
|
## AWS profile naming
|
||||||
|
|
||||||
|
|||||||
+284
@@ -7,6 +7,21 @@ DEFAULT_AGENT="${AI_SBX_AGENT:-codex}"
|
|||||||
DEFAULT_MODE="${AI_SBX_MODE:-clone}"
|
DEFAULT_MODE="${AI_SBX_MODE:-clone}"
|
||||||
DEFAULT_TOKEN_DAYS="${AI_SBX_TOKEN_DAYS:-30}"
|
DEFAULT_TOKEN_DAYS="${AI_SBX_TOKEN_DAYS:-30}"
|
||||||
DEFAULT_TEMPLATE="${AI_SBX_TEMPLATE:-}"
|
DEFAULT_TEMPLATE="${AI_SBX_TEMPLATE:-}"
|
||||||
|
CLAUDE_HOME="${CLAUDE_HOME:-$HOME/.claude}"
|
||||||
|
|
||||||
|
# Only these leave the host. ~/.claude also holds OAuth credentials, shell
|
||||||
|
# snapshots and conversation transcripts, so this is an allowlist rather than
|
||||||
|
# a list of exclusions: anything added to ~/.claude later stays put by default.
|
||||||
|
#
|
||||||
|
# skills is absent deliberately: sbx mounts its own shared skills store over
|
||||||
|
# that path, so it is seeded with "sbx skills import" instead of copied.
|
||||||
|
CLAUDE_CONFIG_ALLOW=(
|
||||||
|
CLAUDE.md
|
||||||
|
AGENTS.md
|
||||||
|
agents
|
||||||
|
commands
|
||||||
|
hooks
|
||||||
|
)
|
||||||
|
|
||||||
# GitHub accepts these as query parameters on the token creation form. A write
|
# 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
|
# level implies read, so only the highest level is listed. "workflows" is
|
||||||
@@ -37,6 +52,7 @@ Usage:
|
|||||||
mise run ai:sbx -- setup [options]
|
mise run ai:sbx -- setup [options]
|
||||||
mise run ai:sbx -- token
|
mise run ai:sbx -- token
|
||||||
mise run ai:sbx -- refresh
|
mise run ai:sbx -- refresh
|
||||||
|
mise run ai:sbx -- config
|
||||||
mise run ai:sbx -- run [-- agent arguments...]
|
mise run ai:sbx -- run [-- agent arguments...]
|
||||||
mise run ai:sbx -- status
|
mise run ai:sbx -- status
|
||||||
mise run ai:sbx -- remove
|
mise run ai:sbx -- remove
|
||||||
@@ -47,6 +63,17 @@ its own to replace an expired or revoked token later.
|
|||||||
Set AI_SBX_TEMPLATE in your mise config to reuse one custom image across
|
Set AI_SBX_TEMPLATE in your mise config to reuse one custom image across
|
||||||
every repository without repeating --template.
|
every repository without repeating --template.
|
||||||
|
|
||||||
|
For the claude agent, setup copies your user-level configuration (CLAUDE.md,
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
config directory as mise.local.toml; it is copied to the workspace root on
|
||||||
|
every run. Repositories without any mise configuration are left alone.
|
||||||
|
|
||||||
Setup options:
|
Setup options:
|
||||||
--aws-profile NAME Host AWS profile to expose inside the sandbox.
|
--aws-profile NAME Host AWS profile to expose inside the sandbox.
|
||||||
May be supplied more than once. A trailing
|
May be supplied more than once. A trailing
|
||||||
@@ -530,6 +557,240 @@ EOF
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
marketplace_url() {
|
||||||
|
local source_kind="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local url="$3"
|
||||||
|
|
||||||
|
case "$source_kind" in
|
||||||
|
github)
|
||||||
|
[[ -n "$repo" ]] || return 1
|
||||||
|
printf 'https://github.com/%s.git' "$repo"
|
||||||
|
;;
|
||||||
|
git)
|
||||||
|
[[ -n "$url" ]] || return 1
|
||||||
|
printf '%s' "$url"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# sbx cp places a source directory *inside* an existing destination directory,
|
||||||
|
# so a repeat copy would nest hooks/hooks. Clearing the target first keeps this
|
||||||
|
# idempotent.
|
||||||
|
copy_claude_config_item() {
|
||||||
|
local item="$1"
|
||||||
|
local sandbox_home="$2"
|
||||||
|
local target="$sandbox_home/.claude/$item"
|
||||||
|
|
||||||
|
# sbx mounts parts of ~/.claude from its own stores. Those paths belong to
|
||||||
|
# sbx, and removing one fails with EBUSY partway through the copy.
|
||||||
|
if sbx exec "$SANDBOX_NAME" \
|
||||||
|
bash -c "mountpoint -q $(printf '%q' "$target")" 2>/dev/null; then
|
||||||
|
|
||||||
|
printf 'Skipping %s: managed by sbx inside the sandbox.\n' "$item" >&2
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
sbx exec "$SANDBOX_NAME" \
|
||||||
|
bash -c "rm -rf $(printf '%q' "$target")"
|
||||||
|
|
||||||
|
sbx cp "$CLAUDE_HOME/$item" "$SANDBOX_NAME:$sandbox_home/.claude/"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_sandbox_claude_config() {
|
||||||
|
if [[ "$CONFIG_AGENT" != claude ]]; then
|
||||||
|
printf 'Agent is %s, not claude; skipping Claude configuration.\n' \
|
||||||
|
"$CONFIG_AGENT"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$CLAUDE_HOME" ]]; then
|
||||||
|
printf 'No %s on the host; skipping Claude configuration.\n' \
|
||||||
|
"$CLAUDE_HOME" >&2
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
require_command jq
|
||||||
|
|
||||||
|
local sandbox_home
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
sandbox_home="$(sbx exec "$SANDBOX_NAME" bash -c 'printf %s "$HOME"')"
|
||||||
|
|
||||||
|
[[ -n "$sandbox_home" ]] ||
|
||||||
|
die "Could not determine the sandbox home directory."
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
sbx exec "$SANDBOX_NAME" bash -c 'mkdir -p "$HOME/.claude"'
|
||||||
|
|
||||||
|
local item
|
||||||
|
for item in "${CLAUDE_CONFIG_ALLOW[@]}"; do
|
||||||
|
[[ -e "$CLAUDE_HOME/$item" ]] || continue
|
||||||
|
copy_claude_config_item "$item" "$sandbox_home"
|
||||||
|
printf 'Copied %s into %s.\n' "$item" "$SANDBOX_NAME"
|
||||||
|
done
|
||||||
|
|
||||||
|
# The store is shared by every sandbox, so this seeds all of them at once.
|
||||||
|
if [[ -d "$CLAUDE_HOME/skills" ]]; then
|
||||||
|
sbx skills import >/dev/null 2>&1 ||
|
||||||
|
printf 'Could not import skills into the shared store.\n' >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
install_sandbox_claude_plugins
|
||||||
|
}
|
||||||
|
|
||||||
|
install_sandbox_claude_plugins() {
|
||||||
|
local known="$CLAUDE_HOME/plugins/known_marketplaces.json"
|
||||||
|
local settings="$CLAUDE_HOME/settings.json"
|
||||||
|
|
||||||
|
if [[ ! -f "$known" || ! -f "$settings" ]]; then
|
||||||
|
printf 'No plugin manifest on the host; skipping plugin install.\n' >&2
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A fresh sandbox knows no marketplaces at all, including the official one
|
||||||
|
# the host acquires on first run, so every marketplace is added explicitly.
|
||||||
|
# Not @tsv: tab is an IFS whitespace character, so read collapses the empty
|
||||||
|
# field an entry without a repo produces and shifts the URL into it.
|
||||||
|
local name source_kind repo url
|
||||||
|
while IFS='|' read -r name source_kind repo url; do
|
||||||
|
[[ -n "$name" ]] || continue
|
||||||
|
|
||||||
|
local marketplace
|
||||||
|
if ! marketplace="$(marketplace_url "$source_kind" "$repo" "$url")"; then
|
||||||
|
printf 'Skipping marketplace %s: unsupported source %s\n' \
|
||||||
|
"$name" "$source_kind" >&2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only github.com is reachable under the default network policy.
|
||||||
|
local host
|
||||||
|
host="${marketplace#https://}"
|
||||||
|
host="${host%%/*}"
|
||||||
|
|
||||||
|
if [[ "$host" != "github.com" ]]; then
|
||||||
|
sbx policy allow network \
|
||||||
|
--sandbox "$SANDBOX_NAME" "$host" \
|
||||||
|
</dev/null >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Without </dev/null sbx exec drains the loop's input and only the
|
||||||
|
# first marketplace is ever processed.
|
||||||
|
sbx exec "$SANDBOX_NAME" \
|
||||||
|
claude plugin marketplace add "$marketplace" \
|
||||||
|
</dev/null >/dev/null 2>&1 ||
|
||||||
|
printf 'Could not add marketplace %s (%s).\n' \
|
||||||
|
"$name" "$marketplace" >&2
|
||||||
|
done < <(
|
||||||
|
jq -r '
|
||||||
|
to_entries[]
|
||||||
|
| [
|
||||||
|
.key,
|
||||||
|
(.value.source.source // ""),
|
||||||
|
(.value.source.repo // ""),
|
||||||
|
(.value.source.url // "")
|
||||||
|
]
|
||||||
|
| join("|")
|
||||||
|
' "$known"
|
||||||
|
)
|
||||||
|
|
||||||
|
local plugin
|
||||||
|
while read -r plugin; do
|
||||||
|
[[ -n "$plugin" ]] || continue
|
||||||
|
|
||||||
|
if sbx exec "$SANDBOX_NAME" \
|
||||||
|
claude plugin install "$plugin" </dev/null >/dev/null 2>&1; then
|
||||||
|
printf 'Installed plugin %s\n' "$plugin"
|
||||||
|
else
|
||||||
|
printf 'Could not install plugin %s\n' "$plugin" >&2
|
||||||
|
fi
|
||||||
|
done < <(
|
||||||
|
jq -r '(.enabledPlugins // {}) | to_entries[] | select(.value) | .key' \
|
||||||
|
"$settings"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
install_sandbox_mise() {
|
||||||
|
local sandbox_home
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
sandbox_home="$(sbx exec "$SANDBOX_NAME" bash -c 'printf %s "$HOME"')"
|
||||||
|
|
||||||
|
[[ -n "$sandbox_home" ]] ||
|
||||||
|
die "Could not determine the sandbox home directory."
|
||||||
|
|
||||||
|
# mise.jdx.dev sits outside the default network policy, so the sandbox gets
|
||||||
|
# the host binary rather than the network installer. This also pins the
|
||||||
|
# agent to the same mise version the host runs.
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
if ! sbx exec "$SANDBOX_NAME" \
|
||||||
|
bash -c 'command -v mise >/dev/null || [[ -x "$HOME/.local/bin/mise" ]]'; then
|
||||||
|
|
||||||
|
local host_mise
|
||||||
|
if ! host_mise="$(command -v mise)"; then
|
||||||
|
printf 'mise is not on the host PATH; skipping sandbox mise setup.\n' >&2
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
sbx exec "$SANDBOX_NAME" bash -c 'mkdir -p "$HOME/.local/bin"'
|
||||||
|
sbx cp "$host_mise" "$SANDBOX_NAME:$sandbox_home/.local/bin/mise"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local personal="$REPO_CONFIG_DIR/mise.local.toml"
|
||||||
|
if [[ -f "$personal" ]]; then
|
||||||
|
sbx cp "$personal" "$SANDBOX_NAME:$REPO_ROOT/mise.local.toml"
|
||||||
|
printf 'Installed personal mise.local.toml in %s.\n' "$SANDBOX_NAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Shims rather than "mise activate": the agent runs non-interactive shells,
|
||||||
|
# which never fire the activation hook, and would silently get the system
|
||||||
|
# toolchain instead of the pinned one.
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
sbx exec "$SANDBOX_NAME" bash -c '
|
||||||
|
persistent=/etc/sandbox-persistent.sh
|
||||||
|
marker="# BEGIN ai-sbx mise configuration"
|
||||||
|
|
||||||
|
if grep -Fq "$marker" "$persistent" 2>/dev/null; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat >>"$persistent" <<'"'"'EOF'"'"'
|
||||||
|
# BEGIN ai-sbx mise configuration
|
||||||
|
export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"
|
||||||
|
# END ai-sbx mise configuration
|
||||||
|
EOF
|
||||||
|
'
|
||||||
|
|
||||||
|
# A repository with no mise configuration is normal, and a broken config is
|
||||||
|
# the repository's problem, not a reason to refuse to start the agent.
|
||||||
|
# Only the workspace path below is expanded by the host shell.
|
||||||
|
# shellcheck disable=SC2016
|
||||||
|
sbx exec "$SANDBOX_NAME" bash -c '
|
||||||
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
|
cd '"$(printf '%q' "$REPO_ROOT")"' 2>/dev/null || exit 0
|
||||||
|
|
||||||
|
for candidate in \
|
||||||
|
mise.toml mise.local.toml .mise.toml .mise.local.toml \
|
||||||
|
.config/mise.toml .config/mise/config.toml; do
|
||||||
|
|
||||||
|
[[ -f "$candidate" ]] && found=true && break
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ "${found:-false}" == true ]] || exit 0
|
||||||
|
|
||||||
|
mise trust . >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
if mise install; then
|
||||||
|
mise reshim >/dev/null 2>&1 || true
|
||||||
|
else
|
||||||
|
printf "mise install failed; the agent starts without pinned tools.\n" >&2
|
||||||
|
fi
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
create_sandbox() {
|
create_sandbox() {
|
||||||
load_config
|
load_config
|
||||||
|
|
||||||
@@ -652,6 +913,10 @@ setup_command() {
|
|||||||
|
|
||||||
install_sandbox_aws_files
|
install_sandbox_aws_files
|
||||||
|
|
||||||
|
install_sandbox_claude_config
|
||||||
|
|
||||||
|
install_sandbox_mise
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
Setup complete.
|
Setup complete.
|
||||||
@@ -685,6 +950,18 @@ refresh_command() {
|
|||||||
install_sandbox_aws_files
|
install_sandbox_aws_files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# The sandbox home survives stop/start, so this is a setup-time job. It exists
|
||||||
|
# as its own command for the case where the host configuration changed and the
|
||||||
|
# sandbox should catch up without being recreated.
|
||||||
|
config_command() {
|
||||||
|
load_config
|
||||||
|
|
||||||
|
sandbox_exists ||
|
||||||
|
die "Sandbox does not exist. Run: mise run ai:sbx -- setup"
|
||||||
|
|
||||||
|
install_sandbox_claude_config
|
||||||
|
}
|
||||||
|
|
||||||
run_command() {
|
run_command() {
|
||||||
load_config
|
load_config
|
||||||
|
|
||||||
@@ -695,6 +972,10 @@ run_command() {
|
|||||||
# the AWS credentials expire between sessions.
|
# the AWS credentials expire between sessions.
|
||||||
install_sandbox_aws_files
|
install_sandbox_aws_files
|
||||||
|
|
||||||
|
# Tool pins change with the branch the agent is about to work on, so this
|
||||||
|
# runs every time rather than only at setup.
|
||||||
|
install_sandbox_mise
|
||||||
|
|
||||||
if (($#)) && [[ "$1" == "--" ]]; then
|
if (($#)) && [[ "$1" == "--" ]]; then
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
@@ -787,6 +1068,9 @@ main() {
|
|||||||
refresh)
|
refresh)
|
||||||
refresh_command "$@"
|
refresh_command "$@"
|
||||||
;;
|
;;
|
||||||
|
config)
|
||||||
|
config_command "$@"
|
||||||
|
;;
|
||||||
run)
|
run)
|
||||||
run_command "$@"
|
run_command "$@"
|
||||||
;;
|
;;
|
||||||
|
|||||||
Reference in New Issue
Block a user