Architecture
How Pastoralist reads overrides, writes the appendix, tracks patches, and handles cleanup
How Pastoralist reads overrides, writes the appendix, tracks patches, and handles cleanup
Pastoralist reads the root package.json, maps each override or resolution into
a pastoralist.appendix entry, and records when the entry was created in its
ledger. Patches created by tools such as patch-package are detected and
tracked on the same entry.
If an override or resolution is no longer needed, Pastoralist marks the appendix
entry as unused and prints a cleanup notice. The override and its appendix entry
are removed only when you run with --remove-unused. Patch files are reported
as potentially unused; Pastoralist does not delete patch files for you.
You manage the override or resolution field; Pastoralist manages the appendix.
In workspace/monorepo setups, Pastoralist:
package.json or project manifest filepastoralist.appendix, with a
ledger entry recording when each override was addeddepPaths or workspaces are configuredpackage.json, usually the rootStandard single-package project with overrides:
Complex workspace setup with shared overrides:
Overrides replace a package version in your dependency tree with the version you choose. This is npm's way to handle dependency conflicts:
{ "overrides": { "foo": "1.0.0", "bar": { "baz": "1.0.0" } }}Resolutions serve the same purpose for Yarn users:
{ "resolutions": { "foo": "1.0.0", "**/bar/baz": "1.0.0" }}Patches are local changes to node_modules packages, usually created with
tools such as patch-package. Pastoralist detects and tracks these patches.
The Pastoralist object in package.json records what the tool manages:
{ "overrides": { "minimist": "1.2.8" }, "pastoralist": { "appendix": { "[email protected]": { "dependents": { "my-app": "minimist@^1.2.6", "mkdirp": "minimist@^1.2.5" }, "ledger": { "addedDate": "2026-05-30T00:00:00.000Z", "reason": "Pin minimist while upstream packages adopt the patched version.", "source": "manual" } } } }}[email protected]addedDate, optional reason and source, security metadata (securityProvider,
cves, cveDetails, severity, vulnerableRange, patchedVersion), and
optional keep constraintsHow nested overrides work for transitive dependencies:
Pastoralist uses sync file I/O intentionally. As a CLI tool, predictable execution and simple debugging outweigh async benefits.
Two caches avoid redundant work: jsonCache (parsed package.json files) and dependencyTreeCache (npm ls output). Caches persist across update() calls - pass clearCache: true to reset.
npm registry requests are limited to 5 concurrent to avoid rate limits during security scans.
How package managers resolve dependencies with overrides:
{
"overrides": {
"foo": "1.0.0",
"bar": {
"baz": "1.0.0"
}
}
}{
"resolutions": {
"foo": "1.0.0",
"**/bar/baz": "1.0.0"
}
}{
"overrides": {
"minimist": "1.2.8"
},
"pastoralist": {
"appendix": {
"[email protected]": {
"dependents": {
"my-app": "minimist@^1.2.6",
"mkdirp": "minimist@^1.2.5"
},
"ledger": {
"addedDate": "2026-05-30T00:00:00.000Z",
"reason": "Pin minimist while upstream packages adopt the patched version.",
"source": "manual"
}
}
}
}
}