Loading...
Loading...
Audit a pnpm 10+ workspace for configuration and monorepo problems: dependency placement, workspace protocol usage, hoisting, catalog configuration, build order and build hooks, dependency rules, and .npmrc settings that are now defaults. Reads and reports only.
npx skill4agent add edloidas/skills workspace-auditcat pnpm-workspace.yaml 2>/dev/null
cat package.json | jq '.packageManager, .engines'
ls -la nx.json turbo.json 2>/dev/nullpackageManager# Good: Explicit patterns
packages:
- 'packages/*'
- 'apps/*'
- 'tools/*'
# Avoid: Too broad
packages:
- '**'pnpm-workspace.yamlpackages:{
"dependencies": {
"@myorg/shared": "workspace:*",
"@myorg/utils": "workspace:^"
}
}"^1.0.0"workspace:*# Find all package.json files and check for org-scoped internal refs
fd -t f 'package.json' packages apps | xargs grep -l '@myorg/'node_modules.npmrchoist=true # enables hoisting to .pnpm/node_modules
shamefully-hoist=true # makes node_modules flat like npm — last resortshamefully-hoist=truepnpm dedupe --check# pnpm-workspace.yaml
catalog:
react: ^19.0.0
react-dom: ^19.0.0
typescript: ^5.0.0
vite: ^6.0.0
vitest: ^3.0.0
# npm: prefix aliases a name to a different package implementation
# vite: npm:@org/custom-vite-fork@^1.0.0{
"dependencies": { "react": "catalog:", "react-dom": "catalog:" },
"devDependencies": { "vite": "catalog:", "vitest": "catalog:", "typescript": "catalog:" }
}catalog:@latestminimumReleaseAgenpm:@latestcatalogMode: forcecatalog:cleanupUnusedCatalogs: true{
"name": "@myorg/app",
"dependencies": {
"@myorg/ui": "workspace:*",
"@myorg/utils": "workspace:*"
}
}pnpm -r run build # respects topological order
turbo run build --dry-run # if Turbo is usedpnpm-workspace.yamlpackage.json# Blacklist: skip post-install scripts for these
ignoredBuiltDependencies:
- unrs-resolver
- sharp
# Whitelist: only these packages may run post-install scripts
onlyBuiltDependencies:
- esbuildallowBuildsignoredBuiltDependenciesonlyBuiltDependenciesallowBuilds:
esbuild: true
unrs-resolver: false
sharp: falsestrictDepBuildsstrictDepBuilds: trueonlyBuiltDependenciesallowBuildsstrictDepBuildspnpm-workspace.yamlminimumReleaseAge: 1440 # 24 hours
minimumReleaseAgeExclude:
- '@typescript/native-preview' # bleeding-edge, exempt by design1440minimumReleaseAgetrustPolicy: audit # audit | warn | off
trustPolicyExclude: # (10.22+) exempt specific packages
- '@myorg/internal'
trustPolicyIgnoreAfter: 525600 # (10.27+) ignore trust for packages older than 1 yeartrustPolicyminimumReleaseAgeblockExoticSubdeps: truecatalog:overrides:
vite: 'catalog:' # force transitive consumers to use the catalog version
vitest: 'catalog:'
lodash: '^4.17.21' # pin vulnerable transitive deppeerDependencyRules:
allowAny:
- vite
- vitest
allowedVersions:
vite: '*'
vitest: '*'allowAny: ['*'].npmrc| Setting | Issue |
|---|---|
| Default in pnpm 9+ — redundant |
| Default in pnpm 10 — redundant; use |
| Superseded by |
| Not default; use only if you want hard failures on peer mismatches — evaluate per-project |
.npmrc.npmrc# Private registry for scoped packages
@myorg:registry=https://npm.myorg.com/
# Windows cross-platform script compatibility
shell-emulator=truenpx syncpack list-mismatchesnpx madge --circular packages/*/srccleanupUnusedCatalogs: truepnpm-workspace.yamlpnpm install # removes stale entries if cleanupUnusedCatalogs is enabled## Workspace Audit Report
### Structure
- pnpm version: 10.x
- Packages: 5 (3 apps, 2 libs)
### Workspace Protocol
- [x] workspace:* used for all internal deps
- [ ] 2 packages use hardcoded versions for internal deps
### Catalog
- [x] Shared deps pinned in catalog
- [ ] @latest used in 1 catalog entry — defeats reproducibility
- [ ] catalogMode not set — consider force to enforce catalog usage
### Build Hooks
- [x] onlyBuiltDependencies configured in pnpm-workspace.yaml
- [ ] Build hook config found in package.json — move to pnpm-workspace.yaml
- [ ] strictDepBuilds not set — unchecked build scripts
### Dependency Rules
- [ ] minimumReleaseAge not set (supply-chain risk)
- [ ] trustPolicy not set (complements minimumReleaseAge)
- [x] overrides pin transitive deps to catalog versions
- [ ] blockExoticSubdeps not set — exotic transitive sources unchecked
### Configuration
- [x] .npmrc is minimal — no cargo-culted settings
- [ ] prefer-frozen-lockfile=true in .npmrc — already the default, remove it
### Recommendations
1. Set minimumReleaseAge: 1440 in pnpm-workspace.yaml
2. Set trustPolicy: audit alongside minimumReleaseAge
3. Move build hook config from package.json to pnpm-workspace.yaml
4. Enable strictDepBuilds: true
5. Replace hardcoded internal dep versions with workspace:*references/workspace-template.md