From d14ef5f867de651a47222a05d39714fd2733bf57 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 21 Jul 2026 08:47:59 -0400 Subject: [PATCH] fix: apply hermit env directly in node shims so a fish login shell doesn't break MCP startup (#10028) Co-authored-by: Claude Opus 4.8 Co-authored-by: Douwe M Osinga --- ui/desktop/src/bin/jbang | 29 +++++++++++++++++++++--- ui/desktop/src/bin/node-setup-common.sh | 30 ++++++++++++++++++++----- ui/desktop/src/bin/uvx | 29 +++++++++++++++++++++--- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/ui/desktop/src/bin/jbang b/ui/desktop/src/bin/jbang index c06b64276..54631052b 100755 --- a/ui/desktop/src/bin/jbang +++ b/ui/desktop/src/bin/jbang @@ -66,11 +66,31 @@ mkdir -p "${MCP_HERMIT_DIR}/bin" log "Changing to directory ${MCP_HERMIT_DIR}." cd "${MCP_HERMIT_DIR}" +download_hermit_binary() { + local HERMIT_TMP + HERMIT_TMP=$(mktemp "${MCP_HERMIT_DIR}/bin/hermit.XXXXXX") + if curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \ + | gzip -dc > "${HERMIT_TMP}" && chmod +x "${HERMIT_TMP}"; then + mv "${HERMIT_TMP}" "${MCP_HERMIT_DIR}/bin/hermit" + else + rm -f "${HERMIT_TMP}" + return 1 + fi +} + +activate_hermit_environment() { + if ! HERMIT_ENV=$(hermit env --shell=bash --activate 2>> "${LOG_FILE}"); then + log "Hermit does not support bash activation. Updating hermit binary." + download_hermit_binary + HERMIT_ENV=$(hermit env --shell=bash --activate 2>> "${LOG_FILE}") + fi + eval "${HERMIT_ENV}" >> "${LOG_FILE}" 2>&1 +} + # Check if hermit binary exists and download if not if [ ! -f "${MCP_HERMIT_DIR}/bin/hermit" ]; then log "Hermit binary not found. Downloading hermit binary." - curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \ - | gzip -dc > "${MCP_HERMIT_DIR}/bin/hermit" && chmod +x "${MCP_HERMIT_DIR}/bin/hermit" + download_hermit_binary log "Hermit binary downloaded and made executable." else log "Hermit binary already exists. Skipping download." @@ -117,12 +137,15 @@ fi # Activate the environment with output redirected to log if [[ "$(uname -s)" == "Linux" ]]; then log "Activating hermit environment." - { . "bin/activate-hermit"; } >> "$LOG_FILE" 2>&1 + activate_hermit_environment fi # Install OpenJDK using hermit log "Installing OpenJDK with hermit." hermit install openjdk@17 >> "$LOG_FILE" +if [[ "$(uname -s)" == "Linux" ]]; then + activate_hermit_environment +fi # Download and install jbang if not present if [ ! -f "${MCP_HERMIT_DIR}/bin/jbang" ]; then diff --git a/ui/desktop/src/bin/node-setup-common.sh b/ui/desktop/src/bin/node-setup-common.sh index 86c8da17b..bae46c61b 100755 --- a/ui/desktop/src/bin/node-setup-common.sh +++ b/ui/desktop/src/bin/node-setup-common.sh @@ -76,11 +76,31 @@ log "Changing to directory ${MCP_HERMIT_DIR}." cd "${MCP_HERMIT_DIR}" +download_hermit_binary() { + local HERMIT_TMP + HERMIT_TMP=$(mktemp "${MCP_HERMIT_DIR}/bin/hermit.XXXXXX") + if curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \ + | gzip -dc > "${HERMIT_TMP}" && chmod +x "${HERMIT_TMP}"; then + mv "${HERMIT_TMP}" "${MCP_HERMIT_DIR}/bin/hermit" + else + rm -f "${HERMIT_TMP}" + return 1 + fi +} + +activate_hermit_environment() { + if ! HERMIT_ENV=$(hermit env --shell=bash --activate 2>> "${LOG_FILE}"); then + log "Hermit does not support bash activation. Updating hermit binary." + download_hermit_binary + HERMIT_ENV=$(hermit env --shell=bash --activate 2>> "${LOG_FILE}") + fi + eval "${HERMIT_ENV}" >> "${LOG_FILE}" 2>&1 +} + # Check if hermit binary exists and download if not if [ ! -f "${MCP_HERMIT_DIR}/bin/hermit" ]; then log "Hermit binary not found. Downloading hermit binary." - curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \ - | gzip -dc > "${MCP_HERMIT_DIR}/bin/hermit" && chmod +x "${MCP_HERMIT_DIR}/bin/hermit" + download_hermit_binary log "Hermit binary downloaded and made executable." else log "Hermit binary already exists. Skipping download." @@ -134,14 +154,14 @@ fi # Activate the environment with output redirected to log. # Activation must run on every platform: macOS GUI apps otherwise never get the # hermit-managed node/npx onto PATH, so STDIO extensions fail with -# "env: node: No such file or directory". The Linux-only guard was introduced in -# #5372 to "preserve existing behavior" on macOS, but that path is now broken. +# "env: node: No such file or directory". log "Activating hermit environment." -{ . "bin/activate-hermit"; } >> "${LOG_FILE}" 2>&1 +activate_hermit_environment # Install Node.js using hermit log "Installing Node.js with hermit." hermit install node >> "${LOG_FILE}" +activate_hermit_environment # Verify installations log "Verifying installation locations:" diff --git a/ui/desktop/src/bin/uvx b/ui/desktop/src/bin/uvx index db6e0c067..af77d1ce7 100755 --- a/ui/desktop/src/bin/uvx +++ b/ui/desktop/src/bin/uvx @@ -66,11 +66,31 @@ mkdir -p "${MCP_HERMIT_DIR}/bin" log "Changing to directory ${MCP_HERMIT_DIR}." cd "${MCP_HERMIT_DIR}" +download_hermit_binary() { + local HERMIT_TMP + HERMIT_TMP=$(mktemp "${MCP_HERMIT_DIR}/bin/hermit.XXXXXX") + if curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \ + | gzip -dc > "${HERMIT_TMP}" && chmod +x "${HERMIT_TMP}"; then + mv "${HERMIT_TMP}" "${MCP_HERMIT_DIR}/bin/hermit" + else + rm -f "${HERMIT_TMP}" + return 1 + fi +} + +activate_hermit_environment() { + if ! HERMIT_ENV=$(hermit env --shell=bash --activate 2>> "${LOG_FILE}"); then + log "Hermit does not support bash activation. Updating hermit binary." + download_hermit_binary + HERMIT_ENV=$(hermit env --shell=bash --activate 2>> "${LOG_FILE}") + fi + eval "${HERMIT_ENV}" >> "${LOG_FILE}" 2>&1 +} + # Check if hermit binary exists and download if not if [ ! -f "${MCP_HERMIT_DIR}/bin/hermit" ]; then log "Hermit binary not found. Downloading hermit binary." - curl -fsSL "https://github.com/cashapp/hermit/releases/download/stable/hermit-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/').gz" \ - | gzip -dc > "${MCP_HERMIT_DIR}/bin/hermit" && chmod +x "${MCP_HERMIT_DIR}/bin/hermit" + download_hermit_binary log "Hermit binary downloaded and made executable." else log "Hermit binary already exists. Skipping download." @@ -123,7 +143,7 @@ fi # Activate the environment with output redirected to log if [[ "$(uname -s)" == "Linux" ]]; then log "Activating hermit environment." - { . "bin/activate-hermit"; } >> "$LOG_FILE" 2>&1 + activate_hermit_environment fi # Initialize python >= 3.10 @@ -133,6 +153,9 @@ hermit install python3@3.10 >> "$LOG_FILE" # Install UV for python using hermit log "Installing UV with hermit." hermit install uv >> "$LOG_FILE" +if [[ "$(uname -s)" == "Linux" ]]; then + activate_hermit_environment +fi # Verify installations log "Verifying installation locations:"