pi-regraft
Vendor and update upstream code as plain files, with a dedicated Pi agent for resumable conflict resolution.
Package details
Install pi-regraft from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-regraft- Package
pi-regraft- Version
0.6.0- Published
- Aug 25, 2026
- Downloads
- 1,827/mo · 248/wk
- Author
- osolmaz
- License
- MIT
- Types
- extension
- Size
- 551.9 KB
- Dependencies
- 4 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./src/extension.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-regraft
pi-regraft is a Pi extension for vendoring code from Git repositories. It lets
you change the copied code in place and pull later upstream changes without
losing your work.
The vendored code stays in your repository as ordinary files. Regraft stores pristine upstream copies in normal commits on your branch and uses them as three-way merge bases during updates. It fetches only the new upstream commit.
The package also includes Regrafter, a dedicated Pi agent for resolving update conflicts, running checks, and pausing when an update needs a product decision.
Install
Install from npm:
pi install npm:pi-regraft
You can also run the GitHub version without installing it:
pi -e git:github.com/osolmaz/pi-regraft
First graft
Run Pi at the root of the repository that will receive the files. Add an upstream repository, tracked ref, optional subdirectory, and destination:
/regraft add https://github.com/example/tool.git@main#extensions/foo vendor/foo
The npm package also installs a regraft executable for scripts and coding
agents:
regraft add https://github.com/example/tool.git@main#extensions/foo vendor/foo
The destination must be empty. Regraft copies the selected upstream tree into
vendor/foo and writes regraft.json before creating a commit named
chore(regraft): import upstream base.
Edit the copied files after that commit and commit your changes normally. If a local change has a reason that may matter during conflict resolution, record it in the manifest:
/regraft note foo "log every failed request"
Commit the updated manifest before pulling from upstream.
Updates
Check whether any tracked ref has advanced:
/regraft status
Update one graft by name:
/regraft update foo
Regraft reads the old pristine tree from your branch and fetches the new upstream commit before merging these trees:
- the old pristine upstream tree
- your committed local tree
- the new upstream tree
It commits the new pristine tree before restoring the merged local version in your worktree. If you made no local changes, the worktree stays clean. If local changes remain, run your project checks and commit the restored local version.
Text conflicts use normal Git conflict markers. Pi receives the affected file
paths and the notes from regraft.json, so the agent can help resolve them.
Regraft also preserves executable bits, symlinks, binary files, and
file-versus-directory changes.
Commands
/regraft add <url>[@ref][#subdir] [dest] copy and commit an upstream tree
/regraft update <name> pull upstream and restore local edits
/regraft status show local bases and upstream status
/regraft note <name> <text> record why a local edit exists
The executable provides the same operations without the leading slash. Add
--json to receive one versioned JSON result on stdout. Expected merge
conflicts return a successful needs_resolution result so an agent can inspect
and resolve them before running project checks.
Regrafter
Regrafter keeps one Pi session and one repository lease for each update run. It can pause for several decisions and resume without losing the conversation or the exact repository state.
Install the commands and pi-factory, then install the app bundle:
npm install -g pi-regraft @osolmaz/pi-factory
pi-factory install osolmaz/pi-regraft --yes
Point Regrafter at a model from your Pi profile — the same providers, models,
and credentials as your regular pi, read in place and never copied:
regrafter config set model <provider/model>
The config lives at $XDG_CONFIG_HOME/regrafter/config.json (default
~/.config/regrafter/config.json). regrafter config show prints the current
selection, regrafter config set thinking <level> adjusts the thinking level,
and regrafter config reset clears the config. When a model is configured,
runs launch Pi with the ambient profile: the host agent dir provides auth.json
and the model catalog, sessions stay in Regrafter's own state directory, and
host extensions, skills, prompt templates, and themes are disabled for the run.
When the configured provider is huggingface, the bundled
pi-huggingface-oauth extension is loaded so Hugging Face OAuth keeps working.
regrafter attach uses the same selection.
Work with Regrafter directly in a repository:
pi-factory run regrafter --cwd /path/to/repository
A main agent or script can drive the same app through bounded controller commands:
regrafter start --repo /path/to/repository --request-file task.md --json
regrafter send <run-id> --decision <decision-id> --message-file answer.md --json
regrafter inspect <run-id> --json
regrafter list --repo /path/to/repository --json
regrafter attach <run-id>
regrafter abort <run-id> --json
regrafter handoff prepare <run-id> --json
regrafter handoff accept <run-id> --evidence <sha256> --actor <id> --reason-file <path> --json
The baseline command grants no authority to create overlay commits, push, or
open pull requests. Grant only the actions the run needs with
--allow commits,push,pull-requests. A later send may add authority, but it
cannot remove authority already granted.
Regrafter never drops a lease because it is old and never silently chooses
between competing local and upstream behavior. abort does not reset files; it
releases the lease only when the repository still matches the last verified run
state.
Use handoff prepare after the repository was reconciled outside Regrafter. It
returns a digest bound to the run, lease, branch, HEAD, index, dirty paths, and
changed file contents. Review that evidence before using handoff accept with
an actor label and a reason file. Acceptance records the reviewed state before
it releases the lease. It transfers responsibility for that state and does not
validate, commit, reset, or endorse the repository work. A pending accepted
handoff can be retried safely after an interrupted lease release.
Local model server
Without a config file, the bundled app defaults to an OpenAI-compatible model
named regrafter at http://127.0.0.1:1234/v1. It does not install or start a
model server. Edit the installed pi-factory.toml when the endpoint or model
differs.
Repository requirements
add and update require an attached Git branch, a clean worktree and index,
and a configured Git author. Git credentials must come from a credential helper
or SSH key. Regraft rejects credentials embedded in source URLs.
An update also refuses to run when ignored, uncommitted files exist inside the graft. Move or remove those files first so they cannot be erased by the update.
Keep every chore(regraft): import upstream base commit in branch history.
Rebasing those commits is safe. Squashing or dropping them removes the merge
bases and blocks future updates.
Regraft fails when a required local base is missing. It never recovers the old base by fetching the previously pinned commit from upstream.
The full commit model and merge rules are in the design document.