# prview usage guide
This document is the user guide for `prview`.
If you want to work on the repo, see `docs/development.md`.
If you want to understand the architecture, see `docs/architecture.md`.
For the `prview.toml` and `.prview-policy.yml` configuration files, see `docs/configuration.md`.
## Installation
### From source
```bash
cd prview-rs
cargo build --release
./target/release/prview --help
```
### Globally (cargo install)
```bash
cargo install --path .
prview --help
```
Full installation details, including release binaries and checksums, are in `docs/INSTALL.md`.
## Basic usage
### Auto mode (default)
```bash
prview
```
Automatically:
- detects the profile (JS/Rust/Python/Mixed)
- uses the current branch as the target
- diffs against the repo's default base
- in standard mode, generates the full artifact pack
- runs tests and lint by default, unless you pick a lighter mode (`--quick`, `--update`, `--ai-only`) or an explicit `--skip-*`
The `prview` tool can analyze repositories that use any base branch
(`develop`, `main`, `master`, etc.); by default it resolves the first of
`develop`, `main`, `master` that exists.
### Quick mode
```bash
prview --quick
```
Skips tests, lint, and heuristics. Diffs and core artifacts only.
`prview --quick` analyzes the current local branch (`HEAD`) and compares it
against the bases resolved for the current repo. It does not pick a PR number
automatically.
To review a specific GitHub PR:
```bash
prview --pr 23 --quick
```
### Gate mode
```bash
prview gate
prview gate --strict
prview gate --json
```
`prview gate` runs the standard fast gate profile, consumes the existing
policy/merge-gate verdict, and exits with a stable automation contract. It does
not compute a second verdict path.
| `0` | `PASS`, or `CONDITIONAL` without `--strict` |
| `1` | `BLOCK` |
| `2` | `CONDITIONAL` with `--strict` |
| `3` | Gate execution failed before a trustworthy verdict was available |
`--json` makes stdout machine-readable (`schema_version: "gate-json/v1"`) with
the verdict, caveats, blocking issues, and artifact paths.
Local pre-push hook recipes and the recommended Shadow -> Warn -> Block rollout
are in [`docs/gate-playbook.md`](gate-playbook.md).
#### Gate profile and measured pre-push budget
`prview gate` applies its own deterministic pre-push profile. It runs as a
quick, quiet review and does not inherit global step opt-ins such as
`--with-tests`, `--with-lint`, `--with-security`, or `--security-full`.
Effective profile:
| Rust / Cargo | `Cargo check` runs; `Clippy`, `Rustfmt`, `Cargo test`, and `Cargo audit` stay visible as skipped checks |
| Security | Semgrep runs when the `semgrep` binary is available |
| Geiger | `Cargo geiger` is out of the gate profile |
| Tests, lint, bundle, heuristics | Disabled for the pre-push gate budget |
| JS/TS | Existing JS checks only run when repo-local `node_modules` tools exist; they are not part of the measured budget below |
Measured on 2026-07-06 with a prebuilt release binary
(`target/release/prview`); compile time is excluded.
| `prview-rs` | `feat/gate-core`, W1-B worktree dirty | 2 | 8.73s, 7.36s | 8.05s | `CONDITIONAL` / exit 0 | Semgrep 4.41s; `Cargo check` cached |
| `pensieve` | `chore/deprivatize`, clean checkout, 14 commits behind origin | 2 | 48.27s, 45.95s | 47.11s | `CONDITIONAL` / exit 0 | Semgrep 32.78s |
### GitHub Actions
This repository ships a composite Action at `action.yml` for external CI usage.
It installs `prview`, runs `prview gate --json`, and maps the step result only
from the gate exit-code contract:
| `0` | success (`PASS`, or `CONDITIONAL` without strict mode) |
| `1` | failure (`BLOCK`) |
| `2` | failure (`CONDITIONAL` with strict mode) |
| `3` | failure (gate execution error) |
Minimal blocking gate:
```yaml
permissions:
contents: read
security-events: write
jobs:
prview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: vetcoders/prview-rs@main # pin to a released tag once one ships `prview gate`
id: prview
with:
strict: "true"
version: "latest"
- uses: github/codeql-action/upload-sarif@v3
if: ${{ steps.prview.outputs['sarif-path'] != '' }}
with:
sarif_file: ${{ steps.prview.outputs['sarif-path'] }}
```
Use `strict: "false"` for advisory rollout: `CONDITIONAL` remains exit `0`,
while `BLOCK` still exits `1`. Extra CLI flags can be passed as whitespace-
separated `args`.
The Action prefers `cargo-binstall` when that binary is already available on the
runner and falls back to `cargo install prview --locked --force`. Set `version`
to a published release that contains `prview gate`, or `latest` for the newest
release. The gate command is not in the `0.5.0` crate; until a release that
includes it is published, install the action from `main`.
SARIF upload requires `permissions: security-events: write`. prview writes
`30_context/INLINE_FINDINGS.sarif` only when there are inline findings or
advisories. GitHub code scanning limits matter for large diffs: SARIF uploads
must be at most 10 MB after gzip compression, and GitHub displays at most 50
annotations per workflow step.
### Specific branch and base
```bash
prview feature/my-feature main
prview feature/x main
```
## Execution modes
| standard (default) | Full review with tests and lint enabled by default |
| `--quick` | Light pass: skip tests/lint/bundle/heuristics |
| `--deep` | All heavier checks enabled (including security and heuristics) |
| `--ci` | Like deep, tuned for automation: no colors, strict non-zero exit |
| `--update` | Incremental rerun after new commits, skipping heavy checks unless forced |
| `--ai-only` | Minimal artifact pack for AI/review flows |
## Quick cheat sheet
```bash
# 1) Fast daily check of the current branch
prview --quick
# 2) Check a specific GitHub PR
prview --pr 23 --quick
# 3) Deeper PR analysis (tests + lint + full gate)
prview --pr 23 --deep
# 4) Compact JSON for automation (stdout = JSON only)
prview --pr 23 --quick --json --quiet
# 5) Automation gate with contractual exit codes
prview gate --json
# 6) Pick up new commits without a full run
prview --update
# 7) Fast machine-readable repo state (branch, HEAD, dirty, latest run)
prview state --json --fast
```
## zsh aliases (`prv`, `prvpr`, `prvjson`)
The repo ships a ready-to-source file:
`tools/shell/prview-aliases.zsh`
To wire it up:
```bash
echo 'source $HOME/Git/prview-rs/tools/shell/prview-aliases.zsh' >> $HOME/.zshrc
source $HOME/.zshrc
```
## Flags
This is a practical shortlist of the most common flags.
The full, always-current option list is available via:
```bash
prview --help
```
### Presets
| `--quick` | Skip tests/lint/bundle/heuristics |
| `--deep` | Enable all checks (including security and heuristics) |
| `--ci` | CI mode: all checks, no colors, strict exit |
| `--ai-only` | Minimal checks, AI context pack only |
### Step control
| `--with-tests` | Force tests on when a preset disabled them; also restores tests for standard `--remote-only` |
| `--skip-tests` | Skip tests |
| `--with-lint` | Force linters on when a preset disabled them; also restores heavier Rust lint for standard `--remote-only` |
| `--skip-lint` | Skip linters |
| `--with-bundle` | Enable the bundle build |
| `--skip-bundle` | Skip the bundle build |
| `--with-security` | Raise the heavy security posture (does not add cargo-geiger or full-tree Semgrep) |
| `--skip-security` | Skip heavy security checks |
| `--security-full` | Full security tier: runs full-tree Semgrep and adds cargo-geiger's unsafe scan (slow; off even under `--deep`) |
By default, Semgrep is scoped to the change when prview can resolve a clean git
baseline: it passes Semgrep `--baseline-commit <merge-base>` so existing
findings outside the diff do not degrade the merge verdict. If the worktree is
dirty or the merge-base is unavailable, prview falls back to a full scan and the
artifact classifier still separates introduced from pre-existing findings.
Semgrep parse/scan errors remain surfaced even when no rule findings are
introduced.
### Profiles
| `--profile auto` | Auto-detect (default) |
| `--profile js` | JavaScript/TypeScript only |
| `--profile rust` | Rust only |
| `--profile python` | Python only |
| `--profile mixed` | All available |
### Special modes
| `--update` | Incremental update (skip heavy checks) |
| `-R, --remote` | Analyze a branch from origin/ |
| `--remote-only` | Resolve bases from origin/* only; a faster remote-review preset in standard mode |
| `--local-only` | Resolve bases from local refs only |
| `--policy-file <path>` | Path to `.prview-policy.yml` |
| `--policy-mode <shadow\|warn\|block>` | Override the policy mode |
| `--why-blocked` | Explain why the merge gate is blocking |
### Output
| `-q, --quiet` | Minimal output |
| `--json` | JSON output |
| `--no-color` | Disable ANSI colors |
| `--no-zip` | Skip ZIP creation |
| `--no-dashboard` | Skip HTML dashboard generation |
## Examples
### Rust project
```bash
prview --profile rust --with-tests feature/x main
```
### Python project
```bash
prview --profile python --with-tests --with-lint
```
### Mixed (Tauri app)
```bash
prview --profile mixed --deep
```
### CI pipeline
```bash
prview --ci feature/x main
```
### Incremental update
After new commits on a branch:
```bash
prview --update feature/x main
```
### JSON for scripts
```bash
prview --json --quiet feature/x main > summary.json
```
In `--json --quiet` mode, stdout contains only the compact JSON summary
(no banners or text summaries). This payload is meant for scripts and agents:
it carries the verdict, `output_dir`, a short `checks_summary`, `top_failures`,
`context_artifacts`, and paths to artifacts. Full detail stays in the run files
on disk, especially the canonical `RUN.json` and `MERGE_GATE.json` pair, plus
`PR_REVIEW.md`.
## Output
Artifacts are written to `$PRVIEW_HOME/runs/<repo>/<branch>/<run_id>/`
or, when `PRVIEW_HOME` is unset, to
`$HOME/.prview/runs/<repo>/<branch>/<run_id>/` in an ordered numbered layout.
New run ids use a timestamp plus short HEAD suffix, for example
`20260704-120500-a1b2c3d`; treat the full value as opaque.
A `latest` symlink points at the most recent run in
`$PRVIEW_HOME/runs/<repo>/<branch>/latest` or
`$HOME/.prview/runs/<repo>/<branch>/latest` when `PRVIEW_HOME` is unset.
```
$HOME/.prview/runs/my-repo/feature-x/20260225-185357/
├── 00_summary/
│ ├── RUN.json # Run metadata, execution mode, check inventory
│ ├── FAILURES_SUMMARY.md # Compact blocking failures without raw dumps
│ ├── MANIFEST.json # SHA256 hashes for generated files
│ ├── SANITY.json # Integrity validation results
│ ├── MERGE_GATE.json # Machine-readable merge decision
│ ├── pr-metadata.txt # Branch, bases, profile
│ ├── file-status.txt # A/M/D + file paths
│ └── commit-list.txt # hash date author message
├── 10_diff/
│ ├── full.patch # Full diff with diff-stat header (+N -N per file)
│ ├── per-commit-diffs/ # Individual per-commit patches
│ │ ├── 00-SUMMARY.md # Commit stats + batch mapping + thematic labels
│ │ ├── 01-abc1234-message.patch
│ │ └── ...
│ └── per-file-diffs/ # Hotspots: files with >=80 lines changed
│ ├── 00-INDEX.txt # Index with diff-stat per file
│ └── *.patch
├── 20_quality/
│ ├── *.result.json # Per-check machine-readable outputs
│ ├── *.log # Per-check raw logs
│ ├── full-checks.log # Full output from all checks
│ ├── checks-errors.log # Filtered: errors/warnings only, with +/-2 lines of context
│ ├── coverage-delta.txt # Source<->test mapping with change status
│ └── BREAKING_CHANGES.md # Removed pub symbols, changed signatures
├── 30_context/
│ ├── INLINE_FINDINGS.sarif # Optional: only when the run has findings/advisories
│ ├── changed-tests.txt # Test files changed in this PR
│ ├── cargo-tree.txt # (Rust) dependency tree for CVE/dependency paths
│ ├── tsc-trace.log # (JS) optional module-resolution diagnostics
│ ├── eslint-report.json # (JS) ESLint result
│ └── vitest-report.json # (JS) Vitest result
├── dashboard.html # Visual HTML summary
└── artifacts.zip # Everything zipped
```
### Key artifacts
#### Signal generators (20_quality/, 10_diff/)
Several generators produce high-signal artifacts — each writes a file **only when**
it has something worth showing:
| `checks-errors.log` | Errors and warnings from checks with +/-2 lines of context | When checks found errors |
| `BREAKING_CHANGES.md` | Removed `pub` symbols, changed signatures, new env requirements | When breaking changes are detected |
| `coverage-delta.txt` | Source-file-to-test mapping (multi-strategy matching) | When the diff contains source files |
| `per-file-diffs/` | Individual patches for files with `>=80` lines changed | When such hotspots exist |
When a generator produces no file, the CLI prints an `i` note explaining why.
#### How to read an artifact pack
- `00_summary/MERGE_GATE.json` is the canonical source of check statuses.
- `PR_REVIEW.md` is a concise review narrative, not a raw log dump.
- `00_summary/FAILURES_SUMMARY.md` summarizes blocking failures and advisories without copying whole JSON files.
- When `30_context/INLINE_FINDINGS.sarif` exists, it emits findings per location/advisory and is suitable for annotation integrations.
- In Rust runs, `PR_REVIEW.md` and `FAILURES_SUMMARY.md` can surface dependency paths to vulnerable crates based on `30_context/cargo-tree.txt`.
- `10_diff/per-commit-diffs/00-SUMMARY.md` carries both the batching and thematic batch labels.
- `20_quality/coverage-delta.txt` is a heuristic; for Rust it drops DELETED files in favor of disk searches for orphaned tests (raising an `ORPHANED_TEST_DETECTED` flag). Inline `#[cfg(test)]` modules are handled silently, without false alarms.
- In fast `remote-only` runs, heavier diagnostics such as `30_context/tsc-trace.log` or `30_context/tauri-info.log` may be intentionally skipped. Check `RUN.json` for `recommended`/`reason` notes on whether they are worth generating.
#### Commit batching
For large PRs, per-commit diffs are grouped automatically:
| <=10 | Individual `.patch` per commit |
| 11–50 | Batches of 5 commits in `batch-NN.patch` |
| >50 | Per-commit diffs skipped (only `full.patch`) |
#### MERGE_GATE
The policy-aware merge decision. Details: `docs/contracts/merge_gate.md`.
## Troubleshooting
### "Not inside a git repository"
Run from a directory inside a git repo.
### "Could not resolve ref: <branch>"
The named base branch does not exist. Pass an existing branch explicitly:
```bash
prview feature/x develop
# or, if the repo has no develop:
prview feature/x main
```
### TypeScript check fails
Make sure `tsconfig.json` exists and `pnpm`/`npm` are available.
### Cargo check fails
Check that `cargo` is on PATH and `Cargo.toml` is valid.