Why this package exists
Ravel is meant to feel closer to an analysis copilot than a generic chat box. The point is not just to answer a question about R syntax. The point is to reason with the current script, the selected code, the loaded objects, the models already in memory, the surrounding project, and the reporting workflow.
Workflow 1: diagnose a model that technically runs but feels wrong
Imagine you just fit a model and the output looks suspicious. Coefficients are huge, standard errors are unstable, or the interaction terms are hard to explain.
fit <- lm(mpg ~ wt * am, data = mtcars)
ravel::ravel_summarize_model(fit)
#> $name
#> [1] "fit"
#>
#> $class
#> [1] "lm"
#>
#> $formula
#> [1] "mpg ~ wt * am"
#>
#> $fit
#> $fit$n
#> [1] 32
#>
#> $fit$aic
#> [1] 157.476
#>
#> $fit$bic
#> [1] 164.8046
#>
#> $fit$r_squared
#> [1] 0.8330375
#>
#> $fit$adj_r_squared
#> [1] 0.8151486
#>
#> $fit$sigma
#> [1] 2.591247
#>
#>
#> $coefficients
#> # A tibble: 4 × 5
#> term estimate std_error statistic p_value
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 (Intercept) 31.4 3.02 10.4 4.00e-11
#> 2 wt -3.79 0.786 -4.82 4.55e- 5
#> 3 am 14.9 4.26 3.49 1.62e- 3
#> 4 wt:am -5.30 1.44 -3.67 1.02e- 3Ravel is designed for prompts like:
Explain this model in plain English, tell me how the interaction changes the interpretation of the main effects, and list the next diagnostics I should run before I trust it.
cat(ravel::ravel_interpret_model(fit))
#> Model type: lm.
#> Formula: mpg ~ wt * am.
#> The model explains about 83.3% of the observed variance (R-squared = 0.833).
#> Term `am` has a positive association (estimate = 14.878) with statistical evidence at the 0.05 level.
#> Term `wt:am` has a negative association (estimate = -5.298) with statistical evidence at the 0.05 level.
#> Term `wt` has a negative association (estimate = -3.786) with statistical evidence at the 0.05 level.
#> Interaction terms are present (wt:am), so main effects should be interpreted conditionally.
ravel::ravel_suggest_diagnostics(fit)
#> [1] "Inspect residuals versus fitted values for non-linearity and heteroskedasticity."
#> [2] "Review a Q-Q plot of residuals for heavy tails or strong departures from normality."
#> [3] "Check leverage and Cook's distance for influential observations."
#> [4] "Consider multicollinearity diagnostics if predictors are strongly related."Workflow 2: turn analysis output into Quarto writing
Once you already have a fitted object, the next bottleneck is often writing. Ravel can help scaffold methods, results, and diagnostics sections without leaving the IDE.
cat(ravel::ravel_draft_quarto_section("results", model = fit))#> ## Results
#>
#> ```{r results}
#> # Fit or summarize the final model here
#> ```
#>
#> Model type: lm.
#> Formula: mpg ~ wt * am.
#> The model explains about 83.3% of the observed variance (R-squared = 0.833).
#> Term `am` has a positive association (estimate = 14.878) with statistical evidence at the 0.05 level.
#> Term `wt:am` has a negative association (estimate = -5.298) with statistical evidence at the 0.05 level.
#> Term `wt` has a negative association (estimate = -3.786) with statistical evidence at the 0.05 level.
#> Interaction terms are present (wt:am), so main effects should be interpreted conditionally.
For a more diagnostics-heavy turn:
Draft a Quarto diagnostics section for this model, summarize the main caveats, and include a chunk for the checks I should run next.
cat(ravel::ravel_draft_quarto_section("diagnostics", model = fit))#> ## Diagnostics
#>
#> ```{r diagnostics}
#> # Produce diagnostic plots or checks here
#> ```
#>
#> Model type: lm.
#> Formula: mpg ~ wt * am.
#> The model explains about 83.3% of the observed variance (R-squared = 0.833).
#> Term `am` has a positive association (estimate = 14.878) with statistical evidence at the 0.05 level.
#> Term `wt:am` has a negative association (estimate = -5.298) with statistical evidence at the 0.05 level.
#> Term `wt` has a negative association (estimate = -3.786) with statistical evidence at the 0.05 level.
#> Interaction terms are present (wt:am), so main effects should be interpreted conditionally.
#>
#> Suggested checks:
#> - Inspect residuals versus fitted values for non-linearity and heteroskedasticity.
#> - Review a Q-Q plot of residuals for heavy tails or strong departures from normality.
#> - Check leverage and Cook's distance for influential observations.
#> - Consider multicollinearity diagnostics if predictors are strongly related.
Workflow 3: ask for a safe code change instead of blindly running it
Ravel stages actions before execution, which matters for analysis work where a small change can silently alter results.
action <- ravel::ravel_preview_code("
summary(mtcars$mpg)
quantile(mtcars$mpg)
")
action$label
#> [1] "Run generated R code"You can then approve and run it explicitly:
approved <- ravel::ravel_approve_action(action)
ravel::ravel_run_code(approved)
#> $success
#> [1] TRUE
#>
#> $output
#> [1] " Min. 1st Qu. Median Mean 3rd Qu. Max. "
#> [2] " 10.40 15.43 19.20 20.09 22.80 33.90 "
#> [3] " 0% 25% 50% 75% 100% "
#> [4] "10.400 15.425 19.200 22.800 33.900 "
#>
#> $warnings
#> character(0)
#>
#> $messages
#> character(0)
#>
#> $value
#> 0% 25% 50% 75% 100%
#> 10.400 15.425 19.200 22.800 33.900
#>
#> $error
#> NULLWorkflow 4: use object-aware context instead of re-explaining everything
When Ravel inspects the current session, it can summarize data frames, models, formulas, and other objects directly.
analysis_objects <- list(
data = mtcars,
formula = mpg ~ wt * am,
model = fit
)
lapply(analysis_objects, ravel::ravel_summarize_object)
#> $data
#> $data$name
#> [1] "X[[i]]"
#>
#> $data$kind
#> [1] "data.frame"
#>
#> $data$class
#> [1] "data.frame"
#>
#> $data$rows
#> [1] 32
#>
#> $data$cols
#> [1] 11
#>
#> $data$columns
#> [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
#> [11] "carb"
#>
#> $data$column_types
#> [1] "numeric" "numeric" "numeric" "numeric" "numeric" "numeric" "numeric"
#> [8] "numeric" "numeric" "numeric" "numeric"
#>
#> $data$preview
#> [1] " mpg cyl disp hp drat wt qsec vs am gear carb\nMazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4\nMazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4\nDatsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1"
#>
#>
#> $formula
#> $formula$name
#> [1] "X[[i]]"
#>
#> $formula$kind
#> [1] "formula"
#>
#> $formula$class
#> [1] "formula"
#>
#> $formula$formula
#> [1] "mpg ~ wt * am"
#>
#>
#> $model
#> $model$name
#> [1] "X[[i]]"
#>
#> $model$class
#> [1] "lm"
#>
#> $model$formula
#> [1] "mpg ~ wt * am"
#>
#> $model$fit
#> $model$fit$n
#> [1] 32
#>
#> $model$fit$aic
#> [1] 157.476
#>
#> $model$fit$bic
#> [1] 164.8046
#>
#> $model$fit$r_squared
#> [1] 0.8330375
#>
#> $model$fit$adj_r_squared
#> [1] 0.8151486
#>
#> $model$fit$sigma
#> [1] 2.591247
#>
#>
#> $model$coefficients
#> # A tibble: 4 × 5
#> term estimate std_error statistic p_value
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 (Intercept) 31.4 3.02 10.4 4.00e-11
#> 2 wt -3.79 0.786 -4.82 4.55e- 5
#> 3 am 14.9 4.26 3.49 1.62e- 3
#> 4 wt:am -5.30 1.44 -3.67 1.02e- 3
#>
#> $model$kind
#> [1] "model"This enables prompts like:
Summarize the objects I have loaded, tell me which one looks like the main modeling artifact, and propose the next analysis step.
Workflow 5: review analytical code, not just syntax
Ravel is also designed for prompts that depend on the active editor and project-level context:
Use the selected code and the current project context to tell me whether this refactor changes results or just changes style.
Summarize the latest analysis diff and tell me what I should validate before I merge it.
Convert this selected tidyverse pipeline to base R, but keep it readable and consistent with the rest of the file.
These are exactly the kinds of tasks where a project-aware assistant feels different from a plain browser chat.
Workflow 6: start inside RStudio
The intended flow is:
install.packages("ravel")
library(ravel)
ravel::ravel_setup_addin()
ravel::ravel_chat_addin()Once the addin is open, Ravel can answer questions like:
- Why did this join fail with the currently loaded objects?
- Explain these coefficients as if I had to present them.
- Draft a results paragraph from the model I just fit.
- Suggest diagnostics for this glm() before I report it.
- Turn this selected code into a safer, simpler version.
What the package is aiming for
The long-term goal is not to mimic a chat website inside RStudio. It is to make RStudio feel like it has an analysis-aware copilot that understands:
- code
- context
- models
- diagnostics
- git state
- reproducible writing
- safe execution
That is the difference Ravel is trying to push.