Collin K. Berke, Ph.D.
  • Home
  • About
  • Now
  • Blog
  • Updates
  • Say Hi!

On this page

  • Background
  • The approach
  • Wrap up
  • Let’s connect

Notes: Validating system dependencies for Rapp

notes
rapp
How to make sure users have the needed tools when ‘shelling out’
Author

Collin K. Berke, Ph.D.

Published

July 9, 2026

Background

Recently, I’ve been using Rapp to develop CLI tools. Now that I’m creating some useful tools (useful to me anyways), my intent is to make them accessible to other folks. To do this, I want to make them available within an R package. Some of these tools, however, “shell out” to other CLI tools not natively installed on a user’s system. When this happens, errors are thrown, confusion sets in, headaches ensue, and the user is left blindly guessing at missing setup steps. What if we could catch this issue right away? What if when the user doesn’t have the needed dependency they receive some useful information on how to perform the setup? Validation checking is the answer.

Note

This post from rOpenSci warns how wrappers to CLI tools is not always a great approach. I heed these warnings related to a “shell out”. But for simple utilities, I’m not going to write C or C++ code to perform some straightforward actions a CLI tool has already implemented.

Here’s my thought process for this validation check:

  1. Print version information for the wrapped CLI tool (if any is available).
  2. Parse the version info to check for presence of the tool.
  3. If the tool isn’t available on the user’s system, print info on how to obtain it.

The approach

To achieve this, the approach I came up with includes the use of some Base R, the stringr, and cli packages. Specifically, the Base R system2() function is used to run the system command via R. stringr is used to identify if the specific package dependency is available via string pattern detection. cli is used to print useful information to the user in cases the system dependency isn’t available.

Let’s break down the entire function:

is_bq_installed <- function() {
  gcloud_version_info <- system2("gcloud", args = "version", stdout = TRUE)

  if (!any(stringr::str_detect(gcloud_version_info, "bq"))) {
    cli::cli_alert_danger("Google Cloud SDK not available.")
    cli::cli_alert_info(
      "See install docs at {.url https://docs.cloud.google.com/sdk/docs/install-sdk}."
    )
  }
}

The first step here is to print the version information, if any is available. In my case, many of the utilities I’ve been working on wrap commands from Google Cloud’s bq CLI tool. This line makes the system call in R to get the version information:

gcloud_version_info <- system2("gcloud", args = "version", stdout = TRUE)

One thing that tripped me up about using system2() is the args argument is what passes the flags for the system command, unlike the older system() Base R function. The other important bit here is stdout = TRUE. Setting this allows the command’s output to be returned to R as a character vector. This is useful for later parsing.

Since I’m interested in making sure users have the required dependency, I use this set of code to check if it’s available:

!any(stringr::str_detect(gcloud_version_info, "bq"))

The reason for str_detect() here should be pretty obvious. It’s detecting the presence of a string pattern in the character vector, ‘bq’ in this case.

The any() function returns a single TRUE or FALSE boolean if any of the values in the character vector are TRUE. The use of ! flips it. Thus, if the “bq” string is not detected, the end result is FALSE, which then kicks off the control statement:

if (!any(stringr::str_detect(gcloud_version_info, "bq"))) {
  cli::cli_alert_danger("Google Cloud SDK not available.")
  cli::cli_alert_info(
    "See install docs at {.url https://docs.cloud.google.com/sdk/docs/install-sdk}."
  )
}

At this point, it’s using some functions from the cli package to push installation information to the user.

Wrap up

This feels like a reasonable approach to system dependency checking when doing some simple CLI tool wrapping. Indeed, if you’re attempting to do something more advanced, I highly suggest reviewing rOpenSci’s blog post. I hope this saves some time for anyone facing this same issue.

Let’s connect

If you found this content useful, please share. If you find these topics interesting and want to discuss further, let’s connect:

  • BlueSky: @collinberke.bsky.social
  • LinkedIn: collinberke
  • GitHub: @collinberke
  • Say Hi!

Reuse

CC BY 4.0

Citation

BibTeX citation:
@misc{berke2026,
  author = {Berke, Collin K},
  title = {Notes: {Validating} System Dependencies for {Rapp}},
  date = {2026-07-09},
  langid = {en}
}
For attribution, please cite this work as:
Berke, Collin K. 2026. Notes: Validating System Dependencies for Rapp. accepted, July 9.