Skip to content

Contribute R path, home, etc. to terminals - #14886

Merged
jmcphers merged 6 commits into
mainfrom
feature/terminal-console-r-version
Aug 1, 2026
Merged

Contribute R path, home, etc. to terminals#14886
jmcphers merged 6 commits into
mainfrom
feature/terminal-console-r-version

Conversation

@jmcphers

Copy link
Copy Markdown
Collaborator

Fixes #7403

Summary

Terminals launched from Positron now use the same R installation as the active console. Previously the terminal always resolved R/Rscript from the system PATH, so on a machine with multiple R versions the terminal ran a different R than the one selected in the console. This also broke extensions that start R in a terminal to do background work (Quarto Preview, Shiny Run App, etc.), since those tasks ran against the system default R rather than the version the user selected.

The R extension now contributes terminal environment variables that point at the active console's R installation:

  • PATH - prepends the directory of the selected R binary so R, Rscript, and anything that shells out to them resolve to the selected version (mirrors how rig exposes a selected R via symlinks on PATH).
  • R_HOME - set so tools that read it directly find the selected installation.
  • QUARTO_R - points at the Rscript directory so quarto render and the bundled Quarto extension use the selected R.
image

The contributed environment is kept in sync as sessions are created, restored, and as the foreground console switches between R versions. When multiple R consoles run different versions, the most recently focused one wins; this ambiguity is expected and documented.

DYLD_LIBRARY_PATH / LD_LIBRARY_PATH are intentionally not contributed, even though the Ark kernel sets them: those affect dynamic linking for every program in the terminal (not just R) and can cause unrelated tools to load R's bundled libraries. R's own launcher scripts already configure their library paths, so they aren't needed for R to work from the terminal.

Note

This does not attempt to address existing issues around environment modules and terminals; if R requires a module load to run, it still may not work in the terminal even after this change. That issue is tracked in #12850.

Release Notes

New Features

  • N/A

Bug Fixes

Validation Steps

@:quarto @:apps @:console

On a system with multiple R versions installed:

  1. Select an R version that is not first on your system PATH as the console interpreter.
  2. Open a new Terminal and run R --version (and Rscript --version) - it should report the version selected in the console, not the system default.
  3. Run Rscript -e 'R.home()' and confirm R_HOME points at the selected installation; check echo $QUARTO_R (or %QUARTO_R% on Windows) points at that R's bin directory.
  4. Switch the foreground console to a different R version, open another Terminal, and confirm it picks up the newly selected version.

Unit coverage for the environment-mutation logic (PATH/R_HOME/QUARTO_R across posix and win32) lives in extensions/positron-r/src/test/terminal-environment.unit.test.ts.

@jmcphers
jmcphers requested a review from jennybc July 15, 2026 17:45
@github-actions

Copy link
Copy Markdown

E2E Tests 🚀
This PR will run tests tagged with: @:critical @:quarto @:apps @:console @:ark

Why these tags?
Tag Source
@:critical Always runs (required)
@:quarto PR description
@:apps PR description
@:console PR description
@:ark Changed files

More on automatic tags from changed files.

readme  valid tags

@jennybc jennybc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm about to delve more into the code and take this for a test drive. But I'll go ahead and post one big-ish observation/question now:

I'm not sure it's necessary or, even, really correct to set the R_HOME env var.

My impression is that R_HOME is an output, not an input. Of an R session (via R.home()) or for a specific R binary (via R RHOME).

Do we know of any tool that reads R_HOME directly from the environment? (I would argue that the tool probably shouldn't do this, but in any case, I'm interested to know if we have something specific in mind.) rig also does not export R_HOME AFAIK.

In a terminal on my machine, R_HOME is not set and my instinct is that that should be true for terminals inside Positron as well.

~ $ echo $R_HOME

~ $ R RHOME
/Library/Frameworks/R.framework/Versions/4.6/Resources
~ $ Rscript -e 'R.home()'
[1] "/Library/Frameworks/R.framework/Versions/4.6/Resources"

Some earlier conversations I've contributed to on this matter:

  • "R_HOME is an output, not an input" point in #12278 (comment)
  • #8453 shows the warning triggered when R_HOME is explicitly set and contradicts an R instance's intrinsic notion of its R_HOME

Update: I've got a dev build up and created this terminal with an active R 4.6 terminal. If I use a rig-supplied shortlink to run the R 4.5 I have, I see this:

~ $ R-4.5-arm64 -q -e 'cat(R.home(), R.version.string, "\n")'
WARNING: ignoring environment value of R_HOME
> cat(R.home(), R.version.string, "
+ ")
/Library/Frameworks/R.framework/Versions/4.5-arm64/Resources R version 4.5.3 (2026-03-11) 

So forcibly setting R_HOME to a specific value means that any other version of R will ignore R_HOME and will complain about it.

I realize not many people would do this. This is more to make the point that I don't see the upside for setting R_HOME, if we're setting PATH to find R and Rscript already and it feels like there's only downside.

@jennybc jennybc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've taken this for a test drive in a dev build and have some peculiar observations. I'll outline what I'm seeing.


Terminal is not associated with the foreground R console version if you don't run any commands in it?

  • Start with no R consoles and no terminals.
  • Start an R console. I choose the current 4.6.
  • Create a new terminal. Use the Terminal: Rename command to name it zsh-r-4.6 to record its origins. Don't do anything in this terminal!
  • Return to console and start another R interpreter. Use R 4.5 this time.
  • Return to terminal and create a new one. Rename it to zsh-r-4.5. Run a probe like which R. I see correct R 4.5 info.
  • Go to the zsh-r-4.6 terminal and run which R. I also see R 4.5 here! It's as if the PATH didn't get adjusted for the R binary until the terminal was used?
  • Go back to the console and foreground R 4.6.
  • Go back to terminal and note that both zsh-r-4.6 and zsh-r-4.5 have the warning about needing to be relaunched.

I'm surprised that the terminal created when R 4.6 is the only console session doesn't get associated with R 4.6, in the case where I didn't use the terminal right away.


Terminal never loses its warning once it gets one, even if you re-foreground the R session it was created with.

  • Start with no R consoles and no terminals.
  • Start an R console. I choose the current 4.6.
  • Create a new terminal. Use the Terminal: Rename command to name it zsh-r-4.6 to record its origins. Run which R. I see correct R 4.6 info.
  • Return to console and start another R interpreter. Use R 4.5 this time.
  • Return to terminal and note that zsh-r-4.6 is now marked with a warning (as it should).
  • Create a new terminal. Rename it to zsh-r-4.5. Run a probe like which R. I see correct R 4.5 info.
  • Go back to the console and foreground R 4.6.
  • Go back to terminal and note that both zsh-r-4.6 and zsh-r-4.5 have the warning about needing to be relaunched.

I would have expected zsh-r-4.6 to revert to healthy / no warning. It feels like once a terminal gets this warning about needing to relaunched, it can never go back?


test('prepends the R binary directory to PATH (windows separator)', () => {
const mutations = getRTerminalEnvironmentMutations(
makeMetadataExtra({ binpath: 'C:/R/R-4.4.0/bin/x64/R.exe' }),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the binpath on Windows probably ends up with backslashes. Would it be a good idea for this fixture to be more realistic?

pth = path.normalize(pth);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 173ec3c!

// exist, the most recently focused one wins; this ambiguity is expected
// (https://github.com/posit-dev/positron/issues/7403).
this._context.subscriptions.push(
positron.runtime.onDidChangeForegroundSession(async (sessionId) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to think about how this relates to the pre-existing handler for onDidChangeForegroundSession()? Should they be combined? Or if not, should they look more similar?

private async didChangeForegroundSession(sessionId: string | undefined): Promise<void> {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think they should be more similar, after evaluating them! I addressed this by adding a new event so that these codepaths agree on when we should be responding to changes. 785ec2d

@jennybc

jennybc commented Jul 29, 2026

Copy link
Copy Markdown
Member

Also, from the original issue:

Do we also want to set RSTUDIO_PANDOC?

@jmcphers

Copy link
Copy Markdown
Collaborator Author

I'm not sure it's necessary or, even, really correct to set the R_HOME env var.

After reading your analysis, I agree with you! I've removed it: 1c20bd1

Terminal is not associated with the foreground R console version if you don't run any commands in it?

This is a "feature" of the VS Code terminal environment variable contribution system. It is able to adjust the environment of a live terminal in place (without a restart) as long as you haven't run any commands in it yet. You can reproduce this behavior by opening a new terminal and setting a value here:

image

As long as you haven't run anything in the terminal, it doesn't get a warning symbol and you can see the variable right away if you echo it. Once you've run commands, you need to restart the terminal to see new values.

Terminal never loses its warning once it gets one, even if you re-foreground the R session it was created with.

This is also a feature of the system (and a less desirable one) and can also be reproduced using the plain old environment variables setting above. Once a terminal is flagged for restart, it can't lose the flag without actually restarting. I don't think it's worth trying to make this upstream feature smarter but LMK if you disagree!

Also, from the original issue: Do we also want to set RSTUDIO_PANDOC?

We already do! This was taken care of a few months ago.

image

@jmcphers
jmcphers requested a review from jennybc July 31, 2026 00:41
@jmcphers
jmcphers merged commit 39d65d7 into main Aug 1, 2026
26 checks passed
@jmcphers
jmcphers deleted the feature/terminal-console-r-version branch August 1, 2026 00:01
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

R version in Terminal doesn't match R version in Console (PATH, QUARTO_R, R_HOME, etc.)

2 participants