hotpatchR is a runtime hotfix utility for locked R package namespaces. It is built for legacy container workflows where a package version is sealed in place and cannot be rebuilt or redeployed.
When R loads a package, it builds a locked namespace. Internal package functions call each other inside that namespace, and the namespace acts as a protective bubble.
That means:
broken_fun() is only visible inside the package namespacecaller_fun() resolves internal calls from that same locked namespacebroken_fun() into the global environment does not update the package’s internal pointerIn practice, this forces a painful current workflow:
This is manual, brittle, and scales badly for large legacy packages.
hotpatchR changes the problem from “global environment hacking” to “namespace surgery.” Instead of copying dependencies into the global environment, it overwrites the function inside the package namespace itself.
Benefits:
inject_patch(pkg, patch_list): overwrite functions inside a package namespace or environmentundo_patch(pkg, names = NULL): restore backed-up originals for patched bindingstest_patched_dir(pkg, test_path): run testthat tests against the modified namespaceapply_hotfix_file(file, pkg = NULL): load a hotfix script and inject the included patch list
library(hotpatchR)
pkg_env <- new.env()
pkg_env$broken_child <- function() "I am broken"
pkg_env$parent_caller <- function() pkg_env$broken_child()
lockEnvironment(pkg_env)
lockBinding("broken_child", pkg_env)
lockBinding("parent_caller", pkg_env)
inject_patch(pkg_env, list(broken_child = function() "I am FIXED"))
pkg_env$parent_caller()
#> "I am FIXED"inject_patch() unlocks the binding inside the target namespace, assigns the replacement function, and then re-locks the binding. This keeps the change local to the package namespace and preserves normal internal function resolution.