Skip to contents

tinytrail is a lightweight R package that — once initialized — leaves a ‘tiny trail’ of human- and AI-readable information about what each script saves to disk, making it effortless to keep better track of small to medium-sized projects. It maintains a YAML trail file (_tinytrail.yaml) at the project root recording which scripts produced which output files and each script’s runtime. The tinytrail package also provides a convenience function that effortlessly registers column names along with sample values (optional) in the YAML.

Installation

install.packages("tinytrail")

# Development version from GitHub:
pak::pak("tinytrail-r/tinytrail")

Usage

Call tinytrail() once near the top of each script. Common write functions are intercepted automatically:

library(tinytrail)

tinytrail(
  description = "Clean and summarise survey data",
  data_source = "Current Population Survey (BLS)"
)

dat <- read.csv("data/raw/survey.csv")

write.csv(dat, "output/clean.csv")   # auto-tracked

png("output/age_dist.png")           # auto-tracked
hist(dat$age, main = "Age distribution")
dev.off()

tinytrail() detects the script name and creates or updates _tinytrail.yaml:

scripts:
  01_clean.R:
    description: Clean and summarise survey data
    data_source: Current Population Survey (BLS)
    first_run: '2026-06-27 09:00'
    latest_run: '2026-06-27 09:01'
    script_runtime: 0.2 min
    n_outputs: 2
    outputs:
    - output/age_dist.png
    - output/clean.csv

For write functions not in the built-in list, pass a list to extra_hooks with the function names and their file-path arguments:

tinytrail(
  description = "Export results",
  extra_hooks = list(
    fn  = c("readr::write_csv", "ggplot2::ggsave"),
    arg = c("file",             "filename")
  )
)

(These two functions are already captured automatically — they’re shown here for illustration only.)

Optionally, pipe data frames through tinytrail_dict() to capture column names and sample values:

# ... cleaning and preparing data ...

dat |>
  tinytrail_dict()

This adds a data dictionary entry to _tinytrail.yaml:

data_dictionary:
  01_clean.R:
    dat:
      columns:
        id: [1, 2, 3, 4, 5]
        age: [34, 52, 28, 41, 37]
        response: ['yes', 'no', 'yes', 'yes', 'no']

Manual tracking with auto = FALSE

To track only specific outputs, set auto = FALSE and use tinytrail_write() explicitly. It returns its argument invisibly, so it drops inline into any save call:

tinytrail("Export selected results", auto = FALSE)

write.csv(dat, tinytrail_write("output/clean.csv"))
saveRDS(model, tinytrail_write(here::here("output/model.rds")))

A pencil sketch of an alpine landscape with winding trails