Reference
Command-line reference
Every command, flag, exit code, environment variable, policy key and risk signal of SwiftProof v0.3.0. Press / to search.
Synopsis
swiftproof init [--repo PATH] [--language go|typescript|javascript|python]
swiftproof lint [--base main] [--head HEAD] [--ci] [flags]
swiftproof review [--base main] [--reviewer=false] [--ci] [flags]
swiftproof review [flags] BASE..HEAD
swiftproof report [--input .swiftproof/confidence-report.json] [--out DIR]
swiftproof version
- lint analyzes a change statically. It never executes repository code and never calls an AI provider.
- review adds sandboxed checks in Docker and, when a model is configured, an AI investigation.
- Only committed files are analyzed; uncommitted edits and untracked files are ignored.
- Reports are written to
.swiftproof/in the repository by default. Console output stays short. - Flags accept one or two dashes (
-cior--ci). Booleans are set with--cior--ci=trueand cleared with--checks=false. A value is given as--base mainor--base=main. - Run
swiftproof <command> --helpfor the flags of a command.
Choosing revisions
Both sides of a comparison resolve to immutable commit IDs, recorded in the report. Renames, deletions, binary files and file type changes are handled.
| Form | Compares |
|---|---|
--base main (default) | From the merge base of main and --head to --head, like a pull request. Commits added to main since the branch point are not part of the change. |
--base main --exact | From the tip of main directly to --head. |
BASE..HEAD | The two exact commits, for example HEAD~1..HEAD to review the last commit. Overrides --base, --head and --exact. |
BASE...HEAD | From the merge base of the two revisions to HEAD. |
A range may appear before or after the flags: swiftproof review main..HEAD --ci and swiftproof review --ci main..HEAD are equivalent. At most one range is accepted. Any revision Git understands works: branches, tags, origin/main, HEAD~3 or a commit ID. CI jobs need enough history to resolve the base (for example fetch-depth: 0).
The trusted policy is always read from the base branch, never from the change under review, so a pull request cannot loosen its own rules.
swiftproof lint
Static analysis of a change: Git comparison, risk signals and a report. No Docker, no provider call, no execution of repository code. Safe to run on untrusted branches.
| Flag | Default | Description |
|---|---|---|
--base REV | main | Base branch or revision. The comparison starts at its merge base with --head; its tip supplies the trusted policy. |
--head REV | HEAD | Candidate revision under review. |
--exact | false | Compare the base revision itself instead of the merge base. |
BASE..HEAD | — | Positional range; see Choosing revisions. |
--repo PATH | . | Repository directory. Any directory inside the work tree works. |
--config PATH | policy of the base | Use this local policy file instead of .swiftproof.json from the base branch. Only pass a file you trust. |
--out DIR | .swiftproof | Report directory, relative to the repository root. The path may not contain symbolic links. |
--format LIST | markdown,json | Comma-separated report formats to write: markdown, json. |
--ci | false | Exit with code 2 when human review is required. See Exit codes. |
--intent TEXT | — | Pull request intent or acceptance criteria, recorded in the report (at most 64 KiB). |
--intent-file PATH | — | Read the intent from a UTF-8 file. Cannot be combined with --intent. |
--checks, --reviewer | false | Must stay false: lint exits with code 3 if either is enabled. Use review. |
swiftproof lint HEAD~1..HEAD # the last commit
swiftproof lint --base origin/main --ci # this branch as a pull request, for CI
swiftproof lint --base main --format json # JSON report only
swiftproof review
Everything lint does, plus the policy's test, typecheck, build and coverage commands in disposable Docker containers, plus an AI investigation when a model is configured. Requires Docker with Linux containers and a preloaded sandbox.image.
| Flag | Default | Description |
|---|---|---|
--base REV | main | Base branch or revision. The comparison starts at its merge base with --head; its tip supplies the trusted policy. |
--head REV | HEAD | Candidate revision under review. |
--exact | false | Compare the base revision itself instead of the merge base. |
BASE..HEAD | — | Positional range; see Choosing revisions. |
--repo PATH | . | Repository directory. |
--config PATH | policy of the base | Use this local policy file instead of .swiftproof.json from the base branch, for example to try a policy before committing it. Only pass a file you trust: it decides what runs and where source is sent. |
--out DIR | .swiftproof | Report directory, relative to the repository root. Artifacts go to DIR/artifacts/. |
--format LIST | markdown,json | Comma-separated report formats to write: markdown, json. |
--ci | false | Exit with code 2 when human review is required, including high-risk signals, unverified areas or incomplete checks. |
--checks | true | Run the configured checks in the sandbox. --checks=false skips them; a configured reviewer may still run sandbox experiments. |
--reviewer | auto | AI investigation. Enabled automatically when a model is set in the trusted policy or SWIFTPROOF_REVIEWER_MODEL. --reviewer=false disables every provider call; --reviewer fails with exit 3 if no model is configured. |
--max-iterations N | policy (20) | Override reviewer.max_iterations for this run, 1 to 100. |
--intent TEXT | — | Pull request intent or acceptance criteria (at most 64 KiB). Recorded in the report and given to the reviewer. |
--intent-file PATH | — | Read the intent from a UTF-8 file. Cannot be combined with --intent. |
--allow-network | false | Give sandbox containers network access. Takes effect only if the trusted policy also sets sandbox.network: true. |
--no-network | false | Force sandbox networking off. Does not affect reviewer API calls; add --reviewer=false for that. |
swiftproof review --base main --ci # typical pull request run
swiftproof review HEAD~1..HEAD --reviewer=false # checks only, no provider
swiftproof review --base main --checks=false --reviewer=false # static only, like lint
swiftproof review --base main --intent-file PR.md # give acceptance criteria
Checks run in the order test, typecheck, build, then coverage. Each container is non-root, has a read-only root and source mount, no added capabilities, no network by default, and the CPU, memory, PID and time limits of the sandbox policy. The Docker socket, your working checkout and API keys are never mounted. If Docker or the image is missing, the run ends with exit 4; nothing ever falls back to your host.
swiftproof init
Write a starter .swiftproof.json for the project. It refuses to overwrite an existing file. Review the commands and image, then commit the file to your base branch.
| Flag | Default | Description |
|---|---|---|
--repo PATH | . | Directory in which to create .swiftproof.json. |
--language NAME | detected | go, typescript, javascript, python or unknown. Detected from go.mod/go.work, tsconfig.json, package.json, then pyproject.toml/setup.py. Selects the defaults. |
swiftproof report
Re-render a saved JSON report, for example to regenerate Markdown in CI. Nothing is re-run, and re-rendering does not authenticate the evidence it contains.
| Flag | Default | Description |
|---|---|---|
--input PATH | .swiftproof/confidence-report.json | Saved JSON report (version 1, at most 64 MiB). |
--out DIR | .swiftproof | Output directory, relative to the current directory. |
--format LIST | markdown,json | Comma-separated formats to write: markdown, json. |
swiftproof version and help
| Command | Prints |
|---|---|
swiftproof version, --version | The version, for example swiftproof v0.3.0, and the license notice. |
swiftproof help, -h, --help | The synopsis. With no argument, SwiftProof prints the same text. |
swiftproof <command> --help | The flags of a command, with their defaults. |
Exit codes
| Code | Meaning |
|---|---|
0 | Report completed without a reproduced high or critical issue. Without --ci, unresolved areas do not change this code. |
1 | A high or critical hypothesis is supported by a differential failure: a generated test passed on the base and failed on the candidate. |
2 | With --ci only: human review required, including high-risk signals, unverified areas or incomplete checks. |
3 | Invalid arguments, Git comparison, or trusted configuration (including an unknown policy key or command name). |
4 | Operational error in the harness, analysis or report writing, such as Docker or the sandbox image being unavailable, or a check that could not run. |
No code means "approved". A 0 says that nothing was reproduced, not that the change is correct.
Environment variables
The AI provider belongs to the deployment rather than to the repository, so these settings can come from the environment. Nothing else can: the image, commands, budgets and sensitive paths are always decided by the trusted policy.
| Variable | Effect |
|---|---|
SWIFTPROOF_REVIEWER_ENDPOINT | Overrides reviewer.endpoint. Same URL rules as the policy. |
SWIFTPROOF_REVIEWER_MODEL | Overrides reviewer.model, and on its own enables the reviewer during review. |
SWIFTPROOF_API_KEY | API key. The name is set by reviewer.api_key_env; this is the default. |
SWIFTPROOF_API_KEY_FILE | Path of a file containing the key, used when the variable above is unset. The file must be readable, or the run fails with exit 3. |
/run/secrets/SWIFTPROOF_API_KEY | Docker secret read last, when neither variable is set. Absence is not an error. |
A blank variable counts as unset. Key files are read whole with surrounding whitespace stripped, bounded to 8 KiB and must hold a single line. When the reviewer runs, the log names where each value came from, never the value itself. Whoever controls this environment chooses where redacted source is sent: keep it out of jobs that run untrusted fork code.
Output files
| Path | Contents |
|---|---|
.swiftproof/CONFIDENCE_REPORT.md | The report to read: change summary, automated checks, investigation summary, reproduced issues, unverified areas, suggested human review, review surface, changed-line execution, recorded evidence and artifacts. |
.swiftproof/confidence-report.json | The same data for tools: commit IDs, changed lines, signals, checks, hypotheses, evidence, audit events and artifact hashes. See the JSON schema. |
.swiftproof/artifacts/ | Check logs, coverage profiles and generated test sources, each referenced by its SHA-256 hash in the report. |
Add .swiftproof/ to .gitignore. The console prints one summary: files and lines changed, number of signals and reproduced issues, the focused review surface and changed-line execution.
Risk signals
Signals are reasons to look, not confirmed defects. Go files get syntax-aware analysis; other languages use labelled text heuristics. Signals on the same lines are merged into one review range in the report.
| Kind | Severity | Raised when |
|---|---|---|
sensitive_path | high | A changed path matches a sensitive_paths glob. |
auth_change | high | A Go function whose name suggests authentication or authorization has its body changed, or a changed line mentions authorization, authentication, JWT, bcrypt, argon2, CSRF or CORS. |
sensitive_function_change | high | A Go function whose name suggests payments (payment, refund, charge, capture, withdraw, deposit, balance…) has its body changed. |
validation_removed | high | A removed line called a validation, assertion or sanitizing function, or raised a validation error. |
public_api_change | high medium | Go: an exported declaration was removed or changed (high) or added (medium). Other languages: a line looks like a public declaration (medium). |
database_write | high | A changed line looks like a database mutation or transaction (INSERT, UPDATE … SET, .Exec(, .Commit(…). |
dynamic_execution | high | eval, process execution, subprocess, child_process, innerHTML and similar. |
type_suppression | high | Type or lint suppression such as @ts-ignore, as any, unsafe, nolint, eslint-disable. |
migration_change | high | A path containing migration or ending in .sql changed. |
infrastructure_change | high | A GitHub workflow, Dockerfile or Terraform file changed. |
file_type_change | high | Git reports a type change, for example a file becoming a symbolic link. |
network_change | medium | A changed line makes HTTP, gRPC or socket calls, or contains a URL. |
error_handling_change | medium | Error checks, wrapping, panic/recover, catch or except changed. |
dependency_change | medium | A dependency manifest or lockfile changed (go.mod, package.json, Cargo.lock, pyproject.toml…). |
uncovered_change | medium low | Added Go lines were not executed by the recorded coverage run. Low when the coverage run itself failed. |
branch_growth | medium | At least five more lines with branch constructs were added than removed in a file. Not a complexity metric. |
large_change | medium | More than 400 lines changed in one file. |
file_deleted | medium | A tracked file was removed. |
binary_change | medium | A binary file changed and cannot be analyzed as text. |
analysis_limited | medium | Go declaration analysis could not complete for a file, for example because it does not parse. |
no_test_change | low | A source file changed and no test file in the same directory or with the same name stem changed. Existing coverage is not measured. |
todo_added | low | A TODO, FIXME, HACK or XXX marker was added. |
Policy file: .swiftproof.json
The policy decides which commands run, in which image, with which limits, and whether an AI provider is used. It is read from .swiftproof.json on the base branch, or from --config PATH. When there is none, built-in defaults for the detected language apply. Keys you omit take the default values shown below.
The file must be a single JSON object of at most 1 MiB. Unknown keys, unknown command names and duplicate keys are rejected with exit 3, so an older binary rejects a key it does not know.
| Key | Type | Default | Description |
|---|---|---|---|
version | integer | 1 | Policy format version. Must be 1. |
language | string | detected | Language written by init. Informational. |
{
"version": 1,
"language": "go",
"commands": {
"test": ["go", "test", "./..."],
"typecheck": ["go", "vet", "./..."],
"build": ["go", "build", "./..."],
"generated_test": ["go", "test", "{package}"],
"coverage": ["go", "test", "-covermode=count", "-coverprofile={coverage_out}", "./..."]
},
"sandbox": { "image": "golang:1.26-bookworm", "network": false, "timeout_seconds": 120,
"max_runtime_seconds": 600, "max_output_bytes": 65536, "memory_mb": 1024, "cpus": 2 },
"reviewer": { "endpoint": "https://api.openai.com/v1/chat/completions", "model": "",
"api_key_env": "SWIFTPROOF_API_KEY", "max_iterations": 20, "max_generated_tests": 10,
"timeout_seconds": 600, "max_input_bytes": 131072 },
"sensitive_paths": ["**/auth/**", "**/payment*/**", "**/migrations/**", ".github/workflows/**", ".swiftproof.json"]
}
commands
Each command is an argv array, not a shell string: ["npm", "test"], never "npm test". At most 128 arguments; configure only the checks your project provides.
| Key | Placeholders | Description |
|---|---|---|
commands.test | — | Test suite, run by review. |
commands.typecheck | — | Type or static check, for example go vet or tsc --noEmit. |
commands.build | — | Build command. |
commands.generated_test | {file}, {package} | How the AI reviewer's temporary tests are run on base and candidate. Go's default uses the test's package so it can exercise unexported code. Verified Go experiments need a single standalone target placeholder. |
commands.coverage | {coverage_out} (exactly once) | Go only. Measures which added lines a sandbox run executed. Runs last, in addition to test, within sandbox.max_runtime_seconds. Add -coverpkg=./... to attribute execution across packages. |
sandbox
| Key | Default | Allowed | Description |
|---|---|---|---|
sandbox.image | golang:1.26-bookworm | image name | Preloaded image with the toolchain and dependencies. Never pulled by SwiftProof; pin it by digest if you can. |
sandbox.network | false | boolean | Allow container networking. Also requires --allow-network on the command line. |
sandbox.timeout_seconds | 120 | 1–3600 | Time limit of each command. |
sandbox.max_runtime_seconds | 600 | 1–7200 | Total sandbox time for the run, shared by checks and experiments. |
sandbox.max_output_bytes | 65536 | 1024–4194304 | Captured output kept per command. |
sandbox.memory_mb | 1024 | 128–32768 | Memory limit of each container, in MiB. |
sandbox.cpus | 2 | 1–32 | CPU limit of each container. |
reviewer
| Key | Default | Allowed | Description |
|---|---|---|---|
reviewer.model | "" | model ID | Tool-capable model. Empty disables the reviewer. Overridden by SWIFTPROOF_REVIEWER_MODEL. |
reviewer.endpoint | https://api.openai.com/v1/chat/completions | URL | Chat Completions endpoint with function calling; a /v1 base URL also works. HTTPS, or HTTP on loopback only. No credentials, query or fragment; redirects are refused. |
reviewer.api_key_env | SWIFTPROOF_API_KEY | variable name | Environment variable holding the key; <NAME>_FILE and /run/secrets/<NAME> follow it. Empty for a provider that needs no key. |
reviewer.max_iterations | 20 | 1–100 | Model turns per investigation. --max-iterations overrides it. |
reviewer.max_generated_tests | 10 | 0–100 | Temporary tests the reviewer may create. |
reviewer.timeout_seconds | 600 | 1–1800 | Total time for the investigation. |
reviewer.max_input_bytes | 131072 | 4096–2097152 | Bound on source context sent to the provider. |
sensitive_paths
Globs of paths that always raise a high sensitive_path signal when changed. Paths are relative to the repository root with forward slashes; * matches within a path segment and ** across segments. Absolute paths, backslashes and .. are rejected.
| Default glob | Covers |
|---|---|
**/auth/** | Any auth directory. |
**/payment*/** | payment, payments and similar directories. |
**/migrations/** | Database migrations. |
.github/workflows/** | CI workflows. |
.swiftproof.json | The policy itself. |
Language defaults
Written by swiftproof init, and used when the base branch has no policy. Stock Node.js and Python images do not contain your dependencies: build an image that does and adapt the commands.
| Language | Image | Commands |
|---|---|---|
go | golang:1.26-bookworm | test go test ./... · typecheck go vet ./... · build go build ./... · generated_test go test {package} · coverage go test -covermode=count -coverprofile={coverage_out} ./... |
typescript, javascript | node:22-bookworm | test npm test · build npm run build |
python | python:3.13-bookworm | test python -m unittest discover · generated_test python -m unittest {file} |
unknown | golang:1.26-bookworm | No commands: review runs no checks until you add them. |
AI reviewer
Optional. When a model is configured, review lets it investigate the change with bounded tools: reading redacted files and diffs, searching source, running existing checks, and creating and running temporary tests on base and candidate. It has no shell and no URL fetcher. Its claims stay hypotheses until a test reproduces a difference.
{
"reviewer": {
"endpoint": "https://your-provider.example/v1",
"model": "your-tool-capable-model",
"api_key_env": "SWIFTPROOF_API_KEY"
}
}
export SWIFTPROOF_API_KEY=… # from your shell or CI secret store
swiftproof review --base main --config .swiftproof.json # try it before committing
swiftproof review --base main --reviewer=false # turn it off for one run
- Only the trusted policy,
--configor the deployment environment can enable the reviewer; a pull request cannot. - Bounded, redacted source context is sent to the provider. Masking of secrets is best effort; use a local provider (for example
http://127.0.0.1:1234/v1) if source must stay local. - API keys never enter test containers.
lintnever calls a provider. - Provider failures and exhausted budgets keep the deterministic results and mark the investigation incomplete; with
--cithat requires human review.
Nothing in the reference matches this filter.