gptr runs language model agents inside your live R session, using in-memory compute. They work with objects you already loaded and reuse your variables and intermediate results across turns. With enough available memory, this includes datasets around 4 GB or larger. Load a dataset once, analyze it by name, and rerun the step you want to change. One function, peter(), is an interactive chat in the console and a programmable call that you put in scripts, loops and if statements.
The model receives bounded descriptions, previews and tool output; the R tool computes on the full object in your session. See vignette("execution-model", package = "gptr") for memory and data-sharing details.
-
One function.
peter()with no prompt opens a chat at the console; with a prompt it runs the agent and returns the session, which the pipe steers:peter("...") |> peter("..."). -
System 1 and System 2. Conversational models (Anthropic, OpenAI, Google Gemini, OpenAI-compatible endpoints, Ollama, and the Claude Code and Codex CLIs) run agents; typed decision models such as TypeSafe AI’s Jev and Clef return yes/no, choice and score answers that go straight into
ifandfor. -
The script is the history. gptr can record executed agent code into your
.R,.Rmd,.qmdor.ipynbdocument. Fresh recorded blocks replay without model calls; supply their required input data and packages when replaying in a fresh session. - Everything is R. Tools are R functions; artifacts are Shiny apps; skills, MCP servers, sub-agents, hooks and plugins use one documented extension API.
-
Safe defaults. The default
manualmode runs read-only actions and asks before changes. The permission gate is not a sandbox; see?gptr_security.
Read the guides and function reference online.
Installation
Install gptr from GitHub’s main branch with R 4.2 or later:
install.packages("pak") # if pak is not installed
pak::pak("Broccolito/gptr@main")This README documents gptr 1.0. CRAN submission is being prepared.
install.packages("gptr") installs the CRAN version, which may still expose the older 0.7 API. Check packageVersion("gptr") before following these examples. No model server or CLI is required for the offline examples below.
Connect a model
For an interactive first session, sign in to the Claude Code CLI or the Codex CLI outside R, then call peter(); with no default model it offers to save one. See vignette("interactive-console", package = "gptr").
Choose a provider explicitly before your first real call. API credentials and CLI sign-in are separate routes; see vignette("language-models").
gptr_env("~/keys/.env") # provider keys, e.g. OPENAI_API_KEY
gptr_providers() # what is configured
gptr_config(model = "openai/gpt-6-sol", .scope = "session")
peter() # chat in the consoleA first session
With a configured model, tell Peter what to do:
library(gptr)
session = peter("Fit mpg from wt in mtcars. Save the model as fit.", mtcars)
session |> peter("Plot fit's residuals and explain what they show.")The pipe continues the same session. The usual permission checks apply.
Run this pattern offline
This scripted model needs no key or server. It supplies the tool code rather than generating it.
library(gptr)
fake = gptr_fake_provider(list(
list(tool = "r", input = list(code = "fit = lm(mpg ~ wt, data = mtcars)\ncoef(fit)")),
"Each 1000 lb of weight lowers mpg by about 5.3.",
list(tool = "r", input = list(code = "predicted = predict(fit)\nhead(predicted)")),
"The predictions are stored in predicted."
))
work = new.env()
session = peter("Fit mpg from wt in mtcars. Save the model as fit.", mtcars,
model = fake, envir = work, mode = auto)
session$text
#> [1] "Each 1000 lb of weight lowers mpg by about 5.3."
ls(work)
#> [1] "fit"
session |> peter("Reuse fit to predict mpg for the same cars.")
#> The predictions are stored in predicted.
#> idle . fake/fake-1 . 2 turns . 6.7k tokens . $0.0000 . s188d555d79
head(work$predicted)
#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive
#> 23.28261 21.91977 24.88595 20.10265
#> Hornet Sportabout Valiant
#> 18.90014 18.79325
session$turns
#> [1] 2The second turn reuses fit.
The same pattern works with a large object already in your workspace. This recipe does not allocate or load a 4 GB dataset:
# counts is a numeric matrix, around 4 GB, already loaded in this R session.
session = peter(
"Compute colSums(counts) as totals and return the six largest totals.",
counts
)
session |> peter("Reuse totals to plot their distribution.")A System 1 question returns a typed R vector with the probabilities attached:
Offline typed-decision example
judge = gptr_fake_provider(list(0.93, 0.08), name = "judge", type = "classifier")
abstracts = c(a = "We randomized 200 adults to drug or placebo.",
b = "We followed a cohort of nurses for 20 years.")
is_rct = peter("Is this abstract about a randomized controlled trial?", abstracts,
model = judge)
as.logical(is_rct)
#> a b
#> TRUE FALSE
gptr_prob(is_rct)
#> a b
#> 0.93 0.08Local models with Ollama
Installed Ollama chat models run agents, for example model = "ollama/qwen3:1.7b". Clef and Clef Flash (Ollama 0.35.1 or later) return typed decisions, for example model = "ollama/clef-flash". gptr never installs Ollama or downloads models, and by default never falls back to a cloud model; a workflow stays local only if every model and tool it uses is local.
Exporting recorded R
A synchronized .R history can become an ordinary R script or a script of peter() calls:
gptr_doc("analysis.R", sync = TRUE)
gptr_export("analysis.R", "analysis-raw.R")
gptr_export("analysis.R", "analysis-peter.R", format = "peter")The default keeps recorded R executable and turns peter() calls into comments. The format = "peter" output keeps calls active and recorded code inert, with bounded output and notes beside the turns. Both preserve ordinary source and refuse stale or ambiguous records. Export does not run or verify the result, recover unrecorded console work, or save your input objects. See vignette("script-as-history", package = "gptr") for interleaved R and a second session.
Learn more
Start with vignette("getting-started", package = "gptr"). Most guides include a runnable offline example. Recipes that need a real provider, MCP server or external program are shown without running them.
| Task | Guide |
|---|---|
| Understand the name and ideas behind Peter | vignette("why-peter") |
| Choose a language model; call Peter from functions and scripts | vignette("language-models") |
| Make logical, choice and score decisions | vignette("system-one") |
Chat, use slash commands, or run inline R with !
|
vignette("interactive-console") |
| Set defaults, permissions, paths and runtime options | vignette("configuration") |
| Record, replay and summarize a workflow | vignette("script-as-history") |
| Run teams, fan-outs, background sessions and the session SDK | vignette("teams-and-background") |
| Use R, files, shell, Python, SQL and Shiny apps | vignette("tools-and-artifacts") |
| Reuse skills, templates, agent files and plugins | vignette("skills-and-plugins") |
| Connect MCP servers or expose an R session | vignette("mcp") |
| Write tools, providers, policies and hooks | vignette("extending-gptr") |
| Understand execution, environments and result objects | vignette("execution-model") |
| Inspect usage, budgets, caching and compaction | vignette("token-efficiency") |
The function reference documents the exported APIs. In R, use help(package = "gptr"), ?peter, ?gptr_export, ?gptr_options, ?gptr_security and ?gptr_egress.
Why Peter?
The package is gptr; you talk to its agent through peter(). The name honors two Peters:
- Peter Naur, the Danish computer scientist who edited the ALGOL 60 report and helped develop the syntax notation now called Backus-Naur Form. His work connects to gptr’s readable R code and history documents.
- Peter Cathcart Wason, the cognitive psychologist who, with Jonathan Evans, studied dual processes in reasoning and the difference between a response and its conscious justification. His work connects to inspecting results, evidence and explanations.
gptr calls typed decision models “System 1” and conversational agents “System 2”. These are software roles; they do not imply human cognition or that Wason introduced those labels. The vignette("why-peter", package = "gptr") guide gives the history and primary sources.
Upgrading from gptr 0.7.0
gptr 1.0.0 is a complete rewrite. get_response() and dataframe_to_text() were removed: use peter("your prompt")$text instead of get_response(), and pass a data frame to peter() as context instead of converting it to text. See NEWS.md.
Acknowledgments
The tool descriptions, edit semantics and prompt-template grammar are derived from ‘pi’ by Mario Zechner (MIT license). The model catalog is derived from models.dev (MIT license) and the secret patterns from gitleaks (MIT license); see inst/COPYRIGHTS. Ideas were borrowed from ‘ellmer’, ‘tidyllm’, ‘btw’ and ‘mcptools’, none of which gptr depends on. Anthropic, OpenAI, Google, TypeSafe AI, Ollama and the vendors of the command-line tools are third-party services; gptr is not affiliated with or endorsed by them.
