Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
pnpm 10.x reference skill covering workspaces, catalogs, patches, peer deps, overrides, and CI/CD caching strategies.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/features-hooks.md
1---2name: pnpm-hooks3description: Customize package resolution and dependency behavior with pnpmfile hooks4---56# pnpm Hooks78pnpm provides hooks via `.pnpmfile.cjs` to customize how packages are resolved and their metadata is processed.910## Setup1112Create `.pnpmfile.cjs` at workspace root:1314```js15// .pnpmfile.cjs16function readPackage(pkg, context) {17// Modify package metadata18return pkg19}2021function afterAllResolved(lockfile, context) {22// Modify lockfile23return lockfile24}2526module.exports = {27hooks: {28readPackage,29afterAllResolved30}31}32```3334## readPackage Hook3536Called for every package before resolution. Use to modify dependencies, add missing peer deps, or fix broken packages.3738### Add Missing Peer Dependency3940```js41function readPackage(pkg, context) {42if (pkg.name === 'some-broken-package') {43pkg.peerDependencies = {44...pkg.peerDependencies,45react: '*'46}47context.log(`Added react peer dep to ${pkg.name}`)48}49return pkg50}51```5253### Override Dependency Version5455```js56function readPackage(pkg, context) {57// Fix all lodash versions58if (pkg.dependencies?.lodash) {59pkg.dependencies.lodash = '^4.17.21'60}61if (pkg.devDependencies?.lodash) {62pkg.devDependencies.lodash = '^4.17.21'63}64return pkg65}66```6768### Remove Unwanted Dependency6970```js71function readPackage(pkg, context) {72// Remove optional dependency that causes issues73if (pkg.optionalDependencies?.fsevents) {74delete pkg.optionalDependencies.fsevents75}76return pkg77}78```7980### Replace Package8182```js83function readPackage(pkg, context) {84// Replace deprecated package85if (pkg.dependencies?.['old-package']) {86pkg.dependencies['new-package'] = pkg.dependencies['old-package']87delete pkg.dependencies['old-package']88}89return pkg90}91```9293### Fix Broken Package9495```js96function readPackage(pkg, context) {97// Fix incorrect exports field98if (pkg.name === 'broken-esm-package') {99pkg.exports = {100'.': {101import: './dist/index.mjs',102require: './dist/index.cjs'103}104}105}106return pkg107}108```109110## afterAllResolved Hook111112Called after the lockfile is generated. Use for post-resolution modifications.113114```js115function afterAllResolved(lockfile, context) {116// Log all resolved packages117context.log(`Resolved ${Object.keys(lockfile.packages || {}).length} packages`)118119// Modify lockfile if needed120return lockfile121}122```123124## Context Object125126The `context` object provides utilities:127128```js129function readPackage(pkg, context) {130// Log messages131context.log('Processing package...')132133return pkg134}135```136137## Use with TypeScript138139For type hints, use JSDoc:140141```js142// .pnpmfile.cjs143144/**145* @param {import('type-fest').PackageJson} pkg146* @param {{ log: (msg: string) => void }} context147* @returns {import('type-fest').PackageJson}148*/149function readPackage(pkg, context) {150return pkg151}152153module.exports = {154hooks: {155readPackage156}157}158```159160## Common Patterns161162### Conditional by Package Name163164```js165function readPackage(pkg, context) {166switch (pkg.name) {167case 'package-a':168pkg.dependencies.foo = '^2.0.0'169break170case 'package-b':171delete pkg.optionalDependencies.bar172break173}174return pkg175}176```177178### Apply to All Packages179180```js181function readPackage(pkg, context) {182// Remove all optional fsevents183if (pkg.optionalDependencies) {184delete pkg.optionalDependencies.fsevents185}186return pkg187}188```189190### Debug Resolution191192```js193function readPackage(pkg, context) {194if (process.env.DEBUG_PNPM) {195context.log(`${pkg.name}@${pkg.version}`)196context.log(` deps: ${Object.keys(pkg.dependencies || {}).join(', ')}`)197}198return pkg199}200```201202## Hooks vs Overrides203204| Feature | Hooks (.pnpmfile.cjs) | Overrides |205|---------|----------------------|-----------|206| Complexity | Can use JavaScript logic | Declarative only |207| Scope | Any package metadata | Version only |208| Use case | Complex fixes, conditional logic | Simple version pins |209210**Prefer overrides** for simple version fixes. **Use hooks** when you need:211- Conditional logic212- Non-version modifications (exports, peer deps)213- Logging/debugging214215## Troubleshooting216217### Hook not running2182191. Ensure file is named `.pnpmfile.cjs` (not `.js`)2202. Check file is at workspace root2213. Run `pnpm install` to trigger hooks222223### Debug hooks224225```bash226# See hook logs227pnpm install --reporter=append-only228```229230<!--231Source references:232- https://pnpm.io/pnpmfile233-->234