patchrun

Usage

How it works

  1. Snapshots the current repo state into a detached Git worktree.
  2. Replays any dirty changes (staged, unstaged, untracked) as a baseline commit.
  3. Runs your command inside the worktree.
  4. Stages everything the command produced and runs git diff --binary from the baseline.
  5. Lets you view, save, apply, or discard the resulting patch.
  6. Removes the worktree (unless --keep).

The baseline replay step is what makes patchrun work on a dirty tree: existing changes are subtracted out so the final patch shows only what the command did.

Patchrun is not a sandbox

The command still runs on your machine with your user permissions. It can access your network, home directory, environment variables, credentials, and files outside the repo if it wants to. patchrun only protects your Git working tree from repo-local file mutations by running inside a disposable copy and returning a patch.

Don't use patchrun for untrusted code. Use a container or VM for that.

Options

patchrun [options] -- <command> [args...]
FlagDescription
--applyApply patch to original repo after command succeeds
--apply-3wayUse git apply --3way if normal apply fails
--save <path>Save patch to path
--stdoutPrint patch to stdout
--jsonPrint machine-readable JSON result to stdout
--keepKeep the disposable worktree (prints its path)
--worktree-dir <path>Parent directory for temporary worktrees
--name <label>Human label for this run
--allow-dirtyInclude the current working tree as baseline
--fail-on-dirtyRefuse to run on a dirty working tree
--include-ignoredInclude ignored files created by command
--include <pathspec>Include only pathspec (repeatable)
--exclude <pathspec>Exclude pathspec (repeatable)
--diffShow the patch after the command
--stat / --no-statShow or hide diffstat (default: show)
--interactive / --no-interactiveForce or disable the prompt
--command-timeout <duration>Kill the command after duration (30s, 5m, 1h)
--reversePrint/save/apply the reverse of the captured patch
--checkVerify the patch applies cleanly; do not modify the working tree
--exec <cmd>Run additional command in the worktree (repeatable)
--snapshot <dir>Dump the post-run worktree (minus .git) into <dir>
--ignore-whitespacePass --ignore-whitespace to git apply
--color <mode>auto (default), always, or never
--no-sidecarSkip the .meta.json file written next to saved patches
--git-bin <path>Override the git executable
--cwd <path>Run as if invoked from <path> instead of the shell's cwd
--list-runsList kept worktrees under --worktree-dir and exit
--pruneRemove every patchrun-* directory under --worktree-dir and exit
--completion <shell>Print a bash/zsh/fish completion script and exit
--quiet / --verboseLess or more logging
--versionPrint version
-h, --helpShow help