IDEs and the R Console
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Checked against R 4.6.1 (2026-06-24) on 2026-10-20; R 4.6.2 is scheduled for 2026-10-29. Besides base R, the examples that were run use the here package (1.0.2), the rstudioapi package (0.19.0) and the profvis package (0.4.0) from CRAN. The product pages were read on the same day: the RStudio IDE user guide for release 2026.10.0, the Positron documentation and release notes (the 2026.10 line), the README of the R extension for VS Code (the 3.0 line), the languageserver and IRkernel documentation, and the ESS home page (which names version 26.05.0).
R itself is a console program. Everything on this page is a way of putting a nicer front end on that console: a window that remembers what was typed (the R GUI), an editor that sends lines to it (RStudio, VS Code, Emacs), or a protocol that lets a separate program drive it (Positron and Jupyter). Knowing the console well therefore pays off in every tool, and the first half of the page is about it. The tools are compared at the end in a table. The language side of a session (the workspace, .RData, .Rprofile) is on Sessions, Workspaces and Startup; installing R is on Getting Started; finding help from the console is on Getting Help and Documentation; running scripts from a shell is on Scripts and the Command Line.
For a short list of IDEs and editors with links to their official pages, see IDEs & Tools.
What was run and what was not
Every [source,r] block that has a script behind it was run with Rscript on R 4.6.1 in a throwaway container and linted with the default lintr linters (clean). The scripts that read books.csv start with a setwd() call in the test script only; the page shows read.csv("books.csv") as it would be written in a project. Output is pasted as #> comments, with the container’s platform strings absent from it. Blocks marked "transcript" are real console sessions captured by running R -q --no-save --interactive with the input read from a file (R echoes input that does not come from a terminal, and --interactive makes interactive() true); they are shown in plain text, with prompts, because the prompts are the point. The --interactive runs were made with R’s error messages redirected to standard output so that they stay in order.
Nothing that needs a window was run. There is no display in the verification container, so the R GUI, R.app, RStudio, Positron, VS Code, Jupyter and Emacs steps are checked against the official documentation and each is labelled "documented, not run" where it appears. Menu names, button labels and keyboard shortcuts come from that documentation and can move between releases.
How an IDE talks to R
There are two designs. In the first, the tool owns a terminal-like console and writes text to it: RStudio inserts the lines it runs into its Console pane, the R extension for VS Code sends code to an R terminal, and Emacs ESS drives an inferior R process. In the second, a program that is not a console hosts R and talks to a front end through the Jupyter message protocol: that is how Positron works with its Ark kernel, and how a Jupyter notebook works with IRkernel. Language features (completion, hover, diagnostics) are a separate channel: the Language Server Protocol, served by the languageserver package for VS Code and by Ark inside Positron.
The R GUI on Windows and macOS
The R installers put a small GUI next to the console. It is a console with menus, not an IDE.
Windows: Rgui.exe and Rterm.exe
The Windows build ships two programs (documented, not run). Rgui.exe is a standard Windows GUI program that provides an R console in its own window; it takes the usual R command-line arguments, which are most easily set in the Target field of a shortcut, and the shortcut’s "Start in" field sets the working directory. By default it is an MDI program (one main window with child windows); --sdi gives separate top-level windows. Rterm.exe is the console for a terminal window such as cmd.exe; the R for Windows FAQ says people who work from a terminal usually prefer it, and notes that the R executables are not added to the PATH by default. At a Windows command line R-intro says Rterm.exe is preferred to R.exe. Since R 4.2.0 only 64-bit builds are provided, and R 4.2.0 and later use UTF-8 as the native encoding through the Universal C Runtime, which the FAQ expects to make the old "quotes do not come out right" problem on the console disappear.
What the GUI adds to a plain console, according to the R for Windows FAQ and the README that ships with the installer:
-
Menus on the console, pager and graphics windows: source an R file, load or save a workspace, change directory (
File | Change dir), and shortcuts forhelp,help.start,aproposandls. -
A built-in script editor. The
edit()andfile.edit()help pages call it the"internal"editor, the Windows default foroptions(editor), and say it can have many files open at once with a limit of 50 edit windows. The menu entries and the shortcut for running the current line or selection are in the GUI’s own menus; the online FAQ does not describe them, so they are not quoted here. -
TAB completion in both
RguiandRterm: inside an unterminated quoted string it completes file paths, otherwise R names and, after a function name and parenthesis, argument names. -
Simpler command-line editing than the readline editor of Unix (see the help under
Help | ConsoleforRguiand the fileREADME.RtermforRterm), plus up/down-arrow history. -
Output buffering: the console buffers output and redraws it in chunks, so output from a long loop can look delayed.
Ctrl-Wtoggles buffering, and a call toflush.console()writes the buffer out (FAQ 7.1). -
Resizing the console sets
options(width)to the new width unless that is disabled in theRconsolefile, which also holds the fonts and colours (there is a preferences editor on theEditmenu). -
Escinterrupts a computation inRgui;Ctrl-CorCtrl-Breakdoes inRterm, becauseCtrl-Cis copy in the GUI.
To keep two projects apart, the FAQ (2.9) suggests one shortcut per project with its own "Start in" folder, or double-clicking a saved .RData file in the project folder, which also sets the working directory. A project in RStudio (below) does the same job with less ceremony. In file names the backslash is an escape character in an R string, so use "c:/data/money.dat" or "c:\\data\\money.dat" (R FAQ 7.8).
macOS: R.app
R.app is the macOS GUI, installed with the CRAN binary distribution (documented, not run). The R for macOS FAQ describes a Cocoa program that embeds R as a framework. Its console is a single frame for both input and output. The built-in editor can run code directly: Command-Return executes the current line or selection and Command-E sources the whole file, and there is syntax colouring, brace matching, completion and a function list. When the built-in editor is in use, edit() keeps R waiting for the editing session to finish; with an external editor it cannot. The history is compatible with the history files R writes (default 250 kept entries), and a directory dragged onto the icon becomes the working directory. R.app does not use command-line arguments, and its startup directory is the user’s home directory unless the Preferences say otherwise. The terminal route on macOS is the same R command as on Unix, in Terminal.app. One consequence worth knowing: the IRkernel installation page warns that the R app does not honour PATH changes made in a shell profile, so its kernel set-up has to be run from R started in Terminal.
The terminal console and command-line editing
Start the console with R in a terminal. The prompt is >; when an expression is incomplete (an open parenthesis, brace or quote) R prints the continuation prompt + and waits for the rest. Auto-printing shows the value of every complete top-level expression that is not invisible. q() quits, and in an interactive session R asks whether to save the workspace unless --save or --no-save was given.
Command-line editing
When R was built with the GNU readline library (check with extSoftVersion()), the console has an editor for recall, editing and re-submission of earlier lines; the default is Emacs-style and a ~/.inputrc file customises it. R-intro Appendix C lists the keys. C is the Control key and M the Meta key; if the terminal has no Meta key, press Esc and then the letter.
| Keys | Action |
|---|---|
|
Previous and next command in the history. |
|
Find the last command containing |
|
Start and end of the line. |
|
Back and forward one word. |
|
Back and forward one character. |
|
Delete the character under the cursor, the one before it, or the rest of the word (saved). |
|
Delete to the end of the line (saved) and paste ("yank") the saved text. |
|
Transpose characters; make the rest of the word lower or upper case. |
The history of typed lines is kept in .Rhistory, normally in the directory where R was started or at R_HISTFILE; savehistory(), loadhistory() and history() work on it, and --no-restore-history skips loading it. --no-readline (Unix only) turns the editor off, which is what ESS needs when it runs R inside Emacs. R --interactive does not turn the editor on: it only asserts that the session is interactive. If command-line editing does not work in a terminal build of R, the cause is how R was built: the R FAQ (7.20) says the development version of readline (for example libreadline-dev on Debian) must be installed before R is configured.
Starting R: the command-line options
The options that matter for interactive and scripted use (R-intro, Appendix B):
| Option | Effect |
|---|---|
|
No start-up banner; also sets |
|
Whether the workspace is saved at the end. One of them (or something implying it) is required in non-interactive use. |
|
Do not load |
|
|
|
Run an expression or a file; both imply |
|
As quiet as possible, for programs that use R to compute results; implies |
|
Unix only. Assert that R is interactive even if input is redirected, for example when it is fed by a pipe from an interactive program. |
|
Unix only. No command-line editing. |
|
Everything after it is ignored by R and available through |
Rscript is the front end for running a file or an expression (Rscript file.R arg1 arg2, Rscript -e 'expression'), and R CMD runs the tools: R CMD BATCH runs a file and writes the console transcript to an .Rout file, R CMD INSTALL installs a package, R CMD check checks one. Whether a session is interactive is decided by whether standard input is a terminal; the next block runs the same three lines through a pipe, once as the default (not interactive) and once with --interactive. The bash block is a captured transcript from the container (the empty prompt R prints at the end of its input is omitted).
Rscript -e 'cat(R.version.string, "\n")'
#> R version 4.6.1 (2026-06-24)
printf 'x <- 1:3\nx * 2\ninteractive()\n' | R -q --no-save
#> > x <- 1:3
#> > x * 2
#> [1] 2 4 6
#> > interactive()
#> [1] FALSE
printf 'x <- 1:3\nx * 2\ninteractive()\n' | R -q --no-save --interactive
#> > x <- 1:3
#> > x * 2
#> [1] 2 4 6
#> > interactive()
#> [1] TRUE
Source: R-intro: Invoking R from the command line; R-intro: Scripting with R; R documentation: Rscript
Two details from the scripting section save time. In a script run with Rscript, stdin() refers to the script file; to read the process’s standard input use "stdin" as a file name, as in scan("stdin") or readLines("stdin"). And a short script can be passed with -e (repeatable, but not together with -f).
Running a file from the console
The console evaluates what is typed; a file is run with source(). The behaviour differs from typing in three ways, all spelled out in ?source: the whole file is parsed before any of it is run (so a syntax error means none of it runs); expressions are not evaluated at top level, so nothing is auto-printed; and, by default, the expressions are evaluated in the global environment. echo = TRUE prints each expression after parsing (this is also the advice of R FAQ 7.16, "Why is the output not printed when I source() a file?"), and print.eval defaults to the value of echo. withAutoprint() is the wrapper that evaluates and auto-prints as if at the console.
script <- tempfile(fileext = ".R")
writeLines(
c(
"books <- read.csv(\"books.csv\")",
"nrow(books)",
"range(books$year, na.rm = TRUE)"
),
script
)
# Like a script run by Rscript: no automatic printing
source(script)
# Like typing the lines at the console
source(script, echo = TRUE)
#>
#> > books <- read.csv("books.csv")
#>
#> > nrow(books)
#> [1] 16
#>
#> > range(books$year, na.rm = TRUE)
#> [1] 1813 2023
Source: R documentation: source
The first source(script) prints nothing; the second shows the lines and their values. source(file, chdir = TRUE) changes the working directory to the file’s folder while it runs, which is the usual cure for scripts that read files by relative path. sys.source() is the lower-level function used when loading packages; its default environment is baseenv(), which ?sys.source warns is probably not what you want, so always pass envir. source(file, local = env) does the same for an explicit environment.
script <- tempfile(fileext = ".R")
writeLines(
c(
"loan_days <- 21L",
"is_overdue <- \\(days) days > loan_days"
),
script
)
env <- new.env()
sys.source(script, envir = env)
ls(env)
#> [1] "is_overdue" "loan_days"
exists("is_overdue")
#> [1] FALSE
env$is_overdue(c(7L, 30L))
#> [1] FALSE TRUE
other <- new.env()
source(script, local = other)
identical(ls(other), ls(env))
#> [1] TRUE
exists("is_overdue")
#> [1] FALSE
Source: R documentation: sys.source
To open a file for editing from the console, file.edit("analysis.R") starts the editor named by options(editor), and edit(obj) opens a deparsed copy of an object in it and returns the edited copy; assign the result back or use fix() to change the object itself. Both are documented, not run: they need an editor. On Unix the default editor comes from the EDITOR or VISUAL environment variable and falls back to vi, which is why file.edit() in a bare terminal can open a program the user did not expect; on Windows it is the built-in script editor, and in R.app the document editor is always used.
Console options that shape the session
options() holds the settings that decide how the console looks and where help and editors open. Set them in .Rprofile (see the sessions page). R FAQ 7.7 explains the idiom for changing one temporarily (keep the value that options() returns and restore it with on.exit()) and why .Options must never be assigned to directly.
| Option | What it does |
|---|---|
|
Maximum columns when printing vectors, matrices and arrays, and when |
|
The prompt (default |
|
The text editor for |
|
The HTML browser used by |
|
The command used by |
|
Whether |
|
The default |
|
A function or expression run on a non-catastrophic error; |
op <- options(width = 40)
print(seq(100, 3000, by = 100))
#> [1] 100 200 300 400 500 600 700
#> [8] 800 900 1000 1100 1200 1300 1400
#> [15] 1500 1600 1700 1800 1900 2000 2100
#> [22] 2200 2300 2400 2500 2600 2700 2800
#> [29] 2900 3000
options(op)
getOption("width")
#> [1] 80
getOption("prompt")
#> [1] "> "
getOption("continue")
#> [1] "+ "
getOption("menu.graphics")
#> [1] TRUE
getOption("help_type")
#> NULL
is.character(getOption("editor")) || is.function(getOption("editor"))
#> [1] TRUE
is.character(getOption("browser")) || is.function(getOption("browser"))
#> [1] TRUE
is.character(getOption("pager")) || is.function(getOption("pager"))
#> [1] TRUE
Source: R documentation: options
The values of editor, browser and pager are platform paths, so the example only checks their type. options(op) restores the old values because options() returns the previous settings of whatever it set; that is the idiom for changing an option temporarily.
Interactive and non-interactive sessions
interactive() is TRUE when R assumes a human is at the console: GUI consoles are always interactive, and a terminal session is interactive when standard input is a terminal. Rscript, R -f and R -e are not. R’s own code uses it (help, debugger and install.packages do), and the answer decides how some errors are reported, whether R asks to save the workspace, which graphics device opens and whether graphics devices ask for confirmation of a new page. Code that asks questions has to cope with both kinds of session.
args <- commandArgs(trailingOnly = TRUE)
cat("interactive():", interactive(), "\n")
cat("arguments:", length(args), "\n")
print(args)
title <- readline("Title? ")
print(title)
print(readLines("stdin", n = 1L))
Run as Rscript read-title.R Hello this printed:
interactive(): FALSE
arguments: 1
[1] "Hello"
Title?
[1] ""
character(0)
Source: R documentation: readLines
readline() did not fail and did not wait: in non-interactive use "the result is as if the response was RETURN", so title is "" and the script carries on with an empty answer. readLines("stdin", n = 1L) read the process’s standard input, which was empty here, so it returned character(0). Fed through a pipe, as in echo "The Dispossessed" | Rscript read-title.R Hello, the last line printed [1] "The Dispossessed" and readline() still returned "". So a script that must be usable both ways reads with readLines("stdin") (or takes an argument) and keeps readline() for interactive use behind if (interactive()). menu() is stricter than readline():
genres <- c("Fiction", "Mystery", "Poetry")
choice <- tryCatch(
menu(genres, title = "Genre?"),
error = \(e) conditionMessage(e)
)
choice
#> [1] "menu() cannot be used non-interactively"
if (!interactive()) {
message("Not interactive: using a default instead of asking")
}
#> Not interactive: using a default instead of asking
Source: R documentation: menu
The message() text went to standard error, which the test harness merged into the output.
RStudio IDE
RStudio is an IDE for R (and Python, Quarto and R Markdown) from Posit Software, PBC, formerly RStudio, PBC. The user guide says it is available in open source and commercial editions and runs on the desktop (Windows 11, macOS 14 or later, Linux) or in a browser connected to RStudio Server or Posit Workbench. It requires R 3.6.0 or higher and chooses among installed versions; the guide recommends the community tool rig for managing them (rig rstudio 4.3.0 starts RStudio with a given R). Everything in this section is documented, not run.
Projects
A project ties a folder to a session. File | New Project creates one in a new directory, in an existing directory, or by cloning a Git or Subversion repository, and writes a .Rproj file and a hidden .Rproj.user directory (added to .gitignore when needed). Opening a project starts a new R session, sources the project’s .Rprofile, loads its .RData if the project options say so, loads its .Rhistory into the History pane, sets the working directory to the project folder and restores the open editor tabs. Project options can override the global choices to restore .RData at start-up and to save the workspace on exit.
The practical reason to prefer a project to setwd() at the top of a script is that the working directory is then set by how the session started, not by a path typed on one person’s machine. Paths in the script are relative to the project, so the same script runs on another machine and from a shell. The community package here (1.0.2) formalises that for code that does not run with the project as its working directory: here::here("data", "books.csv") builds a path from the project’s top-level directory (in the example below, the folder with the .Rproj file). The example fakes the "wrong working directory" that a stray setwd() leaves behind.
project <- file.path(tempdir(), "shelf-project")
dir.create(file.path(project, "data"), recursive = TRUE)
invisible(file.copy("books.csv", file.path(project, "data")))
writeLines("Version: 1.0", file.path(project, "shelf-project.Rproj"))
# Pretend an earlier script left the working directory somewhere else
setwd(file.path(project, "data"))
tryCatch(
nrow(read.csv("data/books.csv")),
warning = \(w) conditionMessage(w)
)
#> [1] "cannot open file 'data/books.csv': No such file or directory"
nrow(read.csv(here::here("data", "books.csv")))
#> [1] 16
basename(here::here())
#> [1] "shelf-project"
The panes
The default layout has four panes. Source holds the editor tabs. Console holds the R console (plus Terminal and Background Jobs tabs). The Environment pane has the tabs Environment, History, Connections, Build, VCS and Tutorial; the Output pane has Files, Plots, Packages, Help, Viewer and Presentation. A fifth, Sidebar pane starts hidden, and Tools > Global Options > Pane Layout rearranges them. During debugging, the Environment pane shows the running function’s environment rather than the global one, and the traceback shares its space.
Running code and shortcuts
Code runs from the editor by being inserted into the console, so everything in the first half of this page still applies. The user guide’s shortcut reference gives (Windows and Linux first, macOS in brackets):
| Action | Windows and Linux | macOS |
|---|---|---|
Run the current line or selection |
|
|
Source the current document (with echo) |
|
|
Source the current document |
|
|
Insert the assignment operator |
|
|
Insert the pipe operator |
|
|
Restart the R session |
|
|
Running a selection pastes every line into the console; Source saves the file to a temporary location and sources it from there, which clutters the console less. Source on Save sources the file each time it is saved, which keeps the global copy of a function in step with its file. Inside an R Markdown or Quarto document Ctrl+Shift+Enter runs the current chunk instead. Which operator the pipe shortcut inserts is a Global Options setting that the shortcut reference does not describe.
Debugging
RStudio’s debugger is a front end to the same R tools described in Debugging. A breakpoint can be an editor breakpoint (click to the left of the line number, or Shift+F9), which injects tracing code into the function without changing the file; if the function object does not exist yet or no longer matches the editor, the breakpoint is deferred (a hollow circle) until source() resolves it. A browser() call in the code is the lowest-level breakpoint and works anywhere, but it is part of the code and has to be sourced like any change. debug(f) flags a function to stop on every call, debugonce(f) on the next call only (the guide says it does not recommend leaving debug() set, because it can trap you in the debugger for some special functions), and undebug(f) clears the flag. Debug > On Error switches between the Error Inspector and "Break in Code"; options(error = recover) gives a post-mortem choice of frame at the console, and traceback() prints the call stack of the last error. When code is stopped, the Environment pane shows the running function’s environment (with unevaluated arguments shown as promises), the traceback pane shows the call stack, and the console prompt becomes Browse[1]> with a toolbar for the debug commands. RStudio’s Error Inspector is where its Show Traceback and Rerun with Debug buttons appear; the current user guide documents the setting but not those two labels, so they are not verified here.
The same commands work in any terminal. The next two transcripts were captured with R -q --no-save --interactive and are real; the function is a deliberately buggy loan check, and a character date is the bug. First traceback() and debugonce():
> days_late <- function(loan_date, return_date) {
+ as.integer(return_date - loan_date) - 21L
+ }
> days_late("2026-05-01", "2026-06-01")
Error in return_date - loan_date :
non-numeric argument to binary operator
> traceback()
1: days_late("2026-05-01", "2026-06-01")
> debugonce(days_late)
> days_late(as.Date("2026-05-01"), as.Date("2026-06-01"))
debugging in: days_late(as.Date("2026-05-01"), as.Date("2026-06-01"))
debug at #1: {
as.integer(return_date - loan_date) - 21L
}
Browse[1]> n
debug at #2: as.integer(return_date - loan_date) - 21L
Browse[1]> loan_date
[1] "2026-05-01"
Browse[1]> c
exiting from: days_late(as.Date("2026-05-01"), as.Date("2026-06-01"))
[1] 10
Then post-mortem debugging with options(error = recover); the number 1 picks frame 1, c leaves its browser, and 0 leaves the menu:
> options(error = recover)
> days_late("2026-05-01", "2026-06-01")
Error in return_date - loan_date :
non-numeric argument to binary operator
Enter a frame number, or 0 to exit
1: days_late("2026-05-01", "2026-06-01")
Selection: 1
Called from: top level
Browse[1]> loan_date
[1] "2026-05-01"
Browse[1]> c
Enter a frame number, or 0 to exit
1: days_late("2026-05-01", "2026-06-01")
Selection: 0
> options(error = NULL)
Profiling and the rstudioapi package
RStudio has a Profile menu that starts and stops the profiler and runs a selection with profiling; the viewer is the community package profvis (documentation), and profiles open in a new tab (documented, not run). The base tool underneath is Rprof(), which samples the call stack into a file that summaryRprof() reads. The example below checks the shape of what summaryRprof() returns rather than the timings, which vary by machine; profvis() returns an htmlwidget, which is what opens in the viewer.
overdue_days <- \(n) {
total <- 0
for (i in seq_len(n)) {
total <- total + sqrt(i)
}
total
}
profile_file <- tempfile(fileext = ".out")
Rprof(profile_file, interval = 0.01)
invisible(overdue_days(2e7))
Rprof(NULL)
prof <- summaryRprof(profile_file)
names(prof)
#> [1] "by.self" "by.total" "sample.interval" "sampling.time"
colnames(prof$by.self)
#> [1] "self.time" "self.pct" "total.time" "total.pct"
unlink(profile_file)
# profvis (community package) wraps the same profiler
p <- profvis::profvis(overdue_days(2e6))
inherits(p, "htmlwidget")
#> [1] TRUE
Source: R documentation: Rprof; R documentation: summaryRprof; profvis documentation: profvis() (community package); profvis documentation: RStudio IDE integration
More on what the numbers mean is on Performance, Profiling and Benchmarking.
The community-maintained rstudioapi package (0.19.0) lets code ask the IDE to do things, such as reading the active document. Outside RStudio it is inert, which the guard below shows:
rstudioapi::isAvailable()
#> [1] FALSE
tryCatch(
rstudioapi::getActiveDocumentContext(),
error = \(e) conditionMessage(e)
)
#> [1] "RStudio not running"
Positron
Positron is Posit’s data-science IDE for Python and R. It is built on Code OSS, the foundation of Visual Studio Code, so it accepts VSIX extensions, with data-science features added (documented, not run). Its licensing page says Positron is under the Elastic License 2.0, a source-available licence that is free to use but does not allow hosting it as a service for third parties; its R kernel, language server and formatter are separate components under the MIT licence. Positron’s own wording is "source-available".
For R the important component is Ark, an R kernel written for Positron. Its README says it is a Jupyter kernel (structured input and output between R and a front end, compatible with any front end that speaks the Jupyter protocol), a Language Server Protocol server (completion, jump to definition, references and diagnostics) and a Debug Adapter Protocol server for step-debugging; the LSP and DAP features were available only in Positron when the README was read. The README said editor breakpoints were still missing and pointed to debug(), debugonce() and browser(); check the release notes of the Positron release in use before relying on that. Ark runs R as an interactive session, which is the same state R --interactive produces for a piped terminal; print interactive() in a Positron console to confirm it on a given installation.
The panes the documentation describes:
-
Console: Positron supports multiple interpreter sessions. Console sessions drive the Console pane; notebook sessions belong to a notebook. The Interpreter picker lists the sessions, and one is the active session that completion, diagnostics and code execution use.
-
Variables: the variables of the Python or R session, plus data tables and open connections.
-
Plots, Data Explorer (large data frames in a fast, filterable grid) and Connections panes.
Several R versions can be installed side by side. Positron builds the list shown in the Interpreter picker by searching well-known root folders per operating system, the PATH, well-known executable paths and, on Windows, the registry; the settings positron.r.customRootFolders and positron.r.customBinaries add locations Positron would not find. The configuration is in the documentation page on R installations.
Source: Positron documentation: About Positron; Positron documentation: Licensing; Ark README (Posit documentation); Positron documentation: Managing interpreters; Positron documentation: Discovering R installations; Positron documentation: Variables pane; Positron documentation: Plots pane; Positron documentation: Data Explorer; Positron documentation: Connections pane
VS Code with the R extension
Visual Studio Code is a general editor; R support comes from the community-maintained R extension from the REditorSupport project, not from Microsoft or the R Project (documented, not run). The extension README (3.0 line) lists: an R language service (completion, signature help, outline, formatting, definition, diagnostics, references), sending code to R terminals, a workspace viewer for the attached session’s variables, a help viewer, a data viewer, a plot viewer, R Markdown support, devtools commands and RStudio add-in support. Its quick start is to install R (3.4.0 or later), install the language server, then install the extension:
install.packages("languageserver")
languageserver is a CRAN package that implements the Language Server Protocol for R; the extension’s language service uses it, and the same package serves Neovim, Emacs (eglot or lsp-mode), Sublime Text and others. If the package is missing, R says exactly what any missing package says:
> library(languageserver)
Error in library(languageserver) :
there is no package called ‘languageserver’
Install it into the library of the R that VS Code will use (on Windows the README recommends letting the R installer write its path to the registry). The README’s recommended extras are all community projects, each one line:
-
httpgd: an SVG graphics device served over HTTP and WebSockets, used by the extension’s plot viewer (jgdis a lighter JSON graphics device with native integration). -
radian: an alternative R console for the terminal; the README now points toarf, a modern console with syntax highlighting and multiline editing, as its successor. -
VSCode-R-Debugger: a separate extension that enables VS Code’s debugging facilities for R scripts.
Jupyter and Emacs ESS
Jupyter notebooks can run R through IRkernel (community). After install.packages("IRkernel"), make the kernel visible to Jupyter from R started in a terminal (not the macOS R app, which does not honour shell PATH changes):
install.packages("IRkernel")
IRkernel::installspec()
installspec(user = FALSE) installs the kernel system-wide. Emacs users have ESS, the add-on package whose home page describes support for R and SAS; the R FAQ (6.1 and 6.2) says to run R from ESS "instead of just running it in a console", describes the inferior R mode with readline-like history, object-name completion and syntax highlighting, and lists several ways to debug compiled code from Emacs (6.3). R --no-readline is for ESS, and on Windows Rterm.exe --ess sets Rterm up for it.
Comparing the tools
| Tool | Maintained by | R versions | Debugging | Notebooks | Best for |
|---|---|---|---|---|---|
Rgui.exe or R.app |
R Project (installed with R) |
The R it ships with |
|
No |
First steps, quick checks, a machine with nothing else installed |
Terminal |
R Project |
Whichever |
The console tools |
No |
Servers, shells, scripts, learning the console |
RStudio IDE |
Posit Software, PBC (open source and commercial editions) |
R 3.6.0 or later; picks an installed R |
Editor breakpoints, |
R Markdown and Quarto documents |
Project-based R work, packages, teaching |
Positron |
Posit Software, PBC (Elastic License 2.0) |
Several side by side, chosen per session |
|
Jupyter notebooks, Quarto |
R and Python together; data exploration |
VS Code with the R extension |
REditorSupport community |
R 3.4.0 or later |
Community VSCode-R-Debugger extension |
VS Code notebooks with a Jupyter kernel, R Markdown |
Developers who already use VS Code, remote development |
Jupyter with IRkernel |
IRkernel community |
The R that ran |
Not covered by the sources read here |
Yes |
Notebooks, teaching, sharing results |
Emacs with ESS |
ESS project |
Whichever R Emacs starts |
Inferior R tools, GUD for compiled code (R FAQ 6.3) |
Not covered by the sources read here |
Emacs users, remote shells |
Common errors
A wrong path in source(). This is the most common failure when a script is run from the wrong working directory. source() fails with two messages, and the second, a warning, is the one that names the file (a transcript from the container):
> source("x.R")
Error in file(filename, "r", encoding = encoding) :
cannot open the connection
In addition: Warning message:
In file(filename, "r", encoding = encoding) :
cannot open file 'x.R': No such file or directory
Source: R documentation: source
The next script catches the error and the warning separately, which is the way to test for them in code:
caught <- character()
result <- withCallingHandlers(
tryCatch(
source("no-such-file.R"),
error = \(e) conditionMessage(e)
),
warning = \(w) {
caught <<- c(caught, conditionMessage(w))
invokeRestart("muffleWarning")
}
)
result
#> [1] "cannot open the connection"
caught
#> [1] "cannot open file 'no-such-file.R': No such file or directory"
Source: R documentation: conditions
Check getwd(), use a project, or pass an absolute path; on Windows remember FAQ 7.8 on backslashes.
Smart quotes pasted into the console. Text copied from a web page or word processor often has curly quotes, which are not R syntax. In a UTF-8 session the error shows the first bad character:
> print(“Rivers of Glass”)
Error: unexpected input in "print(“"
Use straight quotes " or '. The same message appears for other non-ASCII characters that look like an operator, such as a non-breaking space or an en dash.
The continuation prompt + that never goes away. An open quote, parenthesis or brace leaves R waiting for more input. In a terminal, Ctrl-C abandons the line (and Esc in Rgui and in RStudio); typing the closing character completes it. A quote left open swallows the following lines as part of the string, as this transcript shows:
> title <- "Rivers of
+ Glass"
> title
[1] "Rivers of\nGlass"
A script that works in the console and fails with Rscript. The causes are in the section above: readline() returns "" without an error, menu() stops with "menu() cannot be used non-interactively", plots may go to a file instead of a window, and interactive()-guarded code does not run. Test a script with Rscript before depending on it.
languageserver not found. The VS Code language features do not start until the package is installed in the R library the extension uses; run install.packages("languageserver") from that R (the transcript above shows the exact text).
Pitfalls
-
Saving and restoring the workspace:
save.image()writes the objects of.GlobalEnvto.RDatain the start-up directory, which is also whatq("yes")does (R FAQ 7.2); restored silently at the next start, it brings back state a script did not create. RStudio’s project options include "Restore .RData into workspace at startup" and a save-on-exit choice, andR --no-restoreor--vanillaskip it from a shell. -
Cleaning the workspace:
rm(list = ls(all.names = TRUE))removes the objects in the active environment (R FAQ 7.3). It does not unload packages, reset options or restore a fresh search path. Restarting R (Ctrl+Shift+F10in RStudio) is the thorough version. -
Output you expect from
source()that never appears: auto-printing does not happen outside the top level, so useprint()orecho = TRUE(R FAQ 7.16). -
Command-line editing that does not work in a self-built R: readline was not available when R was configured (R FAQ 7.20).
-
Console width: the Windows GUI sets
options(width)from the window (FAQ 5.2); set it explicitly withoptions(width = ...)when output from a script should wrap the same way everywhere. -
A Positron console, an RStudio session and a terminal are three different R processes with different libraries and settings; load the same packages and
.Rprofiledeliberately.
Where older tutorials are outdated
Tutorials written before about 2020 describe a landscape that has shifted:
-
They recommend editors such as Tinn-R or the StatET plug-in for Eclipse. This page does not cover them and their current status was not checked; the R FAQ names Emacs with ESS, and the choices that active documentation shows are RStudio, Positron, VS Code and Jupyter.
-
They write "RStudio, Inc." and use "RStudio Server Pro". The company is Posit Software, PBC (formerly RStudio, PBC) and the commercial server product is documented as Posit Workbench. RStudio remains a product name.
-
They put
setwd("C:/Users/me/...")at the top of every script. A project, a relative path orhere::here()removes the machine-specific path. -
They end sessions with "save workspace image? y" and begin scripts with
rm(list = ls()). Both hide the state a script depends on; start from a clean session instead. -
They show R on Windows with non-UTF-8 code pages and 32-bit builds. R 4.1 is the last version that supported 32-bit Windows, and R 4.2.0 and later use UTF-8 as the native encoding, so the console quote problems described for older systems no longer apply.
-
They treat the console as the only place R runs. Positron, VS Code and Jupyter drive R through kernels or language servers rather than a typed console, as the first diagram shows.