feat(toolbox): update Docker configuration and documentation
- Update ToolboxStack/output/toolbox-base/Dockerfile with latest container configurations - Update ToolboxStack/output/toolbox-base/PROMPT with enhanced AI collaboration instructions - Update ToolboxStack/output/toolbox-base/README.md with current documentation - Add ToolboxStack/collab/tool-additions/ directory for additional tool configurations - Update CloudronStack/output/master-control-script.sh with improved automation logic These changes enhance the developer workspace configuration and improve automation workflows across the project.
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
# It runs three packaging projects in parallel and maintains status tracking
|
# It runs three packaging projects in parallel and maintains status tracking
|
||||||
|
|
||||||
set -e # Exit on any error
|
set -e # Exit on any error
|
||||||
|
set -u # Exit on undefined variables
|
||||||
|
set -o pipefail # Exit on pipe failures
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
@@ -15,6 +17,7 @@ STATUS_FILE="$SCRIPT_DIR/collab/STATUS.md"
|
|||||||
GIT_URL_LIST="$SCRIPT_DIR/collab/GitUrlList.txt"
|
GIT_URL_LIST="$SCRIPT_DIR/collab/GitUrlList.txt"
|
||||||
HUMAN_HELP_DIR="$WORKSPACES_DIR/human-help-required"
|
HUMAN_HELP_DIR="$WORKSPACES_DIR/human-help-required"
|
||||||
MAX_RETRIES=5
|
MAX_RETRIES=5
|
||||||
|
LOG_FILE="$WORKSPACES_DIR/packaging.log"
|
||||||
|
|
||||||
# Docker image prefix
|
# Docker image prefix
|
||||||
DOCKER_PREFIX="tsysdevstack-cloudron-buildtest-"
|
DOCKER_PREFIX="tsysdevstack-cloudron-buildtest-"
|
||||||
@@ -25,6 +28,46 @@ source "$SCRIPT_DIR/package-functions.sh"
|
|||||||
# Create necessary directories
|
# Create necessary directories
|
||||||
mkdir -p "$ARTIFACTS_DIR" "$WORKSPACES_DIR" "$HUMAN_HELP_DIR"
|
mkdir -p "$ARTIFACTS_DIR" "$WORKSPACES_DIR" "$HUMAN_HELP_DIR"
|
||||||
|
|
||||||
|
# Function to log messages
|
||||||
|
log_message() {
|
||||||
|
local level=$1
|
||||||
|
local message=$2
|
||||||
|
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to perform audit of the packaging process
|
||||||
|
perform_audit() {
|
||||||
|
log_message "INFO" "Starting audit process"
|
||||||
|
|
||||||
|
# Count total, completed, failed, and in-progress applications
|
||||||
|
local total_count=$(grep -c "https://" "$GIT_URL_LIST" || echo 0)
|
||||||
|
local completed_count=$(grep -c "✅ COMPLETE" "$STATUS_FILE" || echo 0)
|
||||||
|
local failed_count=$(grep -c "🛑 FAILED" "$STATUS_FILE" || echo 0)
|
||||||
|
local in_progress_count=$(grep -c "🔄 IN PROGRESS" "$STATUS_FILE" || echo 0)
|
||||||
|
local pending_count=$((total_count - completed_count - failed_count - in_progress_count))
|
||||||
|
|
||||||
|
log_message "INFO" "Audit Summary - Total: $total_count, Completed: $completed_count, Failed: $failed_count, In Progress: $in_progress_count, Pending: $pending_count"
|
||||||
|
|
||||||
|
# Check for artifacts directory health
|
||||||
|
local artifact_count=$(find "$ARTIFACTS_DIR" -mindepth 1 -maxdepth 1 -type d | wc -l)
|
||||||
|
log_message "INFO" "Found $artifact_count artifact directories in $ARTIFACTS_DIR"
|
||||||
|
|
||||||
|
# Check for workspace directory health
|
||||||
|
local workspace_count=$(find "$WORKSPACES_DIR" -mindepth 1 -maxdepth 1 -type d | grep -v "human-help-required\|packaging.log" | wc -l)
|
||||||
|
log_message "INFO" "Found $workspace_count workspace directories in $WORKSPACES_DIR"
|
||||||
|
|
||||||
|
# Check for human help requests
|
||||||
|
local help_requests=$(find "$HUMAN_HELP_DIR" -mindepth 1 -maxdepth 1 -name "STATUS-HumanHelp-*" | wc -l)
|
||||||
|
log_message "INFO" "Found $help_requests human help requests in $HUMAN_HELP_DIR"
|
||||||
|
|
||||||
|
# Verify Docker images
|
||||||
|
local docker_images=$(docker images --format "table {{.Repository}}:{{.Tag}}" | grep "$DOCKER_PREFIX" | wc -l)
|
||||||
|
log_message "INFO" "Found $docker_images Docker images with prefix $DOCKER_PREFIX"
|
||||||
|
|
||||||
|
log_message "INFO" "Audit process completed"
|
||||||
|
}
|
||||||
|
|
||||||
# Function to update status in STATUS.md
|
# Function to update status in STATUS.md
|
||||||
update_status() {
|
update_status() {
|
||||||
local app_name=$1
|
local app_name=$1
|
||||||
@@ -76,7 +119,6 @@ run_packaging_script() {
|
|||||||
local username_repo=$(get_username_repo "$url")
|
local username_repo=$(get_username_repo "$url")
|
||||||
local workspace_dir="$WORKSPACES_DIR/$repo_name"
|
local workspace_dir="$WORKSPACES_DIR/$repo_name"
|
||||||
local artifact_dir="$ARTIFACTS_DIR/$repo_name"
|
local artifact_dir="$ARTIFACTS_DIR/$repo_name"
|
||||||
local packaging_script="$WORKSPACES_DIR/packaging-$repo_name.sh"
|
|
||||||
|
|
||||||
echo "$(date): Starting packaging for $repo_name ($url)" >> "$WORKSPACES_DIR/packaging.log"
|
echo "$(date): Starting packaging for $repo_name ($url)" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
|
|
||||||
@@ -89,11 +131,25 @@ run_packaging_script() {
|
|||||||
# Clone repository
|
# Clone repository
|
||||||
if [ ! -d "$workspace_dir/repo" ] || [ -z "$(ls -A "$workspace_dir/repo")" ]; then
|
if [ ! -d "$workspace_dir/repo" ] || [ -z "$(ls -A "$workspace_dir/repo")" ]; then
|
||||||
echo "Cloning $url to $workspace_dir/repo"
|
echo "Cloning $url to $workspace_dir/repo"
|
||||||
git clone "$url" "$workspace_dir/repo"
|
if ! git clone "$url" "$workspace_dir/repo"; then
|
||||||
|
echo "$(date): Failed to clone $url" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
|
update_status "$repo_name" "🛑 FAILED" "Failed to clone repository"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
# Update repository
|
# Update repository
|
||||||
echo "Updating $url in $workspace_dir/repo"
|
echo "Updating $url in $workspace_dir/repo"
|
||||||
(cd "$workspace_dir/repo" && git fetch && git reset --hard origin/main 2>/dev/null || git reset --hard origin/master 2>/dev/null || git pull)
|
if ! (cd "$workspace_dir/repo" && git fetch && git reset --hard origin/main 2>/dev/null || git reset --hard origin/master 2>/dev/null || git pull); then
|
||||||
|
echo "$(date): Failed to update $url" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
|
update_status "$repo_name" "🔄 IN PROGRESS" "Repo update failed, will retry with fresh clone"
|
||||||
|
# Remove the repo and try to clone again
|
||||||
|
rm -rf "$workspace_dir/repo"
|
||||||
|
if ! git clone "$url" "$workspace_dir/repo"; then
|
||||||
|
echo "$(date): Failed to re-clone $url after update failure" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
|
update_status "$repo_name" "🛑 FAILED" "Failed to update or re-clone repository"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Attempt packaging with retries
|
# Attempt packaging with retries
|
||||||
@@ -103,21 +159,31 @@ run_packaging_script() {
|
|||||||
while [ $attempt -le $MAX_RETRIES ] && [ $success -eq 0 ]; do
|
while [ $attempt -le $MAX_RETRIES ] && [ $success -eq 0 ]; do
|
||||||
echo "$(date): Attempt $attempt/$MAX_RETRIES for $repo_name" >> "$WORKSPACES_DIR/packaging.log"
|
echo "$(date): Attempt $attempt/$MAX_RETRIES for $repo_name" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
|
|
||||||
# Run the packaging process (this would call the specific packaging function)
|
# Capture the output and error of the packaging function
|
||||||
if package_application "$repo_name" "$username_repo" "$workspace_dir" "$artifact_dir"; then
|
if package_application "$repo_name" "$username_repo" "$workspace_dir" "$artifact_dir" 2>"$workspace_dir/error.log"; then
|
||||||
success=1
|
success=1
|
||||||
update_status "$repo_name" "✅ COMPLETE" "Packaged successfully on attempt $attempt"
|
update_status "$repo_name" "✅ COMPLETE" "Packaged successfully on attempt $attempt"
|
||||||
echo "$(date): Successfully packaged $repo_name on attempt $attempt" >> "$WORKSPACES_DIR/packaging.log"
|
echo "$(date): Successfully packaged $repo_name on attempt $attempt" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
else
|
else
|
||||||
echo "$(date): Failed to package $repo_name on attempt $attempt" >> "$WORKSPACES_DIR/packaging.log"
|
echo "$(date): Failed to package $repo_name on attempt $attempt" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
|
cat "$workspace_dir/error.log" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
((attempt++))
|
((attempt++))
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ $success -eq 0 ]; then
|
if [ $success -eq 0 ]; then
|
||||||
# Mark as failed and create human help request
|
# Mark as failed and create human help request with more detailed information
|
||||||
update_status "$repo_name" "🛑 FAILED" "Failed after $MAX_RETRIES attempts"
|
local error_details=$(cat "$workspace_dir/error.log" | head -20 | sed 's/"/\\"/g' | tr '\n' ' ')
|
||||||
touch "$HUMAN_HELP_DIR/STATUS-HumanHelp-$repo_name"
|
update_status "$repo_name" "🛑 FAILED" "Failed after $MAX_RETRIES attempts. Error: $error_details"
|
||||||
|
# Create a detailed human help file
|
||||||
|
cat > "$HUMAN_HELP_DIR/STATUS-HumanHelp-$repo_name" << EOF
|
||||||
|
Application: $repo_name
|
||||||
|
URL: $url
|
||||||
|
Issue: Failed to package after $MAX_RETRIES attempts
|
||||||
|
Date: $(date)
|
||||||
|
Error Details:
|
||||||
|
$(cat "$workspace_dir/error.log")
|
||||||
|
EOF
|
||||||
echo "$(date): Marked $repo_name for human help after $MAX_RETRIES failed attempts" >> "$WORKSPACES_DIR/packaging.log"
|
echo "$(date): Marked $repo_name for human help after $MAX_RETRIES failed attempts" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
7
ToolboxStack/collab/tool-additions/AICLI.md
Normal file
7
ToolboxStack/collab/tool-additions/AICLI.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
I need to add the following tools to the toolbox-base image:
|
||||||
|
|
||||||
|
- https://github.com/just-every/code
|
||||||
|
- https://github.com/QwenLM/qwen-code
|
||||||
|
- https://github.com/google-gemini/gemini-cli
|
||||||
|
- https://github.com/openai/codex
|
||||||
|
- https://github.com/sst/opencode
|
||||||
@@ -68,6 +68,9 @@ RUN curl -sSfL https://raw.githubusercontent.com/aquaproj/aqua-installer/v2.3.1/
|
|||||||
# Install mise for runtime management (no global toolchains pre-installed)
|
# Install mise for runtime management (no global toolchains pre-installed)
|
||||||
RUN curl -sSfL https://mise.jdx.dev/install.sh | env MISE_INSTALL_PATH=/usr/local/bin/mise MISE_INSTALL_HELP=0 sh
|
RUN curl -sSfL https://mise.jdx.dev/install.sh | env MISE_INSTALL_PATH=/usr/local/bin/mise MISE_INSTALL_HELP=0 sh
|
||||||
|
|
||||||
|
# Install Node.js via mise to enable npm package installation
|
||||||
|
RUN mise install node@lts && mise global node@lts
|
||||||
|
|
||||||
# Create non-root user with matching UID/GID for host mapping
|
# Create non-root user with matching UID/GID for host mapping
|
||||||
RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
||||||
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
existing_user="$(getent passwd "${USER_ID}" | cut -d: -f1)"; \
|
||||||
@@ -96,6 +99,9 @@ RUN su - "${USERNAME}" -c 'git clone --depth=1 https://github.com/ohmyzsh/ohmyzs
|
|||||||
&& su - "${USERNAME}" -c 'mkdir -p ~/.config/fish' \
|
&& su - "${USERNAME}" -c 'mkdir -p ~/.config/fish' \
|
||||||
&& su - "${USERNAME}" -c 'printf "\nset -gx AQUA_GLOBAL_CONFIG \$HOME/.config/aquaproj-aqua/aqua.yaml\n# Shell prompt and runtime manager\nstarship init fish | source\nmise activate fish | source\ndirenv hook fish | source\nzoxide init fish | source\n" >> ~/.config/fish/config.fish'
|
&& su - "${USERNAME}" -c 'printf "\nset -gx AQUA_GLOBAL_CONFIG \$HOME/.config/aquaproj-aqua/aqua.yaml\n# Shell prompt and runtime manager\nstarship init fish | source\nmise activate fish | source\ndirenv hook fish | source\nzoxide init fish | source\n" >> ~/.config/fish/config.fish'
|
||||||
|
|
||||||
|
# Install Node.js for the toolbox user and set up the environment
|
||||||
|
RUN su - "${USERNAME}" -c 'mise install node@lts && mise use -g node@lts'
|
||||||
|
|
||||||
COPY aqua.yaml /tmp/aqua.yaml
|
COPY aqua.yaml /tmp/aqua.yaml
|
||||||
|
|
||||||
RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
||||||
@@ -103,6 +109,12 @@ RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
|||||||
&& su - "${USERNAME}" -c 'cp /tmp/aqua.yaml ~/.config/aquaproj-aqua/aqua.yaml' \
|
&& su - "${USERNAME}" -c 'cp /tmp/aqua.yaml ~/.config/aquaproj-aqua/aqua.yaml' \
|
||||||
&& su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=~/.config/aquaproj-aqua/aqua.yaml aqua install'
|
&& su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=~/.config/aquaproj-aqua/aqua.yaml aqua install'
|
||||||
|
|
||||||
|
# Install AI CLI tools via npm using mise to ensure Node.js is available
|
||||||
|
RUN mise exec -- npm install -g @just-every/code @qwen-code/qwen-code @google/gemini-cli @openai/codex opencode-ai@latest
|
||||||
|
|
||||||
|
# Install the same AI CLI tools for the toolbox user so they are available in the container runtime
|
||||||
|
RUN su - "${USERNAME}" -c 'mise exec -- npm install -g @just-every/code @qwen-code/qwen-code @google/gemini-cli @openai/codex opencode-ai@latest'
|
||||||
|
|
||||||
# Prepare workspace directory with appropriate ownership
|
# Prepare workspace directory with appropriate ownership
|
||||||
RUN mkdir -p /workspace \
|
RUN mkdir -p /workspace \
|
||||||
&& chown "${USER_ID}:${GROUP_ID}" /workspace
|
&& chown "${USER_ID}:${GROUP_ID}" /workspace
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ Current state:
|
|||||||
- Dockerfile installs shell tooling (zsh/bash/fish with Starship & oh-my-zsh), core CLI utilities (curl, wget, git, tmux, screen, htop, btop, entr, httpie, tea, bc, etc.), build-essential + headers, aqua, and mise. Aqua is pinned to specific versions for gh, lazygit, direnv, git-delta, zoxide, just, yq, xh, curlie, chezmoi, shfmt, shellcheck, hadolint, uv, watchexec; direnv/zoxide hooks are enabled for all shells (direnv logging muted).
|
- Dockerfile installs shell tooling (zsh/bash/fish with Starship & oh-my-zsh), core CLI utilities (curl, wget, git, tmux, screen, htop, btop, entr, httpie, tea, bc, etc.), build-essential + headers, aqua, and mise. Aqua is pinned to specific versions for gh, lazygit, direnv, git-delta, zoxide, just, yq, xh, curlie, chezmoi, shfmt, shellcheck, hadolint, uv, watchexec; direnv/zoxide hooks are enabled for all shells (direnv logging muted).
|
||||||
- aqua-managed CLI inventory lives in README.md alongside usage notes; tea installs via direct download with checksum verification (TEA_VERSION build arg).
|
- aqua-managed CLI inventory lives in README.md alongside usage notes; tea installs via direct download with checksum verification (TEA_VERSION build arg).
|
||||||
- mise handles language/tool runtimes; activation wired into zsh, bash, and fish.
|
- mise handles language/tool runtimes; activation wired into zsh, bash, and fish.
|
||||||
|
- AI CLI tools (just-every/code, QwenLM/qwen-code, google-gemini/gemini-cli, openai/codex, sst/opencode) are installed via npm and available in the PATH.
|
||||||
- docker-compose.yml runs container with host UID/GID, `sleep infinity`, and docker socket mount; run via run.sh/build.sh. Host directories `~/.local/share/mise` and `~/.cache/mise` are mounted for persistent runtimes.
|
- docker-compose.yml runs container with host UID/GID, `sleep infinity`, and docker socket mount; run via run.sh/build.sh. Host directories `~/.local/share/mise` and `~/.cache/mise` are mounted for persistent runtimes.
|
||||||
- Devcontainer config ( .devcontainer/devcontainer.json ) references the compose service.
|
- Devcontainer config ( .devcontainer/devcontainer.json ) references the compose service.
|
||||||
- Documentation: README.md (tooling inventory & workflow) and this PROMPT must stay current, and both should stay aligned with the shared guidance in ../PROMPT. README also notes that build.sh now uses docker buildx with a local cache directory and documents the `dev` → `release-current` → semantic tagging workflow.
|
- Documentation: README.md (tooling inventory & workflow) and this PROMPT must stay current, and both should stay aligned with the shared guidance in ../PROMPT. README also notes that build.sh now uses docker buildx with a local cache directory and documents the `dev` → `release-current` → semantic tagging workflow.
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ The compose service mounts the current repo to `/workspace` (read/write) and run
|
|||||||
| **Runtime & CLI Managers** | 🪄 `mise` • 💧 `aqua` | `mise` handles language/tool runtimes (activation wired into zsh/bash/fish); `aqua` manages standalone CLIs with config at `~/.config/aquaproj-aqua/aqua.yaml`. |
|
| **Runtime & CLI Managers** | 🪄 `mise` • 💧 `aqua` | `mise` handles language/tool runtimes (activation wired into zsh/bash/fish); `aqua` manages standalone CLIs with config at `~/.config/aquaproj-aqua/aqua.yaml`. |
|
||||||
| **Core CLI Utilities** | 📦 `curl` • 📥 `wget` • 🔐 `ca-certificates` • 🧭 `git` • 🔧 `build-essential` + headers (`pkg-config`, `libssl-dev`, `zlib1g-dev`, `libffi-dev`, `libsqlite3-dev`, `libreadline-dev`, `make`) • 🔍 `ripgrep` • 🧭 `fzf` • 📁 `fd` • 📖 `bat` • 🔗 `openssh-client` • 🧵 `tmux` • 🖥️ `screen` • 📈 `htop` • 📉 `btop` • ♻️ `entr` • 📊 `jq` • 🌐 `httpie` • ☕ `tea` • 🧮 `bc` | Provides ergonomic defaults plus toolchain deps for compiling runtimes (no global language installs). |
|
| **Core CLI Utilities** | 📦 `curl` • 📥 `wget` • 🔐 `ca-certificates` • 🧭 `git` • 🔧 `build-essential` + headers (`pkg-config`, `libssl-dev`, `zlib1g-dev`, `libffi-dev`, `libsqlite3-dev`, `libreadline-dev`, `make`) • 🔍 `ripgrep` • 🧭 `fzf` • 📁 `fd` • 📖 `bat` • 🔗 `openssh-client` • 🧵 `tmux` • 🖥️ `screen` • 📈 `htop` • 📉 `btop` • ♻️ `entr` • 📊 `jq` • 🌐 `httpie` • ☕ `tea` • 🧮 `bc` | Provides ergonomic defaults plus toolchain deps for compiling runtimes (no global language installs). |
|
||||||
| **Aqua-Managed CLIs** | 🐙 `gh` • 🌀 `lazygit` • 🪄 `direnv` • 🎨 `git-delta` • 🧭 `zoxide` • 🧰 `just` • 🧾 `yq` • ⚡ `xh` • 🌍 `curlie` • 🏠 `chezmoi` • 🛠️ `shfmt` • ✅ `shellcheck` • 🐳 `hadolint` • 🐍 `uv` • 🔁 `watchexec` | Extend via `~/.config/aquaproj-aqua/aqua.yaml` and run `aqua install`. Direnv logging is muted and hooks for direnv/zoxide are pre-configured for zsh, bash, and fish. |
|
| **Aqua-Managed CLIs** | 🐙 `gh` • 🌀 `lazygit` • 🪄 `direnv` • 🎨 `git-delta` • 🧭 `zoxide` • 🧰 `just` • 🧾 `yq` • ⚡ `xh` • 🌍 `curlie` • 🏠 `chezmoi` • 🛠️ `shfmt` • ✅ `shellcheck` • 🐳 `hadolint` • 🐍 `uv` • 🔁 `watchexec` | Extend via `~/.config/aquaproj-aqua/aqua.yaml` and run `aqua install`. Direnv logging is muted and hooks for direnv/zoxide are pre-configured for zsh, bash, and fish. |
|
||||||
|
| **AI CLI Tools** | 🧠 `@just-every/code` • 🤖 `@qwen-code/qwen-code` • 💎 `@google/gemini-cli` • 🔮 `@openai/codex` • 🌐 `opencode-ai` | AI-powered command-line tools for enhanced development workflows. Node.js is installed via mise to support npm package installation. |
|
||||||
| **Container Workflow** | 🐳 Docker socket mount (`/var/run/docker.sock`) | Enables Docker CLIs inside the container; host Docker daemon required. |
|
| **Container Workflow** | 🐳 Docker socket mount (`/var/run/docker.sock`) | Enables Docker CLIs inside the container; host Docker daemon required. |
|
||||||
| **Runtime Environment** | 👤 Non-root user `toolbox` (UID/GID mapped) • 🗂️ `/workspace` mount | Maintains host permissions and isolates artifacts under `artifacts/ToolboxStack/toolbox-base`. |
|
| **Runtime Environment** | 👤 Non-root user `toolbox` (UID/GID mapped) • 🗂️ `/workspace` mount | Maintains host permissions and isolates artifacts under `artifacts/ToolboxStack/toolbox-base`. |
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user