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.
Your package manager applies overrides during installation. Pastoralist tracks them in the appendix and can change overrides when you opt into cleanup or security fixes.
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 rootOverrides 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 constraintsWith compactAppendix, routine entries can use a top-level addedDate.
Entries with reasons, security data, patches, or keep constraints stay expanded.
How 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 and Bun use overrides; Yarn uses resolutions.
pnpm uses pnpm.overrides or pnpm-workspace.yaml for pnpm 11+.
overrideSource can select a separate JSON or YAML source, and
appendixSource can select a JSON appendix target.
Pastoralist updates those project files. Reinstall dependencies to update the lockfile after changing 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"
}
}
}
}
}