From bf680897e47d32a254e520162c32944a01e4399f Mon Sep 17 00:00:00 2001 From: shrwnsan <38465+shrwnsan@users.noreply.github.com> Date: Wed, 11 Feb 2026 11:23:36 +0800 Subject: [PATCH 1/3] feat: add config file support and optional toolchains Add ~/.agentbox/config for persistent settings (tool, Java, Claude channel). Make Java opt-out with --no-java flag (backwards compatible). Add --cc-latest flag for latest Claude Code channel. Improve Java status message to avoid command-not-found errors. Config file supports bash key=value format with shebang for syntax highlighting. CLI flags override config file settings. Co-Authored-By: GLM --- .gitignore | 5 ++++- Dockerfile | 37 +++++++++++++++++++++++++------------ agentbox | 43 ++++++++++++++++++++++++++++++++++++++++--- config.example | 18 ++++++++++++++++++ entrypoint.sh | 2 +- 5 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 config.example diff --git a/.gitignore b/.gitignore index d2f63d2..875a2e0 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,7 @@ Thumbs.db # Environment files .env .env.local -.env.*.local \ No newline at end of file +.env.*.local + +# User config (keep config.example as template) +/config \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 402124e..cca1533 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,15 @@ # AgentBox - Simplified multi-language development environment for Claude FROM debian:trixie +# Optional Java toolchain (default: on for compatibility) +ARG INCLUDE_JAVA=true + +# Claude Code channel (stable or latest) +ARG CC_CHANNEL=stable + +# Include OpenCode (default: on) +ARG INCLUDE_OPENCODE=true + # Prevent interactive prompts during installation ENV DEBIAN_FRONTEND=noninteractive ENV LANG=en_US.UTF-8 @@ -33,8 +42,8 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ # Python build dependencies python3-dev python3-pip python3-venv \ libssl-dev libffi-dev \ - # Java dependencies - default-jdk maven gradle \ + # Java dependencies (conditional) + $(if [ "$INCLUDE_JAVA" = "true" ]; then echo "default-jdk maven gradle"; fi) \ # Search tools ripgrep fd-find && \ # Setup locale @@ -111,13 +120,15 @@ RUN bash -c "source $NVM_DIR/nvm.sh && \ yarn \ pnpm" -# Install SDKMAN for Java toolchain management -RUN curl -s "https://get.sdkman.io?rcupdate=false" | bash && \ - echo 'source "$HOME/.sdkman/bin/sdkman-init.sh"' >> ~/.bashrc && \ - echo 'source "$HOME/.sdkman/bin/sdkman-init.sh"' >> ~/.zshrc && \ - bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && \ - sdk install java 21.0.9-tem && \ - sdk install gradle" +# Install SDKMAN for Java toolchain management (conditional) +RUN if [ "$INCLUDE_JAVA" = "true" ]; then \ + curl -s "https://get.sdkman.io?rcupdate=false" | bash && \ + echo 'source "$HOME/.sdkman/bin/sdkman-init.sh"' >> ~/.bashrc && \ + echo 'source "$HOME/.sdkman/bin/sdkman-init.sh"' >> ~/.zshrc && \ + bash -c "source $HOME/.sdkman/bin/sdkman-init.sh && \ + sdk install java 21.0.9-tem && \ + sdk install gradle"; \ + fi # Setup Python tools RUN /home/${USERNAME}/.local/bin/uv tool install black && \ @@ -201,11 +212,13 @@ USER ${USERNAME} # Dockerfile hasn't changed. This ensures fresh installs on explicit rebuilds instead # of relying on unpredictable auto-update timing. ARG BUILD_TIMESTAMP=unknown -RUN curl -fsSL https://claude.ai/install.sh | bash -s stable && \ +RUN curl -fsSL https://claude.ai/install.sh | bash -s ${CC_CHANNEL} && \ zsh -i -c 'which claude && claude --version' -RUN curl -fsSL https://opencode.ai/install | bash && \ - zsh -i -c 'which opencode && opencode --version' +RUN if [ "$INCLUDE_OPENCODE" = "true" ]; then \ + curl -fsSL https://opencode.ai/install | bash && \ + zsh -i -c 'which opencode && opencode --version'; \ + fi # Entrypoint ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] diff --git a/agentbox b/agentbox index 1cdb48a..86d1afc 100755 --- a/agentbox +++ b/agentbox @@ -123,6 +123,9 @@ build_image() { --build-arg GROUP_ID="${group_id}" \ --build-arg USERNAME="agent" \ --build-arg BUILD_TIMESTAMP=${build_timestamp} \ + --build-arg INCLUDE_JAVA="${include_java}" \ + --build-arg INCLUDE_OPENCODE="${include_opencode}" \ + --build-arg CC_CHANNEL="${cc_channel}" \ --label "agentbox.hash=${combined_hash}" \ --label "agentbox.version=1.0.0" \ --label "agentbox.built=${build_timestamp}" \ @@ -471,6 +474,9 @@ Options: --rebuild Force rebuild of the image --add-dir DIR Mount additional directory (can be used multiple times) --ignore-dot-env Do not load .env files as environment variables (still mounted) + --no-java Exclude Java toolchain for smaller image (default: included) + --no-opencode Exclude OpenCode installation for smaller image (default: included) + --cc-latest Use Claude Code latest channel instead of stable (may be ahead of stable) Commands: shell [--admin] Start interactive shell instead of Claude CLI @@ -481,6 +487,11 @@ Commands: Use 'shell --admin' to get a shell with sudo privileges. Other commands will be executed inside the container. +Configuration: + Config file: ~/.agentbox/config + CLI flags override config file settings. + See config.example for all available options. + Examples: agentbox # Start Claude CLI for current project agentbox --tool opencode # Start OpenCode instead of Claude @@ -488,11 +499,10 @@ Examples: agentbox -p 3002:8080 # Map host port 3002 to container port 8080 agentbox shell # Start interactive shell instead of Claude agentbox shell --admin # Start admin shell with sudo access - agentbox --add-dir ~/1 --add-dir ~/2 # Add dirs with Claude CLI + agentbox --add-dir ~/1 --add-dir ~/2 # Add dirs with Claude CLI agentbox python script.py # Run Python script in container agentbox --rebuild # Force rebuild image agentbox ssh-init # Set up SSH for AgentBox - AGENTBOX_TOOL=opencode agentbox # Use env var to select tool Environment variables (set in ~/.agentbox/.env): AGENTBOX_EXTRA_HOSTS Comma-separated host:ip pairs added to container /etc/hosts @@ -543,8 +553,20 @@ ssh_setup() { log_info "AgentBox will use this directory for all SSH operations." } +# Load config file if exists +load_config() { + local config_file="${HOME}/.agentbox/config" + if [[ -f "$config_file" ]]; then + # Source the config file, allowing it to override defaults + source "$config_file" + fi +} + # Main execution main() { + # Load config file first (before CLI args, so CLI args can override) + load_config + # Parse arguments local force_rebuild=false local shell_mode=false @@ -553,7 +575,10 @@ main() { declare -a ports=() local extra_dirs=() local tool="${AGENTBOX_TOOL:-claude}" - local ignore_dot_env=false + local ignore_dot_env="${AGENTBOX_IGNORE_DOT_ENV:-false}" + local include_java="${AGENTBOX_INCLUDE_JAVA:-true}" + local include_opencode="${AGENTBOX_INCLUDE_OPENCODE:-true}" + local cc_channel="${AGENTBOX_CC_CHANNEL:-stable}" while [[ $# -gt 0 ]]; do case "$1" in @@ -596,6 +621,18 @@ main() { ignore_dot_env=true shift ;; + --no-java) + include_java=false + shift + ;; + --no-opencode) + include_opencode=false + shift + ;; + --cc-latest) + cc_channel=latest + shift + ;; shell) shell_mode=true shift diff --git a/config.example b/config.example new file mode 100644 index 0000000..a9d1775 --- /dev/null +++ b/config.example @@ -0,0 +1,18 @@ +#!/bin/bash +# AgentBox configuration +# Copy this file to ~/.agentbox/config to customize defaults + +# Tool selection: claude (default) or opencode +# AGENTBOX_TOOL=claude + +# Include Java toolchain (JDK, Maven, Gradle) - default: true +# AGENTBOX_INCLUDE_JAVA=false + +# Include OpenCode - default: true +# AGENTBOX_INCLUDE_OPENCODE=false + +# Claude Code channel: stable or latest - default: stable +# AGENTBOX_CC_CHANNEL=latest + +# Ignore .env files - default: false +# AGENTBOX_IGNORE_DOT_ENV=true diff --git a/entrypoint.sh b/entrypoint.sh index 191f1b5..0dac6b9 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -66,7 +66,7 @@ if [ -t 0 ] && [ -t 1 ]; then echo "📁 Project Directory: ${PROJECT_DIR:-unknown}" echo "🐍 Python: $(python3 --version 2>&1 | cut -d' ' -f2) (uv available)" echo "🟢 Node.js: $(node --version 2>/dev/null || echo 'not found')" - echo "☕ Java: $(java -version 2>&1 | head -1 | cut -d'"' -f2 || echo 'not found')" + echo "☕ Java: $(command -v java >/dev/null 2>&1 && java -version 2>&1 | head -1 | cut -d'"' -f2 || echo 'excluded (--no-java)')" if [ "$TOOL" = "opencode" ]; then echo "🤖 OpenCode: $(opencode --version 2>/dev/null || echo 'not found - check installation')" else From da6f04d142a14b997935b6bde6a1e94f77a78276 Mon Sep 17 00:00:00 2001 From: shrwnsan <38465+shrwnsan@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:27:52 +0800 Subject: [PATCH 2/3] fix: auto-enable OpenCode when tool is set to opencode Override AGENTBOX_INCLUDE_OPENCODE=false when AGENTBOX_TOOL=opencode since the tool cannot run without being installed. Co-Authored-By: GLM --- agentbox | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/agentbox b/agentbox index 86d1afc..ab2e7b9 100755 --- a/agentbox +++ b/agentbox @@ -662,6 +662,11 @@ main() { exit 1 fi + # Auto-enable OpenCode if tool is set to opencode + if [[ "$tool" == "opencode" ]]; then + include_opencode=true + fi + # Check runtime RUNTIME=$(check_runtime) log_info "Using container runtime: $RUNTIME" From bfcfb5ce4f8abb467c61795e8235b8c89858d92e Mon Sep 17 00:00:00 2001 From: shrwnsan <38465+shrwnsan@users.noreply.github.com> Date: Fri, 27 Feb 2026 00:43:04 +0800 Subject: [PATCH 3/3] feat: add AGENTBOX_SIMPLE_PROMPT opt-in and standardize ARG names - Prefix all Docker ARGs with AGENTBOX_ for consistency (INCLUDE_JAVA, CC_CHANNEL, etc.) - Add AGENTBOX_SIMPLE_PROMPT arg for simple traditional Unix-style prompt (user@host:~) - Keep default oh-my-zsh theme for backwards compatibility - Maintain terminal size handling for better TTY support - Add projects/ and .agents/ to .gitignore Co-Authored-By: OpenCode --- .gitignore | 8 +++++++- Dockerfile | 22 +++++++++++++++------- agentbox | 8 +++++--- config.example | 3 +++ 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 875a2e0..66e34a0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,10 @@ Thumbs.db .env.*.local # User config (keep config.example as template) -/config \ No newline at end of file +/config + +# AgentBox project directories +projects/ + +# Local agent documentation +.agents/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index cca1533..4a3287f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,13 +2,16 @@ FROM debian:trixie # Optional Java toolchain (default: on for compatibility) -ARG INCLUDE_JAVA=true +ARG AGENTBOX_INCLUDE_JAVA=true # Claude Code channel (stable or latest) -ARG CC_CHANNEL=stable +ARG AGENTBOX_CC_CHANNEL=stable # Include OpenCode (default: on) -ARG INCLUDE_OPENCODE=true +ARG AGENTBOX_INCLUDE_OPENCODE=true + +# Simple traditional Unix-style prompt (default: off for backwards compatibility) +ARG AGENTBOX_SIMPLE_PROMPT=false # Prevent interactive prompts during installation ENV DEBIAN_FRONTEND=noninteractive @@ -43,7 +46,7 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ python3-dev python3-pip python3-venv \ libssl-dev libffi-dev \ # Java dependencies (conditional) - $(if [ "$INCLUDE_JAVA" = "true" ]; then echo "default-jdk maven gradle"; fi) \ + $(if [ "$AGENTBOX_INCLUDE_JAVA" = "true" ]; then echo "default-jdk maven gradle"; fi) \ # Search tools ripgrep fd-find && \ # Setup locale @@ -121,7 +124,7 @@ RUN bash -c "source $NVM_DIR/nvm.sh && \ pnpm" # Install SDKMAN for Java toolchain management (conditional) -RUN if [ "$INCLUDE_JAVA" = "true" ]; then \ +RUN if [ "$AGENTBOX_INCLUDE_JAVA" = "true" ]; then \ curl -s "https://get.sdkman.io?rcupdate=false" | bash && \ echo 'source "$HOME/.sdkman/bin/sdkman-init.sh"' >> ~/.bashrc && \ echo 'source "$HOME/.sdkman/bin/sdkman-init.sh"' >> ~/.zshrc && \ @@ -165,6 +168,11 @@ if [[ -n "$PS1" ]] && command -v stty >/dev/null; then fi EOF +# Simple traditional Unix-style prompt (opt-in: AGENTBOX_SIMPLE_PROMPT=true) +RUN if [ "$AGENTBOX_SIMPLE_PROMPT" = "true" ]; then \ + echo 'PROMPT='"'"'%n@%m:%~ $ '"'"'' >> ~/.zshrc; \ + fi + # Configure git RUN git config --global init.defaultBranch main && \ git config --global pull.rebase false @@ -212,10 +220,10 @@ USER ${USERNAME} # Dockerfile hasn't changed. This ensures fresh installs on explicit rebuilds instead # of relying on unpredictable auto-update timing. ARG BUILD_TIMESTAMP=unknown -RUN curl -fsSL https://claude.ai/install.sh | bash -s ${CC_CHANNEL} && \ +RUN curl -fsSL https://claude.ai/install.sh | bash -s ${AGENTBOX_CC_CHANNEL} && \ zsh -i -c 'which claude && claude --version' -RUN if [ "$INCLUDE_OPENCODE" = "true" ]; then \ +RUN if [ "$AGENTBOX_INCLUDE_OPENCODE" = "true" ]; then \ curl -fsSL https://opencode.ai/install | bash && \ zsh -i -c 'which opencode && opencode --version'; \ fi diff --git a/agentbox b/agentbox index ab2e7b9..c448b92 100755 --- a/agentbox +++ b/agentbox @@ -123,9 +123,10 @@ build_image() { --build-arg GROUP_ID="${group_id}" \ --build-arg USERNAME="agent" \ --build-arg BUILD_TIMESTAMP=${build_timestamp} \ - --build-arg INCLUDE_JAVA="${include_java}" \ - --build-arg INCLUDE_OPENCODE="${include_opencode}" \ - --build-arg CC_CHANNEL="${cc_channel}" \ + --build-arg AGENTBOX_INCLUDE_JAVA="${include_java}" \ + --build-arg AGENTBOX_INCLUDE_OPENCODE="${include_opencode}" \ + --build-arg AGENTBOX_CC_CHANNEL="${cc_channel}" \ + --build-arg AGENTBOX_SIMPLE_PROMPT="${simple_prompt}" \ --label "agentbox.hash=${combined_hash}" \ --label "agentbox.version=1.0.0" \ --label "agentbox.built=${build_timestamp}" \ @@ -579,6 +580,7 @@ main() { local include_java="${AGENTBOX_INCLUDE_JAVA:-true}" local include_opencode="${AGENTBOX_INCLUDE_OPENCODE:-true}" local cc_channel="${AGENTBOX_CC_CHANNEL:-stable}" + local simple_prompt="${AGENTBOX_SIMPLE_PROMPT:-false}" while [[ $# -gt 0 ]]; do case "$1" in diff --git a/config.example b/config.example index a9d1775..ce611d2 100644 --- a/config.example +++ b/config.example @@ -14,5 +14,8 @@ # Claude Code channel: stable or latest - default: stable # AGENTBOX_CC_CHANNEL=latest +# Simple traditional Unix-style prompt (user@host:~) - default: false +# AGENTBOX_SIMPLE_PROMPT=true + # Ignore .env files - default: false # AGENTBOX_IGNORE_DOT_ENV=true