Every command is non-interactive, idempotent, has --help with examples, and supports --json. Fetching uses your own git — only requirement is that it's on your PATH.
regraft add — vendor and start trackingCopies the files in, pins the source to a commit, and hashes every file it wrote. Supports --dry-run.
# A directory from a repo regraft add owner/repo/tree/main/src/components lib/components # A single file regraft add owner/repo/blob/main/src/utils.ts # Code you copied in by hand a while ago — track it without overwriting your edits regraft add owner/repo/tree/main/src/utils lib/utils --adopt
Per file: doesn't exist → write; exists untracked with different content → skip (needs --force or --adopt); exists and identical → track silently. --force overwrites, --adopt keeps — they're mutually exclusive.
Anything your git can clone — GitHub, GitLab, self-hosted, private, even file://.
<git-url> may be https://, ssh://, file://, or scp-style (git@host:repo.git). Branch names containing / need the #<ref>:<subpath> syntax.
regraft note — record intent after customizingOne plain-English sentence: what changed and why. Snapshots current disk hashes, appends the entry, and regenerates PATCH.md.
# Default file set: every modified tracked file not already covered by a snapshot regraft note "Swapped the default tokens for our brand palette" # Scope explicitly regraft note "Removed the telemetry hooks" --files lib/components/analytics.ts
Intent integrity is enforced: regraft status classifies every locally modified file as modified+intent or modified-unrecorded (which fails the exit code). That's what keeps PATCH.md trustworthy over time.
regraft diff — see both directionsNever writes to the project. Handy right before writing a note or pulling.
# What you changed since vendoring (against the pinned baseline) regraft diff # What upstream changed since your pin — what a pull would bring in regraft diff --upstream
Exits 1 when there are differences, 0 when there are none (like git diff). Binary files are flagged and not diffed.
regraft status — anything need attention?Checks each upstream ref for new commits and classifies every tracked file.
regraft status # exits 1 if anything is stale, unrecorded, missing, or unresolved regraft status --offline # skip the upstream checks entirely (no network)
clean Matches what regraft last wrote modified+intent Locally edited, covered by an intent snapshot modified-unrecorded Locally edited without a note — fails the exit code missing Tracked file no longer on disk conflict-unresolved A previous pull left markers waiting for resolve Run it in CI to catch drift before it compounds.
regraft pull — the corePer file: no local edits → fast-forward to upstream; local edits and upstream unchanged → leave alone; both changed → three-way merge.
regraft pull # merge upstream updates regraft pull --dry-run # report the plan, write nothing regraft pull --force # take upstream wholesale for conflicting files
On conflict, diff3 markers (<<<<<<< local / ||||||| base / >>>>>>> upstream) are written in place and a reconciliation brief lands in .regraft/briefs/ with the conflicted files, the full text of every intersecting intent note, the scoped upstream commit log, and instructions for the resolving agent. Conflicted files are skipped on subsequent pulls until resolved, so markers never stack.
regraft resolve — close the loopRun after you (or your agent) fix the conflicts. Verifies no markers remain and records the outcome.
# Resolve and record the intent in one step regraft resolve --note "Re-applied our palette on the new token system" # Or resolve specific files first, note later regraft resolve lib/components/theme.ts
# Untrack a source — substring match on URL or dest; --hard also deletes the files regraft remove lib/components regraft remove owner/repo --hard # Update regraft itself (latest, or a specific tag) regraft update regraft update v0.1.0 # Tab completion echo 'eval "$(regraft completion bash)"' >> ~/.bashrc regraft completion zsh > ~/.zfunc/_regraft regraft completion fish > ~/.config/fish/completions/regraft.fish
Removed sources keep their intent entries as history, marked orphaned in PATCH.md.
regraft.json Single source of truth: upstream URL, pinned SHA, per-file hashes, and intent entries. Validated with zod on read.
PATCH.md Generated, human- and agent-readable view of every note. Regenerated from the manifest.
.regraft/ Git clone cache and reconciliation briefs. regraft writes .regraft/.gitignore containing * so you never have to think about it.
0 Clean / success / already done 1 Drift, stale, conflict, or error — status: anything stale/unrecorded/missing/unresolved; pull: any conflict or warning; resolve: markers remain or resolution intent missing; add: any file skipped; diff: any difference found
Every command except update accepts --json and prints exactly one JSON object to stdout, with stable shapes agents can pattern-match on.