重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/posit-dev/skills --skill r-cli-appRapp (v0.3.0) 是一个 R 语言包,它提供了一个可直接替代 Rscript 的工具,能够自动将命令行参数解析为 R 值。它可以将简单的 R 脚本转变为功能完善的 CLI 应用程序,具备参数解析、帮助文本和子命令支持——无需任何样板代码。
R ≥ 4.1.0 | CRAN: install.packages("Rapp") | GitHub: r-lib/Rapp
安装后,将 Rapp 启动器添加到 PATH 路径中:
Rapp::install_pkg_cli_apps("Rapp")
这会将 Rapp 可执行文件放置在 ~/.local/bin (macOS/Linux) 或 %LOCALAPPDATA%\Programs\R\Rapp\bin (Windows)。
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
Rapp 扫描 R 脚本的顶层表达式,并将特定模式转换为 CLI 结构。这意味着:
source() 执行和作为 CLI 工具运行时,行为完全一致。只有顶层赋值语句会被识别。函数、循环或条件语句内部的赋值不会被解析为 CLI 参数。
此表是 Rapp 的核心——每个 R 模式都会自动映射到一个 CLI 界面:
| R 顶层表达式 | CLI 界面 | 说明 |
|---|---|---|
foo <- "text" | --foo <value> | 字符串选项 |
foo <- 1L | --foo <int> | 整数选项 |
foo <- 3.14 | --foo <float> | 浮点数选项 |
foo <- TRUE / FALSE | --foo / --no-foo | 布尔开关 |
foo <- NA_integer_ | --foo <int> | 可选整数 (NA = 未设置) |
foo <- NA_character_ | --foo <str> | 可选字符串 (NA = 未设置) |
foo <- NULL | 位置参数 | 默认必需 |
foo... <- NULL | 可变位置参数 | 零个或多个值 |
foo <- c() | 可重复的 --foo | 多个值作为字符串 |
foo <- list() | 可重复的 --foo | 多个值解析为 YAML/JSON |
switch("", cmd1={}, cmd2={}) | 子命令 | app cmd1, app cmd2 |
switch(cmd <- "", ...) | 子命令 | 同上;在 cmd 中捕获命令名称 |
n <- 5L 意味着 --n 10 会得到整数 10L。!is.na(myvar) 进行测试。n_flips → --n-flips。#!/usr/bin/env Rapp
在 chmod +x 之后,使脚本在 macOS/Linux 上可直接执行。在 Windows 上,需显式调用 Rapp myscript.R。
在任何代码之前的井号管道注释 (#|) 用于设置脚本级别的元数据:
#!/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 `|`.
name: 字段设置帮助输出中的应用程序名称(默认为文件名)。
将 #| 注释紧接在它们要注解的赋值语句之前:
#| description: Number of coin flips
#| short: 'n'
flips <- 1L
可用的注解字段:
| 字段 | 用途 |
|---|---|
description: | 在 --help 中显示的帮助文本 |
title: | 显示标题(用于子命令和前置元数据) |
short: | 单字母别名,例如 'n' → -n |
required: | true/false —— 仅用于位置参数 |
val_type: | 覆盖类型:string、integer、float、bool、any |
arg_type: | 覆盖 CLI 类型:option、switch、positional |
action: | 对于可重复选项:replace 或 append |
为常用选项添加 #| short: —— 用户期望常见标志(如 verbose (-v)、output (-o) 或 count (-n))有单字母快捷方式。
标量字面量赋值变为命名选项:
name <- "world" # --name <value> (字符串,默认 "world")
count <- 1L # --count <int> (整数,默认 1)
threshold <- 0.5 # --threshold <flt> (浮点数,默认 0.5)
seed <- NA_integer_ # --seed <int> (可选,省略时为 NA)
output <- NA_character_ # --output <str> (可选,省略时为 NA)
对于可选参数,测试用户是否提供了它们:
seed <- NA_integer_
if (!is.na(seed)) set.seed(seed)
TRUE/FALSE 赋值变为开关:
verbose <- FALSE # --verbose 或 --no-verbose
wrap <- TRUE # --wrap (默认) 或 --no-wrap
值 yes/true/1 设置为 TRUE;no/false/0 设置为 FALSE。
pattern <- c() # --pattern '*.csv' --pattern 'sales-*' → 字符向量
threshold <- list() # --threshold 5 --threshold '[10,20]' → 解析后的值列表
使用 NULL 赋值表示位置参数(默认必需):
#| description: The input file to process.
input_file <- NULL
使用 #| required: false 使其变为可选。使用 is.null(myvar) 进行测试。
使用 ... 后缀来收集多个位置值:
pkgs... <- c()
# install-pkgs dplyr ggplot2 tidyr → pkgs... = c("dplyr", "ggplot2", "tidyr")
使用第一个参数为字符串的 switch() 来声明子命令。switch() 之前的选项是全局的;分支内部的选项是该子命令局部的。
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
}
)
帮助是作用域化的:myapp --help 列出命令;myapp list --help 显示特定于 list 的选项以及全局选项。子命令可以通过在分支内放置另一个 switch() 来嵌套。
每个 Rapp 应用程序都会自动获得 --help(人类可读)和 --help-yaml(机器可读)。这些也适用于子命令。
使用 Rapp::run() 从 R 会话中测试脚本:
Rapp::run("path/to/myapp.R", c("--help"))
Rapp::run("path/to/myapp.R", c("--name", "Alice", "--count", "5"))
它(不可见地)返回评估环境以供检查,并支持 browser() 进行交互式调试。
#!/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
生成的帮助:
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]
#!/usr/bin/env Rapp
#| name: todo
#| description: Manage a simple todo list.
#| description: Path to the todo list file.
#| short: s
store <- ".todo.yml"
switch(
command <- "",
list = {
#| description: Max entries to display (-1 for all).
limit <- 30L
tasks <- if (file.exists(store)) yaml::read_yaml(store) else list()
if (!length(tasks)) {
cat("No tasks yet.\n")
} else {
if (limit >= 0L) tasks <- head(tasks, limit)
writeLines(sprintf("%2d. %s\n", seq_along(tasks), tasks))
}
},
add = {
#| description: Task description to add.
task <- NULL
tasks <- if (file.exists(store)) yaml::read_yaml(store) else list()
tasks[[length(tasks) + 1L]] <- task
yaml::write_yaml(tasks, store)
cat("Added:", task, "\n")
},
done = {
#| description: Index of the task to complete.
#| short: i
index <- 1L
tasks <- if (file.exists(store)) yaml::read_yaml(store) else list()
task <- tasks[[as.integer(index)]]
tasks[[as.integer(index)]] <- NULL
yaml::write_yaml(tasks, store)
cat("Completed:", task, "\n")
}
)
todo add "Write quarterly report"
todo list
todo list --limit 5
todo done 1
todo --store /tmp/work.yml list
将 CLI 脚本放在 exec/ 目录下,并在 DESCRIPTION 文件的 Imports 中添加 Rapp:
mypkg/
├── DESCRIPTION
├── R/
├── exec/
│ ├── myapp # 带有 #!/usr/bin/env Rapp shebang 的脚本
│ └── myapp2
└── man/
用户在安装包后安装 CLI 启动器:
Rapp::install_pkg_cli_apps("mypkg")
提供一个便捷的安装器,这样用户就不需要了解 Rapp:
#' Install mypkg CLI apps
#' @export
install_mypkg_cli <- function(destdir = NULL) {
Rapp::install_pkg_cli_apps(package = "mypkg", destdir = destdir)
}
默认情况下,启动器设置 --default-packages=base,<pkg>,因此只有 base 和该包会被自动加载。对于其他依赖项,请使用 library()。
NA_integer_, NA_character_) → 可选的命名选项。测试:!is.na(x)。#| required: false → 可选的位置参数。测试:!is.null(x)。input_file <- NA_character_
con <- if (is.na(input_file)) file("stdin") else file(input_file, "r")
lines <- readLines(con)
writeLines(lines, stdout())
message("Error: something went wrong") # 写入到 stderr
cat("Error:", msg, "\n", file = stderr()) # 同样写入到 stderr
quit(status = 1) # 非零退出
tryCatch({
result <- do_work()
}, error = function(e) {
cat("Error:", conditionMessage(e), "\n", file = stderr())
quit(status = 1)
})
对于不太常见的主题——启动器自定义(#| launcher: 前置元数据)、详细的 Rapp::install_pkg_cli_apps() API 选项,以及更完整的示例(去重过滤器、可变参数安装包、交互式回退)——请阅读 references/advanced.md。
每周安装数
52
代码仓库
GitHub 星标数
205
首次出现
2026年3月6日
安全审计
安装于
opencode48
gemini-cli45
codex45
cursor45
claude-code44
github-copilot44
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).
Rapp scans top-level expressions of an R script and converts specific patterns into CLI constructs. This means:
source() and as a CLI tool.Only top-level assignments are recognized. Assignments inside functions, loops, or conditionals are not parsed as CLI arguments.
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 / |
n <- 5L means --n 10 gives integer 10L.!is.na(myvar).n_flips → --n-flips.#!/usr/bin/env Rapp
Makes the script directly executable on macOS/Linux after chmod +x. On Windows, call Rapp myscript.R explicitly.
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).
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/ — for positional args only |
Add #| short: for frequently-used options — users expect single-letter shortcuts for common flags like verbose (-v), output (-o), or count (-n).
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)
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.
pattern <- c() # --pattern '*.csv' --pattern 'sales-*' → character vector
threshold <- list() # --threshold 5 --threshold '[10,20]' → list of parsed values
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).
Use ... suffix to collect multiple positional values:
pkgs... <- c()
# install-pkgs dplyr ggplot2 tidyr → pkgs... = c("dplyr", "ggplot2", "tidyr")
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.
Every Rapp automatically gets --help (human-readable) and --help-yaml (machine-readable). These work with subcommands too.
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.
#!/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]
#!/usr/bin/env Rapp
#| name: todo
#| description: Manage a simple todo list.
#| description: Path to the todo list file.
#| short: s
store <- ".todo.yml"
switch(
command <- "",
list = {
#| description: Max entries to display (-1 for all).
limit <- 30L
tasks <- if (file.exists(store)) yaml::read_yaml(store) else list()
if (!length(tasks)) {
cat("No tasks yet.\n")
} else {
if (limit >= 0L) tasks <- head(tasks, limit)
writeLines(sprintf("%2d. %s\n", seq_along(tasks), tasks))
}
},
add = {
#| description: Task description to add.
task <- NULL
tasks <- if (file.exists(store)) yaml::read_yaml(store) else list()
tasks[[length(tasks) + 1L]] <- task
yaml::write_yaml(tasks, store)
cat("Added:", task, "\n")
},
done = {
#| description: Index of the task to complete.
#| short: i
index <- 1L
tasks <- if (file.exists(store)) yaml::read_yaml(store) else list()
task <- tasks[[as.integer(index)]]
tasks[[as.integer(index)]] <- NULL
yaml::write_yaml(tasks, store)
cat("Completed:", task, "\n")
}
)
todo add "Write quarterly report"
todo list
todo list --limit 5
todo done 1
todo --store /tmp/work.yml list
Place CLI scripts in exec/ and add Rapp to Imports in DESCRIPTION:
mypkg/
├── DESCRIPTION
├── R/
├── exec/
│ ├── myapp # script with #!/usr/bin/env Rapp shebang
│ └── myapp2
└── man/
Users install the CLI launchers after installing the package:
Rapp::install_pkg_cli_apps("mypkg")
Expose a convenience installer so users don't need to know about Rapp:
#' Install mypkg CLI apps
#' @export
install_mypkg_cli <- function(destdir = NULL) {
Rapp::install_pkg_cli_apps(package = "mypkg", destdir = destdir)
}
By default, launchers set --default-packages=base,<pkg>, so only base and the package are auto-loaded. Use library() for other dependencies.
NA_integer_, NA_character_) → optional named option. Test: !is.na(x).#| required: false → optional positional arg. Test: !is.null(x).input_file <- NA_character_
con <- if (is.na(input_file)) file("stdin") else file(input_file, "r")
lines <- readLines(con)
writeLines(lines, stdout())
message("Error: something went wrong") # writes to stderr
cat("Error:", msg, "\n", file = stderr()) # also stderr
quit(status = 1) # non-zero exit
tryCatch({
result <- do_work()
}, error = function(e) {
cat("Error:", conditionMessage(e), "\n", file = stderr())
quit(status = 1)
})
For less common topics — launcher customization (#| launcher: front matter), detailed Rapp::install_pkg_cli_apps() API options, and more complete examples (deduplication filter, variadic install-pkg, interactive fallback) — read references/advanced.md.
Weekly Installs
52
Repository
GitHub Stars
205
First Seen
Mar 6, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode48
gemini-cli45
codex45
cursor45
claude-code44
github-copilot44
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
125,600 周安装
项目安全设置协调器 - 自动化安全扫描、配置与风险评估工具
221 周安装
TypeScript/Python/.NET项目代码检查工具自动配置 - ESLint, Ruff, Roslyn Analyzers
220 周安装
React前端项目重构与脚手架生成工具 - 支持单体迁移和最小化项目创建
221 周安装
任务文档创建器:自动化生成任务管理文档与Linear看板集成
221 周安装
ln-100-documents-pipeline:自动化文档生成流水线,一键创建完整项目文档系统
222 周安装
Babylon.js 3D引擎入门教程 - 从场景初始化到相机系统完整指南
220 周安装
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 |
falseval_type: | Override type: string, integer, float, bool, any |
arg_type: | Override CLI type: option, switch, positional |
action: | For repeatable options: replace or append |