# Yarn Admin & Architecture Guide

A complete, source-based reference to the internals, configuration, operations, and security model of **Yarn 1 ("Classic")**, version `1.23.0-0` (commit `c2dda50`). This guide is written for operators, build engineers, platform architects, and contributors — anyone who needs to understand *how Yarn works inside* rather than just how to use it. For day-to-day command usage, see the companion **User Guide**.

---

## Table of Contents

1. [Executive Summary](#1-executive-summary)
2. [System Architecture](#2-system-architecture)
3. [The Install Pipeline](#3-the-install-pipeline)
4. [Repository Structure](#4-repository-structure)
5. [Module Reference](#5-module-reference)
6. [The Lockfile Format](#6-the-lockfile-format)
7. [Registries & Resolution](#7-registries--resolution)
8. [Configuration Mastery](#8-configuration-mastery)
9. [Environment Variables](#9-environment-variables)
10. [Caching, Mirrors & Storage](#10-caching-mirrors--storage)
11. [Security Analysis](#11-security-analysis)
12. [Operations & CI](#12-operations--ci)
13. [Building Yarn From Source](#13-building-yarn-from-source)
14. [Error Model & Exit Codes](#14-error-model--exit-codes)
15. [Code Quality & Conventions](#15-code-quality--conventions)
16. [Potential Improvements](#16-potential-improvements)
17. [Quick Reference](#17-quick-reference)

---

## 1. Executive Summary

Yarn is a command-line dependency manager for the JavaScript/Node.js ecosystem. Its job is to take a declarative manifest (`package.json`) and produce a deterministic, verified, on-disk dependency tree (`node_modules`) plus a lockfile (`yarn.lock`) that pins the exact result.

**Key facts**

| Property | Value |
|----------|-------|
| Project name | `yarn` (binaries: `yarn`, `yarnpkg`) |
| Version analyzed | `1.23.0-0` |
| License | BSD-2-Clause |
| Language | JavaScript (ES with Flow type annotations) |
| Runtime | Node.js (`engines.node >= 4.0.0`; supported set `^4.8.0 \|\| ^5.7.0 \|\| ^6.2.2 \|\| >=8.0.0`) |
| Entry point | `bin/yarn.js` → `src/cli/index.js` |
| Build system | Gulp (Babel transpile) + Webpack (single-file bundle) |
| Type checking | Flow |
| Tests | Jest |
| Default registry | `https://registry.yarnpkg.com` (a CDN proxy of the npm registry) |
| Lockfile version | `1` |
| Cache version | `6` |

**Design goals.** Yarn was built to solve three problems with early npm: **determinism** (a lockfile that pins the whole tree), **speed** (a global cache + parallel network and I/O), and **security** (integrity hashes on every package). Those three pillars are visible throughout the architecture: the resolver produces a fully pinned graph, the fetcher caches and hashes everything, and the lockfile records both.

> [!NOTE]
> "Classic" Yarn (the 1.x line documented here) is a mature, stable codebase in maintenance mode. The actively developed successor, Yarn 2+ ("Berry"), is a separate repository with a plugin architecture and Plug'n'Play by default. Yarn 1 already ships an *experimental* Plug'n'Play implementation (see [§7](#7-registries--resolution)).

---

## 2. System Architecture

Yarn is a single Node process that orchestrates several cooperating subsystems. There is no daemon, no server, and no database — state lives entirely in files (`package.json`, `yarn.lock`, the cache, and `.yarnrc`/`.npmrc`).

```text
                         bin/yarn.js  (thin launcher; honors yarn-path)
                                │
                                ▼
                    src/cli/index.js  (main)
        ┌───────────────────────┼────────────────────────┐
        │  parse global flags (commander.js)              │
        │  resolve command name (default = "install")     │
        │  build Reporter (Console | JSON)                │
        │  construct Config  ◄─────── .yarnrc / .npmrc / env / DEFAULTS
        │  acquire mutex (optional: file | network)       │
        └───────────────────────┬────────────────────────┘
                                │ command.run(config, reporter, flags, args)
                                ▼
                  src/cli/commands/<command>.js   (44 commands)
                                │
        ┌───────────────┬───────┴────────┬───────────────┬──────────────┐
        ▼               ▼                ▼               ▼              ▼
  PackageResolver  PackageFetcher  PackageLinker  PackageHoister  PackageInstallScripts
        │               │                │               │              │
        ▼               ▼                ▼               ▼              ▼
   Resolvers       Fetchers         node_modules     hoisted tree   lifecycle scripts
  (registry +     (tarball/git/         layout
   8 exotics)      copy + cache)
        │               │
        ▼               ▼
    Registries      Global cache + offline mirror
  (npm + yarn)
        │
        ▼
   RequestManager  (HTTP, retries, concurrency, HAR capture)
```

### Layering

| Layer | Responsibility | Key modules |
|-------|----------------|-------------|
| **CLI** | Argument parsing, command dispatch, output | `src/cli/index.js`, `src/cli/commands/*` |
| **Orchestration** | The install lifecycle and its steps | `src/cli/commands/install.js` (the `Install` class) |
| **Resolution** | Turn version ranges into pinned packages | `src/package-resolver.js`, `src/resolvers/*` |
| **Fetching** | Download + cache + verify packages | `src/package-fetcher.js`, `src/fetchers/*` |
| **Linking** | Lay out `node_modules`, hoist, link bins | `src/package-linker.js`, `src/package-hoister.js` |
| **Registry I/O** | Auth, config, registry protocol | `src/registries/*`, `src/util/request-manager.js` |
| **Persistence** | Lockfile + integrity | `src/lockfile/*`, `src/integrity-checker.js` |
| **Reporting** | Console/JSON output, progress, prompts | `src/reporters/*` |
| **Config** | Merge `.yarnrc`/`.npmrc`/env/defaults | `src/config.js`, `src/rc.js` |

### The launcher and `yarn-path`

`src/cli/index.js`'s `start()` function checks for a `yarn-path` (or `yarnPath`) setting in the resolved `.yarnrc`. If present — and the `YARN_IGNORE_PATH` environment variable is not set — Yarn **spawns the Yarn bundle at that path** instead of running itself. This is the mechanism behind `yarn policies set-version` / `yarn set version`: a project can commit an exact Yarn release into `.yarn/releases/` and pin every developer to it regardless of their globally installed Yarn.

```text
process start
   │
   ├─ read .yarnrc for yarn-path
   │     └─ if set and !YARN_IGNORE_PATH → spawn that bundle (.cjs via node, else direct) → exit
   │
   └─ otherwise → main({startArgs, args, endArgs})
```

---

## 3. The Install Pipeline

The `Install` class in `src/cli/commands/install.js` (≈1,150 lines) is the heart of Yarn. `yarn add`, `yarn remove`, `yarn upgrade`, `yarn import`, `yarn unplug`, `yarn check`, `yarn list`, and others all subclass or reuse it.

`Install.init()` assembles an ordered list of **steps**, each wrapped in a hook (`callThroughHook`) so plugins/`experimentalYarnHooks` can intercept them, then runs them in sequence with progress reporting:

```text
Install.init()
  ├─ checkUpdate()                 once-a-day self-update nag
  ├─ fetchRequestFromCwd()         read manifests → dependency requests + patterns
  ├─ (optional) checkCompatibility  engines/os/cpu checks
  ├─ STEP resolveStep   → resolver.init(requests)        Resolving packages...
  │        └─ bailout() if integrity matches and lockfile is clean → done early
  ├─ STEP auditStep     → audit.performAudit() (if --audit)        Auditing...
  ├─ STEP fetchStep     → fetcher.fetch(manifests)                 Fetching packages...
  │        └─ compatibility.check() across the whole graph
  ├─ STEP linkStep      → linker.init(patterns)                    Linking dependencies...
  ├─ STEP pnpStep       → generatePnpMap() (if PnP enabled)        write .pnp.js
  ├─ STEP buildStep     → scripts.init() (unless --ignore-scripts) Building fresh packages...
  ├─ (optional) HAR save / autoclean
  ├─ saveLockfileAndIntegrity()    write yarn.lock + .yarn-integrity
  └─ persistChanges()              write back package.json (for add/remove/upgrade)
```

### The bailout optimization

Before doing any network work, `Install.bailout()` consults the **integrity checker** (`src/integrity-checker.js`). It compares the requested patterns, the lockfile cache, the flags, and the workspace layout against the stored `.yarn-integrity` file. If everything matches and a lockfile exists, Yarn prints `success Already up-to-date.` and exits immediately. This is why a no-op `yarn install` is nearly instantaneous.

Bailout is **disabled** when `--audit`, `--force`, `--skip-integrity-check`, or Plug'n'Play is in effect (PnP installs are fast enough that the check is not worthwhile). `--frozen-lockfile` additionally turns a needed-update into a hard error here.

### Lifecycle script ordering

`wrapLifecycle()` (exported from `install.js`) frames the install with npm-compatible lifecycle scripts:

```text
preinstall → [install work] → install → postinstall → (if !production) prepublish → prepare
```

`yarn run` adds `pre<script>`/`post<script>` wrapping for arbitrary scripts; `yarn publish` runs `prepublish`, `prepare`, `prepublishOnly`, `prepack`, then `publish`, `postpublish`; `yarn pack` runs `prepack`/`postpack`; `yarn remove` runs `preuninstall`/`uninstall`/`postuninstall`.

---

## 4. Repository Structure

The repository is large by file count (~5,200 files) but the *source* is concentrated — most files are test fixtures and a cached HTTP request fixture set under `__tests__/fixtures/request-cache/`. The triage that matters:

```text
yarn/
├── bin/                        Launcher scripts (yarn.js)
├── src/                        ◄── ALL production source
│   ├── cli/
│   │   ├── index.js            main(): flag parsing, dispatch, mutex, error handling
│   │   ├── aliases.js          command-name aliases (upgrade-interactive, etc.)
│   │   └── commands/           44 command modules (see §5)
│   ├── registries/             npm + yarn registry clients
│   ├── resolvers/              registry resolvers + 8 exotic resolvers
│   ├── fetchers/               tarball / git / copy fetchers
│   ├── lockfile/               lockfile parse / stringify
│   ├── reporters/              console / json / buffer / event reporters
│   │   └── lang/               localized message strings (en.js, ...)
│   ├── util/                   ~40 utility modules (fs, git, crypto, ...)
│   │   └── normalize-manifest/ package.json normalization + validation
│   ├── config.js               central configuration object
│   ├── constants.js            URLs, filenames, versions, concurrency
│   ├── errors.js               error class hierarchy
│   ├── package-resolver.js     drives resolution of the whole graph
│   ├── package-fetcher.js      drives fetching of all manifests
│   ├── package-linker.js       lays out node_modules + bin links
│   ├── package-hoister.js      hoisting / deduplication algorithm
│   ├── package-request.js      a single dependency request
│   ├── package-reference.js    a resolved package reference
│   ├── package-install-scripts.js  runs install/build scripts in parallel
│   ├── package-compatibility.js    engines/os/cpu checks
│   ├── integrity-checker.js    decides whether reinstall is needed
│   ├── workspace-layout.js     workspace graph model
│   ├── resolution-map.js       selective "resolutions" field support
│   └── hoisted-tree-builder.js builds the tree audit/why/list consume
├── packages/
│   ├── lockfile/               @yarnpkg/lockfile (standalone parser package)
│   └── pkg-tests/              end-to-end behavioral test harness
├── __tests__/                  Jest unit tests + fixtures
├── scripts/                    build/release scripts (dist, deb, rpm, chocolatey, win)
├── resources/                  installer resources (debian, winsetup, chocolatey)
└── package.json                manifest (deps, scripts, jest config)
```

---

## 5. Module Reference

### CLI commands (`src/cli/commands/`, 44 modules)

Each command module exports `run`, `setFlags`, and `hasWrapper`, and is registered in `src/cli/commands/index.js`. The dispatcher in `index.js` defaults to `install` when no command is given, and to `run` (script execution) when an unrecognized name is given.

**Install family** (subclass or reuse the `Install` class):

| Module | Command | Notes |
|--------|---------|-------|
| `install.js` | `install` | The base `Install` class + the install pipeline. |
| `add.js` | `add` | `Add extends Install`; appends args as new requests, computes save ranges. |
| `remove.js` | `remove` | Deletes from manifest + reinstalls to regenerate the lockfile. |
| `upgrade.js` | `upgrade` | Computes outdated set, unlocks them in the lockfile, delegates to `Add`. |
| `upgrade-interactive.js` | `upgrade-interactive` | Inquirer checkbox UI over the outdated set. |
| `import.js` | `import` | `Import extends Install`; builds a graph from `package-lock.json`/`node_modules`. |
| `unplug.js` | `unplug` | Marks packages for unplugging during a PnP install. |
| `check.js` | `check` | Verifies tree vs. lockfile (`--integrity`, `--verify-tree`). |
| `list.js` | `list` | Builds and prints the hoisted tree. |
| `outdated.js` | `outdated` | Diffs current vs. wanted vs. latest. |
| `licenses.js` | `licenses` | `list` + `generate-disclaimer` subcommands. |
| `audit.js` | `audit` | Posts a gzip'd dependency tree to the registry audit endpoint. |
| `why.js` | `why` | Traces dependency reasons and disk sizes. |

**Project & scripts:**

| Module | Command | Notes |
|--------|---------|-------|
| `init.js` | `init` | Interactive manifest creation; `-2`/`--install` delegate to `policies set-version`. |
| `run.js` | `run` | Runs `package.json` scripts and `.bin` binaries; suggests on typos via `leven`. |
| `exec.js` | `exec` | Runs an arbitrary command in Yarn's env. |
| `node.js` | `node` | Runs Node with Yarn's version + PnP require. |
| `bin.js` | `bin` | Prints `.bin` folder or a binary path. |
| `create.js` | `create` | Global-installs and runs a `create-*` package. |

**Registry / publishing:**

| Module | Command | Notes |
|--------|---------|-------|
| `publish.js` | `publish` | Bump → login → pack → PUT to registry → revoke token. |
| `pack.js` | `pack` | Builds the publishable tarball (honors `files`, `.npmignore`, `bundledDependencies`). |
| `version.js` | `version` | Bumps version, runs `preversion`/`version`/`postversion`, git-tags. |
| `versions.js` | `versions` | Reports yarn/node/component versions. |
| `login.js` / `logout.js` | `login`/`logout` | Store/clear registry credentials; token acquisition (`getToken`). |
| `owner.js` | `owner` | Add/remove/list package maintainers. |
| `tag.js` | `tag` | Manage dist-tags. |
| `team.js` | `team` | Manage org teams. |
| `info.js` | `info` | Registry metadata for a package. |
| `access.js` | `access` | Reserved — `notYetImplemented`. |
| `generate-lock-entry.js` | `generate-lock-entry` | Print a lockfile entry for the current package. |

**Global / linking / workspaces / config:**

| Module | Command | Notes |
|--------|---------|-------|
| `global.js` | `global` | `add`/`remove`/`list`/`upgrade`/`bin`/`dir`; manages a side install + bin links. |
| `link.js` / `unlink.js` | `link`/`unlink` | Create/remove dev symlinks in the global link registry. |
| `workspace.js` | `workspace` | Run a command in one named workspace. |
| `workspaces.js` | `workspaces` | `info` + `run` across all workspaces. |
| `config.js` | `config` | `get`/`set`/`delete`/`list`/`current` against `.yarnrc`. |
| `policies.js` | `policies set-version` | Download + pin a Yarn release (incl. `berry`, `nightly`). |
| `cache.js` | `cache` | `list`/`dir`/`clean` on the global cache. |
| `autoclean.js` | `autoclean` | Strip docs/tests/examples from deps via `.yarnclean`. |
| `help.js` | `help` | Render help text. |

**Helper modules:** `_build-sub-commands.js` (factory for commands with subcommands like `cache`, `config`, `global`), `_useless.js` (factory for the deliberate no-op commands).

> [!NOTE]
> Three commands are intentional no-ops built via `_useless.js`: `dedupe`, `prune`, and `lockfile`. Each throws a message explaining that `yarn install` already performs the operation. This is documented behavior, not a bug.

### Core engine modules (`src/`)

| Module | Role |
|--------|------|
| `package-resolver.js` | Orchestrates resolution of the entire graph; deduplicates patterns; tracks `patterns`/`patternsByPackage`; integrates `ResolutionMap`. |
| `package-request.js` | Represents one dependency request; finds versions on the registry or via exotic resolvers; computes the outdated set (`getOutdatedPackages`). |
| `package-reference.js` | A resolved package instance with its requests, patterns, remote, permissions. |
| `package-fetcher.js` | Fetches all resolved manifests (parallel), populating the cache. |
| `package-linker.js` | Builds the flat hoisted tree, copies/symlinks packages, links bins, resolves peer dependencies. |
| `package-hoister.js` | The hoisting algorithm; `HoistManifest`, `NohoistResolver` for `nohoist` workspace rules. |
| `package-install-scripts.js` | Runs `install`/`postinstall` build scripts with bounded concurrency. |
| `package-compatibility.js` | Validates `engines`, `os`, `cpu` against the host. |
| `integrity-checker.js` | Computes/compares `.yarn-integrity`; the basis of the bailout optimization. |
| `resolution-map.js` | Implements the `resolutions` manifest field for forcing transitive versions. |
| `workspace-layout.js` | Models the workspace graph and the virtual aggregator manifest. |
| `config.js` | The central `Config` object: folders, registries, options, lifecycle script execution, manifest read/write. |
| `lockfile/` | Custom lockfile tokenizer/parser + stringifier (see §6). |

---

## 6. The Lockfile Format

`yarn.lock` (lockfile version `1`) is generated by `src/lockfile/stringify.js` and read by `src/lockfile/parse.js`. It is a custom, YAML-like, human-readable format — **not** JSON and **not** strictly YAML.

A representative entry:

```text
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


lodash@^4.17.0, lodash@^4.17.21:
  version "4.17.21"
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#hash"
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvKw==
```

Key properties of the format:

- **Multiple patterns share one entry.** `lodash@^4.17.0, lodash@^4.17.21:` means both ranges resolved to the same package; the body is written once.
- **Field ordering is stable.** `stringify.js` sorts fields by a fixed priority (`name`, `version`, `uid`, `resolved`, `integrity`, `registry`, `dependencies`) then alphabetically, so diffs stay minimal across runs.
- **Keys are quoted only when necessary** (`maybeWrap`/`shouldWrapKey`), keeping the file readable.
- **`npm` registry is the implicit default** — entries omit `registry` when it is `npm` (`implodeEntry`).
- **Integrity is normalized** with a stable sort of multi-hash strings (`serializeIntegrity`).

### The parser

`parse.js` implements a hand-written tokenizer (`tokenise`) and recursive-descent `Parser`. Notable behaviors:

- It enforces **two-space indentation** — odd indentation throws `Invalid number of spaces`.
- It rejects newer lockfiles: if a `# yarn lockfile v<N>` comment declares a version greater than `LOCKFILE_VERSION` (1), it errors and tells you to upgrade Yarn.
- If the custom parse fails on a non-`.yml` file, it **falls back to a YAML safe-load** (`js-yaml` `FAILSAFE_SCHEMA`).
- It detects and resolves **git merge conflicts** automatically: `hasMergeConflicts()` finds `<<<<<<<`/`=======`/`>>>>>>>` markers, `extractConflictVariants()` splits the two sides, and both are parsed and merged. A successful merge reports `info Merge conflict detected in yarn.lock and successfully merged.`; an unmergeable one returns a `conflict` result.

> [!TIP]
> Because Yarn auto-merges lockfile conflicts, the recommended resolution for a `yarn.lock` git conflict is simply to run `yarn install` — it will parse both variants, merge them, and rewrite a clean lockfile.

The standalone `@yarnpkg/lockfile` package (`packages/lockfile/`) exposes this `parse`/`stringify` pair for third-party tooling.

---

## 7. Registries & Resolution

### Dual-registry model

`src/registries/` defines two registry clients, both subclasses of `BaseRegistry`:

```text
BaseRegistry
  └─ NpmRegistry      (folder: node_modules; filename: package.json)
        └─ YarnRegistry  (filename: yarn.json; holds Yarn's own defaults + ~/.yarnrc)
```

- **`NpmRegistry`** speaks the npm registry protocol: it resolves the registry URL per package/scope, handles scoped-package name escaping (`@scope%2fpkg`), enforces HTTPS for `yarnpkg.com`/`npmjs.org`, reads `.npmrc` from the standard cascade (cwd → home → global prefix `etc`), and assembles auth headers (`_authToken` → Bearer, `_auth` → Basic, username/`_password` → Basic). It also handles 2FA: on a `OneTimePasswordError` it prompts for a one-time password and retries.
- **`YarnRegistry`** layers Yarn-specific defaults on top. Its `DEFAULTS` object is the authoritative source of Yarn's built-in configuration values (see [§8](#8-configuration-mastery)). Its `getOption()` resolves a key by checking the Yarn config, then an npm-name mapping (`npmMap`), then the npm config, then `DEFAULTS`. It persists global settings to `~/.yarnrc` via `saveHomeConfig()`.

### Resolvers

`src/resolvers/index.js` registers two registry resolvers (`npm`, `yarn`) and **eight exotic resolvers** for non-registry sources. `getExoticResolver(pattern)` tests each in turn:

| Exotic resolver | Pattern example |
|-----------------|-----------------|
| `git-resolver` | `git+https://…`, `git+ssh://…` |
| `tarball-resolver` | `https://example.com/pkg.tgz` |
| `github-resolver` | `user/repo`, `github:user/repo` |
| `gitlab-resolver` | `gitlab:user/repo` |
| `bitbucket-resolver` | `bitbucket:user/repo` |
| `gist-resolver` | `gist:hash` |
| `file-resolver` | `file:../path` |
| `link-resolver` | `link:../path` |

Each registry resolver is also exposed as an exotic via a generated `ExoticRegistryResolver` subclass, enabling `npm:foo@1.0.0` / `yarn:foo@1.0.0` protocol patterns.

### Fetchers

`src/fetchers/` mirrors the resolver families. `BaseFetcher.fetch()` creates the destination, calls the subclass `_fetch()`, normalizes the resulting manifest, and links any declared `bin` entries (via `cmd-shim` on Windows, symlinks elsewhere). Subclasses include a tarball fetcher (with a `LocalTarballFetcher`), a git fetcher, and a copy fetcher for `file:` dependencies. Fetched tarballs may be copied into the **offline mirror** for air-gapped reinstalls.

### Plug'n'Play (experimental)

When `--enable-pnp`/`--pnp` is set (or `installConfig.pnp` in `package.json`), the install pipeline adds a `pnpStep` that writes a `.pnp.js` file mapping every dependency to its location in the cache, bypassing `node_modules` entirely. `yarn node` and `yarn run` auto-`--require` this file. `yarn unplug` materializes a package out of the cache into `.yarn/unplugged/` for debugging; it errors if PnP is disabled.

---

## 8. Configuration Mastery

### Configuration sources & precedence

Yarn merges configuration from multiple sources. Highest precedence wins:

```text
command-line flags
  ▼
environment variables (YARN_*, NPM_CONFIG_*, npm_config_*)
  ▼
project .yarnrc / .npmrc   (searched cwd → upward)
  ▼
home  ~/.yarnrc / ~/.npmrc
  ▼
global prefix  etc/yarnrc / etc/npmrc
  ▼
YarnRegistry.DEFAULTS  (built-in defaults)
```

`.yarnrc` is parsed with the lockfile parser; `.npmrc` is parsed as INI (`ini`). Disable auto-detection with `--no-default-rc`; supply an explicit file with `--use-yarnrc <path>`.

### Built-in defaults (`YarnRegistry.DEFAULTS`)

These are the authoritative Yarn defaults from `src/registries/yarn-registry.js`:

| Key | Default | Meaning |
|-----|---------|---------|
| `registry` | `https://registry.yarnpkg.com` | Package registry. |
| `save-prefix` | `^` | Range prefix for `yarn add`. |
| `bin-links` | `true` | Create `.bin` symlinks. |
| `ignore-scripts` | `false` | Skip lifecycle scripts. |
| `ignore-optional` | `false` | Skip optional dependencies. |
| `strict-ssl` | `true` | Enforce valid TLS certs. |
| `init-version` | `1.0.0` | Default version for `yarn init`. |
| `init-license` | `MIT` | Default license for `yarn init`. |
| `version-tag-prefix` | `v` | Git tag prefix for `yarn version`. |
| `version-git-tag` | `true` | Create a git tag on `yarn version`. |
| `version-git-sign` | `false` | GPG-sign the version tag. |
| `version-commit-hooks` | `true` | Run git commit hooks. |
| `version-git-message` | `v%s` | Version commit message template. |
| `user-agent` | `yarn/<v> npm/? node/<v> <platform> <arch>` | HTTP User-Agent. |

### npm-key compatibility mapping

`YarnRegistry` maps several Yarn config names to their npm equivalents (`npmMap`), so npm config files keep working:

| Yarn key | npm key |
|----------|---------|
| `version-git-sign` | `sign-git-tag` |
| `version-tag-prefix` | `tag-version-prefix` |
| `version-git-tag` | `git-tag-version` |
| `version-commit-hooks` | `commit-hooks` |
| `version-git-message` | `message` |

### Path-relative keys

These keys are resolved relative to the `.yarnrc` that defines them, and folder keys are auto-created: `yarn-offline-mirror`, `cache-folder`, `global-folder`, `offline-cache-folder`, `yarn-path`.

### Other notable settings

| Setting | Effect |
|---------|--------|
| `yarn-path` | Spawn a pinned Yarn bundle instead of the global one. |
| `yarn-offline-mirror` | Directory to mirror downloaded tarballs into. |
| `yarn-offline-mirror-pruning` | Prune unused tarballs from the mirror on install. |
| `disable-self-update-check` | Suppress the once-a-day outdated-Yarn nag. |
| `script-shell` | Shell used to run scripts. |
| `scripts-prepend-node-path` | Prepend Node's dir to `PATH` in scripts. |
| `lastUpdateCheck` | Timestamp Yarn writes to throttle update checks. |

> [!IMPORTANT]
> Yarn reads **both** Yarn-prefixed (`YARN_*`) and npm-prefixed (`NPM_CONFIG_*`, `npm_config_*`) environment variables. Environment variables are converted to config keys by lowercasing, stripping the prefix, turning `__` into `.` and `_` into `-`. This is how CI systems inject registry tokens (`npm_config_//registry.example.com/:_authToken`).

---

## 9. Environment Variables

Yarn reads these process environment variables directly (from `src/constants.js`, `src/config.js`, registry, and command modules):

| Variable | Used for |
|----------|----------|
| `YARN_SILENT` | Force silent mode (equivalent to `--silent`). |
| `YARN_IGNORE_PATH` | Ignore the `yarn-path` setting (prevents launcher recursion). |
| `YARN_WRAP_OUTPUT` | Toggle the header/footer output wrapper. |
| `YARN_AUTH_TOKEN` / `NPM_AUTH_TOKEN` | Bearer token for registry auth (`yarn login`/`getToken`). |
| `NPM_CONFIG_*` / `npm_config_*` | npm-style config injection (registry, auth, etc.). |
| `NODE_ENV` / `NPM_CONFIG_PRODUCTION` / `YARN_PRODUCTION` | Toggle production (skip devDependencies). |
| `CHILD_CONCURRENCY` | Override max concurrent child processes (default 5). |
| `NODE_OPTIONS` | Passed through to `yarn node`. |
| `PREFIX` / `DESTDIR` / `LOCALAPPDATA` | Global install prefix resolution. |
| `GITHUB_TOKEN` | Authenticated GitHub API calls in `policies set-version`. |
| `HOME` / `USERPROFILE` / `XDG_*` | Home, cache, config, and data directory resolution. |
| `TERM_PROGRAM` | Emoji auto-enable detection. |
| `PATH` / `Path` | Binary lookup (platform-aware key via `getPathKey`). |

---

## 10. Caching, Mirrors & Storage

Yarn keeps three distinct on-disk stores. Their locations are platform-dependent and derived in `src/constants.js` + `src/util/user-dirs.js` (XDG on Linux, AppData on Windows, etc.).

| Store | Constant / setting | Purpose |
|-------|--------------------|---------|
| **Global cache** | `PREFERRED_MODULE_CACHE_DIRECTORIES` (XDG cache dir, then `os.tmpdir()/.yarn-cache-<uid>`) | Every downloaded + extracted package, keyed by integrity. Cache format version `6`. |
| **Link registry** | `LINK_REGISTRY_DIRECTORY` (`<dataDir>/link`) | Symlinks created by `yarn link`. |
| **Global modules** | `GLOBAL_MODULE_DIRECTORY` (`<dataDir>/global`) | Packages installed via `yarn global add`. |
| **Offline mirror** | `yarn-offline-mirror` (opt-in) | Raw `.tgz` tarballs kept next to the project for offline installs. |

Inspect and manage the cache:

```bash
yarn cache dir                # print cache location
yarn cache list               # list cached packages
yarn cache list --pattern lo* # filter by name
yarn cache clean              # wipe the whole cache
yarn cache clean lodash       # remove one package
```

> [!TIP]
> On CI, persist the **global cache** (`yarn cache dir`) across builds rather than `node_modules`. Combined with `--frozen-lockfile`, this gives fast, fully reproducible installs. For air-gapped builds, commit a `yarn-offline-mirror` and install with `--offline`.

Yarn-managed sentinel files inside a project:

| File | Purpose |
|------|---------|
| `yarn.lock` | The lockfile. |
| `.yarn-integrity` | Integrity snapshot powering the bailout optimization. |
| `.yarnclean` | Filter list for `yarn autoclean`. |
| `.pnp.js` | Plug'n'Play resolution map (when PnP enabled). |
| `.yarn-single-instance` | Mutex lock file (`--mutex file`). |
| `yarn-error.log` | Crash report written on unexpected errors. |

---

## 11. Security Analysis

### Integrity verification

Every fetched package is verified against a cryptographic integrity hash (Subresource-Integrity style, `sha512` preferred with `sha1` fallback via the `ssri` library). The hash is recorded in `yarn.lock` (`integrity` field) and in `.yarn-integrity`. A package whose downloaded bytes do not match its recorded hash is rejected. This protects against tampered mirrors and corrupted downloads.

### Transport security

`NpmRegistry` enforces HTTPS for the official registries: any `http://` URL matching `yarnpkg.com`, `npmjs.org`, or `npmjs.com` is rewritten to `https://` (`REGEX_REGISTRY_ENFORCED_HTTPS`). TLS certificate validation is on by default (`strict-ssl: true`). Proxies are supported via `--proxy`/`--https-proxy`.

### Authentication

Credentials are never hard-coded. Auth is resolved per-registry from config in priority order: `_authToken` (Bearer) → `_auth` (Basic) → `username` + `_password` (Basic). Tokens can also come from `YARN_AUTH_TOKEN`/`NPM_AUTH_TOKEN` env vars. Two-factor auth is supported interactively or via `--otp`. `yarn login` stores only username/email in `~/.yarnrc`; the password is requested per publish and used to mint a token that is **revoked** at the end of the operation (see `publish`/`owner`/`tag`/`team` flows).

### Lifecycle script execution (the main risk surface)

Like all package managers, Yarn's largest attack surface is **install scripts** (`preinstall`/`install`/`postinstall`) — arbitrary code that runs during install. Mitigations available to operators:

- `--ignore-scripts` (or `ignore-scripts: true` in config) disables all lifecycle scripts.
- `yarn audit` (and `--audit` during install) flags known-vulnerable packages against the registry advisory database.
- The integrity system ensures the *bytes* of a package match what was locked, so a malicious change to an already-locked package is detected.

> [!CAUTION]
> Running `yarn install` executes install scripts from every dependency in the tree by default. In untrusted or high-security environments, install with `--ignore-scripts` and audit scripts before enabling them. Pair this with a committed `yarn.lock` so the exact, reviewed package set is what gets installed.

### Error classes with security meaning

`src/errors.js` defines `SecurityError` (a `MessageError` subclass) and `OneTimePasswordError`, used to surface integrity/auth failures distinctly from ordinary errors.

> [!NOTE]
> Yarn 1 depends on the now-deprecated `request` HTTP library and uses the legacy `url.parse` API (the source of the Node 24 deprecation warning, community issue [#9210](https://github.com/yarnpkg/yarn/issues/9210)). These are maintenance/compatibility concerns rather than active vulnerabilities, but they are reasons the project recommends migrating to Yarn 2+ for new work.

---

## 12. Operations & CI

### Recommended CI install

```bash
yarn install --frozen-lockfile --non-interactive
```

- `--frozen-lockfile` fails the build if `yarn.lock` is out of date — catching un-committed dependency changes.
- `--non-interactive` prevents Yarn from ever blocking on a prompt (it would otherwise error `Can't answer a question unless a user TTY`).

### Deployment

```bash
yarn install --frozen-lockfile --production
```

Installs only runtime `dependencies`. Combine with `NODE_ENV=production` for the same effect via environment.

### Concurrency tuning

| Knob | Default | How to change |
|------|---------|---------------|
| Network concurrency | 8 | `--network-concurrency <n>` |
| Network timeout | 30000 ms | `--network-timeout <ms>` |
| Child-process concurrency | 5 | `CHILD_CONCURRENCY` env var |

### Single-instance enforcement

```bash
yarn install --mutex file              # lock via .yarn-single-instance
yarn install --mutex network:31997     # lock via a localhost port
```

Useful when multiple jobs might run Yarn in the same workspace concurrently. The default single-instance port is `31997`.

### Diagnostics

| Action | Command |
|--------|---------|
| Verbose internals | `yarn <cmd> --verbose` |
| Machine-readable logs | `yarn <cmd> --json` |
| Network capture | `yarn install --har` → `yarn-install_<ts>.har` |
| Verify install integrity | `yarn check` / `yarn check --integrity` |
| Crash report | auto-written to `yarn-error.log` (includes args, env PATH, versions, manifests, lockfile) |

> [!TIP]
> When filing a bug, attach the auto-generated `yarn-error.log`. It captures the command arguments, Yarn/Node versions, platform, full stack trace, and the relevant manifests and lockfile — everything a maintainer needs to reproduce.

### Pinning Yarn for the whole team

```bash
yarn policies set-version 1.22.19   # or: latest, rc, nightly, berry
```

This writes `.yarn/releases/yarn-<v>.cjs` and sets `yarn-path` in `.yarnrc`. Commit both. Every subsequent `yarn` invocation in the repo runs that exact bundle, regardless of each developer's globally installed version.

---

## 13. Building Yarn From Source

Yarn is written in Flow-typed JavaScript and transpiled with Babel via Gulp; release artifacts are bundled with Webpack.

Key `package.json` scripts:

| Script | Command | Purpose |
|--------|---------|---------|
| `build` | `gulp build` | Transpile `src/` → `lib/`. |
| `build-bundle` | `node ./scripts/build-webpack.js` | Single-file Webpack bundle. |
| `build-dist` | `bash ./scripts/build-dist.sh` | Full distributable build. |
| `build-deb` | `./scripts/build-deb.sh` | Debian package. |
| `build-chocolatey` | `powershell ./scripts/build-chocolatey.ps1` | Windows Chocolatey package. |
| `build-win-installer` | `scripts\build-windows-installer.bat` | Windows MSI. |
| `watch` | `gulp watch` | Rebuild on change. |
| `lint` | `eslint . && flow check` | Lint + type-check. |
| `test` | `yarn lint && yarn test-only` | Full test suite. |
| `test-only` | `node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose` | Jest only. |

Testing:

- **Unit tests** live in `__tests__/`, run by Jest, and use a committed HTTP request cache (`__tests__/fixtures/request-cache/`) so tests run offline and deterministically.
- **End-to-end tests** live in `packages/pkg-tests/` and exercise real install behavior against fixture packages.

CI matrices (AppVeyor / Azure Pipelines) test across Node 8/10/12/13 on Windows, Linux, and macOS.

> [!NOTE]
> Yarn is self-hosting: its own CI uses Yarn to install Yarn's dependencies (`yarn install --frozen-lockfile`), and the development bootstrap script adds the Yarn apt repository to install Yarn before building it.

---

## 14. Error Model & Exit Codes

### Error class hierarchy (`src/errors.js`)

```text
Error
 ├─ MessageError(msg, code)          user-facing message; printed without a stack trace
 │   ├─ ProcessSpawnError(.process)  failed to spawn a child process
 │   ├─ SecurityError                integrity / security failures
 │   └─ ProcessTermError(.EXIT_CODE) a child process terminated; carries its exit code
 ├─ ResponseError(.responseCode)     HTTP-level error
 └─ OneTimePasswordError             2FA OTP required/incorrect
```

`MessageError`s are printed as clean one-line errors. Any other (unexpected) error triggers `onUnexpectedError()`, which writes a detailed `yarn-error.log` and prints a "report this" message. A `ProcessTermError` propagates the child's own exit code.

### Audit exit codes

`yarn audit` returns a bitmask summing the severities present, so CI can gate on it:

| Severity | Bit value |
|----------|-----------|
| info | 1 |
| low | 2 |
| moderate | 4 |
| high | 8 |
| critical | 16 |

A clean audit exits `0`; an audit finding a high + a low vulnerability exits `10` (8 + 2).

---

## 15. Code Quality & Conventions

| Aspect | Convention |
|--------|------------|
| **Types** | Flow (`/* @flow */` header required by lint rule `flowtype/require-valid-file-annotation`). |
| **Formatting** | Prettier — single quotes, trailing commas, no bracket spacing, 120-col print width. |
| **Linting** | ESLint extending `eslint-config-fb-strict`, plus a custom `eslint-plugin-yarn-internal` (e.g. `warn-language` to keep user-facing strings centralized). |
| **`require-await`, `no-process-exit`, `no-return-await`** | Enforced as errors. |
| **i18n** | All user-facing text flows through `reporter.lang(key, ...args)`, resolved from `src/reporters/lang/*`. New strings must be added there, not inlined. |
| **Command shape** | Every command exports `run`, `setFlags`, `hasWrapper`; optional `examples`, `requireLockfile`, `noArguments`, `shouldRunInCurrentCwd`. |
| **Subcommands** | Built with the `_build-sub-commands.js` factory for a consistent `yarn <cmd> <subcmd>` UX. |

Architecture patterns worth noting:

- **Class inheritance for command variants.** `Add`, `GlobalAdd`, `Import` extend `Install`, overriding hooks (`prepareRequests`, `bailout`, `applyChanges`) rather than duplicating the pipeline.
- **Step-and-hook pipeline.** The install flow is a list of hookable async steps, enabling `experimentalYarnHooks` interception (`resolveStep`, `fetchStep`, `linkStep`, `buildStep`, `pnpStep`, `auditStep`, `runScript`).
- **Reporter abstraction.** All output goes through a `Reporter` interface (`ConsoleReporter`, `JSONReporter`, `BufferReporter`, `EventReporter`, `NoopReporter`), so `--json` and silent modes work uniformly and commands can be driven programmatically.

---

## 16. Potential Improvements

Observations drawn from the source (Yarn 1 is in maintenance mode, so these are largely addressed in Yarn 2+):

- **Deprecated HTTP stack.** Yarn 1 depends on the unmaintained `request` library and legacy `url.parse`, producing deprecation warnings on modern Node (community issue [#9210](https://github.com/yarnpkg/yarn/issues/9210)). A migration to `fetch`/`undici` would remove these.
- **Audit endpoint coupling.** `yarn audit` assumes the registry implements the npm audit API; custom registries return 410 and break it (community issue [#9234](https://github.com/yarnpkg/yarn/issues/9234)). A graceful "audit unsupported" path would improve robustness. Note the source already disables the (npm-incompatible) automatic-fix action reporting.
- **PnP is experimental in 1.x.** The Plug'n'Play implementation works but is not the default; Yarn 2+ promotes it to a first-class strategy.
- **`node_modules` copying cost.** The default linker copies packages into `node_modules`; `--link-duplicates` hard-links duplicates, but the broader inefficiency is what PnP and Yarn 2+ address.
- **Self-update nag.** The once-a-day "Yarn is outdated" check writes `lastUpdateCheck` to home config; centrally managed installs should set `disable-self-update-check`.

---

## 17. Quick Reference

### Key paths & files

| Path | Role |
|------|------|
| `bin/yarn.js` | Launcher. |
| `src/cli/index.js` | `main()` — parse, dispatch, run. |
| `src/cli/commands/` | 44 command modules. |
| `src/config.js` / `src/constants.js` | Central config / canonical constants. |
| `src/registries/yarn-registry.js` | Built-in config defaults. |
| `src/lockfile/` | Lockfile parse/stringify. |
| `yarn.lock` | The lockfile (v1). |
| `.yarn-integrity` | Bailout integrity snapshot. |
| `yarn-error.log` | Crash report. |

### Canonical constants (`src/constants.js`)

| Constant | Value |
|----------|-------|
| `YARN_REGISTRY` | `https://registry.yarnpkg.com` |
| `SUPPORTED_NODE_VERSIONS` | `^4.8.0 \|\| ^5.7.0 \|\| ^6.2.2 \|\| >=8.0.0` |
| `LOCKFILE_VERSION` | `1` |
| `CACHE_VERSION` | `6` |
| `NETWORK_CONCURRENCY` | `8` |
| `NETWORK_TIMEOUT` | `30000` ms |
| `CHILD_CONCURRENCY` | `5` |
| `SINGLE_INSTANCE_PORT` | `31997` |
| `LOCKFILE_FILENAME` | `yarn.lock` |
| `INTEGRITY_FILENAME` | `.yarn-integrity` |
| `CLEAN_FILENAME` | `.yarnclean` |
| `PNP_FILENAME` | `.pnp.js` |

### CI one-liners

```bash
# Reproducible install
yarn install --frozen-lockfile --non-interactive

# Production deploy
yarn install --frozen-lockfile --production

# Security gate (fails on high+ severity)
yarn audit --level high

# Offline / air-gapped
yarn install --offline
```

### Install-pipeline cheat sheet

```text
resolve → fetch → link → (pnp) → build → write lockfile + integrity → persist manifest
   │         │       │              │
 bailout   cache   hoist        scripts
```

---

_Generated June 2026 from yarnpkg/yarn at c2dda50. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
