Skip to contents

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 if and for.
  • The script is the history. gptr can record executed agent code into your .R, .Rmd, .qmd or .ipynb document. 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 manual mode 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 console

A 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] 2

The 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.08

Local 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.