pi-regraft

Vendor and update upstream code as plain files, with a dedicated Pi agent for resumable conflict resolution.

Packages

Package details

extension

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.4.0
Published
Aug 2, 2026
Downloads
551/mo · 551/wk
Author
osolmaz
License
MIT
Types
extension
Size
401.7 KB
Dependencies
3 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:

  1. the old pristine upstream tree
  2. your committed local tree
  3. 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 --ref v0.4.0 --yes

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

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 after verifying the repository handoff state.

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.

License

MIT