Command reference

Four commands: scan, login, submit, logout. Only login and submit ever touch the network. scan makes zero network calls, no exceptions. Run with npx @redential/cli <command>, or redential <command> after a global install.

scan

Scans the local git history and prints the proof bundle. Nothing is uploaded.

Usage
redential scan [options]

Flags

FlagDefaultDescription
--repo <path>.Path to the git repository to scan.
--author <email>(none)Author email that is yours. Repeatable. Passing at least one enables non-interactive mode for identity selection.
--yesfalseConfirm “I am authorized to analyze this repository” non-interactively.
--jsonfalseForce JSON-only output, even on an interactive terminal (this is already the default when stdout is piped).

Interactively (a real TTY, no --author/--yes), scanasks which of the repo's author emails are yours, then asks you to confirm you're authorized to analyze the repository. Both are required before a bundle is produced. --author alone never implies authorization.

Output

Prints the full JSON bundle first, byte for byte what submit would later send. When stdout is an interactive terminal (and --jsonwasn't passed), a human-readable "wrapped" summary follows underneath it, rendered entirely from the same bundle, no new data, no network:

redential scan (excerpt)
{
  "schema_version": "1.0.0",
  "runner": "local",
  "tool_version": "0.1.0",
  "created_at": "2026-07-09T14:32:01.000Z",
  "repo": { "host_type": "github", "age_days": 742, "repo_fingerprint": "a3f9…" },
  "identity": { "author_identity_hashes": ["9c1e…"], "other_contributors_count": 3 },
  "commits": { "user_total": 1847, "first_at": "2024-06-02T09:14:00Z", "last_at": "2026-07-08T21:05:00Z", "span_days": 767, "hour_histogram": [...], "weekday_histogram": [...] },
  "signed": { "count": 831, "ratio": 0.45 },
  "languages": [ { "extension": ".ts", "share": 0.62 }, { "extension": ".sql", "share": 0.14 } ],
  "categories": [ { "name": "backend", "commit_count": 902, "churn_share": 0.51 } ],
  "detected_skills": [ { "slug": "payments/stripe", "commit_count": 12, "first_seen": "2024-09-01T10:00:00Z", "last_seen": "2025-11-20T18:30:00Z" } ],
  "ownership": { "user_commit_ratio": 0.78 },
  "integrity": { "merkle_root": "7be2…", "algorithm": "sha256" },
  "attestation": { "authorized_confirmation": true, "confirmed_at": "2026-07-09T14:32:01.000Z" }
}

  ────────────────────────────────────────────────────────────

  ╔════════════════════════════════════════════════════════════╗
  ║                 YOUR PRIVATE REPO, WRAPPED                 ║
  ╚════════════════════════════════════════════════════════════╝

  2 years, 1,847 commits

  COMMITS BY HOUR (UTC)
  0     6     12    18
  ▁····▁▁▃▅█▇▄▃▂▂▁▁▁▁▁····

  COMMITS BY WEEKDAY
  Sun  ██░░░░░░░░░░░░░░░░░░  5
  Mon  ███████████████████░  40

  TOP LANGUAGES
  .ts    ████████████████████   62%
  .sql   ████░░░░░░░░░░░░░░░░   14%

  SKILLS DETECTED
  payments/stripe     12 commits

  Ownership       78% of this repo's commits are yours
  Signed commits  45% of your commits are cryptographically signed

  Nothing left your machine. Verify: github.com/Redential/redential-cli

Every field is documented in Trust & privacy. Pipe it (redential scan | jq) and you get only the raw JSON: the wrapped summary is a terminal-only convenience, never a second source of data.

Warnings (non-blocking)

If the repo's remote looks like a known public host (github.com, gitlab.com, bitbucket.org), scanprints a warning to stderr suggesting the GitHub App instead. It never blocks or refuses to scan, because "known host" isn't the same as "publicly accessible" and scan has zero network access to tell the difference. The CLI's primary use case is a private employer repo hosted on github.com.

login

Authenticates via device flow (RFC 8628) and stores a session token locally. No flags.

Usage
redential login

Prints a verification URL and a short code, and makes a best-effort attempt to open the URL in your default browser. Auto-open is never load-bearing: on a headless box, over SSH, or if no browser is installed, it silently fails and login proceeds exactly as if auto-open didn't exist; the printed URL and code are always the fallback. Approve the code in the browser, and login polls until it receives an access token, then stores it at ~/.config/redential/credentials.json (mode 0600).

The stored session records which server issued it. If you later change REDENTIAL_SITE_URL, submit refuses and asks you to log in again rather than silently sending a token to a different host. See Troubleshooting.

submit

Scans, shows you the bundle, and uploads it after you confirm. Requires a prior redential login.

Usage
redential submit [options]

Flags

FlagDefaultDescription
--repo <path>.Path to the git repository to scan, same as scan.
--author <email>(none)Author email that is yours. Repeatable. Enables non-interactive identity selection, same as scan.
--yesfalseConfirm “I am authorized to analyze this repository” non-interactively, same meaning as scan --yes.
--confirm-uploadfalseConfirm the upload itself non-interactively. Separate from --yes on purpose: consenting to be scanned and consenting to upload are different decisions.
Fully non-interactive (CI)
redential submit --repo . --author you@company.com --yes --confirm-upload

What happens, in order

StepBehavior
1. Build the bundleExact same code path as scan, same author selection, same authorization prompt.
2. Print itByte for byte what step 4 sends, not a re-serialization, the literal printed string.
3. Ask to upload“Upload this bundle?”, a separate confirmation from step 1's authorization attestation.
4. Visibility gateAn anonymous HEAD request straight to the repo's remote URL (never to Redential's servers). A confirmed public remote (2xx/3xx) blocks the upload outright.
5. UploadPOST to Redential with the bearer token from login. On success, only the bundle id is printed, never the full response.

The visibility gate is submit-only. It's a real network check, stronger than scan's local heuristic. Anything inconclusive (private/gated, network error, timeout) doesn't block; it falls back to the same warning scan would have shown, and proceeds.

logout

Deletes the locally stored session token. No flags.

Usage
redential logout

Removes ~/.config/redential/credentials.json only. It never touches the device salt (a separate file used to make repo/author fingerprints non-reversible), which is device-local and unrelated to your session.

Exit codes

CodeMeaning
0Success.
1Any handled failure: a scan/auth/submit/network error, a denied or expired device-flow login, or EOF on an interactive prompt (see Troubleshooting).

Every command-level error is one of four typed errors (scan, auth, submit, or network), and every one of them sets a non-zero exit code rather than hanging or silently succeeding. Network-error messages are built only from the request's host and HTTP status, never from headers or body, so a failed request can never echo your bearer token or bundle content into a printed error.

Something not matching what you see locally? Open an issue.

← CLI overview