Command reference

Six commands: scan, login, submit, logout, status, explain. Only login and submit ever touch the network. scan, status, and explain make zero network calls, no exceptions. Run with npx redential <command> (an alias of @redential/cli), or redential <command> after a global install.

A global --debug flag works on every command: verbose diagnostic logging to stderr (git commands, phase timings, counts), never the token or bundle content.

Usage
redential --debug scan --repo <path>
redential scan --debug --repo <path>   # either position works

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).
--detailsfalseOn a real terminal, add the COMMITS BY HOUR/WEEKDAY histogram sections to the summary. No effect with --json or piped output.
--since <spec>(full history)Limit analysis to commits at/after this date: a relative window ("2years", "18months", "30days") or an absolute date ("2024-01-01").

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

What gets printed depends on whether stdout is a real terminal and on --json:

stdout is...--jsonOutput
piped or redirectedeitherThe exact bundle JSON only, byte for byte what submit would later send. No summary.
a real terminal (TTY)noThe human-readable summary only, --details adds two extra sections. No JSON dump.
a real terminal (TTY)yesThe exact bundle JSON only, nothing else, for scripting from an interactive shell.

Run redential scan --json whenever you want the literal payload on screen, even in a terminal. On a TTY with no --json, the summary is a short, shareable overview rendered entirely from the same bundle scan already computed: structural findings first (tagged DIRECT/INFERRED, see Structural detection & explain), then everything else grouped by category, top languages and categories, ownership and signed-commit ratios, and a closing block restating what does (and never) leaves the machine:

redential scan (TTY summary)
  PRIVATE WORK, LOCALLY DERIVED
  1 year · 1,378 authored commits · 100% ownership

  CAPABILITIES DETECTED

  Payment webhook flow    30 commits   STRUCTURAL · DIRECT

  Frontend
    Next.js              139 commits
    React                113 commits
    Tailwind CSS          80 commits
    Zustand               40 commits
    +1 more

  Backend
    Express               90 commits

  Databases
    PostgreSQL            60 commits

  AI
    Anthropic API         20 commits

  TOP LANGUAGES
  .ts   ████████████████████   62%
  .tsx  ██████░░░░░░░░░░░░░░   20%
  .md   ███░░░░░░░░░░░░░░░░░    8%

  TOP CATEGORIES
  Frontend  ████████████████████   59%
  Backend   ████████░░░░░░░░░░░░   25%
  Testing   ███░░░░░░░░░░░░░░░░░   10%

  Ownership       100% of this repo's commits are yours
  Signed commits  0% of your commits are cryptographically signed
  Tip: signing future commits adds a stronger identity anchor to your attestation.

  ────────────────────────────────────────────────────────────
  Nothing left your machine. Nothing is uploaded unless you run
  `redential submit` — and only the bounded bundle: aggregates,
  salted fingerprints, and closed-vocabulary capability slugs.
  Never code, file names, commit messages, or other contributors.
  Verify: github.com/Redential/redential-cli
  ────────────────────────────────────────────────────────────

  Inspect the exact payload:  redential scan --json
  More detail (hour/weekday histograms):  redential scan --details

Capability groups are capped at 4 entries with an honest +N more, ordered by their own total commit count. Every field printed here, and every field in the raw JSON, is documented in Trust & privacy. Pipe it (redential scan | jq) and you get only the raw JSON: this summary is a terminal-only rendering of the same bundle, 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.
--label <text>(none)A private nickname for this repo, visible only to you. Required when not running in an interactive terminal.
Fully non-interactive (CI)
redential submit --repo . --author you@company.com --yes --confirm-upload --label "acme backend"
--label is mandatory on every submit. On a real terminal without it, submit prompts interactively; without a terminal (a script, CI) and no --label, submit refuses immediately, before any network call at all. See Private label for what it is and why it's required.

What happens, in order

StepBehavior
1. Build the bundleExact same code path as scan, same author selection, same authorization prompt.
2. Resolve the private label--label <text> if given, validated immediately. Required, non-interactively, before any network call: on a real terminal without it, the actual prompt fires later, inside step 3.
3. Show what gets uploadedA short summary, an identity-corroboration line (if it succeeds), a “WHAT GETS UPLOADED” consent box, THEN the interactive label prompt (only if --label wasn't given), then the exact bundle JSON and the label line, all before the upload prompt.
4. Ask to upload“Upload this bundle?”, a separate confirmation from step 1's authorization attestation.
5. 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.
6. Upload the bundlePOST to Redential with the bearer token from login. On success, only the bundle id is printed, never the full response.
7. Upload the private labelA second POST, only after step 6 succeeds. A failure here never retries and never re-uploads the bundle: it warns and submit still exits 0.

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.

status

A read-only snapshot of local CLI state: login state, config dir, and the last submission on record. Zero network, works whether or not you're logged in. No flags.

Usage
redential status
redential status (example)
redential 0.5.0
Config dir: ~/.config/redential
Site: https://www.redential.com
Logged in: yes (https://www.redential.com)
Last submission: 2026-07-14T18:02:11.000Z to https://www.redential.com
  bundle hash: 7be2f1a9c3d4…
  repo fingerprint: a3f9e21b0c88…

Reads only files this CLI itself already writes (credentials.json, last-submission.json): never the scanned repo, never a git command, never the network. It never prints access_token. The bundle hash and repo fingerprint shown are 12-character prefixes only, enough to eyeball "is this the record I think it is" without printing the full value into a terminal that might get pasted into a support thread.

explain

Local-only: explains the structural detection for one taxonomy skill slug, why it was (or wasn't) detected, and whether it's claimed. Zero network, no output written anywhere, no --json mode. See Structural detection & explain for what "structural" means.

Usage
redential explain <skill> [options]

Flags

FlagDefaultDescription
--repo <path>.Path to the git repository to inspect.
--author <email>git config user.emailAuthor email to attribute against. Repeatable. Defaults to the repo's own git config user.email.
--since <spec>(full history)Limit attribution to commits at/after this date, a relative window ("2years", "18months", "30days") or an absolute date ("2024-01-01"), same as scan --since.

Unlike scan's prompted author picker, author selection here is non-interactive on purpose: explainnever builds or sends anything, so it's meant to run unattended, by a script or a developer piping it around. The output below is illustrative, built from the CLI's real print templates with made-up file paths and line numbers, not a captured run:

redential explain payments/payment-webhook-flow (illustrative)
Skill: payments/payment-webhook-flow — Payment webhook flow
Classification: DIRECT — all three anchors sit in the same function or the same file — the strongest, most direct signal.

Anchors:
  webhook-verification:
    src/webhooks/stripe.ts:14 in handleStripeWebhook — stripe.webhooks.constructEvent (receiver resolved to import "stripe")
  db-write:
    src/webhooks/stripe.ts:22 in handleStripeWebhook — prisma .upsert(...) (receiver resolved to import "prisma")
  idempotency-guard:
    src/webhooks/stripe.ts:22 in handleStripeWebhook — upsert-shaped write is idempotent by construction (prisma .upsert(...) (receiver resolved to import "prisma"))

Connection: src/webhooks/stripe.ts (same-function — all anchors inside one function, 0 file hops)

Attribution (author: you@company.com):
  YES — your own added-lines diff touched: src/webhooks/stripe.ts

Claimed: yes

explain is still a narrow spike, not a general detector. It can currently only explain the six structural patterns the CLI ships: the Stripe, PayPal, Mercado Pago, Lemon Squeezy, and Paddle webhook flows, plus the IAP/RevenueCat purchase flow. An ordinary import-tier slug, like payments/stripe, gets a plain error naming the slugs explain can currently cover, instead. An unknown slug (not in taxonomy.json at all) is a usage error too. Both exit 1.

An AMBIGUOUSclassification (pattern present but not fully connected, or missing an anchor kind entirely) is never claimed, and never appears in a bundle: it's local, on-screen feedback only, here specifically to show you why a skill you expected to see wasn't detected. A repository with no structural finding at all for the requested skill prints a plain "not detected" message and exits 1.

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