---
title: "Skills and plugins"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Skills and plugins}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
A skill teaches a workflow; a prompt template turns a repeated request into a slash command;
an agent definition describes a specialist. A plugin distributes these resources and can add R
tools or MCP servers. Start with Markdown when instructions are enough. See
[Extending gptr](extending-gptr.html) when you need executable behavior.
## Find and use skills
List resources without running plugin code:
``` r
library(gptr)
gptr_skills()
gptr_agents(scope = "project")
gptr_plugins(installed = TRUE)
```
`gptr_skills(scope = c("all", "project", "user", "packages"))` reports each skill's name,
description, source, path, catalog token estimate and visibility. The same scope choices apply
to `gptr_agents()`. A short skill catalog helps the model choose relevant instructions; the body
is loaded on demand. Preload a known skill with `skills = "name"`:
``` r
peter("Review the normalization steps.", skills = "analysis-review")
peter$read("skill:analysis-review/SKILL.md")
peter$read("skill:analysis-review/references/checklist.md")
```
These paths refer to files inside the skill directory. Keep long references and examples in
separate files and tell the skill when to read them. A skill supplies instructions, not a data
snapshot; objects named in its text must still be available to the tools that use them. See
[Execution model](execution-model.html) for the R environment and provider context,
[Language models](language-models.html)
for choosing the model used by these calls, and [Tools and artifacts](tools-and-artifacts.html)
for reading files.
## Write a skill
Put `SKILL.md` in `.gptr/skills/analysis-review/` for a project, or in
`file.path(tools::R_user_dir("gptr", "config"), "skills", "analysis-review")` for your own sessions.
A minimal file is:
```yaml
---
name: analysis-review
description: Review an R analysis for units, missing values and reproducibility.
---
Check the input dimensions and missing values before interpreting results.
Report quantities with units. Read references/checklist.md for the detailed checks.
Ask before changing the analysis.
```
Use a lowercase name of at most 64 characters with letters, digits and hyphens, beginning with
a letter or digit. Avoid a trailing hyphen or consecutive hyphens.
`description` is required and should say when to use the skill. `name` defaults to the folder
name. `disable-model-invocation: true` hides a skill from automatic catalog selection; an
explicit `skills =` preload still works. `allowed-tools` is retained as metadata and does not
grant or restrict permissions by itself.
Project discovery also recognizes `.agents/skills/` and `.claude/skills/`. User discovery includes
the gptr configuration directory and compatible `.agents`, `.claude`, `.codex` and `.pi/agent`
skill directories. Attached packages and enabled plugins can supply skills. For another location,
set `skills.paths`; relative paths belong to the project, while absolute or `~/` paths are user
resources:
``` r
gptr_config(skills = list(paths = "training/skills"), .scope = "project")
gptr_reload()
```
## Prompt templates and project instructions
Save a prompt template as `.gptr/prompts/review.md`, or under the user's gptr `prompts/` directory.
Its file name becomes `/review` in the [interactive console](interactive-console.html):
```yaml
---
description: Review an analysis section
argument-hint: section focus
---
Review $1. Focus on ${2:-reproducibility}. The full request is: $ARGUMENTS
```
For example, `/review "normalization steps" "missing values"` substitutes the two quoted
arguments. `$1`, `$2`, `$ARGUMENTS` and `$@` cover the common forms; `${1:-default}` provides a
fallback, `${@:2:2}` takes a slice, and Claude's `$ARGUMENTS[0]` selects the first argument.
Substitution happens once and does not evaluate R or shell code. Template `model` and
`allowed-tools` fields are retained as metadata; the generated command does not apply them.
An existing slash command wins over a template with the same name.
Use `AGENTS.md` for instructions that apply to a directory rather than a selected workflow.
From the project root to the current directory, gptr takes the first existing file among
`AGENTS.override.md`, `AGENTS.md` and `CLAUDE.md`, and also reads `CLAUDE.local.md`. It includes
user instructions from the gptr configuration directory and `.gptr/vignette.Rmd` when present.
These are instruction data; executable extensions live in a different directory.
## Agent definition files
An agent file is Markdown with required `name` and `description` frontmatter. Save this as
`.gptr/agents/reviewer.md`:
```yaml
---
name: reviewer
description: Check an analysis and report issues without changing files.
model: inherit
tools: [r, read, grep, find, ls]
preset: minimal
max_turns: 8
---
Inspect the supplied objects and files. Give evidence for each issue and suggest a fix.
```
Load a definition by name (or with `file =`); pass it to `agents =` to make the specialist
available:
``` r
reviewer = gptr_agent("reviewer")
peter("Have the reviewer check this analysis.", agents = list(reviewer))
```
Definitions can also set `skills`, `backend`, permission `mode` and a structured `returns`
schema. `gptr_agent()` creates the same records in R. An agent definition does not itself run a
review; execution and object transfer are covered in
[Teams and background work](teams-and-background.html).
Compatible `.claude/agents`, `.codex/agents` and `.pi/agents` directories are discovered too.
## Package a plugin
An R package stores its resources under `inst/gptr/`; the installed directory is `gptr/`.
Add these fields to `DESCRIPTION`:
```text
Imports: gptr
Config/gptr/plugin: true
Config/gptr/api: >= 1.0, < 2
```
A directory plugin instead keeps `plugin.json` at its root. This manifest works for an R package
with an exported factory `gptrlab::gptr_plugin`:
```json
{
"name": "gptrlab",
"version": "0.1.0",
"description": "Analysis review instructions and tools",
"gptr": {"api": ">= 1.0, < 2"},
"skills": "skills",
"prompts": "prompts",
"agents": "agents",
"mcpServers": "mcp.json",
"extension": {
"entry": "gptrlab::gptr_plugin",
"activation": "lazy",
"provides": {"tool": ["gptrlab/add"]},
"declarations": {
"gptrlab/add": {"signature": "add(a, b)", "description": "Add two numbers"}
}
}
}
```
The factory registers the promised records:
``` r
gptr_plugin = function(gptr) {
gptr$require(">= 1.0, < 2")
schema = list(
type = "object", required = I(c("a", "b")),
properties = list(a = list(type = "number"), b = list(type = "number"))
)
gptr$register(gptr::gptr_tool(
"add", "Add two numbers", parameters = schema,
fun = function(a, b) a + b, exposure = "r", namespace = "gptrlab"
))
}
```
Export that function from the package. For a directory plugin, put a factory as the last
expression of each `extensions/*.R` file instead of using a package entry point.
Enable an installed plugin, or an existing directory, for a call:
``` r
peter("Review the analysis.", plugins = "gptrlab")
peter("Review the analysis.", plugins = "./lab-plugin")
gptr_config(plugins = "gptrlab", .scope = "user")
gptr_check("gptrlab", error = TRUE)
```
`gptr_check()` validates a package and can execute its extension factory in a scratch registry;
review its code before checking or enabling it. Listing with `gptr_plugins()` only reads metadata.
R code activates lazily when the manifest declares `extension.provides`, unless activation is
`"eager"`. Without those declarations, code loads eagerly. Resource discovery and code activation
are separate: skills and templates can be available before the package namespace loads.
Claude bundles with `.claude-plugin/plugin.json` can contribute skills, commands, agents and MCP
configuration. gptr reads compatible installed Claude plugin inventories but does not install
plugins for you. Claude hooks and executable Claude plugin behavior are not imported. Supported
root substitutions include `${CLAUDE_PLUGIN_ROOT}` and `${GPTR_PLUGIN_ROOT}` in plugin resources.
See [MCP](mcp.html) for the connection and authentication steps.
## Trust and precedence
Project skills, templates, executable extensions, plugins and MCP servers require project trust.
Review a project before calling `gptr_trust(".", trust = TRUE)`. Untrusted agent definitions have
special restrictions on their model and tools and require interactive confirmation when usable;
unattended runs refuse them. [Configuration](configuration.html) explains the trust boundary.
For the same resource kind and name, session definitions take priority over trusted project
resources, then user resources, plugins and built-ins. Equal-rank collisions keep the first
registration and produce a diagnostic. Built-in permission safeguards remain active. Inspect
`gptr_registry(diagnostics = TRUE)` when a resource is missing or shadowed; `gptr_reload()`
rereads changed resources for later use.
To add instructions for one call, pass a small extension:
``` r
library(gptr)
units = function(gptr) {
gptr$register(gptr_prompt_section("example_units", "Report quantities with units."))
}
```
``` r
session = peter("Report a distance of 3 metres.", extensions = units)
session
```
For recorded workflows that others can replay, see [Script as history](script-as-history.html).