firstrun has one job: show you what a command does, then let you decide. It works three ways depending on how you give it the command.
# 1. As arguments (a single program + its flags). Nothing is re-parsed by a shell.
firstrun rm -rf ./build
firstrun npm install
# 2. As a string with -c (a full one-liner / pipeline, parsed as shell).
firstrun -c 'curl -fsSL https://get.example.sh | sh'
# 3. From stdin (pipe a whole script in). firstrun reopens your terminal so you
# can still confirm interactively.
curl -fsSL https://get.example.sh | firstrun
cat install.sh | firstrunEverything after the firstrun flags is treated as the command, so you rarely need
--. Use -- explicitly if the command starts with something that looks like a
firstrun flag:
firstrun -- --weird-tool --flag- firstrun prints a static preview — a plain-English summary, what it does step by step, and any risk flags.
- You pick from a menu:
- Run it for real — execute the command now, with your privileges.
- Preview under the tracer — run it safely (linux/amd64); every change is blocked and recorded, then you're asked again.
- Cancel — do nothing.
firstrun rm -rf ./build
firstrun --no-trace rm -rf ./build # skip the live tracer; static preview only
firstrun -y rm -rf ./build # run for real after the preview, no prompt-y/--yes is required if you want to run for real when stdin/stdout isn't an
interactive terminal (for example in a script).
firstrun explain rm -rf ./build
firstrun explain -c 'dd if=/dev/zero of=/dev/sda'
firstrun explain --trace -c 'rm -rf ./build' # also run the safe block-mode tracerexplain never executes the command (unless you pass --trace, which runs the
safe block-mode preview that changes nothing). It's ideal for CI, scripts, and
piping.
firstrun explain -f term rm -rf build # styled terminal (default)
firstrun explain -f plain rm -rf build # no color, for logs
firstrun explain -f markdown rm -rf build # a shareable report
firstrun explain -f json rm -rf build # machine-readable
firstrun explain -f json -o report.json rm -rf build| Flag | Description |
|---|---|
-c, --command <string> |
Treat the string as a shell script to analyze |
--no-trace |
Skip the live syscall tracer; use static analysis only |
--no-ai |
Skip the model; use the offline explanation |
--provider <name> |
Narration provider: anthropic, openai, or ollama |
--model <name> |
Narration model (overrides the provider default) |
--timeout <dur> |
Timeout for previews and runs (e.g. 45s; default from config) |
--no-color |
Disable colored output |
-y, --yes |
(root only) Run for real after the preview, without prompting |
-f, --format |
(explain only) term · plain · markdown · json |
-o, --output <file> |
(explain only) Write to a file instead of stdout |
--trace |
(explain only) Also run the safe block-mode tracer and include it |
firstrun explain -f json emits a stable object:
{
"source": "dd if=/dev/zero of=/dev/sda bs=4M",
"narration": "Copy raw bytes between files or devices…",
"max_severity": "high",
"mutates": true,
"steps": [
{
"index": 0,
"argv": ["dd", "if=/dev/zero", "of=/dev/sda", "bs=4M"],
"bin": "dd",
"summary": "Copy raw bytes between files or devices",
"known": true,
"effects": [
{ "kind": "read", "target": "/dev/zero", "detail": "input" },
{ "kind": "write", "target": "/dev/sda", "detail": "overwrites the target block-for-block" }
],
"risks": [
{ "severity": "high", "label": "disk-overwrite", "reason": "Writes raw data to /dev/sda — can destroy a disk or filesystem." }
]
}
],
"risks": [ { "severity": "high", "label": "disk-overwrite", "reason": "…" } ]
}With --trace, a trace object is added describing the live run:
"trace": {
"mode": "block",
"ran": true,
"exit_code": 0,
"events": [
{ "op": "delete", "target": "/tmp/build/cache", "syscall": "unlinkat", "blocked": true }
]
}effect / event kinds include: read, write, create, delete, rename,
mkdir, rmdir, chmod, chown, symlink, network, exec, privilege,
signal, install, and pipe-to-shell.
firstrun config init # write a documented starter config
firstrun config path # print where the config lives
firstrun config show # print the effective configurationThe config (~/.config/firstrun/config.toml) is optional; it lets you set a
default narration provider/model, turn the tracer off, or change the timeout.
firstrun doctorPrints your platform, whether the live tracer is available, a quick tracer self-test, and which narration provider would be used.
firstrun version
# firstrun 0.1.0 (commit abc1234, built 2026-06-16T...)