R targets
Use when creating reproducible analysis pipelines, managing computational workflows, or using the targets package for pipeline orchestration in R. Provides expert guidance on target definitions, static and dynamic branching, dependency graphs, caching, cloud storage backends, and integration with renv for fully reproducible workflows. Do NOT use for initial project scaffold, directory structure, or setup — use r-project-setup instead. Do NOT use for general data wrangling within a target — use r-data-analysis instead.From its SKILL.md
npx -y skills add alexvantwisk/supeRpowers --skill r-targetsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.8 KB, as published. Nobody here has run it
R Targets — Pipeline Orchestration
Reproducible analysis pipelines with the targets package. Define targets once,
re-run only what changed. All code uses base pipe |>, <- for assignment,
and tidyverse style.
Boundary: Pipeline design and execution with targets. For initial project scaffolding, use r-project-setup instead.
Lazy references:
- Read
references/branching-patterns.mdfor static vs dynamic branching decision tree and recipes - Read
references/targets-integration-recipes.mdfor copy-paste pipeline patterns (ML, reports, simulations)
Agent dispatch: For renv + targets reproducibility questions, hand off to the r-dependency-manager agent.
MCP integration (when R session available):
- When uncertain about targets API (tar_target options, branching syntax):
btw_tool_docs_help_pageto read installed docs - Before writing targets that process data:
btw_tool_env_describe_data_frameto verify input structure
Pipeline Fundamentals
The _targets.R file defines the pipeline:
library(targets)
tar_option_set(
packages = c("dplyr", "ggplot2", "readr"),
format = "qs"
)
# Source functions from R/ directory
tar_source()
list(
tar_target(data_raw, read_csv("data/raw/input.csv", col_types = cols())),
tar_target(data_clean, clean_data(data_raw)),
tar_target(model, fit_model(data_clean)),
tar_target(report, render_report(model), format = "file")
)
Each tar_target() is a cacheable unit. targets tracks dependencies via static
code analysis — only outdated targets re-run on tar_make().
Non-Obvious Commands
tar_workspace(failed_target) # Load failed target's deps for interactive debugging
tar_invalidate(name) # Force a target to re-run (cache override)
tar_branches(target) # Inspect individual dynamic branches
Standard workflow (tar_make(), tar_read(), tar_visnetwork(), etc.) — Claude already knows these.
Target formats: Default to format = "qs" globally via tar_option_set() (install qs2, the maintained successor to qs, so the fast path is available). Use "file" for side-effect targets (plots, reports, exports). Use "parquet" for cross-language interop on large datasets.
Static Branching
Map targets over known values at definition time:
library(tarchetypes)
tar_map(
values = tibble(dataset = c("train", "test", "validation")),
tar_target(data, load_data(dataset)),
tar_target(model, fit_model(data))
)
See references/branching-patterns.md for detailed recipes.
Dynamic Branching
Map targets over values computed at runtime:
tar_target(files, list.files("data/", full.names = TRUE)),
tar_target(
processed,
process_file(files),
pattern = map(files)
)
Patterns: map() (1:1), cross() (all combinations), slice() (subset).
Error Handling and Debugging
# Load a failed target's dependencies for interactive debugging
tar_workspace(failed_target_name)
# Find failed targets
tar_meta() |> dplyr::filter(!is.na(error))
# Continue pipeline despite failures
tar_target(x, risky_fn(), error = "continue")
# Get traceback for a failure
tar_traceback(failed_target_name)
Integration: targets + Quarto
library(tarchetypes)
list(
tar_target(data, load_data()),
tar_target(model, fit_model(data)),
tar_quarto(report, path = "report.qmd")
)
In report.qmd, access pipeline results with targets::tar_read(model).
Integration: targets + tidymodels
list(
tar_target(raw, read_csv("data.csv", col_types = cols())),
tar_target(split, initial_split(raw, strata = outcome)),
tar_target(rec, build_recipe(training(split))),
tar_target(spec, build_model_spec()),
tar_target(wf, workflow() |> add_recipe(rec) |> add_model(spec)),
tar_target(folds, vfold_cv(training(split), v = 10, strata = outcome)),
tar_target(tuned, tune_grid(wf, resamples = folds, grid = 20)),
tar_target(best, select_best(tuned, metric = "roc_auc")),
tar_target(final, finalize_workflow(wf, best) |> last_fit(split))
)
Integration: targets + renv
Version-control renv.lock, _targets.R, and R/. Gitignore _targets/ (machine-specific cache).
Parallel Execution
library(crew)
tar_option_set(
controller = crew_controller_local(workers = 4)
)
crew is the recommended backend. Workers execute independent targets in parallel. For HPC scale-out (SLURM, SGE, PBS, LSF), use crew.cluster controllers (e.g. crew_controller_slurm()).
Gotchas
| Trap | Why It Fails | Fix |
|---|---|---|
| One giant target that does everything | No caching granularity; any change reruns the whole thing | Break into small, focused targets with single responsibilities |
| Targets that return invisible side effects | targets caches return values; side effects not tracked | Return the value explicitly, or use format = "file" for side-effect targets |
| Hard-coded file paths inside functions | targets cannot detect the dependency | Pass paths as target inputs so targets tracks them |
Functions defined inside _targets.R | Functions pollute the pipeline definition | Move functions to R/; tar_source() loads them |
_targets/ committed to git | Cache is machine-specific and large | Add _targets/ to .gitignore |
Using tar_load() inside a target function | Loaded target is invisible to the dependency graph | Pass the value as a function argument |
| Non-serializable objects (DB connections, R6) | format = "qs" or "rds" cannot serialize them | Return data, not connections; reconnect inside the target |
| NULL-returning targets silently skipped | Target appears up-to-date but carries no value | Return a sentinel value or empty tibble |
| Redesigning entire pipeline when user asked to add one target | Scope creep risks breaking a working pipeline | Add the requested target, suggest improvements as follow-up |
Examples
Happy Path: Convert a Script to a Targets Pipeline
Prompt: "Convert my analysis script into a reproducible targets pipeline."
# Before: monolithic script (R/analysis.R)
# data <- read_csv("data/raw/sales.csv")
# clean <- data |> filter(!is.na(revenue))
# model <- lm(revenue ~ region + quarter, data = clean)
# saveRDS(model, "output/model.rds")
# After: _targets.R
library(targets)
tar_option_set(packages = c("dplyr", "readr"), format = "qs")
tar_source()
list(
tar_target(data_raw, read_csv("data/raw/sales.csv", col_types = cols())),
tar_target(data_clean, clean_sales(data_raw)),
tar_target(model, fit_revenue_model(data_clean)),
tar_target(model_file, save_model(model, "output/model.rds"), format = "file")
)
# R/functions.R — extracted pipeline functions
clean_sales <- function(df) {
df |> dplyr::filter(!is.na(revenue))
}
fit_revenue_model <- function(df) {
lm(revenue ~ region + quarter, data = df)
}
save_model <- function(model, path) {
saveRDS(model, path)
path
}
# Run: tar_make()
# Inspect: tar_read(model)
# Visualize: tar_visnetwork()
Edge Case: Dynamic Branching with pattern = map() on Grouped Data
Prompt: "Fit a separate model for each region in my data using dynamic branching."
# _targets.R
library(targets)
tar_option_set(packages = c("dplyr", "readr"), format = "qs")
tar_source()
list(
tar_target(data_raw, read_csv("data/sales.csv", col_types = cols())),
tar_target(
regions,
data_raw |> dplyr::distinct(region) |> dplyr::pull(region)
),
tar_target(
region_data,
data_raw |> dplyr::filter(region == regions),
pattern = map(regions)
),
tar_target(
region_model,
lm(revenue ~ quarter, data = region_data),
pattern = map(region_data)
),
tar_target(
combined,
bind_region_results(region_model),
# Aggregate all branches back into one target
pattern = map(region_model)
)
)
# tar_make() runs one branch per region.
# tar_read(region_model, branches = 1) reads a single branch.
# tar_read(combined) returns aggregated results.
More example prompts:
- "Add Quarto report rendering as a target in my pipeline"
- "Set up parallel execution for my branched targets"
- "Debug a failing target in my pipeline"