diff --git a/internal/daemon/imagebuild.go b/internal/daemon/imagebuild.go index ff19215..359892f 100644 --- a/internal/daemon/imagebuild.go +++ b/internal/daemon/imagebuild.go @@ -23,21 +23,20 @@ import ( ) const ( - defaultMiseVersion = "v2025.12.0" - defaultMiseInstallPath = "/usr/local/bin/mise" - defaultMiseActivateLine = `eval "$(/usr/local/bin/mise activate bash)"` - defaultNodeTool = "node@22" - defaultOpenCodeTool = "github:anomalyco/opencode" - defaultClaudeCodePackage = "@anthropic-ai/claude-code" - defaultPiPackage = "@mariozechner/pi-coding-agent" - defaultNPMGlobalPrefix = "/root/.local/share/banger/npm-global" - defaultTPMRepo = "https://github.com/tmux-plugins/tpm" - defaultResurrectRepo = "https://github.com/tmux-plugins/tmux-resurrect" - defaultContinuumRepo = "https://github.com/tmux-plugins/tmux-continuum" - defaultTMUXPluginDir = "/root/.tmux/plugins" - defaultTMUXResurrectDir = "/root/.tmux/resurrect" - tmuxManagedBlockStart = "# >>> banger tmux plugins >>>" - tmuxManagedBlockEnd = "# <<< banger tmux plugins <<<" + defaultMiseVersion = "v2025.12.0" + defaultMiseInstallPath = "/usr/local/bin/mise" + defaultMiseActivateLine = `eval "$(/usr/local/bin/mise activate bash)"` + defaultNodeTool = "node@22" + defaultOpenCodeTool = "github:anomalyco/opencode" + defaultClaudeCodeTool = "npm:@anthropic-ai/claude-code" + defaultPiTool = "npm:@mariozechner/pi-coding-agent" + defaultTPMRepo = "https://github.com/tmux-plugins/tpm" + defaultResurrectRepo = "https://github.com/tmux-plugins/tmux-resurrect" + defaultContinuumRepo = "https://github.com/tmux-plugins/tmux-continuum" + defaultTMUXPluginDir = "/root/.tmux/plugins" + defaultTMUXResurrectDir = "/root/.tmux/resurrect" + tmuxManagedBlockStart = "# >>> banger tmux plugins >>>" + tmuxManagedBlockEnd = "# <<< banger tmux plugins <<<" ) type imageBuildSpec struct { @@ -307,26 +306,28 @@ func buildModulesCommand(modulesBase string) string { func appendMiseSetup(script *bytes.Buffer) { const ( - nodeShimPath = "/root/.local/share/mise/shims/node" - npmShimPath = "/root/.local/share/mise/shims/npm" + nodeShimPath = "/root/.local/share/mise/shims/node" + npmShimPath = "/root/.local/share/mise/shims/npm" + claudeShimPath = "/root/.local/share/mise/shims/claude" + piShimPath = "/root/.local/share/mise/shims/pi" ) - claudePath := filepath.ToSlash(filepath.Join(defaultNPMGlobalPrefix, "bin", "claude")) - piPath := filepath.ToSlash(filepath.Join(defaultNPMGlobalPrefix, "bin", "pi")) fmt.Fprintf(script, "curl -fsSL https://mise.run | MISE_INSTALL_PATH=%s MISE_VERSION=%s sh\n", shellQuote(defaultMiseInstallPath), shellQuote(defaultMiseVersion)) fmt.Fprintf(script, "%s use -g %s\n", shellQuote(defaultMiseInstallPath), shellQuote(defaultNodeTool)) fmt.Fprintf(script, "%s use -g %s\n", shellQuote(defaultMiseInstallPath), shellQuote(defaultOpenCodeTool)) + fmt.Fprintf(script, "%s use -g %s\n", shellQuote(defaultMiseInstallPath), shellQuote(defaultClaudeCodeTool)) + fmt.Fprintf(script, "%s use -g %s\n", shellQuote(defaultMiseInstallPath), shellQuote(defaultPiTool)) fmt.Fprintf(script, "%s reshim\n", shellQuote(defaultMiseInstallPath)) fmt.Fprintf(script, "if [[ ! -e %s ]]; then echo 'node shim not found after mise install' >&2; exit 1; fi\n", shellQuote(nodeShimPath)) fmt.Fprintf(script, "if [[ ! -e %s ]]; then echo 'npm shim not found after mise install' >&2; exit 1; fi\n", shellQuote(npmShimPath)) fmt.Fprintf(script, "if [[ ! -e %s ]]; then echo 'opencode shim not found after mise install' >&2; exit 1; fi\n", shellQuote(opencode.ShimPath)) - fmt.Fprintf(script, "mkdir -p %s\n", shellQuote(defaultNPMGlobalPrefix)) - fmt.Fprintf(script, "NPM_CONFIG_PREFIX=%s %s install -g %s %s\n", shellQuote(defaultNPMGlobalPrefix), shellQuote(npmShimPath), shellQuote(defaultClaudeCodePackage), shellQuote(defaultPiPackage)) - fmt.Fprintf(script, "if [[ ! -e %s ]]; then echo 'claude binary not found after npm install' >&2; exit 1; fi\n", shellQuote(claudePath)) - fmt.Fprintf(script, "if [[ ! -e %s ]]; then echo 'pi binary not found after npm install' >&2; exit 1; fi\n", shellQuote(piPath)) + fmt.Fprintf(script, "if [[ ! -e %s ]]; then echo 'claude shim not found after mise install' >&2; exit 1; fi\n", shellQuote(claudeShimPath)) + fmt.Fprintf(script, "if [[ ! -e %s ]]; then echo 'pi shim not found after mise install' >&2; exit 1; fi\n", shellQuote(piShimPath)) + fmt.Fprintf(script, "ln -snf %s %s\n", shellQuote(nodeShimPath), shellQuote("/usr/local/bin/node")) + fmt.Fprintf(script, "ln -snf %s %s\n", shellQuote(npmShimPath), shellQuote("/usr/local/bin/npm")) fmt.Fprintf(script, "ln -snf %s %s\n", shellQuote(opencode.ShimPath), shellQuote(opencode.GuestBinaryPath)) - fmt.Fprintf(script, "ln -snf %s %s\n", shellQuote(claudePath), shellQuote("/usr/local/bin/claude")) - fmt.Fprintf(script, "ln -snf %s %s\n", shellQuote(piPath), shellQuote("/usr/local/bin/pi")) + fmt.Fprintf(script, "ln -snf %s %s\n", shellQuote(claudeShimPath), shellQuote("/usr/local/bin/claude")) + fmt.Fprintf(script, "ln -snf %s %s\n", shellQuote(piShimPath), shellQuote("/usr/local/bin/pi")) script.WriteString("mkdir -p /etc/profile.d\n") script.WriteString("cat > /etc/profile.d/mise.sh <<'EOF'\n") fmt.Fprintf(script, "if [ -n \"${BASH_VERSION:-}\" ] && [ -x %s ]; then\n", shellQuote(defaultMiseInstallPath)) diff --git a/internal/daemon/imagebuild_test.go b/internal/daemon/imagebuild_test.go index 9c7fc44..af7662d 100644 --- a/internal/daemon/imagebuild_test.go +++ b/internal/daemon/imagebuild_test.go @@ -20,17 +20,19 @@ func TestBuildProvisionScriptInstallsDefaultTools(t *testing.T) { "curl -fsSL https://mise.run | MISE_INSTALL_PATH='/usr/local/bin/mise' MISE_VERSION='v2025.12.0' sh", "'/usr/local/bin/mise' use -g 'node@22'", "'/usr/local/bin/mise' use -g 'github:anomalyco/opencode'", + "'/usr/local/bin/mise' use -g 'npm:@anthropic-ai/claude-code'", + "'/usr/local/bin/mise' use -g 'npm:@mariozechner/pi-coding-agent'", "'/usr/local/bin/mise' reshim", "if [[ ! -e '/root/.local/share/mise/shims/node' ]]; then echo 'node shim not found after mise install' >&2; exit 1; fi", "if [[ ! -e '/root/.local/share/mise/shims/npm' ]]; then echo 'npm shim not found after mise install' >&2; exit 1; fi", "if [[ ! -e '/root/.local/share/mise/shims/opencode' ]]; then echo 'opencode shim not found after mise install' >&2; exit 1; fi", - "mkdir -p '/root/.local/share/banger/npm-global'", - "NPM_CONFIG_PREFIX='/root/.local/share/banger/npm-global' '/root/.local/share/mise/shims/npm' install -g '@anthropic-ai/claude-code' '@mariozechner/pi-coding-agent'", - "if [[ ! -e '/root/.local/share/banger/npm-global/bin/claude' ]]; then echo 'claude binary not found after npm install' >&2; exit 1; fi", - "if [[ ! -e '/root/.local/share/banger/npm-global/bin/pi' ]]; then echo 'pi binary not found after npm install' >&2; exit 1; fi", + "if [[ ! -e '/root/.local/share/mise/shims/claude' ]]; then echo 'claude shim not found after mise install' >&2; exit 1; fi", + "if [[ ! -e '/root/.local/share/mise/shims/pi' ]]; then echo 'pi shim not found after mise install' >&2; exit 1; fi", + "ln -snf '/root/.local/share/mise/shims/node' '/usr/local/bin/node'", + "ln -snf '/root/.local/share/mise/shims/npm' '/usr/local/bin/npm'", "ln -snf '/root/.local/share/mise/shims/opencode' '/usr/local/bin/opencode'", - "ln -snf '/root/.local/share/banger/npm-global/bin/claude' '/usr/local/bin/claude'", - "ln -snf '/root/.local/share/banger/npm-global/bin/pi' '/usr/local/bin/pi'", + "ln -snf '/root/.local/share/mise/shims/claude' '/usr/local/bin/claude'", + "ln -snf '/root/.local/share/mise/shims/pi' '/usr/local/bin/pi'", "cat > /etc/profile.d/mise.sh <<'EOF'", "if [ -n \"${BASH_VERSION:-}\" ] && [ -x '/usr/local/bin/mise' ]; then", `eval "$(/usr/local/bin/mise activate bash)"`, diff --git a/scripts/customize.sh b/scripts/customize.sh index 13eebed..23d6d50 100755 --- a/scripts/customize.sh +++ b/scripts/customize.sh @@ -95,9 +95,8 @@ MISE_VERSION="v2025.12.0" MISE_INSTALL_PATH="/usr/local/bin/mise" MISE_ACTIVATE_LINE='eval "$(/usr/local/bin/mise activate bash)"' NODE_TOOL="node@22" -CLAUDE_CODE_PACKAGE="@anthropic-ai/claude-code" -PI_PACKAGE="@mariozechner/pi-coding-agent" -NPM_GLOBAL_PREFIX="/root/.local/share/banger/npm-global" +CLAUDE_CODE_TOOL="npm:@anthropic-ai/claude-code" +PI_TOOL="npm:@mariozechner/pi-coding-agent" TMUX_PLUGIN_DIR="/root/.tmux/plugins" TMUX_RESURRECT_DIR="/root/.tmux/resurrect" TMUX_TPM_REPO="https://github.com/tmux-plugins/tpm" @@ -406,6 +405,8 @@ DEBIAN_FRONTEND=noninteractive apt-get -y install ${APT_PACKAGES_ESCAPED} curl -fsSL https://mise.run | MISE_INSTALL_PATH="$MISE_INSTALL_PATH" MISE_VERSION="$MISE_VERSION" sh "$MISE_INSTALL_PATH" use -g "$NODE_TOOL" "$MISE_INSTALL_PATH" use -g github:anomalyco/opencode +"$MISE_INSTALL_PATH" use -g "$CLAUDE_CODE_TOOL" +"$MISE_INSTALL_PATH" use -g "$PI_TOOL" "$MISE_INSTALL_PATH" reshim if [[ ! -e /root/.local/share/mise/shims/node ]]; then echo 'node shim not found after mise install' >&2 @@ -419,19 +420,19 @@ if [[ ! -e /root/.local/share/mise/shims/opencode ]]; then echo 'opencode shim not found after mise install' >&2 exit 1 fi -mkdir -p "$NPM_GLOBAL_PREFIX" -NPM_CONFIG_PREFIX="$NPM_GLOBAL_PREFIX" /root/.local/share/mise/shims/npm install -g "$CLAUDE_CODE_PACKAGE" "$PI_PACKAGE" -if [[ ! -e "$NPM_GLOBAL_PREFIX/bin/claude" ]]; then - echo 'claude binary not found after npm install' >&2 +if [[ ! -e /root/.local/share/mise/shims/claude ]]; then + echo 'claude shim not found after mise install' >&2 exit 1 fi -if [[ ! -e "$NPM_GLOBAL_PREFIX/bin/pi" ]]; then - echo 'pi binary not found after npm install' >&2 +if [[ ! -e /root/.local/share/mise/shims/pi ]]; then + echo 'pi shim not found after mise install' >&2 exit 1 fi +ln -snf /root/.local/share/mise/shims/node /usr/local/bin/node +ln -snf /root/.local/share/mise/shims/npm /usr/local/bin/npm ln -snf /root/.local/share/mise/shims/opencode /usr/local/bin/opencode -ln -snf "$NPM_GLOBAL_PREFIX/bin/claude" /usr/local/bin/claude -ln -snf "$NPM_GLOBAL_PREFIX/bin/pi" /usr/local/bin/pi +ln -snf /root/.local/share/mise/shims/claude /usr/local/bin/claude +ln -snf /root/.local/share/mise/shims/pi /usr/local/bin/pi mkdir -p /etc/profile.d cat > /etc/profile.d/mise.sh <<'MISEPROFILE' if [ -n \"\${BASH_VERSION:-}\" ] && [ -x \"$MISE_INSTALL_PATH\" ]; then diff --git a/scripts/make-rootfs-void.sh b/scripts/make-rootfs-void.sh index f8cb9fb..6f65020 100755 --- a/scripts/make-rootfs-void.sh +++ b/scripts/make-rootfs-void.sh @@ -13,7 +13,7 @@ Build an experimental Void Linux rootfs image plus a matching /root work-seed. Defaults: --out ./build/manual/rootfs-void.ext4 - --size 2G + --size 4G --mirror https://repo-default.voidlinux.org --arch x86_64 @@ -345,6 +345,8 @@ set -euo pipefail curl -fsSL https://mise.run | MISE_INSTALL_PATH="$MISE_INSTALL_PATH" MISE_VERSION="$MISE_VERSION" sh "$MISE_INSTALL_PATH" use -g "$NODE_TOOL" "$MISE_INSTALL_PATH" use -g "$OPENCODE_TOOL" +"$MISE_INSTALL_PATH" use -g "$CLAUDE_CODE_TOOL" +"$MISE_INSTALL_PATH" use -g "$PI_TOOL" "$MISE_INSTALL_PATH" reshim if [[ ! -e /root/.local/share/mise/shims/node ]]; then echo "node shim not found after mise install" >&2 @@ -358,19 +360,19 @@ if [[ ! -e /root/.local/share/mise/shims/opencode ]]; then echo "opencode shim not found after mise install" >&2 exit 1 fi -mkdir -p "$NPM_GLOBAL_PREFIX" -NPM_CONFIG_PREFIX="$NPM_GLOBAL_PREFIX" /root/.local/share/mise/shims/npm install -g "$CLAUDE_CODE_PACKAGE" "$PI_PACKAGE" -if [[ ! -e "$NPM_GLOBAL_PREFIX/bin/claude" ]]; then - echo "claude binary not found after npm install" >&2 +if [[ ! -e /root/.local/share/mise/shims/claude ]]; then + echo "claude shim not found after mise install" >&2 exit 1 fi -if [[ ! -e "$NPM_GLOBAL_PREFIX/bin/pi" ]]; then - echo "pi binary not found after npm install" >&2 +if [[ ! -e /root/.local/share/mise/shims/pi ]]; then + echo "pi shim not found after mise install" >&2 exit 1 fi +ln -snf /root/.local/share/mise/shims/node /usr/local/bin/node +ln -snf /root/.local/share/mise/shims/npm /usr/local/bin/npm ln -snf /root/.local/share/mise/shims/opencode /usr/local/bin/opencode -ln -snf "$NPM_GLOBAL_PREFIX/bin/claude" /usr/local/bin/claude -ln -snf "$NPM_GLOBAL_PREFIX/bin/pi" /usr/local/bin/pi +ln -snf /root/.local/share/mise/shims/claude /usr/local/bin/claude +ln -snf /root/.local/share/mise/shims/pi /usr/local/bin/pi EOF cat <<'EOF' | sudo tee "$profile_mise" >/dev/null @@ -400,16 +402,15 @@ MANUAL_DIR="${BANGER_MANUAL_DIR:-$REPO_ROOT/build/manual}" BANGER_BIN="$(resolve_banger_bin)" SSH_KEY="$("$BANGER_BIN" internal ssh-key-path)" OUT_ROOTFS="$MANUAL_DIR/rootfs-void.ext4" -SIZE_SPEC="2G" +SIZE_SPEC="4G" MIRROR="https://repo-default.voidlinux.org" ARCH="x86_64" MISE_VERSION="v2025.12.0" MISE_INSTALL_PATH="/usr/local/bin/mise" NODE_TOOL="node@22" OPENCODE_TOOL="github:anomalyco/opencode" -CLAUDE_CODE_PACKAGE="@anthropic-ai/claude-code" -PI_PACKAGE="@mariozechner/pi-coding-agent" -NPM_GLOBAL_PREFIX="/root/.local/share/banger/npm-global" +CLAUDE_CODE_TOOL="npm:@anthropic-ai/claude-code" +PI_TOOL="npm:@mariozechner/pi-coding-agent" GUESTNET_BOOTSTRAP_SCRIPT="$REPO_ROOT/internal/guestnet/assets/bootstrap.sh" GUESTNET_VOID_CORE_SERVICE="$REPO_ROOT/internal/guestnet/assets/void-core-service.sh" MODULES_DIR=""