cheat sheet
Yarn Package Manager
Yarn is a fast, deterministic package manager from Meta. Covers Yarn Classic (v1) vs Yarn Berry (v4), install, add, remove, workspaces, Plug'n'Play, and migration tips.
Yarn Package Manager
What it is
Yarn is a package manager created by Meta (then Facebook) in 2016 as a faster, more reliable alternative to npm. It introduced deterministic installs via a lockfile (yarn.lock) and offline installs via a local cache.
There are two major, incompatible lines of Yarn:
| Yarn Classic (v1) | Yarn Berry (v2–v4, "modern") | |
|---|---|---|
| Status | Maintenance only | Actively developed |
| Install model | node_modules folder | Plug'n'Play (PnP) by default |
| Config file | .yarnrc | .yarnrc.yml |
| CLI | yarn add, yarn upgrade | yarn add, yarn up |
| Zero-installs | No | Yes (via committed cache) |
| Workspaces | Yes | Yes (improved) |
For new projects in 2026, use Yarn v4 via Corepack. Yarn Classic (v1) is in maintenance mode and should not be chosen for new work.
Install Yarn
The recommended approach for modern Yarn is via Corepack, which ships with Node.js 16.9+:
# Enable Corepack (one-time, may need sudo on Linux)
corepack enable
# Activate the latest stable Yarn in the current project
corepack prepare yarn@stable --activate
# Or pin a specific version
corepack prepare yarn@4.5.1 --activate
Output: (none — exits 0 on success)
This sets the packageManager field in package.json and places a local Yarn binary shim so every developer on the project uses the same version.
yarn --version
Output:
4.5.1
To install Yarn Classic (v1) globally via npm (legacy use only):
npm install -g yarn@1
Output: (none — exits 0 on success)
Install project dependencies
yarn install # install all deps from package.json + yarn.lock
yarn install --immutable # CI mode: fail if yarn.lock would change
yarn install --mode skip-build # skip postinstall scripts
Output:
➤ YN0000: · Yarn 4.5.1
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed in 0s 312ms
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed in 1s 420ms
➤ YN0000: ┌ Link step
➤ YN0000: └ Completed in 0s 218ms
➤ YN0000: · Done with warnings in 2s 012ms
Add packages
yarn add express # add to dependencies
yarn add -D typescript ts-node # add to devDependencies
yarn add -O nodemailer # add to optionalDependencies
yarn add -g serve # install globally (v1 only; v4 uses yarn dlx)
yarn add lodash@4.17.21 # specific version
yarn add "axios@>=1.0.0 <2" # version range
yarn add github:user/repo # from GitHub
Output (yarn add express):
➤ YN0000: · Yarn 4.5.1
➤ YN0000: ┌ Resolution step
➤ YN0013: │ express@npm:^4.19.2 can be deduped from 4.18.2 to 4.19.2, but this would change the lockfile
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed in 0s 312ms
➤ YN0000: ┌ Link step
➤ YN0000: └ Completed
➤ YN0000: · Done in 1s 102ms
Remove packages
yarn remove express # remove from dependencies
yarn remove -D typescript # (v1: yarn remove; v4 infers from manifest)
Output: (none — exits 0 on success)
Update packages
# Yarn v4
yarn up lodash # update to latest matching version range
yarn up lodash@^4 # update and change range
yarn up --interactive # pick packages interactively (alias: yarn up -i)
yarn up "*" # update all packages
# Yarn v1 (classic)
yarn upgrade lodash
yarn upgrade-interactive --latest
Output: (none — exits 0 on success)
Inspect packages
yarn outdated # (v1 only) show packages with newer versions
yarn info lodash # show metadata for a package
yarn list # list installed packages
yarn list --pattern "react*" # filter list
yarn why express # explain why a package is installed
Output (yarn why express):
└─ my-app@workspace:.
└─ express@npm:4.19.2 (via npm:^4.19.2)
Run scripts
yarn run build # run the "build" script from package.json
yarn run dev # run "dev"
yarn start # shorthand for yarn run start
yarn test # shorthand for yarn run test
yarn run lint -- --fix # pass extra args after --
Output: (none — exits 0 on success)
yarn dlx — run a package without installing (v4)
yarn dlx is Yarn's equivalent of npx. It fetches and runs a package in a temporary environment.
yarn dlx create-next-app my-app # scaffold a Next.js project
yarn dlx create-vite my-app # scaffold a Vite project
yarn dlx @yarnpkg/sdks vscode # generate IDE SDK config for PnP
Output (yarn dlx create-vite my-app):
✔ Select a framework: › React
✔ Select a variant: › TypeScript
Scaffolding project in /home/user/my-app...
Done. Now run:
cd my-app
yarn install
yarn dev
yarn.lock
yarn.lock is automatically maintained by Yarn. It records the exact resolved version and checksum of every package in the dependency tree.
- Always commit
yarn.lockto version control. This guarantees every developer and every CI run installs identical versions. - Do not hand-edit
yarn.lock. Let Yarn manage it. - When you see a merge conflict in
yarn.lock, accept either side and re-runyarn install— Yarn will regenerate a correct file.
Plug'n'Play (PnP)
Yarn v4 defaults to Plug'n'Play mode. Instead of a node_modules folder, Yarn generates a .pnp.cjs file that teaches Node where each package lives in Yarn's cache.
Benefits:
- Installs are faster (no file copying).
- The dependency graph is strictly enforced.
- Zero-installs: commit
.yarn/cacheand.pnp.cjsto git; CI never needs to runyarn install.
# Check PnP integrity
yarn install --check-cache
# Generate IDE support files for PnP (VS Code, IntelliJ, etc.)
yarn dlx @yarnpkg/sdks vscode
yarn dlx @yarnpkg/sdks vim
Output: (none — exits 0 on success)
If PnP causes problems with a legacy package, fall back to node_modules linker in .yarnrc.yml:
# .yarnrc.yml — disable PnP and use node_modules instead
nodeLinker: node-modules
Workspaces
Yarn workspaces let you manage a monorepo from a single root package.json.
// Root package.json
{
"name": "my-monorepo",
"private": true,
"workspaces": ["packages/*", "apps/*"]
}
# Install all workspace deps from the root
yarn install
# Run a script in a specific workspace
yarn workspace my-app run build
yarn workspace @my-org/ui run dev
# Add a dep to a specific workspace
yarn workspace my-app add react
# Add a local workspace package as a dep
yarn workspace my-app add @my-org/ui@workspace:*
# Run a script across all workspaces (Yarn v4)
yarn workspaces foreach --all run test
yarn workspaces foreach --parallel run build
Output (yarn workspaces foreach --all run build):
➤ YN0000: ┌ [packages/ui]: $ tsc
➤ YN0000: └ Completed in 2s 401ms
➤ YN0000: ┌ [packages/utils]: $ tsc
➤ YN0000: └ Completed in 1s 812ms
➤ YN0000: ┌ [apps/web]: $ next build
➤ YN0000: └ Completed in 18s 734ms
Migrating between package managers
npm → Yarn:
# In a project with package.json but no yarn.lock
yarn install # imports npm deps, generates yarn.lock
rm package-lock.json # remove npm lockfile
Output: (none — exits 0 on success)
Yarn → npm:
npm install # npm reads package.json, ignores yarn.lock, generates package-lock.json
rm yarn.lock
Output: (none — exits 0 on success)
Yarn v1 → Yarn v4:
corepack enable
yarn set version stable # writes .yarnrc.yml, updates packageManager in package.json
yarn install # migrates
yarn dlx @yarnpkg/sdks vscode # update IDE support
Output: (none — exits 0 on success)
npm vs pnpm vs Yarn comparison
| Feature | npm v10 | pnpm v9 | Yarn v4 |
|---|---|---|---|
| Lockfile | package-lock.json | pnpm-lock.yaml | yarn.lock |
| Install speed | Baseline | 2–3× faster | 1.5–2× faster |
| Disk efficiency | Low (copies) | High (hard-links) | High (zip cache) |
| Strict isolation | No | Yes | Yes (PnP) |
| Zero-installs | No | No | Yes (with PnP) |
| Workspaces | Yes | Yes | Yes |
| Corepack support | Yes | Yes | Yes |
| PnP support | No | No | Yes (default) |
| Maturity | Very stable | Stable | Stable |
Yarn Classic (v1) vs Yarn Berry (v2+) — incompatibility in depth
Yarn split into two incompatible product lines in early 2020 when v2 (Berry) shipped with Plug'n'Play as the default. The split was contentious and many projects deferred migration; today (2026) Yarn v4 is mature and most ecosystems support PnP. Reach for this section when you inherit an old yarn codebase and need to know whether to migrate or hold.
| Concern | Yarn Classic (v1) | Yarn Berry (v2/v3/v4) |
|---|---|---|
| Last release | v1.22.22 (frozen) | v4.5.x (active) |
| CLI binary | Installed globally | Per-project shim via Corepack |
| Config file | .yarnrc (key=value) | .yarnrc.yml (YAML) |
| Lockfile format | yarn.lock (custom) | yarn.lock (custom, incompatible schema) |
| Default linker | node_modules | pnp |
| Cache | ~/.yarn/cache (per-version dirs) | .yarn/cache/*.zip (per-project zip files) |
| Plugins | None | First-class plugin system |
| Workspaces | Yes (basic) | Yes (with foreach, constraints) |
yarn upgrade | Bumps within range | Renamed to yarn up |
| Add package | yarn add foo | yarn add foo (same) |
| Run script | yarn run build / yarn build | Same (but no implicit fall-through to bin) |
| TypeScript editor support | "Just works" | Requires yarn dlx @yarnpkg/sdks vscode |
If a project is "stuck" on Yarn v1 because a single dependency fails under PnP, switch the linker to
node-modulesin.yarnrc.yml. You get the modern CLI, plugin system, and lockfile format without committing to PnP semantics.
Plug'n'Play (PnP) — deep-dive
PnP is Yarn Berry's flagship install strategy. Instead of materialising a node_modules tree, Yarn writes a single .pnp.cjs file that overrides Node's require() resolver with an in-memory map from (package, version) → location-in-.yarn/cache. Reach for PnP when install time and disk usage are pain points, or when you want zero-install workflows where CI never runs yarn install.
What ships on disk
my-app/
├── .pnp.cjs # the resolver — patches Node's require()
├── .pnp.loader.mjs # ESM loader (Node ≥ 16.12 with --loader)
├── .yarn/
│ ├── cache/ # immutable zip files, one per package
│ │ ├── express-npm-4.19.2-abc123.zip
│ │ └── ...
│ ├── releases/ # the Yarn binary itself (commit this)
│ │ └── yarn-4.5.1.cjs
│ ├── plugins/ # plugins installed via yarn plugin import
│ └── sdks/ # IDE support files (gitignored)
├── .yarnrc.yml
├── package.json
└── yarn.lock
The .yarn/cache/*.zip files are the actual package contents. PnP unzips them lazily into memory via the zipfs virtual filesystem — no extraction step.
Run a script under PnP
Yarn injects the resolver automatically for any process started by yarn run. From outside Yarn (e.g. an editor or node directly), you need the loader flag.
# Yarn-spawned process — PnP is set up automatically
yarn node script.js
# Native node — must inject the loader
node --require ./.pnp.cjs --loader ./.pnp.loader.mjs script.mjs
Output: (none — exits 0 on success)
Zero-installs
Commit .yarn/cache/ (the zip files) and .pnp.cjs to git. Clones include everything needed — yarn install becomes optional in CI.
# In CI — no install step required
yarn test
yarn build
Output:
Test Suites: 12 passed, 12 total
Tests: 84 passed, 84 total
Add this to .gitignore to commit cache but skip generated artifacts:
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.pnp.*
Wait — invert the last line: do commit .pnp.* for zero-installs, don't commit it if you're not using zero-installs (it's regenerated each install). The Yarn docs ship the canonical version.
IDE support for PnP
Editors don't know about Yarn's virtual filesystem out of the box. Generate SDK shims that point your editor's TypeScript at the in-cache copy.
yarn dlx @yarnpkg/sdks vscode
yarn dlx @yarnpkg/sdks vim
yarn dlx @yarnpkg/sdks base # generic — works for any editor with --reach
Output:
✔ Skipping integration: vscode (already installed)
✔ Installed SDKs for VS Code
✔ Updated .gitignore
In VS Code, switch the workspace TypeScript version to the Yarn SDK (Command Palette → "TypeScript: Select TypeScript Version" → "Use Workspace Version").
When to fall back from PnP to node_modules
Most issues today are package-specific, not framework-wide. Try the project once; if a single package misbehaves, file an upstream issue and use .yarnrc.yml to switch only that package:
# .yarnrc.yml — switch to node_modules layout
nodeLinker: node-modules
# Or keep PnP but mark a package as "unplugged" — extract it to disk
# so it can do filesystem tricks (sharp, esbuild, etc.)
unpluggedPackages:
- sharp
- "@swc/core"
Output: (none — exits 0 on success)
Constraints — enforce monorepo policies
Constraints are a v4-only feature that lets you assert invariants across every workspace package — for example "every package depends on the same React version" or "every internal package has the same license". Constraints are Prolog-style rules in constraints.pro, but yarn constraints also accepts a JavaScript-based yarn.config.cjs.
// yarn.config.cjs
module.exports = {
async constraints({ Yarn }) {
// Every workspace must use the same react version
for (const dep of Yarn.dependencies({ ident: "react" })) {
dep.update("^18.3.1");
}
// Every package must have a license
for (const ws of Yarn.workspaces()) {
ws.set("license", "MIT");
}
// Internal packages must mark themselves private
for (const ws of Yarn.workspaces()) {
if (ws.ident?.startsWith("@my-org/internal-")) {
ws.set("private", true);
}
}
},
};
# Check for violations
yarn constraints
# Auto-fix violations
yarn constraints --fix
Output (yarn constraints with a violation):
➤ YN0000: ┌ Constraints checks
➤ YN0086: │ @my-org/web@workspace:apps/web must depend on react@^18.3.1, got ^17.0.2
➤ YN0000: └ Completed
➤ YN0086: · The lockfile would have been modified
yarn constraints --fix rewrites the manifests so violations disappear; commit the result.
Plugins — extend the CLI
Yarn Berry has a plugin system that adds commands and hooks. Plugins are CJS bundles loaded from .yarn/plugins/. The official ones cover constraints, interactive tools, version policies, and workspace utilities.
# List plugins available from the Yarn org
yarn plugin list
# Install a plugin (downloaded to .yarn/plugins/ and committed)
yarn plugin import @yarnpkg/plugin-interactive-tools
yarn plugin import @yarnpkg/plugin-typescript
yarn plugin import @yarnpkg/plugin-version
# Remove
yarn plugin remove @yarnpkg/plugin-interactive-tools
Output (yarn plugin import @yarnpkg/plugin-interactive-tools):
➤ YN0000: Downloading https://repo.yarnpkg.com/4.5.1/packages/plugin-interactive-tools/...
➤ YN0000: Saving the new plugin in .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
The interactive-tools plugin gives you yarn upgrade-interactive (Yarn v4's flagship feature for visual dependency upgrades) and yarn search.
yarn upgrade-interactive
Output:
? Pick the packages you want to upgrade.
Press <space> to select, <a> to toggle all, <i> to invert selection.
◯ Patch updates
react 18.3.0 → 18.3.1
◯ Minor updates
typescript 5.4.5 → 5.5.4
◯ Major updates
@types/node 20.12.7 → 22.5.0
Workspaces — monorepo deep-dive
Yarn v4 workspaces feel similar to pnpm's but lean more on plugins and built-in shell commands. The big differentiator is yarn workspaces foreach, which runs commands topologically across packages with concurrency control.
Filter workspaces
yarn workspaces foreach (alias yarn workspaces foreach --all) supports rich filtering by name, path, and dependency relationships.
# All workspaces (default)
yarn workspaces foreach --all run build
# Topologically — respect dependency order
yarn workspaces foreach --topological run build
# Parallel — independent tasks like lint/typecheck
yarn workspaces foreach --all --parallel run lint
# Limit concurrency
yarn workspaces foreach --all --parallel --jobs 4 run test
# By name
yarn workspaces foreach --include "@my-org/ui" --include "@my-org/api" run test
# By git diff — only what's changed since main
yarn workspaces foreach --since=origin/main run test
# Include packages that depend on the changed ones (transitively)
yarn workspaces foreach --since=origin/main --recursive run test
Output (yarn workspaces foreach --topological run build):
➤ YN0000: ┌ [@my-org/types]: $ tsc
➤ YN0000: └ Completed in 1s 102ms
➤ YN0000: ┌ [@my-org/utils]: $ tsc # waited for types
➤ YN0000: └ Completed in 1s 215ms
➤ YN0000: ┌ [@my-org/ui]: $ tsc # waited for utils
➤ YN0000: └ Completed in 2s 487ms
Workspace protocols
The workspace: protocol pins a dependency to a sibling workspace. yarn pack rewrites it to a real version on publish.
{
"dependencies": {
"@my-org/ui": "workspace:*",
"@my-org/utils": "workspace:^",
"@my-org/types": "workspace:~1.2.3"
}
}
| Specifier | Resolves to | On publish |
|---|---|---|
workspace:* | Any version | Replaced with the exact installed version |
workspace:^ | Caret of the workspace version | Replaced with ^<v> |
workspace:~ | Tilde | Replaced with ~<v> |
workspace:1.2.3 | Pinned | Replaced with 1.2.3 |
.yarnrc.yml configuration reference
.yarnrc.yml is the project-level config. Common keys you'll touch:
# .yarnrc.yml
nodeLinker: pnp # pnp | node-modules | pnpm
# Cache compression — lower = smaller .zip, slower install (0–9; default 0)
compressionLevel: 0
# Where to put .yarn/cache (default: alongside package.json)
cacheFolder: "./.yarn/cache"
# Treat each script invocation through Yarn's own shell (cross-platform)
enableScripts: true
# Telemetry — disable in CI
enableTelemetry: false
# Network — set a proxy for corporate VPNs
httpProxy: "http://proxy.example.com:8080"
httpsProxy: "http://proxy.example.com:8080"
networkConcurrency: 50
networkTimeout: 60000
# Pin the Yarn version (matches packageManager in package.json)
yarnPath: ".yarn/releases/yarn-4.5.1.cjs"
# Custom registry (alternative: per-scope via npmScopes)
npmRegistryServer: "https://registry.npmjs.org"
npmAlwaysAuth: true
# Auth tokens per registry
npmAuthToken: "${NPM_AUTH_TOKEN}"
npmScopes:
my-org:
npmRegistryServer: "https://npm.pkg.github.com"
npmAlwaysAuth: true
npmAuthToken: "${GITHUB_TOKEN}"
# Allow these packages to run install scripts (Yarn v4 prompts for unknown ones)
enableScripts: true
supportedArchitectures:
os: ["linux", "darwin", "win32"]
cpu: ["x64", "arm64"]
libc: ["glibc", "musl"]
Publishing — yarn npm publish
Yarn v4 publishes via yarn npm publish. The npm namespace exists because Yarn supports other registries via plugins; the npm one is the default.
# Bump version (npm-style)
yarn version patch # 1.2.3 → 1.2.4
yarn version minor # 1.2.3 → 1.3.0
yarn version major # 1.2.3 → 2.0.0
yarn version --immediate 1.5.0 # exact
# Dry-run pack — see what would ship without publishing
yarn pack --dry-run
# Publish a single workspace package
yarn workspace @my-org/ui npm publish --access public
# Publish every public workspace package
yarn workspaces foreach --all --no-private npm publish --tolerate-republish
Output (yarn npm publish):
➤ YN0000: ┌ Resolution step
➤ YN0000: └ Completed
➤ YN0000: ┌ Fetch step
➤ YN0000: └ Completed
➤ YN0000: ┌ Link step
➤ YN0000: └ Completed
➤ YN0000: ┌ npm publish
➤ YN0000: │ + @my-org/ui@1.2.4
➤ YN0000: └ Completed in 2s 814ms
Yarn vs npm vs pnpm vs Bun — final comparison
| Feature | npm v10 | pnpm v9 | Yarn v4 | Bun v1.2 |
|---|---|---|---|---|
| Lockfile | package-lock.json | pnpm-lock.yaml | yarn.lock | bun.lock |
| Install model | Hoisted node_modules | Symlinked node_modules | PnP (or node_modules) | Hoisted node_modules |
| Cold install (300 pkgs) | ~45 s | ~18 s | ~25 s (PnP: ~12 s) | ~3 s |
| Disk per project | ~250 MB | ~5 MB | ~20 MB (PnP cache) | ~250 MB |
| Built-in monorepo | Workspaces | Workspaces + catalogs | Workspaces + constraints | Workspaces |
| Native TypeScript exec | No | No | Via tsx | Yes |
| Plugin system | No | Via hooks | Yes (first-class) | No |
| Zero-installs | No | No | Yes | No |
| Cross-platform scripts | Via cross-env | shell-emulator=true | Yarn's own shell parser | Yes |
| Ecosystem maturity | Very stable | Stable | Stable | Maturing |
See bun for the Bun deep-dive; pnpm for the disk-efficient alternative.
Common pitfalls
- "Yarn v1 command not found" after enabling Corepack — Corepack ships a v1-incompatible shim for old projects. Either install v1 globally via
npm install -g yarn@1or migrate to v4. - PnP breaks
eslint --resolve-plugins-relative-to— ESLint v8+ understands PnP only after youyarn dlx @yarnpkg/sdksor setpnpintegration in your config. yarn.lockmerge conflicts — accept either side and re-runyarn install. Yarn regenerates a deterministic lockfile.- CI cache misses on Yarn Berry — cache
.yarn/cache/and.yarn/install-state.gz, notnode_modules(with PnP there is no node_modules to cache). yarn workspaces foreachskipping packages — the script name must exist in every workspace. Add--if-presentor filter explicitly.- Editors showing red squiggles in PnP projects — generate SDKs:
yarn dlx @yarnpkg/sdks vscode. The shims point at the zipped cache. - Postinstall scripts not running under v4 with
enableScripts: false— explicitly allow per-package or setenableScripts: trueafter auditing. workspace:*shipping to npm — Yarn rewrites this on publish, but only viayarn npm publish. Directnpm publishwill ship the literalworkspace:*string and break consumers.yarn config set foo barwriting to the wrong file — Yarn Berry uses.yarnrc.yml; running v1'syarn configagainst a Berry project produces silent no-ops. Edit.yarnrc.ymldirectly.- Corepack failing in offline CI — Corepack downloads the pinned Yarn release on first use. Pre-warm the cache or commit
.yarn/releases/yarn-<version>.cjs.
Real-world recipes
Migrate an existing Yarn v1 project to v4
The canonical upgrade path. Run inside a clean working tree so you can review every diff before committing.
corepack enable
yarn set version stable # writes .yarnrc.yml, updates packageManager
yarn install # regenerates yarn.lock in v4 format
yarn dlx @yarnpkg/sdks vscode # restore IDE intellisense for PnP
yarn dlx @yarnpkg/doctor # diagnose remaining issues
Output (yarn doctor):
➤ YN0000: ┌ General rules
➤ YN0000: │ ✓ Workspaces have a license field
➤ YN0000: │ ⚠ apps/web depends on missing peer "react-dom"
➤ YN0000: └ Completed
Pin Yarn version in the team's projects
Corepack reads packageManager in package.json. Pinning ensures every developer and every CI run uses the exact same Yarn binary.
{
"packageManager": "yarn@4.5.1"
}
corepack enable
corepack prepare yarn@4.5.1 --activate
yarn --version
Output:
4.5.1
Zero-install CI with cached PnP
The whole point of zero-installs: no yarn install in CI. Commit .yarn/cache/ and .pnp.cjs; CI clones and runs scripts.
# .github/workflows/ci.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: yarn test # no install — .yarn/cache is committed
- run: yarn build
yarn test
Output:
➤ YN0000: ┌ jest
➤ YN0000: │ Tests: 84 passed, 84 total
➤ YN0000: └ Completed in 14s 218ms
Apply a runtime patch to a single dependency
When upstream is slow to ship a fix, yarn patch produces a versioned patch file that's reapplied automatically on every install.
yarn patch lodash@npm:4.17.21
Output:
➤ YN0000: Package lodash@npm:4.17.21 got extracted with success!
➤ YN0000: You can now edit the following folder: /tmp/yarn-patch-xyz
➤ YN0000: Once you're done with your changes, run:
➤ YN0000: yarn patch-commit -s /tmp/yarn-patch-xyz
Edit the source, then:
yarn patch-commit -s /tmp/yarn-patch-xyz
Output: (none — exits 0 on success)
Yarn writes .yarn/patches/lodash-npm-4.17.21-<hash>.patch and updates package.json's resolutions so the patch is sticky across reinstalls.
Run only changed workspace packages in CI
--since filters workspaces by git diff. Combined with --recursive, it also runs against transitive consumers of the changed packages — the right scope for safety while keeping PR times bounded.
yarn workspaces foreach --since=origin/main --recursive --parallel run test
Output:
➤ YN0000: ┌ [@my-org/api]: $ vitest run
➤ YN0000: │ Tests: 24 passed
➤ YN0000: └ Completed
➤ YN0000: ┌ [@my-org/web]: $ vitest run # consumer of api
➤ YN0000: │ Tests: 38 passed
➤ YN0000: └ Completed
Publish all public workspace packages on tag
Combined yarn version + yarn workspaces foreach npm publish flow. Run from a clean working tree; commit version bumps in a single squash.
yarn workspaces foreach --all --no-private exec yarn version minor
git commit -am "release: bump minor across all packages"
git tag "v$(node -p "require('./package.json').version")"
yarn workspaces foreach --all --no-private npm publish --access public --tolerate-republish
git push --follow-tags
Output (final publish step):
➤ YN0000: ┌ [@my-org/types]: + @my-org/types@1.3.0
➤ YN0000: ├ [@my-org/utils]: + @my-org/utils@1.3.0
➤ YN0000: ├ [@my-org/ui]: + @my-org/ui@1.3.0
➤ YN0000: └ Completed in 8s 211ms