Trust & privacy
The bundle is the only thing that ever leaves your machine, and every value in it is either an aggregate, a salted hash, or a member of a closed public vocabulary. Nothing free-form derived from your code can appear in the output, not because of a policy statement, but because the CLI is structurally incapable of it. Every claim on this page is backed by an executable test, not just prose.
What leaves your machine, and what doesn't
| Never leaves your machine | Only travels after redential submit, and only this |
|---|---|
| Source code, diffs, snippets | The bundle printed by scan, byte for byte |
| File and directory names | An extension (.ts) and an inferred category (backend) |
| Commit messages | Aggregate cadence: hour/weekday histograms |
| Other contributors' names or emails | An aggregate count of other contributors |
| The remote URL | Only the host kind (github, gitlab, etc.), never the URL |
| Secrets of any kind | Nothing. A secret-scan runs over the bundle and blocks output on any match |
scan makes zero network calls, no exceptions, not even a version check. login and submit are the only two commands that touch the network at all, and submit uploads nothing without your explicit confirmation. There is no daemon, no watch mode, no background process, no telemetry.
"The CLI reads your code": bounded output, explained precisely
This is the principle most often misread, so it's worth being exact. The CLI DOES read the content of diffs, locally, via git show/git diff, because that's how skills are detected. The guarantee is not "the CLI never looks at code"; it's that what leaves the machine is bounded: reading is local and unbounded, output is public and enumerable.
Concretely, for skills: the only content-derived values in the bundle are skill slugs, and a slug is valid only if it appears in a public, versioned taxonomy shipped in the CLI repo. A slug outside that list invalidates the whole bundle. The vocabulary is the ceiling of what detection can ever say about your code, both when the bundle is built and when it's later rendered on your profile.
The bundle, field by field
Schema: schema/bundle.v1.json, JSON Schema with additionalProperties: false everywhere. An unlisted field makes the bundle invalid by design, not just by convention.
Top level
| Field | What |
|---|---|
| schema_version | "1.0.0" through "1.4.0". The schema is the trust contract, the version pins it. |
| runner | "local" or "ci". Local scans are user-controlled (weakest tier). |
| tool_version | CLI version, for reproducibility of the analysis. |
| created_at | Scan timestamp. |
Every version from 1.1.0 onward is purely additive over the previous one: 1.1.0 adds integrity.date_forensics, 1.2.0 adds two optional fields to detected_skills[] entries (evidence, confidence, see detected_skills below), and 1.4.0 adds the optional repo.shallow field (see repo, identitybelow). A bundle that omits an optional field is fully valid, and a consumer that only understands an earlier shape doesn't break on its absence.
repo, identity
| Field | What |
|---|---|
| repo.host_type | Only the KIND of host ("github"). Never the URL, org, or repo name. |
| repo.age_days | First commit to now. |
| repo.repo_fingerprint | Salted hash of the root commit sha, lets the server detect a repo being re-submitted without ever knowing which repo it is. |
| repo.shallow | Optional boolean, schema 1.4.0+. Present and true only when the scanned clone is shallow (git clone --depth N, or a CI checkout that truncates history by default): history before the boundary isn't available locally, so age_days/commits.span_days can be a lower bound versus the real repo. Never sent as an explicit false, and never penalized. |
| identity.author_identity_hashes | Only salted hashes of the emails you selected as yours. |
| identity.other_contributors_count | An aggregate count, nothing else. |
commits, signed
| Field | What |
|---|---|
| commits | Volume (user_total), span (first_at/last_at/span_days), and cadence (24-bucket hour histogram UTC, 7-bucket weekday histogram). Doubles as a behavioral fingerprint. |
| signed | Count and ratio of cryptographically signed commits (GPG/SSH/x509). A commit only counts as signed when git reports a verified good signature (status G), never an untrusted, unchecked, bad, expired, or revoked one. |
languages, categories
Share of churn by file extension (.ts, .py) and by technical category (auth, payments, infra, frontend, backend, data, testing, ai-workflow, docs, other), never file names. Lockfiles, minified JS, build-output directories, and one-off generated-file dumps are excluded from both the numerator and denominator of every share, so a single npm install can't dwarf months of hand-authored work.
detected_skills
{ "slug": "payments/stripe", "commit_count": 12,
"first_seen": "2024-03-01T10:00:00Z", "last_seen": "2025-11-20T18:30:00Z" }Detected locally by matching your commits' added diff lines against deterministic, versioned signatures: imports, config files, per-library API-call shapes. Zero network, no LLMs. Per skill, only commit_count, first_seen and last_seen, never the matched lines, file names, or any excerpt. May be an empty array; the field is always present.
Since schema 1.2.0, an entry can also carry two optional, closed-enum fields: evidence ("import" or "structural") and confidence ("direct" or "inferred", only present alongside evidence: "structural"). A "structural" entry means the slug was verified by following connected relations in the code, such as a payment webhook's signature verification wired to a database write and guarded by an idempotency check, not a single matched import line, still computed entirely locally with zero network calls.
{ "slug": "payments/payment-webhook-flow", "commit_count": 4,
"first_seen": "2025-01-10T09:00:00Z", "last_seen": "2025-06-02T14:20:00Z",
"evidence": "structural", "confidence": "direct" }An unattributed or ambiguous structural finding is never emitted, under any field: only a claim backed by a connected shape found in commits that are yours ever reaches the bundle. No paths, function names, or node/edge counts of the underlying code graph are ever exposed either; evidence and confidence are the entire surface. See Structural detection & explain for how it works and redential explain for inspecting it locally.
ownership, integrity, attestation
| Field | What |
|---|---|
| ownership.user_commit_ratio | Your share of total commits. Aggregate only. |
| integrity.merkle_root | sha256 Merkle root over your commit shas, enables future re-verification without revealing a single sha. |
| integrity.date_forensics | Four aggregates only, never a per-commit value: author_span_days, committer_span_days, mismatch_ratio, committer_burst_ratio. |
| attestation | Records that you confirmed "I am authorized to analyze this repository", and when. Part of the payload, not just a UI gate. |
date_forensics (added in schema 1.1.0) compares each commit's author date (when the change was written) against its committer date (when the commit object was last written): a replayed history can forge author dates freely, but a naive replay still leaves large author_span_days alongside a near-zero committer_span_days and both ratios near 1.0. This is a heuristic signal for server-side scoring only: scan/submit never fail, warn, or block on these values themselves, they just compute and report them, exactly like every other field on this page.
Attested vs. Proven / Verified
Everything local is falsifiable, git dates can be forged. The resulting tier is therefore the weakestone on Redential: "Attested" (metadata only), never called Proven or Verified, and never visually mixed with them. Attested has partial anchors: signed commits (can't be forged retroactively without the key), a behavioral fingerprint (your hour/weekday cadence compared against your own verified public activity), and a Merkle root for future re-verification, but no independent verification of the underlying code.
Proven and Verified require either connecting a readable repository (the GitHub App reads the actual code) or defending the claim live: a short recorded session where you answer questions generated from your own bundle, in real time. Faking a git history is cheap; defending fabricated experience under questioning is not. That gap, not the detection heuristics, is the actual security boundary.
Don't take this on faith. Read the source or run test/privacy/ yourself.
← CLI overview