lpm patch / patch-commit / patch-remove
Create, apply, and remove dependency patches without a separate package fork.
lpm patch creates an editable copy of a dependency so you can fix its files without a separate fork.
lpm patch [OPTIONS] <KEY>
lpm patch-commit [OPTIONS] <STAGING_DIR>
lpm patch-remove [OPTIONS] <SELECTORS>...| Command | Purpose |
|---|---|
lpm patch | Copy the original package files to a temporary directory. |
lpm patch-commit | Create a patch file and register it in the project. |
lpm patch-remove | Remove one or more patch registrations. |
The commands use the nearest ancestor with package.json. They do not prompt for confirmation.
Quickstart
First, install the dependency with lpm install:
lpm install lodash@4.17.21
lpm patch lodashEdit the files inside the printed package_dir. Then commit the printed staging directory:
# Replace this example path with the printed staging directory.
lpm patch-commit /tmp/lpm-patch-XXXXXX
lpm installpatch-commit writes the patch and its registration. The next install applies it to node_modules before lifecycle scripts run.
Commit patches/, package.json, and lpm.lock to Git.
The lockfile records each patch's checksum. A fresh clone applies the patches from these files, including with lpm install --offline, without state from an earlier install.
Examples
# Select an exact installed version.
lpm patch lodash@4.17.21
# Select one installed version from a range.
lpm patch 'lodash@^4.0.0'
# Patch a scoped dependency.
lpm patch '@scope/package@1.2.3'
# Preview removal of two registered patches.
lpm patch-remove lodash '@scope/package@1.2.3' --dry-run
# Remove a registration and retain its patch file.
lpm patch-remove lodash --keep-file
lpm installProject configuration
patch-commit creates this entry automatically:
{
"lpm": {
"patchedDependencies": {
"lodash@4.17.21": {
"path": "patches/lodash@4.17.21.patch",
"originalIntegrity": "sha512-..."
}
}
}
}| Field | Meaning |
|---|---|
| Entry key | The package name and exact version. |
path | The patch file, relative to this package.json. |
originalIntegrity | The source integrity recorded when you created the patch. |
lpm.json has no patch configuration block.
There is no install flag to disable all patches for one run.
An install that omits a dev or optional dependency also skips its patch and retains the registration.
A later full install restores that dependency and applies its patch.
Select a package
| Selector | Behavior |
|---|---|
lodash | Select one package identity from the project lockfile. |
lodash@4.17.21 | Select an exact version. Without a matching lockfile entry, require an unambiguous cached source. |
lodash@^4.0.0 | Select one package identity that matches the range in the project lockfile. |
lodash@latest | Rejected. Patch creation does not resolve registry tags. |
Bare names and ranges require a lockfile. Multiple matching versions produce an error that lists the choices.
The same name and version from different sources can also be ambiguous. Patch registrations cannot distinguish those sources. Pin the dependency to one source before you create its patch.
Packages must already exist in the local store. Registry authentication is unnecessary for extraction, commit, and removal.
Edit and commit a patch
Extraction always starts from the original package files, including when the project already uses a patch. To replace an existing patch, include every edit that you want to retain.
The staging directory contains node_modules/<name>/ and a .lpm-patch.json file with the selected package and integrity.
Keep this file intact. Keep the staging directory at its original temporary location until commit succeeds.
Supported edits include additions, changes, and deletions of UTF-8 text files. Binary edits and symlinks are rejected. File permissions, executable-mode changes, and empty directories are not represented in the patch.
Patch filenames and file paths must pass the same checks during commit and install. Paths cannot escape the package, use internal metadata names, or contain unsupported filename characters. The patch file and each changed file have a 256 MiB limit. Prepared file contents have a combined 512 MiB limit.
patch-commit rejects an empty patch. On validation failure, it preserves the staging directory and the project files.
On success, it updates the registration and existing lockfile, then removes the staging directory.
Short, unscoped packages usually produce patches/<name>@<version>.patch.
Scoped or long names use a readable prefix and a digest. Use the reported filename instead of constructing it yourself.
A commit cannot replace an artifact that another registration still references. To keep both patches, move the existing artifact to a separate path. Then update its registration before commit.
Workspace members
From a member directory, the patch commands update that member's manifest and its records in the shared root lockfile. Run the commands from the project that owns the patch. See Workspaces.
Remove patches
lpm patch-remove lodash '@scope/package@1.2.3' --dry-run
lpm patch-remove lodash '@scope/package@1.2.3'
lpm installRemoval accepts exact keys and bare names that match one registered version. It does not accept ranges or registry tags.
By default, removal deletes an unshared patch file only inside the project's patches/ directory.
A file that another registration references stays on disk. --keep-file retains the file even after its last registration disappears.
--dry-run performs the same selection and file-safety checks without changes.
An unsafe deletion fails during the preview. Use --keep-file when you want to remove only its registration and lockfile record.
Removal does not immediately change installed package files. The next install restores the original package files.
Integrity checks
Installs check the patch file against the checksum in lpm.lock.
Each selected destination must also have the source integrity recorded in originalIntegrity.
A cached copy of the old source cannot authorize a patch for a different source.
A mismatch stops installation. The check binds the patch to the selected package bytes. It does not detect an upstream republish until an install selects those new bytes.
Patches apply after dependency resolution. A patch to package.json cannot change the resolved graph or repair a peer conflict that prevents installation.
Use Overrides or Peer dependencies for those changes.
Recovery
| Error | Action |
|---|---|
| Package is absent from the store | Run lpm install, then extract the package again. |
| Patch checksum differs | Restore the recorded artifact, or create its replacement through patch and patch-commit. |
| Source integrity differs or a hunk fails | Preserve your edits. Extract the current package and create a new patch against it. |
| Patch target is absent from the dependency graph | Remove its stale registration with patch-remove. |
| Staging metadata is missing or invalid | Extract a new staging directory, then copy your edits into its package directory. |
Patch registrations differ from lpm.lock before an offline install | Run an online install once, commit the lockfile, then retry lpm install --offline. |
JSON and automation
All three commands accept the global --json flag:
lpm patch lodash@4.17.21 --json > patch-work.json
jq -r '.package_dir, .staging_dir' patch-work.json
# After a script or editor changes the files in package_dir:
lpm patch-commit "$(jq -r '.staging_dir' patch-work.json)" --json
lpm patch-remove lodash --dry-run --jsonExtraction returns name, version, key, staging_dir, package_dir, and next_steps.
Use next_steps[].args to obtain the commit arguments without parsing a shell command.
Commit returns the artifact path, changed-file counts, original integrity, and whether it updated a lockfile.
Removal returns a removed array with each key, file-deletion result, and retention reason.
Flags
| Command | Flag | Behavior |
|---|---|---|
patch-remove | --dry-run | Check and preview removal without changes. |
patch-remove | --keep-file | Retain the patch files. |
| All three | --json | Write structured output. |
| All three | -h, --help | Show command help. |
See also
lpm install— apply registered patches.lpm sbom— include patch metadata in a software bill of materials.package.json > lpm.patchedDependencies— registration format.- Content-addressable store — original package storage.