Terminal Commands
Different ways to run commands like you do in a terminal. These functions are identical on basic-webserver.
Code
app [main!] { cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.21.0/4rAQg8kUYZ3Vksr4qMQHpaFYNiHSn9GgS7gVxghd1XYV.tar.zst", roc: "nightly-2026-08-12-606470f", } import cli.Stdout import cli.Cmd import cli.OsStr # Different ways to run commands like you do in a terminal. main! = |_args| { # Simplest way to execute a command (prints to your terminal). Cmd.exec!("echo", ["Hello"])? # To execute and capture the output (stdout and stderr) without inheriting your terminal. cmd_output = Cmd.new("echo") .args(["Hi"]) .exec_output!()? Stdout.line!("${Str.inspect(cmd_output)}")? # To run a command with environment variables. Cmd.new("env") .clear_envs() # You probably don't need to clear all other environment variables, this is just an example. .env("FOO", "BAR") .envs([("BAZ", "DUCK"), ("XYZ", "ABC")]) # Set multiple environment variables at once with `envs` .exec_cmd!()? # To execute and just get the exit code (prints to your terminal). # Prefer using `exec!` or `exec_cmd!`. exit_code = Cmd.new("cat") .args(["non_existent.txt"]) .exec_exit_code!()? Stdout.line!("Exit code: ${exit_code.to_str()}")? # To execute and capture the output (stdout and stderr) in the original form as bytes without inheriting your terminal. # Prefer using `exec_output!`. cmd_output_bytes = Cmd.new("echo") .args(["Hi"]) .exec_output_bytes!()? Stdout.line!("${Str.inspect(cmd_output_bytes)}")? Ok({}) }
Output
Run this from the directory that has main.roc in it:
$ roc main.roc
Hello
{ stderr_utf8_lossy: "", stdout_utf8: "Hi
" }
BAZ=DUCK
FOO=BAR
XYZ=ABC
cat: non_existent.txt: No such file or directory
Exit code: 1
{ stderr_bytes: [], stdout_bytes: [72, 105, 10] }