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 (-ci or --ci). Booleans are set with --ci or --ci=true and cleared with --checks=false. A value is given as --base main or --base=main.
  • Run swiftproof <command> --help for 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.

FormCompares
--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 --exactFrom the tip of main directly to --head.
BASE..HEADThe two exact commits, for example HEAD~1..HEAD to review the last commit. Overrides --base, --head and --exact.
BASE...HEADFrom 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.

FlagDefaultDescription
--base REVmainBase branch or revision. The comparison starts at its merge base with --head; its tip supplies the trusted policy.
--head REVHEADCandidate revision under review.
--exactfalseCompare 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 PATHpolicy of the baseUse this local policy file instead of .swiftproof.json from the base branch. Only pass a file you trust.
--out DIR.swiftproofReport directory, relative to the repository root. The path may not contain symbolic links.
--format LISTmarkdown,jsonComma-separated report formats to write: markdown, json.
--cifalseExit 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, --reviewerfalseMust 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.

FlagDefaultDescription
--base REVmainBase branch or revision. The comparison starts at its merge base with --head; its tip supplies the trusted policy.
--head REVHEADCandidate revision under review.
--exactfalseCompare the base revision itself instead of the merge base.
BASE..HEAD—Positional range; see Choosing revisions.
--repo PATH.Repository directory.
--config PATHpolicy of the baseUse 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.swiftproofReport directory, relative to the repository root. Artifacts go to DIR/artifacts/.
--format LISTmarkdown,jsonComma-separated report formats to write: markdown, json.
--cifalseExit with code 2 when human review is required, including high-risk signals, unverified areas or incomplete checks.
--checkstrueRun the configured checks in the sandbox. --checks=false skips them; a configured reviewer may still run sandbox experiments.
--reviewerautoAI 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 Npolicy (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-networkfalseGive sandbox containers network access. Takes effect only if the trusted policy also sets sandbox.network: true.
--no-networkfalseForce 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.

FlagDefaultDescription
--repo PATH.Directory in which to create .swiftproof.json.
--language NAMEdetectedgo, 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.

FlagDefaultDescription
--input PATH.swiftproof/confidence-report.jsonSaved JSON report (version 1, at most 64 MiB).
--out DIR.swiftproofOutput directory, relative to the current directory.
--format LISTmarkdown,jsonComma-separated formats to write: markdown, json.

swiftproof version and help

CommandPrints
swiftproof version, --versionThe version, for example swiftproof v0.3.0, and the license notice.
swiftproof help, -h, --helpThe synopsis. With no argument, SwiftProof prints the same text.
swiftproof <command> --helpThe flags of a command, with their defaults.

Exit codes

CodeMeaning
0Report completed without a reproduced high or critical issue. Without --ci, unresolved areas do not change this code.
1A high or critical hypothesis is supported by a differential failure: a generated test passed on the base and failed on the candidate.
2With --ci only: human review required, including high-risk signals, unverified areas or incomplete checks.
3Invalid arguments, Git comparison, or trusted configuration (including an unknown policy key or command name).
4Operational 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.

VariableEffect
SWIFTPROOF_REVIEWER_ENDPOINTOverrides reviewer.endpoint. Same URL rules as the policy.
SWIFTPROOF_REVIEWER_MODELOverrides reviewer.model, and on its own enables the reviewer during review.
SWIFTPROOF_API_KEYAPI key. The name is set by reviewer.api_key_env; this is the default.
SWIFTPROOF_API_KEY_FILEPath 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_KEYDocker 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

PathContents
.swiftproof/CONFIDENCE_REPORT.mdThe 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.jsonThe 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.

KindSeverityRaised when
sensitive_pathhighA changed path matches a sensitive_paths glob.
auth_changehighA 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_changehighA Go function whose name suggests payments (payment, refund, charge, capture, withdraw, deposit, balance…) has its body changed.
validation_removedhighA removed line called a validation, assertion or sanitizing function, or raised a validation error.
public_api_changehigh mediumGo: an exported declaration was removed or changed (high) or added (medium). Other languages: a line looks like a public declaration (medium).
database_writehighA changed line looks like a database mutation or transaction (INSERT, UPDATE … SET, .Exec(, .Commit(…).
dynamic_executionhigheval, process execution, subprocess, child_process, innerHTML and similar.
type_suppressionhighType or lint suppression such as @ts-ignore, as any, unsafe, nolint, eslint-disable.
migration_changehighA path containing migration or ending in .sql changed.
infrastructure_changehighA GitHub workflow, Dockerfile or Terraform file changed.
file_type_changehighGit reports a type change, for example a file becoming a symbolic link.
network_changemediumA changed line makes HTTP, gRPC or socket calls, or contains a URL.
error_handling_changemediumError checks, wrapping, panic/recover, catch or except changed.
dependency_changemediumA dependency manifest or lockfile changed (go.mod, package.json, Cargo.lock, pyproject.toml…).
uncovered_changemedium lowAdded Go lines were not executed by the recorded coverage run. Low when the coverage run itself failed.
branch_growthmediumAt least five more lines with branch constructs were added than removed in a file. Not a complexity metric.
large_changemediumMore than 400 lines changed in one file.
file_deletedmediumA tracked file was removed.
binary_changemediumA binary file changed and cannot be analyzed as text.
analysis_limitedmediumGo declaration analysis could not complete for a file, for example because it does not parse.
no_test_changelowA source file changed and no test file in the same directory or with the same name stem changed. Existing coverage is not measured.
todo_addedlowA 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.

KeyTypeDefaultDescription
versioninteger1Policy format version. Must be 1.
languagestringdetectedLanguage 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.

KeyPlaceholdersDescription
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

KeyDefaultAllowedDescription
sandbox.imagegolang:1.26-bookwormimage namePreloaded image with the toolchain and dependencies. Never pulled by SwiftProof; pin it by digest if you can.
sandbox.networkfalsebooleanAllow container networking. Also requires --allow-network on the command line.
sandbox.timeout_seconds1201–3600Time limit of each command.
sandbox.max_runtime_seconds6001–7200Total sandbox time for the run, shared by checks and experiments.
sandbox.max_output_bytes655361024–4194304Captured output kept per command.
sandbox.memory_mb1024128–32768Memory limit of each container, in MiB.
sandbox.cpus21–32CPU limit of each container.

reviewer

KeyDefaultAllowedDescription
reviewer.model""model IDTool-capable model. Empty disables the reviewer. Overridden by SWIFTPROOF_REVIEWER_MODEL.
reviewer.endpointhttps://api.openai.com/v1/chat/completionsURLChat 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_envSWIFTPROOF_API_KEYvariable nameEnvironment variable holding the key; <NAME>_FILE and /run/secrets/<NAME> follow it. Empty for a provider that needs no key.
reviewer.max_iterations201–100Model turns per investigation. --max-iterations overrides it.
reviewer.max_generated_tests100–100Temporary tests the reviewer may create.
reviewer.timeout_seconds6001–1800Total time for the investigation.
reviewer.max_input_bytes1310724096–2097152Bound 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 globCovers
**/auth/**Any auth directory.
**/payment*/**payment, payments and similar directories.
**/migrations/**Database migrations.
.github/workflows/**CI workflows.
.swiftproof.jsonThe 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.

LanguageImageCommands
gogolang:1.26-bookwormtest go test ./... · typecheck go vet ./... · build go build ./... · generated_test go test {package} · coverage go test -covermode=count -coverprofile={coverage_out} ./...
typescript, javascriptnode:22-bookwormtest npm test · build npm run build
pythonpython:3.13-bookwormtest python -m unittest discover · generated_test python -m unittest {file}
unknowngolang:1.26-bookwormNo 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, --config or 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. lint never calls a provider.
  • Provider failures and exhausted budgets keep the deterministic results and mark the investigation incomplete; with --ci that requires human review.