Configuration
Configure Pastoralist with package.json, rc files, or JavaScript config files
Configure Pastoralist with package.json, rc files, or JavaScript config files
For most projects, start small: enable workspace scanning only if you have workspaces, and enable security checks only where you want advisory data.
Pastoralist searches for configuration files in this order (first found wins):
.pastoralistrc (JSON format).pastoralistrc.jsonpastoralist.jsonpastoralist.config.cjspastoralist.config.jspastoralist.config.mjsAll external config files use the same top-level Pastoralist settings. Choose the filename by format and convention:
.pastoralistrc: extensionless rc file parsed as JSON.pastoralistrc.json: explicit JSON rc file, and the JSON option created by
pastoralist initpastoralist.json: visible non-dotfile JSON configpastoralist.config.cjs: CommonJS module with module.exportspastoralist.config.js: JavaScript config. CommonJS exports are accepted;
otherwise it is imported as a modulepastoralist.config.mjs: ESM module with export defaultUse pastoralist.json, not .pastoralist.json.
Enable security checks with defaults:
{ "checkSecurity": true, "depPaths": "workspace", "security": { "provider": "osv" }}.pastoralistrc.json{ "checkSecurity": true, "depPaths": "workspace", "security": { "provider": "osv", "severityThreshold": "medium" }}pastoralist.config.jsmodule.exports = { depPaths: ["packages/*/package.json", "apps/*/package.json"], checkSecurity: true, security: { provider: "osv", severityThreshold: "high", excludePackages: ["@types/*"], },};pastoralist.config.mjsexport default { checkSecurity: true, depPaths: "workspace", security: { provider: "osv", severityThreshold: "critical", },};When both external config files and package.json configuration exist,
Pastoralist merges them and lets package.json take precedence:
package.json overrides top-level fieldssecurity) are deep merged.pastoralistrc.json:
{ "checkSecurity": true, "depPaths": "workspace", "security": { "provider": "osv", "severityThreshold": "medium" }}package.json:
{ "pastoralist": { "security": { "severityThreshold": "high" } }}Effective configuration:
{ "checkSecurity": true, "depPaths": "workspace", "security": { "provider": "osv", "severityThreshold": "high" }}| Option | Type | Description |
|---|---|---|
checkSecurity | boolean | Enable security vulnerability scanning |
compactAppendix | boolean | Collapse routine appendix entries to { addedDate }; entries with security info, patches, or active keep constraints stay expanded |
depPaths | "workspace" | "workspaces" | string[] | Paths to scan for dependencies in monorepos |
appendix | object | Auto-generated dependency tracking (managed by Pastoralist) |
overridePaths | object | Manual override tracking for specific paths |
resolutionPaths | object | Manual resolution tracking for specific paths |
bestCase | object | Opt-in dependency-portfolio optimization policy |
security | object | Security scanning configuration |
The security object supports the following options:
| Option | Type | Description |
|---|---|---|
enabled | boolean | Enable/disable security checks |
provider | "osv" | "github" | "snyk" | "npm" | "socket" | "spektion" | array | Security provider or providers to use |
autoFix | boolean | Automatically apply security fixes |
interactive | boolean | Use interactive mode for security fixes |
securityProviderToken | string | API token for providers that require authentication. Prefer provider environment variables; use this only for controlled config that will not be committed. |
severityThreshold | "low" | "medium" | "high" | "critical" | Minimum severity level to report |
excludePackages | string[] | Packages to exclude from security checks |
hasWorkspaceSecurityChecks | boolean | Include workspace packages in security scans |
strict | boolean | Fail when a security provider cannot complete |
Enable bestCase when package fixes must be chosen as one portfolio instead
of independently. Pastoralist evaluates complete version combinations so a fix
for one package cannot hide a vulnerability introduced elsewhere.
{ "pastoralist": { "checkSecurity": true, "bestCase": { "enabled": true, "userOwnedOverrides": ["alpha"], "riskAggregation": "both", "objectives": [ "known-exploited", "critical", "high", "expected-exploitation", "package-exposures", "compatibility", "change-count", "oldness" ], "search": { "mode": "auto", "exactStateLimit": 256, "beamWidth": 16, "maxEvaluations": 1000 } } }}| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable portfolio selection during security checks |
userOwnedOverrides | string[] | [] | Hard-constrain listed packages to their active override version |
riskAggregation | "unique-cves" | "package-exposures" | "both" | "both" | Choose how vulnerability risk is counted |
objectives | BestCaseObjective[] | See above | Set the lexicographic ranking order |
search.mode | "auto" | "exact" | "beam" | "auto" | Select exhaustive or deterministic bounded search |
search.exactStateLimit | positive integer | 256 | Limit exact search to this many states in auto mode |
search.beamWidth | positive integer | 16 | Retain this many states at each step during beam search |
search.maxEvaluations | positive integer | 1000 | Stop after this many complete-state evaluations |
Objectives are compared in array order; Pastoralist does not combine them
into a weighted sum. Supported objectives are known-exploited, critical,
high, medium, low, expected-exploitation, package-exposures,
compatibility, change-count, and oldness.
An exact search reports provenOptimal: true only when it evaluates every
state. Beam search and capped exact search report provenOptimal: false.
You can configure Pastoralist directly in your package.json:
{ "name": "my-project", "version": "1.0.0", "pastoralist": { "checkSecurity": true, "depPaths": "workspace", "security": { "provider": "osv", "severityThreshold": "medium", "excludePackages": ["@types/*"] } }}For monorepos, use depPaths to specify which package.json files to scan:
The simplest approach for monorepos with a workspaces field:
{ "workspaces": ["packages/*", "apps/*"], "pastoralist": { "depPaths": "workspace" }}This scans all workspace packages defined in your workspaces field.
"workspaces" is accepted as an alias.
For more control, specify custom glob patterns:
{ "pastoralist": { "depPaths": ["packages/*/package.json", "apps/*/package.json"] }}Every appendix entry gets a ledger with at least addedDate. When a security
provider detects a fix, Pastoralist adds CVE, severity, provider, and
vulnerable-range metadata to the same ledger:
{ "pastoralist": { "appendix": { "[email protected]": { "dependents": { "my-app": "lodash@^4.17.0" }, "ledger": { "addedDate": "2026-05-30T00:00:00.000Z", "reason": "Security vulnerability CVE-2021-23337", "source": "security", "securityChecked": true, "securityCheckDate": "2026-05-30T00:00:00.000Z", "securityCheckResult": "clean", "securityProvider": "osv", "cves": ["CVE-2021-23337"], "cveDetails": [ { "cve": "CVE-2021-23337", "severity": "high", "patchedVersion": "4.17.21" } ], "severity": "high", "vulnerableRange": "<4.17.21", "patchedVersion": "4.17.21", "keep": true } } } }}addedDate: ISO timestamp recorded when the entry was first written. Always presentreason: Why the override was needed. Accepts a non-empty string, a ProjectReason, or a BestCaseReasonsource: How the entry was created — "manual" or "security"securityChecked: Whether a security check was performedsecurityCheckDate: When the last security check occurredsecurityCheckResult: Result of the last check — "clean", "error", or "skipped"securityProvider: Which provider detected the vulnerabilitycves: All CVE identifiers related to this vulnerabilitycveDetails: Per-CVE objects with cve, severity, and patchedVersionseverity: Highest severity across all CVEs (low, medium, high, critical)vulnerableRange: Semver range that is affectedpatchedVersion: Version that resolves the vulnerabilitykeep: Prevent --remove-unused from removing this entry. Set to true or a KeepConstraint objectUse a project reason for an engineer-selected pin or patch:
{ "reason": { "type": "project", "summary": "Keep the patched fork until upstream publishes a release.", "pin": "2.4.1", "patch": "patches/example+2.4.1.patch", "constraints": ["Requires the current plugin API"], "references": ["https://example.com/upstream/issue/123"] }}summary is required. pin, patch, constraints, and references are
optional and descriptive; package-manager overrides and appendix patch paths
remain authoritative.
Best-case selection writes a reason tied to the complete portfolio decision:
{ "reason": { "type": "best-case", "summary": "Selected as part of the lowest-risk dependency portfolio", "decisionId": "best-case-4b825dc642cb", "policyHash": "d14a028c2a3a2bc9", "search": { "evaluatedStates": 64, "provenOptimal": true }, "impact": { "fixedVulnerabilities": 3, "introducedVulnerabilities": 0, "remainingVulnerabilities": 1 } }, "cves": ["CVE-2026-1234"]}The reason belongs to one dependency item. Dependencies selected by the same
portfolio share a decisionId. CVEs remain in the sibling cves field.
keepTo pin an override so --remove-unused never removes it, set keep: true on the ledger:
{ "ledger": { "addedDate": "2026-05-30T00:00:00.000Z", "keep": true }}For time-bounded or version-bounded keeps, use a KeepConstraint object:
{ "ledger": { "addedDate": "2026-05-30T00:00:00.000Z", "keep": { "reason": "Waiting for upstream patch", "until": "2027-06-01", "untilVersion": "4.18.0" } }}KeepConstraint fields:
reason (required): Why this override is being keptuntil: ISO date after which the keep is considered expireduntilVersion: Semver. The keep expires once the root dependency meets or exceeds this versionreviewBy: Freeform field for tracking who should review the decisionThis shows which packages were overridden for security reasons and when they were last checked.
depPaths: "workspace" for most monorepos--checkSecurityUse pastoralist.config.cjs for CommonJS or pastoralist.config.mjs for ESM:
export default { checkSecurity: true, depPaths: "workspace", security: { provider: "osv", severityThreshold: "high", },};TypeScript config files are not loaded directly. Use JSON, CJS, JS, or MJS config files.
You can use JavaScript config files to provide environment-specific settings:
// pastoralist.config.jsconst isDev = process.env.NODE_ENV === "development";const isCI = process.env.CI === "true"; module.exports = { checkSecurity: !isDev, // Only check in production/CI depPaths: "workspace", security: { provider: "osv", severityThreshold: isCI ? "high" : "medium", autoFix: isCI && !isDev, },};If you're currently using CLI flags, you can migrate to config files:
pastoralist --checkSecurity --depPaths "packages/*/package.json"{ "checkSecurity": true, "depPaths": ["packages/*/package.json"]}pastoralistCLI flags still work and will override config file settings.
{
"checkSecurity": true,
"depPaths": "workspace",
"security": {
"provider": "osv"
}
}{
"checkSecurity": true,
"depPaths": "workspace",
"security": {
"provider": "osv",
"severityThreshold": "medium"
}
}module.exports = {
depPaths: ["packages/*/package.json", "apps/*/package.json"],
checkSecurity: true,
security: {
provider: "osv",
severityThreshold: "high",
excludePackages: ["@types/*"],
},
};export default {
checkSecurity: true,
depPaths: "workspace",
security: {
provider: "osv",
severityThreshold: "critical",
},
};{
"checkSecurity": true,
"depPaths": "workspace",
"security": {
"provider": "osv",
"severityThreshold": "medium"
}
}{
"pastoralist": {
"security": {
"severityThreshold": "high"
}
}
}{
"checkSecurity": true,
"depPaths": "workspace",
"security": {
"provider": "osv",
"severityThreshold": "high"
}
}{
"pastoralist": {
"checkSecurity": true,
"bestCase": {
"enabled": true,
"userOwnedOverrides": ["alpha"],
"riskAggregation": "both",
"objectives": [
"known-exploited",
"critical",
"high",
"expected-exploitation",
"package-exposures",
"compatibility",
"change-count",
"oldness"
],
"search": {
"mode": "auto",
"exactStateLimit": 256,
"beamWidth": 16,
"maxEvaluations": 1000
}
}
}
}{
"name": "my-project",
"version": "1.0.0",
"pastoralist": {
"checkSecurity": true,
"depPaths": "workspace",
"security": {
"provider": "osv",
"severityThreshold": "medium",
"excludePackages": ["@types/*"]
}
}
}{
"workspaces": ["packages/*", "apps/*"],
"pastoralist": {
"depPaths": "workspace"
}
}{
"pastoralist": {
"depPaths": ["packages/*/package.json", "apps/*/package.json"]
}
}{
"pastoralist": {
"appendix": {
"[email protected]": {
"dependents": {
"my-app": "lodash@^4.17.0"
},
"ledger": {
"addedDate": "2026-05-30T00:00:00.000Z",
"reason": "Security vulnerability CVE-2021-23337",
"source": "security",
"securityChecked": true,
"securityCheckDate": "2026-05-30T00:00:00.000Z",
"securityCheckResult": "clean",
"securityProvider": "osv",
"cves": ["CVE-2021-23337"],
"cveDetails": [
{
"cve": "CVE-2021-23337",
"severity": "high",
"patchedVersion": "4.17.21"
}
],
"severity": "high",
"vulnerableRange": "<4.17.21",
"patchedVersion": "4.17.21",
"keep": true
}
}
}
}
}{
"reason": {
"type": "project",
"summary": "Keep the patched fork until upstream publishes a release.",
"pin": "2.4.1",
"patch": "patches/example+2.4.1.patch",
"constraints": ["Requires the current plugin API"],
"references": ["https://example.com/upstream/issue/123"]
}
}{
"reason": {
"type": "best-case",
"summary": "Selected as part of the lowest-risk dependency portfolio",
"decisionId": "best-case-4b825dc642cb",
"policyHash": "d14a028c2a3a2bc9",
"search": {
"evaluatedStates": 64,
"provenOptimal": true
},
"impact": {
"fixedVulnerabilities": 3,
"introducedVulnerabilities": 0,
"remainingVulnerabilities": 1
}
},
"cves": ["CVE-2026-1234"]
}{
"ledger": {
"addedDate": "2026-05-30T00:00:00.000Z",
"keep": true
}
}{
"ledger": {
"addedDate": "2026-05-30T00:00:00.000Z",
"keep": {
"reason": "Waiting for upstream patch",
"until": "2027-06-01",
"untilVersion": "4.18.0"
}
}
}export default {
checkSecurity: true,
depPaths: "workspace",
security: {
provider: "osv",
severityThreshold: "high",
},
};// pastoralist.config.js
const isDev = process.env.NODE_ENV === "development";
const isCI = process.env.CI === "true";
module.exports = {
checkSecurity: !isDev, // Only check in production/CI
depPaths: "workspace",
security: {
provider: "osv",
severityThreshold: isCI ? "high" : "medium",
autoFix: isCI && !isDev,
},
};pastoralist --checkSecurity --depPaths "packages/*/package.json"{
"checkSecurity": true,
"depPaths": ["packages/*/package.json"]
}pastoralist