Skip to content

Add the "reprexes" skill (.claude/skills/reprexes)#282

Open
d-morrison wants to merge 9 commits into
mainfrom
add-reprexes-skill
Open

Add the "reprexes" skill (.claude/skills/reprexes)#282
d-morrison wants to merge 9 commits into
mainfrom
add-reprexes-skill

Conversation

@d-morrison

Copy link
Copy Markdown
Member

Summary

Adds a project-level Claude Code skill at .claude/skills/reprexes/SKILL.md.

reprexes captures a debugging workflow: when a technical problem is hard to pin down, isolate it into a minimal reproducible example ("reprex") and iterate candidate fixes on that fast, clean loop instead of inside the full application — then port the fix back. Includes the R/Quarto reprex package workflow (reprex::reprex(), venue / session_info / std_out_err).

References: https://r4ds.hadley.nz/workflow-help.html#making-a-reprex, https://reprex.tidyverse.org/.

Vendoring it here makes it available to collaborators and the @claude CI bot in this repo (previously it lived only in a personal user-level config).

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings May 27, 2026 02:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a repository-local Claude Code skill (reprexes) documenting a workflow for isolating bugs into minimal reproducible examples (reprexes), with specific guidance for R and Quarto debugging.

Changes:

  • Added a new .claude skill definition and documentation for creating and iterating on reprexes.
  • Included R/Quarto-specific recommendations, including use of the {reprex} package and targeted quarto render workflows.

Comment thread .claude/skills/reprexes/SKILL.md Outdated
Comment on lines +20 to +21
payoff is real: ~80% of the time, the act of building a thorough reprex
surfaces the cause on its own — the noise you strip away was hiding it.
Comment thread .claude/skills/reprexes/SKILL.md Outdated
Comment on lines +109 to +110
- When the bug might be **version-dependent**, capture `sessionInfo()` (or
run `tidyverse_update()`) in the reprex so versions are part of the record.
@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1-2-g6ad689f

QR code for preview link

🚀 View preview at
https://UCD-SERG.github.io/lab-manual/pr-preview/pr-282/

Built to branch gh-pages at 2026-06-17 17:26 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Copilot AI review requested due to automatic review settings May 27, 2026 04:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.

Comment thread .claude/skills/reprexes/SKILL.md Outdated
Comment on lines +68 to +70
`Rscript /tmp/reprex.R` (a fresh process — no stale `globalenv()` state
masking or faking the bug). For a Quarto page, render just that file:
`quarto render /tmp/reprex.qmd --to html`, not the whole site.
Comment thread .claude/skills/reprexes/SKILL.md Outdated
Comment on lines +98 to +100
Copy the code and call `reprex::reprex()` (reads the clipboard by default),
or point it at a file with `reprex(input = "/tmp/reprex.R")` — handy from a
non-interactive CLI session where there's no clipboard. Useful arguments:
Comment on lines +122 to +123
- When the bug might be **version-dependent**, capture `sessionInfo()` (or set
`session_info = TRUE` above) in the reprex so versions are part of the
@d-morrison

Copy link
Copy Markdown
Member Author

@claude review

@claude

claude Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 1m 18s —— View job


Code Review

  • Gather context
  • Read SKILL.md file
  • Review for correctness, clarity, and best practices
  • Post review findings

Overall: This is a well-structured, accurate, and practical skill document. The workflow is sound, the R-specific details are correct, and the guidance is actionable. Two issues from the existing Copilot review comments remain unaddressed and are worth fixing before merge.


Issues to fix

1. Namespace inconsistency — reprex(input = ...) vs. reprex::reprex() (line 99)

The file introduces the function as reprex::reprex() (line 98) but then immediately drops the namespace qualifier:

reprex(input = "/tmp/reprex.R")

This will fail unless the package is explicitly attached with library(reprex) — which isn't shown. For consistency and copy-paste reliability, this should be:

reprex::reprex(input = "/tmp/reprex.R")

Fix this →

2. Rscript /tmp/reprex.R still loads user profiles (line 68)

Rscript /tmp/reprex.R

Rscript without flags still sources the user's .Rprofile and .Renviron, which can silently affect behavior (e.g., options, library paths, env vars). Since this step is explicitly framed as "run in a clean session," using:

Rscript --vanilla /tmp/reprex.R

would be more consistent with that goal. (--vanilla is equivalent to --no-save --no-restore --no-site-file --no-environ --no-init-file.)

Fix this →


Already addressed

  • The earlier copilot note about tidyverse_update() is fully resolved — the current text correctly positions it as something to run outside the reprex to rule out stale packages, while explicitly noting it doesn't record versions.
  • The "~80% of the time" unsourced statistic is no longer in the file.

Minor observations (no action required)

  • The frontmatter (name, description, user-invocable, allowed-tools) is correctly structured.
  • The "Before declaring the reprex good" checklist and the closing "Don't" section are both useful anchors.
  • The reprex_clean() / reprex_rescue() / reprex_invert() companion helpers section is a nice addition not commonly documented in concise reprex guides.
  • The cross-platform /tmp vs. tempdir() / tempfile() callouts are appropriately handled throughout.

@d-morrison

Copy link
Copy Markdown
Member Author

Claude Code CLI (local session) is working on this — paws off until I'm done.

@d-morrison

Copy link
Copy Markdown
Member Author

@claude review

- Use reprex::reprex(input = ...) instead of bare reprex() for
  copy/paste reliability without an explicit library(reprex).
- Use Rscript --vanilla in the clean-session step so .Rprofile/.Renviron
  don't silently affect reproducibility.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 3, 2026 22:16
@d-morrison

Copy link
Copy Markdown
Member Author

Addressed both remaining findings from the latest review:

  • Namespace consistency (line ~99): reprex(input = ...)reprex::reprex(input = ...) so it works without an explicit library(reprex). (tidyverse::tidyverse_update() later in the file is already namespaced.)
  • Clean-session flag (line ~68): Rscript /tmp/reprex.RRscript --vanilla /tmp/reprex.R, with a note that --vanilla skips .Rprofile/.Renviron, matching the stated clean-session goal.

The earlier inline notes (the ~80% statistic and the tidyverse_update() version-recording caveat) were already resolved in the current file per the review.

@claude review

@claude

claude Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 1m 17s —— View job


Code Review

  • Read SKILL.md
  • Review for correctness, clarity, and best practices
  • Post findings

Overall: The file is in good shape. Both issues flagged in the prior reviews (Copilot and previous Claude pass) have been resolved. No blocking issues remain.


Previously reported issues — now fixed

reprex::reprex(input = ...) namespace — the call on what was line 99 now reads reprex::reprex(input = "/tmp/reprex.R"), consistent with the namespaced form introduced just above it.

Rscript --vanilla — the clean-session step now correctly uses Rscript --vanilla /tmp/reprex.R, which suppresses .Rprofile / .Renviron loading as described.

tidyverse::tidyverse_update() — properly namespaced, and the surrounding prose correctly notes it updates packages rather than recording versions, so it belongs outside the reprex itself.

✅ Unsourced statistic — the "~80% of the time" claim is gone.


Minor observations (no action required)

  • The callr attribution for reprex 2.0's clean-session execution is accurate.
  • session_info = TRUE correctly names both sessionInfo() and sessioninfo::session_info() — reprex uses whichever is available.
  • std_out_err = TRUE capturing C-level / subprocess output is a useful edge-case note not commonly documented.
  • reprex_clean() / reprex_rescue() / reprex_invert() are all real exported functions in reprex 2.x — the descriptions are correct.
  • The dput() tactic for embedding minimal slices of real data inline is solid advice.
  • The tempfile(fileext = ".R") / tempdir() cross-platform callouts appear consistently throughout — good.
  • The closing "Don't" list is a useful anchor.

This is ready to merge from a content-accuracy standpoint.

@claude

claude Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 1m 7s —— View job


Code Review

  • Gather context
  • Read current SKILL.md
  • Verify claimed fixes
  • Review for any remaining issues

Overall: Both claimed fixes are confirmed and correctly applied. The document is accurate, actionable, and ready to merge. No blocking issues remain.


Fixes verified

1. Namespace consistency — confirmed

Both calls are now correctly namespaced:

reprex::reprex()  # line ~98, clipboard variant
reprex::reprex(input = "/tmp/reprex.R")  # line ~99, file variant

No bare reprex(...) calls remain.

2. Clean-session flag — confirmed

Step 3 now reads:

Rscript --vanilla /tmp/reprex.R

And correctly explains: "--vanilla skips .Rprofile/.Renviron so no stale globalenv() state or profile settings mask or fake the bug." The rationale matches the stated goal.


Minor observations (no action required)

  • The companion helpers reprex_clean(), reprex_rescue(), reprex_invert() are not namespaced, but they appear in descriptive prose rather than standalone copy-paste code, so the risk of confusion is much lower than the reprex::reprex(input = ...) case that was fixed.
  • sessionInfo() is intentionally un-namespaced — it's a base R / utils function, so no qualifier is needed.
  • The callr-since-2.0 note is accurate. The venue = table, std_out_err, wd =, and session_info = argument docs are all correct.
  • The tidyverse::tidyverse_update() positioning (outside the reprex, to rule out stale packages, with an explicit note that it doesn't record versions) is exactly right.

This PR looks good to merge.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.

Comment on lines +62 to +66
portable path). Put in it, in order:
- the package loads (`library(...)`),
- the minimal data (see tactics below),
- the minimal code that triggers the phenomenon, with a comment marking
where it goes wrong.
Comment on lines +96 to +98
formats a reprex for sharing: it runs your code in a clean, separate R
session (via `callr` since reprex 2.0) and emits code **plus actual
output**.
Comment on lines +103 to +110
output is destined for a PR comment or an upstream issue. Useful arguments:
- `venue =` — output format:
- `"gh"` — GitHub-flavored Markdown (default)
- `"so"` / `"ds"` — Stack Overflow / Discourse
- `"slack"` — Slack message
- `"r"` — runnable R script with commented output
- `"html"` — HTML
- `"rtf"` — rich text for presentations
@d-morrison

Copy link
Copy Markdown
Member Author

Claude Code CLI (local session) is working on this — paws off until I'm done.

Qualify reprex_clean(), reprex_rescue(), reprex_invert(), and the
remaining bare reprex() reference with reprex::, matching the already-
namespaced reprex::reprex() calls. They're code-formatted function
references, so the namespace reads naturally.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@d-morrison

Copy link
Copy Markdown
Member Author

Addressed the minor observation.

Namespaced the companion helpers: reprex_clean(), reprex_rescue(), and reprex_invert() are now reprex::reprex_clean(), etc. I also namespaced the two other bare reprex() references (the reprex::reprex_invert() description and the "Validation bonus" line) so every reprex-package function in the doc is qualified consistently. They're all code-formatted (backticked) function references, so the reprex:: prefix reads naturally rather than oddly. sessionInfo() is left bare since it's base R, and tidyverse::tidyverse_update() was already qualified.

@claude review

@claude

claude Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 2m 43s —— View job


Code Review

  • Gather context
  • Read current SKILL.md
  • Verify claimed namespace fixes for companion helpers
  • Check new Copilot comments (blank lines, "since reprex 2.0")
  • Post findings

Overall: The claimed namespace fixes are confirmed. Three minor issues from the most recent Copilot pass (2026-06-03T22:22:05Z) remain unaddressed — two are trivial blank-line fixes, one is a factual accuracy question.


Claimed fix verified — ✅

All three companion helpers are now correctly namespaced:

reprex::reprex_clean()   (line 122)
reprex::reprex_rescue()  (line 123)
reprex::reprex_invert()  (line 125)

The two other bare reprex() references are also correctly qualified (reprex::reprex() at lines 99 and 117). No un-namespaced reprex-package calls remain.


Remaining issues (new Copilot comments, not yet addressed)

1. Missing blank line before the nested bullet list in step 2 (line ~62)

The sub-list after "Put in it, in order:" has no blank line separator:

   portable path). Put in it, in order:
   - the package loads (`library(...)`),   ← no blank line before this

Standard CommonMark / GitHub Markdown requires a blank line before a list inside a numbered list item for consistent rendering. Fix: add a blank line after Put in it, in order:.

Fix this →.%20Put%20in%20it%2C%20in%20order%3A%22%20add%20a%20blank%20line%20before%20the%20%22-%20the%20package%20loads%22%20nested%20bullet%20list%20to%20match%20the%20repo%E2%80%99s%20%22blank%20line%20before%20lists%22%20markdown%20formatting%20rule.&repo=UCD-SERG%2Flab-manual)

2. "since reprex 2.0" qualifier is likely inaccurate (line 97)

  session (via `callr` since reprex 2.0) and emits code **plus actual

The callr-backed subprocess execution was introduced in reprex 0.2.0 (2018), not reprex 2.0 (2021). reprex 2.0 was a major API rework, but it didn't introduce callr. The parenthetical is a factual claim that appears to be wrong, and it'll silently mislead readers over time. The safest fix is to drop the version qualifier: (via \callr`)`.

Fix this →

3. Missing blank line before "Useful arguments:" and before the venue = nested list (line ~103–105)

  output is destined for a PR comment or an upstream issue. Useful arguments:
  - `venue =` — output format:
    - `"gh"` — GitHub-flavored Markdown (default)   ← no blank line before nested list

Two spots need blank lines: before the - \venue =`list (or "Useful arguments:" should be its own paragraph), and before the nested list ofvenue` values. Without blank lines, some Markdown renderers may not recognize the nested structure.

Fix this →


Previously verified (no action needed)

All fixes from earlier review rounds are intact: reprex::reprex(input = ...), Rscript --vanilla, tidyverse::tidyverse_update() positioning, and the removed unsourced statistic.


The blank-line issues are cosmetic/render-safety; the callr version qualifier is the one substantive accuracy concern. Otherwise content is solid.

@d-morrison

Copy link
Copy Markdown
Member Author

Claude Code CLI (local session) is working on this — paws off until I'm done.

…0' qualifier

Address latest Copilot review:
- Add blank line before the nested bullet list in step 2 and before the
  'Useful arguments' / nested venue lists, per the repo's blank-line-before-
  lists markdown convention.
- callr-backed clean-session execution dates to reprex 0.1.0 (2017), not 2.0,
  so drop the inaccurate '(via callr since reprex 2.0)' version qualifier.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 3, 2026 22:56
@d-morrison

Copy link
Copy Markdown
Member Author

Addressed the 3 remaining items from the latest Copilot pass (commit f296acd):

  • Blank line before nested list in step 2 (line ~62) — added.
  • Blank lines before "Useful arguments:" and the nested venue = list (line ~104) — added both.
  • "since reprex 2.0" qualifier (line 97) — corrected. Verified against the reprex changelog: callr-backed clean-session execution dates to reprex 0.1.0 (2017), not 2.0. Dropped the version qualifier to (via callr) so the text stays accurate.

@claude review

@claude

claude Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 53s —— View job


Code Review

  • Gather context
  • Read current SKILL.md
  • Verify claimed fixes (blank lines, "since reprex 2.0" qualifier)
  • Check for any remaining issues
  • Post findings

Overall: All three claimed fixes are confirmed and correctly applied. The document is accurate, clean, and ready to merge. No blocking or minor issues remain.


Fixes verified — ✅ all three

1. Blank line before nested list in step 2

   portable path). Put in it, in order:

   - the package loads (`library(...)`),

Blank line is present. ✅

2. Blank lines before "Useful arguments:" list and nested venue = values

  output is destined for a PR comment or an upstream issue. Useful arguments:

  - `venue =` — output format:

    - `"gh"` — GitHub-flavored Markdown (default)

Both blank lines are present. ✅

3. "since reprex 2.0" qualifier dropped

The line now reads:

  session (via `callr`) and emits code **plus actual output**.

Version qualifier is gone. ✅


Full document check (no action needed)

  • All reprex-package function calls are namespaced (reprex::reprex(), reprex::reprex_clean(), reprex::reprex_rescue(), reprex::reprex_invert()). ✅
  • Rscript --vanilla /tmp/reprex.R is correct and matches the clean-session framing. ✅
  • sessionInfo() correctly left bare (base R / utils). ✅
  • tidyverse::tidyverse_update() correctly namespaced and positioned outside the reprex. ✅
  • Cross-platform /tmp vs. tempfile(fileext = ".R") / tempdir() callouts are consistent throughout. ✅
  • The reprex_clean() / reprex_rescue() / reprex_invert() descriptions are accurate. ✅
  • The "Before declaring the reprex good" checklist and closing "Don't" section are both solid anchors. ✅

This PR is ready to merge.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@d-morrison

Copy link
Copy Markdown
Member Author

Done with my local session — unclaiming. (Re-triggered @claude review on the latest commit.)

@claude

claude Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 1m 15s —— View job


Code Review

  • Gather context
  • Read current SKILL.md (latest commit f296acd)
  • Verify all previously reported fixes are still in place
  • Check for any new issues
  • Post findings

Overall: All previously reported fixes are confirmed in place. The latest Copilot pass (2026-06-03T22:58:09Z) had no new comments. No blocking or minor issues remain — this PR is ready to merge.


All fixes verified — ✅

Namespace consistency
Every reprex-package function reference is qualified:

  • reprex::reprex() (clipboard call) ✅
  • reprex::reprex(input = "/tmp/reprex.R") (file call) ✅
  • reprex::reprex_clean(), reprex::reprex_rescue(), reprex::reprex_invert()
  • sessionInfo() correctly left bare (base R / utils) ✅
  • tidyverse::tidyverse_update() correctly namespaced and positioned outside the reprex ✅

Clean-session flag
Step 3 reads Rscript --vanilla /tmp/reprex.R with the correct rationale ("skips .Rprofile/.Renviron so no stale globalenv() state or profile settings mask or fake the bug") ✅

callr version qualifier dropped
The line now reads (via \callr`)` — the inaccurate "since reprex 2.0" qualifier is gone ✅

Blank lines before nested lists

  • Blank line after "Put in it, in order:" (step 2) ✅
  • Blank line before the venue = list and before its nested values ✅

Unsourced statistic — the "~80% of the time" claim is gone ✅


Full document check (no action needed)

  • Frontmatter (name, description, user-invocable, allowed-tools) is correctly structured.
  • Cross-platform /tmp vs. tempfile(fileext = ".R") / tempdir() callouts are consistent throughout.
  • The dput() tactic for embedding minimal data slices inline is sound advice.
  • The "Before declaring the reprex good" checklist and closing "Don't" section are both solid anchors.
  • The reprex::reprex_invert() description ("the inverse of reprex::reprex()") is accurate.
  • std_out_err = TRUE capturing C-level / subprocess output is a useful edge-case note.
  • tidyverse::tidyverse_update() positioning (outside the reprex, to rule out stale packages, with an explicit note it doesn't record versions) is exactly right.
  • Build-artifact confounders (_site/, _freeze/, .quarto/) callout is appropriate for a Quarto-heavy repo.

This PR is ready to merge.

@d-morrison

Copy link
Copy Markdown
Member Author

Claude Code CLI (local session) is working on this — paws off until I'm done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants