The manifesto package provides tools for managing
project environments in R using standardized TOML manifest files. These
manifest files make project metadata, dependencies, and environment
settings explicit and portable. This vignette introduces the core
features of manifesto and demonstrates how to use it in
typical R workflows.
Installation
You can install the stable version of manifesto from
CRAN:
pak::pak('manifesto')To install the development version from GitHub:
pak::pak('christopherkenny/manifesto')Installing from a Manifest
For example purposes, we’ll use a manifest file included with the
manifesto package. This file is located in the
inst/examples directory of the package.
manifest_path <- system.file('complex.toml', package = 'manifesto')To install all dependencies listed in a TOML manifest:
manifest_install(manifest_path)To install with optional groups:
manifest_install(manifest_path, groups = 'dev')
manifest_install(manifest_path, groups = c('dev', 'ci'))To preview what would be installed:
manifest_install(manifest_path, dry_run = TRUE)
#>
#> ── Dry run: would install the following 3 packages ──
#>
#> • dplyr@>=1.0.10
#> • BiocManager@>=1.30.10
#> • readr@2.1.4Creating and Using a Manifest
Creating a Minimal Manifest
path <- manifest_create()
path
#> [1] "/tmp/RtmpUtD65y/file1f7846d608db.toml"#> [manifesto]
#> version = "0.0.1"
#>
#> [project]
#> name = "Project"
#> version = "0.0.1"
#>
#> [environment]
#> r_version = "*"
#>
#> [dependencies]
This creates a file with default sections:
-
[manifesto]with the current package version -
[project]with name and version placeholders -
[environment]with a default R version -
[dependencies], initialized as an empty table
Example Manifest Files
Basic project manifest
In general, this structure is only useful when there are dependencies
to specify. Suppose we want to list dplyr and
ggplot2 as dependencies for our project. Here, we specify
that we need dplyr version >= 1.0.0 and any
version of ggplot2. (Practically, “any” version will be
limited to versions that meet the R version requirement and match with
other dependencies.)
Then run:
manifest_create(
path = tempfile(fileext = '.toml'),
name = 'myproject',
r_version = '>= 4.2.0',
dependencies = list(
dplyr = '>= 1.0.0',
ggplot2 = '*'
)
)This creates a manifest file with the following content:
Adding optional dependency groups
Often, we need to specify optional dependencies for development,
testing, or CI. We can do this by passing additional named arguments to
manifest_create().
manifest_create(
path = tempfile(fileext = '.toml'),
name = 'myproject',
r_version = '>= 4.2.0',
dependencies = list(
dplyr = '>= 1.0.0',
ggplot2 = '*'
),
'dev-dependencies' = list(
testthat = '>= 3.1.0',
lintr = '*'
),
'ci-dependencies' = list(
pkgdown = '*'
)
)Including a package from GitHub
Not all packages are available on CRAN. You can include packages from
GitHub or other sources by specifying additional details. Note that
manifesto uses the pak package to handle these
dependencies, so any source that pak supports can be
used.
The corresponding call to manifest_create() would look
like this:
manifest_create(
path = tempfile(fileext = '.toml'),
name = 'myproject',
r_version = '>= 4.2.0',
dependencies = list(
dplyr = '>= 1.0.0',
ggplot2 = '*',
cli = '*'
),
'dev-dependencies' = list(
gh = list(source = 'github', repo = 'r-lib/gh', ref = 'v1.4.0')
)
)Using a local package path
You can also specify a local package path for development or testing purposes.
manifest_create(
path = tempfile(fileext = '.toml'),
name = 'myproject',
r_version = '>= 4.2.0',
dependencies = list(
dplyr = '>= 1.0.0'
),
'dev-dependencies' = list(
mydevpkg = list(source = 'local', path = '../mydevpkg')
)
)[manifesto]
version = "0.0.1"
[project]
name = "myproject"
version = "0.1.0"
[environment]
r_version = ">= 4.2.0"
[dependencies]
dplyr = ">= 1.0.0"
[dev-dependencies]
mydevpkg = { source = "local", path = "../mydevpkg" }
These examples reflect common patterns for specifying runtime, development, CI, and local dependencies.
Validating a Manifest
You can validate the structure and content of a manifest with:
manifest_validate(path = manifest_path)This checks for required sections, valid dependency specifications, and correct field usage.
Example Workflow
In general, you only have to create and share a file. You can use the
manifest_create() function to create a manifest file. Then
anyone with the file can use manifest_install() to install
the dependencies. manifesto is a generally lightweight
package, so it should not add much overhead to your workflow.
The use of groups allows you to specify different sets of dependencies for different purposes, such as development, testing, or for workshops. The original motivation was as a workshop tool, but has expanded a bit to allow for more general use.
1. Creating a new manifest with common dependencies
manifest <- manifest_create(
path = tempfile(fileext = '.toml'),
name = 'myproject',
version = '0.1.0',
r_version = '>= 4.2.0',
dependencies = list(
dplyr = '>= 1.0.0',
ggplot2 = '*',
glue = '*'
),
'dev-dependencies' = list(
testthat = '>= 3.1.0',
lintr = '*'
)
)This creates a manifest for an R project that uses dplyr
and ggplot2, with development tools like
testthat grouped separately.
2. Installing core and dev dependencies
manifest_install(manifest, groups = 'dev', dry_run = TRUE)
#>
#> ── Dry run: would install the following 5 packages ──
#>
#> • dplyr@>=1.0.0
#> • ggplot2
#> • glue
#> • testthat@>=3.1.0
#> • lintrThis installs everything from [dependencies] and
[dev-dependencies]. Here, for CRAN purposes,
dry_run = TRUE means no packages are installed, but the
output shows what would be installed.
The general idea then is that dependencies must always
be installed. Groups like dev would be used for development
or testing.
3. Installing all dependencies
The special group name all is reserved to allow a user
to install everything in the manifest.
manifest_install(manifest, groups = 'all', dry_run = TRUE)
#>
#> ── Dry run: would install the following 5 packages ──
#>
#> • dplyr@>=1.0.0
#> • ggplot2
#> • glue
#> • testthat@>=3.1.0
#> • lintrBy default, only [dependencies] is installed, whereas
all installs everything.
Manifest File Structure
A valid TOML manifest must contain the following top-level sections:
-
[manifesto](required)-
version: (required) should match the version of themanifestopackage used to generate it.
-
-
[project](required)-
name: (required) the name of the project. -
version: (required) the version of the project. -
authors: (optional) an array of tables with fields such asname,email, androles.
-
-
[environment](required)-
r_version: (required) a valid R version requirement string (e.g., “>= 4.2.0”).
-
-
[dependencies](required)- List of core package dependencies (name = version).
Optional groups:
-
[<group>-dependencies](optional)- Named groups such as
dev,suggests,ci,enhances,workshop, etc. - Each contains its own set of package references.
- Named groups such as
Each package reference may be: - A version string (e.g., “>=
1.0.0”) - A table with source, repo,
ref, or url (e.g., for GitHub, GitLab, or
custom sources)
Examples:
gh = { source = "github", repo = "r-lib/gh", ref = "v1.4.0" }
custompkg = { source = "url", url = "https://example.com/custompkg.tar.gz" }
Converting from DESCRIPTION to Manifest
manifest_desc <- tempfile(fileext = '.toml')
manifest_from_description(
system.file(package = 'cli', 'DESCRIPTION'),
path = manifest_desc
)#> [manifesto]
#> version = "0.0.1"
#>
#> [project]
#> name = "cli"
#> version = "3.6.5"
#> authors = [
#> { name = "Gábor Csárdi", email = "gabor@posit.co", roles = ["aut", "cre"] },
#> { name = "Hadley Wickham", roles = "ctb" },
#> { name = "Kirill Müller", roles = "ctb" },
#> { name = "Salim Brüggemann", email = "salim-b@pm.me", roles = "ctb" },
#> { name = "Posit Software, PBC", roles = ["cph", "fnd"] }
#> ]
#>
#> [environment]
#> r_version = ">= 3.4"
#>
#> [dependencies]
#> utils = "*"
#>
#> [suggests-dependencies]
#> callr = "*"
#> covr = "*"
#> crayon = "*"
#> digest = "*"
#> glue = ">= 1.6.0"
#> grDevices = "*"
#> htmltools = "*"
#> htmlwidgets = "*"
#> knitr = "*"
#> methods = "*"
#> processx = "*"
#> ps = """
#> >=
#> 1.3.4.9000"""
#> rlang = ">= 1.0.2.9003"
#> rmarkdown = "*"
#> rprojroot = "*"
#> rstudioapi = "*"
#> testthat = ">= 3.2.0"
#> tibble = "*"
#> whoami = "*"
#> withr = "*"
This uses fields from the DESCRIPTION file to populate:
- Project name and version
- Author information
- R version from
Depends - Dependency sections such as
Imports,Suggests,LinkingTo, andEnhances
Converting from Manifest to DESCRIPTION
description_path <- tempfile(pattern = 'DESCRIPTION')
manifest_to_description(manifest_desc, out = description_path)#> Package: cli
#> Version: 3.6.5
#> Title: TODO Title
#> Description: TODO Description
#> License: TODO License
#> Encoding: UTF-8
#> Authors@R: c( person("Gábor", "Csárdi", email = "gabor@posit.co", role
#> = c("aut", "cre")), person("Hadley", "Wickham", role =
#> c("ctb")), person("Kirill", "Müller", role = c("ctb")),
#> person("Salim", "Brüggemann", email = "salim-b@pm.me", role =
#> c("ctb")), person("Posit Software,", "PBC", role = c("cph",
#> "fnd")) )
#> Depends: R (>= 3.4)
#> Imports: utils
#> Suggests: callr, covr, crayon, digest, glue (>= 1.6.0), grDevices,
#> htmltools, htmlwidgets, knitr, methods, processx, ps (>=
#> 1.3.4.9000), rlang (>= 1.0.2.9003), rmarkdown, rprojroot,
#> rstudioapi, testthat (>= 3.2.0), tibble, whoami, withr
Required DESCRIPTION fields such as Title,
Description, and License are filled with
placeholder TODO values if missing. Author information is
translated into Authors@R format.
It’s very important to note that these types of files have different purposes. Not all fields in a DESCRIPTION file are required in a manifest file, so conversion can be lossy.
Learn More
For complete documentation, visit:
https://github.com/christopherkenny/manifesto
This package is intended to streamline environment specification and improve reproducibility in R projects.
DISCLAIMER: This vignette has been written with help from ChatGPT 4o. It has been reviewed for correctness and edited for clarity by the package author. Please note any issues at https://github.com/christopherkenny/manifesto/issues.
