Skip to content

API reference

The typed core, straight from the source.

Models

Result models. Every core function returns these, never formatted strings.

Formatting is a separate layer (formatters/); the CLI and TUI only present.

RepoRef dataclass

Where the data came from: a local path or a remote clone.

Provenance dataclass

Stamp carried by every combined or packed artifact.

FileEntry dataclass

One file the reaper looked at. Paths are POSIX-style and relative.

HarvestResult dataclass

The flagship: gathered files ready to be concatenated.

TreeNode dataclass

One node in a hierarchical listing.

TreeResult dataclass

A hierarchical file listing. Works on any folder, git or not.

PackedFile dataclass

One file inlined into a conjured bundle.

PackResult dataclass

A repo conjured into an LLM-ingestible bundle.

ReanimatedFile dataclass

One file reconstructed from a conjured bundle.

ReanimateResult dataclass

The inverse of conjure: what rose from the artifact.

ExtensionStat dataclass

Census row: one file extension.

CensusResult dataclass

File-type census: what is buried here, and how much of it.

Marker dataclass

One TODO/FIXME/HACK/XXX haunting the codebase.

UnfinishedResult dataclass

Every unfinished thing the scan turned up.

ConfigValue dataclass

One effective grimoire setting and where it came from.

Recipe dataclass

A named bundle of flags stored in the grimoire.

RiteStep dataclass

One step of a rite: a command and its CLI argument tokens.

The literal token {source} anywhere in args is replaced with the source currently being processed; a step without it ignores the rite's source loop and runs identically for every source.

Rite dataclass

A named, ordered sequence of steps stored in the grimoire.

StepOutcome dataclass

One step's result against one source.

RiteResult dataclass

A rite's combined outcome across every step and source.

combined()

Nest outcomes as {source: {step: output}} for export/display.

GrimoireResult dataclass

Effective configuration: values, origins, and stored recipes and rites.

PulseCheck dataclass

One signs-of-life check.

PulseResult dataclass

Doctor report: is this corpse fit for necromancy?

CommitEntry dataclass

One commit in the chronicle.

ChangelogSection dataclass

Commits gathered under one tag (or the unreleased head).

ChronicleResult dataclass

Commit history, newest first, optionally grouped into a changelog.

Soul dataclass

One contributor's ledger.

SoulsResult dataclass

Contributor stats, a bus-factor estimate, and an optional heatmap.

Hotspot dataclass

One file ranked by how often it changes and how much.

HauntResult dataclass

Code churn and hotspots: the classic bug-risk proxy.

AuthorShare dataclass

One author's slice of a single file's history.

AutopsyResult dataclass

Deep single-file examination.

DeadFile dataclass

A file that lived and died: path, fatal commit, and its author.

GraveyardResult dataclass

Every file that ever lived and died in the repo.

ResurrectResult dataclass

A dead file brought back from the graveyard.

Branch dataclass

One branch's hygiene report.

GhostsResult dataclass

Branch hygiene: activity, merged-but-undeleted, gone remotes.

StaleFile dataclass

One file ranked by how long it has gone untouched.

RotResult dataclass

Staleness report: files untouched the longest.

TombstoneResult dataclass

A stats card for demos and READMEs.

SecretFinding dataclass

One secret the exhumation turned up. Never carries the full secret.

ExhumeResult dataclass

Secrets dug out of the full history.

VeilCount dataclass

How many times one rule fired during a veiling.

VeilResult dataclass

A redaction pass: what was hidden, never what it was.

Omen dataclass

One file's risk prophecy. Scores are 0..1; omens are hints, not fate.

OmensResult dataclass

Composite per-file risk, ranked most-cursed first.

CloneCluster dataclass

Files that are byte-for-byte the same soul in different bodies.

DoppelgangersResult dataclass

Duplicate files by content hash.

BloatEntry dataclass

One heavy body: a working-tree file or a blob still in the walls.

BloatResult dataclass

The largest files, and the blobs deleted from the tree but not the past.

SkeletonEntry dataclass

One structural bone: an import, class, function, or method.

SkeletonFile dataclass

One file stripped to its structure.

BonesResult dataclass

Implementation stripped, structure kept: the compact code map.

ScryDelta dataclass

One file's churn between the two refs.

ScryResult dataclass

What changed between two refs: churn, files, and contributors.

Dependency dataclass

One dependency read from a manifest.

Affliction dataclass

One known vulnerability afflicting a pinned dependency.

PlagueResult dataclass

Dependency manifests checked against the OSV database (opt-in network).

CommandHint dataclass

One real command lifted from the repo's own tooling files, not guessed.

Gotcha dataclass

One file that keeps breaking: churn plus bug-fix density.

DistillResult dataclass

A repo distilled into the facts an Agent Skill bundle is built from.

ScavengedSkill dataclass

One skill folder lifted whole from the source.

ScavengeResult dataclass

Existing Agent Skill folders scavenged into a library directory.

GraveOutcome dataclass

One repo's fate in a necropolis fan-out.

NecropolisResult dataclass

A command fanned across every grave in the manifest.

WardCheck dataclass

One ward in the composite CI gate: a ritual run against its threshold.

WardResult dataclass

The composite gate: every configured ward, and whether any broke.

LeechBlock dataclass

One fenced code block pulled out of a markdown document.

LeechResult dataclass

Fenced code blocks drained from a document back into files.

EmbalmResult dataclass

A repo state preserved in a provenance-stamped tarball.

WakeSection dataclass

One Keep-a-Changelog category in the drafted section.

WakeResult dataclass

A changelog section drafted from the commits since the last tag.

LineageResult dataclass

Every commit that added or removed a needle, back to its first summoning.

FileOwnership dataclass

One file's dominant author and how tightly they hold it.

DirOwnership dataclass

One top-level directory's dominant author.

PossessionResult dataclass

The knowledge map: who holds each file, and where one soul holds all.

Revenant dataclass

A file that died and rose again (at least once).

RepeatOffender dataclass

A file that keeps getting 'fixed'.

RevenantResult dataclass

What will not stay buried: resurrections and repeat offenders.

Prophecy dataclass

One file's forecast. Like omens: a hint, never fate.

ProphecyResult dataclass

Omens extended across time: which files will demand attention next.

ExorciseTarget dataclass

One thing the purge plan would expel from history.

ExorciseResult dataclass

A safe purge plan: it plans and prints, it never rewrites history.

EffigySlice dataclass

One top-level directory's share of the effigy treemap.

EffigyResult dataclass

The portrait of the dead: everything the SVG poster is drawn from.

CacheEntry dataclass

One interred repo in the catacombs.

BanishResult dataclass

What the exorcism removed.

Core

Resolve a source argument: local path, or remote URL via the catacombs.

resolve_source(source, ref=None, depth=1, backend=None)

Turn a path or URL into a readable local directory.

Local paths are used in place. Remote URLs are cloned (shallow by default) into the catacombs and reused on repeat visits.

The flagship: gather files matching patterns and prepare them for concatenation. Returns a HarvestResult; rendering lives in formatters/.

CapExceeded

Bases: RuntimeError

The total size cap was hit. The message says exactly where.

harvest(repo, patterns=DEFAULT_PATTERNS, excludes=None, max_file_size=None, max_total_size=None, include_binary=False, invoked='reaper harvest', generated=None)

Gather every matching file under the resolved source.

Skips are never silent: each skipped file is recorded with its reason so the report can show exactly what was left in the ground.

Hierarchical file listing. Works on any folder, git or not.

tree(repo, max_depth=None, dirs_only=False, with_sizes=False, with_lines=False, excludes=None, invoked='reaper limbs', generated=None)

Build the hierarchy, honoring ignore rules and the depth limit.

The shared secret/PII rules engine behind exhume and veil.

One engine, two rituals: exhume detects (full history, masked previews), veil redacts (any artifact, [VEILED:rule-name]). Neither ever writes a full secret to any output, log, or error message - a found secret appears only as AKIA...9X2Q (masked).

Built-in signatures cover the common key formats plus a Shannon-entropy sweep for the ones that have no format. The grimoire extends the set:

[rules.internal-hostname]
pattern = "[a-z0-9-]+\.corp\.example\.com"
severity = "medium"
veil_only = true   # redacted by veil, never reported by exhume

Rule dataclass

One signature: a name, a compiled pattern, and how loudly to scream.

RuleMatch dataclass

One raw hit inside a text: which rule, where, and the matched span.

RuleError

Bases: ValueError

A custom rule is miswritten. Message names the rule and the sin.

VeiledText dataclass

A redacted text and the tally of what was hidden.

load_rules(custom=None)

The built-ins plus grimoire extensions (see config.custom_rules).

shannon_entropy(text)

Bits per character; random base64 sits near 6, English near 4.

mask(secret)

First/last 4 chars only, per the contract: never the full secret.

fingerprint(rule, secret)

Stable id for a finding that does not store the secret itself.

scan_text(text, rules=None, with_entropy=True)

Every rule hit in a text, ordered by position. Overlaps: first rule wins.

load_baseline(path)

Fingerprints to suppress: a JSON list of strings, or a previous exhume --format json report (fingerprints are pulled from findings).

exhume(repo, rules=None, with_entropy=True, baseline=None, since_ref=None, invoked='reaper exhume', generated=None, backend=None)

Scan every reachable blob in history for secrets.

Each unique blob is read once; findings are attributed to the oldest commit that introduced the blob at its recorded path. since_ref bounds the walk to blobs reachable in since_ref..HEAD -- new blobs only -- instead of the full object graph; a blob already scanned in a prior run (anything reachable from since_ref) is never read again.

cursed(result, fail_on)

CI gate: does this report warrant exit 3?

veil_text(text, rules=None, with_entropy=True)

Replace every rule hit with [VEILED:rule-name].

veil(text, source, repo, rules=None, with_entropy=True, invoked='reaper veil', generated=None)

Veil an artifact's text; returns (result, redacted text).

scrub(message, rules=None)

Veil a log/debug line. --shriek output goes through this.

Omens: a composite risk prophecy per file.

The score blends four classic proxies - churn, bug-fix density, recency, and size - each normalized to 0..1, weighted by the grimoire's [omens] table. Lenses isolate one component (--lens churn) or blend them all.

Honest framing, per the plan: omens are hints, not fate. A high score says "look here first", never "this file is broken".

omens(repo, lens='all', weights=None, limit=None, backend=None, invoked='reaper omens', generated=None, now=None)

Score every surviving file and rank the cursed ones first.

doomed(result, fail_over)

The omens at or above the CI threshold (exit 3 when non-empty).

Doppelgangers and bloat: the same bytes twice, and the heavy bytes.

doppelgangers finds working-tree files that are byte-for-byte identical (content sha256), reporting clusters and the space a cleanup would reclaim.

bloat ranks the largest working-tree files and, in a repo, the blobs that were deleted from the tree but still weigh down .git - the body is still in the walls.

doppelgangers(repo, excludes=None, min_size=1, invoked='reaper doppelgangers', generated=None)

Cluster identical files by content hash.

Size is compared first so only same-sized files get hashed; empty files are ignored by default (min_size=1) because a thousand empty init.py are convention, not waste.

bloat(repo, limit=DEFAULT_LIMIT, excludes=None, invoked='reaper bloat', generated=None, backend=None)

The largest files in the tree, and dead blobs still haunting .git.

Works on plain folders too - the walls section is simply empty when there is no history to hide bodies in.

Bones: strip implementation, keep structure.

Emits every file's imports, class/function signatures, and docstring first lines - a compact code map that fits huge repos into small contexts.

Python parses with the stdlib ast (zero deps, exact). Other languages go through tree-sitter when the git-reaper[bones] extra is installed; without it they are reported as skipped, never silently dropped.

bones(repo, excludes=None, invoked='reaper bones', generated=None)

Walk the tree and reduce every recognized source file to its bones.

Scry: gaze between two refs and read what changed.

Graduated from the back of the crypt once omens stabilized. The vision covers the commits reachable from B but not A (git's A..B range): total churn, the most-changed files, who did the changing, and which souls appeared for the first time inside the range.

scry(repo, ref_a, ref_b, limit=None, backend=None, invoked='reaper scry', generated=None)

Compare two refs: churn, files, and contributors in A..B.

Plague: check dependency manifests against the OSV database.

Manifest parsing is pure and offline. The network hop is injectable (and lives in net/osv.py), so --offline degrades gracefully to manifest parsing and tests never touch the wire.

Only exactly-pinned dependencies are queried - a range like >=2.0 has no single version to ask about - and every skip is counted, never silent.

plague(repo, offline=False, query_batch=None, vuln_summary=None, invoked='reaper plague', generated=None)

Read every manifest under the root; consult the oracle unless offline.

The necropolis: fan one reaper command across every grave in a manifest.

Graves come from a necropolis.toml manifest or, with --org, from the gh CLI. Each grave gets its own artifact in the out dir; a combined INDEX.md records every outcome, including the failures - a fan-out that hides a failed grave is worse than none.

The runner is injectable: the CLI passes a closure that re-invokes the Typer app (the same trick cast uses), and tests pass a fake.

FleetError

Bases: ValueError

The manifest is miswritten or the org lookup failed.

Grave dataclass

One repo in the necropolis.

load_manifest(path)

Parse necropolis.toml: [[grave]] tables with source, name?, tags?.

derive_name(source)

A grave's name from its source: last path segment, .git shroud removed.

org_graves(org, limit=200)

Every repo in a GitHub org, via the gh CLI (which owns the auth).

artifact_extension(args)

Match the per-grave artifact suffix to any --format in the args.

necropolis(command, args, graves, out_dir, runner, tag=None, archive=None)

Run reaper <command> <grave> <args> --out <dir>/<name>.<ext> per grave.

archive, one of fsutil.ARCHIVE_FORMATS, packages the whole out_dir (every grave's artifact plus INDEX.md/SKILL.md) into a single file afterward; this is separate from any --format a fanned-out sub-command carries in args, which only affects that sub-command's own per-grave artifact.

render_index(result)

The combined index: one row per grave, failures included.

render_index_skill(result, out_dir)

The routing skill at the library's root: one row per harvested skill.

An agent loads this first and follows the row to the right repo's skill; each row's description is read back from the skill it routes to.

fleet_exit_code(result)

1 if any grave failed outright, else 3 if any is cursed, else 0.

Signs-of-life check: the first thing to run when a ritual misbehaves.

Cache

The catacombs: the clone cache.

Remote clones land in a content-addressed cache under ~/.cache/git-reaper/catacombs/<host>/<owner>/<repo>, shallow by default, reused across runs, and cleared by banish. Local file:// sources are buried flat as localhost/<name>-<digest> to stay inside Windows path limits.

catacombs_root()

Cache root, overridable via GIT_REAPER_CACHE for tests and CI.

grave_path(url)

Map a remote URL to its plot in the catacombs.

list_graves()

Every interred repo, oldest first.

mark_grave(repo_path, url)

Record the source URL and refresh the last-used stamp.

banish(older_than_seconds=None)

Clear the catacombs. With older_than, a partial exorcism.

parse_age(text)

Parse '7d', '12h', '90m' into seconds. Raises ValueError.

Schemas

JSON schema export for every result model.

Every JSON-emitting command publishes its schema (--schema) so notebooks and models can consume reaper output without guessing. Schemas are derived from the dataclasses in models.py; keeping them mechanical keeps them honest.

schema_for(cls)

Build a JSON schema for a result model dataclass.

artifact_schema(command)

The provenance schema string for a command's artifacts, e.g. 'harvest/v1'.