# insideR **insideR** (`insider`) makes R package calls transparent, replayable, and editable. It resolves what a call runs, captures the inputs and relevant hidden state, extracts inspectable R code where possible, and produces artifacts that can be reviewed and compared before a change is adopted. insideR is strongest when the behavior of interest is implemented in ordinary R functions, S3 methods, and helper chains that R can inspect. It does not decompile compiled code or make opaque external side effects reproducible. ## Install From a cloned checkout: ``` r install.packages("remotes") remotes::install_local(".") ``` If the GitHub repository is visible to your account, install it directly: ``` r # Set GITHUB_PAT in your environment first if private access is required. remotes::install_github("lennon-li/insider") ``` Do not put a real token in a script or commit it. The package imports `cli`, `codetools`, `methods`, `rlang`, `tools`, and `utils`; `remotes` installs these dependencies as needed. Optional features use packages listed in `Suggests`. ## Quick start This example uses [`stats::fivenum()`](https://rdrr.io/r/stats/fivenum.html), which is available in a standard R installation and needs no data or package-specific setup: ``` r library(insider) x <- c(1, 3, 5, 7, 100) explanation <- explain_call(stats::fivenum(x)) print(explanation) replay_dir <- file.path(tempdir(), "fivenum-replay") unpacked <- unpack_call( stats::fivenum(x), output_dir = replay_dir, overwrite = TRUE ) source(file.path(replay_dir, "replay.R"), chdir = TRUE) scan_secrets(unpacked) ``` [`explain_call()`](https://insider.biostats.ai/reference/explain_call.md) reports dispatch, the inspected call path, replay status, and static risk findings. [`unpack_call()`](https://insider.biostats.ai/reference/unpack_call.md) runs the original call once, captures the values it uses, and creates a replay project. The generated replay checks its result against the captured original result; it may still require the original package or other external dependencies when those boundaries could not be extracted. ## Capabilities ### Understand - `explain_call(expr, max_depth = 5L, eval_dispatch = TRUE)` resolves the executed function or S3 method, walks same-package helpers, and reports replayability and static risk findings. - `trace_call(expr)` observes the shallow runtime path and dispatch boundaries while the call runs, reporting unresolved portions instead of inferring them. - `explain_error(expr)` captures an error-time package traceback when the call fails. - `build_graph(x, cache = TRUE, refresh = FALSE)` indexes an R source directory or installed package. [`graph_search()`](https://insider.biostats.ai/reference/graph_search.md), [`graph_node()`](https://insider.biostats.ai/reference/graph_node.md), [`graph_callers()`](https://insider.biostats.ai/reference/graph_callers.md), and [`graph_callees()`](https://insider.biostats.ai/reference/graph_callees.md) query definitions and call edges. - `explain_function(graph, name)` summarizes a graph node without requiring a concrete call. `build_context(graph, entry, task = NULL, format = c("md", "json"), depth = 1L)` creates compact static context for a named entry point. ### Replay and slice ``` r unpack_call( expr, output_dir, max_depth = 5L, overwrite = FALSE, dispatch = c("candidates", "static"), eval_dispatch = TRUE ) slice_call( expr, output_dir, max_depth = 5L, overwrite = FALSE, dispatch = c("candidates", "static"), eval_dispatch = TRUE ) ``` [`unpack_call()`](https://insider.biostats.ai/reference/unpack_call.md) creates this project shape: ``` text replay_dir/ replay.R # extracted code, input loading, verification customize.R # editable extracted function definitions compare.R # rerun customize.R and compare results insider_manifest.rds # machine-readable metadata data/ *.rds # captured inputs original_result.rds # result from the original call hidden_state.rds # captured options/RNG state when relevant ``` Hidden state is scoped and restored where supported. Behavior-changing options and RNG state are handled when detected; locale, timezone, and other uncaptured state are reported rather than silently promised reproducible. [`slice_call()`](https://insider.biostats.ai/reference/slice_call.md) adds `dependencies.json`, `insider_context.md`, `insider_context.json`, and `validation_plan.md`, and returns an `insider_slice` object. [`resolve_dependencies()`](https://insider.biostats.ai/reference/resolve_dependencies.md) summarizes extracted and unresolved functions, captured objects, packages, compiled boundaries, dispatch candidates, and runtime unknowns. It accepts an `insider_unpack` or `insider_trace` object. JSON artifacts use `jsonlite` with data frames represented as arrays of row objects, named lists represented as objects, and scalar values unboxed. `NA`, typed missing values, `Inf`, `-Inf`, and `NaN` are represented as JSON `null`. Unsupported object classes fail before the artifact is written; nested package artifact classes are serialized through their underlying list representation. ### Graph and change - `change_impact(graph, name, transitive = TRUE)` reports callers, exported APIs reached, risk notes, related tests, and suggested validation commands. - `find_modification_points(graph, name)` ranks reachable functions that may be safer places to customize. - `extract_function(package, name, output_file, max_depth = 5L, dispatch = c("candidates", "static"), overwrite = FALSE)` writes extracted source without invoking the target function. - `diff_versions(package, name = NULL, v1, v2, lib = .libPaths(), timeout = 30, scope = c("exported", "all"))` compares one function (or, with `name = NULL`, every function in `scope`) across two already-installed package versions. Graph nodes have stable qualified identities (`file::function` for source graphs and `package::function` for installed graphs) while retaining short names for display. Short-name queries remain convenient when unique; duplicate names require the qualified identity and are reported as ambiguous otherwise. ### Compare and patch `compare_call(custom_result, original_result, ignore = character(), tolerance = sqrt(.Machine$double.eps))` distinguishes identical results, equality within tolerance, structural differences, and results that are not meaningfully comparable. `compare.R` uses this function after you edit `customize.R`. For in-memory experiments, `with_patch(expr, patches, ignore = character(), tolerance = sqrt(.Machine$double.eps))` temporarily replaces named function bindings for one call, restores them afterward, and compares the result. `propose_change(expr, patches, graph, ignore = character(), tolerance = sqrt(.Machine$double.eps), output_dir = NULL, on_secret = c("redact", "abort"))` combines a temporary patch with graph impact and an advisory validation handoff. Proposal call and error text is redacted by default, including short values assigned to credential-named arguments; use `on_secret = "abort"` to refuse proposal creation when such text is detected. If `output_dir` is supplied, it writes `proposal.md` and `proposal.json` without persisting the raw values. ### Store `insider_store(dir = ".", create = FALSE)` finds or creates a project-local `.insider/` store. Saving is explicit: ``` r store <- insider_store(".", create = TRUE) id <- store_save(store, explanation, label = "fivenum explanation") store_list(store) saved <- store_get(store, id) store_remove(store, id) ``` The store is intended for single-user curation; concurrent writers are not coordinated. [`unpack_call()`](https://insider.biostats.ai/reference/unpack_call.md), [`propose_change()`](https://insider.biostats.ai/reference/propose_change.md), [`bundle()`](https://insider.biostats.ai/reference/bundle.md), and [`diff_versions()`](https://insider.biostats.ai/reference/diff_versions.md) each accept an optional `store = ` (plus `store_label`, `store_tags`) to record their result in one call instead of a separate [`store_save()`](https://insider.biostats.ai/reference/store_save.md) step; the id is attached as the result’s `"store_id"` attribute. Omitting `store` (the default) records nothing. ### Safety - [`explain_call()`](https://insider.biostats.ai/reference/explain_call.md), [`unpack_call()`](https://insider.biostats.ai/reference/unpack_call.md), and related extraction paths perform a static AST-oriented scan of inspected R code for calls that warrant review, such as shell execution, network access, dynamic evaluation, file changes, global-state mutation, and compiled entry points. - `scan_secrets(unpacked)` scans character values in captured `.rds` inputs and generated textual artifacts for common secret-shaped patterns. It reports redacted previews; it does not inspect arbitrary binary objects or guarantee that secrets are absent. - `check_dependency_risk(x, lookup = oysteR_lookup)` checks dependency/version pairs from a dependency report, or package names, through an injectable lookup. The default uses `oysteR` when available; a lookup failure is reported as not checked. These are review aids, not malware detection, complete secret detection, or a security guarantee. Review captured `.rds` files and generated scripts before sharing or executing them. ## Status and limitations The capabilities above are implemented and exported in the current package. insideR is not a replacement for R packages, Git, a debugger, a dependency manager, or a full security scanner. It does not mutate installed package source when applying a temporary patch. Expect partial extraction, unresolved dependencies, or replay differences for: - compiled C/C++/Fortran internals and other opaque boundaries; - complex S4/R6 systems or runtime dispatch that cannot be resolved; - heavy tidy evaluation or non-standard evaluation; - database, API, filesystem, time, locale, timezone, or other external side effects; - Shiny/reactive workflows and parallel execution; - hidden global state that is not captured by the supported state snapshot. Graph edges and dependency classifications are evidence from static analysis, namespace inspection, and (for traces) observed execution. They are not a complete proof of every possible runtime path. Validate any customization with the generated replay, relevant package tests, and `R CMD check` as appropriate. ## Philosophy insideR supports a deliberate promotion path: ``` text local customization -> repeated useful pattern -> documented recipe -> formal option -> package feature ``` Users get visibility and room to experiment, maintainers retain control of the package API, and coding agents receive focused context plus explicit unknowns and validation prompts. # Package index ## Call transparency Open up one package call: see what really runs, extract it into a self-contained, self-verifying replay script. - [`explain_call()`](https://insider.biostats.ai/reference/explain_call.md) : Explain what a package call actually executes - [`unpack_call()`](https://insider.biostats.ai/reference/unpack_call.md) : Unpack a package call into a self-contained, self-verifying replay script - [`extract_function()`](https://insider.biostats.ai/reference/extract_function.md) : Extract a Package Function as Standalone Source - [`compare_call()`](https://insider.biostats.ai/reference/compare_call.md) : Compare a customized call result with the original result - [`with_patch()`](https://insider.biostats.ai/reference/with_patch.md) : Temporarily patch functions inside one call ## Runtime tracing See the actual path one concrete call took, and get a focused explanation when it errors. - [`trace_call()`](https://insider.biostats.ai/reference/trace_call.md) : Trace the runtime path of one call - [`explain_error()`](https://insider.biostats.ai/reference/explain_error.md) : Explain an error from a package call - [`explain_last_error()`](https://insider.biostats.ai/reference/explain_last_error.md) : Explain the most recent error ## Dependency resolution and package slicing Resolve what a call depends on, and export a call-specific package slice with dependency and validation artifacts. - [`resolve_dependencies()`](https://insider.biostats.ai/reference/resolve_dependencies.md) : Resolve the dependencies of an extracted call slice - [`slice_call()`](https://insider.biostats.ai/reference/slice_call.md) : Extract a call-specific package slice and agent context ## Safety checks Scan captured inputs for sensitive-looking values and check dependencies for known CVEs. - [`scan_secrets()`](https://insider.biostats.ai/reference/scan_secrets.md) : Scan unpacked values, binary artifacts, and generated text for sensitive-looking values - [`check_dependency_risk()`](https://insider.biostats.ai/reference/check_dependency_risk.md) : Check package dependencies for known CVEs ## Function explanation Explain an important package function before you have a concrete call to run. - [`explain_function()`](https://insider.biostats.ai/reference/explain_function.md) : Explain a package function - [`build_context()`](https://insider.biostats.ai/reference/build_context.md) : Build agent-facing context for one package entry point ## Change impact and modification advice Assess what changing one function would affect, and find the safest place to intervene. - [`change_impact()`](https://insider.biostats.ai/reference/change_impact.md) : Assess the impact of changing one graph node - [`find_modification_points()`](https://insider.biostats.ai/reference/find_modification_points.md) : Find safer places to modify behavior reached from one node - [`propose_change()`](https://insider.biostats.ai/reference/propose_change.md) : Assemble a change proposal from a temporary patch - [`diff_versions()`](https://insider.biostats.ai/reference/diff_versions.md) : Diff a Package Function (or Every Function) Across Installed Versions - [`bundle()`](https://insider.biostats.ai/reference/bundle.md) : Bundle replay and proposal artifacts into a single shareable handoff ## Persistent store Keep a curated, project-local record of insider analyses under a .insider/ directory, to list and retrieve them across sessions. - [`insider_store()`](https://insider.biostats.ai/reference/insider_store.md) : Resolve or create a project-local insider store - [`store_save()`](https://insider.biostats.ai/reference/store_save.md) : Save one insider artifact into a persistent store - [`store_list()`](https://insider.biostats.ai/reference/store_list.md) : List artifacts recorded in a persistent insider store - [`store_get()`](https://insider.biostats.ai/reference/store_get.md) : Retrieve one artifact from a persistent insider store - [`store_remove()`](https://insider.biostats.ai/reference/store_remove.md) : Remove one artifact from a persistent insider store ## Code graph Index a whole package or source directory into a queryable graph of definitions and call edges. - [`build_graph()`](https://insider.biostats.ai/reference/build_graph.md) : Build a code graph of an R package or source directory - [`graph_search()`](https://insider.biostats.ai/reference/graph_search.md) : Search the code graph for definitions by name - [`graph_node()`](https://insider.biostats.ai/reference/graph_node.md) : Show one definition with its source and line numbers - [`graph_callers()`](https://insider.biostats.ai/reference/graph_callers.md) : Who calls this function? - [`graph_callees()`](https://insider.biostats.ai/reference/graph_callees.md) : What does this function call? ## Package - [`insider`](https://insider.biostats.ai/reference/insider-package.md) [`insider-package`](https://insider.biostats.ai/reference/insider-package.md) : insideR: Make R Package Calls Transparent, Replayable, and Editable # Articles ### Guides - [Getting started: transparent calls](https://insider.biostats.ai/articles/transparent-calls.md): - [The code graph: explore a whole package](https://insider.biostats.ai/articles/code-graph.md):