Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 61 additions & 22 deletions setup-coder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -460,13 +460,44 @@ else
fi
fi

if run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && command -v node' &>/dev/null; then
info "Node.js already available for ${CODER_USER}: $(run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && node --version')"
# Check if nvm has a node version installed (not just system node)
# "nvm current" returns "system" or "none" when no nvm-managed node is active
_nvm_current="$(run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && nvm current' 2>/dev/null || echo "none")"
if [[ "$_nvm_current" != "system" && "$_nvm_current" != "none" && "$_nvm_current" != "N/A" ]]; then
info "Node.js already available via nvm for ${CODER_USER}: ${_nvm_current}"
else
info "Installing Node.js LTS via nvm..."
run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && nvm install --lts'
info "Node.js installed: $(run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && node --version')"
fi

# Node.js 24+ requires C++20 for native module compilation (node-gyp)
# Configure gcc-13 with C++20 flags if needed
_node_major="$(run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && node --version' 2>/dev/null | sed 's/^v//' | cut -d. -f1)"
if [[ "$_node_major" -ge 24 ]] 2>/dev/null; then
# Ensure gcc-13 is installed (supports C++20)
if ! command -v g++-13 &>/dev/null; then
info "Installing g++-13 for Node ${_node_major} C++20 requirement..."
apt-get install -y --no-install-recommends g++-13 gcc-13
fi

# Add C++20 compiler settings to coder's environment if not already set
if ! grep -q 'CXX=.*g++-13' "${CODER_HOME}/.bashrc" 2>/dev/null; then
info "Configuring C++20 compiler for native modules..."
cat >> "${CODER_HOME}/.bashrc" << 'CXXFLAGS_EOF'

# C++20 compiler settings for Node.js 24+ native modules (node-gyp)
export CXX="g++-13"
export CC="gcc-13"
export CXXFLAGS="-std=c++20"
CXXFLAGS_EOF
chown "${CODER_USER}:${CODER_USER}" "${CODER_HOME}/.bashrc"
info "C++20 compiler configured (g++-13)"
else
info "C++20 compiler already configured"
fi
fi

# ---------------------------------------------------------------------------
# Step 5: Install Python ecosystem (uv + ruff + qt-mcp)
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -901,7 +932,13 @@ if [[ -n "${AITOOLS_DIR}" && -d "${AITOOLS_DIR}/coder" ]]; then
chown -R "${CODER_USER}:${CODER_USER}" "${_coder_dst}"

info "Running npm install for coder-mcp..."
run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && cd ~/tools/coder && npm install --omit=dev'
# For Node 24+, explicitly set C++20 compiler (bashrc not sourced in non-interactive shells)
_node_major="$(run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && node --version' 2>/dev/null | sed 's/^v//' | cut -d. -f1)"
if [[ "$_node_major" -ge 24 ]] 2>/dev/null && command -v g++-13 &>/dev/null; then
run_as_coder 'export CXX=g++-13 CC=gcc-13 CXXFLAGS="-std=c++20" NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && cd ~/tools/coder && npm install --omit=dev'
else
run_as_coder 'export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && cd ~/tools/coder && npm install --omit=dev'
fi
info "coder-mcp installed"
fi
else
Expand Down Expand Up @@ -1092,8 +1129,8 @@ else
fi

# --- Git identity (--global defaults; override per-repo with git config user.name/email) ---
_current_git_name="$(sudo -Hu "$CODER_USER" git config --global user.name 2>/dev/null || true)"
_current_git_email="$(sudo -Hu "$CODER_USER" git config --global user.email 2>/dev/null || true)"
_current_git_name="$(sudo -Hu "$CODER_USER" bash -c 'cd && git config --global user.name' 2>/dev/null || true)"
_current_git_email="$(sudo -Hu "$CODER_USER" bash -c 'cd && git config --global user.email' 2>/dev/null || true)"

if [[ -n "$_current_git_name" && -n "$_current_git_email" ]]; then
info "Git identity: ${_current_git_name} <${_current_git_email}>"
Expand Down Expand Up @@ -1121,15 +1158,15 @@ else
read -r _git_email
_git_email="${_git_email:-$_git_email_default}"
fi
sudo -Hu "$CODER_USER" git config --global user.name "$_git_name"
sudo -Hu "$CODER_USER" git config --global user.email "$_git_email"
sudo -Hu "$CODER_USER" bash -c "cd && git config --global user.name '$_git_name'"
sudo -Hu "$CODER_USER" bash -c "cd && git config --global user.email '$_git_email'"
info "Git identity: ${_git_name} <${_git_email}>"
fi

# --- SSH commit signing ---
# Only offer when SSH public keys were discovered from the primary user
if [[ ${#_pub_keys[@]} -gt 0 ]]; then
_current_signing_key="$(sudo -Hu "$CODER_USER" git config --global user.signingkey 2>/dev/null || true)"
_current_signing_key="$(sudo -Hu "$CODER_USER" bash -c 'cd && git config --global user.signingkey' 2>/dev/null || true)"

if [[ -n "$_current_signing_key" ]]; then
info "SSH signing already configured: ${_current_signing_key}"
Expand Down Expand Up @@ -1181,10 +1218,10 @@ if [[ ${#_pub_keys[@]} -gt 0 ]]; then
chown "${CODER_USER}:${CODER_USER}" "$_coder_sign_key"
chmod 644 "$_coder_sign_key"

sudo -Hu "$CODER_USER" git config --global gpg.format ssh
sudo -Hu "$CODER_USER" git config --global user.signingkey "$_coder_sign_key"
sudo -Hu "$CODER_USER" git config --global commit.gpgsign true
sudo -Hu "$CODER_USER" git config --global tag.gpgsign true
sudo -Hu "$CODER_USER" bash -c "cd && git config --global gpg.format ssh"
sudo -Hu "$CODER_USER" bash -c "cd && git config --global user.signingkey '$_coder_sign_key'"
sudo -Hu "$CODER_USER" bash -c "cd && git config --global commit.gpgsign true"
sudo -Hu "$CODER_USER" bash -c "cd && git config --global tag.gpgsign true"
info "SSH signing enabled: ${_sign_basename} → commits & tags"
fi
fi
Expand Down Expand Up @@ -1304,10 +1341,10 @@ check() {
shift
if "$@" &>/dev/null; then
info "PASS: ${desc}"
(( PASS++ ))
(( ++PASS )) || true
else
err "FAIL: ${desc}"
(( FAIL++ ))
(( ++FAIL )) || true
fi
}

Expand Down Expand Up @@ -1359,23 +1396,25 @@ check "cratedex.service is active" \
check "${CODER_USER} has ruff" \
test -x "${CODER_HOME}/.local/bin/ruff"

# Node.js
# Node.js (use -H to set HOME correctly for nvm)
check "${CODER_USER} has node" \
bash -c "sudo -u ${CODER_USER} -i bash -c 'export NVM_DIR=\"\$HOME/.nvm\" && . \"\$NVM_DIR/nvm.sh\" && node --version'"
bash -c "sudo -Hu ${CODER_USER} bash -c 'export NVM_DIR=\"\$HOME/.nvm\" && . \"\$NVM_DIR/nvm.sh\" && node --version'"

# Agent CLIs
check "${CODER_USER} has Claude Code CLI" \
bash -c "sudo -u ${CODER_USER} -i bash -c 'command -v claude'"
sudo -u "${CODER_USER}" test -x "${CODER_HOME}/.local/bin/claude"

check "${CODER_USER} has OpenAI Codex CLI" \
bash -c "sudo -u ${CODER_USER} -i bash -c 'export NVM_DIR=\"\$HOME/.nvm\" && . \"\$NVM_DIR/nvm.sh\" && command -v codex'"
bash -c "sudo -Hu ${CODER_USER} bash -c 'export NVM_DIR=\"\$HOME/.nvm\" && . \"\$NVM_DIR/nvm.sh\" && command -v codex'"

check "${CODER_USER} has Google Gemini CLI" \
bash -c "sudo -u ${CODER_USER} -i bash -c 'export NVM_DIR=\"\$HOME/.nvm\" && . \"\$NVM_DIR/nvm.sh\" && command -v gemini'"
bash -c "sudo -Hu ${CODER_USER} bash -c 'export NVM_DIR=\"\$HOME/.nvm\" && . \"\$NVM_DIR/nvm.sh\" && command -v gemini'"

# MCP tools
check "coder-mcp installed" \
test -f "${CODER_HOME}/tools/coder/bin/coder-mcp.js"
# MCP tools (only check coder-mcp if AITOOLS_DIR was set or it was installed manually)
if [[ -n "${AITOOLS_DIR:-}" || -d "${CODER_HOME}/tools/coder" ]]; then
check "coder-mcp installed" \
test -f "${CODER_HOME}/tools/coder/bin/coder-mcp.js"
fi

check "github-mcp image available" \
run_as_coder 'podman image exists ghcr.io/github/github-mcp-server'
Expand Down
Loading