Note
The majority of this codebase was generated by AI. While it lacks the manual scrutiny of hand-crafted code, we still rely on it daily.
loadfast is an R package for interactive development on large R packages. It is intended as a drop-in replacement for devtools::load_all() when reload time is a bottleneck.
For a given package path, loadfast performs a full load on the first call, then uses MD5-based change detection to re-source only changed R/ files on subsequent calls.
loadfast is intended for the edit-reload-test loop, not as a general replacement for devtools::load_all(). The main tradeoff is described in Important limitation: incremental reload does not clean up stale symbols.
At runtime, loadfast does not depend on pkgload or devtools. Its main runtime dependency is rlang.
Install from GitHub with either pak or remotes:
pak::pkg_install("finccam/loadfast")
# or
remotes::install_github("finccam/loadfast")Call load_fast() from a package root or from any path inside a package:
loadfast::load_fast()
# or
loadfast::load_fast("path/to/your/package")load_fast() reads the package name from DESCRIPTION, builds a namespace, processes NAMESPACE imports, sources R/ files, attaches the package to the search path, and optionally sources testthat helpers.
It supports packages that rely on standard R namespace behavior, including imports, S4 classes, and R6 classes.
load_fast() supports the following arguments:
helpers = TRUEto sourcehelper*.Rfiles fromtests/testthat/when testthat is availableattach_testthat = NULLto auto-detect whethertestthatshould be attachedfull = TRUEto force a complete teardown and rebuildverbose = TRUEto emit per-phase timing logs
If runtime code needs a specific file to be re-sourced on the next load, call load_fast_register_reload() to register that file for reload. This is useful for runtime patching and temporary method overrides.
If renv.lock changes between incremental loads for the same package path, load_fast() warns. Dependency changes may require restarting R or reinstalling packages.
Reloading the loadfast package resets the in-memory loader state, so the next load_fast() call for a package path performs a full load.
For performance, the incremental path does not track which symbols came from which file and does not remove stale objects when files are deleted or functions are removed.
This is a conscious tradeoff, not a claim that cleanup is impossible in principle. We have not found a performant enough implementation yet for the large-project use case loadfast targets. Approaches based on per-file symbol diffing and repeated enumeration of large namespaces were too slow.
After an incremental reload:
- deleted files can leave old objects behind
- removed variables or functions can remain available in the loaded package until you force a full rebuild
Use full = TRUE after deleting files, removing functions, or whenever you need a clean namespace state.
There is a known compatibility bug when multiple packages are loaded in the same R session with loadfast and one package calls code from another package.
In particular, when package A is loaded and package B is then loaded, calling a function from B that depends on A can fail with:
Error in function_in_a() : object 'lazydata' not foundAfter installation, the addin is available from the Addins menu as LOADFAST > Load Fast.
To bind it to a keyboard shortcut:
- Open
Tools > Modify Keyboard Shortcuts - Filter for
Load fast - Assign the shortcut you want
You can bind loadfast::load_fast() directly in keybindings.json:
{
"key": "ctrl+shift+l",
"command": "workbench.action.terminal.sendSequence",
"args": {
"text": "loadfast::load_fast()\n"
},
"when": "editorTextFocus && editorLangId == 'r' || terminalFocus"
}You can bind loadfast::load_fast() in the Zed keymap:
"ctrl-shift-l": [
"workspace::SendKeystrokes",
# note: you also need to add a command to focus the terminal first
"l o a d f a s t : : l o a d _ f a s t ( )"
]This repository uses a custom test harness.
Run the full test suite with:
Rscript test_loadfast.RRun only matching checks by setting LOADFAST_TEST_FILTER. The value is treated as a regular expression matched against each check description.
Example:
LOADFAST_TEST_FILTER="inter-pkg|dep-order" Rscript test_loadfast.R