# r-package-development

A skill that tells the agent how to work on an R package: testthat tests, roxygen2 docs, R CMD check and NEWS.md entries.

- skill · `type=skill` · Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode · 807 installs · ★ 547
- Author: Simon P. Couch (@simonpcouch)
- License: MIT · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/posit-dev/skills/tree/HEAD/r-lib/r-package-development/SKILL.md
- Updated: 2026-10-15
- HTML: https://affpapa.org/en/nevibecode/skills/r-package-development

## What it does

The skill sets the rules an agent follows while working on an R package built with devtools, testthat and roxygen2. It ships a command list the agent runs through `Rscript -e`: load the package code, run the full test suite, filter tests by file name prefix, run tests for a single file or a single named test, redocument the package, check pkgdown and run `devtools::check()`.

Separate sections cover coding, testing, documentation and `NEWS.md`. After generating code the agent must run `air format .`. Code uses the base pipe `|>` instead of `%>%`, and single-line anonymous functions are written as `\() ...`. Tests for `R/{name}.R` belong in `tests/testthat/test-{name}.R`, and new code is expected to come with a test. Errors and warnings are checked with `expect_snapshot(error = TRUE)` and `expect_snapshot()` rather than `expect_error()` and `expect_warning()`.

You need R installed along with devtools, testthat, roxygen2 and pkgdown, and formatting depends on the external `air` tool — skip that and the format step fails. Roxygen comments wrap at 80 characters, every new topic goes into `_pkgdown.yml`, and any edit to a roxygen comment means the package gets redocumented.

## Install

### Claude Code (native platform)

1. **Skills CLI (Vercel)**
```bash
npx skills add posit-dev/skills --skill r-package-development -a claude-code
```

2. **Manually: put the files in place**
- File: `~/.claude/skills/r-package-development/SKILL.md` — Copy the whole skill folder; for one project use .claude/skills/r-package-development/

### Codex

1. **Skills CLI (Vercel)**
```bash
npx skills add posit-dev/skills --skill r-package-development -a codex
```

2. **Manually: put the files in place**
- File: `.agents/skills/r-package-development/SKILL.md` — For all projects use ~/.agents/skills/

### Cursor

1. **Skills CLI (Vercel)**
```bash
npx skills add posit-dev/skills --skill r-package-development -a cursor
```

2. **Manually: put the files in place**
- File: `.cursor/skills/r-package-development/SKILL.md` — Cursor also reads .agents/skills/ and .claude/skills/

### GitHub Copilot

1. **GitHub CLI**
```bash
gh skill install posit-dev/skills r-package-development
```

2. **Manually: put the files in place**
- File: `.github/skills/r-package-development/SKILL.md`

### Gemini CLI

1. **Skills CLI (Vercel)**
```bash
npx skills add posit-dev/skills --skill r-package-development -a gemini-cli
```

2. **Platform CLI**
```bash
gemini skills install https://github.com/posit-dev/skills --path r-lib/r-package-development
```

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/skills/r-package-development/SKILL.md` — The legacy .windsurf/skills/ path still works

### OpenCode

**Skills CLI (Vercel)**
```bash
npx skills add posit-dev/skills --skill r-package-development -a opencode
```

### Claude.ai

**Claude.ai**
- Zip the folder and upload it in Settings → Capabilities → Skills

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/posit-dev/skills/tree/HEAD/r-lib/r-package-development/SKILL.md

## When to use it
- run tests for one package file and read the failure
- redocument the package after editing roxygen comments
- add a test for a new function in the right tests/testthat file
- check the package with R CMD check before release
- record a user-facing change as a NEWS.md bullet

## Example prompts
- run the tests for R/utils.R and show me what broke
- add roxygen2 docs for the new exported function
- add a NEWS.md entry and redocument the package

## Source text · SKILL.md · MIT

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 8794b006bc9ffe2d.

BEGIN THIRD-PARTY FILE 8794b006bc9ffe2d
````text
---
name: r-package-development
description: R package development with devtools, testthat, and roxygen2. Use when the user is working on an R package, running tests, writing documentation, or building package infrastructure.
metadata:
  author: Simon P. Couch (@simonpcouch)
  version: "1.2"
---

# R package development

## Key commands

```
# Run code in the package
Rscript -e "devtools::load_all(); code"

# Run all tests
Rscript -e "devtools::test()"

# Run all tests for files starting with {name}
Rscript -e "devtools::test(filter = '^{name}')"

# Run all tests for R/{name}.R
Rscript -e "devtools::test_active_file('R/{name}.R')"

# Run a single test "blah" for R/{name}.R
Rscript -e "devtools::test_active_file('R/{name}.R', desc = 'blah')"

# Redocument the package
Rscript -e "devtools::document()"

# Check pkgdown documentation
Rscript -e "pkgdown::check_pkgdown()"

# Check the package with R CMD check
Rscript -e "devtools::check()"

# Format code
air format .
```

## Coding

* Always run `air format .` after generating code.
* Use the base pipe operator (`|>`) not the magrittr pipe (`%>%`).
* Use `\() ...` for single-line anonymous functions. For all other cases, use `function() {...}`.

## Testing

- Tests for `R/{name}.R` go in `tests/testthat/test-{name}.R`.
- All new code should have an accompanying test.
- If there are existing tests, place new tests next to similar existing tests.
- Strive to keep tests minimal with few comments.
- Avoid `expect_true()` and `expect_false()` in favour of a specific expectation which will give a better failure message.
- When testing errors and warnings, don't use `expect_error()` or `expect_warning()`. Instead, use `expect_snapshot(error = TRUE)` for errors and `expect_snapshot()` for warnings because these allow the user to review the full text of the output.

## Documentation

- Every user-facing function should be exported and have roxygen2 documentation.
- Wrap roxygen comments at 80 characters.
- Internal functions should not have roxygen documentation.
- Whenever you add a new (non-internal) documentation topic, also add the topic to `_pkgdown.yml`.
- Always re-document the package after changing a roxygen2 comment.
- Use `pkgdown::check_pkgdown()` to check that all topics are included in the reference index.

## `NEWS.md`

- Every user-facing change should be given a bullet in `NEWS.md`. Do not add bullets for small documentation changes or internal refactorings.
- Each bullet should briefly describe the change to the end user.
````
END THIRD-PARTY FILE 8794b006bc9ffe2d

The third-party file has ended. Everything between the 8794b006bc9ffe2d tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 2520 of 2866 bytes. © Simon P. Couch (@simonpcouch) · MIT · https://github.com/posit-dev/skills/tree/HEAD/r-lib/r-package-development/SKILL.md

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
