API Reference
Complete reference for pastoralist CLI and Node.js API
Complete reference for pastoralist CLI and Node.js API
Pastoralist provides both a CLI interface and a Node.js API for programmatic usage.
:::tip[Configuration Files]
Most CLI options can be configured using config files. See the Configuration documentation for details on using .pastoralistrc, pastoralist.config.js, or package.json for persistent settings.
:::
pastoralistRun pastoralist on the current directory's package.json.
npx pastoralist
pastoralist doctorRun a read-only setup and override health check. This command enables dry-run
summary mode and does not modify package.json.
npx pastoralist doctor
pastoralist onboardPrint a first-run onboarding checklist with initial local usage, agent setup, and GitHub Action setup.
npx pastoralist onboard
pastoralist --path <path>Run pastoralist on a specific package.json file.
params:
<path>: path to a package.json file# Run on a specific package
npx pastoralist --path packages/app/package.json
# Run on a nested project
npx pastoralist --path ./nested/project/package.json
pastoralist --depPaths [paths...]Run pastoralist on multiple package.json files using glob patterns.
params:
[paths...]: array of glob patterns# Run on all packages in monorepo
npx pastoralist --depPaths "packages/*/package.json"
# Run on multiple directories
npx pastoralist --depPaths "packages/*/package.json" "apps/*/package.json"
pastoralist --ignore [patterns...]Exclude files matching glob patterns.
params:
[patterns...]: array of glob patterns to ignore# Ignore test directories
npx pastoralist --ignore "**/test/**" "**/dist/**"
# Ignore specific packages
npx pastoralist --depPaths "**/*package.json" --ignore "**/node_modules/**" "**/legacy/**"
pastoralist --root <root>Set the root directory for all operations.
params:
<root>: root directory path# Run from different directory
npx pastoralist --root /path/to/project
# Combine with other options
npx pastoralist --root ../my-project --path package.json
pastoralist initInitialize configuration with the guided setup. The wizard can configure workspace paths, security scanning, and where the configuration should be saved.
# Start interactive setup
npx pastoralist init
When run, this will:
workspaces entries from package.jsondepPaths: "workspace" or custom package globspackage.json or a supported config filepastoralist --init agent-skillInstall the bundled Pastoralist agent skill into .agents/skills/pastoralist.
npx pastoralist --init agent-skill
pastoralist init agent-skill is also supported.
pastoralist --interactiveReview security fixes interactively. Use this with --checkSecurity when you
want to approve fixes instead of applying everything with --forceSecurityRefactor.
# Review security fixes before applying them
npx pastoralist --checkSecurity --interactive
pastoralist --debugEnable detailed debug output.
npx pastoralist --debug
pastoralist --dry-runPreview changes without modifying package.json.
npx pastoralist --dry-run
pastoralist --outputFormat jsonReturn machine-readable output for CI or custom tooling.
npx pastoralist --summary --outputFormat json
pastoralist --quietQuiet mode for CI pipelines. Outputs minimal text and uses exit codes.
npx pastoralist --quiet --checkSecurity
pastoralist --summaryDisplay metrics table after run.
npx pastoralist --summary
pastoralist --setup-hookAdd pastoralist to your postinstall script automatically.
npx pastoralist --setup-hook
pastoralist-setup-local-devSet up local agent config, selected skills, and selected local hooks.
npx -p pastoralist pastoralist-setup-local-dev --dry-run
npx -p pastoralist pastoralist-setup-local-dev --skills all --hooks git,postinstall
pastoralist --remove-unusedRemove overrides that no package in your project depends on. When Pastoralist detects unused overrides during a run, it displays a notice suggesting this flag.
npx pastoralist --remove-unused
pastoralist --checkSecurityEnable security vulnerability scanning.
npx pastoralist --checkSecurity
pastoralist --securityProvider <provider...>Choose one or more security providers. Supported values are osv, github,
npm, snyk, socket, and spektion.
npx pastoralist --checkSecurity --securityProvider osv npm
pastoralist --forceSecurityRefactorApply security override fixes without prompting.
npx pastoralist --checkSecurity --forceSecurityRefactor
pastoralist --strictFail when a security provider, network request, or API call cannot complete.
npx pastoralist --checkSecurity --strict
Control provider cache behavior for security checks.
npx pastoralist --checkSecurity --cache-dir .cache/pastoralist
npx pastoralist --checkSecurity --cache-ttl 3600
npx pastoralist --checkSecurity --no-cache
npx pastoralist --checkSecurity --refresh-cache
npm install pastoralist
update(options)Update package.json overrides and the appendix. Each appendix entry includes a
ledger with at least addedDate; security metadata is added when security
checks run. This is a low-level API: pass the parsed package.json as config.
The CLI handles config loading for normal command-line use. update() is
synchronous and returns an UpdateContext, so the examples below intentionally
do not use await.
params:
options: configuration object
path: path to package.json (default: './package.json')config: parsed package.json contentdepPaths: array of glob patterns for multiple filesignore: array of glob patterns to ignoreroot: root directory pathdebug: enable debug loggingdryRun: preview changes without writing package.jsonsummary: include summary metricsremoveUnused: remove overrides with no active dependentscheckSecurity: enable security checkssecurityProvider: security provider to useforceSecurityRefactor: apply security fixes without promptingstrict: fail on security provider errorsimport { resolveJSON, update } from "pastoralist";
// Basic usage
const path = "./package.json";
const config = resolveJSON(path);
if (config) {
update({ config, path });
}
// With specific path
const workspacePath = "./packages/app/package.json";
const workspaceConfig = resolveJSON(workspacePath);
if (workspaceConfig) {
update({ config: workspaceConfig, path: workspacePath });
}
// With debug mode
if (config) {
update({ config, path, debug: true });
}
// Multiple packages
if (config) {
update({
config,
path,
depPaths: ["packages/*/package.json"],
ignore: ["**/test/**"],
});
}
optimizeBestCasePortfolio(options)Evaluate complete package-version states and return the lowest-risk state under a lexicographic policy. The evaluator must return alerts for the complete state, not for one package in isolation.
params:
choices: package names, current versions, and candidate versionsevaluate: async BestCaseEvaluator callback for one complete stateconfig: optional BestCaseConfig policy and search limitsimport {
optimizeBestCasePortfolio,
type BestCaseEvaluator,
type BestCasePackageChoice,
} from "pastoralist";
const choices: BestCasePackageChoice[] = [
{
packageName: "example",
currentVersion: "1.0.0",
versions: ["1.0.0", "1.1.0"],
},
];
const evaluate: BestCaseEvaluator = async (state) => {
const usesVulnerableVersion = state.example === "1.0.0";
const alerts = usesVulnerableVersion
? [
{
packageName: "example",
currentVersion: state.example,
vulnerableVersions: "<1.1.0",
patchedVersion: "1.1.0",
severity: "high" as const,
title: "Example vulnerability",
cves: ["CVE-2026-1234"],
fixAvailable: true,
},
]
: [];
return { alerts };
};
const result = await optimizeBestCasePortfolio({
choices,
evaluate,
config: {
enabled: true,
search: { mode: "auto", exactStateLimit: 256 },
},
});
console.log(result.selectedState);
console.log(result.search.provenOptimal);
BestCaseEvaluation may also return incompatibilities, oldness, valid,
and error. Rejected callbacks are recorded as invalid states and do not abort
other evaluations.
SecurityChecker.checkSecurity(config, options) accepts bestCase and a
project-supplied bestCaseEvaluator. Package JSON can configure bestCase, but
the evaluator is an API option because functions cannot be stored in JSON.
LedgerReason is a non-empty string, ProjectReason, or BestCaseReason.
Reasons are stored per appendix dependency.
import type { LedgerReason } from "pastoralist";
const reason: LedgerReason = {
type: "project",
summary: "Pin this dependency while the upstream fix is reviewed.",
pin: "3.2.1",
patch: "patches/example+3.2.1.patch",
constraints: ["Must retain the current runtime API"],
references: ["https://example.com/upstream/issue/123"],
};
A BestCaseReason contains decisionId, policyHash, search, and impact.
CVEs stay in ledger.cves; they are not duplicated in the reason.
logger(config)Create a logger instance for custom debugging.
params:
config: logger configuration
file: source file nameisLogging: enable/disable loggingimport { logger } from "pastoralist";
// Create logger
const log = logger({
file: "my-script.js",
isLogging: true,
});
// Use logger
log.debug("starting action", "method-name", { data: "value" });
log.error("unexpected error", "method-name", { error: err });
import { resolveJSON, update } from "pastoralist";
const path = "./package.json";
const config = resolveJSON(path);
// Ensure overrides are up-to-date before building
if (config) {
update({ config, path });
console.log("Package overrides verified");
}
import { resolveJSON, update } from "pastoralist";
import glob from "glob";
// Update all workspace packages
const packages = glob.sync("packages/*/package.json");
for (const pkgPath of packages) {
const pkg = resolveJSON(pkgPath);
if (pkg) {
update({ config: pkg, path: pkgPath });
console.log(`Updated ${pkgPath}`);
}
}
import { resolveJSON, update } from "pastoralist";
import { execSync } from "child_process";
const path = "./package.json";
const config = resolveJSON(path);
// Check if overrides are up-to-date
const before = execSync("git status --porcelain").toString();
if (config) {
update({ config, path });
}
const after = execSync("git status --porcelain").toString();
if (before !== after) {
console.error("Package.json overrides need updating");
process.exit(1);
}
import { logger, resolveJSON, update } from "pastoralist";
// Create custom logger
const log = logger({
file: "my-script.js",
isLogging: process.env.DEBUG === "true",
});
const path = "./package.json";
const config = resolveJSON(path);
// Log custom events
log.debug("starting", "custom-action", { time: Date.now() });
if (config) {
update({ config, path, debug: true });
}
log.debug("completed", "custom-action", { time: Date.now() });
import { resolveJSON, update } from "pastoralist";
try {
const path = "./package.json";
const config = resolveJSON(path);
if (!config) throw new Error("Package.json not found");
update({ config, path });
} catch (error) {
if (error.message === "Package.json not found") {
console.error("Package.json not found");
} else {
console.error("Unexpected error:", error);
}
}
DEBUG=trueEnable debug output (equivalent to --debug flag).
DEBUG=true npx pastoralist
Pastoralist includes full TypeScript support.
import { resolveJSON, update, type Options } from "pastoralist";
const path = "./package.json";
const config = resolveJSON(path);
if (!config) {
throw new Error("Package.json not found");
}
const options: Options = {
config,
path,
debug: true,
};
update(options);
npx pastoralist
npx pastoralist doctor
npx pastoralist onboard
# Run on a specific package
npx pastoralist --path packages/app/package.json
# Run on a nested project
npx pastoralist --path ./nested/project/package.json
# Run on all packages in monorepo
npx pastoralist --depPaths "packages/*/package.json"
# Run on multiple directories
npx pastoralist --depPaths "packages/*/package.json" "apps/*/package.json"
# Ignore test directories
npx pastoralist --ignore "**/test/**" "**/dist/**"
# Ignore specific packages
npx pastoralist --depPaths "**/*package.json" --ignore "**/node_modules/**" "**/legacy/**"
# Run from different directory
npx pastoralist --root /path/to/project
# Combine with other options
npx pastoralist --root ../my-project --path package.json
# Start interactive setup
npx pastoralist init
npx pastoralist --init agent-skill
# Review security fixes before applying them
npx pastoralist --checkSecurity --interactive
npx pastoralist --debug
npx pastoralist --dry-run
npx pastoralist --summary --outputFormat json
npx pastoralist --quiet --checkSecurity
npx pastoralist --summary
npx pastoralist --setup-hook
npx -p pastoralist pastoralist-setup-local-dev --dry-run
npx -p pastoralist pastoralist-setup-local-dev --skills all --hooks git,postinstall
npx pastoralist --remove-unused
npx pastoralist --checkSecurity
npx pastoralist --checkSecurity --securityProvider osv npm
npx pastoralist --checkSecurity --forceSecurityRefactor
npx pastoralist --checkSecurity --strict
npx pastoralist --checkSecurity --cache-dir .cache/pastoralist
npx pastoralist --checkSecurity --cache-ttl 3600
npx pastoralist --checkSecurity --no-cache
npx pastoralist --checkSecurity --refresh-cache
npm install pastoralist
import { resolveJSON, update } from "pastoralist";
// Basic usage
const path = "./package.json";
const config = resolveJSON(path);
if (config) {
update({ config, path });
}
// With specific path
const workspacePath = "./packages/app/package.json";
const workspaceConfig = resolveJSON(workspacePath);
if (workspaceConfig) {
update({ config: workspaceConfig, path: workspacePath });
}
// With debug mode
if (config) {
update({ config, path, debug: true });
}
// Multiple packages
if (config) {
update({
config,
path,
depPaths: ["packages/*/package.json"],
ignore: ["**/test/**"],
});
}
import {
optimizeBestCasePortfolio,
type BestCaseEvaluator,
type BestCasePackageChoice,
} from "pastoralist";
const choices: BestCasePackageChoice[] = [
{
packageName: "example",
currentVersion: "1.0.0",
versions: ["1.0.0", "1.1.0"],
},
];
const evaluate: BestCaseEvaluator = async (state) => {
const usesVulnerableVersion = state.example === "1.0.0";
const alerts = usesVulnerableVersion
? [
{
packageName: "example",
currentVersion: state.example,
vulnerableVersions: "<1.1.0",
patchedVersion: "1.1.0",
severity: "high" as const,
title: "Example vulnerability",
cves: ["CVE-2026-1234"],
fixAvailable: true,
},
]
: [];
return { alerts };
};
const result = await optimizeBestCasePortfolio({
choices,
evaluate,
config: {
enabled: true,
search: { mode: "auto", exactStateLimit: 256 },
},
});
console.log(result.selectedState);
console.log(result.search.provenOptimal);
import type { LedgerReason } from "pastoralist";
const reason: LedgerReason = {
type: "project",
summary: "Pin this dependency while the upstream fix is reviewed.",
pin: "3.2.1",
patch: "patches/example+3.2.1.patch",
constraints: ["Must retain the current runtime API"],
references: ["https://example.com/upstream/issue/123"],
};
import { logger } from "pastoralist";
// Create logger
const log = logger({
file: "my-script.js",
isLogging: true,
});
// Use logger
log.debug("starting action", "method-name", { data: "value" });
log.error("unexpected error", "method-name", { error: err });
import { resolveJSON, update } from "pastoralist";
const path = "./package.json";
const config = resolveJSON(path);
// Ensure overrides are up-to-date before building
if (config) {
update({ config, path });
console.log("Package overrides verified");
}
import { resolveJSON, update } from "pastoralist";
import glob from "glob";
// Update all workspace packages
const packages = glob.sync("packages/*/package.json");
for (const pkgPath of packages) {
const pkg = resolveJSON(pkgPath);
if (pkg) {
update({ config: pkg, path: pkgPath });
console.log(`Updated ${pkgPath}`);
}
}
import { resolveJSON, update } from "pastoralist";
import { execSync } from "child_process";
const path = "./package.json";
const config = resolveJSON(path);
// Check if overrides are up-to-date
const before = execSync("git status --porcelain").toString();
if (config) {
update({ config, path });
}
const after = execSync("git status --porcelain").toString();
if (before !== after) {
console.error("Package.json overrides need updating");
process.exit(1);
}
import { logger, resolveJSON, update } from "pastoralist";
// Create custom logger
const log = logger({
file: "my-script.js",
isLogging: process.env.DEBUG === "true",
});
const path = "./package.json";
const config = resolveJSON(path);
// Log custom events
log.debug("starting", "custom-action", { time: Date.now() });
if (config) {
update({ config, path, debug: true });
}
log.debug("completed", "custom-action", { time: Date.now() });
import { resolveJSON, update } from "pastoralist";
try {
const path = "./package.json";
const config = resolveJSON(path);
if (!config) throw new Error("Package.json not found");
update({ config, path });
} catch (error) {
if (error.message === "Package.json not found") {
console.error("Package.json not found");
} else {
console.error("Unexpected error:", error);
}
}
DEBUG=true npx pastoralist
import { resolveJSON, update, type Options } from "pastoralist";
const path = "./package.json";
const config = resolveJSON(path);
if (!config) {
throw new Error("Package.json not found");
}
const options: Options = {
config,
path,
debug: true,
};
update(options);