Quickstart
Scaffold a profile, validate it, and run your first scan.
On this page
This page takes you from an empty directory to a saved JSON result you can re-render, diff, and file as evidence. It should take about ten minutes.
Scaffold a profile
refpoint init my-baseline --title "My Baseline" --author "Platform Team"That writes a profile root and one example control:
my-baseline/
├── profile.rpp
└── controls/
└── example.rpcprofile.rpp carries a commented allowed_commands hint. Without it, the
first command check anyone adds is refused with no obvious cause.
Write a control
Open my-baseline/controls/example.rpc and replace the example with something
you actually care about.
control "ssh-01" {
title = "SSH root login is disabled"
description = "Direct root login over SSH removes accountability."
impact = 0.9
remediation = "Set PermitRootLogin no in /etc/ssh/sshd_config and reload sshd."
platform = ["linux"]
tags = {
category = "ssh"
}
only_if "package" {
name = "openssh-server"
installed = true
}
check "root-login" "sshd_config" {
option "PermitRootLogin" {
value = "no"
}
}
}The only_if block is a precondition. On a host with no SSH server the control
is reported as skipped with a reason, rather than failing for a service that
was never meant to be there.
Validate before you run
refpoint check my-baselinecheck parses the profile and decodes every check body, only_if
precondition, and any_of member against its resource provider. It collects
every problem in one pass instead of stopping at the first, and each finding
renders with a clickable path:line:col and a “did you mean” suggestion.
It also reports which executables the profile’s command checks would run:
Profile "my-baseline" is valid (12 controls loaded)
Commands used: getent, systemctl
Declares no allowed_commands, so the operator's list governs alone.
Run with: --allowed-commands getent,systemctlRun it
refpoint run my-baselineWith no target given, the run defaults to local. Every run prints a
three-line banner to stderr before anything else:
refpoint <version>
config loaded: <absolute path or "none">
profiles run: <absolute path>That goes to stderr, not stdout, so a report streaming to stdout is never
contaminated. The config path is announced because the working directory is
searched first, and a config.toml shipped inside a cloned repository would
otherwise govern the run silently.
Preview a fleet run first
refpoint run my-baseline --targets web-01,web-02 --dry-runThe dry run opens transports, probes each target’s platform, and classifies
every control as run, waive, or skip with a reason. It executes no checks
and always exits 0. Controls guarded by only_if are marked conditional, since
the precondition is decided on the target at run time.
Save the result and work with it
refpoint run my-baseline --format json --output result.json
refpoint report result.json --format html --output report.html
refpoint tui result.json
refpoint diff last-week.json result.jsonThe JSON file is the artifact of record. Re-renderings produced by report are
derivative and are not attested.
Read the exit code
| Code | Condition |
|---|---|
| 0 | Everything passed |
| 1 | At least one control failed, and either no threshold was set or the score met it |
| 2 | At least one target was unreachable or a control errored |
| 5 | Controls failed and the weighted score fell below --threshold |
| 130 | Interrupted by SIGINT or SIGTERM |
Code 2 is the one to watch in CI. It means the scan could not see part of what it was asked to look at, which is a broken run rather than a fleet to remediate. Unreachable targets are counted separately and are never pruned from the report, so a job that reached only half its hosts can never report a clean pass.