Skip to content

CLI reference

The pluvial binary is both the compiler and the runtime. Running it with no arguments starts the REPL; running it with a file compiles and runs that file.

Terminal window
pluvial # start the REPL (no arguments)
pluvial file.plu # compile and run file.plu
pluvial run file.plu # explicit run subcommand
pluvial --version # print the version and exit
pluvial -v # same as --version
pluvial --help # print usage and exit
pluvial -h # same as --help
  • pluvial file.plu is the standard way to run a program. The .plu extension is a convention, not a requirement.
  • run and check are additions, not replacements — pluvial file.plu still runs the file implicitly.
  • --help is written to stdout (so it can be piped to a pager); a usage error is written to stderr and exits with code 64.
Terminal window
pluvial run file.plu [args...]

Compiles and runs the file. Trailing arguments are available to the program through std/os’s args().

Terminal window
pluvial check file.plu

Compiles the source and reports type errors without executing the program — a dry run for editor integration, pre-commit hooks, and CI.

  • On success: exit 0, no output (“no news is good news”), so pluvial check $f && next-step composes naturally.
  • On failure: exit 65, printing the full error block (colored if stderr is a TTY).
Terminal window
pluvial format [--check] <file>...
pluvial format - # read stdin, write stdout

Formats source files. The style is: 4-space indentation, { kept on the keyword line (def f() int {, } else {), spaces around binary operators and after commas, no trailing whitespace, and a single trailing newline. Parentheses are placed precedence-aware (the minimum needed to reproduce the same AST).

  • Formatting is idempotentformat(format(x)) == format(x).
  • Comments are not preserved (the scanner removes them before the AST).
  • --check prints a diff and exits 1 when there is a formatting difference (exit 0 when there is none) — useful as a CI gate.
Terminal window
pluvial test [file|dir] # no argument → current directory

Runs tests. A directory is searched recursively for *_test.plu files. Tests are written with std/test. Output looks like:

===== pluvial test =====
math_test.plu
✓ add works
✗ multiply fails
expected: 0
got: 1
===== 3 passed, 1 failed =====

When everything passes, the summary is ===== N passed =====.

Terminal window
pluvial doc file.plu # generate Markdown to stdout
pluvial doc -o dir/ # write Markdown files to a directory

Generates documentation from ## doc comments, which attach to the declaration that follows them (def, struct, enum, or a top-level variable).

Terminal window
pluvial lsp

Starts a Language Server Protocol server over stdin/stdout (JSON-RPC 2.0 with Content-Length framing). It provides diagnostics (publishDiagnostics), hover (textDocument/hover), and go-to-definition (textDocument/definition). A VS Code extension (vscode-pluvial) is provided; other editors can point their LSP client at pluvial lsp directly.

Terminal window
pluvial build file.plu [-o name]

Ahead-of-time compilation. Pluvial lowers the program through its SSA IR to LLVM IR and produces a stand-alone native executable. It resolves the dependency closure, caches per-module objects under ~/.pluvial/cache/, and links everything into one binary. This requires LLVM (llc) and clang. (pluvial run and the REPL always use the bytecode VM and are unaffected.)

Running pluvial with no arguments starts an interactive Read-Eval-Print Loop:

$ pluvial
Pluvial REPL — type 'exit' to quit
> 1 + 2
3
> "hello".to_upper()
HELLO
> int x = 5
> x + 1
6
> def double(int n) int { return n * 2 }
> double(7)
14
> exit
$
  • Typing an expression prints its value. Declarations, assignments, and control-flow statements do not print.
  • Declarations persist across lines — globals, functions, and structs stay defined for the whole session.
  • Errors do not end the session. A compile error (65) or runtime error (70) prints its block and re-prompts; the session state is untouched.
  • Re-declaring a global is allowed in the REPL (the slot and type can be replaced), because the previous line has already run. Re-declaring a function or struct is still an error, as in file mode.
  • The session ends on EOF (Ctrl-D) or by typing exit / quit on a line.

Pluvial follows the sysexits convention:

CodeMeaning
0Success
64Misuse of the CLI (wrong number of arguments)
65Compile error (type error, syntax error, static error)
66Could not open or read the input file
70Runtime error (division by zero, stack overflow)

Error blocks use ANSI color when stderr is a TTY:

  • error: / runtime error: — bold red
  • --> file:line:col — bold
  • caret span ^^^ — bold red
  • = help: — bold blue
  • gutter | and the source line — unstyled

When stderr is not a TTY (pipes, CI, test harnesses), color is suppressed entirely and the output is byte-identical to the uncolored form.