gptr runs a language model agent inside your R session. The agent reads files, writes files, evaluates R code written by the model in the environment you give it and starts processes on your behalf. This page describes what gptr does to keep those actions under your control and where its protections end. gptr_egress describes what is sent to model providers.
Everything happens because you asked
Nothing runs when the package is loaded. A model is contacted only when you call peter() (or
a function that you give a prompt), and model-written code is evaluated only in the
environment you pass as envir (by default the frame that called peter()); gptr never
assigns into the global environment by itself. Files are written only inside a .gptr/
directory you created with gptr_init() or confirmed interactively, inside
tools::R_user_dir("gptr"), inside the session temporary directory, into documents you bound
with gptr_doc() or confirmed, and by tool calls that the permission mode allowed. In a
non-interactive run without such consent nothing is written outside the session temporary
directory.
Permission modes
Every tool call passes a permission gate. The default mode is manual: only actions that the
classifier knows to be read-only run without asking; every other action, including any change
to a file or an object, asks first with a one-line prompt. edits also allows file edits
inside the project and still asks before R code that is not known to be read-only; auto
asks only for level-4 actions (for example deleting the project directory, or changing gptr's
own configuration) and for reads of registered secrets; plan changes nothing. When nobody
can answer a question (Rscript, knitr, a scheduled job) the run stops with status blocked
and a gptr_error_permission condition that says how to allow the action, unless you set
options(gptr.noninteractive_ask = "deny"). Model code cannot switch the gate off or loosen
it during a run: the safety options are copied when the run starts. Only the option
gptr.unsafe_no_permissions, set by you outside a run, removes the gate, and it is meant for
disposable sandboxes.
What the gate cannot do
The risk levels come from a static classifier (gptr_risk()). It is advisory and it is not a
security boundary: R code can compute function names, call compiled code or load packages
whose effects the classifier cannot see, and R has no sandbox for code that runs inside your
session. In auto mode a model can delete or overwrite files and objects. Use auto only
in projects you can restore (version control, backups, gptr_rewind() for recent turns),
and run untrusted prompts or untrusted projects in a disposable container or virtual machine.
Sub-agents, workers and child processes
Inline sub-agents run in your session and see its objects. The worker backend runs a
sub-agent in a separate R process that starts from gptr's reduced child environment (it does
not read your ~/.Renviron), but that process runs under your user account with your file
permissions: the worker backend is not an isolation boundary. Its permission requests are
sent to your session and classified again there. MCP servers, the claude and codex
command-line tools, shell commands started with peter$sh() and Shiny artifacts are ordinary
processes of your account as well; artifacts start without any registered secret and listen
on the loopback interface, and each launch gets an access token in its address (on Windows
only when 'openssl' is installed; otherwise gptr says that the artifact has no token).
Untrusted content
Model replies, tool results, file contents, MCP results and project instruction files
(AGENTS.md, CLAUDE.md, .gptr/vignette.Rmd) are treated as data. Text from these sources
is never used as a formatting template, so braces in a reply cannot run R code. A project you
cloned is untrusted until you trust it with gptr_trust(trust = TRUE) (see gptr_trust()),
or answer yes when gptr_init() asks: until then its settings can only tighten
permissions, its extensions, plugins and MCP servers do not run, and its instruction files
are shown to the model as information rather than commands. When trusted files change after a
pull, gptr asks again.
Secrets
Keys are held in a private vault and appear in sessions, logs and errors only as markers such
as [secret:ANTHROPIC_API_KEY]. Values are redacted before anything is written or sent: the
session files, documents, caches, spill files, wire logs and the output of child processes.
gptr never reads the credential files of other tools. Reading a registered secret from model
code asks even in auto mode. A key registered after it already appeared in a file (for
example pasted into a prompt) can be removed from the files with gptr_scrub(); run
gptr_scrub(error = TRUE) before committing to fail when any registered secret remains.
Data at rest and protected health information (PHI)
gptr keeps what it needs to resume and replay work. Review what you commit when the data are personal or clinical:
.gptr/sessions/(full conversations, including printed results) is excluded from git by the.gptr/.gitignorethatgptr_init()writes..gptr/cache/s1/holds System 1 answers and is committed by default so that a script replays without model calls. It stores a salted hash of each input and a hash of each question, never their text, but the answers themselves (a label and its probability) remain, and the salt is committed with the cache, so anyone with the repository can test guesses of short inputs. For PHI, stop committing it withgptr_config(cache_commit = list(s1 = FALSE, s2 = FALSE), .scope = "project")(gptr then keeps a.gitignoreincache/s1/), or clear it withgptr_cache("clear", "s1")before committing..gptr/cache/s2/(answer text for replay),.gptr/transcripts/(console transcripts),.gptr/checkpoints/(pre-images of objects and files) and the data snapshots of artifacts (.gptr/artifacts/<id>/v<n>/data/) are excluded from git by default..gptr/plans/(plans proposed inplanmode) and theapp.Rof each artifact are committed by default; they can quote data values the model saw.Documents you record into keep the model's code and up to
gptr.doc_output_lineslines of printed output per step, which can contain data values. Review them before sharing.
Local servers
gptr_mcp_serve() exposes the live session to other agents over HTTP on 127.0.0.1 only,
with a random bearer token and an Origin check, and every call passes the permission gate.
Any local process that learns the token can call the served tools while the server runs; stop
it with gptr_mcp_serve(stop = TRUE) when you are done.