Pastoralist
A CLI for automatically shepherding package.json overrides 👩🏽🌾
Install / Use
/learn @yowainwright/PastoralistREADME
Pastoralist
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=6f41d7dd-fce9-49ea-ae43-040a51f458bd" />
Pastoralist helps you maintain node module overrides and address security issues in dependencies.
- Pastoralist tracks, secures, and cleans up your
overrides,resolutions, andpatches. - Pastoralist can help resolve dependency security alerts by creating overrides for vulnerable packages.
TL;DR
One command. Three features.
npm i pastoralist -D && pastoralist --init
- Tracks why each override exists
- Scans for security vulnerabilities
- Removes unused overrides
Table of Contents
- What are overrides and resolutions?
- The Problem
- The Solution
- What Pastoralist Automates
- How Pastoralist Works
- Configuration
- Setup
- Thanks
What are overrides and resolutions?
Package manager overrides and resolutions let you control exact dependency versions in your node_modules.
Package managers (npm, yarn, pnpm, bun) use these overrides to fix:
- Security vulnerabilities in nested dependencies
- Bugs in transitive dependencies
- Version conflicts
Read more: npm overrides, yarn resolutions, pnpm overrides, bun overrides
The Problem
You add overrides to fix a security alert or broken dependency:
"overrides": {
"lodash": "4.17.21" // Why? What for? No idea anymore.
}
Six months later, you have no clue:
flowchart LR
You[You] --> Question1{Why is this here?}
Question1 --> Question2{What uses it?}
Question2 --> Question3{Still needed?}
Question3 --> Stuck[🤷 Just leave it...]
style You fill:#e3f2fd
style Stuck fill:#ffebee
You end up with ghost overrides haunting your package.json forever.
The Solution
Pastoralist automatically documents every override:
"overrides": {
"trim": "^0.0.3"
},
"pastoralist": {
"appendix": {
"trim@^0.0.3": {
"dependents": {
"remark-parse": "4.0.0" // ← Ah! remark-parse needs this
}
}
}
}
No more mysteries. Every override is tracked.
flowchart LR
Install[npm install] --> Auto[Pastoralist runs]
Auto --> Track[Tracks deps]
Auto --> Scan[Scans security]
Auto --> Clean[Cleans unused]
Track --> Done[✓ Done]
Scan --> Done
Clean --> Done
style Install fill:#e3f2fd
style Auto fill:#f3e5f5
style Done fill:#e8f5e9
Automatic cleanup:
When trim is no longer needed, Pastoralist removes it automatically:
"overrides": {}, // ← Cleaned up automatically
"pastoralist": {
"appendix": {} // ← Cleaned up automatically
}
Automatic security checks:
Run once with --checkSecurity enabled:
"pastoralist": {
"security": {
"enabled": true,
"provider": "osv"
}
}
Pastoralist tracks the fix:
"overrides": {
"lodash": "4.17.21" // ← Auto-fixed CVE-2021-23337
},
"pastoralist": {
"appendix": {
"lodash@4.17.21": {
"dependents": {"my-app": "lodash@^4.17.0"},
"ledger": {
"reason": "Security vulnerability CVE-2021-23337",
"securityProvider": "osv"
}
}
}
}
Security fixes are tracked with full context.
What Pastoralist Automates
1. Override Tracking
Pastoralist documents every override, including nested dependencies.
"overrides": {
"pg": {
"pg-types": "^4.0.1" // Nested override
}
}
flowchart TD
Start([Nested override detected]) --> Parse[Parse parent dependency]
Parse --> Track[Track in appendix]
Track --> End([Full dependency chain visible])
style Start fill:#e3f2fd
style End fill:#e8f5e9
style Parse fill:#f3e5f5
Result:
"pastoralist": {
"appendix": {
"pg-types@^4.0.1": {
"dependents": {
"my-app": "pg@^8.13.1 (nested override)"
}
}
}
}
2. Security Checks
Enable security scanning with your preferred provider.
"pastoralist": {
"security": {
"enabled": true,
"provider": "osv",
"severityThreshold": "medium"
}
}
flowchart TD
Start([npm install]) --> Scan[Request vulnerability reports]
Scan --> Detect{Vulnerabilities found?}
Detect -->|Yes| Fix[Auto-generate override]
Detect -->|No| Done[✓ Done]
Fix --> Done
style Start fill:#e3f2fd
style Fix fill:#fff3cd
style Done fill:#e8f5e9
Supported providers:
- OSV (default) - No auth required
- GitHub - Requires token and permissions (see below)
- Snyk [EXPERIMENTAL] - Requires CLI and token
- Socket [EXPERIMENTAL] - Requires CLI and token
GitHub Provider Setup
When using the GitHub provider in CI workflows, add the vulnerability-alerts: read permission:
permissions:
contents: write
vulnerability-alerts: read
You must also enable Dependabot alerts in your repository: Settings > Code security and analysis > Dependabot alerts.
If permissions are insufficient, Pastoralist will warn and continue (your workflow won't fail).
3. Cleanup
When dependencies are removed, Pastoralist removes their overrides.
flowchart TD
Start([Dependency removed or updated]) --> Check[Check if override still needed]
Check --> Remove[Auto-remove from overrides & appendix]
Remove --> Done[✓ Cleaned up]
style Start fill:#e3f2fd
style Remove fill:#f3e5f5
style Done fill:#e8f5e9
Pastoralist also detects overrides that no package depends on and labels them as (unused override). To remove them:
pastoralist --remove-unused
4. Patch Tracking
Works with patch-package. Links patches to overrides and warns about unused patches.
"pastoralist": {
"appendix": {
"lodash@4.17.21": {
"dependents": {"my-app": "lodash@^4.17.0"},
"patches": ["patches/lodash+4.17.21.patch"] // ← Auto-tracked
}
}
}
How Pastoralist Works
You: Add an override when needed.
Pastoralist: Tracks, scans, and cleans up.
flowchart LR
You[You add override] --> Install[npm install]
Install --> Pastor[Pastoralist runs]
Pastor --> Track[Tracks it]
Pastor --> Scan[Scans it]
Pastor --> Clean[Cleans if unused]
Track --> Chill[Back to coding]
Scan --> Chill
Clean --> Chill
style You fill:#e3f2fd
style Pastor fill:#f3e5f5
style Chill fill:#e8f5e9
Add it to your postinstall script and forget about it:
"scripts": {
"postinstall": "pastoralist"
}
For detailed architecture, code flows, and user journeys, see Architecture and User Journeys
Key Notes
- You control what goes into overrides/resolutions
- Pastoralist handles tracking, security, and cleanup
- Runs on every install via postinstall hook
Using Pastoralist with Workspaces and Monorepos
Pastoralist provides enhanced support for monorepo scenarios where overrides are defined at the root but dependencies exist in workspace packages.
Auto-Detection
If your package.json has a workspaces field, Pastoralist automatically scans workspace packages:
{
"workspaces": ["packages/*", "apps/*"],
"overrides": {
"lodash": "4.17.21"
}
}
Run pastoralist and it automatically scans all workspace packages. No configuration needed.
Manual Configuration
For explicit control, configure workspace scanning:
{
"pastoralist": {
"depPaths": "workspace"
}
}
Or specify custom paths:
{
"pastoralist": {
"depPaths": ["packages/*/package.json", "apps/*/package.json"]
}
}
Monorepo Override Tracking
When you have overrides at the root for packages only installed in workspace packages, Pastoralist tracks them properly:
// Root package.json with overrides for workspace packages
{
"overrides": {
"lodash": "4.17.21" // Used by workspace packages, not root
},
"pastoralist": {
"overridePaths": {
"packages/app-a/package.json": {
"lodash@4.17.21": {
"dependents": {
"app-a": "lodash@^4.17.0"
}
}
}
}
}
}
Configuration Options
- Interactive Configuration - Let Pastoralist guide you through setup
