Skip to content

Commit f41dcf0

Browse files
authored
Rapp v0.3.0 (#781)
* empty template `hugodown::use_tidy_post("rapp-0-3-0")` * Add Rapp v0.3.0 announcement post * Updates after review from @rich-iannone * final proofread
1 parent 0ca1031 commit f41dcf0

File tree

4 files changed

+451
-0
lines changed

4 files changed

+451
-0
lines changed

content/blog/rapp-0-3-0/index.Rmd

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
---
2+
output: hugodown::hugo_document
3+
4+
slug: rapp-0-3-0
5+
title: Rapp 0.3.0
6+
date: 2026-02-18
7+
author: Tomasz Kalinowski
8+
description: >
9+
Rapp is an R front-end (like Rscript) that turns simple scripts into polished CLIs,
10+
with automatic argument parsing, generated help, and support for
11+
commands and installable launchers.
12+
13+
photo:
14+
url: https://unsplash.com/photos/two-yellow-red-blue-papers-Ay7Nkvc49ag
15+
author: Carolina Garcia Tavizon
16+
17+
18+
# one of: "deep-dive", "learn", "package", "programming", "roundup", or "other"
19+
categories: [package]
20+
tags: [r-lib, package, programming, yaml]
21+
---
22+
23+
We're excited to share our first tidyverse blog post for Rapp, alongside the `0.3.0` release. Rapp helps you turn R scripts into polished command-line tools, with argument parsing and help generation built in.
24+
25+
## Why a command-line interface for R?
26+
27+
A command-line interface (CLI) lets you run programs from a terminal, without opening an IDE or starting an interactive R session. This is useful when you want to:
28+
29+
- automate tasks via cron jobs, scheduled tasks, or CI/CD pipelines
30+
- chain R scripts together with other tools in data pipelines
31+
- let others run your R code without needing to know R
32+
- package reusable tools that feel native to the terminal
33+
- expose specific actions through a clean interface that LLM agents can invoke
34+
35+
There are several established packages for building CLIs in R, including argparse, optparse, and docopt, where you explicitly parse and handle command-line arguments in code. Rapp takes a different approach: it derives the CLI surface from the structure of your R script and injects values at runtime, so you never need to handle CLI arguments manually.
36+
37+
## How Rapp works
38+
39+
At its core, Rapp is an alternative front-end to R: a drop-in replacement for `Rscript` that automatically turns common R expression patterns into command-line options, switches, positional arguments, and subcommands. You write normal R code and Rapp handles the CLI surface.
40+
41+
Rapp also uses special `#|` comments (similar to Quarto's YAML-in-comments syntax) to add metadata such as help descriptions and short aliases.
42+
43+
## A tiny example
44+
45+
Here's a complete Rapp script (from the package examples), a coin flipper:
46+
47+
```r
48+
#!/usr/bin/env Rapp
49+
#| name: flip-coin
50+
#| description: |
51+
#| Flip a coin.
52+
53+
#| description: Number of coin flips
54+
#| short: 'n'
55+
flips <- 1L
56+
57+
sep <- " "
58+
wrap <- TRUE
59+
60+
seed <- NA_integer_
61+
if (!is.na(seed)) {
62+
set.seed(seed)
63+
}
64+
65+
cat(sample(c("heads", "tails"), flips, TRUE), sep = sep, fill = wrap)
66+
```
67+
68+
Let's break down how Rapp interprets this script:
69+
70+
| R code | Generated CLI option | What it does |
71+
|--------|------------|-------------|
72+
| `flips <- 1L` | `--flips` or `-n` | Integer option with default of 1 |
73+
| `sep <- " "` | `--sep` | String option with default of `" "` |
74+
| `wrap <- TRUE` | `--wrap` / `--no-wrap` | Boolean toggle (TRUE/FALSE becomes on/off) |
75+
| `seed <- NA_integer_` | `--seed` | Optional integer (NA means "not set") |
76+
77+
The `#| short: 'n'` comment adds `-n` as a short alias for `--flips`. The `#!/usr/bin/env Rapp` line (called a "shebang") lets you run the script directly on macOS and Linux without typing `Rapp` first.
78+
79+
### Running the script
80+
81+
With Rapp installed and `flip-coin` available on your `PATH` (see [Get started](#get-started) below), you can run the app from the terminal:
82+
83+
```sh
84+
flip-coin -n 3
85+
#> heads tails heads
86+
87+
flip-coin --seed 42 -n 5
88+
#> tails heads tails tails heads
89+
```
90+
91+
### Auto-generated help
92+
93+
Rapp generates `--help` from your script (and `--help-yaml` if you want a machine-readable spec):
94+
95+
```sh
96+
flip-coin --help
97+
```
98+
99+
```text
100+
Usage: flip-coin [OPTIONS]
101+
102+
Flip a coin.
103+
104+
Options:
105+
-n, --flips <FLIPS> Number of coin flips [default: 1] [type: integer]
106+
--sep <SEP> [default: " "] [type: string]
107+
--wrap / --no-wrap [default: true] Disable with `--no-wrap`.
108+
--seed <SEED> [default: NA] [type: integer]
109+
```
110+
111+
::: {.callout-warning}
112+
## Breaking change in 0.3.0: positional arguments are now required by default
113+
114+
If you're upgrading from an earlier version of Rapp, note that positional arguments are now **required** unless explicitly marked optional.
115+
116+
```r
117+
# Before 0.3.0: this positional was optional
118+
name <- NULL
119+
120+
# In 0.3.0+: add this comment to keep it optional
121+
#| required: false
122+
name <- NULL
123+
```
124+
125+
If your scripts use positional arguments with `NULL` defaults that should remain optional, add `#| required: false` above them.
126+
:::
127+
128+
## Highlights in 0.3.0
129+
130+
Rapp will be new to most readers, so rather than listing every change, here are the main ideas (and what's improved in 0.3.0).
131+
132+
### Options, switches, and repeatable flags from plain R
133+
134+
Rapp recognizes a small set of "declarative" patterns at the top level of your script:
135+
136+
- Scalar literals like `flips <- 1L` become options like `--flips 10`.
137+
- Logical defaults like `wrap <- TRUE` become toggles like `--wrap` / `--no-wrap`.
138+
- `#| short: n` adds a short alias like `-n` (new in 0.3.0).
139+
- `c()` and `list()` defaults declare repeatable options (new in 0.3.0): callers can supply the same flag multiple times and values are appended.
140+
141+
### Subcommands with `switch()`
142+
143+
Rapp can now turn a `switch()` block into subcommands (and you can nest `switch()` blocks for nested commands). Here's a small sketch of a `todo`-style app:
144+
145+
```r
146+
#!/usr/bin/env Rapp
147+
#| name: todo
148+
#| description: Manage a simple todo list.
149+
150+
#| description: Path to the todo list file.
151+
#| short: s
152+
store <- ".todo.yml"
153+
154+
switch(
155+
command <- "",
156+
157+
#| description: Display the todos
158+
list = {
159+
limit <- 30L
160+
# ...
161+
},
162+
163+
#| description: Add a new todo
164+
add = {
165+
task <- NULL
166+
# ...
167+
}
168+
)
169+
```
170+
171+
Help is scoped to the command you're asking about, so `todo --help` lists the commands, and `todo list --help` shows just the options/arguments for `list` (plus any parent/global options).
172+
173+
### Installable launchers for package CLIs
174+
175+
A big part of sharing CLI tools is making them easy to run after installation. In `0.3.0`, `install_pkg_cli_apps()` installs lightweight launchers for scripts in a package's `exec/` directory that use either `#!/usr/bin/env Rapp` or `#!/usr/bin/env Rscript`:
176+
177+
```r
178+
Rapp::install_pkg_cli_apps("mypackage")
179+
```
180+
181+
(There's also `uninstall_pkg_cli_apps()` to remove a package's launchers.)
182+
183+
## Get started
184+
185+
Here's the quickest path to your first Rapp script:
186+
187+
```r
188+
# 1. Install the package
189+
install.packages("Rapp")
190+
```
191+
192+
```r
193+
# 2. Install the command-line launcher
194+
Rapp::install_pkg_cli_apps("Rapp")
195+
```
196+
197+
Then create a script (e.g., `hello.R`):
198+
199+
```{.r filename="hello.R"}
200+
#!/usr/bin/env Rapp
201+
#| name: hello
202+
#| description: Say hello
203+
204+
name <- "world"
205+
cat("Hello,", name, "\n")
206+
```
207+
208+
And run it:
209+
210+
```sh
211+
Rapp hello.R --name "R users"
212+
#> Hello, R users
213+
```
214+
215+
### Learn more
216+
217+
To dig deeper into Rapp:
218+
219+
- browse examples in the package: `system.file("examples", package = "Rapp")`
220+
- read the full documentation: <https://github.com/r-lib/Rapp>
221+
- note that Rapp requires R ≥ 4.1.0
222+
223+
If you try Rapp, we'd love feedback! We especially want to hear about your experiences with edge cases in argument parsing, help output, and how commands should feel. Issues and ideas are welcome at <https://github.com/r-lib/Rapp/issues>.

0 commit comments

Comments
 (0)