#!/usr/bin/env bash workspace="$HOME/ai_workspace" app="opencode" env="" rebuild=false while [[ $# -gt 0 ]]; do case "$1" in -p|--path) workspace="$(readlink -f "$2")" shift 2 ;; -a|--app) app="$2" shift 2 ;; -e|--env) env="$2" shift 2 ;; --rebuild) rebuild=true shift ;; *) echo "Usage: $0 [-p /path/to/workspace] [-a claude|opencode] [-e rust] [--rebuild]" >&2 exit 1 ;; esac done case "$app" in claude) image_name="claude-code-local" npm_pkg="@anthropic-ai/claude-code" cmd="claude" extra_volumes=( -v "$HOME/.claude:/root/.claude" -v "$HOME/.claude.json:/root/.claude.json" ) ;; opencode) image_name="opencode-local" npm_pkg="opencode-ai" cmd="opencode" extra_volumes=( -v "$HOME/.config/opencode:/root/.config/opencode" -v "$HOME/.local/share/opencode:/root/.local/share/opencode" -v "$HOME/.local/state/opencode:/root/.local/state/opencode" -v "$HOME/.claude:/root/.claude" # allow access to claude config for hacked auth ) ;; *) echo "Unknown app '$app'. Choose 'claude' or 'opencode'." >&2 exit 1 ;; esac env_suffix="" env_layer="" case "$env" in "") ;; rust) env_suffix="-rust" env_layer='RUN curl --proto '"'"'=https'"'"' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y ENV PATH="/root/.cargo/bin:${PATH}"' ;; *) echo "Unknown env '$env'. Supported: rust" >&2 exit 1 ;; esac image_name="${image_name}${env_suffix}" if $rebuild || ! docker image inspect "$image_name" &>/dev/null; then echo "Building $image_name..." dockerfile="FROM node:24-bullseye ${env_layer} RUN npm install -g $npm_pkg WORKDIR /workspace CMD [\"$cmd\"]" docker build --pull -t "$image_name" - <<< "$dockerfile" fi clear docker run -it --rm \ --name "${image_name}-container" \ -v "$workspace:/workspace" \ "${extra_volumes[@]}" \ -w /workspace \ "$image_name"