| Title: | Opinionated Project Scaffolding via Composable Themes |
|---|---|
| Description: | Provides a composable theme system for project scaffolding. Themes are ordered lists of steps that deploy files, inline text, or execute functions, with per-file merge strategies for handling pre-existing content. Includes pre-set themes for R analysis projects, targets workflows, and Claude Code agent configuration. |
| Authors: | Ben Zipperer [aut, cre], Economic Policy Institute [cph, fnd] |
| Maintainer: | Ben Zipperer <benzipperer@gmail.com> |
| License: | MIT + file LICENSE |
| Version: | 0.6.0 |
| Built: | 2026-10-12 10:19:39 UTC |
| Source: | https://github.com/economic/prefab |
Creates a theme that deploys Claude Code agent settings and rules for an R analysis project.
claude_r_analysis(settings_json = TRUE)claude_r_analysis(settings_json = TRUE)
settings_json |
Logical. If |
A prefab_theme object.
claude_r_analysis()claude_r_analysis()
Creates a theme that deploys Claude Code agent settings and rules for an R package.
claude_r_package()claude_r_package()
A prefab_theme object.
claude_r_package()claude_r_package()
Creates a theme that deploys Claude Code agent settings and rules for an R targets project.
claude_r_targets(settings_json = TRUE)claude_r_targets(settings_json = TRUE)
settings_json |
Logical. If |
A prefab_theme object.
claude_r_targets()claude_r_targets()
Creates a new project directory and applies a theme to it.
create_project(path, theme, open = rlang::is_interactive())create_project(path, theme, open = rlang::is_interactive())
path |
Path for the new project directory. Resolved to an absolute path
via |
theme |
A |
open |
Whether to activate the new project after creating it, following
the convention of |
The normalized project path (invisibly).
theme_from_dir() for how a template directory is read.
## Not run: create_project("~/projects/my-analysis", r_analysis()) create_project("my-targets-project", r_targets() + claude_r_targets()) # A directory of template files create_project("~/projects/my-report", "~/templates/quarto-report") ## End(Not run)## Not run: create_project("~/projects/my-analysis", r_analysis()) create_project("my-targets-project", r_targets() + claude_r_targets()) # A directory of template files create_project("~/projects/my-report", "~/templates/quarto-report") ## End(Not run)
Returns a step-builder function that resolves source paths relative to a local directory. The directory path is resolved to an absolute path at creation time.
from_dir(path)from_dir(path)
path |
Path to the directory. Resolved to absolute via |
A function with signature
function(source, dest, strategy = "overwrite", data = NULL) that returns
a step_file() object.
Returns a step-builder function that resolves source paths relative to a
package's inst/ directory. Works with both installed packages and during
development with devtools::load_all().
from_package(package)from_package(package)
package |
Package name (string). |
A function with signature
function(source, dest, strategy = "overwrite", data = NULL) that returns
a step_file() object.
Interactive project launcher: prompts for a project name via
rstudioapi::showPrompt(), builds a path from root (and an optional dated
subdirectory), and creates the project with create_project(). It is
designed to be bound to a key chord so that a single keystroke scaffolds and
opens a fresh project. The prompt shows the destination directory (including
the dated subdirectory when date = TRUE), and re-prompts with a hint if the
entered name is invalid rather than aborting.
launch_project( theme, root = getOption("prefab.project_root", "~"), date = FALSE, slug = getOption("prefab.project_slug", TRUE), open = rlang::is_interactive(), label = NULL )launch_project( theme, root = getOption("prefab.project_root", "~"), date = FALSE, slug = getOption("prefab.project_slug", TRUE), open = rlang::is_interactive(), label = NULL )
theme |
A |
root |
Directory under which the project is created. Defaults to the
|
date |
Whether to nest the project under a |
slug |
Whether to slugify the entered name into a filesystem-safe
directory name (lower-case, non-alphanumeric runs collapsed to |
open |
Whether to activate the new project after creating it. Passed to
|
label |
Optional prompt-window title, used to show which theme a key
chord will apply (e.g. |
Bind it in Positron by running it via workbench.action.executeCode.console,
for example in keybindings.json:
{
"key": "Ctrl+P N",
"command": "workbench.action.executeCode.console",
"args": {
"langId": "r",
"code": "prefab::launch_project(prefab::r_analysis(), label = 'r_analysis')",
"focus": false
}
}
For programmatic (non-interactive) project creation from a known path, use
create_project() directly.
The normalized project path (invisibly), or NULL if the prompt is
cancelled or left empty.
theme_from_dir() for how a template directory is read.
Sources an R file containing custom theme functions into the global
environment, making them available for use with use_theme() and
create_project().
load_themes(file = NULL)load_themes(file = NULL)
file |
Path to an R file defining theme functions. If |
The file is resolved in order: the explicit file argument, then the
PREFAB_THEMES environment variable, then ~/.prefab-themes.R.
The file path that was sourced (invisibly), or NULL invisibly if
no file was found.
## Not run: # Source from default locations load_themes() # Source from a specific file load_themes("~/my-org-themes.R") ## End(Not run)## Not run: # Source from default locations load_themes() # Source from a specific file load_themes("~/my-org-themes.R") ## End(Not run)
Constructs a theme from step objects. NULL arguments are silently dropped,
enabling conditional steps via if (cond) step(...).
new_theme(...)new_theme(...)
... |
Step objects ( |
A list with class "prefab_theme" containing a steps element.
+
Themes compose with +, which concatenates their steps with the left
operand's steps first. Either operand may be a path to a directory of
template files, coerced with theme_from_dir() using its defaults:
r_analysis() + claude_r_analysis() r_analysis() + "~/my-extras" "~/my-baseline" + r_analysis()
Steps cannot be added to a theme directly; wrap them in new_theme() first.
Anything that is neither a theme nor a path to an existing directory is an
error.
One limitation: an fs::path() value does not work as a + operand in
either position, because fs defines its own + method and R refuses to
choose between the two. Wrap it in theme_from_dir() instead. A plain
character path, and fs::path() values at use_theme(),
create_project(), and launch_project(), are all fine.
theme_from_dir() for how a template directory is read.
Creates a theme that scaffolds a simple R analysis project with main.R,
README.md, and .gitignore.
r_analysis(data_dirs = TRUE)r_analysis(data_dirs = TRUE)
data_dirs |
Logical. If |
A prefab_theme object.
r_analysis()r_analysis()
Creates a theme that scaffolds an R targets project with _targets.R,
packages.R, README.md, and .gitignore.
r_targets()r_targets()
A prefab_theme object.
r_targets()r_targets()
Creates a step that deploys a file or directory to the project.
step_file(source, dest, strategy = "overwrite", data = NULL)step_file(source, dest, strategy = "overwrite", data = NULL)
source |
Absolute path to the source file or directory. Typically
produced by a source helper ( |
dest |
Path to the destination, relative to the project root. |
strategy |
How to handle a pre-existing destination file. One of
|
data |
|
A list with class "prefab_step_file".
Creates a step that executes an R function for its side effects.
step_run(fn, ..., .label = NULL)step_run(fn, ..., .label = NULL)
fn |
A function to execute. |
... |
Additional arguments passed to |
.label |
Optional label for display. When |
A list with class "prefab_step_run".
Creates a step that deploys inline text content to the project. Like
step_file() but takes a character vector instead of a source file path.
step_text(content, dest, strategy = "overwrite")step_text(content, dest, strategy = "overwrite")
content |
Character vector of lines to deploy (one element per line).
|
dest |
Path to the destination, relative to the project root. |
strategy |
How to handle a pre-existing destination file. One of
|
A list with class "prefab_step_text".
Prints the R code that would reproduce the given theme via cat(), and
returns the code invisibly as a single character string.
theme_code(theme)theme_code(theme)
theme |
A |
The generated R code as a single character string (invisibly).
This function reads a directory tree and makes a theme. Each file becomes a
step_file(). Each empty directory becomes a step that makes the directory
again. An optional _prefab.yml file at the root of the directory
can change the strategy and the template data for each file.
theme_from_dir(path, strategy = "skip")theme_from_dir(path, strategy = "skip")
path |
The path to a directory of template files. The directory must
exist. prefab expands a leading |
strategy |
The default merge strategy for all files. A |
Each file below path becomes a step_file(). The destination of the step
is the path of the file relative to path. prefab includes hidden files.
prefab also includes hidden empty directories.
prefab excludes these directories at all levels of the tree:
.git
.Rproj.user
_targets
renv/library
prefab does not deploy the symbolic links below path.
This function is called by use_theme(), create_project(), launch_project(), and +
when they process a path. They call this function with the default arguments.
A prefab_theme object.
## Not run: # Make a theme from a directory of configuration files use_theme(theme_from_dir("~/my-template")) # The short form. It calls theme_from_dir() with the default arguments. use_theme("~/my-template") # Add the theme to another theme use_theme(r_analysis() + theme_from_dir("~/my-extras")) ## End(Not run)## Not run: # Make a theme from a directory of configuration files use_theme(theme_from_dir("~/my-template")) # The short form. It calls theme_from_dir() with the default arguments. use_theme("~/my-template") # Add the theme to another theme use_theme(r_analysis() + theme_from_dir("~/my-extras")) ## End(Not run)
Discovers the project root and executes the theme against it.
use_theme(theme)use_theme(theme)
theme |
A |
The project root path (invisibly).
theme_from_dir() for how a template directory is read.
## Not run: use_theme(r_analysis()) use_theme(r_analysis() + claude_r_analysis()) # A directory of template files use_theme("~/my-template") ## End(Not run)## Not run: use_theme(r_analysis()) use_theme(r_analysis() + claude_r_analysis()) # A directory of template files use_theme("~/my-template") ## End(Not run)