Patchworks keeps a project connected to the template it came from. It records the exact template commit and prepares later template changes one first-parent commit at a time, without treating the project as a conventional Git fork.
Project-specific changes stay in place. Each template update becomes a normal, reviewable working-tree diff or pull request.
npm install --global patchworks
# or
bun add --global patchworksPatchworks requires Node.js 18 or newer.
To give a coding agent the official end-to-end update workflow, install the included skill with the Skills CLI:
npx skills add ludicroushq/patchworks --skill patchworks-updatepatchworks create https://github.com/example/template my-project
cd my-projectcreate makes an exact-tree root commit from the selected template branch, then
adds .patchworks.json and .github/workflows/patchworks.yaml in a second
commit. This preserves tracked files, executable modes, binary content, and
Git links while removing the template's reachable history and remote.
Patchworks will not overwrite its reserved files. It also refuses to write
through symbolic links or unsafe .github paths. The destination is prepared
in a temporary sibling directory and moved into place only after setup succeeds.
Local setup attributes both commits to the user.name and user.email active
where patchworks create was invoked. Configure both values first; Patchworks
fails instead of inventing a bot identity when either is missing. In GitHub
Actions, it uses the triggering actor and the verified
<GITHUB_ACTOR_ID>+<GITHUB_ACTOR>@users.noreply.github.com address, falling
back to the username-only noreply form only when GitHub omits the actor ID.
Use --branch <name> to follow a branch other than the template's default.
patchworks update
git status --short
git diff
git diff --cachedAn update requires a clean working tree. Patchworks fetches the configured
template branch, finds the next commit on its first-parent history, applies a
strict binary-capable patch, and advances .patchworks.json. It prepares one
commit per run. Normal file changes are unstaged so they appear in a plain
git diff.
Gitlink changes are the one staging exception: a submodule pointer has no
worktree content that can represent a new commit, so Patchworks leaves that
index entry staged. Review git diff --cached whenever an update contains a
submodule.
If Git cannot apply every hunk cleanly, Patchworks keeps the partial result for
review and writes the full patch plus per-file rejects beneath
.patchworks-rejects/<commit>/. Resolve the code, remove every reject artifact,
validate the project, and only then commit. A later run prepares the next
template commit.
For automation, --report <path> writes structured JSON. If the template's
history was rewritten but the recorded commit is still available, review the
new history and pass --rebase to explicitly apply the aggregate old-to-new
diff. Patchworks cannot reconstruct a diff after the recorded object has been
pruned and can no longer be fetched.
patchworks create installs a scheduled workflow. A minimal workflow is:
name: Patchworks
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * *"
permissions:
contents: write
pull-requests: write
concurrency:
group: patchworks-${{ github.repository }}
cancel-in-progress: false
jobs:
patchworks:
runs-on: ubuntu-latest
steps:
# Use a GitHub App token or fine-grained PAT for private cross-repository
# templates, workflow-file updates, or unattended CI on the resulting PR.
- uses: ludicroushq/patchworks@v0
with:
token: ${{ secrets.PATCHWORKS_TOKEN }}The custom token is optional. With no secret, the action falls back to
GITHUB_TOKEN. Before checkout it looks for an open patchworks/update pull
request and skips the run if one exists, so a scheduled run cannot replace
human conflict resolutions. It also refuses to reuse an update branch unless
its head exactly matches the newest merged Patchworks pull request, protecting
orphaned or human commits. Because GITHUB_TOKEN cannot read the repository's
Actions administration setting, Patchworks warns you to enable pull-request
creation instead of claiming it verified that setting. Prepared changes are
committed and opened with
peter-evans/create-pull-request.
Newly generated workflows pin the exact Patchworks action version that created
them. Upgrade that v<semver> tag deliberately (or pin a full commit SHA); it
does not follow a moving major tag. The action executes the exact patchworks
package version recorded by its own revision, not patchworks@latest. The
patchworks-package input exists for testing an exact canary package.
Four GitHub permission details matter:
- Enable Settings → Actions → General → Workflow permissions → Allow GitHub
Actions to create and approve pull requests when using
GITHUB_TOKEN. GITHUB_TOKENcannot push changes to.github/workflows. If the template may update workflow files, pass a GitHub App token or fine-grained personal access token throughwith: tokenwith Contents, Pull requests, and Workflows write access.- The same custom token needs read access to a private template in another
repository on the same GitHub host. The action safely authenticates same-host
HTTPS, SCP-style, and
ssh://git@...URLs; other hosts keep using their own ambient Git credentials. - Use a custom token as well when bot pull requests must trigger unattended CI.
Pull-request workflow runs created with
GITHUB_TOKENare approval-gated.
See the full guides at patchworks.dev.
This repository is a Bun and Turborepo monorepo:
bun install
bun run checkThe published CLI lives in packages/patchworks, the documentation site lives
in docs, and the root GitHub Action is implemented by action.yml and
action/.
MIT