> Comprehensive R package for command-line interface styling, semantic messaging, (1) Format console output with inline markup and colors, (2) Display errors, warnings, or messages with cli_abort/cli_warn/cli_inform, (3) Show progress indicators for long-running operations, (4) Create semantic CLI elements (headers, lists, alerts, code blocks), (5) Apply themes and customize output styling, (6) Handle pluralization in user-facing text, (7) Work with ANSI strings, hyperlinks, or custom containers. Also use when migrating from base R message/warning/stop, debugging cli code, or improving existing cli usage.
npx skills add https://github.com/posit-dev/skills --skill cli
task: Display error with context and formatting
use: cli_abort() with inline markup and bullet lists
task: Show warning with formatting
use: cli_warn() with inline markup
task: Display informative message
use: cli_inform() with inline markup
task: Show progress for counted operations
use: cli_progress_bar() with total count
task: Show simple progress steps
use: cli_progress_step() with status messages
task: Format code or function names
use: {.code ...} or {.fn package::function}
task: Format file paths
use: {.file path/to/file}
task: Format package names
use: {.pkg packagename}
task: Format variable names
use: {.var variable_name}
task: Format values
use: {.val value}
task: Handle singular/plural text
use: {?s} or {?y/ies} with pluralization
task: Create headers
use: cli_h1(), cli_h2(), cli_h3()
task: Create alerts
use: cli_alert_success(), cli_alert_danger(), cli_alert_warning(), cli_alert_info()
task: Create lists
use: cli_ul(), cli_ol(), cli_dl() with cli_li()
Use inline markup with {.class content} syntax to format text:
# Basic formatting
cli_text("Function {.fn mean} calculates averages")
cli_text("Install package {.pkg dplyr}")
cli_text("See file {.file ~/.Rprofile}")
cli_text("{.var x} must be numeric, not {.obj_type_of {x}}")
cli_text("Got value {.val {x}}")
# Code formatting
cli_text("Use {.code sum(x, na.rm = TRUE)}")
# Paths and arguments
cli_text("Reading from {.path /data/file.csv}")
cli_text("Set {.arg na.rm} to TRUE")
# Types and classes
cli_text("Object is {.cls data.frame}")
# Emphasis
cli_text("This is {.emph important}")
cli_text("This is {.strong critical}")
# Fields
cli_text("The {.field name} field is required")
Vectors are automatically collapsed with commas and "and":
pkgs <- c("dplyr", "tidyr", "ggplot2")
cli_text("Installing packages: {.pkg {pkgs}}")
#> Installing packages: dplyr, tidyr, and ggplot2
files <- c("data.csv", "script.R")
cli_text("Found {length(files)} file{?s}: {.file {files}}")
#> Found 2 files: data.csv and script.R
Use double braces {{ and }} to escape literal braces:
cli_text("Use {{variable}} syntax in glue")
#> Use {variable} syntax in glue
For complete markup reference: See references/inline-markup.md for all 50+ inline classes, edge cases, nesting rules, and advanced patterns.
Use {?} for pluralization with three patterns:
nfile <- 1
cli_text("Found {nfile} file{?s}")
#> Found 1 file
nfile <- 3
cli_text("Found {nfile} file{?s}")
#> Found 3 files
ndir <- 1
cli_text("Found {ndir} director{?y/ies}")
#> Found 1 directory
ndir <- 5
cli_text("Found {ndir} director{?y/ies}")
#> Found 5 directories
nfile <- 0
cli_text("Found {nfile} file{?s}: {?no/the/the} file{?s}")
#> Found 0 files: no files
nfile <- 1
cli_text("Found {nfile} file{?s}: {?no/the/the} file{?s}")
#> Found 1 file: the file
nfile <- 3
cli_text("Found {nfile} file{?s}: {?no/the/the} file{?s}")
#> Found 3 files: the files
Use no() to display "no" instead of zero:
nfile <- 0
cli_text("Found {no(nfile)} file{?s}")
#> Found no files
Use qty() to set quantity explicitly:
nupd <- 3
ntotal <- 10
cli_text("{nupd}/{ntotal} {qty(nupd)} file{?s} {?needs/need} updates")
#> 3/10 files need updates
For advanced pluralization: See references/inline-markup.md for edge cases and complex patterns.
Use cli conditions instead of base R for better formatting:
# Before (base R)
stop("File not found: ", path)
# After (cli)
cli_abort("File {.file {path}} not found")
# With bullets for context
check_file <- function(path) {
if (!file.exists(path)) {
cli_abort(c(
"File not found",
"x" = "Cannot read {.file {path}}",
"i" = "Check that the file exists"
))
}
}
# Before (base R)
warning("Column ", col, " has missing values")
# After (cli)
cli_warn("Column {.field {col}} has missing values")
# With context
cli_warn(c(
"Data quality issues detected",
"!" = "Column {.field {col}} has {n_missing} missing value{?s}",
"i" = "Consider using {.fn tidyr::drop_na}"
))
# Before (base R)
message("Processing ", n, " files")
# After (cli)
cli_inform("Processing {n} file{?s}")
# With structure
cli_inform(c(
"v" = "Successfully loaded {.pkg dplyr}",
"i" = "Version {packageVersion('dplyr')}"
))
"x" - Error/problem (red X)"!" - Warning (yellow !)"i" - Information (blue i)"v" - Success (green checkmark)"*" - Bullet point">" - Arrow/pointerFor advanced error design: See references/conditions.md for error design principles, rlang integration, testing strategies, and real-world patterns.
process_data <- function() {
cli_progress_step("Loading data")
data <- load_data()
cli_progress_step("Cleaning data")
clean <- clean_data(data)
cli_progress_step("Analyzing data")
analyze(clean)
}
process_files <- function(files) {
cli_progress_bar("Processing files", total = length(files))
for (file in files) {
process_file(file)
cli_progress_update()
}
}
Progress bars auto-close when the function exits:
process <- function() {
cli_progress_bar("Working", total = 100)
for (i in 1:100) {
Sys.sleep(0.01)
cli_progress_update()
}
# No need to call cli_progress_done() - auto-closes
}
For advanced progress: See references/progress.md for nested progress, custom formats, parallel processing, all progress variables, and Shiny integration.
cli_h1("Main Section")
cli_h2("Subsection")
cli_h3("Detail")
cli_alert_success("Operation completed successfully")
cli_alert_danger("Critical error occurred")
cli_alert_warning("Potential issue detected")
cli_alert_info("Additional information available")
# Regular text with markup
cli_text("This is formatted text with {.emph emphasis}")
# Code blocks
cli_code(c(
"library(dplyr)",
"mtcars %>% filter(mpg > 20)"
))
# Verbatim text (no formatting)
cli_verbatim("This is displayed exactly as-is: {not interpolated}")
# Unordered list
cli_ul()
cli_li("First item")
cli_li("Second item")
cli_end()
# Ordered list
cli_ol()
cli_li("First step")
cli_li("Second step")
cli_end()
# Definition list
cli_dl()
cli_li(c(name = "The name field"))
cli_li(c(email = "The email address"))
cli_end()
# Before: Base R error handling
validate_input <- function(x, y) {
if (!is.numeric(x)) {
stop("x must be numeric")
}
if (length(y) == 0) {
stop("y cannot be empty")
}
if (length(x) != length(y)) {
stop("x and y must have the same length")
}
}
# After: CLI error handling
validate_input <- function(x, y) {
if (!is.numeric(x)) {
cli_abort(c(
"{.arg x} must be numeric",
"x" = "You supplied a {.cls {class(x)}} vector",
"i" = "Use {.fn as.numeric} to convert"
))
}
if (length(y) == 0) {
cli_abort(c(
"{.arg y} cannot be empty",
"i" = "Provide at least one element"
))
}
if (length(x) != length(y)) {
cli_abort(c(
"{.arg x} and {.arg y} must have the same length",
"x" = "{.arg x} has length {length(x)}",
"x" = "{.arg y} has length {length(y)}"
))
}
}
check_required_columns <- function(data, required_cols) {
actual_cols <- names(data)
missing_cols <- setdiff(required_cols, actual_cols)
if (length(missing_cols) > 0) {
cli_abort(c(
"Required column{?s} missing from data",
"x" = "Missing {length(missing_cols)} column{?s}: {.field {missing_cols}}",
"i" = "Data has {length(actual_cols)} column{?s}: {.field {actual_cols}}",
"i" = "Add the missing column{?s} or check for typos"
))
}
invisible(data)
}
process_files <- function(files, verbose = TRUE) {
n <- length(files)
if (verbose) {
cli_progress_bar(
format = "Processing {cli::pb_bar} {cli::pb_current}/{cli::pb_total} [{cli::pb_eta}]",
total = n
)
}
results <- vector("list", n)
for (i in seq_along(files)) {
results[[i]] <- process_file(files[[i]])
if (verbose) {
cli_progress_update()
}
}
results
}
{} syntaxUse Expo DOM components to run web code in a webview on native and as-is on web. Migrate web code to native incrementally.
Frontend development guidelines for React/TypeScript applications. Modern patterns including Suspense, lazy loading, useSuspenseQuery, file organization with features directory, MUI v7 styling, TanStack Router, performance optimization, and TypeScript best practices. Use when creating components, pages, features, fetching data, styling, routing, or working with frontend code.
Next.js 16 Cache Components - PPR, use cache directive, cacheLife, cacheTag, updateTag
| Build Shopify apps, extensions, themes using GraphQL Admin API, Shopify CLI, Polaris UI, and Liquid. "shopify theme", "liquid template", "polaris", "shopify graphql", "shopify webhook", "shopify billing", "app subscription", "metafields", "shopify functions"
Build Gradio web UIs and demos in Python. Use when creating or editing Gradio apps, components, event listeners, layouts, or chatbots.
MANDATORY prerequisite — load this skill BEFORE every `generate_diagram` tool call. NEVER call `generate_diagram` directly without loading this skill first. Trigger whenever the user asks to create, generate, draw, render, sketch, or build a diagram — flowchart, architecture diagram, sequence diagram, ERD or entity-relationship diagram, state diagram or state machine, gantt chart, or timeline. Also trigger when the user mentions Mermaid syntax or wants a system architecture, decision tree, dependency graph, API call flow, auth handshake, schema, or pipeline visualized in FigJam. Routes to type-specific guidance, sets universal Mermaid constraints, and tells you when to use a different diagram type or skip the tool entirely (mindmaps, pie charts, class diagrams, etc.).
Analyzes web performance using Chrome DevTools MCP. Measures Core Web Vitals (LCP, INP, CLS) and supplementary metrics (FCP, TBT, Speed Index), identifies render-blocking resources, network dependency chains, layout shifts, caching issues, and accessibility gaps. Use when asked to audit, profile, debug, or optimize page load performance, Lighthouse scores, or site speed. Biases towards retrieval from current documentation over pre-trained knowledge.
Algorithmic philosophies are computational aesthetic movements that are then expressed through code. Output .md files (philosophy), .html files (interactive viewer), and .js files (generative algorithms).
Take posit-dev/cli from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.