Run command-line tools in a reproducible and isolated way, right from R.
Tired of system() calls that work on your machine but break everywhere else? condathis is here to help! It lets you create self-contained environments for your command-line tools, so your R code runs reliably for you, your colleagues, and your future self.
A Quick Example
Let’s have some fun with cowpy. With just two commands, we can install and run it in its own isolated environment:
# 1. Install 'cowpy' into an environment named 'cowpy-env'
condathis::create_env(packages = "cowpy", env_name = "cowpy-env")
#> ! Environment cowpy-env succesfully created.
# 2. Run it!
# Example showing redirection from a file to the Standard Input (STDIN)
temp_file <- tempfile()
writeLines("{condathis} is awesome!", temp_file)
condathis::run("cowpy", stdin = temp_file, env_name = "cowpy-env")
#> _________________________
#> < {condathis} is awesome! >
#> -------------------------
#> \ ^__^
#> \ (oo)\_______
#> (__)\ )\/\
#> ||----w |
#> || ||Maybe you want to try something fancier, like rich-cli for formatting messages?
condathis::create_env(packages = "rich-cli", env_name = "rich-cli-env")
#> ! Environment rich-cli-env succesfully created.
condathis::run(
"rich", "[b]Condathis[/b] is awesome!", "-p", "-a", "heavy",
env_name = "rich-cli-env"
)
#> ┏━━━━━━━━━━━━━━━━━━━━━━━┓
#> ┃ Condathis is awesome! ┃
#> ┗━━━━━━━━━━━━━━━━━━━━━━━┛That’s it! You can now package any command-line tool with your R script, ensuring it works everywhere, every time.
Get Started
Install the release version of the package from CRAN:
install.packages("condathis")Or get the development version from R-Universe:
install.packages("condathis", repos = c("https://luciorq.r-universe.dev", getOption("repos")))Why condathis?
R’s system() and system2() are powerful, but they depend on tools being installed on the host system. This creates a few problems:
- Reproducibility: Will your script from last year still work? Will your collaborator be able to run your code if they have a different version of a tool?
- Conflicts: What if two different tools need two different versions of the same dependency?
condathis solves these issues by creating isolated environments for each tool.
Reproducibility: An Example
Let’s say you’re using fastqc for quality control in a bioinformatics pipeline. Different versions of fastqc can produce slightly different results.
With condathis, you can lock in a specific version:
fastq_file <- system.file("extdata", "sample1_L001_R1_001.fastq.gz", package = "condathis")
temp_out_dir <- file.path(tempdir(), "output")
fs::dir_create(temp_out_dir)
# Always use fastqc version 0.12.1
condathis::create_env(packages = "fastqc==0.12.1", channels = c("conda-forge", "bioconda"), env_name = "fastqc-0.12.1")
#> ! Environment fastqc-0.12.1 succesfully created.
condathis::run("fastqc", fastq_file, "-o", temp_out_dir, env_name = "fastqc-0.12.1")
#> application/gzip
#> Started analysis of sample1_L001_R1_001.fastq.gz
#> Approx 90% complete for sample1_L001_R1_001.fastq.gz
#> Analysis complete for sample1_L001_R1_001.fastq.gzNow your analysis will produce the same output files, regardless of where or when it’s run.
Isolation: An Example
Need to use a specific version of a tool like curl that’s different from your system’s version? No problem.
Your system’s curl:
libcurlVersion()
#> [1] "8.7.1"
#> attr(,"ssl_version")
#> [1] "SecureTransport (LibreSSL/3.3.6)"
#> attr(,"libssh_version")
#> [1] ""
#> attr(,"protocols")
#> [1] "dict" "file" "ftp" "ftps" "gopher" "gophers" "http"
#> [8] "https" "imap" "imaps" "ldap" "ldaps" "mqtt" "pop3"
#> [15] "pop3s" "rtsp" "smb" "smbs" "smtp" "smtps" "telnet"
#> [22] "tftp"A specific curl version, isolated with condathis:
condathis::create_env(
packages = "curl==8.10.1",
env_name = "curl-env"
)
#> ! Environment curl-env succesfully created.
# Handling output thorough R objects
out <- condathis::run(
"curl", "--version",
env_name = "curl-env",
verbose = "silent"
)
message(out$stdout)
#> curl 8.10.1 (aarch64-apple-darwin20.0.0) libcurl/8.10.1 OpenSSL/3.5.4 (SecureTransport) zlib/1.3.1 zstd/1.5.7 libssh2/1.11.1 nghttp2/1.67.0
#> Release-Date: 2024-09-18
#> Protocols: dict file ftp ftps gopher gophers http https imap imaps ipfs ipns mqtt pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp ws wss
#> Features: alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM SPNEGO SSL threadsafe TLS-SRP UnixSockets zstdThis allows you to run tools with conflicting dependencies side-by-side without any issues.
How It Works
The package condathis relies on micromamba to bring reproducibility and isolation. micromamba is a lightweight, fast, and efficient package manager that “does not need a base environment and does not come with a default version of Python”.
The integration of micromamba into R is handled using the processx and withr packages.
Known Caveats
Special characters in CLI commands are interpreted as literals and not expanded.
- It is not supported the use of output redirections in commands, e.g. “|” or “>”.
- Instead of redirects (e.g. “>”), use the argument
stdout = "<FILENAME>.txt". Instead of Pipes (“|”), simple run multiple calls tocondathis::run(), usingstdoutargument to control the output andstdinto control the input of each command. P.S. The current implementation only supports files as the “STDIN”.
- Instead of redirects (e.g. “>”), use the argument
- File paths should not use special characters for relative paths, e.g. “~”, “.”, “..”.
- Expand file paths directly in R, using
basefunctions or functions from thefspackage.
- Expand file paths directly in R, using
