Configuration
Configure Pastoralist with package.json, rc files, or JavaScript config files
Configure Pastoralist with package.json, rc files, or JavaScript config files
CLI flags take precedence over package.json settings, which take precedence
over external config files. Security settings are deep merged across sources.
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 OSV:
{ "checkSecurity": true}.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 }; reasons, security data, patches, and keep constraints stay expanded |
depPaths | "workspace" | "workspaces" | string[] | Paths to scan for dependencies in monorepos |
overrideSource | string | JSON or YAML file containing package-manager overrides |
appendixSource | string | JSON file or .pastoralistrc receiving the appendix |
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 |
preferLatest | boolean | Prefer the latest candidate without reported vulnerabilities over the minimum patched version |
strict | boolean | Fail when a security provider cannot complete |
Enable bestCase to rank candidate version combinations under one policy.
The built-in evaluator checks advisory data for the candidate state; it does
not materialize a lockfile or resolve peer compatibility. Supply an API
bestCaseEvaluator when the project needs those checks.
{ "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.
depPaths: "workspace" reads patterns from package.json#workspaces and
pnpm-workspace.yaml. Use explicit package manifest globs for other layouts.
See Workspaces for package-manager examples.
overrideSource reads and writes overrides from a separate JSON or YAML file.
For pnpm 11+, Pastoralist resolves pnpm-workspace.yaml automatically.
appendixSource writes the appendix to a JSON config file or .pastoralistrc.
{ "pastoralist": { "overrideSource": "config/overrides.json", "appendixSource": ".pastoralistrc.json" }}Expanded appendix entries include ledger.addedDate. Security fixes can add
CVE, severity, provider, and vulnerable-range metadata to that 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 } } } }}With compactAppendix: true, routine entries can use top-level addedDate
instead of a ledger. Entries with reasons, security data, patches, or keep
constraints stay expanded.
addedDate: Date recorded when the entry was first writtenreason: 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 }}To keep an override until a date or version is reached, 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.
Use 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.
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
}{
"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
}
}
}
}{
"pastoralist": {
"overrideSource": "config/overrides.json",
"appendixSource": ".pastoralistrc.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 --checkSecurity --depPaths "packages/*/package.json"{
"checkSecurity": true,
"depPaths": ["packages/*/package.json"]
}pastoralist