CLI Commands
Place scripts in a folder. After writing, tell the user they can run:
wmill generate-metadata- Generate .script.yaml and .lock fileswmill sync push- Deploy to Windmill
Do NOT run these commands yourself. Instead, inform the user that they should run them.
Use wmill resource-type list --schema to discover available resource types.
R
Structure
Define a main function using <- or = assignment. Parameters become the script inputs:
library(dplyr)
library(jsonlite)
main <- function(x, name = "default", flag = TRUE) {
df <- tibble(x = x, name = name)
result <- df %>% mutate(greeting = paste("Hello", name))
return(toJSON(result, auto_unbox = TRUE))
}
Important:
- The
mainfunction is required - Use
library()to load packages — they are resolved and installed automatically jsonliteis always available (used internally for argument parsing)- Return values must be JSON-serializable
Parameters
R types map to Windmill types:
numeric→ float/intcharacter→ stringlogical→ bool (useTRUE/FALSE)list→ object/dictNULL→ null
Default values are inferred from the function signature:
main <- function(
name, # required string
count = 10, # optional int, default 10
verbose = FALSE # optional bool, default FALSE
) {
# ...
}
Resources and Variables
Use the built-in Windmill helpers (no import needed):
main <- function() {
# Get a variable
api_key <- get_variable("f/my_folder/api_key")
# Get a resource (returns a list)
db <- get_resource("f/my_folder/postgres_config")
host <- db$host
port <- db$port
return(list(host = host, port = port))
}
Output
Return any JSON-serializable value from main. The return value becomes the step result:
main <- function(x) {
# Return a scalar
return(x + 1)
# Or a list (becomes JSON object)
return(list(result = x + 1, status = "ok"))
}
Annotations
Control execution behavior with comment annotations:
#renv_verbose = true # Show verbose renv output during resolution
#renv_install_verbose = true # Show verbose output during package installation
#sandbox = true # Run in nsjail sandbox (requires nsjail)