Include

The #> include directive allows you to read external files at build time and embed their contents directly into your R code as variables. This enables you to keep SQL queries, data files, templates, and other content in separate files while embedding them at build time.

Advantages

Syntax

#> include:TYPE file_path variable_name

The directive consists of three space-separated parts:

Built-in Readers

Builder includes readers for common file types:

Type Function Package
txt readLines base
sql readLines base
csv read.csv base
tsv read.delim base
rds readRDS base
json jsonlite::fromJSON jsonlite
yml yaml::read_yaml yaml
yaml yaml::read_yaml yaml
xml xml2::read_xml xml2
xlsx readxl::read_excel readxl
parquet arrow::read_parquet arrow
fst fst::read_fst fst

Basic Examples

Reading SQL Files

#> include:sql queries/users.sql user_query

Expands to:

user_query <- c("SELECT * FROM users", "WHERE active = 1")

Reading CSV Data

Embed small lookup tables or static data directly in your code:

#> include:csv data/lookup_table.csv lookup_data

Expands to:

lookup_data <- structure(list(id = 1:3, name = c("a", "b", "c")), class = "data.frame", row.names = c(NA, -3L))

Reading JSON Configuration

#> include:json config/settings.json app_config

Custom Readers

You can define custom readers for new file types or override the defaults using the -reader CLI argument or reader: config option.

Via CLI

builder -reader tsv '\(x) read.delim(x, sep="\t", header=FALSE)'

Via Config File

reader: tsv \(x) read.delim(x, sep="\t", header=FALSE)
reader: myformat \(x) mypackage::read_myformat(x)

Custom Reader Format

The reader function must accept a single argument (the file path). You can use:

When you override a built-in reader, a warning is displayed:

[WARNING] Overriding reader for 'tsv'

How It Works

When the preprocessor encounters an #> include directive:

  1. It parses the file type, file path, and variable name
  2. It looks up the reader function for that file type
  3. It constructs an R expression: reader_function('file_path')
  4. It captures the result using dput() and capture.output()
  5. It generates an assignment: variable_name <- <result>

This happens at build time, so the final R code contains no file reading operations—just the embedded data.

Extending via Plugins

For more complex include handling, you can use a plugin that implements the include hook. This allows you to intercept and transform #> include directives with custom logic.

plugin <- function(input, output) {
  list(
    include = function(type, path, object, file) {
      # type = file type (e.g., "csv")
      # path = file path to include
      # object = variable name for result
      # file = source file being processed
      
      # Return NULL to use default processing
      # Or return a replacement line
      NULL
    }
  )
}

See Plugins for more details.

Important Notes

Processing Pipeline

The #> include directive is processed in the second pass, after macro definitions are collected but before macro expansion.

  1. First pass: All #> define constants and #> macro definitions are collected
  2. Second pass: #> include directives are processed, then macros are expanded
  3. The result is pure R code with all preprocessing directives removed

See Architecture for the complete processing pipeline.

Common Use Cases