Receber por email
← Voltar para o catálogo

r-cli-app

Build command-line apps in R using the Rapp package. Use when creating a CLI tool in R, adding argument parsing to an R script, turning an R script into a command-line app, shipping CLIs in an R package, or using Rapp (the alternative Rscript front-end). Also use for shebang scripts, exec/ directory in R packages, or subcommand-based R tools.

403estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add posit-dev/skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/r-cli-app/svg)](https://www.skillteca.com.br/skills/r-cli-app)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Building CLI Apps with Rapp

Rapp (v0.3.0) is an R package that provides a drop-in replacement for Rscript that automatically parses command-line arguments into R values. It turns simple R scripts into polished CLI apps with argument parsing, help text, and subcommand support — with zero boilerplate.

R ≥ 4.1.0 | CRAN: install.packages("Rapp") | GitHub: r-lib/Rapp

After installing, put the Rapp launcher on PATH:

Rapp::install_pkg_cli_apps("Rapp")

This places the Rapp executable in ~/.local/bin (macOS/Linux) or %LOCALAPPDATA%\Programs\R\Rapp\bin (Windows).

Core Concept: Scripts Are the Spec

Rapp scans top-level expressions of an R script and converts specific patterns into CLI constructs. This means:

  1. The same script works identically via source() and as a CLI tool.
  2. You write normal R code — Rapp infers the CLI from what you write.
  3. Default values in your R code become the CLI defaults.

Only top-level assignments are recognized. Assignments inside functions, loops, or conditionals are not parsed as CLI arguments.

Pattern Recognition: R → CLI Mapping

This table is the heart of Rapp — each R pattern automatically maps to a CLI surface:

| R Top-Level Expression | CLI Surface | Notes | |---|---|---| | foo <- "text" | --foo <value> | String option | | foo <- 1L | --foo <int> | Integer option | | foo <- 3.14 | --foo <float> | Float option | | foo <- TRUE / FALSE | --foo / --no-foo | Boolean toggle | | foo <- NA_integer_ | --foo <int> | Optional integer (NA = not set) | | foo <- NA_character_ | --foo <str> | Optional string (NA = not set) | | foo <- NULL | positional arg | Required by default | | foo... <- NULL | variadic positional | Zero or more values | | foo <- c() | repeatable --foo | Multiple values as strings | | foo <- list() | repeatable --foo | Multiple values parsed as YAML/JSON | | switch("", cmd1={}, cmd2={}) | subcommands | app cmd1, app cmd2 | | switch(cmd <- "", ...) | subcommands | Same; captures command name in cmd |

Type behavior

  • Non-string scalars are parsed as YAML/JSON at the CLI and coerced to the

R type of the default. n <- 5L means --n 10 gives integer 10L.

  • NA defaults signal optional arguments. Test with !is.na(myvar).
  • Snake case variable names map to kebab-case: n_flips → --n-flips.
  • Positional args always arrive as character strings — convert manually.

Script Structure

Shebang line

#!/usr/bin/env Rapp

Makes the script directly executable on macOS/Linux after chmod +x. On Windows, call Rapp myscript.R explicitly.

Front matter metadata

Hash-pipe comments (#|) before any code set script-level metadata:

#!/usr/bin/env Rapp
#| name: my-app
#| title: My App
#| description: |
#|   A short description of what this app does.
#|   Can span multiple lines using YAML block scalar `|`.

The name: field sets the app name in help output (defaults to filename).

Per-argument annotations

Place #| comments immediately before the assignment they annotate:

#| description: Number of coin flips
#| short: 'n'
flips <- 1L

Available annotation fields:

| Field | Purpose | |---|---| | description: | Help text shown in --help | | title: | Display title (for subcommands and front matter) | | short: | Single-letter alias, e.g. 'n' → -n | | required: | true/false — for positional args only | | val_type: | Override type: string, integer, float, bool, any | | arg_type: | Override CLI type: option, switch, positional | | action: | For repeatable options: replace or append |

Add #| short: for frequently-used options — users expect single-letter shortcuts for common flags like verbose (-v), output (-o), or count (-n).

Named Options

Scalar literal assignments become named options:

name <- "world"          # --name <value>    (string, default "world")
count <- 1L              # --count <int>     (integer, default 1)
threshold <- 0.5         # --threshold <flt> (float, default 0.5)
seed <- NA_integer_      # --seed <int>      (optional, NA if omitted)
output <- NA_character_  # --output <str>    (optional, NA if omitted)

For optional arguments, test whether the user supplied them:

seed <- NA_integer_
if (!is.na(seed)) set.seed(seed)

Boolean Switches

TRUE/FALSE assignments become toggles:

verbose <- FALSE   # --verbose or --no-verbose
wrap <- TRUE       # --wrap (default) or --no-wrap

Values yes/true/1 set TRUE; no/false/0 set FALSE.

Repeatable Options

pattern <- c()     # --pattern '*.csv' --pattern 'sales-*'  → character vector
threshold <- list() # --threshold 5 --threshold '[10,20]'   → list of parsed values

Positional Arguments

Assign NULL for positional args (required by default):

#| description: The input file to process.
input_file <- NULL

Make optional with #| required: false. Test with is.null(myvar).

Variadic positional args

Use ... suffix to collect multiple positional values:

pkgs... <- c()
# install-pkgs dplyr ggplot2 tidyr → pkgs... = c("dplyr", "ggplot2", "tidyr")

Subcommands

Use switch() with a string first argument to declare subcommands. Options before the switch() are global; options inside branches are local to that subcommand.

switch(
  command <- "",

  #| title: Display the todos
  list = {
    #| description: Max entries to display (-1 for all).
    limit <- 30L
    # ... list implementation
  },

  #| title: Add a new todo
  add = {
    #| description: Task description to add.
    task <- NULL
    # ... add implementation
  },

  #| title: Mark a task as completed
  done = {
    #| description: Index of the task to complete.
    index <- 1L
    # ... done implementation
  }
)

Help is scoped: myapp --help lists commands; myapp list --help shows list-specific options plus globals. Subcommands can nest by placing another switch() inside a branch.

Built-in Help

Every Rapp automatically gets --help (human-readable) and --help-yaml (machine-readable). These work with subcommands too.

Development and Testing

Interactive Development

Use Rapp::run() to test scripts from an R session:

Rapp::run("path/to/myapp.R", c("--help"))
Rapp::run("path/to/myapp.R", c("--name", "Alice", "--count", "5"))

It returns the evaluation environment (invisibly) for inspection, and supports browser() for interactive debugging.

Testing CLI Apps in Packages

Use Rapp::run() with testthat snapshot testing. Test computed values by accessing the returned environment, and test output with expect_snapshot().

See [references/advanced.md](references/advanced.md#testing-cli-apps) for detailed testing patterns, including:

  • Accessing computed values via the evaluation environment
  • Snapshot testing for help output and formatted text
  • Testing file side effects and state changes

Complete Example: Coin Flipper

#!/usr/bin/env Rapp
#| name: flip-coin
#| description: |
#|   Flip a coin.

#| description: Number of coin flips
#| short: 'n'
flips <- 1L

sep <- " "
wrap <- TRUE

seed <- NA_integer_
if (!is.na(seed)) {
  set.seed(seed)
}

cat(sample(c("heads", "tails"), flips, TRUE), sep = sep, fill = wrap)
flip-coin            # heads
flip-coin -n 3       # heads tails heads
flip-coin --seed 42 -n 5
flip-coin --help

Generated help:

Usage: flip-coin [OPTIONS]

Flip a coin.

Options:
  -n, --flips <FLIPS>  Number of coin flips [default: 1] [type: integer]
      --sep <SEP>      [default: " "] [type: string]
      --wrap / --no-wrap  [default: true]
      --seed <SEED>    [default: NA] [type: integer]

Complete Example: Todo Manager (Subcommands)

#!/usr/bin/env Rapp
#| name: todo
#| description: Manage a simple todo list.

#| description: Path to the todo list
Compartilhar X LinkedIn