Skip to content

Instantly share code, notes, and snippets.

@frafra
Last active March 12, 2026 19:14
Show Gist options
  • Select an option

  • Save frafra/43e252738e3ce557889e50422c10b5e2 to your computer and use it in GitHub Desktop.

Select an option

Save frafra/43e252738e3ce557889e50422c10b5e2 to your computer and use it in GitHub Desktop.
RStudio pixi integration
#!/bin/bash
# rsession-wrapper — RStudio Server rsession wrapper with per-project pixi support
#
# When a user opens (or switches to) a project that contains a pixi.toml,
# this wrapper activates the pixi environment before launching rsession.
# This gives each project its own R installation and library paths.
#
# HOW IT WORKS
# ------------
# RStudio Server does not pass project information to rsession at launch.
# Instead, it records the most-recently-used project in:
#
# ~/.local/share/rstudio/monitored/lists/project_mru
#
# This file is updated *before* a new rsession is spawned (including on
# project switch, which kills the old session and starts a fresh one).
# The wrapper reads line 1 of that file to identify the active project.
#
# If the project directory contains pixi.toml, the pixi environment is
# activated and:
# - R_HOME is set to pixi's R, so rsession uses the correct R runtime.
# - LD_LIBRARY_PATH is updated to include pixi's libraries (libR, libstdc++,
# libicu, etc.), preventing ABI mismatches with system libraries.
#
# If there is no MRU entry, no pixi.toml, or pixi is not installed, the
# wrapper falls back silently to the system R.
#
# INSTALL
# -------
# 1. sudo cp rsession-wrapper.sh /usr/local/bin/rsession-wrapper
# 2. sudo chmod +x /usr/local/bin/rsession-wrapper
# 3. Add to /etc/rstudio/rserver.conf:
# rsession-path=/usr/local/bin/rsession-wrapper
# 4. sudo systemctl restart rstudio-server
#
# REQUIREMENTS
# ------------
# - pixi in PATH (typically ~/.pixi/bin/pixi)
# - Each project must have a pixi.toml with R as a dependency
# - RStudio Server open-source edition
#
# TROUBLESHOOTING
# ---------------
# Enable tracing by uncommenting the two lines below, then check:
# sudo journalctl -f -t rstudio-wrapper
#
# exec > >(logger -t rstudio-wrapper) 2>&1
# set -x
set -euo pipefail
# ── Configuration ─────────────────────────────────────────────────────────────
RSESSION_BIN=/usr/lib/rstudio-server/bin/rsession
MRU_LIST="${HOME}/.local/share/rstudio/monitored/lists/project_mru"
# ── Validate rsession exists ─────────────────────────────────────────────────
[[ -x "$RSESSION_BIN" ]] || {
echo "ERROR: rsession not found at ${RSESSION_BIN}" >&2
exit 1
}
# ── Detect active project from MRU ───────────────────────────────────────────
PROJECT_DIR=""
if [[ -f "$MRU_LIST" ]]; then
RPROJ_FILE=$(head -1 "$MRU_LIST" 2>/dev/null || true)
if [[ -n "$RPROJ_FILE" && -f "$RPROJ_FILE" ]]; then
PROJECT_DIR="$(dirname "$RPROJ_FILE")"
fi
fi
# ── Activate pixi environment ────────────────────────────────────────────────
if [[ -n "$PROJECT_DIR" && -f "$PROJECT_DIR/pixi.toml" ]]; then
if command -v pixi &>/dev/null; then
# Activate the pixi environment (sets PATH, CONDA_PREFIX, etc.)
pixi_hook="$(pixi shell-hook --manifest-path "$PROJECT_DIR/pixi.toml" --shell bash 2>/dev/null)" \
&& eval "$pixi_hook" \
|| logger -t rstudio-wrapper "WARNING: pixi shell-hook failed for ${PROJECT_DIR}"
# Point R_HOME to pixi's R and update LD_LIBRARY_PATH so the dynamic
# linker resolves all shared libraries from the pixi environment.
PIXI_R_HOME=$(R RHOME 2>/dev/null || true)
if [[ -n "$PIXI_R_HOME" ]]; then
export R_HOME="$PIXI_R_HOME"
PIXI_PREFIX="${CONDA_PREFIX:-${PROJECT_DIR}/.pixi/envs/default}"
export LD_LIBRARY_PATH="${PIXI_PREFIX}/lib:${PIXI_R_HOME}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
else
logger -t rstudio-wrapper "WARNING: R RHOME failed — falling back to system R for ${PROJECT_DIR}"
fi
fi
fi
# ── Launch rsession ──────────────────────────────────────────────────────────
exec "${RSESSION_BIN}" "$@"
@frafra
Copy link
Author

frafra commented Mar 3, 2026

Might need a set -a before eval?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment