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")
StatusMaintenance onlyActively developed
Install modelnode_modules folderPlug'n'Play (PnP) by default
Config file.yarnrc.yarnrc.yml
CLIyarn add, yarn upgradeyarn add, yarn up
Zero-installsNoYes (via committed cache)
WorkspacesYesYes (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+:

bash
# 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.

bash
yarn --version

Output:

text
4.5.1

To install Yarn Classic (v1) globally via npm (legacy use only):

bash
npm install -g yarn@1

Output: (none — exits 0 on success)

Install project dependencies

bash
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:

text
➤ 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

bash
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):

text
➤ 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

bash
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

bash
# 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

bash
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):

text
└─ my-app@workspace:.
   └─ express@npm:4.19.2 (via npm:^4.19.2)

Run scripts

bash
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.

bash
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):

text
✔ 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.lock to 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-run yarn 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/cache and .pnp.cjs to git; CI never needs to run yarn install.
bash
# 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:

yaml
# .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.

json
// Root package.json
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": ["packages/*", "apps/*"]
}
bash
# 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):

text
➤ 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:

bash
# 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:

bash
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:

bash
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

Featurenpm v10pnpm v9Yarn v4
Lockfilepackage-lock.jsonpnpm-lock.yamlyarn.lock
Install speedBaseline2–3× faster1.5–2× faster
Disk efficiencyLow (copies)High (hard-links)High (zip cache)
Strict isolationNoYesYes (PnP)
Zero-installsNoNoYes (with PnP)
WorkspacesYesYesYes
Corepack supportYesYesYes
PnP supportNoNoYes (default)
MaturityVery stableStableStable

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.

ConcernYarn Classic (v1)Yarn Berry (v2/v3/v4)
Last releasev1.22.22 (frozen)v4.5.x (active)
CLI binaryInstalled globallyPer-project shim via Corepack
Config file.yarnrc (key=value).yarnrc.yml (YAML)
Lockfile formatyarn.lock (custom)yarn.lock (custom, incompatible schema)
Default linkernode_modulespnp
Cache~/.yarn/cache (per-version dirs).yarn/cache/*.zip (per-project zip files)
PluginsNoneFirst-class plugin system
WorkspacesYes (basic)Yes (with foreach, constraints)
yarn upgradeBumps within rangeRenamed to yarn up
Add packageyarn add fooyarn add foo (same)
Run scriptyarn run build / yarn buildSame (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-modules in .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

text
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.

bash
# 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.

bash
# In CI — no install step required
yarn test
yarn build

Output:

text
Test Suites: 12 passed, 12 total
Tests:       84 passed, 84 total

Add this to .gitignore to commit cache but skip generated artifacts:

text
.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.

bash
yarn dlx @yarnpkg/sdks vscode
yarn dlx @yarnpkg/sdks vim
yarn dlx @yarnpkg/sdks base   # generic — works for any editor with --reach

Output:

text
✔ 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:

yaml
# .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.

javascript
// 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);
      }
    }
  },
};
bash
# Check for violations
yarn constraints

# Auto-fix violations
yarn constraints --fix

Output (yarn constraints with a violation):

text
➤ 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.

bash
# 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):

text
➤ 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.

bash
yarn upgrade-interactive

Output:

text
? 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.

bash
# 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):

text
➤ 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.

json
{
  "dependencies": {
    "@my-org/ui": "workspace:*",
    "@my-org/utils": "workspace:^",
    "@my-org/types": "workspace:~1.2.3"
  }
}
SpecifierResolves toOn publish
workspace:*Any versionReplaced with the exact installed version
workspace:^Caret of the workspace versionReplaced with ^<v>
workspace:~TildeReplaced with ~<v>
workspace:1.2.3PinnedReplaced with 1.2.3

.yarnrc.yml configuration reference

.yarnrc.yml is the project-level config. Common keys you'll touch:

yaml
# .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.

bash
# 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):

text
➤ 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

Featurenpm v10pnpm v9Yarn v4Bun v1.2
Lockfilepackage-lock.jsonpnpm-lock.yamlyarn.lockbun.lock
Install modelHoisted node_modulesSymlinked node_modulesPnP (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 monorepoWorkspacesWorkspaces + catalogsWorkspaces + constraintsWorkspaces
Native TypeScript execNoNoVia tsxYes
Plugin systemNoVia hooksYes (first-class)No
Zero-installsNoNoYesNo
Cross-platform scriptsVia cross-envshell-emulator=trueYarn's own shell parserYes
Ecosystem maturityVery stableStableStableMaturing

See bun for the Bun deep-dive; pnpm for the disk-efficient alternative.

Common pitfalls

  1. "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@1 or migrate to v4.
  2. PnP breaks eslint --resolve-plugins-relative-to — ESLint v8+ understands PnP only after you yarn dlx @yarnpkg/sdks or set pnp integration in your config.
  3. yarn.lock merge conflicts — accept either side and re-run yarn install. Yarn regenerates a deterministic lockfile.
  4. CI cache misses on Yarn Berry — cache .yarn/cache/ and .yarn/install-state.gz, not node_modules (with PnP there is no node_modules to cache).
  5. yarn workspaces foreach skipping packages — the script name must exist in every workspace. Add --if-present or filter explicitly.
  6. Editors showing red squiggles in PnP projects — generate SDKs: yarn dlx @yarnpkg/sdks vscode. The shims point at the zipped cache.
  7. Postinstall scripts not running under v4 with enableScripts: false — explicitly allow per-package or set enableScripts: true after auditing.
  8. workspace:* shipping to npm — Yarn rewrites this on publish, but only via yarn npm publish. Direct npm publish will ship the literal workspace:* string and break consumers.
  9. yarn config set foo bar writing to the wrong file — Yarn Berry uses .yarnrc.yml; running v1's yarn config against a Berry project produces silent no-ops. Edit .yarnrc.yml directly.
  10. 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.

bash
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):

text
➤ 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.

json
{
  "packageManager": "yarn@4.5.1"
}
bash
corepack enable
corepack prepare yarn@4.5.1 --activate
yarn --version

Output:

text
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.

yaml
# .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
bash
yarn test

Output:

text
➤ 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.

bash
yarn patch lodash@npm:4.17.21

Output:

text
➤ 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:

bash
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.

bash
yarn workspaces foreach --since=origin/main --recursive --parallel run test

Output:

text
➤ 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.

bash
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):

text
➤ 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