Installation
Set up Roughly in VS Code, Zed, RStudio, or on the command line
Roughly runs as an editor extension (the comfortable way) or as a standalone CLI (for scripts and CI). Pick whichever fits; they are the same binary underneath.
VS Code (recommended)
Section titled “VS Code (recommended)”Install the Roughly extension from the VS Code Marketplace. The extension bundles the Roughly CLI for Linux x86_64, macOS aarch64, and Windows x86_64, so there is nothing else to set up.
On another architecture, install the CLI separately and point the extension at it with the
roughly.pathsetting (see the language server page).
Install the R extension (Zed has no built-in R support), then the Roughly extension from Zed’s extension registry.
To also get Roughly’s
#:annotation highlighting in Zed, enable LSP semantic tokens for R — see the language server page.
Command line
Section titled “Command line”Use the CLI directly for formatting and linting in CI, with RStudio, or to back an editor extension on a platform without a bundled binary. Install it in whichever way suits you — a prebuilt binary, or from source with Cargo.
Prebuilt binary (Linux, macOS, and Windows):
- Download the binary for your platform from the GitHub Releases page.
- Add it to your system
PATH.
With Cargo, if you have a Rust toolchain:
cargo install --git https://github.com/felix-andreas/roughly roughlyRStudio (formatter only)
Section titled “RStudio (formatter only)”You can configure Roughly as an external formatter in RStudio:
-
Open RStudio and navigate to:
Options > Code > Formatting > Format with an External ToolSet the reformat command to:
path/to/roughly fmt -
To enable format-on-save, go to:
Options > Code > Saving > Format with an External ToolCheck the
Reformat documents on saveoption.
The CLI has three commands:
# Format R files (rewrites in place)roughly fmt # format files in the current directoryroughly fmt path/to/files # format files at a specific pathroughly fmt --check # list files that would change, exit 1 (for CI)roughly fmt --diff # show the diff without writing
# Lint and type-checkroughly check # check files in the current directoryroughly check path/to/filesroughly check --output json # one JSON object per diagnostic (for CI)roughly check --min-severity error # only errors render and affect the exit code
# Run the language server (for editors that speak LSP)roughly serverroughly check runs the linter by default. To also surface type errors and unused-variable
warnings, opt in through roughly.toml:
[check]typing = true # report type errorsunused = true # report unused local variablesType inference itself is always on and powers editor features like hover and inlay hints — the
settings above only control which diagnostics roughly check reports.
Machine-readable output
Section titled “Machine-readable output”roughly check --output json writes one JSON object per diagnostic to stdout (JSON
Lines); progress and error messages stay on stderr, so stdout is pure JSON:
{"path":"R/utils.R","line":2,"column":3,"endLine":2,"endColumn":7,"severity":"error","code":"syntax-error","message":"Syntax Error: unexpected \"<- (\""}line/column/endLine/endColumn are 1-based, severity is "error" or "warning", and
code is the diagnostic’s stable code. related lists the locations a diagnostic points at beyond
its own range — for example, each “overwrites an earlier top-level binding” warning names the
sibling binding site — as {path, line, column, endLine, endColumn, message} objects (empty when a
diagnostic stands alone). These field names are a contract — safe to build CI on.
Exit codes
Section titled “Exit codes”roughly check and roughly fmt share one scheme:
| Code | Meaning |
|---|---|
| 0 | Clean — no diagnostics (check); nothing to change (fmt) |
| 1 | Findings — any diagnostic, warnings included (check); files that would be reformatted (fmt --check, fmt --diff) |
| 2 | Usage, configuration, or I/O error |
A warnings-only check run exits 1 by default; pass --min-severity error to gate on errors only.
Next steps
Section titled “Next steps”- Typing guide — how inference and
#:annotations work - Formatter, Linter, and Language Server references
- Configuration — every
roughly.tomloption