Commit Graph
2222 Commits
Author SHA1 Message Date
Renovate Bot aa975da532 chore(deps): update dependencies (#626)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | Type | Update | Pending |
|---|---|---|---|---|---|---|
| [@astrojs/check](https://github.com/withastro/astro/tree/main/packages/language-tools/astro-check) ([source](https://github.com/withastro/astro/tree/HEAD/packages/language-tools/astro-check)) | [`0.9.11` → `0.9.12`](https://renovatebot.com/diffs/npm/@astrojs%2fcheck/0.9.11/0.9.12) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@astrojs%2fcheck/0.9.12?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@astrojs%2fcheck/0.9.11/0.9.12?slim=true) | devDependencies | patch |  |
| [@astrojs/starlight](https://starlight.astro.build) ([source](https://github.com/withastro/starlight/tree/HEAD/packages/starlight)) | [`0.42.6` → `0.42.7`](https://renovatebot.com/diffs/npm/@astrojs%2fstarlight/0.42.6/0.42.7) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@astrojs%2fstarlight/0.42.7?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@astrojs%2fstarlight/0.42.6/0.42.7?slim=true) | dependencies | patch | `0.42.8` |
| [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`7.4.1` → `7.4.2`](https://renovatebot.com/diffs/npm/astro/7.4.1/7.4.2) | ![age](https://developer.mend.io/api/mc/badges/age/npm/astro/7.4.2?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/astro/7.4.1/7.4.2?slim=true) | dependencies | patch | `7.4.4` (+1) |
| [node](https://github.com/actions/node-versions) | `24` → `26` | ![age](https://developer.mend.io/api/mc/badges/age/github-releases/actions%2fnode-versions/26.12.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/github-releases/actions%2fnode-versions/24.22.2/26.12.1?slim=true) | uses-with | major | `26.13.0` |
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm/npm/pnpm)) | [`12.15.0` → `12.16.1`](https://renovatebot.com/diffs/npm/pnpm/12.15.0/12.16.1) | ![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/12.16.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/12.15.0/12.16.1?slim=true) | packageManager | minor |  |

---

### Release Notes

<details>
<summary>withastro/astro (@&#8203;astrojs/check)</summary>

### [`v0.9.12`](https://github.com/withastro/astro/blob/HEAD/packages/language-tools/astro-check/CHANGELOG.md#0912)

[Compare Source](https://github.com/withastro/astro/compare/@astrojs/[email protected]...@astrojs/[email protected])

##### Patch Changes

- [#&#8203;18455](https://github.com/withastro/astro/pull/18455) [`7af66fc`](https://github.com/withastro/astro/commit/7af66fc785d85b1df1f98e7123a52b2306250985) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes the `astro-check` binary ignoring its first two command-line arguments, so flags such as `--help`, `--root`, `--watch`, and `--tsconfig` are respected again. If your scripts padded the arguments to work around this (for example, `astro-check -- -- --tsconfig ./tsconfig.app.json`), remove the padding.
- Updated dependencies \[[`044148d`](https://github.com/withastro/astro/commit/044148d5cfbc90e0277b3205a52ec73bc452bb7e)]:
  - [@&#8203;astrojs/language-server](https://github.com/astrojs/language-server)@2.17.3

</details>

<details>
<summary>withastro/starlight (@&#8203;astrojs/starlight)</summary>

### [`v0.42.7`](https://github.com/withastro/starlight/blob/HEAD/packages/starlight/CHANGELOG.md#0427)

[Compare Source](https://github.com/withastro/starlight/compare/@astrojs/[email protected]...@astrojs/[email protected])

##### Patch Changes

- [#&#8203;4264](https://github.com/withastro/starlight/pull/4264) [`94e0985`](https://github.com/withastro/starlight/commit/94e0985ddbbbd5c0f50a4cea94dc2c92de0a607c) Thanks [@&#8203;chrispezza](https://github.com/chrispezza)! - Fixes a layout shift where the table of contents could be painted at the start of the content area and then jump to the end when a page's HTML arrived in several chunks

- [#&#8203;4285](https://github.com/withastro/starlight/pull/4285) [`6f22edd`](https://github.com/withastro/starlight/commit/6f22eddf21c90aed7bd4e3c82e48615a56268a69) Thanks [@&#8203;tunetheweb](https://github.com/tunetheweb)! - Improves hero image loading by adding `fetchpriority="high"` hint for browsers

</details>

<details>
<summary>withastro/astro (astro)</summary>

### [`v7.4.2`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#742)

[Compare Source](https://github.com/withastro/astro/compare/[email protected]@7.4.2)

##### Patch Changes

- [#&#8203;18430](https://github.com/withastro/astro/pull/18430) [`dda9ec3`](https://github.com/withastro/astro/commit/dda9ec395c89a1420abb3b8f88b5c7f1f385f82e) Thanks [@&#8203;Abhirup-99](https://github.com/Abhirup-99)! - Speeds up content sync with `experimental.collectionStorage: "chunked"` by computing each character's UTF-8 width from its code point instead of encoding every character through `TextEncoder`. On a store of \~44k entries this cuts the chunking step from about 60 seconds to well under a second, with byte-identical output.

- [#&#8203;18438](https://github.com/withastro/astro/pull/18438) [`5e0eaa4`](https://github.com/withastro/astro/commit/5e0eaa4415a9081efdaeb3d9af3717ce3226ad18) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `astro dev` with `@astrojs/cloudflare` failing with ``Calling `require` for "node-fetch"`` when a server dependency such as `cross-fetch` requires `node-fetch`

- [#&#8203;18376](https://github.com/withastro/astro/pull/18376) [`a4e201d`](https://github.com/withastro/astro/commit/a4e201d79f19caa6bf4222f42167aeb602c066e6) Thanks [@&#8203;okxint](https://github.com/okxint)! - Fixes `astro dev` treating a stale lock file containing a Linux thread ID as a running Astro server. A successful process lookup with no matching PID now marks the lock as stale, preventing `astro dev stop` and `astro dev --force` from killing the unrelated process that owns the thread.

- [#&#8203;18467](https://github.com/withastro/astro/pull/18467) [`d1fb7d3`](https://github.com/withastro/astro/commit/d1fb7d36dad440c57d62b071e752ae220cca2baa) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes the `defineConfig()` types for `i18n.defaultLocale`, `i18n.fallback`, and `i18n.domains` so they accept a custom locale's `path` instead of its `codes`, matching how Astro validates and uses these values

- [#&#8203;18475](https://github.com/withastro/astro/pull/18475) [`cf27e70`](https://github.com/withastro/astro/commit/cf27e70a9057ce29ade2a8a843bd9275a696e9ab) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Bumps the minimum supported Node.js version to 22.23.4, which includes the fixes from the [October 2026 Node.js security releases](https://nodejs.org/en/blog/vulnerability/october-2026-security-releases)

  This is a patch release because the [Node.js support and upgrade policy](https://docs.astro.build/en/upgrade-astro/#nodejs-support-and-upgrade-policies) allows the Core team to raise the minimum Maintenance LTS version in a patch release when a disclosed and fixed Node.js security flaw affects Astro.

- [#&#8203;18451](https://github.com/withastro/astro/pull/18451) [`7a0ba6f`](https://github.com/withastro/astro/commit/7a0ba6f48ebae256a1ce49de4f1c62c009ff94e2) Thanks [@&#8203;DenisCDev](https://github.com/DenisCDev)! - Fixes `astro sync`, `astro check` and `astro build` replacing the optimized dependencies of a dev server running in the same project, which broke framework islands in that dev server until it was restarted with `--force`

- [#&#8203;18336](https://github.com/withastro/astro/pull/18336) [`e943003`](https://github.com/withastro/astro/commit/e943003259c3bb4d528d3d49c8ccd3eb8f84b8b5) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes inline styles in dev so that framework-transformed CSS is used, such as scoped styles and `v-bind()` in Vue single-file components

- [#&#8203;18399](https://github.com/withastro/astro/pull/18399) [`829fc00`](https://github.com/withastro/astro/commit/829fc00629ef715fc606b89c6e684ca93f9253b9) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a dev server error (`Could not find server component name`) for a `server:defer` island that imports `astro:actions` or `astro:config/server`, when its page was not the first island page loaded after starting the server

- [#&#8203;18330](https://github.com/withastro/astro/pull/18330) [`4db9e0d`](https://github.com/withastro/astro/commit/4db9e0d1e6a54c2300b96a0ff0cfaf5c188cecda) Thanks [@&#8203;Samuteg](https://github.com/Samuteg)! - Fixes the `astro:env/server` virtual module being generated with invalid JS in dev when any environment variable contains `$` replacement patterns (`` $` ``, `$&`, `$'`, `$1`, …). The inlined env JSON was passed as a string to `String.replace`, so e.g. the `KITTY_PUBLIC_KEY` value set by default in Kitty terminals corrupted the module and broke dev with `Failed to parse source for import analysis`

- Updated dependencies \[[`cf27e70`](https://github.com/withastro/astro/commit/cf27e70a9057ce29ade2a8a843bd9275a696e9ab)]:
  - [@&#8203;astrojs/telemetry](https://github.com/astrojs/telemetry)@3.4.1
  - [@&#8203;astrojs/markdown-satteri](https://github.com/astrojs/markdown-satteri)@0.4.5

</details>

<details>
<summary>actions/node-versions (node)</summary>

### [`v26.12.1`](https://github.com/actions/node-versions/releases/tag/26.12.1-39618969937): 26.12.1

[Compare Source](https://github.com/actions/node-versions/compare/26.12.0-38668157440...26.12.1-39618969937)

Node.js 26.12.1

### [`v26.12.0`](https://github.com/actions/node-versions/releases/tag/26.12.0-38668157440): 26.12.0

[Compare Source](https://github.com/actions/node-versions/compare/26.11.1-37718106145...26.12.0-38668157440)

Node.js 26.12.0

### [`v26.11.1`](https://github.com/actions/node-versions/releases/tag/26.11.1-37718106145): 26.11.1

[Compare Source](https://github.com/actions/node-versions/compare/26.11.0-37718124002...26.11.1-37718106145)

Node.js 26.11.1

### [`v26.11.0`](https://github.com/actions/node-versions/releases/tag/26.11.0-37718124002): 26.11.0

[Compare Source](https://github.com/actions/node-versions/compare/26.10.0-35737674515...26.11.0-37718124002)

Node.js 26.11.0

### [`v26.10.0`](https://github.com/actions/node-versions/releases/tag/26.10.0-35737674515): 26.10.0

[Compare Source](https://github.com/actions/node-versions/compare/26.9.0-35174947414...26.10.0-35737674515)

Node.js 26.10.0

### [`v26.9.0`](https://github.com/actions/node-versions/releases/tag/26.9.0-35174947414): 26.9.0

[Compare Source](https://github.com/actions/node-versions/compare/26.8.2-34429851330...26.9.0-35174947414)

Node.js 26.9.0

### [`v26.8.2`](https://github.com/actions/node-versions/releases/tag/26.8.2-34429851330): 26.8.2

[Compare Source](https://github.com/actions/node-versions/compare/26.8.1-33034053154...26.8.2-34429851330)

Node.js 26.8.2

### [`v26.8.1`](https://github.com/actions/node-versions/releases/tag/26.8.1-33034053154): 26.8.1

[Compare Source](https://github.com/actions/node-versions/compare/26.8.0-33034064325...26.8.1-33034053154)

Node.js 26.8.1

### [`v26.8.0`](https://github.com/actions/node-versions/releases/tag/26.8.0-33034064325): 26.8.0

[Compare Source](https://github.com/actions/node-versions/compare/26.7.0-31064755789...26.8.0-33034064325)

Node.js 26.8.0

### [`v26.7.0`](https://github.com/actions/node-versions/releases/tag/26.7.0-31064755789): 26.7.0

[Compare Source](https://github.com/actions/node-versions/compare/26.6.0-30872438625...26.7.0-31064755789)

Node.js 26.7.0

### [`v26.6.0`](https://github.com/actions/node-versions/releases/tag/26.6.0-30872438625): 26.6.0

[Compare Source](https://github.com/actions/node-versions/compare/26.5.1-30508404249...26.6.0-30872438625)

Node.js 26.6.0

### [`v26.5.1`](https://github.com/actions/node-versions/releases/tag/26.5.1-30508404249): 26.5.1

[Compare Source](https://github.com/actions/node-versions/compare/26.5.0-28944078721...26.5.1-30508404249)

Node.js 26.5.1

### [`v26.5.0`](https://github.com/actions/node-versions/releases/tag/26.5.0-28944078721): 26.5.0

[Compare Source](https://github.com/actions/node-versions/compare/26.4.0-28176665805...26.5.0-28944078721)

Node.js 26.5.0

### [`v26.4.0`](https://github.com/actions/node-versions/releases/tag/26.4.0-28176665805): 26.4.0

[Compare Source](https://github.com/actions/node-versions/compare/26.3.1-27765697053...26.4.0-28176665805)

Node.js 26.4.0

### [`v26.3.1`](https://github.com/actions/node-versions/releases/tag/26.3.1-27765697053): 26.3.1

[Compare Source](https://github.com/actions/node-versions/compare/26.3.0-26776574275...26.3.1-27765697053)

Node.js 26.3.1

### [`v26.3.0`](https://github.com/actions/node-versions/releases/tag/26.3.0-26776574275): 26.3.0

[Compare Source](https://github.com/actions/node-versions/compare/26.2.0-26201774761...26.3.0-26776574275)

Node.js 26.3.0

### [`v26.2.0`](https://github.com/actions/node-versions/releases/tag/26.2.0-26201774761): 26.2.0

[Compare Source](https://github.com/actions/node-versions/compare/26.1.0-25496618813...26.2.0-26201774761)

Node.js 26.2.0

### [`v26.1.0`](https://github.com/actions/node-versions/releases/tag/26.1.0-25496618813): 26.1.0

[Compare Source](https://github.com/actions/node-versions/compare/26.0.0-25413736946...26.1.0-25496618813)

Node.js 26.1.0

### [`v26.0.0`](https://github.com/actions/node-versions/releases/tag/26.0.0-25413736946): 26.0.0

[Compare Source](https://github.com/actions/node-versions/compare/24.22.2-40806817314...26.0.0-25413736946)

Node.js 26.0.0

</details>

<details>
<summary>pnpm/pnpm (pnpm)</summary>

### [`v12.16.1`](https://github.com/pnpm/pnpm/releases/tag/v12.16.1): pnpm 12.16.1

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.16.0...v12.16.1)

This release fixes `pnpm install` hanging on a cold store in workspaces that install Cargo crates, and `pnpm pack` shipping a file that `files` excludes by name.

##### Patch Changes

- `pnpm install` no longer hangs on a cold store in a workspace that also installs Cargo crates or a Rust toolchain.

- `pnpm pack` and `pnpm publish` now apply a `files` entry that names a file after the glob and directory entries, as npm does. A file excluded by name, such as `!dist/index.js`, stays out even when a later `dist/**` matches it. A file named by its path, such as `lib/secret.js`, ships even when a later `!lib/*.js` matches it.

- `pnpm install` no longer leaves a broken symlink in an injected workspace dependency when the package links to a file outside its published files and pnpm imports by hardlink. Installing a git dependency now skips internal directory symlinks when importing its files into the store.

- `pnpm install` now relinks a command that a workspace project renames into the projects that depend on it when `sharedWorkspaceLockfile` is `false` [pnpm/tasks#224](https://github.com/pnpm/tasks/issues/224).

- `pnpm install` and `pnpm rebuild` now refresh privately hoisted `.bin` shims in `node_modules/.pnpm/node_modules/.bin` after a dependency build replaces a script target with a native executable [#&#8203;17402](https://github.com/pnpm/pnpm/issues/17402).

- `pnpm install` now reads a package's manifest to decide its peer dependencies when it updates an existing lockfile, as it does when it resolves from scratch.

- Commands, `pnpm --version`, `pnpm self-update`, and invocations with unknown flags now apply the same `packageManager` and `devEngines.packageManager` settings when switching to the pinned pnpm version or recording it in `pnpm-lock.yaml`. `--config.<key>` flags and `lockfileDir` now reach the version switch and lockfile sync on every entry point. Unreadable settings in `pnpm-workspace.yaml` or the global `config.yaml` that do not affect the pin decision no longer block the version switch [pnpm/tasks#222](https://github.com/pnpm/tasks/issues/222).

- pnpm now accepts the `--cache-dir <dir>` flag, as in `pnpm install --cache-dir /tmp/pnpm-cache` [#&#8203;17422](https://github.com/pnpm/pnpm/issues/17422).

- When the version or range given to `pnpm unpublish` matches every published version, the error now says so and shows the same command with `--force`. Before, the error suggested running `pnpm unpublish <pkg>@<version>`, the command that had just failed.

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.16.0`](https://github.com/pnpm/pnpm/releases/tag/v12.16.0): pnpm 12.16

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.15.0...v12.16.0)

This release adds a global `--env-file` flag, updates to a symlinked `pnpm-lock.yaml`, and `pnpm setup --no-modify-path`. It also fixes two security issues, in zstd decompression and in signing.

##### Minor Changes

- Added a repeatable global `--env-file <path>` flag to load environment variables from dotenv-style files before running a command. Later files override earlier files, variables already in the environment are preserved, and loaded variables are visible to user-level `.npmrc` interpolation and lifecycle scripts [#&#8203;7111](https://github.com/pnpm/pnpm/issues/7111).

- pnpm can now update a `pnpm-lock.yaml` that is a symlink. List the directories the lockfile may link into in the `symlinkedLockfileTargetDirs` setting, in the global config or with `PNPM_CONFIG_SYMLINKED_LOCKFILE_TARGET_DIRS`. pnpm writes the update to the file the symlink points to if that file is inside one of these directories. The symlink stays in place. pnpm ignores this setting in `pnpm-workspace.yaml` [#&#8203;17222](https://github.com/pnpm/pnpm/issues/17222).

- Added a `--no-modify-path` option to `pnpm setup`. It installs pnpm without adding it to `PATH`, leaving the shell config file, the Windows registry, and the GitHub Actions environment files unchanged. `pnpm setup` then prints the lines to add yourself [get.pnpm.io#37](https://github.com/pnpm/get.pnpm.io/issues/37).

##### Patch Changes

##### Security

- Fixed memory exposure and allocation handling vulnerabilities when processing zstd-compressed data [#&#8203;17388](https://github.com/pnpm/pnpm/pull/17388).

- Signing in pnpm and pnpr no longer uses arithmetic that may leak the private key through timing. This covers shared artifacts, OCI registry tokens, and OIDC login state [advisory](https://rustsec.org/advisories/RUSTSEC-2026-0387).

##### Installing packages

- A dependency symlink that pnpm cannot point at the wanted target now fails the install with an error that names the link. This happens when the filesystem still serves the old link after pnpm removed it, as a `node_modules` served by a virtual filesystem does. pnpm used to remove the link again without end and crashed with a segmentation fault once the thread ran out of stack.

- Concurrent workspace installs no longer lose store-index rows when initializing the shared SQLite index [#&#8203;17388](https://github.com/pnpm/pnpm/pull/17388).

- Agent skill links now keep the same target across installs when a package version is installed with several sets of peer dependencies. An install no longer fails with `ERR_PNPM_AGENT_SKILL_PATH_OCCUPIED` on a skill link that pnpm created for another of those copies [#&#8203;17319](https://github.com/pnpm/pnpm/issues/17319).

- pnpm now fails at once, without retrying, when a downloaded package archive contains a rejected entry path [#&#8203;17205](https://github.com/pnpm/pnpm/issues/17205).

- pnpm now builds a git-hosted dependency in every new location it links the dependency into, such as a new global virtual store slot or a fresh `node_modules`. When the side-effects cache holds the build output, pnpm restores it from there. Before, only the install that fetched the dependency built it. This also fixes dependencies that are already in the store [#&#8203;17224](https://github.com/pnpm/pnpm/issues/17224).

- Changes a `preResolution` hook makes to the lockfiles now take effect. The hook now also runs when pnpm installs from an up-to-date lockfile. An error thrown by the hook now fails the install.

- A custom fetcher in the pnpmfile can now call `fetchers.directory` to fetch a package from a local directory. The call rejects with `ERR_PNPM_TARBALL_INTEGRITY` if the lockfile pins an archive integrity for the package. Previously, calling `fetchers.directory` failed with a `TypeError`.

- `packageImportMethod: copy` now also applies to packages that have lifecycle scripts or patches. On a filesystem that supports block cloning, such as ReFS or a Dev Drive on Windows, these packages were cloned [#&#8203;17195](https://github.com/pnpm/pnpm/issues/17195).

- With `nodeLinker: hoisted` and `autoInstallPeers: false`, a package that workspace projects use with different peer versions is now installed once per peer variant, so each project's copy resolves that project's peer [#&#8203;17395](https://github.com/pnpm/pnpm/issues/17395).

- Under `nodeLinker: hoisted`, `pnpm install` now leaves a patched package that is already in place alone. The same holds for a package whose peers include a patched package, such as every package peering on a patched `react-native` [#&#8203;17188](https://github.com/pnpm/pnpm/issues/17188).

- With `nodeLinker: hoisted`, an install that stops partway no longer leaves the next install trusting the packages it was replacing. Before, reverting the change that started the stopped install, such as a patch edit, kept the half-replaced package in `node_modules`.

##### Repeat installs and changed settings

- A repeat `pnpm install` now acts on a change to these settings. Before, it reported "Already up to date".

  - `storeDir` or `virtualStoreDir`: it recreates `node_modules`.
  - `globalVirtualStoreDir`: it links the packages from the new directory.
  - `virtualStoreDirMaxLength`: it renames the virtual store directories.
  - `dangerouslyAllowAllBuilds` turned on: it runs the builds it skipped.
  - `trustLockfile` turned off: it verifies the lockfile.

- `pnpm add`, `pnpm remove`, and `pnpm update` now fail if `node_modules` does not match the current settings. Run `pnpm install` to recreate it. Previously, these commands removed and reinstalled `node_modules` without asking. They report:

  - `ERR_PNPM_UNEXPECTED_STORE` if `node_modules` was linked from a different store.
  - `ERR_PNPM_UNEXPECTED_VIRTUAL_STORE` if it was linked from a different virtual store directory.
  - `ERR_PNPM_MODULES_BREAKING_CHANGE` if it was installed by an incompatible pnpm version, or if `node_modules/.modules.yaml` cannot be read.
  - `ERR_PNPM_NODE_LINKER_DIFF` if it was installed with a different `nodeLinker`.

  `pnpm update` now also fails with `ERR_PNPM_HOIST_PATTERN_DIFF` and the other errors `pnpm add` reports for a changed hoist pattern or `virtualStoreDirMaxLength`.

- An install filtered to some workspace projects now fails if `node_modules` was installed with a different `nodeLinker`, `hoistPattern`, `publicHoistPattern`, store, or virtual store. Before, it recreated `node_modules` and left the projects it skipped without their dependencies. A `pnpm install` of the whole workspace still recreates `node_modules` [pnpm/tasks#217](https://github.com/pnpm/tasks/issues/217).

- `pnpm install` and the `verifyDepsBeforeRun` check now notice an edited patch file when `sharedWorkspaceLockfile` is `false`.

- `pnpm install` now takes its fast path in a workspace with `patchedDependencies` when the previous install ran with another major version of pnpm.

- `pnpm install` now relinks the bins of a workspace package when its `bin` field changes, including with `--frozen-lockfile` and an unchanged lockfile. A filtered install relinks them in the selected projects, and the next install that covers the remaining projects relinks them there [#&#8203;17324](https://github.com/pnpm/pnpm/issues/17324).

- `pnpm install` now removes command shims from `node_modules/.bin` when a workspace dependency renames or removes an entry from its `bin` field [pnpm/tasks#211](https://github.com/pnpm/tasks/issues/211).

##### Resolving dependencies and the lockfile

- A package that a plain range and a `<prefix>:` specifier both resolve from one registry is now recorded once in `pnpm-lock.yaml` and installed once. The lockfile key names the registry a package resolved from. When that registry declares a prefix, through `prefix` in `registries` or through `namedRegistries`, the package is keyed `<name>@<prefix>:<version>` however its dependency was written: with the prefix, as a plain range its scope routes to that registry, or through the default registry. Before, the plain range was keyed `<name>@<version>`, so one tarball was installed twice and `instanceof` checks and module singletons broke between the two copies. The same name and version served by two registries still get separate entries. When several prefixes declare one registry, its packages are keyed by the lexicographically smallest prefix.

  If a scope you route reaches a registry that also declares a prefix, your next `pnpm install` re-keys those entries, which shows up as a lockfile diff. Commit it. `pnpm install --frozen-lockfile` installs the lockfile as recorded.

- `pnpm install` now resolves a scope's packages again when the scope is routed to another registry in `registries`. Before, the lockfile kept the versions and integrity resolved from the old registry, so the install failed when the new registry did not serve a locked version or served different content. pnpm records in the workspace state which registry each scope routed to, so a fresh clone without that record installs the lockfile as recorded. Changing the default registry resolves nothing again, and `pnpm install --frozen-lockfile` is unchanged.

- When `autoDedupe` is off, a workspace project's dependencies now resolve from its own ranges, like they do with `sharedWorkspaceLockfile: false`. Previously, another project's narrower range could hold them back. For example, `ajv: "*"` now resolves to the latest Ajv even if another project depends on `ajv@^6`. Packages that a project lists in `peerDependencies` still follow the versions other projects use. `pnpm dedupe` and installs with `autoDedupe: true` still pick one version that satisfies every range. Set `autoDedupe: true` if CI runs `pnpm dedupe --check` [#&#8203;17235](https://github.com/pnpm/pnpm/issues/17235).

- An optional dependency written with a named-registry prefix, such as `work:^1.0.0`, now fails the install when it cannot be resolved but the lockfile already has a matching entry from that registry. Such a dependency was skipped, which removed its entries from the lockfile.

- With `injectWorkspacePackages: true`, a `workspace:` dependency written as a relative path, such as `workspace:../lib-a`, in a workspace package now resolves from that package's directory [#&#8203;17284](https://github.com/pnpm/pnpm/issues/17284).

- Fixed `pnpm install` failing with `ERR_PNPM_UNSUPPORTED_PROTOCOL` when a workspace package injected through a relative path, such as `workspace:../lib`, has `catalog:` dependencies. Their catalog entries now resolve the way they do for a package injected by name [#&#8203;17280](https://github.com/pnpm/pnpm/issues/17280).

- `pnpm dedupe` now refreshes cached registry metadata while re-resolving locked versions [#&#8203;17208](https://github.com/pnpm/pnpm/issues/17208).

- `pnpm dedupe --check` no longer fails when the only difference is a `deprecated` notice that the registry added or removed after the lockfile was written [#&#8203;17198](https://github.com/pnpm/pnpm/issues/17198).

- Installs delegated to a pnpr server now resolve every prefix declared for a registry URL. A dependency or lockfile entry that used the second of two prefixes for the same registry, such as `zeta:` next to `work:` in `namedRegistries`, failed on the server [pnpm/tasks#204](https://github.com/pnpm/tasks/issues/204).

- Registry revisions are now addressed at `<registry>/<name>@<version>+r<revision>` [pnpm/tasks#208](https://github.com/pnpm/tasks/issues/208).

##### Adding packages and global packages

- `pnpm add <pkg>@<tag>` and `pnpm add <pkg>@<range>` now install the version the tag or range resolves to, even when the saved range allows a newer one [#&#8203;17234](https://github.com/pnpm/pnpm/issues/17234).

- `pnpm add <pkg>` without a version now installs the version under the dist-tag set by the `tag` setting. An `npm:` alias or a `jsr:` dependency without a version resolves that tag too. The setting is read from `pnpm-workspace.yaml`, the global config, `PNPM_CONFIG_TAG`, and `--config.tag`, and defaults to `latest`.

- `pnpm add` now accepts the lowercase short options `-p`, `-d`, `-o`, and `-e` as aliases of `--save-prod`, `--save-dev`, `--save-optional`, and `--save-exact`.

- `pnpm -D install <pkg>` now saves the package to devDependencies. An `add` option such as `-D` or `-E` written before `install <pkg>` was rejected as an unexpected argument.

- `pnpm add -T` now reports that the short option is ambiguous and points to `--save-types` and `--tilde`.

- Global packages installed with `pnpm add -g` are now linked from the global virtual store, so global packages that share dependencies share one copy. Set `virtualStoreType: project` to give each global install its own virtual store.

- `pnpm add -g` and the other `--global` commands now fail with `ERR_PNPM_CONFIG_CONFLICT_VIRTUAL_STORE_DIR_WITH_GLOBAL` when `--virtual-store-dir` is passed. A custom `--hoist-pattern` fails with `ERR_PNPM_CONFIG_CONFLICT_HOIST_PATTERN_WITH_GLOBAL`. Passing `--link-workspace-packages`, `--shared-workspace-lockfile`, or `--config.lockfile-dir` with `--global` also fails, with the matching `ERR_PNPM_CONFIG_CONFLICT_*_WITH_GLOBAL` code.

##### Registries, proxies, and login

- pnpm now reads the `strictSsl` and `localAddress` settings from `pnpm-workspace.yaml`, the global `config.yaml`, `PNPM_CONFIG_*` environment variables, and `--config.*` options. This includes `pnpm self-update` and the download of the pnpm version pinned in `packageManager`. Before, pnpm read them only from `.npmrc` as `strict-ssl` and `local-address` and ignored the other sources [pnpm/tasks#201](https://github.com/pnpm/tasks/issues/201).

- When Corepack runs pnpm and the native binary has to be downloaded, the download now uses the proxy from pnpm's config. That proxy comes from `PNPM_CONFIG_HTTPS_PROXY` and the matching variables, the global `config.yaml`, and the user `.npmrc`. Previously, the download read the proxy only from `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` [pnpm/tasks#215](https://github.com/pnpm/tasks/issues/215).

- When the `pnpm` package downloads its native binary on first run, as it does under Corepack, it now trusts the CA certificates from the `ca`, `ca[]`, and `cafile` settings of `.npmrc`, including the ones scoped to the registry. A registry behind a private CA failed with `fetch failed` before, unless `NODE_EXTRA_CA_CERTS` named the CA. A project `.npmrc` is used only while the download is checked against npm's signature. Node.js versions that cannot add CA certificates after startup still need `NODE_EXTRA_CA_CERTS`.

- `pnpm login` saves the token in `<pnpm config>/auth.ini` again. Since v12.1.0, an unscoped login had made its registry the default for every project that did not name a registry. A login now also removes the token an earlier login saved for that registry or scope under `_auth` in the global `config.yaml`. `pnpm login --scope` still routes the scope through the global `registries` setting.

- pnpm no longer warns that a `registries` entry routed through the `@` scope matches no configured registry. pnpm applied such an entry and its options such as `serverType` while reporting it as ignored [pnpm/tasks#184](https://github.com/pnpm/tasks/issues/184).

##### Running scripts and other commands

- `pnpm ci --lockfile` and `pnpm ci --config.lockfile=true` no longer delete `pnpm-lock.yaml`. `pnpm ci` now always keeps the lockfile and runs a frozen install from it.

- `pnpm deploy --legacy` now checks the workspace lockfile against `minimumReleaseAge` and the other resolution policies, as `pnpm install` does, and fails with `ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION` when a locked version is too new. It used to deploy an older version that is not in the lockfile without a warning [#&#8203;17209](https://github.com/pnpm/pnpm/issues/17209).

- `pnpm deploy` now keeps a deployed symlink to a directory inside the project even if the directory is not among the deployed files, such as a link into `node_modules` [#&#8203;17288](https://github.com/pnpm/pnpm/issues/17288).

- `pnpm pack` and `pnpm publish` now keep `pnpm.config` in the published `package.json`. They also always include the file `pnpm.config` points to in the tarball [#&#8203;17210](https://github.com/pnpm/pnpm/issues/17210).

- `pnpm -r publish --batch` now sends `PUT /-/pnpr/v0/publish`, the batch publish endpoint that pnpr serves.

- `pnpm audit --ignore` and `pnpm audit --ignore-unfixable` now exit with a non-zero code when vulnerabilities at or above the audit level remain after ignoring. Before, these commands always exited with code 0.

- `pnpm audit --fix` and `pnpm audit --interactive` now fail with `ERR_PNPM_AUDIT_FIX_WITH_IGNORE` when combined with `--ignore` or `--ignore-unfixable`. Before, the fix ran and the ignore flags had no effect.

- `pnpm -r run <script>` now honors the `requiredScripts` setting from `pnpm-workspace.yaml`. If the script is listed there and a selected project does not define it, the run fails with `ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT` and names the projects that lack it.

- `pnpm run` and `pnpm exec` no longer report the dependencies as out of date after a lockfile change when `dedupePeers` is `true` [#&#8203;17322](https://github.com/pnpm/pnpm/issues/17322).

- On macOS, killing pnpm while it runs scripts in several projects at once now ends every one of those scripts. Before, a script could keep running after pnpm died.

- `pnpm run`, `pnpm exec`, and `pnpm dlx` no longer dump a core file for `pnpm` itself when a command they started dies from a signal [#&#8203;17204](https://github.com/pnpm/pnpm/issues/17204).

- The `runtime` setting is now read. Setting `runtime: false` in `pnpm-workspace.yaml`, `pnpm_config_runtime=false`, or `--config.runtime=false` stops `pnpm install`, `pnpm add`, `pnpm dedupe`, and the other installing commands from installing the runtimes in `devEngines.runtime` and `engines.runtime`. `pnpm dedupe` now also accepts `--no-runtime`.

- Directory selectors with `legacyDirFiltering: true` now include the project in the named directory along with its descendants. Excluding a directory also excludes that project [pnpm/tasks#196](https://github.com/pnpm/tasks/issues/196).

- `pnpm help --all` and `pnpm help -a` now print the full list of commands. They used to fail with an "unrecognized subcommand" error.

- Reading the file-creation mask on Linux no longer sets it. pnpm had to replace the mask to learn what it was, and a file another thread created in the window between the two calls was created unmasked.

- pnpm now passes an interrupt on to the handler it replaced, with the arguments that handler expects. A handler that asked for the signal's details was called without them. Only a program that embeds pnpm and installs its own `SIGINT`, `SIGTERM` or `SIGHUP` handler was affected.

##### Store

- `pnpm store prune` now keeps the packages that a project still uses when pnpm copied or cloned them into `node_modules`. These include patched packages, built packages, and every package installed with `packageImportMethod: copy`. Before, the prune removed them, and the next install downloaded them again [#&#8203;7192](https://github.com/pnpm/pnpm/issues/7192).

- `pnpm store prune` now keeps the packages of a project when the store path reaches its directory through a symlink. Previously, prune dropped such a project from its list and removed the packages only that project used from the global virtual store.

- `pnpm store prune` now removes the package metadata cache, the `metadata*` directories in the cache directory. This clears the outdated integrity checksums that cause `ERR_PNPM_TARBALL_INTEGRITY` when a registry republishes a version.

##### Speed

- `pnpm install` resolves dependencies faster in large workspaces on Linux, macOS, and Windows on x64 and arm64.

- Sped up cold installs and `pnpm fetch` on macOS. pnpm now links downloaded packages into the virtual store on a separate thread, so a slow link pass no longer pauses the downloads that are still in flight [#&#8203;17271](https://github.com/pnpm/pnpm/issues/17271).

- Sped up installs that add new projects to a workspace with a peer-heavy lockfile. pnpm now reads the lockfile's locked peer versions once for all new projects [#&#8203;17311](https://github.com/pnpm/pnpm/issues/17311).

- Warm installs no longer read the `package.json` of every git-hosted dependency. pnpm now stores the manifest of a git-hosted package in the store index when it fetches the package.

- `pnpm update --depth <n>` with a large `n`, such as the `--depth=9999` that `update-browserslist-db` runs, now finishes as fast as `--depth Infinity`. It used memory and stack in proportion to `n` on lockfiles with dependency cycles, and could run out of memory or crash [#&#8203;17329](https://github.com/pnpm/pnpm/issues/17329).

##### Output and warnings

- Output that fills the terminal, such as `pnpm run --stream` script output, is now written once. Before, every new line also rewrote all the lines already on screen [#&#8203;17387](https://github.com/pnpm/pnpm/issues/17387).

- pnpm now warns when a pnpmfile defines the `importPackage` hook. pnpm does not run this hook. Use the `packageImportMethod` setting to choose how packages are written to `node_modules`.

- `pnpm` now warns when a project's `pnpm-workspace.yaml` sets `ci`, `globalShims`, or `tools`, and names where to set them instead. These settings were already ignored there without a warning. `pnpm config set` also refuses to write them to a project's `pnpm-workspace.yaml`.

- pnpm no longer documents the `scriptsPrependNodePath` setting, which has no effect. A `pnpm-workspace.yaml` that sets it still loads.

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xODEuNyIsInVwZGF0ZWRJblZlciI6IjQ0LjE5OS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://gitea.com/gitea/docs/pulls/626
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
2026-11-02 00:49:41 +00:00
silverwindandLunny Xiao 6632d38fe2 Document the commitstatus token scope (#622)
Documents https://github.com/go-gitea/gitea/pull/40144 for main, which adds `read:commitstatus` and `write:commitstatus` token scopes so CI integrations can report commit statuses without full repository access. The repository scopes include them.

Adds the scope to the OAuth2 provider scope table and the API usage permission list. Draft until the Gitea PR merges.

_Written by Claude (Opus 5.5)._

---------

Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/622
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-11-01 18:19:38 +00:00
silverwindandbircni ef57d8d2c0 Document gitea-cli OAuth2 application (#620)
Documents https://github.com/go-gitea/gitea/pull/40036 for main, which renames the built-in tea OAuth2 application to gitea-cli and keeps `tea` as an alias in `[oauth2] DEFAULT_APPLICATIONS`.

The default list and the pre-configured applications table also gain the missing gitea-app and gitea-vscode entries.

_Written by Claude (Opus 5.5)._

---------

Co-authored-by: bircni <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/620
Reviewed-by: bircni <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-11-01 12:50:48 +00:00
bircni ba4abd749d update to 28.3.0 (#623)
Bump the v28 docs to the 28.3.0 release:

- point the `28` version variables (`version`, `sourceVersion`, `dockerVersion`, `displayVersion`) at 28.3.0
- update the v28 entry in `update_api_docs.sh` to `28.3.0`
- regenerate `static/swagger-28.json` and `static/openapi3-28.json` from the `v28.3.0` tag, which picks up the updated `Deadline` and `Labels` descriptions from go-gitea/gitea#39869 and go-gitea/gitea#39873

Reviewed-on: https://gitea.com/gitea/docs/pulls/623
Reviewed-by: silverwind <[email protected]>
2026-11-01 10:11:04 +00:00
silverwind 8197192134 Document GITEA_* env aliases, missing variables and accurate examples (#618)
https://gitea.com/gitea/runner/pulls/1358 mirrors every built-in `GITHUB_*` variable as `GITEA_*`. The variables page now lists both names for each, in the same paired style as the context table.

It also adds variables that runners already set but the page left out (`*_ACTOR_ID`, `*_REF_PROTECTED`, `*_REPOSITORY_ID`, `*_REPOSITORY_OWNER_ID`, `*_TRIGGERING_ACTOR`, `*_WORKFLOW_SHA`, `ACT`, `ImageOS`, `RUNNER_DEBUG`, `RUNNER_ENVIRONMENT`, `RUNNER_NAME`, `RUNNER_WORKSPACE`, `TRACEPARENT`, `TRACESTATE`).

Examples copied from GitHub's runner (`/home/runner/work/_temp/...` paths, `__run`, `ghs_***`) are replaced with the values gitea-runner and Gitea actually produce, using placeholder users, repositories and instance URLs.

The zh-cn and zh-tw pages get the environment variable section they never had.

Reviewed-on: https://gitea.com/gitea/docs/pulls/618
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-31 05:25:00 +00:00
brock0124andLunny Xiao 97fa45dabc fix(Hem Chart Registry docs): typo (#614)
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/614
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: brock0124 <[email protected]>
2026-10-29 02:19:31 +00:00
ee9e91cdeb Add project workflow documentation (#308)
Documentation for https://github.com/go-gitea/gitea/pull/30205

---------

Co-authored-by: silverwind <[email protected]>
Co-authored-by: silverwind <[email protected]>
Co-authored-by: silverwind <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/308
Reviewed-by: silverwind <[email protected]>
2026-10-28 16:12:53 +00:00
Renovate BotandLunny Xiao d301461648 chore(deps): update dependencies (#611)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | Type | Update | Pending |
|---|---|---|---|---|---|---|
| [@astrojs/check](https://github.com/withastro/astro/tree/main/packages/language-tools/astro-check) ([source](https://github.com/withastro/astro/tree/HEAD/packages/language-tools/astro-check)) | [`0.9.10` → `0.9.11`](https://renovatebot.com/diffs/npm/@astrojs%2fcheck/0.9.10/0.9.11) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@astrojs%2fcheck/0.9.11?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@astrojs%2fcheck/0.9.10/0.9.11?slim=true) | devDependencies | patch | `0.9.12` |
| [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`7.3.8` → `7.4.1`](https://renovatebot.com/diffs/npm/astro/7.3.8/7.4.1) | ![age](https://developer.mend.io/api/mc/badges/age/npm/astro/7.4.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/astro/7.3.8/7.4.1?slim=true) | dependencies | minor | `7.4.2` |
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm/npm/pnpm)) | [`12.13.0` → `12.15.0`](https://renovatebot.com/diffs/npm/pnpm/12.13.0/12.15.0) | ![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/12.15.0?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/12.13.0/12.15.0?slim=true) | packageManager | minor |  |
| [ubuntu](https://github.com/actions/runner-images) | `24.04` → `26.04` | ![age](https://developer.mend.io/api/mc/badges/age/github-runners/ubuntu/26.04?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/github-runners/ubuntu/24.04/26.04?slim=true) | github-runner | major |  |

---

### Release Notes

<details>
<summary>withastro/astro (@&#8203;astrojs/check)</summary>

### [`v0.9.11`](https://github.com/withastro/astro/blob/HEAD/packages/language-tools/astro-check/CHANGELOG.md#0911)

[Compare Source](https://github.com/withastro/astro/compare/@astrojs/[email protected]...@astrojs/[email protected])

##### Patch Changes

- [#&#8203;18445](https://github.com/withastro/astro/pull/18445) [`d736df7`](https://github.com/withastro/astro/commit/d736df7a9cc03c12b22e538f058fb1f769672471) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes the `--preserveWatchOutput` help text, which described the opposite of the flag's behavior. Setting it to `true` keeps output between checks in watch mode.

- [#&#8203;18444](https://github.com/withastro/astro/pull/18444) [`c55134c`](https://github.com/withastro/astro/commit/c55134c1d3c238a43e17cfeff136375a4d9d5d35) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `astro check --watch` exiting immediately when the project path contains `node_modules` or `.git`

</details>

<details>
<summary>withastro/astro (astro)</summary>

### [`v7.4.1`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#741)

[Compare Source](https://github.com/withastro/astro/compare/[email protected]@7.4.1)

##### Patch Changes

- [#&#8203;18425](https://github.com/withastro/astro/pull/18425) [`6fdc36e`](https://github.com/withastro/astro/commit/6fdc36ed97316d932d2e143b85739f0af37ab329) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Preserves the last modified date of cached optimized images and incrementally restored build output when copying them into the build output on all platforms

- [#&#8203;18419](https://github.com/withastro/astro/pull/18419) [`395d195`](https://github.com/withastro/astro/commit/395d19525986a276bf81af7bd365e7a35dc20ef3) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a typo in the error message shown when a font `cssVariable` is invalid

- [#&#8203;18401](https://github.com/withastro/astro/pull/18401) [`484822f`](https://github.com/withastro/astro/commit/484822fbba652745c4f2da5ef434a350203578e2) Thanks [@&#8203;danielmlr](https://github.com/danielmlr)! - Fixes a bug where projects whose path contains an apostrophe (`'`) failed to load sessions, middleware, a cache provider, or a `src/fetch.ts` handler

- [#&#8203;18407](https://github.com/withastro/astro/pull/18407) [`a6e00be`](https://github.com/withastro/astro/commit/a6e00beae6c134d0c1b5248eb02fbf119b7d64e9) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a `TSCONFIG_ERROR` during `astro build` when a parent directory contains a `tsconfig.json` that cannot be resolved, such as one extending `astro/tsconfigs/strict` without installed dependencies

- [#&#8203;18427](https://github.com/withastro/astro/pull/18427) [`908f167`](https://github.com/withastro/astro/commit/908f1672a9fe6c40e6b73bfb0307f0d1f3ac2057) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes an `Unterminated string` build error when application code imports from `astro/config` (for example, `fontProviders` in a shared fonts module)

- [#&#8203;18428](https://github.com/withastro/astro/pull/18428) [`40e7d54`](https://github.com/withastro/astro/commit/40e7d54c7f969b402f011d32ccd87123835d0aa1) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes missing styles in production builds for conditionally rendered framework components (e.g. Svelte components inside `{#if}` blocks) imported by a hydrated island

- [#&#8203;18424](https://github.com/withastro/astro/pull/18424) [`617ff59`](https://github.com/withastro/astro/commit/617ff59820b4a5777eb5d3765c09d29082b11acc) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes style-only HMR in `.astro` components falling back to a full page reload when a PostCSS plugin (such as `@unocss/postcss`) lists the component as a dependency of its own style

- [#&#8203;18274](https://github.com/withastro/astro/pull/18274) [`70834bb`](https://github.com/withastro/astro/commit/70834bbea43695c563358ea055d32ecb5e0a78dd) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixes increasing memory usage when editing the Astro configuration while the dev server is running

### [`v7.4.0`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#740)

[Compare Source](https://github.com/withastro/astro/compare/[email protected]@7.4.0)

##### Minor Changes

- [#&#8203;17894](https://github.com/withastro/astro/pull/17894) [`b7a1bd9`](https://github.com/withastro/astro/commit/b7a1bd99ac7c68cf36078058f15f1bd1fab4cbe8) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Adds a new `--timings` flag to `astro build` to help you find what slows down your builds

  When a build takes longer than expected, it can be hard to tell whether the cause is an integration, a Markdown processor plugin, image processing, or even syntax highlighting. Add the `--timings` flag to your build command to print a summary once the build finishes:

  ```sh
  astro build --timings
  ```

  This is helpful to decide what to optimize first, or to compare build times before and after a change to your project.

- [#&#8203;17830](https://github.com/withastro/astro/pull/17830) [`a937b0d`](https://github.com/withastro/astro/commit/a937b0d3ec236c8dd1c62a7a4da7c65b2fdbb7c1) Thanks [@&#8203;florian-lefebvre](https://github.com/florian-lefebvre)! - Adds a new optional `getFontProperties()` callback to font providers

  Font providers can now expose the weights, styles, subsets and formats a font family actually has. Astro uses it when resolving your font configuration to warn about values a provider cannot serve, for example a weight a font family does not offer.

  All built-in providers implement it. If you maintain a custom font provider, implementing this callback is optional for now but it will be required in Astro 8:

  ```ts
  import type { FontProvider } from 'astro';

  const provider: FontProvider = {
  	name: 'my-provider',
  	resolveFont: ({ familyName }) => {
  		// ...
  	},
  	getFontProperties: ({ familyName }) => ({
  		weights: ['400', '700'],
  		styles: ['normal', 'italic'],
  		subsets: ['latin'],
  		formats: ['woff2'],
  	}),
  };
  ```

- [#&#8203;17830](https://github.com/withastro/astro/pull/17830) [`a937b0d`](https://github.com/withastro/astro/commit/a937b0d3ec236c8dd1c62a7a4da7c65b2fdbb7c1) Thanks [@&#8203;florian-lefebvre](https://github.com/florian-lefebvre)! - Adds a `fetch()` function to the font provider `init()` context

  This function requests a provider API, retrying transient failures and more. It lets providers that wrap a 3rd-party unifont provider pass the context to it directly:

  ```ts
  import type { FontProvider } from 'astro';
  import type { InitializedProvider } from 'unifont';
  import { acmeProvider } from '@acme/unifont-provider';

  export function acmeFontProvider(): FontProvider {
  	const provider = acmeProvider();
  	let initializedProvider: InitializedProvider | undefined;
  	return {
  		name: provider._name,
  		async init(context) {
  			initializedProvider = await provider(context);
  		},
  		// ...
  	};
  }
  ```

- [#&#8203;18015](https://github.com/withastro/astro/pull/18015) [`0b30239`](https://github.com/withastro/astro/commit/0b302391059dbc4f8ece24d7b44599c7ec9fef24) Thanks [@&#8203;florian-lefebvre](https://github.com/florian-lefebvre)! - Adds `experimental.redirectPage`, letting you provide your own `src/pages/3xx.astro` in place of the redirect page Astro generates in static builds.

  A static site has no server to send an HTTP `Location` header, so Astro generates a small HTML page with a `<meta http-equiv="refresh">` tag for each redirect it builds:

  - Your [`redirects`](https://docs.astro.build/en/reference/configuration-reference/#redirects) entries
  - `Astro.redirect()` calls in prerendered pages
  - i18n redirects

  That page's markup, wording, and refresh delay were fixed, so you could not brand or translate it.

  To enable this feature, add the experimental flag to your Astro config:

  ```js
  // astro.config.mjs
  import { defineConfig } from 'astro/config';

  export default defineConfig({
    experimental: {
      redirectPage: true,
    },
  });
  ```

  Then create `src/pages/3xx.astro`. Astro renders it once per redirect, passing that redirect's details as props:

  ```astro
  ---
  // src/pages/3xx.astro
  import type { RedirectPageProps as Props } from 'astro';

  const { from, to, status, delay } = Astro.props;
  ---

  <html lang="en">
    <head>
      <meta http-equiv="refresh" content={`${delay};url=${to}`} />
      <meta name="robots" content="noindex" />
      <title>Redirecting…</title>
    </head>
    <body>
      <p>This page has moved. <a href={to}>Continue to {to}</a>.</p>
    </body>
  </html>
  ```

  Your page must render a `<meta http-equiv="refresh">` tag pointing at `to`, because in a static build that tag is the redirect. Astro logs a warning during the build if it is missing.

  See the [experimental redirect page documentation](https://docs.astro.build/en/reference/experimental-flags/redirect-page/) for more information.

- [#&#8203;18265](https://github.com/withastro/astro/pull/18265) [`910ee69`](https://github.com/withastro/astro/commit/910ee69147c4c2460f2b31a294bc70c5269f44d4) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Adds a `notFound()` handler to `astro/fetch` and `astro/hono` that renders the custom 404 page when no route matches, including a prerendered `404.astro`

  Add it before `pages()` in a custom worker or server entrypoint that does not run inside `App.render`, such as a Hono app used directly as a Cloudflare worker. Without it, `pages()` and `middleware()` return an empty 404 with an internal `X-Astro-Error` header for unmatched routes. `astro()` already includes this handling.

  ```ts
  import { Hono } from 'hono';
  import { notFound, pages } from 'astro/hono';
  import { cf } from '@astrojs/cloudflare/hono';

  const app = new Hono();
  app.use(cf());
  app.use(notFound());
  app.use(pages());
  export default app;
  ```

- [#&#8203;18177](https://github.com/withastro/astro/pull/18177) [`7d814e5`](https://github.com/withastro/astro/commit/7d814e5ac3e7c84b4e4fd4e6c7cc6820f553742c) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Adds support for separate `build` and `runtime` image services

  `image.service` now also accepts a `build` and a `runtime` service. The `build` service optimizes images on prerendered pages when you build your site, and is also used during development. The `runtime` service handles images on on-demand rendered pages and the image endpoint of your deployed site.

  The following example uses Sharp to optimize images on prerendered pages, and an image CDN for on-demand rendered pages:

  ```js
  // astro.config.mjs
  import { defineConfig } from 'astro/config';

  export default defineConfig({
    image: {
      service: {
        build: { entrypoint: 'astro/assets/services/sharp' },
        runtime: { entrypoint: 'my-image-cdn-service' },
      },
    },
  });
  ```

##### Changes for integration authors

`config.image.service` keeps the shape the user configured it with. When a project sets `build` and `runtime` services, `config.image.service.entrypoint` and `config.image.service.config` are `undefined`.

If your integration reads `image.service`, check for the `runtime` property to get the service you need:

```ts
'astro:config:done': ({ config }) => {
  const { service } = config.image;
  const runtimeService = 'runtime' in service ? service.runtime : service;

  if (runtimeService.entrypoint === 'astro/assets/services/sharp') {
    // ...
  }
},
```

Setting `image.service` with `updateConfig()` replaces the existing service instead of merging with it when the two use different shapes. For example, setting a single service in a project that uses `build` and `runtime` services replaces both.

- [#&#8203;18277](https://github.com/withastro/astro/pull/18277) [`2715958`](https://github.com/withastro/astro/commit/2715958666b0a706b069d0592da3a070b3796a9b) Thanks [@&#8203;florian-lefebvre](https://github.com/florian-lefebvre)! - Increases the minimum Node.js version to 22.22.0

  The minimum supported Node.js version is now 22.22.0, the latest Node.js 22 release supported by StackBlitz. This change is in line with Astro's [Node.js support policy](https://docs.astro.build/en/upgrade-astro/#support).

- [#&#8203;18313](https://github.com/withastro/astro/pull/18313) [`71e2b24`](https://github.com/withastro/astro/commit/71e2b24bb365e5a8809fc0432716f91ecc6d8ab5) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Allows integrations to control where Astro writes client, server, and prerender build output.

  Custom prerenderers can access the final output locations through the new `outputDirectories` context:

  ```ts
  setPrerenderer((defaultPrerenderer, { outputDirectories }) => {
    const { client, server, prerender } = outputDirectories

    return createPrerenderer({
      defaultPrerenderer,
      client,
      server,
      prerender,
    })
  })
  ```

- [#&#8203;18177](https://github.com/withastro/astro/pull/18177) [`7d814e5`](https://github.com/withastro/astro/commit/7d814e5ac3e7c84b4e4fd4e6c7cc6820f553742c) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Lets custom prerenderers report the images used on prerendered pages

  Astro now generates images on prerendered pages from the image information that a prerenderer's `getStaticPaths()` and `render()` return. If your prerenderer wraps Astro's default one, pass this information through:

  ```js
  setPrerenderer((defaultPrerenderer) => ({
    name: 'my-prerenderer',
    async setup() {
      await defaultPrerenderer.setup?.();
    },
    async getStaticPaths() {
      const result = await defaultPrerenderer.getStaticPaths();
      const { paths, metadata } = Array.isArray(result) ? { paths: result } : result;
      return { paths: paths.filter(({ pathname }) => !pathname.startsWith('/drafts')), metadata };
    },
    render(request, options) {
      return defaultPrerenderer.render(request, options);
    },
    async teardown() {
      await defaultPrerenderer.teardown?.();
    },
  }));
  ```

  Returning a plain array from `getStaticPaths()` or a plain `Response` from `render()` still works, but is deprecated: images used on those pages are not generated.

- [#&#8203;17932](https://github.com/withastro/astro/pull/17932) [`b905ff1`](https://github.com/withastro/astro/commit/b905ff1a8649b7a9a9056d9b05ca25ae7b3c07a1) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Adds support for experimental parallel prerendering

  This experimental feature makes `astro build` render your static pages in parallel, using multiple CPU cores at once instead of one. On sites with many pages, this can significantly reduce build times, at the cost of higher memory usage.

  To enable this feature, add the experimental flag in your Astro config:

  ```js
  // astro.config.mjs
  import { defineConfig } from 'astro/config';

  export default defineConfig({
    experimental: {
      parallelPrerender: true,
    },
  });
  ```

  By default, Astro uses all available CPU cores but one. Each additional worker increases the memory used by your build. If your build runs out of memory, or does not get faster, set `workers` to a lower number:

  ```js
  // astro.config.mjs
  import { defineConfig } from 'astro/config';

  export default defineConfig({
    experimental: {
      parallelPrerender: {
        workers: 4,
      },
    },
  });
  ```

  Each worker renders as many pages at once as your [`build.concurrency`](https://docs.astro.build/en/reference/configuration-reference/#buildconcurrency) setting allows.

  This feature has no effect when your adapter provides its own way of prerendering pages. Among official adapters, this only applies to `@astrojs/cloudflare`. Astro logs a warning during the build when the flag is ignored.

  For more information on enabling and using this feature in your project, see the [experimental parallel prerendering docs](https://docs.astro.build/en/reference/experimental-flags/parallel-prerender/).

##### Patch Changes

- [#&#8203;18313](https://github.com/withastro/astro/pull/18313) [`71e2b24`](https://github.com/withastro/astro/commit/71e2b24bb365e5a8809fc0432716f91ecc6d8ab5) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes deployment integrations being unable to use Vite manifests when preparing build output

- [#&#8203;18270](https://github.com/withastro/astro/pull/18270) [`0c3bf11`](https://github.com/withastro/astro/commit/0c3bf116ee70aae4772313fc167a372c7d54869e) Thanks [@&#8203;ArmandPhilippot](https://github.com/ArmandPhilippot)! - Fixes the JSDoc for CSP utilities to point to the render context reference in docs.

- [#&#8203;18368](https://github.com/withastro/astro/pull/18368) [`1f04637`](https://github.com/withastro/astro/commit/1f04637a6ca23b59e8982424248ead47d6a3ec31) Thanks [@&#8203;43081j](https://github.com/43081j)! - Replaces internal use of `find-proc` with `tinyps`.

- [#&#8203;18355](https://github.com/withastro/astro/pull/18355) [`59b9cc0`](https://github.com/withastro/astro/commit/59b9cc00726495bb45f5c4b000dbbb7b5a19d662) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes prerender errors being silently swallowed when using a custom `src/fetch.ts` with an adapter that prerenders in its own runtime, such as `@astrojs/cloudflare`. Previously, a page that threw during prerendering was written as an empty HTML file and the build succeeded. The build now fails with the underlying error.

- [#&#8203;18177](https://github.com/withastro/astro/pull/18177) [`7d814e5`](https://github.com/withastro/astro/commit/7d814e5ac3e7c84b4e4fd4e6c7cc6820f553742c) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixes original images being kept despite only `width` or `height` being read.

- [#&#8203;18353](https://github.com/withastro/astro/pull/18353) [`af54bfa`](https://github.com/withastro/astro/commit/af54bfaebff9180cb96822c0da11737b4b26e65a) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `glob()` loader swallowing rendering errors during content sync, which allowed `astro build` to exit successfully (code 0) even when a remark/rehype plugin threw an error

- [#&#8203;18271](https://github.com/withastro/astro/pull/18271) [`23e8e28`](https://github.com/withastro/astro/commit/23e8e28c22effe006fe19abb193802e2fec8eaab) Thanks [@&#8203;ArmandPhilippot](https://github.com/ArmandPhilippot)! - Fixes the `sync` command description in `astro help`, which only mentioned content collections.

- Updated dependencies \[[`b7a1bd9`](https://github.com/withastro/astro/commit/b7a1bd99ac7c68cf36078058f15f1bd1fab4cbe8), [`2715958`](https://github.com/withastro/astro/commit/2715958666b0a706b069d0592da3a070b3796a9b)]:
  - [@&#8203;astrojs/internal-helpers](https://github.com/astrojs/internal-helpers)@0.13.0
  - [@&#8203;astrojs/markdown-satteri](https://github.com/astrojs/markdown-satteri)@0.4.4
  - [@&#8203;astrojs/telemetry](https://github.com/astrojs/telemetry)@3.4.0

</details>

<details>
<summary>pnpm/pnpm (pnpm)</summary>

### [`v12.15.0`](https://github.com/pnpm/pnpm/releases/tag/v12.15.0): pnpm 12.15

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.14.0...v12.15.0)

This release lets `pnpm-workspace.yaml` delegate settings to other files and config dependencies with `include`, adds `lockfile.integrityTarget: tar` and tar-registry support, accepts zstd-compressed registry responses, and honors `SOURCE_DATE_EPOCH` in `pnpm deploy` and `pnpm install`. It also rejects registry metadata that names a different package than the one requested and speeds up workspace installs and macOS file linking.

##### Minor Changes

- `pnpm-workspace.yaml` can now delegate settings to other YAML files and to config dependencies through a new `include` field. Each source may define only the settings the root manifest delegates to it. Every setting has one owner. Commands that change settings write each one to the file that owns it. A relative path in an included file is relative to that file. See [Splitting Settings Across Files](https://pnpm.io/config-includes).

  A config dependency supplies its settings through the YAML file named in the `pnpm.config` field of its `package.json`. The new `bootConfig` setting sets the release-age and trust policy pnpm uses to install config dependencies and the pnpm version from `packageManager`.

- Added the `lockfile.integrityTarget` setting. With `integrityTarget: tar`, `pnpm-lock.yaml` pins the hash of every package's uncompressed tar, so the lockfile no longer changes when a registry recompresses its tarballs or serves them as tars. pnpm learns a version's tar hash from the store or by downloading it once. `pnpm audit signatures` ties the tar hash to the signed `.tgz` integrity.

  ```yaml title="pnpm-workspace.yaml"
  lockfile:
    integrityTarget: tar
  ```

- pnpm can now install from a registry that serves uncompressed tars with zstd or gzip content coding. `pnpm-lock.yaml` records the hash of each tar. Declare such a registry with `serverType: pnpr` in `registries` to keep tarball URLs out of the lockfile. See [Tar registries](https://pnpm.io/registries#tar-registries).

  pnpm now decodes the content coding of tarball downloads itself. It rejects a zstd response whose window is larger than 8 MiB.

  Added the `maxTarballUnpackedSize` setting. It caps the bytes the files of one package may unpack to, 4 GiB by default.

- Registry revisions now always pin the hash of the uncompressed tar, the original included. pnpm records an original selected through the revision protocol, for example with a `+r0` specifier, as `revision: 0` in the lockfile and fetches it from the registry's digest route. pnpm checks a revision's tar whether the registry sends it as a tar, gzip, or zstd. Revision metadata must list revision 0 and mark the selected revision. pnpm rejects incomplete revision metadata with `ERR_PNPM_MALFORMED_METADATA`.

- pnpm now accepts zstd-compressed responses. Registries that serve zstd send package metadata in fewer bytes than with gzip, most of all the full metadata that settings such as `minimumReleaseAge` and `trustPolicy` read.

- `pnpm deploy` and `pnpm install` now use the `SOURCE_DATE_EPOCH` environment variable as an upper bound for timestamps in `node_modules/.modules.yaml` and `node_modules/.pnpm-workspace-state-v1.json`. With an equivalently prepared deploy target and an epoch no later than the timestamps that would otherwise be recorded, deploying the same project twice produces identical files [#&#8203;17171](https://github.com/pnpm/pnpm/issues/17171).

- `pnpm update --interactive` now highlights the row under the cursor in cyan while keeping the colors of its version changes.

##### Patch Changes

##### Security

- pnpm now fails with `ERR_PNPM_REGISTRY_NAME_MISMATCH` if a registry returns metadata for a package other than the one requested. Before, pnpm installed the package under the name in the metadata, so `allowBuilds` rules for the requested package did not apply to it.

- `minimumReleaseAgeExcludePrune` and `trustPolicyExcludePrune` now keep exclusions for resolved configuration dependencies and their transitive dependencies [#&#8203;17142](https://github.com/pnpm/pnpm/issues/17142).

##### Resolving dependencies

- When `pnpm install` resolves a dependency again, it now reuses a version that the install already resolved for the same package, as a fresh install does. Before, it kept the version the lockfile pinned and added a second copy of the package. A locked version still stays when nothing else in the install prefers another version. To pin a transitive dependency on purpose, use `overrides` [#&#8203;17084](https://github.com/pnpm/pnpm/issues/17084).

- When another workspace project adds a different version of a package, a project's auto-installed peer on that package now moves to the version a fresh install picks. It used to stay on its locked version while any other project still accepted that version [#&#8203;17058](https://github.com/pnpm/pnpm/issues/17058).

- A package that lists the same dependency in `dependencies` and as an optional peer now gets the peer bound when a project adds a provider for it later. The lockfile now records every peer a package declares, including one its own dependency supplies [#&#8203;17056](https://github.com/pnpm/pnpm/issues/17056).

- `pnpm install --prod` and `pnpm deploy --prod` no longer drop a dependency that a package declares both as an optional peer and as its own dependency, when the package resolved it as its own dependency and a dev dependency provides the same package under another alias.

- `pnpm install` with an existing lockfile and a second `pnpm dedupe` now keep optional peer bindings that point into a dependency cycle or back into the dependent package. Before, the second run dropped the optional peer binding from the lockfile snapshot key.

- `pnpm install` and `pnpm dedupe` now preserve own-dependency and peer-dependency bindings when reusing a lockfile whose peer suffixes were hashed by `peersSuffixMaxLength`.

  Upgrading a direct dependency in one workspace project now refreshes matching transitive pins in sibling projects during the same `pnpm install` pass.

- With `resolvePeersFromWorkspaceRoot: false`, a workspace project no longer binds a peer to a version that only another project's dependencies provide. pnpm now auto-installs a version that satisfies the peer range for that project. Before, the project got a version outside the range, with no peer warning.

- `pnpm install`, `pnpm add`, and `pnpm update` now reuse the lockfile's resolution for dependencies that take part in a dependency cycle, such as `mlly` and `pkg-types`. They re-resolved those packages and everything that depends on them from the registry before [pnpm/tasks#130](https://github.com/pnpm/tasks/issues/130).

- pnpm now measures a `pnpm.overrides` entry written as a `workspace:` path, such as `workspace:./packages/foo`, from the directory holding `pnpm-workspace.yaml`. It used to be measured from each package the override rewrote. The install then linked a directory that does not exist, or failed if workspace packages were injected [#&#8203;17010](https://github.com/pnpm/pnpm/issues/17010).

- `pnpm install` now removes config dependencies that are no longer declared, including when the entire `configDependencies` setting is removed. Frozen installs reject a lockfile that still records removed config dependencies.

- `pnpm install --update-checksums` now re-resolves every locked package and records the integrity the registry reports now.

- `pnpm add` and `pnpm install` now accept `gist:<id>` dependencies and GitHub Gist URLs, and install them from the gist's archive. `pnpm pkg fix` normalizes a `gist:` repository the way `npm pkg fix` does, `pnpm licenses` links a gist package to its gist page, and `pnpm sbom` reports the repository of a package whose `repository` field is a `gist:` shorthand.

- `pnpm add` now reads the package name correctly from a tarball URL under a registry URL that has a path, such as `https://example.com/npm/`, and installs a registry tarball URL with a malformed percent escape as a plain tarball URL. Before, the registry path became part of the name, so a scoped package failed with `ERR_PNPM_INVALID_PACKAGE_NAME`.

- With `minimumReleaseAge` set, pnpm now revalidates a package's cached full metadata with a single ETag request so an unchanged registry answers with `304`, even when the registry does not list a publish time for every version. Previously, pnpm downloaded that metadata again whenever the cached copy was older than `minimumReleaseAge`. With `resolutionMode` set to `lowest-direct` or `time-based`, pnpm also reuses that metadata across every workspace project that depends on the package.

- When pnpm revalidates cached registry metadata, it now sends `If-Modified-Since` when the registry's modification time is a date without a time, and no longer crashes when the modification time is before 1970.

- Added protocol versioning between the pnpm client and pnpr server, verified applied resolution policies in resolution responses, and preserved structured error codes across the wire.

##### Performance

- Sped up `pnpm install` on macOS. On a 12-core Mac, installing 1352 packages from a warm store took 1.3 seconds, down from 2.2. pnpm now writes package files into `node_modules` with 4 threads on macOS, whatever the number of CPU cores. Set the `PNPM_MACOS_LINK_THREADS` environment variable to use a different number of threads, or to `0` to write files with the threads pnpm uses for the rest of the install.

- `pnpm install` is faster and uses less memory in large workspaces with `sharedWorkspaceLockfile: false`. Each project's install no longer reads the manifests of every other workspace project again. Installs that wait for their workspace dependencies now count toward `workspaceConcurrency` [#&#8203;16966](https://github.com/pnpm/pnpm/issues/16966).

- Sped up workspace project discovery, dependency resolution, lockfile up-to-date checks, and peer dependency checks in large workspaces [#&#8203;16839](https://github.com/pnpm/pnpm/issues/16839) [pnpm/tasks#9](https://github.com/pnpm/tasks/issues/9). On a workspace with 6,833 projects, the lockfile up-to-date check uses about 1 second less CPU time. The peer dependency check at the end of an install now checks linked workspace projects against the manifests already in memory, without reading each `package.json` again.

- Sped up bin linking and build planning during `pnpm install`. Package binary targets and shebang runtimes are now precalculated during tarball extraction and served in `pnpr` registry metadata alongside verified `requiresBuild`, tarball size, and file-count metadata.

- Lowered peak memory when pnpm downloads many packuments, such as during lockfile verification with `trustPolicy` on Linux. In one 1,800-entry workspace, a lockfile update now peaks at 1.8 to 2.0 GB. It peaked at 2.6 to 3.7 GB before [#&#8203;17020](https://github.com/pnpm/pnpm/issues/17020).

- `pnpm install` in a Cargo workspace skips crates that an earlier install already unpacked into the store. Before, a repeat install processed every crate in `Cargo.lock` again. `pnpm install --force` unpacks every crate again [pnpm/tasks#69](https://github.com/pnpm/tasks/issues/69).

##### Linking node_modules and workspaces

- Concurrent installs that import the same package into one project now all complete. One of them used to fail with `ENOTEMPTY` when its copy of the package collided with the copy another install had already placed [pnpm/tasks#48](https://github.com/pnpm/tasks/issues/48).

- `pnpm install` now succeeds when `node_modules` is a symlink to an existing directory. Dependency hoisting previously rejected a symlinked `node_modules` as an invalid destination [#&#8203;17157](https://github.com/pnpm/pnpm/issues/17157).

- A filtered first install under the isolated linker now links every workspace project by name into `node_modules/.pnpm/node_modules`, not only the selected ones [pnpm/tasks#155](https://github.com/pnpm/tasks/issues/155).

- With `nodeLinker: hoisted`, a filtered install such as `pnpm --filter app add <pkg>` keeps the root `node_modules` links and bins of the workspace projects it did not select. A project with no dependencies of its own lost them until the next full install.

- `pnpm install --filter` with `nodeLinker: hoisted` and `--prod` or `--dev` now preserves previously installed dependency groups for unselected workspace projects [pnpm/tasks#164](https://github.com/pnpm/tasks/issues/164). Repeat filtered installs also re-resolve when a transitive injected workspace dependency or a linked dependency's version changes.

- With `sharedWorkspaceLockfile: false`, `pnpm install` now runs the workspace root's pnpmfile for every project, after the project's own pnpmfile. Before, it ran only the pnpmfile in the project's directory.

- `pnpm install` and `pnpm peers check` now detect peer dependency issues and report linked package versions in linked projects that use `package.json5` or `package.yaml` [pnpm/tasks#172](https://github.com/pnpm/tasks/issues/172).

- `pnpm install` and `pnpm peers check` no longer report an unmet peer when a workspace package's peer is provided by a remote tarball URL. pnpm now compares the peer range with the version in the tarball's manifest [#&#8203;17037](https://github.com/pnpm/pnpm/issues/17037).

- `pnpm prune` now removes extraneous direct packages from `node_modules` when `package.json` and `pnpm-lock.yaml` are already in sync. `pnpm prune` also honors `--filter`, `--recursive`, `sharedWorkspaceLockfile: false`, and the `trustLockfile` setting and `--trust-lockfile` flag. With the lockfile trusted, `pnpm prune --prod` works offline when every package is in the store [#&#8203;16999](https://github.com/pnpm/pnpm/issues/16999).

##### Injected workspace packages

- `pnpm install --frozen-lockfile` now fails with `ERR_PNPM_OUTDATED_LOCKFILE` when a local directory dependency or injected workspace package changes a dependency to a different tarball URL or git commit [#&#8203;17129](https://github.com/pnpm/pnpm/issues/17129). It also fails when an injected workspace package changes a dependency's named-registry range, such as `work:^2.0.0`, to one the locked version no longer satisfies.

- `pnpm install --frozen-lockfile` now accepts the lockfile it wrote for a `file:` dependency on a directory without a `package.json`. It also accepts the lockfile for an injected workspace package that bundles a dependency in `bundledDependencies`, lists a dependency in both `dependencies` and `optionalDependencies`, or publishes from a `publishConfig.directory` whose `package.json` lists other dependencies than the project's own. Before, these failed with `ERR_PNPM_OUTDATED_LOCKFILE`.

- The lockfile now records a `catalog:` peer dependency of an injected workspace package as written in its `package.json`. It recorded the catalog's range before, so editing the catalog changed the consumer's lockfile entry [pnpm/tasks#153](https://github.com/pnpm/tasks/issues/153).

- `pnpm install` now resolves a git, tarball, or tag dependency of an injected workspace package again when its spec changes. Before, it kept the old version.

- Repeat installs and `verifyDepsBeforeRun` now re-check projects that inject a modified workspace package, including when `sharedWorkspaceLockfile` is `false` [#&#8203;17007](https://github.com/pnpm/pnpm/issues/17007), and accept aliased `workspace:` ranges on linked dependencies.

- An injected workspace package that was linked now becomes a copy when the project that depends on it starts providing one of its peers at a version the package's own workspace context lacks. The link used to stay until that dependency was updated, so the package could not find the peer the project provides [#&#8203;17057](https://github.com/pnpm/pnpm/issues/17057).

- An injected workspace package now keeps only the files its manifest lists after a lifecycle script or a script named in `syncInjectedDepsAfterScripts` rebuilds it. Before, these refreshes copied every file of the package directory into the injected copy, including files that `files` or `.npmignore` leave out. With `deployAllFiles: true` the copy still gets every file.

- A script listed in `syncInjectedDepsAfterScripts` now keeps a package's links to its own files as links in the injected copies, the way `pnpm install` writes them, and updates those copies when `sharedWorkspaceLockfile` is `false`. Before, a directory link the script added became a real directory or went missing with `deployAllFiles`, and with `sharedWorkspaceLockfile: false` the copies kept the files from the last install.

##### Running scripts and checking dependencies

- Pressing Ctrl+C during `pnpm -r run` or `pnpm --filter <pkg> run` no longer reports `ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL`. pnpm now ends with the interrupted script's status, such as 130 for a script that SIGINT ended on Linux or macOS [#&#8203;16964](https://github.com/pnpm/pnpm/issues/16964).

- With `enableGlobalVirtualStore`, a Node.js resolve hook that a script registers now sees the importer as `context.parentURL` after pnpm's `NODE_PATH` fallback fails to find a bare specifier. Hooks that resolve tsconfig `paths` aliases from the importer failed with `ERR_MODULE_NOT_FOUND` [#&#8203;16979](https://github.com/pnpm/pnpm/issues/16979).

- `pnpm run`, `pnpm exec`, and `pnpm restart` now pass the install flags they were given, such as `--lockfile-dir`, `--modules-dir`, `--store-dir`, `--offline`, and `--ignore-scripts`, to the `pnpm install` that `verifyDepsBeforeRun: install` starts. When that install leaves the dependencies out of date, pnpm now prints a warning.

- A repeated `pnpm install --filter` now finishes without reinstalling when the selected projects are up to date, and so does `pnpm install` once filtered commands have installed every project. After a filtered install, `pnpm run` and `pnpm exec` now install a selected project whose dependencies changed in between [#&#8203;17011](https://github.com/pnpm/pnpm/issues/17011), require the workspace root when a filtered install with `pruneDirectDependencies: true` skipped it [pnpm/tasks#181](https://github.com/pnpm/tasks/issues/181), and preserve the recorded ignored build scripts of unselected projects.

- The check that runs before a script now holds the workspace projects that the selected project depends on, including with `sharedWorkspaceLockfile: false` and for workspace dependencies declared with `link:`. `--filter=<project>...` now selects `link:` dependencies as well. In a workspace that has no `package.json` at its root, `pnpm run` and `pnpm exec` no longer reinstall before every command when the dependencies are up to date.

- `verifyDepsBeforeRun` and repeat `pnpm install` runs now apply `overrides` before comparing a modified `package.json` with `pnpm-lock.yaml` [#&#8203;17127](https://github.com/pnpm/pnpm/issues/17127). `pnpm install` with `optimisticRepeatInstall` now re-runs when `configDependencies` changed, `verifyDepsBeforeRun` reports `node_modules` out of date when `useGitBranchLockfile` is enabled and the branch lockfile is missing, and in a single-project repository both checks record a successful lockfile check so later runs skip it until the lockfile changes [#&#8203;16993](https://github.com/pnpm/pnpm/issues/16993).

- `pnpm install` and `verifyDepsBeforeRun` now compare manifests, lockfiles, and patch files by content hash. They notice an edit that kept the file's modification time, as `cp -p`, `rsync -a`, or an archive extraction leave it, and a patch file that was copied or touched without changing its content no longer marks dependencies as outdated [#&#8203;16988](https://github.com/pnpm/pnpm/issues/16988).

##### Deploying, packing, and other commands

- `pnpm deploy` now deploys `file:` dependencies that live outside the workspace directory. It failed with "Refusing to deploy unsafe lockfile path" [#&#8203;16983](https://github.com/pnpm/pnpm/issues/16983).

- `pnpm deploy` now records the peer dependencies of the workspace packages it copies into the deployed lockfile. Before, pnpm rejected that lockfile with `--frozen-lockfile` when a deployed workspace package declared a peer and `injectWorkspacePackages` was off [#&#8203;17093](https://github.com/pnpm/pnpm/issues/17093).

- `pnpm install --frozen-lockfile` and `verifyDepsBeforeRun` now succeed inside a directory created by `pnpm deploy`. `pnpm deploy` writes self-contained workspace and lockfile settings, prunes unused `patchedDependencies`, and preserves workspace-level dependency resolutions on deployed directory dependencies.

- On macOS, `pnpm deploy` no longer writes a second, unused copy of every package to `node_modules/.pnpm/@` in the deploy directory [#&#8203;17116](https://github.com/pnpm/pnpm/issues/17116).

- `pnpm patch-commit` and `pnpm install` now apply a patch that renames or moves a file of the patched package. Such a patch failed with "rename/copy operations in patches are not yet supported".

- In workspaces with `sharedWorkspaceLockfile: false`, `pnpm patch`, `pnpm patch-commit`, and `pnpm patch-remove` now resolve patch files and `patchedDependencies` entries at the workspace root. `pnpm install` checks configured patches across all workspace projects before reporting unused patches.

- `pnpm pack` and `pnpm publish` no longer include editor swap files such as `.*.swp`, macOS `._*` files, `.lock-wscript`, `.wafpickle-*`, `build/config.gypi`, or `archived-packages/` in the tarball. Naming one of these files in `files` still includes it [#&#8203;16955](https://github.com/pnpm/pnpm/issues/16955).

- `pnpm pack` and `pnpm publish` now support extended glob patterns and brace ranges such as `part{1..3}.js` and `part{a..c}.js`, including descending ranges, steps, and zero padding, in `files`, `.npmignore`, and `.gitignore`. Explicitly listed internal directory symlinks are preserved below excluded directories, entry points honor nested ignore files, ignore negations can re-include default-excluded logs and backup files, and nested lockfiles follow the package's file selection rules.

- Trusted publishing with OIDC now works with registries whose URL has a path, such as `https://registry.example/npm/private/`. pnpm previously sent the token exchange request to the root of the registry host.

- `pnpm deprecate` and `pnpm unpublish` now work for packages whose registry metadata is larger than 10 MiB, such as `typescript`. They accept up to 50 MiB, the same limit as `pnpm owner`.

- `pnpm owner ls` now lists the owners of a package on the npm registry. It reported every package as not found.

- `pnpm licenses list --prod` now includes optional dependencies, including transitive ones. Pass `--no-optional` to leave them out. `pnpm licenses list` also reports no licenses for workspace projects not recorded in the lockfile, errors when `pnpm-lock.yaml` is missing, and formats empty results as the requested text or JSON [pnpm/tasks#174](https://github.com/pnpm/tasks/issues/174).

- `pnpm why` now reads each selected workspace project's lockfile and modules directory when `sharedWorkspaceLockfile` is `false` [pnpm/tasks#169](https://github.com/pnpm/tasks/issues/169).

- `pnpm pkg fix` now converts a `repository` string such as `github:pnpm/example` to the object form, as `npm pkg fix` does. It also normalizes a GitHub, GitLab, or Bitbucket repository URL the way `npm pkg fix` does [#&#8203;16980](https://github.com/pnpm/pnpm/issues/16980).

##### Configuration and setting up pnpm

- Registry credentials and TLS settings passed with `--config`, such as `--config.//registry.example.com/:_authToken=<token>`, are now applied. They take precedence over the same settings in `.npmrc` files.

- pnpm now reads only the settings it needs to decide whether to switch to the pnpm version a project pins. A setting outside them can no longer fail that decision or change its outcome. For example, `pnpm --version` no longer fails in a pinned project whose `pnpm-workspace.yaml` has a setting this pnpm cannot read. Projects that pin neither pnpm nor a runtime skip this check without reading any settings.

- When pnpm switches to the version a project pins, an option only the pinned pnpm knows now reaches that pnpm when it comes immediately before the command name, as in `pnpm --new-flag install`. When switching for `pnpm --version` or an unrecognized command line, pnpm also honors `--color`, `--no-color`, `--reporter`, and `--loglevel` wherever they appear on the command line.

- `pnpm self-update` now updates the project's pnpm pin when Homebrew installed pnpm or Corepack runs it, leaving the global pnpm alone [#&#8203;17001](https://github.com/pnpm/pnpm/issues/17001). Run inside a workspace package, `pnpm self-update` updates the pin in the workspace root's manifest, including in `package.yaml` or `package.json5`.

- `pnpm setup` now completes when Windows registry environment values cannot be read or written. It prints PowerShell commands to configure `PNPM_HOME` and `PATH` without registry access [#&#8203;17167](https://github.com/pnpm/pnpm/issues/17167).

- `pnpm setup` now succeeds when it cannot tell which shell configuration file to update, for example in a container where `SHELL` is not set. It installs pnpm and prints the `PNPM_HOME` and `PATH` lines to add yourself. Previously it failed with `ERR_PNPM_UNKNOWN_SHELL`, and so did the installer script at get.pnpm.io [#&#8203;16973](https://github.com/pnpm/pnpm/issues/16973).

- In StackBlitz WebContainers, `pnpm` no longer crashes intermittently with `Parking not supported on this platform`, and running a command that does not exist now reports that the command was not found. Previously it sometimes failed with a generic error.

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.14.0`](https://github.com/pnpm/pnpm/releases/tag/v12.14.0): pnpm 12.14.0

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.13.0...v12.14.0)

This release adds the `sideEffectsCache.exclude` setting, stops `pnpm install` from waiting on the daily update check, and keeps pnpm from aborting with a core dump when the reader of its output exits.

##### Minor Changes

- Added the `sideEffectsCache.exclude` setting for packages whose build depends on something pnpm cannot include in the cache key, such as the system libraries a native addon links against. pnpm builds the listed packages in every project and never restores or saves their builds through the side-effects cache, locally or on a `remoteCache` server. Under the global virtual store, each project gets its own copy of these packages and of the packages that depend on them. Entries use the same `name`, `@scope/*`, and `name@version` patterns as `minimumReleaseAgeExclude` [#&#8203;5271](https://github.com/pnpm/pnpm/issues/5271).

- `pnpm login` now prints the `npm-notice` response header during web-based login. Registries use it to show the verification code that completes the sign-in in the browser.

##### Patch Changes

##### Installing packages

- `pnpm install` and `pnpm add` no longer wait for the daily update check. If the command finishes first, pnpm skips the update notice and checks again next time. On a registry that accepted the connection but never answered, an install that had nothing to do used to take minutes [#&#8203;16839](https://github.com/pnpm/pnpm/issues/16839).

- `pnpm install`, `pnpm add` and `pnpm update` now reuse `pnpm-lock.yaml` when the workspace configures a catalog entry that no dependency references, such as an unused entry or one whose package an `overrides` entry replaces. Before, every resolution in such a workspace resolved all dependencies again from the registry [#&#8203;16923](https://github.com/pnpm/pnpm/issues/16923).

- `pnpm install` now looks up a git dependency's branch or tag once per install, even when many workspace projects depend on it. With `linkWorkspacePackages` enabled, it used to run `git ls-remote` once per project [#&#8203;16899](https://github.com/pnpm/pnpm/issues/16899).

- A filtered install, such as `pnpm install --filter <pkg>`, now keeps the `pnpm-lock.yaml` entries of workspace projects that are missing from disk, as in a sparse checkout. Their importers, packages, and catalog entries stay even when the filter matches every project on disk [#&#8203;16931](https://github.com/pnpm/pnpm/issues/16931).

- pnpm now decides whether a dependency that a package also declares as an optional peer is linked as a dependency or as a peer from the shallowest path that reaches the package. When an existing lockfile records such a dependency as a regular dependency and a newly added dependency now provides the peer, pnpm records it as a peer, as a fresh install does. The lockfile entry of such a package can change on the next install [#&#8203;16901](https://github.com/pnpm/pnpm/issues/16901).

- An install that adds nothing to the store no longer changes the modification time of the store directory. CI caches that check modification times, such as GitLab's, no longer re-upload an unchanged store [#&#8203;16929](https://github.com/pnpm/pnpm/issues/16929).

##### Running commands and scripts

- pnpm no longer aborts with a core dump when the reader of its output has exited, as in `pnpm list | head -1` or `pnpm start 2>&1 | head -1`. The command finishes with its usual exit code, and a failing script's exit code is kept. A write to stdout that fails for another reason, such as a full disk, ends the command with exit code 1 [#&#8203;16904](https://github.com/pnpm/pnpm/issues/16904) [pnpm/tasks#132](https://github.com/pnpm/tasks/issues/132).

- On Windows, `pnpm exec`, `pnpm run`, and commands such as `pnpm nx` now return when the command they run exits, even if it left a detached process running and pnpm's output is redirected or piped. Previously a shell reading that output waited until the detached process, such as the Nx daemon, exited [#&#8203;16930](https://github.com/pnpm/pnpm/issues/16930).

- Commands that do not write the project manifest now leave a missing `package.json` absent. This covers queries such as `pnpm why` and `pnpm outdated`, `pnpm fetch`, `pnpm dedupe --check`, and commands that exit with an error, such as `pnpm rt ls`. These commands used to create one from the initialization template. `pnpm sbom` run from a lockfile alone now reports the root component as `unknown` with version `0.0.0` [#&#8203;16907](https://github.com/pnpm/pnpm/issues/16907).

- `pnpm run` now reports a failed script as a JSON record under `--reporter=ndjson`. It printed a plain `[ELIFECYCLE]` line to stderr.

- `pnpm run` no longer prints `[ELIFECYCLE] Command failed with exit code N.` to stderr when a script fails under `--reporter=silent`, `--silent`, or `--loglevel=silent`.

- `pnpm pipeline --dry-run` no longer writes a run report when no projects are selected. With `--json` it prints `{"tasks": []}` [pnpm/tasks#126](https://github.com/pnpm/tasks/issues/126).

##### Packing and publishing

- `pnpm pack` and `pnpm publish` now ship the whole gitignored directory that `main`, `browser`, or `bin` points into, as npm does. Previously only the `main` and `bin` files themselves were packed, and a gitignored `browser` file was left out [#&#8203;16908](https://github.com/pnpm/pnpm/issues/16908).

- `pnpm pack` and `pnpm publish` now honor a `.npmignore` or `.gitignore` inside a subdirectory when `package.json` has a `files` field. The package root's ignore files and those inherited from the workspace are still skipped [#&#8203;16909](https://github.com/pnpm/pnpm/issues/16909).

##### Setting up pnpm and toolchains

- `--registry`, `--https-proxy`, `--http-proxy`, and `--no-proxy` now apply when pnpm resolves and downloads the pnpm version a project pins in `packageManager`. Before, these lookups went to `https://registry.npmjs.org/`, which a firewall that only allows a private registry blocks [#&#8203;16911](https://github.com/pnpm/pnpm/discussions/16911).

- On Windows, `pnpm install` now installs the Rust toolchain for rustup's default host, so a machine set up with `rustup set default-host x86_64-pc-windows-gnu` gets the MinGW toolchain. Without a default host, pnpm installs the MSVC toolchain for the machine's architecture, as rustup does. This includes a pnpm built for MinGW, such as the MSYS2 package, which has installed the MinGW toolchain since 12.13.0. An x64 pnpm on ARM64 Windows now installs the ARM64 toolchain [#&#8203;16854](https://github.com/pnpm/pnpm/issues/16854).

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE4MS43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

<!-- cloudflare-preview --> Preview: https://pr-611.docs-gitea-com.pages.dev

---------

Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/611
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
2026-10-26 22:30:15 +00:00
Gitea Bot 4ea46e6315 Update the latest api documents (#612)
Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the "update api spec files" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-612.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/612
Co-authored-by: Gitea Bot <[email protected]>
2026-10-26 16:10:40 +00:00
silverwindandLunny Xiao cb424640a2 docs: document Forwarded header and client port for REVERSE_PROXY_LIMIT (#560)
Document https://github.com/go-gitea/gitea/pull/39190, which reads the RFC 7239 `Forwarded` header when `X-Forwarded-For` is absent and keeps the forwarded client port.

- `REVERSE_PROXY_LIMIT`: list `X-Real-IP`, `X-Forwarded-For` and `Forwarded` in the order they are read, and where the client port comes from, also in zh-cn and zh-tw
- Reverse proxies: require the proxy to set `X-Real-IP`, since Caddy, Apache and HAProxy pass a client-sent one through by default, and mention `X-Real-Port` for logging the client port

Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/560
Reviewed-by: Lunny Xiao <[email protected]>
2026-10-23 22:44:51 +00:00
bircniandsilverwind 09bb4cabcf Add documentation for gt, the Gitea CLI (#603)
Adds a CLI product for gt (https://gitea.com/gitea/cli), set up like the runner, with short guides for installation, logging in, CI and scripting. Each command's details stay in gt <command> --help. Until the first release, the docs are served at /cli/; make cut-version PRODUCT=cli VERSION=0.1 adds the release series.

Closes https://gitea.com/gitea/cli/issues/16

<!-- cloudflare-preview --> Preview: https://pr-603.docs-gitea-com.pages.dev

---------

Co-authored-by: silverwind <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/603
Reviewed-by: Lunny Xiao <[email protected]>
Reviewed-by: silverwind <[email protected]>
2026-10-23 12:16:49 +00:00
silverwind 9699ec2c87 docs: clarify that team package permissions cover the whole org (#605)
Packages belong to the owner, so a team's packages permission covers every package of the organization, regardless of the team's repositories. State that in the access restrictions section, matching the team settings change in https://github.com/go-gitea/gitea/pull/39953.

The old note announced a dedicated team permission for finer control, which has existed since the packages unit was added, so it is replaced.

Reviewed-on: https://gitea.com/gitea/docs/pulls/605
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-22 23:46:15 +00:00
silverwindandbircni c00af83676 Document the artifact retention limit (#602)
Documents https://github.com/go-gitea/gitea/pull/39894 for main and 28. Workflows can request a shorter artifact retention, down to 1 day, and `github.retention_days` carries `ARTIFACT_RETENTION_DAYS`, empty when artifacts are kept forever.

---------

Co-authored-by: bircni <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/602
Reviewed-by: bircni <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-22 20:05:39 +00:00
silverwind c9282b96da Clarify reverse proxy authentication requirements (#604)
Document that reverse proxy authentication requires Gitea to be reachable only through the authenticating proxy, and which routes each setting covers. Companion to https://github.com/go-gitea/gitea/pull/39940.

_Written by Claude._

Reviewed-on: https://gitea.com/gitea/docs/pulls/604
Reviewed-by: bircni <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-22 16:33:31 +00:00
49d912f7fb docs: fix repository path in binary install restore example (#601)
Fixes the binary-install restore example in the Backup and Restore docs.

The default `[repository] ROOT` is `{APP_DATA_PATH}/gitea-repositories`, but the example restored repos to `/var/lib/gitea/data/repositories/`, so restored repositories did not show up. Changed it to `/var/lib/gitea/data/gitea-repositories/`.

The Docker and Docker-rootless examples are unchanged: their app.ini templates set `[repository] ROOT` explicitly, so their paths are already correct.

Refs go-gitea/gitea#39736

---------

Co-authored-by: silverwind <[email protected]>
Co-authored-by: silverwind <[email protected]>
Co-authored-by: souvik-biswas-dev <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/601
Reviewed-by: silverwind <[email protected]>
Co-authored-by: souvikbiswasdev <[email protected]>
2026-10-22 03:46:06 +00:00
398f418387 docs: document protected branch deletion and system users (#583)
Documents protected branch deletion and system users in push, force-push and deletion allowlists, added in https://github.com/go-gitea/gitea/pull/39243 and https://github.com/go-gitea/gitea/pull/39735 (both merged).

Updates the Actions token permissions guide and audit actor names to match.

---------

Co-authored-by: silverwind <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/583
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Enoque Duarte <[email protected]>
2026-10-22 03:43:37 +00:00
silverwind be6aefc7e8 Simplify the runner docs and fix their outdated facts (#600)
The runner pages had drifted from the runner. They claimed Podman is unsupported, a registration retry limit of 10, a `container.env` proxy override that has no effect, and they used the deprecated `generate-config` command, while the actual instructions were buried under implementation details.

The develop and 5.x pages are rewritten from the current runner sources (`main` is `v5.2.0`). They are shorter and aimed at operators, with a new page covering what jobs get. The reference generator now documents the `config` command, and the quickstart pages in every language use the `gitea-runner` binary name.

Reviewed-on: https://gitea.com/gitea/docs/pulls/600
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-21 05:25:45 +00:00
bircni a874918bb7 Document runner 4 and 5, regenerate the 28.2.0 api documents (#599)
The 28.2.0 bump in #594 only changed the version string of the api documents, so they still listed the 28.1.0 endpoints. They are now regenerated from v28.2.0 (mostly new `423 repoArchivedError` responses).

The runner docs stopped at 3.3.0 while the runner is at 5.1.1:

- cut the runner `4` and `5` series, `/runner/` now serves 5.1.1 and `/runner/4/` 4.1.0, the `3` series is bumped to 3.5.0
- series specific image tags and versions in the new copies, the `3` series no longer claims the `latest` tag
- 4.0 and 5.0 sections in the upgrade guide, and the Git 2.34.1 requirement of 5.0 in the requirements
- regenerated every reference page from the newest stable tag of its series

Reviewed-on: https://gitea.com/gitea/docs/pulls/599
Reviewed-by: TheFox0x7 <[email protected]>
2026-10-20 19:19:28 +00:00
Renovate Bot 5304217222 chore(deps): update dependencies (#595)
Co-authored-by: Renovate Bot <[email protected]>
2026-10-20 18:53:10 +00:00
Shudhanshu Singh 88356280ec docs: mention release reactions in the REACTIONS setting (#598)
Documents the `[ui] RELEASE_REACTIONS` setting added in https://github.com/go-gitea/gitea/pull/38415, which sets the reactions available on releases (default `+1, laugh, hooray, heart, rocket, eyes`). `REACTIONS` now only covers issues, pull requests and comments. Updated in English, 简体中文 and 繁體中文.

Reviewed-on: https://gitea.com/gitea/docs/pulls/598
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Shudhanshu Singh <[email protected]>
2026-10-20 13:21:46 +00:00
Gitea BotandLunny Xiao c7dc13cf83 Update the latest api documents (#596)
Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the "update api spec files" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-596.docs-gitea-com.pages.dev

---------

Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/596
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
2026-10-19 14:05:10 +00:00
Gitea BotandLunny Xiao bed218d62d Update the runner reference pages (#597)
Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the "update runner reference" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-597.docs-gitea-com.pages.dev

---------

Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/597
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
2026-10-19 09:24:38 +00:00
Lunny Xiao 08aff1bae9 update to v28.2.0 (#594)
<!-- cloudflare-preview --> Preview: https://pr-594.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/594
Reviewed-by: silverwind <[email protected]>
2026-10-19 04:58:10 +00:00
Lunny Xiao 8cf8f49a95 Remove on-cloud-provider page (#593)
Cloud providers are now listed in awesome-gitea (https://gitea.com/gitea/awesome-gitea/pulls/202). Removes the page from the current docs and its zh-cn/zh-tw translations; released versioned docs are untouched.

Reviewed-on: https://gitea.com/gitea/docs/pulls/593
Reviewed-by: silverwind <[email protected]>
2026-10-18 19:06:41 +00:00
2af7b60fd9 docs(actions): document OIDC workload identity (#526)
Document the OpenID Connect tokens that Gitea Actions jobs can request since https://github.com/go-gitea/gitea/pull/39052, so they can sign in to cloud providers without long-lived secrets.

- Add an OpenID Connect page covering how to trust Gitea, request a token and match its claims
- Document the `id-token` permission scope and its maximum
- Translate both for zh-cn and zh-tw, which still listed `id-token` as unsupported

Co-authored-by: silverwind <[email protected]>
Co-authored-by: silverwind <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/526
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Max P. <[email protected]>
2026-10-18 07:12:16 +00:00
Jakub VránaandJakub Vrana db9e6f9f48 docs: document pre-filling issues and pull requests from query parameters (#592)
Describe the query parameters of the new issue and pull request pages, including those added in https://github.com/go-gitea/gitea/pull/39804.

---------

Co-authored-by: Jakub Vrana <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/592
Reviewed-by: wxiaoguang <[email protected]>
Reviewed-by: bircni <[email protected]>
Co-authored-by: Jakub Vrána <[email protected]>
2026-10-17 21:56:31 +00:00
Lunny Xiao b555a247e0 refactor: drop the remaining docusaurus names from identifiers and comments (#589)
Follow-up to #588.

- rename `DocusaurusSidebarItem` -> `SidebarSourceItem`, `fromDocusaurus` -> `fromSidebarSource`, `docusaurusSidebars` -> `sidebarSources`
- reword comments and READMEs that described behaviour by comparison with docusaurus; fix the stale note in `sites/docs/src/config/api.ts`
- drop `.docusaurus/` from `.gitignore`

No functional change. `pnpm check` has 0 errors and `pnpm build` still builds 6690 pages.

<!-- cloudflare-preview --> Preview: https://pr-589.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/589
Reviewed-by: silverwind <[email protected]>
2026-10-15 17:39:24 +00:00
Lunny Xiao 2275bef3bd refactor: rename i18n/*/docusaurus-plugin-content-docs to i18n/*/docs (#588)
Drops the leftover docusaurus name from the translated content directories.

- git mv i18n/{en-us,zh-cn,zh-tw}/docusaurus-plugin-content-docs -> i18n/{locale}/docs (pure renames, content unchanged)
- update the paths in packages/content-loader/src/products.ts, scripts/cut-version.mjs and sites/docs/README.md

current.json / version-*.json keep their names and stay beside the content.

Verified: pnpm build succeeds, 6690 pages built.

<!-- cloudflare-preview --> Preview: https://pr-588.docs-gitea-com.pages.dev
Reviewed-on: https://gitea.com/gitea/docs/pulls/588
Reviewed-by: Zettat123 <[email protected]>
2026-10-12 21:05:07 +00:00
Renovate Bot 1408e4890e chore(deps): update dependencies (#585)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | Type | Update | Pending |
|---|---|---|---|---|---|---|
| [@astrojs/starlight](https://starlight.astro.build) ([source](https://github.com/withastro/starlight/tree/HEAD/packages/starlight)) | [`0.42.4` → `0.42.5`](https://renovatebot.com/diffs/npm/@astrojs%2fstarlight/0.42.4/0.42.5) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@astrojs%2fstarlight/0.42.5?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@astrojs%2fstarlight/0.42.4/0.42.5?slim=true) | dependencies | patch | `0.42.6` |
| [actions/setup-node](https://github.com/actions/setup-node) ([changelog](https://github.com/actions/setup-node/compare/820762786026740c76f36085b0efc47a31fe5020..949feb2413d6458794dcd2491c4babbbce0c15c1)) | `8207627` → `949feb2` |  |  | action | digest |  |
| [astro](https://astro.build) ([source](https://github.com/withastro/astro/tree/HEAD/packages/astro)) | [`7.3.5` → `7.3.6`](https://renovatebot.com/diffs/npm/astro/7.3.5/7.3.6) | ![age](https://developer.mend.io/api/mc/badges/age/npm/astro/7.3.6?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/astro/7.3.5/7.3.6?slim=true) | dependencies | patch | `7.3.8` (+1) |
| [pnpm](https://pnpm.io) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm/npm/pnpm)) | [`12.8.2` → `12.10.1`](https://renovatebot.com/diffs/npm/pnpm/12.8.2/12.10.1) | ![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/12.10.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/12.8.2/12.10.1?slim=true) | packageManager | minor | `12.11.2` (+2) |

---

### Release Notes

<details>
<summary>withastro/starlight (@&#8203;astrojs/starlight)</summary>

### [`v0.42.5`](https://github.com/withastro/starlight/blob/HEAD/packages/starlight/CHANGELOG.md#0425)

[Compare Source](https://github.com/withastro/starlight/compare/@astrojs/[email protected]...@astrojs/[email protected])

##### Patch Changes

- [#&#8203;4227](https://github.com/withastro/starlight/pull/4227) [`5ba7a70`](https://github.com/withastro/starlight/commit/5ba7a70ad491ed8b5fc7033558dcc5428112cf97) Thanks [@&#8203;I90rche](https://github.com/I90rche)! - Adds Macedonian language support

</details>

<details>
<summary>withastro/astro (astro)</summary>

### [`v7.3.6`](https://github.com/withastro/astro/blob/HEAD/packages/astro/CHANGELOG.md#736)

[Compare Source](https://github.com/withastro/astro/compare/[email protected]@7.3.6)

##### Patch Changes

- [#&#8203;18166](https://github.com/withastro/astro/pull/18166) [`5134d0f`](https://github.com/withastro/astro/commit/5134d0f9e7478f23b1a590fa2416a2469c62ee23) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes an intermittent dev server crash when using `astro:actions` inside a server island with adapters that use a pre-bundled SSR environment (e.g. `@astrojs/cloudflare`)

- [#&#8203;18076](https://github.com/withastro/astro/pull/18076) [`8a2df66`](https://github.com/withastro/astro/commit/8a2df6675aa62fea382bce1cdb30c4260e0f104b) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes stale scoped styles during HMR when both markup and `<style>` are changed in a single save

- [#&#8203;18252](https://github.com/withastro/astro/pull/18252) [`2d29e7e`](https://github.com/withastro/astro/commit/2d29e7e38db65fcca7f241c967417003e20ecf43) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes CSS from other pages leaking into a page's `<head>` in dev when the page imports a module such as `astro:config/server`.

- [#&#8203;18000](https://github.com/withastro/astro/pull/18000) [`6724575`](https://github.com/withastro/astro/commit/67245751e02fb94223266d3c55cc7d7ac65ab060) Thanks [@&#8203;barclayd](https://github.com/barclayd)! - Fixes a bug where server islands containing framework components rendered empty in the dev server when using a custom `src/fetch.ts`

- [#&#8203;18241](https://github.com/withastro/astro/pull/18241) [`7c5fd6f`](https://github.com/withastro/astro/commit/7c5fd6f1faf4d87d0c9c5836ee47cc0d6d529ca3) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes the composable `i18n()` handler from `astro/fetch` and `astro/hono` returning an empty 404 for paths without a locale prefix. It now renders the custom 404 page, matching `astro()`.

- [#&#8203;18164](https://github.com/withastro/astro/pull/18164) [`1a6997f`](https://github.com/withastro/astro/commit/1a6997f280529650e4f1dacf0388e8fe07d05a1a) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes CSS Module HMR in dev when a component is rendered both with and without hydration on the same page. Astro now uses path-based class name hashing in dev mode so that editing CSS declarations no longer changes the generated selectors, allowing Vite's CSS HMR to update styles without a full page reload.

- [#&#8203;18243](https://github.com/withastro/astro/pull/18243) [`dd29d62`](https://github.com/withastro/astro/commit/dd29d62b1e7bd071804f822e90361cf5c9784682) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `context.props` being `null` in middleware and endpoints when the composable `astro/hono` or `astro/fetch` `actions()` handler runs before `middleware()`, or when `pages()` runs without `middleware()`

- [#&#8203;18193](https://github.com/withastro/astro/pull/18193) [`95d5d16`](https://github.com/withastro/astro/commit/95d5d16ce983612e09b588bb249f76d273c872f7) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `astro build` failing on Windows with Node.js 25+ with `ERR_INVALID_ARG_VALUE` when clearing the output directory hits a transient `EPERM` error

- [#&#8203;18220](https://github.com/withastro/astro/pull/18220) [`d6c13a4`](https://github.com/withastro/astro/commit/d6c13a48c682bb42da1eb295d520f9667035e1fb) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes type errors reported in Astro's built-in `<Picture />` and `<Font />` components when type-checking a project with `tsc` and `@astrojs/ts-content-mapper`

- [#&#8203;18133](https://github.com/withastro/astro/pull/18133) [`faac481`](https://github.com/withastro/astro/commit/faac481dc86efdd2e4987069a7298f2aea3f1c6c) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes lost request state when Vite discovers server dependencies during a request in Cloudflare dev mode

- [#&#8203;18146](https://github.com/withastro/astro/pull/18146) [`2af4516`](https://github.com/withastro/astro/commit/2af45163fb7757a533bdf929874278e0a7483cfc) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes CSS imported from an `injectScript('page')` script being dropped during build

- [#&#8203;18159](https://github.com/withastro/astro/pull/18159) [`e5f8fe0`](https://github.com/withastro/astro/commit/e5f8fe0fcfd1c1845ae425cbf874864ce5ab5a37) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a hang when a `server:defer` component is inside a slot of another component in an MDX content collection entry

- [#&#8203;18246](https://github.com/withastro/astro/pull/18246) [`c3b42ad`](https://github.com/withastro/astro/commit/c3b42adb50612041b2e1c59f386065be934e5259) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes the `glob()` loader skipping content files whose paths contain `#` or `?`

- [#&#8203;18248](https://github.com/withastro/astro/pull/18248) [`b97184e`](https://github.com/withastro/astro/commit/b97184e53012404990da6788be5aa30f99c4cf6e) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a bug where page routes added with `injectRoute()` returned a 404 when `i18n.routing.prefixDefaultLocale` was `true` and the route path had no locale prefix

- [#&#8203;18251](https://github.com/withastro/astro/pull/18251) [`3415263`](https://github.com/withastro/astro/commit/34152630b0dd77c2bfae68e568e01f824a8ee603) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes content collection changes being ignored in `astro dev` after the dev server restarts because of a config change

- [#&#8203;18226](https://github.com/withastro/astro/pull/18226) [`ad54af0`](https://github.com/withastro/astro/commit/ad54af063accfa123bf36c44a126da0404c480bb) Thanks [@&#8203;imharjot](https://github.com/imharjot)! - Fixes `Astro.cookies.get()` returning `undefined` for request cookies with empty values

- [#&#8203;18155](https://github.com/withastro/astro/pull/18155) [`37ab0e4`](https://github.com/withastro/astro/commit/37ab0e47ff53a688b667b6197807717bc4454e1b) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes nondeterministic ordering of the server manifest's `assets` array, ensuring builds with identical inputs produce byte-identical output

- [#&#8203;18099](https://github.com/withastro/astro/pull/18099) [`6987261`](https://github.com/withastro/astro/commit/69872618b7b7c915b2bd51a4b41e3a3e3116f3bb) Thanks [@&#8203;renovate](https://github.com/apps/renovate)! - Adds YAML parsing with timestamp and merge key support, and formats YAML errors consistently across Astro, Markdown, MDX, and Markdoc.

- [#&#8203;15595](https://github.com/withastro/astro/pull/15595) [`64e4039`](https://github.com/withastro/astro/commit/64e40396dc7e955986fd6d7bbd195f72556933d5) Thanks [@&#8203;qzio](https://github.com/qzio)! - Improves CSRF protection by taking modern browsers headers into account

- [#&#8203;18215](https://github.com/withastro/astro/pull/18215) [`941bd5e`](https://github.com/withastro/astro/commit/941bd5ecbe0b8ffdc9cde92880d402b8edc37d7a) Thanks [@&#8203;ump45nose](https://github.com/ump45nose)! - Fixes a runtime `ReferenceError` for inlined scripts that import a URL with `/* @&#8203;vite-ignore */`.

  Astro now inlines scripts after Vite replaces its preload markers, so ignored dynamic imports can remain inline without shipping an unresolved `__VITE_PRELOAD__` reference.

- [#&#8203;18179](https://github.com/withastro/astro/pull/18179) [`6caa659`](https://github.com/withastro/astro/commit/6caa6594afb557177e885077028db37506c409b7) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes custom View Transition direction names that are not valid CSS identifiers, such as names starting with a digit or containing spaces. These directions now match their animations correctly.

- [#&#8203;18250](https://github.com/withastro/astro/pull/18250) [`7eae39b`](https://github.com/withastro/astro/commit/7eae39bebbafc5a7b7763a8733a6e60ded5ead17) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a 404 for a CSS file that a dynamic import preloads when the imported module uses a component that is also a hydrated island on the same page

- [#&#8203;18176](https://github.com/withastro/astro/pull/18176) [`7c9d00d`](https://github.com/withastro/astro/commit/7c9d00d251e42b577ed298879fe9e68a345bd776) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes duplicate CSS in production builds when a component is both server-rendered and used with `client:only` on the same page

- [#&#8203;18245](https://github.com/withastro/astro/pull/18245) [`492e95f`](https://github.com/withastro/astro/commit/492e95f8716829f1bd0ead70405ad982a0a5c105) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes the composable `astro/fetch` and `astro/hono` handlers (`trailingSlash()`, `redirects()`, `actions()`, `middleware()`, and `pages()`) so they reject over-encoded request paths with a `400 Bad Request`, matching `astro()`. For these requests, `redirects()` and `actions()` return the `400` response instead of `undefined`, so no redirect is issued and no action runs.

- [#&#8203;18078](https://github.com/withastro/astro/pull/18078) [`0a2ab10`](https://github.com/withastro/astro/commit/0a2ab102a91c141f42b6d7da9810db74f61d1fa0) Thanks [@&#8203;manuelgruber](https://github.com/manuelgruber)! - Fixes `Astro.rewrite()` and `context.rewrite()` selecting the wrong route in `astro dev` when two dynamic routes match the same path

- [#&#8203;18210](https://github.com/withastro/astro/pull/18210) [`62b13ba`](https://github.com/withastro/astro/commit/62b13ba3e0068057a47fbfc2ab8842b263c68f0d) Thanks [@&#8203;edmundhung](https://github.com/edmundhung)! - Allows Astro CLI commands to install tagged package versions

- [#&#8203;18069](https://github.com/withastro/astro/pull/18069) [`d39eb97`](https://github.com/withastro/astro/commit/d39eb97752ea6f5d02c82e6fe35fdbfb8d9f8982) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a dev server dependency scan failure when an `.astro` file contains a literal `<script` in frontmatter or a template expression

- [#&#8203;18114](https://github.com/withastro/astro/pull/18114) [`c17d920`](https://github.com/withastro/astro/commit/c17d9209bef385ea88b6fee36e91ad4e635f4a86) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Fixes Astro on StackBlitz and other WebContainer environments

- [#&#8203;18088](https://github.com/withastro/astro/pull/18088) [`cb767f9`](https://github.com/withastro/astro/commit/cb767f974e7ef1fec9b2d496e51b09c985c93947) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes a `MODULE_LEVEL_DIRECTIVE` warning during build caused by a stale `"use astro:head-inject"` directive in content collection propagated asset modules

- [#&#8203;18247](https://github.com/withastro/astro/pull/18247) [`2b3f73d`](https://github.com/withastro/astro/commit/2b3f73db230e3bff28ed9784a3b21257a97611e0) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes actions returning 500 for malformed JSON request bodies and undecodable action names. A `SyntaxError` from invalid JSON now returns 400 (`BAD_REQUEST`), and a `URIError` from a malformed percent-encoded action name now returns 404 (`NOT_FOUND`).

- [`1d9e910`](https://github.com/withastro/astro/commit/1d9e910a0308ef9699694a2871b3d71b6f5c3383) Thanks [@&#8203;matthewp](https://github.com/matthewp)! - Validates the `Host` header against `security.allowedDomains` when using the Node adapter

- [#&#8203;18249](https://github.com/withastro/astro/pull/18249) [`c7799a4`](https://github.com/withastro/astro/commit/c7799a4b21f2f7384cf070765f0912f9ac08848b) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes the `fontsource` font provider to resolve variable fonts when using the "Variable" suffix in the font name (e.g. `"Inter Variable"`)

- [#&#8203;18163](https://github.com/withastro/astro/pull/18163) [`e48da9d`](https://github.com/withastro/astro/commit/e48da9d4f6f293d8708bd8de9ae235429272f556) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `<video muted>` losing its muted state after a ClientRouter navigation in Chrome

- [#&#8203;18244](https://github.com/withastro/astro/pull/18244) [`f67e7f7`](https://github.com/withastro/astro/commit/f67e7f7fe13e67131bb4e4c538970af60bdbbb94) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes localized error pages such as `src/pages/pt/404.astro` returning a `200` status when rendered through the `pages()` handler from `astro/fetch` or `astro/hono`

- [#&#8203;18242](https://github.com/withastro/astro/pull/18242) [`c5275e3`](https://github.com/withastro/astro/commit/c5275e3d5a688a7d246c9576b594870675b70e37) Thanks [@&#8203;astro-factory](https://github.com/apps/astro-factory)! - Fixes `experimental_AstroContainer` output including dev toolbar `data-astro-source-file` and `data-astro-source-loc` attributes when rendering components under Vitest

- Updated dependencies \[[`6987261`](https://github.com/withastro/astro/commit/69872618b7b7c915b2bd51a4b41e3a3e3116f3bb), [`62b13ba`](https://github.com/withastro/astro/commit/62b13ba3e0068057a47fbfc2ab8842b263c68f0d)]:
  - [@&#8203;astrojs/internal-helpers](https://github.com/astrojs/internal-helpers)@&#8203;0.12.0
  - [@&#8203;astrojs/markdown-satteri](https://github.com/astrojs/markdown-satteri)@&#8203;0.4.3

</details>

<details>
<summary>pnpm/pnpm (pnpm)</summary>

### [`v12.10.1`](https://github.com/pnpm/pnpm/releases/tag/v12.10.1): pnpm 12.10.1

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.10.0...v12.10.1)

This release fixes `pnpm install` failures after an `overrides` change and on a filtered frozen install with `catalogPrune`. It also fixes several bugs in the experimental `nodeLinker.type: loaded`, which now keeps its generated files in `node_modules`.

##### Patch Changes

- With `nodeLinker.type: loaded`, pnpm now writes its generated files to `node_modules`, which projects already ignore in git. The store manifest and loader are `node_modules/.pnpm/.store-manifest.json` and `node_modules/.pnpm/.store-loader.mjs`. Bin shims are in `node_modules/.bin`.

  Earlier versions wrote `.pnpm-store.json` and `.pnpm-store-loader.mjs` to the project root, and a `.pnpm` directory to the root and to each workspace package. Delete them after reinstalling.

- With `nodeLinker.type: loaded`, packages that ship their own `node_modules` directory, such as `npm` with its bundled dependencies, now load from the store. Before, one such package in the install stopped every Node.js process from starting.

- With `nodeLinker.type: loaded`, scripts can now run a Node.js runtime installed through `devEngines.runtime`. Before, every script that called `node` re-ran its own shim until it failed with "Argument list too long".

- With `nodeLinker.type: loaded`, Node.js processes start faster. In a project with 13,000 stored files, the startup overhead per process dropped from 67 ms to 18 ms.

- `pnpm install` no longer fails with `ERR_PNPM_NO_MATCHING_VERSION` after a change to `overrides` when the lockfile resolves an optional peer dependency to an npm alias of another package [#&#8203;16654](https://github.com/pnpm/pnpm/issues/16654).

- A frozen install with `catalogPrune` no longer removes catalog entries that `pnpm-lock.yaml` still records. Before, `pnpm install --frozen-lockfile --filter` failed with `ERR_PNPM_LOCKFILE_CONFIG_MISMATCH` when some workspace projects were missing from disk [#&#8203;16638](https://github.com/pnpm/pnpm/issues/16638).

- `pnpm install --fix-lockfile` no longer removes the `deprecated` and `hasBin` fields from lockfile entries [#&#8203;6600](https://github.com/pnpm/pnpm/issues/6600).

- With `enableGlobalVirtualStore`, an install that updates `node_modules` now repairs a package in the global virtual store that an interrupted install left without some of its dependency links or package files. Before, such an install kept the incomplete package if the project's `node_modules` already recorded it [#&#8203;16642](https://github.com/pnpm/pnpm/issues/16642).

- `pnpm install` now skips the Cargo and Python projects inside a nested directory that has its own `pnpm-workspace.yaml` or `.git` directory, such as a git worktree of the same workspace or a separate clone.

- The `Request took` warning for package metadata now starts timing when pnpm sends the request. Before, it also counted the time the request waited for a free request slot, so large installs printed it for requests the registry answered quickly.

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.10.0`](https://github.com/pnpm/pnpm/releases/tag/v12.10.0): pnpm 12.10.0

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.9.1...v12.10.0)

This release adds an experimental `loaded` node linker, lets `pnpm-lock.yaml` record resolution settings, and reads cached registry metadata faster. It also carries several security fixes, including one that stops a dependency version from writing files outside the global virtual store.

##### Minor Changes

- Added experimental `nodeLinker: { type: loaded }` installation. Compatible dependencies load directly from the content-addressable store through an automatically registered Node.js loader. `nodeLinker.excluded` selects packages and their dependency trees to install in the global virtual store.

- `lockfile.includeResolutionSettings: true` makes `pnpm-lock.yaml` record `autoDedupe`, `dedupeInjectedDeps`, `dedupePeerDependents` and `linkWorkspacePackages`. Installs then treat a lockfile that records other values as outdated. A lockfile that records `autoDedupe` is reused by later installs on any machine, so `pnpm run` after `pnpm install --frozen-lockfile` no longer starts another install [#&#8203;16583](https://github.com/pnpm/pnpm/issues/16583).

##### Patch Changes

##### Security

- `pnpm install` now prevents dependency versions with path traversal from writing files outside the global virtual store.

- pnpm now verifies locked config dependencies against their registry before installing them. Config dependencies must come from an npm registry. The lockfile can no longer replace the integrity of a config dependency pinned with `version+integrity`.

- Lockfile verification now checks the tarballs inside a `variations` resolution against the registry. A `name@version` lockfile entry with an empty `variations` resolution is now rejected.

- `pnpm audit signatures` now verifies signatures against the integrity recorded in the lockfile. Packages without a recorded integrity cannot pass signature verification.

- `pnpm install` and `pnpm publish` now reject archive metadata larger than 64 MiB before reading it into memory. Publishing a pre-built tarball also rejects manifests and README files larger than 64 MiB.

- Two URL or local path dependencies no longer share a virtual store directory when one URL has `+`, `#`, `:`, or `?` where the other has `/`. Such dependencies, including git dependencies pinned with `#`, now get a hash suffix on their directory name.

- The warning about an ignored project `.npmrc` registry setting no longer prints the username and password of a URL-scoped key such as `//user:[email protected]/${PATH}/:_authToken`.

##### Installing and resolving dependencies

- `pnpm install` now fails with `ERR_PNPM_UNSUPPORTED_PROTOCOL` when a dependency uses a specifier with a protocol pnpm does not support, such as Yarn's `patch:`. On Windows, such a specifier failed with `os error 123`. On other platforms, pnpm linked it to a directory that does not exist. Reading a `package.json` that fails now names the file [#&#8203;16590](https://github.com/pnpm/pnpm/issues/16590).

- `pnpm install` now fails with `ERR_PNPM_PACKAGE_MANIFEST_INVALID_ATTRIBUTE` when a project declares a dependency whose specifier is not a string, such as `"is-positive": 42`. Before, the dependency was silently left out of the lockfile. A `readPackage` hook can still correct the specifier.

- Fixed `pnpm install` failing with `ERR_PNPM_CMD_SHIM_RESOLVE_PATH` when an executable's parent directory contains a dangling symlink.

- `pnpm install --frozen-lockfile` no longer fails with `ERR_PNPM_RESOLUTION_SHAPE_MISMATCH` when a `name@version` lockfile entry has a resolution served by a custom fetcher [pnpm/tasks#108](https://github.com/pnpm/tasks/issues/108).

- `pnpm install --fix-lockfile` repairs a lockfile whose importer references a package that has no snapshot entry, as left by a badly merged lockfile. It failed with `ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY` since 12.8.0 [#&#8203;16618](https://github.com/pnpm/pnpm/issues/16618).

- When a dependency moves an exact dependency of its own to an older version, a peer dependency that pnpm installed automatically now moves with it. Before, `pnpm install` and `pnpm dedupe` kept the newer locked version of the peer, so the lockfile held two copies of it, for example two copies of `vue` [pnpm/tasks#61](https://github.com/pnpm/tasks/issues/61).

- `pnpm dedupe` now reads registry metadata for a dependency pinned to an exact version, as `pnpm install` does. If the registry metadata disagreed with the package's `package.json`, the lockfile it wrote depended on whether `minimumReleaseAge` was set [#&#8203;16615](https://github.com/pnpm/pnpm/issues/16615).

##### Speed and size

- Dependency resolution reads cached registry metadata faster. The metadata cache moved to `<cache-dir>/v12/`, so the first install after upgrading downloads registry metadata again. A damaged cache entry is downloaded again, or reported as an error when `--offline` is set. `pnpm cache prune` also removes the metadata cache that older pnpm versions wrote under `<cache-dir>/v11/` [#&#8203;13512](https://github.com/pnpm/pnpm/pull/13512).

- Package metadata requests no longer wait behind queued tarball downloads when `maxSockets` or a proxy limits the connections to a registry. Large installs resolve faster and print fewer `Request took` warnings.

- Sped up installs in large workspaces on macOS when the dependency links already exist. pnpm now keeps a link that already points at the right package without trying to create it first. Relinking the direct dependencies of 1,000 workspace projects took 45 ms, down from 116 ms [pnpm/tasks#65](https://github.com/pnpm/tasks/issues/65).

- Commands in a project that pins a different pnpm version start about 13 ms faster on macOS. pnpm now runs the pinned version's binary directly, without the shell script in front of it [pnpm/tasks#66](https://github.com/pnpm/tasks/issues/66).

- The pnpm binary is about 0.9 MB smaller, and the arm64 Linux binary is about 1 MB smaller still.

##### Running scripts and commands

- `pnpm run` no longer prints `[ELIFECYCLE] Command failed ...` after Ctrl+C ends the script. pnpm still exits the way the script's shell did: on Windows with the shell's exit code (`cmd` reports `-1073741510`, PowerShell `1`), on Unix by re-raising `SIGINT` [#&#8203;16579](https://github.com/pnpm/pnpm/issues/16579).

- `pnpm run "/<regex>/"` now accepts JavaScript regular expression syntax such as lookahead and lookbehind. A selector like `"/^hello:(?!b).*$/"` failed with `ERR_PNPM_NO_SCRIPT` [#&#8203;16604](https://github.com/pnpm/pnpm/issues/16604).

- `pnpm run` and `pnpm exec` now forward `--config.*` command-line flags to the install started by `verifyDepsBeforeRun` [pnpm/tasks#60](https://github.com/pnpm/tasks/issues/60).

- On Windows, a process started by `pnpm run` or `pnpm exec` can again start a child with `CREATE_BREAKAWAY_FROM_JOB`. That child keeps running after pnpm exits, even if the command fails [#&#8203;16628](https://github.com/pnpm/pnpm/issues/16628).

- Empty `nodeOptions` values from command-line flags and environment variables now override lower-priority settings. Scripts retain `NODE_OPTIONS` from the parent environment or `extraEnv` when `nodeOptions` is empty.

- pnpm now reads the `failIfNoMatch` setting from `pnpm-workspace.yaml`, so a filter that matches no workspace project exits with code 1 when the setting is `true`. The new `--no-fail-if-no-match` flag turns the setting off for one command [#&#8203;16577](https://github.com/pnpm/pnpm/issues/16577).

##### Configuration, setup, and pnpm versions

- `pnpm config get --global` and `pnpm config list --global` now show only the global configuration, also when run inside a project. Settings from the project's `pnpm-workspace.yaml` and `.npmrc` were included before. The same applies to `--location=global` [#&#8203;16598](https://github.com/pnpm/pnpm/issues/16598).

- pnpm now prints config warnings, such as an unset environment variable in `.npmrc`, when loading the config fails.

- pnpm 11 releases older than 11.28.4 can run pnpm 12 again when the `packageManager` field pins it. Since 12.9.0 they failed with `SyntaxError: Invalid or unexpected token` [#&#8203;16594](https://github.com/pnpm/pnpm/issues/16594).

- On Windows, `pnpm self-update` no longer runs the update a second time when it replaces a `pnpm.cmd` linked by pnpm 12.8 or older. cmd.exe read on in the replaced `pnpm.cmd`, printed an error about a command that is not recognized, and ran the new pnpm once more [#&#8203;16573](https://github.com/pnpm/pnpm/issues/16573).

- `pnpm setup` now puts `$PNPM_HOME/bin` first on `PATH` in login shells that inherited it further down, such as the VS Code terminal on macOS. Before, another `node` took precedence over the one installed by `pnpm runtime set node -g`. Run `pnpm setup` again to update the block in your shell config [#&#8203;16635](https://github.com/pnpm/pnpm/issues/16635).

- `pnpm setup` now names the shell config file even if it is already up to date [#&#8203;16608](https://github.com/pnpm/pnpm/issues/16608).

##### Updating, auditing, and publishing

- `pnpm update --latest` now applies the `savePrefix` setting when it rewrites a dependency whose range has no operator of its own, such as `<2.0.0`.

- The interactive `pnpm audit --fix` picker now shows each patched version with the `saveExact` and `savePrefix` style that the override is written with [#&#8203;13209](https://github.com/pnpm/pnpm/issues/13209).

- `pnpm unpublish <pkg>@&#8203;<version>` now deletes the tarball under the registry's path when the registry is served under one, such as Gitea's npm registry. It used to send the delete to the host root and report success without removing the version [#&#8203;16568](https://github.com/pnpm/pnpm/issues/16568). It also no longer mistakes a sibling path such as `/npm-mirror/` for the registry path `/npm/` [pnpm/tasks#94](https://github.com/pnpm/tasks/issues/94).

##### Output and messages

- A warning about a project's `devEngines` or `packageManager` pin is now printed to stderr. A command such as `pnpm cache path` or `pnpm list --json` keeps only its own output on stdout [#&#8203;16584](https://github.com/pnpm/pnpm/issues/16584).

- `pnpm list` now reports the correct package paths when `nodeLinker` is `hoisted` [#&#8203;9593](https://github.com/pnpm/pnpm/issues/9593).

- Resolution errors now name the failing dependency and its parent packages. Fatal errors appear as structured error records with their error codes when using `--reporter=ndjson`.

- The error for an invalid git repository in the lockfile now has the code `ERR_PNPM_INVALID_GIT_REPOSITORY`. Its message now lists every rejected form of the value.

- `pnpm runtime --help` and `pnpm help runtime` now name the `set` subcommand and the runtimes it accepts [#&#8203;16580](https://github.com/pnpm/pnpm/issues/16580).

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.9.1`](https://github.com/pnpm/pnpm/releases/tag/v12.9.1): pnpm 12.9.1

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.9.0...v12.9.1)

This release moves the WebContainer build into a separate `@pnpm/wasm` package, shrinks the `pnpm` package back to about 4 MB, and fixes `pnpm publish` with provenance from GitLab CI.

##### Patch Changes

- The WebAssembly build for StackBlitz WebContainers now ships as a separate `@pnpm/wasm` package. The `pnpm` and `@pnpm/exe` packages no longer include it, which brings their unpacked size back from about 55 MB to about 4 MB. In a WebContainer, install `@pnpm/wasm` with npm to get the `pnpm` command.

- `pnpm publish` with provenance from GitLab CI is no longer rejected by the npm registry with a 422 error. The provenance statement now includes the GitLab CI variables in `invocation.parameters`, as npm does [#&#8203;16551](https://github.com/pnpm/pnpm/issues/16551).

- `pnpm audit signatures` now uses the TLS settings of the redirect target when a registry redirects its signing-keys request, for example to registry.npmjs.org. A `cafile` scoped to a private registry no longer makes the redirected request fail [#&#8203;16541](https://github.com/pnpm/pnpm/issues/16541).

- Fixed `pnpm install --frozen-lockfile` rejecting an up-to-date lockfile when an injected workspace package uses a catalog entry in `peerDependencies` [#&#8203;16557](https://github.com/pnpm/pnpm/issues/16557).

- The `[<since>]` filter selector works again with Git 2.24 through 2.27 [#&#8203;16561](https://github.com/pnpm/pnpm/issues/16561). With Git older than 2.24, the selector now fails with an error that names the required Git version.

  It also detects changes in projects whose directory names contain non-ASCII characters. Such a change used to be credited to the parent project. `changedFilesIgnorePattern` and `testPattern` now match changed files whose names contain non-ASCII characters.

- The `pnpm` executable is about 10% smaller. On macOS arm64 it went from 45.1 MB to 40.3 MB.

- Sped up trust downgrade checks for packages with long release histories.

- With `optimisticRepeatInstall: false`, `pnpm install` now runs the projects' own lifecycle scripts, such as `prepare`, even when `node_modules` is already up to date [#&#8203;16545](https://github.com/pnpm/pnpm/issues/16545).

- `pnpm self-update` now fails for Homebrew-installed pnpm and prints the `brew upgrade` command for the installed formula, such as `brew upgrade pnpm` or `brew upgrade pnpm@11`. It used to install a second copy of pnpm that the Homebrew one kept shadowing [#&#8203;16547](https://github.com/pnpm/pnpm/issues/16547).

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.9.0`](https://github.com/pnpm/pnpm/releases/tag/v12.9.0): pnpm 12.9

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.8.2...v12.9.0)

This release runs pnpm in StackBlitz WebContainers, adds a per-registry `networkConcurrency` setting, and records every installed project in the store. It also carries a security fix for `pnpm login`.

##### Minor Changes

- pnpm now automatically uses WebAssembly in StackBlitz WebContainers, including when installation scripts are disabled. Native installations continue to use the native executable when installation scripts are enabled.

- A `registries` entry can now set `networkConcurrency`, the most requests pnpm keeps in flight to that registry's origin. Requests to other registries keep the overall limit. The setting may live in `pnpm-workspace.yaml` or the global `config.yaml`.

  ```yaml
  registries:
    https://npm.corp.example.com/:
      scopes: ["@&#8203;acme"]
      networkConcurrency: 4
  ```

- `pnpm install` now records every project it installs in the store's `projects` directory, as a symlink to the project directory. A `--frozen-store` install without the global virtual store still records nothing. Only projects that used the global virtual store were recorded before [#&#8203;6929](https://github.com/pnpm/pnpm/issues/6929).

##### Patch Changes

- `pnpm login` no longer forwards credentials in its request body to another origin during redirects.

##### Installing packages

- Fixed `pnpm install` failing on Android with `ERR_PNPM_STORE_DIR_ACQUIRE_OPERATION_LOCK` [#&#8203;16508](https://github.com/pnpm/pnpm/issues/16508).

- `pnpm install --frozen-lockfile` again succeeds when a workspace project recorded in `pnpm-lock.yaml` has no directory, such as a project left out of a Docker build context. It still fails if the project's directory exists without a `package.json` [#&#8203;16453](https://github.com/pnpm/pnpm/issues/16453).

- `pnpm install --frozen-lockfile` no longer requires a `pnpm-lock.yaml` in a project that has no dependencies. It also succeeds when `pnpm-lock.yaml` records only the pinned pnpm version, as other commands write it when they run before the first install [#&#8203;16477](https://github.com/pnpm/pnpm/issues/16477).

- Fixed `pnpm install --frozen-lockfile` rejecting a fresh lockfile when an injected workspace dependency has an optional peer supplied by another workspace project [#&#8203;16428](https://github.com/pnpm/pnpm/issues/16428).

- With `nodeLinker: hoisted`, a filtered install now keeps the packages of the workspace projects an earlier install put in `node_modules`. This also covers the install that `pnpm --filter <selector> run` and `pnpm --filter <selector> exec` start before the command. Before, these installs removed every package that only the unselected projects needed [#&#8203;16483](https://github.com/pnpm/pnpm/issues/16483).

- `pnpm install` with `nodeLinker: hoisted` now refreshes directories supplied by custom fetchers when reinstalling. pnpm also keeps the symlinks inside those directories.

- With `enableGlobalVirtualStore` on, scripts can run entry points that a CommonJS require hook loads again, such as `ts-node index.ts`. They failed with `ERR_UNKNOWN_FILE_EXTENSION` on Node.js versions without built-in TypeScript support [#&#8203;16436](https://github.com/pnpm/pnpm/issues/16436).

- pnpm now keeps each project's current lockfile and hidden hoisted dependencies in its own `node_modules/.pnpm` when `virtualStoreDir` points at a shared global virtual store. `--virtual-store-dir` now sets the global virtual store's location too [pnpm/tasks#47](https://github.com/pnpm/tasks/issues/47).

- `pnpm clean` no longer deletes the project when `virtualStoreDir` or `globalVirtualStoreDir` is set to the project directory. It also leaves a directory outside the project alone when the setting reaches it through a symlink. It now removes a global virtual store that `globalVirtualStoreDir` places inside the project, as it does for `virtualStoreDir`.

##### Optional dependencies

- `pnpm install` no longer fails when a dependency of an optional dependency is missing from the registry. Like npm, pnpm now leaves out the nearest optional dependency above it, together with its subtree [#&#8203;16511](https://github.com/pnpm/pnpm/issues/16511).

- When an optional dependency fails to build, pnpm now removes its link from `node_modules`. A repeat `pnpm install` then reports "Already up to date" and no longer reruns the failing build [#&#8203;16468](https://github.com/pnpm/pnpm/issues/16468).

- `pnpm install` now prints a warning with the error when an optional dependency cannot be fetched and is skipped. The skipped package is no longer counted in the `Packages: +N` summary. The `pnpm:skipped-optional-dependency` log reports the skip with the `fetch_failure` reason [#&#8203;16514](https://github.com/pnpm/pnpm/issues/16514).

##### Resolving dependencies

- Fixed `pnpm install` changing an unchanged project's direct dependency to a sibling workspace's pinned version when its dependency tree contains a cycle [#&#8203;16417](https://github.com/pnpm/pnpm/issues/16417).

- With `autoDedupe` enabled, downgrading a dependency in one workspace project now moves the other projects to that version when it satisfies their ranges. This also applies to a filtered `pnpm --filter <project> add` [#&#8203;16432](https://github.com/pnpm/pnpm/issues/16432).

- `pnpm install` and `pnpm dedupe` now move an optional peer to the version already in the dependency graph when no other package provides its locked version anymore. After a bump such as `vue` 3.5.40 to 3.5.43, the lockfile kept a second copy of `@vue/server-renderer` for `@vue/test-utils` [#&#8203;16443](https://github.com/pnpm/pnpm/issues/16443).

- `pnpm dedupe --check` no longer fails right after `pnpm install` when a project's optional peer is satisfied by a package another workspace project installs. `pnpm dedupe` now picks the same versions for that package's dependencies as `pnpm install` [#&#8203;16447](https://github.com/pnpm/pnpm/issues/16447).

- `pnpm install` no longer re-resolves an up-to-date lockfile on every run when a patched package is a peer in a peer cycle [#&#8203;16418](https://github.com/pnpm/pnpm/issues/16418).

- With `autoDedupe` enabled, `pnpm install --lockfile-only` no longer resolves the dependency graph again when nothing changed since an earlier `--lockfile-only` install deduplicated the lockfile. Such an install keeps the lockfile even if versions were published since it was written, or if only a setting such as `resolutionMode` changed. Run `pnpm dedupe` to apply such a change [#&#8203;16458](https://github.com/pnpm/pnpm/issues/16458).

##### Speed and network

- A repeat `pnpm install` in a large workspace reports "Already up to date" faster [#&#8203;16487](https://github.com/pnpm/pnpm/issues/16487).

- Sped up dependency resolution of workspaces with many peer dependencies.

- `pnpm install` sends fewer registry metadata requests when the lockfile already decides which version a range resolves to. This now also covers ranges that several locked versions satisfy when one of them outranks the others, and direct dependencies kept at their locked version. Packages that `minimumReleaseAgeExclude` lists without a version now reuse cached registry metadata the same way they do when `minimumReleaseAge` is not set [#&#8203;16458](https://github.com/pnpm/pnpm/issues/16458).

- pnpm no longer downloads every packument again on each install from a registry whose metadata responses forbid caching, such as `Cache-Control: no-store`. pnpm revalidates the cached metadata with a conditional request, so a registry that supports conditional requests answers with a 304 when the package has not changed [#&#8203;16528](https://github.com/pnpm/pnpm/issues/16528).

- Cached metadata for a package published within `minimumReleaseAge` is now revalidated with its ETag, so the npm registry can answer `304 Not Modified`. Before, the next install that checked the cache downloaded the whole document again [#&#8203;16506](https://github.com/pnpm/pnpm/issues/16506).

- A fetch timeout while other downloads from the same host are still running now lowers concurrency for that host to one connection. Retries of that request, and later downloads from that host, use the lower concurrency. Other hosts keep the configured concurrency [#&#8203;12791](https://github.com/pnpm/pnpm/issues/12791).

- Sped up `pnpm install --offline` when the version a range picks is not in the store. While it looks for a version the store holds, pnpm now reads only the versions the range admits [#&#8203;16495](https://github.com/pnpm/pnpm/issues/16495).

- `pnpm install --offline` now reuses config dependency tarballs that are already present in the store [pnpm/tasks#46](https://github.com/pnpm/tasks/issues/46).

##### Running scripts

- `pnpm -s <script>` runs the script again, with `-s` meaning `--sequential` as it does for `pnpm run -s <script>`. pnpm rejected it with "unexpected argument '-s' found" [#&#8203;16446](https://github.com/pnpm/pnpm/issues/16446).

- `pnpm run` and `pnpm exec` now warn and run the command when the install that `verifyDepsBeforeRun` starts fails. This lets scripts run in sandboxes where pnpm cannot install, such as containers with a read-only store or no network [#&#8203;15173](https://github.com/pnpm/pnpm/issues/15173).

- A filtered `pnpm run` or `pnpm exec` now finds dependencies out of date when a workspace dependency of a selected project has no `node_modules` directory, as after a filtered install. With `verifyDepsBeforeRun: install`, pnpm installs that dependency before running the command [pnpm/tasks#45](https://github.com/pnpm/tasks/issues/45).

- Scripts run without a terminal no longer start a second `sh` each. One watchdog per pnpm command now ends every script's process group if pnpm is killed, so `pnpm -r run` across many projects starts half as many processes [#&#8203;16489](https://github.com/pnpm/pnpm/issues/16489).

- `Terminate batch job (Y/N)?` no longer appears after pressing Ctrl+C in a script started with `pnpm` from PowerShell or cmd on Windows [#&#8203;16502](https://github.com/pnpm/pnpm/issues/16502).

- `pnpm rebuild` and `pnpm approve-builds` refresh command launchers when a build changes a command's interpreter or replaces it with a native executable. Dependent packages' build scripts use the refreshed launchers.

- When `pnpm run <script>` or `pnpm <script>` finds nothing to run and `--filter` follows the script name, the error now suggests putting the filter option before the script name [#&#8203;4655](https://github.com/pnpm/pnpm/issues/4655).

- Package-name filters now support `?` to match one character [#&#8203;2817](https://github.com/pnpm/pnpm/issues/2817).

##### The pinned pnpm and `pnpm self-update`

- pnpm no longer downloads the project's pinned pnpm version again on every command when `nodeVersion` in `pnpm-workspace.yaml` names a different Node.js major than the `node` on `PATH`. Before, each of those commands took about a second longer and failed without network access [#&#8203;16497](https://github.com/pnpm/pnpm/issues/16497).

- Several `pnpm` commands started at once in a project that pins `packageManager` no longer fail with `The process cannot access the file because it is being used by another process` on Windows while the pinned pnpm is being installed.

- pnpm can now switch to a `packageManager` version below 11 on x64 musl Linux, such as Alpine [#&#8203;16467](https://github.com/pnpm/pnpm/issues/16467).

- A `devEngines.packageManager` range no longer makes pnpm replace the version recorded in `pnpm-lock.yaml` with the running pnpm while the recorded version still satisfies the range. When pnpm does record a version, it records the running pnpm only if it meets `minimumReleaseAge`. Otherwise it records the newest version in the range that meets it, or the running pnpm if none does [#&#8203;16431](https://github.com/pnpm/pnpm/issues/16431).

- On Windows, `pnpm self-update` now replaces a `pnpm.exe` left in `PNPM_HOME` or in `PNPM_HOME\bin`. Windows ran that executable in place of the updated `pnpm.cmd` shim, so `pnpm --version` kept printing the old version after a successful update. If the executable was in `PNPM_HOME`, `self-update` now asks you to run `pnpm setup` [#&#8203;9094](https://github.com/pnpm/pnpm/issues/9094).

- `pnpm self-update` now checks that a version installed as the JavaScript `pnpm` can start before making it the global `pnpm`. If Node.js is missing, the update fails and the current `pnpm` stays in place.

##### Other commands

- `pnpm deploy` now finds patches and local dependencies when the target directory sits under a symlink, such as `/tmp` on macOS. It failed with `ERR_PNPM_PATCH_NOT_FOUND` [#&#8203;16470](https://github.com/pnpm/pnpm/issues/16470).

- `pnpm deploy --legacy` now resolves the deployed project's relative `file:`, `link:`, and path dependencies from the project's own directory [#&#8203;16475](https://github.com/pnpm/pnpm/issues/16475).

- `pnpm update --global` now removes hard-linked executables from `PNPM_HOME` when migrating packages from the old global layout [#&#8203;16420](https://github.com/pnpm/pnpm/issues/16420).

- `pnpm store prune` no longer fails on store index entries that pnpm 11 wrote for git-hosted packages without a `package.json`. Entries that still cannot be read are kept and counted in the prune summary.

- `pnpm store prune` now aborts when an error other than a missing directory occurs while scanning project directories in the mark phase.

- `pnpm config get` and `pnpm config list` now report a setting given on the command line with `--config.<name>=<value>`. Before, a value such as `--config.node-linker=hoisted` reached the install but was absent from the reported configuration [#&#8203;16276](https://github.com/pnpm/pnpm/issues/16276).

- `pnpm -r pkg get` now reports every selected project when several share a package name. Projects with the same name are keyed by their directory relative to the workspace root. Before, only one of them appeared in the output.

- The install summary shows a `link:` dependency as `+ name <- path`, and the Node.js API's `hideLinkedPkgsDiff` reporter option leaves matching linked dependencies out of the summary.

- The `--force` help text of `pnpm install` and `pnpm add` now says that `--force` keeps skipping optional dependencies built for other platforms. It points to `forceIgnoresPlatform` and the `--os`, `--cpu`, and `--libc` options for installing them [#&#8203;16435](https://github.com/pnpm/pnpm/issues/16435).

- The `homepage` field of the published `pnpm` package points to <https://pnpm.io> again.

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

<!-- cloudflare-preview --> Preview: https://pr-585.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/585
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
2026-10-12 16:24:14 +00:00
Gitea Bot adaae2f859 Update the runner reference pages (#586)
Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the "update runner reference" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-586.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/586
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
2026-10-12 16:04:09 +00:00
silverwind 424c481e19 docs: drop the gc.reflogExpire default (#584)
Gitea no longer sets `gc.reflogExpire`, leaving reflog expiry to git's defaults, see https://github.com/go-gitea/gitea/pull/39703, backported in https://github.com/go-gitea/gitea/pull/39711.

Reviewed-on: https://gitea.com/gitea/docs/pulls/584
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-10 16:56:06 +00:00
silverwind ad95b7776c docs: update GO_GET_CLONE_URL_PROTOCOL default (#580)
Copy the new `app.example.ini` wording from https://github.com/go-gitea/gitea/pull/39674, backported in https://github.com/go-gitea/gitea/pull/39676. `GO_GET_CLONE_URL_PROTOCOL` now defaults to ssh when `DISABLE_HTTP_GIT` is enabled.

Reviewed-on: https://gitea.com/gitea/docs/pulls/580
Reviewed-by: wxiaoguang <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-08 13:28:26 +00:00
Lunny Xiao f940b0bc9e ci: generate the v28 awesome page and explain skipped previews (#579)
The v28 release (#564) added the `prepare-awesome-v%` Makefile rule, but the checks and publish workflows still only prepare awesome.md up to 1.27, so version-28/awesome.md is not generated in CI. Both workflows now call `prepare-awesome-v28`.

The preview step is skipped when Cloudflare secrets are unavailable, which is the case for pull requests from forks (#557 and #565 have no preview line, while same-repo PRs like #533 and #563 do). The skip is now a visible notice. Previewing fork PRs would need a separate trusted workflow and is not part of this change.

Reviewed-on: https://gitea.com/gitea/docs/pulls/579
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
2026-10-07 04:29:39 +00:00
bircniandLunny Xiao 444879b492 update to 28.1.0 (#578)
Bump the v28 docs to the 28.1.0 release, following the 1.27.3 bump (#532):

- point the `28` version variables (`version`, `sourceVersion`, `dockerVersion`, `displayVersion`) at 28.1.0
- update the v28 entry in `update_api_docs.sh` to `28.1.0`
- regenerate `static/swagger-28.json` and `static/openapi3-28.json` from the `v28.1.0` tag

---------

Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/578
Reviewed-by: TheFox0x7 <[email protected]>
Co-authored-by: bircni <[email protected]>
2026-10-07 03:00:58 +00:00
bc7e2b3caa docs: link-local egress targets are allowable (#573)
Documents https://github.com/go-gitea/gitea/pull/39560: link-local addresses can be allowed with an explicit `ALLOWED_HOST_LIST` entry again, only cloud metadata endpoints stay hard-denied. Merge after that PR.

*Written by Claude.*

---------

Co-authored-by: bircni <[email protected]>
Co-authored-by: TheFox0x7 <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/573
Reviewed-by: bircni <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-06 21:56:56 +00:00
Renovate Bot 5823b20e70 chore(deps): update dependencies (#575)
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [pnpm](https://github.com/pnpm/pnpm/tree/main/pnpm) ([source](https://github.com/pnpm/pnpm/tree/HEAD/pnpm/npm/pnpm)) | [`12.6.0` → `12.8.2`](https://renovatebot.com/diffs/npm/pnpm/12.6.0/12.8.2) | ![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/12.8.2?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/12.6.0/12.8.2?slim=true) |
| [sharp](https://sharp.pixelplumbing.com) ([source](https://github.com/lovell/sharp), [changelog](https://github.com/lovell/sharp/blob/main/docs/src/content/docs/changelog.md)) | [`0.35.4` → `0.35.5`](https://renovatebot.com/diffs/npm/sharp/0.35.4/0.35.5) | ![age](https://developer.mend.io/api/mc/badges/age/npm/sharp/0.35.5?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/sharp/0.35.4/0.35.5?slim=true) |
| [starlight-openapi](https://github.com/HiDeoo/starlight-openapi) ([source](https://github.com/HiDeoo/starlight-openapi/tree/HEAD/packages/starlight-openapi)) | [`0.26.2` → `0.26.3`](https://renovatebot.com/diffs/npm/starlight-openapi/0.26.2/0.26.3) | ![age](https://developer.mend.io/api/mc/badges/age/npm/starlight-openapi/0.26.3?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/starlight-openapi/0.26.2/0.26.3?slim=true) |

---

### Release Notes

<details>
<summary>pnpm/pnpm (pnpm)</summary>

### [`v12.8.2`](https://github.com/pnpm/pnpm/releases/tag/v12.8.2): pnpm 12.8.2

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.8.1...v12.8.2)

pnpm 12.8.2 fixes a startup crash on Linux ppc64le and `UnknownIssuer` errors on systems without CA certificates. `pnpm run` no longer installs before every script on CI when `autoDedupe` is enabled, and resolution and hoisted installs on macOS are faster.

##### Patch Changes

##### Platforms and environments

- Fixed pnpm crashing on startup on Linux ppc64le [#&#8203;16380](https://github.com/pnpm/pnpm/issues/16380).

- Fixed installs failing with `UnknownIssuer` on Linux systems without CA certificates, such as `node:24-slim`, when `NODE_EXTRA_CA_CERTS` is set. The extra certificates now extend the bundled CA roots [#&#8203;16365](https://github.com/pnpm/pnpm/issues/16365).

- pnpm now creates its store operation locks and other per-user lock files in `$XDG_RUNTIME_DIR` when it points to a directory only the user can write to. Otherwise, pnpm still uses `/tmp` on Linux and macOS. Sandboxes that block writes to `/tmp` can point `XDG_RUNTIME_DIR` at a writable directory [#&#8203;16390](https://github.com/pnpm/pnpm/issues/16390).

- POSIX bin shims and the `pnpm`, `pn`, `pnpx`, and `pnx` launchers now run inside a Nix build, where the system default path holds none of the utilities they call. Installing again replaces the shims already in `node_modules` [#&#8203;16377](https://github.com/pnpm/pnpm/issues/16377).

- In a project that pins another pnpm version, pnpm now passes a command with an option it does not know to the pinned version. Before, pnpm rejected the option before switching, so `pnpm install --auto-dedupe` failed with "Unknown option" even though the pinned pnpm supports it [#&#8203;16353](https://github.com/pnpm/pnpm/issues/16353).

##### Installing and resolving dependencies

- `pnpm install --frozen-lockfile` now fails when `Cargo.lock` does not satisfy a dependency requirement in `Cargo.toml`. The error names the crate and the version the lockfile holds [#&#8203;16355](https://github.com/pnpm/pnpm/issues/16355).

- `pnpm install` returns "Already up to date" again in a workspace with injected workspace dependencies and a shared lockfile. Since 12.7.0 every repeat install in such a workspace ran the full install and copied the injected projects again.

- With `injectWorkspacePackages: true`, a fresh `pnpm install` now records a workspace dependency as `link:` when its injected copy differs from the project only by an optional peer that peer-dependent dedupe merges. It was recorded as a peer-suffixed `file:` copy [#&#8203;16354](https://github.com/pnpm/pnpm/issues/16354).

- `pnpm dedupe --check` now passes right after `pnpm dedupe` when deduplication merges variants of a package that differ only in their peers. A lockfile key whose peer suffix named a merged variant now names the variant that replaced it [#&#8203;16356](https://github.com/pnpm/pnpm/issues/16356).

- When `minimumReleaseAge` hides the version that `latest` points to, pnpm now falls back to a prerelease of the same major before a stable version of an older major. A stable version of the same major is still preferred. Before, while a new `1.0.0` was too new, `latest` fell back to an old `0.0.1` even though `1.0.0-beta.4` had been `latest` until then [#&#8203;16388](https://github.com/pnpm/pnpm/issues/16388).

- Git-hosted dependencies now respect `pmOnFail`. If it is set to anything other than `download`, a git-hosted dependency that pins a pnpm version is prepared by the running pnpm, and pnpm does not download the pinned version [#&#8203;16376](https://github.com/pnpm/pnpm/issues/16376).

- pnpmfile hooks such as `readPackage` now run once for a dependency that several packages request at the same time. They could run twice for it before.

- `childConcurrency` now defaults to 5, the documented value. It used to be capped at 4 and to follow the host's CPU count.

##### Running scripts

- `pnpm run` and `pnpm exec` no longer install dependencies before every script on CI when `autoDedupe` is enabled. `pnpm install --frozen-lockfile` now keeps the deduplication record left by an earlier install [#&#8203;16374](https://github.com/pnpm/pnpm/issues/16374).

- On macOS and Linux, lifecycle scripts and `pnpm run` now always get `PATH` from the `PATH` variable. When the environment also held a `Path` variable, a script sometimes got `Path`'s value, and failed with `node: not found` [#&#8203;16308](https://github.com/pnpm/pnpm/issues/16308).

- `pnpm run` now exits after a `SIGTERM` in a container where pnpm is PID 1 and the script runs pnpm again, as `"start": "pnpm serve"` does. Since 12.6.0 it kept waiting after the script had shut down, until the container runtime killed it.

##### Other commands and settings

- `pnpm config get globalShims`, `pnpm shim list`, and global installs no longer read `globalShims` from a project's `pnpm-workspace.yaml`. Only the global config file, the pnpm home's own `pnpm-workspace.yaml`, and `PNPM_CONFIG_GLOBAL_SHIMS` set it, so a repository cannot choose which globally installed packages get project-aware shims.

- `pnpm config set --location=project` refuses a machine-level setting such as `stateDir` or `scope` with `ERR_PNPM_CONFIG_SET_NOT_A_PROJECT_SETTING`, which names where the setting belongs. `pnpm config delete` still clears such a key from a project's `pnpm-workspace.yaml`.

- `pnpm deploy` no longer fails with `ERR_PNPM_DEPLOY_AMBIGUOUS_PEER` in a workspace with `injectWorkspacePackages: true` when a workspace package lists its peer dependency as a dev dependency too [#&#8203;16375](https://github.com/pnpm/pnpm/issues/16375).

- `pnpm deploy` no longer copies the workspace root's `packageManager` and `devEngines.packageManager` fields into the deployed `package.json` [#&#8203;16403](https://github.com/pnpm/pnpm/issues/16403).

- `pnpm publish` now includes bare `README` files and README files with Markdown extensions such as `readme.markdown` in registry metadata [#&#8203;12704](https://github.com/pnpm/pnpm/issues/12704).

- `pnpm store prune` now removes the packages that only expired `pnpm dlx` cache entries used. They were left in the store until the next `pnpm store prune` [#&#8203;16383](https://github.com/pnpm/pnpm/discussions/16383).

##### Performance

- Sped up dependency resolution in large workspaces, and when many dependencies request different ranges of the same package. Resolution also uses less memory.

- Sped up `pnpm install` with `nodeLinker: hoisted` on macOS when the lockfile is re-resolved, such as with `autoDedupe` enabled [#&#8203;16397](https://github.com/pnpm/pnpm/issues/16397).

- Sped up extracting package tarballs.

- `pnpm install` without `--frozen-lockfile` is faster on some machines in projects with a `pnpm-workspace.yaml`. Those installs linked with one worker thread per core, half of what a frozen install uses.

- On Windows, warm `pnpm install --frozen-lockfile` runs are 4-5% faster on 4- and 8-core machines. pnpm now links with one worker thread per core on Windows, between 4 and 16. This changes frozen installs and installs in projects without a `pnpm-workspace.yaml` on machines with 3 to 15 cores.

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.8.1`](https://github.com/pnpm/pnpm/releases/tag/v12.8.1): pnpm 12.8.1

[Compare Source](https://github.com/pnpm/pnpm/compare/[email protected])

pnpm 12.8.1 fixes `pnpm install --frozen-lockfile` rejecting lockfiles with injected workspace packages that have peers, restores the executable bit on files of local directory dependencies, makes `pnpm dedupe` converge, and uses less CPU on many-core machines.

##### Patch Changes

- `pnpm install --frozen-lockfile` no longer rejects a freshly generated lockfile when an injected workspace package has peer dependencies [#&#8203;16332](https://github.com/pnpm/pnpm/issues/16332).

- Executable files in a `file:` directory dependency or an injected workspace package keep their executable bit again. Since 12.8.0, pnpm installed these files without the permissions they have in their project.

- `pnpm dedupe` now reaches a stable lockfile when a package's peer suffix is long enough to be hashed. Before, each run could switch that package's key between the hashed and the spelled-out suffix, so `pnpm dedupe --check` always failed [#&#8203;16331](https://github.com/pnpm/pnpm/issues/16331).

- `pnpm install --frozen-lockfile`, the default in CI, now uses less CPU on machines with more than 8 cores. Warm installs on many-core Windows machines got up to 10% faster. Frozen installs now link with at most 16 worker threads.

- `verifyDepsBeforeRun` no longer reports dependencies as outdated after a filtered install just because `pnpm-lock.yaml` has a newer modification time. It checks the lockfile against the packages that install put in place. Before, `pnpm run` reinstalled the whole workspace with lifecycle scripts on, for example after a Docker `COPY` brought in a lockfile with a newer mtime [#&#8203;16322](https://github.com/pnpm/pnpm/issues/16322).

  After a filtered install, `verifyDepsBeforeRun` now also checks that the install put the selected projects' dependencies in place. A `node_modules` directory alone no longer counts as proof.

- `pnpm run` and `pnpm exec` no longer install a project that has never been installed and has nothing to install. Such a project declares no dependencies, no peer dependencies that `autoInstallPeers` would fetch, and no install lifecycle scripts. The command now runs without writing `node_modules` or `pnpm-lock.yaml` [#&#8203;16313](https://github.com/pnpm/pnpm/issues/16313).

- `pnpm update -g --latest` now upgrades globally installed packages beyond their saved version ranges [#&#8203;16320](https://github.com/pnpm/pnpm/issues/16320).

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.8.0`](https://github.com/pnpm/pnpm/releases/tag/v12.8.0): pnpm 12.8

[Compare Source](https://github.com/pnpm/pnpm/compare/[email protected])

pnpm 12.8.0 warns when `pnpm pack` or `pnpm publish` would ship a `.env` file that `files` does not list, installs `sharedWorkspaceLockfile: false` workspaces concurrently, applies every setting passed as `--config.<name>=<value>`, and no longer leaves the Windows terminal stuck after Ctrl+C in a script.

##### Minor Changes

- `pnpm pack` and `pnpm publish` now warn when the tarball includes a `.env` or `.env.*` file that the `files` field of `package.json` does not list. Templates such as `.env.example` are not reported. List the file in `files` to publish it on purpose, or exclude it in `.npmignore` or `.gitignore` [#&#8203;7826](https://github.com/pnpm/pnpm/issues/7826).

- `pnpm pack` now honors `--silent`, `--reporter=silent`, and `--loglevel=silent` to hide the tarball contents and summary. With `--json`, lifecycle script output and the final JSON output remain visible [#&#8203;10297](https://github.com/pnpm/pnpm/issues/10297).

##### Patch Changes

##### Installing packages

- Installing through a `pnpr` server now records the pnpmfile checksum in the lockfile, so a later `pnpm install --frozen-lockfile` accepts that lockfile [#&#8203;14460](https://github.com/pnpm/pnpm/issues/14460). A frozen install through the pnpr server now fails if the pnpmfile changed. If the pnpmfile defines a `readPackage`, `afterAllResolved` or `preResolution` hook or custom resolvers, pnpm resolves dependencies locally and prints a warning that the pnpr server was not used.

  Installing through a `pnpr` server also links a workspace project at the directory its `publishConfig.directory` names. A server that does not forward the setting makes the install fail with `ERR_PNPM_PNPR_PUBLISH_DIRECTORY_MISMATCH`, so pnpm never writes a lockfile that points at the wrong directory. The server rejects a `publishConfig.directory` that points outside its project.

- Installing a git-hosted dependency that has to be built no longer fails when that dependency's own dependencies have build scripts nobody approved. pnpm skips those builds while preparing the dependency, as it does without `strictDepBuilds` [#&#8203;9764](https://github.com/pnpm/pnpm/issues/9764).

- A git-hosted dependency that is a pnpm workspace with no committed lockfile is now detected as a pnpm project [#&#8203;14011](https://github.com/pnpm/pnpm/issues/14011).

- `pnpm install --dev` and `pnpm fetch --dev` now install the optional dependencies of devDependencies, such as the platform binaries of Biome and oxlint. The project's own `optionalDependencies` are still skipped [#&#8203;9678](https://github.com/pnpm/pnpm/issues/9678).

- `pnpm install --offline` and `pnpm add --offline` now resolve a version range to the newest matching version whose tarball is already in the store. They used to pick the newest version in the cached metadata and fail with `ERR_PNPM_NO_OFFLINE_TARBALL` when its tarball was missing [#&#8203;10715](https://github.com/pnpm/pnpm/issues/10715).

- If an offline install fails because the registry metadata cache uses the layout from before pnpm 11.27 and 12.4, the error now names the older mirror on disk and explains that one online install repopulates the cache. The error also carries the `ERR_PNPM_NO_OFFLINE_META` code. `pnpm cache prune --help` now says that pnpm 11.26 and earlier, and pnpm 12.3 and earlier, depend on the directories it removes [#&#8203;15656](https://github.com/pnpm/pnpm/issues/15656).

- Running `pnpm install` now refreshes dependencies when a package declared with a local `file:` directory changes its dependencies [#&#8203;4623](https://github.com/pnpm/pnpm/issues/4623).

- A repeat `pnpm install` now keeps its fast up-to-date check when an override replaces a declared local `file:` dependency [#&#8203;12892](https://github.com/pnpm/pnpm/issues/12892).

- `pnpm install` now removes an optional dependency from `node_modules` if its install script fails. Code that checks whether the package is installed no longer finds a package that cannot load [#&#8203;8756](https://github.com/pnpm/pnpm/issues/8756).

- With `nodeLinker: hoisted`, `pnpm install` now restores a workspace project's `node_modules` after it was deleted. Before, the install printed "Already up to date" and left the project without the dependencies nested under it. On Windows, the install also no longer fails with "Access is denied" when another project's copy of a shared dependency links to the deleted directory.

- Under `nodeLinker: hoisted`, `pnpm install` now clears orphaned package directories that an interrupted or failed install leaves in a project's `node_modules`. A directory recorded by the previous install is removed, while an unrecorded directory is moved to `node_modules/.ignored`. A copy already in `.ignored` is never overwritten [#&#8203;13676](https://github.com/pnpm/pnpm/issues/13676).

- Concurrent installs no longer fail when they replace the same stale hoisted dependency link. Virtual store cleanup now keeps the temporary lockfiles that concurrent installs write.

##### Resolving and linking dependencies

- `pnpm install` no longer aborts on a failed allocation of many gigabytes when peer dependency ranges combine overlapping `||` alternatives [#&#8203;15867](https://github.com/pnpm/pnpm/issues/15867).

- `pnpm install` no longer fails when a package from the registry declares a `file:` dependency on a directory inside itself, such as `"@&#8203;types/css-tree": "file:./typings/css-tree"`. pnpm links that dependency to the directory inside the package, as npm and Yarn do. The lockfile records it as `link:<root>/typings/css-tree` [#&#8203;9141](https://github.com/pnpm/pnpm/issues/9141).

- An `npm:` alias written by `overrides` now stays in place when a change elsewhere makes pnpm re-resolve the aliased dependency. Before, pnpm could look up the alias name at the aliased version, which failed with `ERR_PNPM_NO_MATCHING_VERSION` or locked an unrelated package [#&#8203;16309](https://github.com/pnpm/pnpm/issues/16309).

- A peer dependency no longer resolves to two different versions for one package. This happened when the package peer-depends on another package and on one of that package's peers, and it is installed deeper than a direct dependency of the package that provides them [#&#8203;12098](https://github.com/pnpm/pnpm/issues/12098).

- An optional peer dependency is no longer resolved from another workspace project's package when the project provides one of that package's own peers at a version it rejects. This avoids bogus unmet peer errors [#&#8203;13989](https://github.com/pnpm/pnpm/issues/13989).

- `pnpm dedupe` no longer changes the lockfile on every run when a nested peer dependency is provided through an npm alias [#&#8203;15709](https://github.com/pnpm/pnpm/issues/15709).

- With `resolutionMode: time-based` and `minimumReleaseAge` both set, `pnpm install` no longer reports a subdependency as too new when only the time-based cutoff excludes it. Such subdependencies used to fail a strict install with `ERR_PNPM_NO_MATURE_MATCHING_VERSION`, or were added to `minimumReleaseAgeExclude` [#&#8203;13569](https://github.com/pnpm/pnpm/issues/13569). A transitive dependency that has no matching version published before the time-based cutoff now resolves to the lowest matching version allowed by `minimumReleaseAge`. pnpm picks a version younger than `minimumReleaseAge` only if no older version matches [#&#8203;16298](https://github.com/pnpm/pnpm/issues/16298).

- `pnpm install` retries registry metadata fetches that fail with a timeout, a dropped connection, or an interrupted response body before it applies `trustPolicy` or `minimumReleaseAge`. A transient fetch failure is not reported as `TRUST_DOWNGRADE` or `MINIMUM_RELEASE_AGE_VIOLATION` [#&#8203;12031](https://github.com/pnpm/pnpm/issues/12031).

- pnpm's built-in package compatibility database no longer applies to a project's own manifest. A project named like a published package, such as `vue-loader`, no longer gains dependencies on `pnpm install` or `pnpm update`. User-configured `packageExtensions` still apply to project manifests [#&#8203;11700](https://github.com/pnpm/pnpm/issues/11700).

- Packages in an external `virtualStoreDir` can resolve the project's direct dependencies selected by `hoistPattern`. Run `pnpm install --force` to repair an existing installation [#&#8203;5652](https://github.com/pnpm/pnpm/issues/5652).

- `pnpm install` now links the executables of auto-installed peer dependencies into the workspace root's `node_modules/.bin`, including after a frozen-lockfile reinstall [#&#8203;8511](https://github.com/pnpm/pnpm/issues/8511).

##### Lockfiles and frozen installs

- `pnpm install --frozen-lockfile` now works on a detached HEAD when `gitBranchLockfile` is enabled. The install reads the lockfiles of the local and remote-tracking branches that contain the checked-out commit. It still writes the shared `pnpm-lock.yaml` [#&#8203;7672](https://github.com/pnpm/pnpm/issues/7672).

- `pnpm install --frozen-lockfile` now accepts a lockfile that has no importer entry for a workspace package without dependencies. Such a package added after the lockfile was written made the install fail with `ERR_PNPM_PACKAGE_MANAGER_NO_IMPORTER` [#&#8203;15875](https://github.com/pnpm/pnpm/issues/15875).

- `pnpm install` now fails with `ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY` when an importer references a dependency version that has no snapshot entry. Before, the install succeeded and left a `node_modules` symlink pointing at a missing virtual-store directory [#&#8203;14764](https://github.com/pnpm/pnpm/issues/14764).

- `pnpm install` on CI now fails on an outdated lockfile when `preferFrozenLockfile` is explicitly set to `true`. Setting it to `true` used to let CI update the lockfile [#&#8203;9072](https://github.com/pnpm/pnpm/pull/9072).

- With `gitBranchLockfile` enabled, each emoji or other character outside the Basic Multilingual Plane in a branch name now becomes `!!` in the lockfile name. Before, each such character became one `!`.

##### Workspaces and filtering

- `pnpm install` in a workspace with `sharedWorkspaceLockfile: false` now installs projects concurrently, up to `workspaceConcurrency` at a time [#&#8203;14480](https://github.com/pnpm/pnpm/issues/14480). A project is resolved, fetched, and written to its virtual store without waiting for the workspace projects it depends on. It waits for them only before it links its dependencies and runs its lifecycle scripts, so its scripts still run after theirs. A project with a `preinstall` or `pnpm:devPreinstall` script, or with an injected or `file:` workspace dependency, waits for its workspace dependencies before it starts.

  The installs of the projects also share their package metadata, lockfile verification, and store caches, so they use less CPU and memory when several projects depend on the same packages. An install with a pnpmfile no longer starts an extra Node.js process when the pnpmfile has no `preResolution` hook.

- With `enableGlobalVirtualStore` and `sharedWorkspaceLockfile: false`, each project now keeps its current lockfile and its hidden hoisted dependencies in its own `node_modules/.pnpm`. Before, every project wrote them to the workspace root's `node_modules/.pnpm`, so each repeat install treated the other projects' packages as its own and relinked them [#&#8203;14480](https://github.com/pnpm/pnpm/issues/14480).

- `pnpm rebuild`, `pnpm approve-builds`, and `pnpm ignored-builds` now work on the current project's `node_modules` when they run inside a project of a workspace with `sharedWorkspaceLockfile: false`. They used to read the workspace root's `node_modules`, so `pnpm rebuild` did not rebuild the project's dependencies and created a second virtual store at the workspace root [#&#8203;9402](https://github.com/pnpm/pnpm/issues/9402).

- `pnpm install` no longer creates a `node_modules` symlink inside the `publishConfig.directory` of a workspace package linked with `linkDirectory`. A build tool that cleaned its output directory through that symlink deleted the files of the package's dependencies. `pnpm install` also removes a symlink that an earlier install left there [#&#8203;16226](https://github.com/pnpm/pnpm/issues/16226). It also no longer fails with `ERR_PNPM_CMD_SHIM_RESOLVE_PATH` when such a package has a `bin` field and its `publishConfig.directory` does not exist yet.

- `pnpm install` no longer fails for an injected workspace dependency whose package publishes from a `publishConfig.directory` that its own `prepare` script builds. The injected copy now picks up that directory once `prepare` finishes building it. `pnpm install --frozen-lockfile` no longer reports the dependency as outdated while the directory has not been built yet [#&#8203;7811](https://github.com/pnpm/pnpm/issues/7811).

- An in-place edit to the source of an injected workspace package now shows up in its injected copy, unless a build writes to that package or `packageImportMethod` is set. pnpm hardlinks such packages under the default import method [#&#8203;4410](https://github.com/pnpm/pnpm/issues/4410). Scripts listed in `syncInjectedDepsAfterScripts` now update injected dependencies while they run, so a watcher on the injected package, such as a dev server, sees each change before the script exits.

- With `sharedWorkspaceLockfile: false`, an injected workspace package that has lifecycle scripts is now hard linked into the projects that depend on it. Before, pnpm left a plain copy, so later edits to the package did not reach those projects [#&#8203;9828](https://github.com/pnpm/pnpm/issues/9828).

- `injectWorkspacePackages` now hard links a workspace dependency declared with a relative path, such as `workspace:../foo`, the same way it already does for `workspace:*` [#&#8203;10446](https://github.com/pnpm/pnpm/issues/10446).

- Workspace discovery prunes dot-prefixed directories, so a `packages` pattern such as `**` no longer matches projects inside `.cache` and other hidden directories [#&#8203;16250](https://github.com/pnpm/pnpm/issues/16250).

- `pnpm import` in a workspace now keeps the versions pinned by a `yarn.lock` inside a workspace project [#&#8203;4385](https://github.com/pnpm/pnpm/issues/4385).

##### Store and caches

- Files imported from the store now follow the umask of the install that writes them. Installing with a umask of `077` no longer leaves imported files readable by the group and others [#&#8203;3807](https://github.com/pnpm/pnpm/issues/3807).

- `pnpm install` keeps the owner, group, and mode of files already in a shared store, including `index.db`. New store files and directories inherit the store directory's group-write bit. When that directory is setgid, new files inherit its group. pnpm does not change a file's owner or group [#&#8203;12765](https://github.com/pnpm/pnpm/issues/12765).

- When `pnpm install` repairs a store file that was modified through a hard link in `node_modules`, the repair now keeps the file's inode on Linux and macOS, so hard-linked copies in other projects are healed at the same time. On Windows the repair still replaces the file, so other projects are healed on their next install [#&#8203;3445](https://github.com/pnpm/pnpm/issues/3445).

- `pnpm install` now reports a full store at once when writing package files fails. It no longer retries the tarball [#&#8203;8581](https://github.com/pnpm/pnpm/issues/8581).

- pnpm now warns when it cannot hard link packages from an existing store in the pnpm home directory and falls back to a store on the project's filesystem. This can happen when the project is on another filesystem, such as a bind-mounted workspace in a container. The warning names both stores and suggests setting `storeDir` [#&#8203;14505](https://github.com/pnpm/pnpm/issues/14505).

- The side-effects cache now restores the symlinks that a build script creates inside a package. A warm install used to replace each of them with a copy of its target [#&#8203;12859](https://github.com/pnpm/pnpm/issues/12859).

  After upgrading, every package with a build script is built once more.

- The global virtual store and the side-effects cache now key built packages by the Node.js version that the root project's `devEngines.runtime` or `engines.runtime` pins. That is the Node.js their build scripts run with. A dependency that declares its own `engines.runtime` no longer changes the key for every other package.

- With `enableGlobalVirtualStore`, an install into a fresh `node_modules` no longer runs the build scripts of a dependency whose global virtual store slot an earlier install already built. `pnpm rebuild` still runs them [#&#8203;14480](https://github.com/pnpm/pnpm/issues/14480).

- Concurrent installs that share a global virtual store now run a package's build in its shared slot one at a time. A failed build leaves the slot in place and marks it for the next install to rebuild [#&#8203;15568](https://github.com/pnpm/pnpm/issues/15568).

- A warm `pnpm install` reuses on-disk package metadata for five minutes when the registry does not send an ETag. Registries that send an ETag, including the public npm registry, still revalidate with a conditional request. `pnpm update` still fetches current metadata [#&#8203;13976](https://github.com/pnpm/pnpm/issues/13976).

- pnpm no longer revalidates cached registry metadata when the registry sends `Cache-Control: max-age=0`, `no-cache`, or `no-store`. It downloads the metadata again, so a version newly published to such a registry is visible on the next install [#&#8203;13487](https://github.com/pnpm/pnpm/issues/13487).

- `pnpm install` honors `Cache-Control` for dependencies named with an `http:` or `https:` tarball URL. A fresh response is taken from the store with no request, and a stale one is revalidated with `If-None-Match` [#&#8203;15648](https://github.com/pnpm/pnpm/issues/15648).

##### Patched dependencies

- `pnpm install` now repairs a `pnpm-lock.yaml` whose `(patch_hash=<hash>)` dependency paths disagree with its `patchedDependencies` map, including paths that lack the hash their patch calls for. Before, pnpm accepted such a lockfile as up to date and kept the old patched files. `pnpm install --frozen-lockfile` now fails on such a lockfile with `ERR_PNPM_INCONSISTENT_PATCH_HASH`. It fails with `ERR_PNPM_UNCHECKABLE_PATCH_HASH` when a patch hash in the lockfile is malformed, or when the lockfile lacks the package version or patch entry that the check needs [#&#8203;15336](https://github.com/pnpm/pnpm/pull/15336).

- `pnpm install` with `nodeLinker: hoisted` now applies a patch once to each copy of a patched dependency in a workspace. Before, a copy that several workspace projects shared could receive the patch twice and end up with the patched content duplicated [#&#8203;7565](https://github.com/pnpm/pnpm/issues/7565).

- `pnpm install` and `pnpm fetch` now fail with `ERR_PNPM_PATCH_NOT_FOUND` when a patch file listed in `patchedDependencies` does not exist [#&#8203;5268](https://github.com/pnpm/pnpm/issues/5268).

- `engineStrict` now checks the patched `package.json` when a `patchedDependencies` entry changes `engines`. A patch that relaxes `engines.node` no longer fails the install against the published range [#&#8203;9603](https://github.com/pnpm/pnpm/issues/9603).

- `pnpm patch` now applies the existing patch file to the edit directory of a git-hosted dependency, as it already does for packages from the registry [#&#8203;9699](https://github.com/pnpm/pnpm/issues/9699).

##### Adding, updating, and removing dependencies

- `pnpm add <dir>` now warns when the added directory declares peer dependencies, as `pnpm link` does. The directory is saved as a `link:` dependency, and its peers are not resolved from the project that adds it. Use the `file:` protocol to have them resolved [#&#8203;5523](https://github.com/pnpm/pnpm/issues/5523).

- `pnpm add --save-types` no longer adds a `@types/*` package whose resolved version is deprecated. DefinitelyTyped publishes such stubs for packages that ship their own types, such as `@types/typescript` for `typescript` [#&#8203;15636](https://github.com/pnpm/pnpm/issues/15636).

- `pnpm version`, `pnpm add`, and `pnpm pkg set` keep JSON5 style when they update `package.json5`. ASCII identifier keys stay unquoted, strings keep JSON5 quotes, and indented files keep trailing commas [#&#8203;15717](https://github.com/pnpm/pnpm/issues/15717).

##### Running scripts and commands

- `pnpm run` and `pnpm exec` no longer install dependencies automatically when the root `package.json` still keeps `overrides`, `packageExtensions`, `patchedDependencies`, or `ignoredOptionalDependencies` in its `pnpm` field. pnpm no longer reads that field, so the install rewrote the lockfile without those settings. The command now fails and asks to move the settings to `pnpm-workspace.yaml` [#&#8203;16278](https://github.com/pnpm/pnpm/issues/16278).

- When `verifyDepsBeforeRun` triggers an install before a filtered `pnpm run` or `pnpm exec`, pnpm now installs only the selected projects and their dependencies. A later filtered command also installs a selected project that an earlier filtered install skipped [#&#8203;11865](https://github.com/pnpm/pnpm/issues/11865).

- `pnpm -r run /regexp/` now honors the `tasks` `dependsOn` declared for each script the selector matches, like running the script by name does. Matched scripts that depend on each other run in order. Each matched script runs once [#&#8203;15596](https://github.com/pnpm/pnpm/issues/15596).

- `pnpm run` exits with the code of a script that handles Ctrl+C and shuts down. A script that finished cleanly is not reported as a lifecycle failure. The commands after it in the same script still run [#&#8203;9945](https://github.com/pnpm/pnpm/issues/9945).

- pnpm no longer hangs after a lifecycle script exits while a process it started in the background keeps the script's output open. pnpm stops reading that output one second after the script exits [#&#8203;5730](https://github.com/pnpm/pnpm/issues/5730).

- `pnpm run` and lifecycle scripts use the configured `scriptShell`, including Git Bash on Windows, when `shellEmulator` is also enabled. `shellEmulator` still runs scripts when `scriptShell` is not set. Extra arguments passed to `pnpm run` are quoted for the shell that runs the script, so a Windows path stays intact [#&#8203;14719](https://github.com/pnpm/pnpm/issues/14719).

- With `enableGlobalVirtualStore`, dependency build scripts now see the workspace root's `node_modules/.bin`, as they do with a local virtual store. A `postinstall` script that runs `node` finds the Node.js installed by `devEngines.runtime` and no longer fails with "command not found" on machines without a system Node.js [#&#8203;15652](https://github.com/pnpm/pnpm/issues/15652). Dependency build scripts also see the bins of privately hoisted dependencies.

- Dependency install scripts now find the node-gyp bundled with pnpm when pnpm runs through a symlink, such as `node_modules/.bin/pnpm` or the `pnpm` that `npm install -g pnpm` links. They used to fail with `node-gyp: command not found` on macOS [#&#8203;15694](https://github.com/pnpm/pnpm/issues/15694).

- `pnpm run` and lifecycle scripts now set `npm_config_node_gyp` to the bundled `node-gyp` entry point. Tools that read the variable resolve the same `node-gyp` pnpm builds with. An `npm_config_node_gyp` value the environment already sets is kept as is [#&#8203;16270](https://github.com/pnpm/pnpm/issues/16270).

- Scripts now see the `npm_command` environment variable that npm sets. It holds `run-script` when the command runs a script, and the command's own name otherwise [#&#8203;16265](https://github.com/pnpm/pnpm/issues/16265).

- Commands run from a POSIX shell through a dependency's own `node_modules/.bin`, such as `node_modules/vite/node_modules/.bin/esbuild`, no longer fail with `MODULE_NOT_FOUND` [#&#8203;10189](https://github.com/pnpm/pnpm/issues/10189).

- `pnpx --version` and `pnpm dlx --version` now print the pnpm version. Other unknown options before the command are reported as errors. Before, pnpm tried to download a package named after the option [#&#8203;16259](https://github.com/pnpm/pnpm/issues/16259).

- `pnpm dlx` now keeps the virtual store of its cached installs in `node_modules/.pnpm`, like every other install [#&#8203;13955](https://github.com/pnpm/pnpm/issues/13955). `pnpm pack-app` now names the manifest of its runtime install directory `pnpm-pack-app-<target>`.

##### Publishing, packing, and deploying

- `pnpm pack` and `pnpm publish` now ship a file that the `files` field names even when another entry excludes the directory holding it. For example, `["**", "!dist", "dist/index.d.ts"]` ships `dist/index.d.ts` [#&#8203;16213](https://github.com/pnpm/pnpm/issues/16213).

- `pnpm pack` prunes a directory that a `files` field exclusion names, such as `!**/test`, excluding the directory and its contents from the packed package [#&#8203;15738](https://github.com/pnpm/pnpm/issues/15738).

- `pnpm publish` now waits at least 5 minutes for the registry to answer a publish request, like npm. This fixes "409 Conflict - Failed to save packument" errors when the registry is slow to answer [#&#8203;11454](https://github.com/pnpm/pnpm/issues/11454).

- `pnpm deploy --prod` no longer fails with `ERR_PNPM_OUTDATED_LOCKFILE` when the deployed project declares a `devEngines.runtime` with `onFail: download`. The runtime stays out of the deployed `node_modules` with the rest of the dev dependencies [#&#8203;15703](https://github.com/pnpm/pnpm/issues/15703).

- `pnpm deploy` with a shared lockfile now copies workspace dependencies into the deploy directory, even when `packageImportMethod` is set to `hardlink`. Before, their files were hard-linked to the workspace sources, so editing a source file also changed the deployed copy [#&#8203;12176](https://github.com/pnpm/pnpm/issues/12176).

- `pnpm deploy --legacy` no longer leaves broken links to nested local dependencies of workspace packages [#&#8203;9575](https://github.com/pnpm/pnpm/issues/9575).

##### Configuration and pnpmfile hooks

- Every setting pnpm supports can now be set with `--config.<name>=<value>` on the command line, not only the ones whose command also carries a matching flag. Before, `pnpm install --config.frozen-lockfile=true` dropped the setting and rewrote `pnpm-lock.yaml` as though the install had not been frozen [#&#8203;16276](https://github.com/pnpm/pnpm/issues/16276).

- Settings given on the command line, such as `--registry` and `--store-dir`, now take precedence over the values a pnpmfile `updateConfig` hook sets [#&#8203;14063](https://github.com/pnpm/pnpm/issues/14063).

- `pnpm config set --location=project` and `pnpm config delete --location=project`, run from a package inside a workspace, now write settings that belong in `pnpm-workspace.yaml` to the workspace root's `pnpm-workspace.yaml`. Before, they created a new `pnpm-workspace.yaml` in the current package, which made that package the workspace root. Settings stored in `.npmrc` are still written to the current directory [#&#8203;13757](https://github.com/pnpm/pnpm/issues/13757).

- pnpm now reads the workspace directory override from `PNPM_CONFIG_WORKSPACE_DIR`, like other settings. `NPM_CONFIG_WORKSPACE_DIR` still works as a fallback [#&#8203;16275](https://github.com/pnpm/pnpm/issues/16275).

- pnpm now fails with `ERR_PNPM_AUTH_INVALID_BASE64` when a registry's `_password` in `.npmrc` is not valid base64. Before, it sent the value as the raw password. A `username` or `_password` left empty, for example by an unset environment variable, now supplies no credential [#&#8203;16273](https://github.com/pnpm/pnpm/issues/16273).

- `proxy=false` now turns proxying off even when `HTTP_PROXY`, `HTTPS_PROXY`, or `ALL_PROXY` is set. pnpm no longer sends requests through a proxy named only in `ALL_PROXY`.

- `pnpm install` now runs the install hooks of a config dependency plugin's pnpmfile, including `readPackage`, `afterAllResolved`, and custom resolvers. Its pnpmfile is also counted in `pnpmfileChecksum`. Before, only the plugin's `updateConfig` hook ran, so a plugin could not change the resolved dependencies.

- A pnpmfile `fetchers` hook now runs once per package on a fresh install when it handles a resolution with a custom `type` or delegates a git-hosted one to the same subdirectory [#&#8203;15584](https://github.com/pnpm/pnpm/issues/15584). These packages were fetched a second time for installation, so the installed files could come from a different archive than the one their dependencies were read from. The hook also no longer runs twice when a `resolvers` hook returns a tarball resolution without a manifest [#&#8203;15025](https://github.com/pnpm/pnpm/issues/15025).

- `pnpm install` now re-fetches a package from a custom resolver when the `integrity` of its resolution changes, with or without `enableGlobalVirtualStore`. It used to update the lockfile but keep the old files in `node_modules` [#&#8203;15670](https://github.com/pnpm/pnpm/issues/15670).

- `pnpm install` now rejects invalid results from a `readPackage` hook. A hook that returns a non-object value fails with `ERR_PNPM_BAD_READ_PACKAGE_HOOK_RESULT` [#&#8203;15730](https://github.com/pnpm/pnpm/issues/15730). A hook that sets a dependency range to a value other than a string, such as `undefined`, fails with an error that names the dependency, the package and the pnpmfile. Delete the property to remove a dependency [#&#8203;15705](https://github.com/pnpm/pnpm/issues/15705).

##### Global packages, pnpm versions, and runtimes

- `pnpm update --global` now reinstalls the global packages that pnpm 10 installed into the previous global directory, `<global-dir>/5`, so their commands are linked into the pnpm home `bin` directory again and `pnpm list --global` lists them. Once every package is migrated, pnpm deletes the previous directory and the commands pnpm 10 linked into the pnpm home [#&#8203;11528](https://github.com/pnpm/pnpm/issues/11528).

- A signal sent to pnpm, such as `SIGTERM`, now reaches the pnpm that pnpm switches to because of `packageManager` or `devEngines.packageManager`, and the one that `pnpm with` runs. The signal used to be dropped, so scripts running under that pnpm never got to shut down [#&#8203;9948](https://github.com/pnpm/pnpm/issues/9948).

- On arm64 musl Linux, such as Alpine on ARM, switching to a pinned pnpm older than 12 now runs the JavaScript `pnpm` package. The standalone executable of those versions crashed at startup on that platform [#&#8203;10443](https://github.com/pnpm/pnpm/issues/10443).

- Global shims such as `node` now work when pnpm runs through a relative symlink, as with a Homebrew install. They were copies of that symlink and did not resolve from the global bin directory [#&#8203;15691](https://github.com/pnpm/pnpm/issues/15691).

- `pnpm env remove --global` deletes Node.js versions that pnpm installed into its own store, including when another tool installed pnpm [#&#8203;8357](https://github.com/pnpm/pnpm/issues/8357).

- `pnpm self-update` no longer suggests a downgrade when `minimumReleaseAge` holds back the registry's `latest` release. It now says that release is still within the cutoff [#&#8203;12006](https://github.com/pnpm/pnpm/issues/12006).

##### Windows

- Interrupting a script with Ctrl+C on Windows no longer leaves the terminal stuck [#&#8203;14860](https://github.com/pnpm/pnpm/issues/14860). A script that runs through a batch shim, as `vite dev` does through `vite.CMD`, made cmd.exe wait forever on its "Terminate batch job (Y/N)?" answer, and every following keystroke went to that prompt. pnpm now ends a cmd.exe script shell once it has sat for a second after the interrupt with nothing running under it. A script that takes longer to shut down is still waited for. A second Ctrl+C ends the script's shell at once.

- On Windows, `pnpm run` now passes the arguments after the script name to the script as typed. Before, `cmd` expanded `%VAR%` in them and backslashes arrived doubled. Line breaks still arrive as the two characters `\n`, because `cmd` cannot pass them. The command line pnpm prints for the script quotes the arguments the same way on every platform [#&#8203;16257](https://github.com/pnpm/pnpm/issues/16257).

- The Windows `pnpm.exe` runs on a clean Windows install that does not have the Visual C++ Redistributable. It used to exit immediately on startup because that runtime was missing [#&#8203;15723](https://github.com/pnpm/pnpm/issues/15723).

- On Windows, the `.cmd` command shims in `node_modules/.bin` now keep a `%` in the project path. Before, cmd.exe expanded it as a variable reference, so the command received a mangled `NODE_PATH` [#&#8203;15716](https://github.com/pnpm/pnpm/issues/15716). Command shims also run tools whose paths contain non-ASCII characters [#&#8203;6999](https://github.com/pnpm/pnpm/issues/6999), including the PowerShell shims in Windows PowerShell 5.1 [#&#8203;16217](https://github.com/pnpm/pnpm/issues/16217).

- Bin shims in `node_modules/.bin` run from Cygwin on Windows again. The shims passed a `/cygdrive/c/...` path to the Windows `node` found on `PATH`, so Node.js failed with `Cannot find module 'C:\cygdrive\c\...'` [#&#8203;12845](https://github.com/pnpm/pnpm/issues/12845).

- On Windows, installing pnpm with npm inside a project now writes `node_modules/.bin` shims that run `pnpm.exe`. A global install with `npm install --location=global` now gets the same shims as `npm install -g` [#&#8203;15688](https://github.com/pnpm/pnpm/issues/15688).

- `pnpm install` no longer fails with `ERR_PNPM_WORKSPACE_INVALID_GLOB` on Windows for a wildcard pattern such as `plugins/*/*` in `pnpm-workspace.yaml` when the workspace is on a different drive than the pnpm cache or state directory [#&#8203;16239](https://github.com/pnpm/pnpm/issues/16239).

- On Windows, `pnpm install` no longer skips a dependency's build script on a later install when the package ships an executable file and the script changes nothing inside the package directory [#&#8203;15667](https://github.com/pnpm/pnpm/issues/15667).

- `pnpm setup` no longer writes the `pn.ps1`, `pnpx.ps1`, and `pnx.ps1` PowerShell wrappers. It also removes the ones an earlier setup wrote. PowerShell now runs `pn`, `pnpx`, and `pnx` through their `.cmd` wrappers, like `pnpm` itself. Before, these aliases failed with a "not digitally signed" error wherever the execution policy blocks unsigned scripts [#&#8203;8444](https://github.com/pnpm/pnpm/issues/8444).

- `pnpm setup` on Windows no longer panics when an unrelated environment variable has a name containing a non-ASCII character. It skips that variable [#&#8203;15684](https://github.com/pnpm/pnpm/issues/15684).

- On Windows, `pnpm setup` repairs the `PNPM_HOME` registry type left by older pnpm versions, even when the configured directory has not changed.

- On Windows, the `ERR_PNPM_BAD_ENV_FOUND` error of `pnpm setup` now shows the value `PNPM_HOME` is currently set to. Before, it showed the directory pnpm wanted to set.

- On Windows, pnpm expands nested `%VAR%` references in `PNPM_HOME` and the other directory environment variables it uses for its home, store, cache, state, and config directories. pnpm fails with an error when a `%VAR%` reference remains after expansion [#&#8203;13236](https://github.com/pnpm/pnpm/issues/13236).

- On Windows, if the global bin directory is not in `PATH` and a `PATH` entry still contains an unexpanded variable such as `%PNPM_HOME%`, the error now names that entry. A variable referenced from the user `Path` must be set to a full path and stored as a plain string (`REG_SZ`) for the entry to expand [#&#8203;5283](https://github.com/pnpm/pnpm/issues/5283).

##### Inspecting dependencies

- `pnpm audit` and `pnpm audit signatures` now fail with an error when the lockfile contains unresolvable dependency references [#&#8203;13638](https://github.com/pnpm/pnpm/issues/13638).

- `pnpm licenses list` now reports the actual on-disk package locations when using `nodeLinker: hoisted` or `shamefully-hoist: true` [#&#8203;8589](https://github.com/pnpm/pnpm/issues/8589). With `--json`, its `paths` array now includes every installed copy of a package, including hoisted copies and isolated installations with different peer dependencies.

- `pnpm root` now prints the configured `modulesDir`. It used to print `node_modules` regardless of the setting. A project's own `modulesDir` from `packageConfigs` is printed too [#&#8203;9113](https://github.com/pnpm/pnpm/issues/9113).

##### Output and messages

- With the default and append-only reporters, installs with `--loglevel warn` or `--loglevel error` now print the full output of a failed install script. The output of successful scripts, including the root project's own install hooks, stays hidden. With `--loglevel warn`, pnpm also prints ignored build script warnings.

- When a dependency fails to resolve, the error now shows the cause. For example, a Node.js runtime download behind a proxy that re-signs TLS now reports `invalid peer certificate: UnknownIssuer` [#&#8203;9556](https://github.com/pnpm/pnpm/issues/9556).

- When installing a git dependency over SSH fails with `Permission denied (publickey)`, pnpm suggests checking the loaded keys with `ssh-add -l`. Resolving an SSH URL that refuses the key also shows a local HTTPS rewrite that leaves the recorded URL alone [#&#8203;13743](https://github.com/pnpm/pnpm/issues/13743).

- Lockfile verification now fails with `ERR_PNPM_TARBALL_URL_MISMATCH`, `ERR_PNPM_TARBALL_REVISION_MISMATCH`, or `ERR_PNPM_MISSING_NAMED_REGISTRY` when every rejected entry failed that check. These failures were reported as the generic `ERR_PNPM_LOCKFILE_RESOLUTION_VERIFICATION`.

- The lockfile verification error now suggests relaxing the policy that flagged an entry only if a fresh resolution still fails and you trust the affected packages. Errors from checks that no policy controls, such as a missing tarball integrity, no longer suggest relaxing a policy [#&#8203;14411](https://github.com/pnpm/pnpm/issues/14411).

- `pnpm install` no longer prints an extra `Progress:` line after the progress line is marked `done` [#&#8203;16184](https://github.com/pnpm/pnpm/issues/16184).

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

### [`v12.7.0`](https://github.com/pnpm/pnpm/releases/tag/v12.7.0): pnpm 12.7

[Compare Source](https://github.com/pnpm/pnpm/compare/v12.6.0...v12.7.0)

pnpm 12.7.0 ships with `.nvmrc` and `.node-version` support in the global `node` shim, `pnpm install --allow-build`, `pnpm publish --publish-wait-timeout`, and `pnpm-workspace.yaml` created from the `workspaces` field. `pnpm install --force` no longer installs optional dependencies built for other platforms. This release also carries security fixes for bin shims on Nix, for lifecycle scripts of packages in a `storeDir` inside the workspace, and for `userAgent` placeholders in `pnpm-workspace.yaml`.

##### Minor Changes

- `pnpm install --force` now keeps skipping optional dependencies whose `os`, `cpu` or `libc` do not match the host. It still refetches every package and lifts `engineStrict`. The new `forceIgnoresPlatform` setting restores the previous behaviour, installing optional dependencies of every platform under `--force` [#&#8203;6133](https://github.com/pnpm/pnpm/issues/6133).

- The global `node` shim created by pnpm now uses the Node.js version from the nearest `.nvmrc` or `.node-version` file when the project does not declare a Node.js runtime in `devEngines.runtime` or `engines.runtime` [#&#8203;4471](https://github.com/pnpm/pnpm/issues/4471). The nearest directory with a Node.js runtime declaration decides the version. Within one directory, `package.json` takes precedence over `.node-version`, which takes precedence over `.nvmrc`. An `.nvmrc` value that only nvm can act on, such as `system` or a custom alias, is ignored.

- `pnpm install` now supports the `--allow-build` option to selectively allow or deny package lifecycle scripts and record them in `pnpm-workspace.yaml` [#&#8203;15388](https://github.com/pnpm/pnpm/issues/15388).

- Added `pnpm publish --publish-wait-timeout <milliseconds>` to wait for published versions and their tarballs to become available from the registry. Set `publishWaitTimeout` in `pnpm-workspace.yaml` to configure a default. A value of `0` disables the check.

  Recursive publishing confirms availability before publishing dependent packages. If confirmation times out, the command fails.

  When `pnpm publish -r --report-summary` fails after some uploads were accepted, the summary file now lists those packages.

- `pnpm install` now creates `pnpm-workspace.yaml` from the `workspaces` field of the root `package.json` when the repository has no `pnpm-workspace.yaml`. The projects the field lists are linked on that same install. An existing `pnpm-workspace.yaml` is never changed. With `--ignore-workspace`, no file is created. If the `workspaces` field later differs from `packages` in `pnpm-workspace.yaml`, pnpm prints a warning [#&#8203;2255](https://github.com/pnpm/pnpm/issues/2255).

- When a project pins a pnpm version or a runtime that another pnpm process is installing at that moment, pnpm now waits a few seconds and then installs and runs a private copy of its own. It used to wait up to five minutes and then use the shared install directory without the lock. The private copy is removed once the command has run. `pnpm store prune` removes any private copy that a killed process left behind [#&#8203;15413](https://github.com/pnpm/pnpm/issues/15413).

- pnpm now keeps the blank lines between entries of `package.json` when it updates the file, for example on `pnpm add` [#&#8203;5602](https://github.com/pnpm/pnpm/issues/5602).

##### Patch Changes

##### Security

- pnpm no longer expands environment variables in a `userAgent` set in a project's `pnpm-workspace.yaml`. A `userAgent` with a placeholder in that file is now ignored. Before this fix, pnpm sent the variable's value to the configured registry [#&#8203;15415](https://github.com/pnpm/pnpm/issues/15415).

- On Nix, a dependency's bin named like a system utility such as `sed` can no longer redirect a POSIX bin shim or the `pnpm`, `pn`, `pnpx`, and `pnx` launchers. The shims and launchers now ignore `node_modules` and relative `PATH` entries while they locate their own files. Installing again replaces the shims already in `node_modules` [#&#8203;14883](https://github.com/pnpm/pnpm/issues/14883).

- pnpm no longer treats manifests inside its store, cache, state, or modules directories as workspace projects. Before, a `storeDir` inside the workspace could let lifecycle scripts of packages in the store run without `allowBuilds` approval [#&#8203;15033](https://github.com/pnpm/pnpm/issues/15033).

- Packages that run a lifecycle script are no longer hard-linked into the virtual store, so a build script can no longer rewrite the workspace source of an injected package or the store copy it was imported from [#&#8203;15483](https://github.com/pnpm/pnpm/issues/15483).

##### Installing packages

- Fixed `pnpm install`, `pnpm add`, `pnpm remove`, and `pnpm peers check` running out of memory when many packages share a missing peer dependency. This mostly affected projects with `autoInstallPeers: false` [#&#8203;15362](https://github.com/pnpm/pnpm/issues/15362).

- pnpm no longer hangs for up to 5 minutes after a pnpm process was killed while setting up the pnpm version pinned in `packageManager` or `devEngines` [#&#8203;15360](https://github.com/pnpm/pnpm/issues/15360), [#&#8203;15393](https://github.com/pnpm/pnpm/issues/15393). The killed process left behind a lock that every later pnpm command in the project waited on. pnpm now detects that the process holding a lock is gone and takes the lock over at once. The same applies to the locks pnpm takes while installing a managed runtime or writing the global bin directory. Two pnpm processes that are both still running keep waiting for each other as before.

- Requests to a registry or tarball server whose TLS certificate fails verification now fail at once. Such requests were retried for more than a minute without any output [#&#8203;9134](https://github.com/pnpm/pnpm/issues/9134).

- On macOS, pnpm now falls back to its bundled CA roots when system trust evaluation is unavailable, such as in a sandbox or when macOS cannot create an SSL policy for a registry connection. Installs failed or crashed on the first registry request in that case. Custom `ca` certificates are now honored directly [#&#8203;15329](https://github.com/pnpm/pnpm/issues/15329), [#&#8203;14461](https://github.com/pnpm/pnpm/issues/14461).

- `pnpm install` now caps concurrent connections to a proxy at 50 sockets by default [#&#8203;15280](https://github.com/pnpm/pnpm/issues/15280). It also immediately retries transient connection resets when downloading package archives.

- `pnpm install` now reuses a package already present in the store when an existing lockfile entry satisfies the dependency, avoiding registry requests that fail without authorization [#&#8203;2522](https://github.com/pnpm/pnpm/issues/2522).

- Installing or adding dependencies no longer fails when a previously installed local tarball file was deleted from disk [#&#8203;8367](https://github.com/pnpm/pnpm/issues/8367).

- `pnpm install` now installs the new version of a local tarball dependency whose file was replaced at the same path [#&#8203;2437](https://github.com/pnpm/pnpm/issues/2437). `pnpm install --frozen-lockfile` rejects such a changed tarball, even when the previous archive contents are in the store [#&#8203;1889](https://github.com/pnpm/pnpm/issues/1889).

- `pnpm install` now fetches committed submodules of git dependencies [#&#8203;1470](https://github.com/pnpm/pnpm/issues/1470).

- `pnpm install` now applies patches produced by `pnpm patch-commit` when an edit removes the trailing lines of a file along with its newline. The install no longer fails with `ERR_PNPM_INVALID_PATCH` ("expected end of hunk") [#&#8203;12451](https://github.com/pnpm/pnpm/issues/12451).

- `pnpm install` now preserves existing `node_modules` directories when a cross-device move reports `EXDEV` [#&#8203;14504](https://github.com/pnpm/pnpm/issues/14504).

- `pnpm install` no longer fails when writing the workspace state file encounters an error. Failures to update the state file now emit a warning instead of aborting the install [#&#8203;14550](https://github.com/pnpm/pnpm/issues/14550).

- Interrupting `pnpm install` with Ctrl+C or SIGTERM no longer leaves a temporary lockfile (`.pnpm-lock.yaml.*.tmp`) behind in the project [#&#8203;1418](https://github.com/pnpm/pnpm/issues/1418).

- `pnpm install` now relinks a direct dependency whose link in `node_modules` points to a missing target. Before, it reported "Already up to date" and left the broken link [#&#8203;9758](https://github.com/pnpm/pnpm/issues/9758).

- `pnpm install` uses less CPU when it links packages from a warm store. On Windows, a warm install could take several times longer than with pnpm 11 [#&#8203;15439](https://github.com/pnpm/pnpm/issues/15439).

- `pnpm install` now runs `node --version` once per run. A workspace whose projects keep their own lockfiles (`sharedWorkspaceLockfile: false`) previously ran the probe once or twice for every project, and on macOS the concurrent launches waited on each other, so a project could wait several seconds before its linking started.

- A repeat `pnpm install --frozen-lockfile` with `nodeLinker: hoisted` in a workspace no longer re-links `node_modules` when nothing changed.

- Custom fetcher hooks no longer run a second time during installation when an archive was already fetched during dependency resolution [#&#8203;15025](https://github.com/pnpm/pnpm/issues/15025).

- Fixed a package resolved by a `resolvers` pnpmfile hook installing without its own dependencies. This happened when the hook returned no `manifest` and a `fetchers` hook handled the resolution [#&#8203;15552](https://github.com/pnpm/pnpm/issues/15552).

- `pnpm install --prod` and other installs that skip `devDependencies` no longer run the `pnpm:devPreinstall` script [#&#8203;7065](https://github.com/pnpm/pnpm/issues/7065). They skip `prepare` lifecycle scripts too, as do installs given package arguments.

- `pnpm prune --prod` and production installs now remove devDependencies when `lockfile: false` is configured [#&#8203;2677](https://github.com/pnpm/pnpm/issues/2677).

- `pnpm install --prod`, `pnpm fetch --prod` and `pnpm deploy --prod` no longer install a devDependency that is only there to satisfy an optional peer dependency of a production dependency. `pnpm list`, `pnpm why`, `pnpm licenses`, `pnpm sbom` and `pnpm audit` leave it out of `--prod` results too. The same applies to `--dev`. A peer that is not optional is still installed and audited [#&#8203;15344](https://github.com/pnpm/pnpm/issues/15344).

- `pnpm install` no longer skips optional dependencies that the Node.js version locked for a `devEngines.runtime` range supports, when the range uses `onFail: download`. An explicitly set `nodeVersion` still takes priority [#&#8203;14628](https://github.com/pnpm/pnpm/issues/14628).

- `pnpm fetch` now also installs the pnpm version that `pnpm-lock.yaml` pins, when it differs from the running pnpm. A later `pnpm install --offline` that switches to the pinned version no longer fails because that version is missing from the store [#&#8203;11808](https://github.com/pnpm/pnpm/issues/11808).

- A dependency that ships a `binding.gyp` and sets `gypfile: false` no longer gets the `node-gyp rebuild` install script pnpm synthesizes for it. Such a dependency needs no `allowBuilds` entry and is no longer listed under "Ignored build scripts".

- `pnpm install` no longer adds `allowBuilds` placeholder entries to `pnpm-workspace.yaml` when it runs in CI or without a terminal. Interactive installs still add them [#&#8203;11574](https://github.com/pnpm/pnpm/issues/11574).

- pnpm now detects the same CI environments as pnpm 11, including AWS CodeBuild, which does not set `CI`. On these services `pnpm install` uses a frozen lockfile by default and fails with `ERR_PNPM_OUTDATED_LOCKFILE` when the lockfile is outdated.

##### Resolving and linking dependencies

- Installing through a pnpr server now installs a project's peer dependencies when `autoInstallPeers` is enabled. A project that declared only peer dependencies failed with `ERR_PNPM_OUTDATED_LOCKFILE` or skipped its peers [#&#8203;14833](https://github.com/pnpm/pnpm/issues/14833).

- pnpm now installs a dependency that a package also declares as an optional peer dependency, for example `lightningcss` in some vite builds. The dependency was missing from `node_modules`, so the package failed to import it [#&#8203;8912](https://github.com/pnpm/pnpm/issues/8912).

- Removal overrides such as `"parent>peer": "-"` now prevent optional peers from being installed from another workspace package [#&#8203;15008](https://github.com/pnpm/pnpm/issues/15008).

- Removing an entry from `overrides` now re-resolves the packages it targeted. A version the override had locked is no longer kept just because the declared range still accepts it [#&#8203;4587](https://github.com/pnpm/pnpm/issues/4587).

- `packageExtensions` and `overrides` entries with a ranged selector (such as `@<X` or `@*`) no longer match a dependency that has no `package.json`, such as a local directory dependency [#&#8203;15007](https://github.com/pnpm/pnpm/issues/15007).

- Trim leading and trailing whitespace from dependency override selectors in `pnpm.overrides` [#&#8203;6356](https://github.com/pnpm/pnpm/issues/6356).

- With `trustPolicy: no-downgrade`, pnpm now resolves the newest matching version that is not a trust downgrade. Previously a dependency failed with `ERR_PNPM_TRUST_DOWNGRADE` even when an older version satisfied its range. `pnpm self-update` picks its target version the same way. A request for an exact version still fails [#&#8203;14176](https://github.com/pnpm/pnpm/issues/14176).

- `pnpm install` now re-resolves a dependency when its manifest range is updated from a prerelease to a stable version. The lockfile previously retained the prerelease version and caused `--frozen-lockfile` to fail [#&#8203;15528](https://github.com/pnpm/pnpm/issues/15528).

- `pnpm install --ignore-pnpmfile` no longer removes `pnpmfileChecksum` from an up-to-date `pnpm-lock.yaml`. `pnpm install --frozen-lockfile --ignore-pnpmfile` no longer fails with `ERR_PNPM_LOCKFILE_CONFIG_MISMATCH` when the lockfile records a `pnpmfileChecksum`. A command that resolves dependencies with the pnpmfile ignored still writes the lockfile without it [#&#8203;10944](https://github.com/pnpm/pnpm/issues/10944).

- `pnpm install` and `pnpm peers check` now use local tarball packages' actual versions when checking peer dependencies. Compatible packages no longer fail with `strictPeerDependencies` enabled.

- `pnpm peers check` and the install-time peer dependency check now resolve peer dependencies from the workspace root when `resolvePeersFromWorkspaceRoot` is enabled [#&#8203;14982](https://github.com/pnpm/pnpm/issues/14982).

- `autoDedupe` and `pnpm dedupe` now move transitive dependencies to the version a `catalog:` dependency pins, as they already did for versions written directly in `package.json`. Previously they could move those dependencies to a higher version and keep both versions in the lockfile.

- `pnpm dedupe` now produces a stable lockfile when a dependency's range matches both a direct dependency and an `npm:` alias of the same package. The dependency resolves to the version of the direct dependency. Repeated runs previously alternated between two lockfiles [#&#8203;15588](https://github.com/pnpm/pnpm/issues/15588).

- Merging lockfiles now preserves recorded configuration fields such as `overrides`, `neverBuiltDependencies`, `patchedDependencies`, `packageExtensionsChecksum`, `settings`, and `catalogs` [#&#8203;8366](https://github.com/pnpm/pnpm/issues/8366).

- A lockfile entry whose resolution is unchanged now keeps its recorded `deprecated` message [#&#8203;5772](https://github.com/pnpm/pnpm/issues/5772).

- pnpm no longer writes a package's legacy array-form `engines`, such as `["node >= 0.8"]`, to the lockfile. It was recorded as an object keyed by index, such as `{'0': node >= 0.8}` [#&#8203;4518](https://github.com/pnpm/pnpm/issues/4518).

- Tarball URLs recorded in the lockfile now strip default HTTP and HTTPS ports (`:80` and `:443`) [#&#8203;15539](https://github.com/pnpm/pnpm/issues/15539).

- `node_modules/.package-map.json` no longer contains entries that point at directories that do not exist. Such entries appeared for packages installed only with peer dependencies, most visibly with `enableGlobalVirtualStore` [#&#8203;14938](https://github.com/pnpm/pnpm/issues/14938).

- With `nodeLinker: hoisted`, `hoistWorkspacePackages` now links each workspace project that `hoistPattern` or `publicHoistPattern` selects into the root `node_modules`, unless a hoisted package or a root dependency already uses its name. The project's bins are linked into the root `node_modules/.bin` [#&#8203;7553](https://github.com/pnpm/pnpm/issues/7553).

- With `nodeLinker: hoisted`, `pnpm install` now removes the commands of the packages it removes from `node_modules/.bin`, such as a nested copy deduped into the root `node_modules` [#&#8203;7568](https://github.com/pnpm/pnpm/issues/7568).

- `pnpm install` no longer puts a dependency's bin on `PATH` for that dependency's own lifecycle scripts before the bin's file exists. pnpm links such a bin after the dependency's build has run. It also removes such a bin left by an earlier install. This fixes installing the `node` package on Windows [#&#8203;15501](https://github.com/pnpm/pnpm/issues/15501).

- Dependencies and executable binaries are now correctly linked and accessible for workspace packages using `publishConfig.directory` and `publishConfig.linkDirectory` [#&#8203;8338](https://github.com/pnpm/pnpm/issues/8338).

- Bin linking leaves workspace and linked dependency files outside node\_modules unchanged. Already executable bin files no longer receive redundant permission changes.

##### Workspaces and filtering

- `pnpm install` now finds workspace projects reached through a symlink, such as a `packages` directory that links to a folder outside the workspace. It installs their dependencies, and the links in their `node_modules` resolve [#&#8203;1044](https://github.com/pnpm/pnpm/issues/1044).

- A dependency declared with `catalog:` now counts as a workspace dependency when its catalog entry points at a workspace project, for example `workspace:*` [#&#8203;15587](https://github.com/pnpm/pnpm/issues/15587). With `linkWorkspacePackages` enabled, so does an `npm:` alias of a workspace project, such as `"math-alias": "npm:math@^1.0.0"`. `pnpm -r run` runs that project first. `--filter <pkg>...` selects it.

- A `workspace:` dependency now resolves to a workspace project whose version is not valid semver, such as `1` or `1.0`. `workspace:*`, `workspace:^`, and `workspace:~` match it. A range identical to the version also matches it [#&#8203;4567](https://github.com/pnpm/pnpm/issues/4567).

- A `workspace:` dependency with an exact version now resolves to a workspace project whose version carries SemVer build metadata. For example, `workspace:0.5.6-next.3` matches a project at `0.5.6-next.3+f60facc` [#&#8203;6483](https://github.com/pnpm/pnpm/issues/6483).

- Secondary dependencies now prefer the version resolved by the local project's direct dependencies over versions from sibling workspace projects [#&#8203;7191](https://github.com/pnpm/pnpm/issues/7191).

- `pnpm install` now re-resolves a workspace project's auto-installed peer dependency when another workspace project changes its specifier for that package to one that excludes the locked version but still overlaps the peer range. The peer then resolves to the version a fresh install would pick [#&#8203;11800](https://github.com/pnpm/pnpm/issues/11800).

- `pnpm install --frozen-lockfile` now fails with `ERR_PNPM_OUTDATED_LOCKFILE` when `pnpm-lock.yaml` lists a workspace project whose directory or manifest file is missing. The install used to report success without installing that project's dependencies [#&#8203;7667](https://github.com/pnpm/pnpm/issues/7667).

- `pnpm install -r` now installs every workspace project when `recursiveInstall` is set to `false` in `pnpm-workspace.yaml` [#&#8203;7504](https://github.com/pnpm/pnpm/issues/7504).

- `pnpm install` with `--filter` now installs only the dependencies of the selected projects when using `nodeLinker: hoisted` [#&#8203;8882](https://github.com/pnpm/pnpm/issues/8882).

- `pnpm install` now updates an injected workspace dependency after that package's own dependencies change, when `shared-workspace-lockfile` is `false` [#&#8203;7209](https://github.com/pnpm/pnpm/issues/7209).

- `pnpm install` now copies the output of a workspace package's own `prepare`, `install`, or `postinstall` script into the injected copies of that package. Before, the injected copies kept only the files that existed before the script ran. `syncInjectedDepsAfterScripts` now also works when `modulesDir` is set [#&#8203;9464](https://github.com/pnpm/pnpm/issues/9464).

- `syncInjectedDepsAfterScripts` now copies files into injected dependencies when `node_modules` is on another filesystem than the package sources. The sync previously failed with a cross-device link error and made the script run exit with an error [#&#8203;14703](https://github.com/pnpm/pnpm/issues/14703).

- A `modulesDir` with several path segments, such as `www/modules`, now puts each workspace project's dependencies in `<project>/www/modules` on both fresh and frozen installs, and `pnpm bin` prints `<project>/www/modules/.bin` [#&#8203;15484](https://github.com/pnpm/pnpm/issues/15484).

- With `nodeLinker: hoisted`, pnpm now installs the root project's dependencies into a custom `modulesDir` instead of `node_modules`. With a custom `modulesDir`, the virtual store and its `lock.yaml` now default to `<modulesDir>/.pnpm`.

- A repeat `pnpm install` in a workspace with a custom `modulesDir` now takes the up-to-date fast path. Before, pnpm looked for each workspace project's dependencies in `node_modules` and ran a full install every time.

- pnpm now warns when a workspace install covers a project that has its own `pnpm-workspace.yaml`. The nested file's settings, such as `patchedDependencies`, do not apply when the outer workspace installs that project. pnpm reads settings only from the `pnpm-workspace.yaml` at the workspace root [#&#8203;11724](https://github.com/pnpm/pnpm/issues/11724).

- The `[<since>]` filter selector now compares against the commit where the current branch forked from `<since>`. Projects changed only by newer commits on `<since>` are no longer selected. Uncommitted changes are still included. In a shallow clone without that commit, pnpm compares against `<since>` directly, as before [#&#8203;9907](https://github.com/pnpm/pnpm/issues/9907).

- `--filter "[<since>]"` now selects workspace packages when dependency versions change in a catalog in `pnpm-workspace.yaml` [#&#8203;8718](https://github.com/pnpm/pnpm/issues/8718). It also selects projects that files were moved out of when git detects the move as a rename [#&#8203;15481](https://github.com/pnpm/pnpm/issues/15481).

- `--filter` now evaluates selectors in order, so later inclusion filters can re-include packages that an earlier exclusion filter excluded [#&#8203;9354](https://github.com/pnpm/pnpm/issues/9354).

##### Adding, updating, and removing dependencies

- `pnpm add` now saves changes to `package.json` before running lifecycle scripts, so a postinstall script failure leaves the added dependency in `package.json` [#&#8203;8627](https://github.com/pnpm/pnpm/issues/8627).

- `pnpm add` now saves the requested exact version when adding a dependency, even when the manifest already contains a version range [#&#8203;6040](https://github.com/pnpm/pnpm/issues/6040).

- `pnpm add <pkg>@&#8203;<version>` and `pnpm update <pkg>@&#8203;<version>` now move the catalog entry onto the named version when the entry's range already covers it. For example, `^7.22.17` becomes `^7.29.6`, the same way `pnpm update <pkg>` moves an entry to the version it resolves [#&#8203;13715](https://github.com/pnpm/pnpm/issues/13715).

- `pnpm add` and `pnpm install` keep an empty `peerDependencies`, `dependencies`, `devDependencies`, or `optionalDependencies` field that was already in `package.json`. pnpm still drops such a field when it removes the last entry itself, as `pnpm remove` does [#&#8203;5096](https://github.com/pnpm/pnpm/issues/5096).

- `pnpm update` now keeps a version range whose shape has no save prefix, such as `<= 3.0.0` or `>=1.0.0 <2.0.0`, when the updated version still satisfies it. Before, `<= 3.0.0` became `^3.0.0` [#&#8203;6714](https://github.com/pnpm/pnpm/issues/6714).

- `pnpm update <pkg>` now moves a package off a locked version the registry no longer serves, such as an unpublished release. The lockfile check for supply-chain policies such as `minimumReleaseAge` used to reject that version before the update could replace it [#&#8203;9953](https://github.com/pnpm/pnpm/issues/9953).

- `pnpm update --prod` no longer installs devDependencies when run in a project installed with `--prod` [#&#8203;8038](https://github.com/pnpm/pnpm/issues/8038).

- `pnpm update --interactive --workspace` now allows external dependencies to be updated.

- `pnpm outdated` and `pnpm update` now apply `minimumReleaseAge` to GitHub Actions. `minimumReleaseAgeExclude` entries match action names such as `actions/checkout` [#&#8203;13923](https://github.com/pnpm/pnpm/issues/13923).

- `pnpm remove` now accepts `--trust-lockfile` and `--no-trust-lockfile` to control supply-chain policy checks while removing a package [#&#8203;14406](https://github.com/pnpm/pnpm/issues/14406).

- `pnpm unlink` now removes the `link:` dependency that `pnpm link <dir>` added to `package.json`. The linked package is removed from `node_modules` and the lockfile. A `link:` dependency to another directory is kept [#&#8203;4219](https://github.com/pnpm/pnpm/issues/4219).

- `pnpm install` now prunes unreferenced catalog entries from `pnpm-workspace.yaml` when `catalogPrune: true` is configured [#&#8203;15273](https://github.com/pnpm/pnpm/issues/15273).

- `minimumReleaseAgeExcludePrune` and `trustPolicyExcludePrune` now work in workspaces with `shared-workspace-lockfile=false`. Once every project has been installed, pnpm drops an entry only if no project lockfile records it. Undecided `allowBuilds` entries are pruned the same way [#&#8203;14612](https://github.com/pnpm/pnpm/issues/14612).

- Exclude entries that pnpm writes to `pnpm-workspace.yaml` now match the file's list indentation and dominant quote style [#&#8203;15571](https://github.com/pnpm/pnpm/issues/15571), [#&#8203;15079](https://github.com/pnpm/pnpm/issues/15079).

- `pnpm import` now converts dependencies that use Yarn's `patch:` protocol. The dependency keeps the version it patches, and the patch file is added to `patchedDependencies` in `pnpm-workspace.yaml`. If the patch file is missing, pnpm prints a warning and imports the dependency without the patch [#&#8203;10278](https://github.com/pnpm/pnpm/issues/10278).

- `pnpm import` in a workspace now keeps the versions pinned by the root `yarn.lock`, `package-lock.json`, or `npm-shrinkwrap.json` when another workspace project's range allows a newer version. Before, the root project got the newest version in its range [#&#8203;4385](https://github.com/pnpm/pnpm/issues/4385).

- `pnpm patch`, `pnpm patch-commit`, and `pnpm patch-remove` now work in a project of a workspace with `sharedWorkspaceLockfile: false`. `pnpm patch` failed there with `ERR_PNPM_PATCH_NO_LOCKFILE` after a successful install. The reinstall after committing or removing a patch left the project's own `node_modules` unchanged [#&#8203;9926](https://github.com/pnpm/pnpm/issues/9926).

- `pnpm patch-commit` now resolves default patch directory locations when passed a package name or package specifier (such as `pnpm patch-commit <pkg>` or `pnpm patch-commit <pkg>@&#8203;<version>`).

- `pnpm patch-commit` now updates the lockfile snapshot and prunes removed dependencies when the patch modifies `package.json` [#&#8203;6866](https://github.com/pnpm/pnpm/issues/6866).

- `pnpm patch-commit` now falls back to copying package files when hard linking fails.

##### Running scripts and commands

- A script that pnpm runs without a terminal now ends when pnpm itself is killed. Killing pnpm's process group, as Playwright's `webServer` does to stop the command it started, used to leave the script running and holding the caller's output pipes open [#&#8203;15555](https://github.com/pnpm/pnpm/issues/15555).

- `pnpm --filter <project> <command>` and `pnpm -r <command>` now run a command installed in the selected projects' dependencies when none of them has a script by that name. This matches `pnpm <command>` in a single project. `pnpm run` with `--filter` or `-r` still reports the missing script [#&#8203;10151](https://github.com/pnpm/pnpm/issues/10151).

- `pnpm exec` and `pnpm dlx` now set `npm_execpath`, `INIT_CWD`, `npm_node_execpath`, and `NODE` in child environments when Node.js is available. Stale inherited `NODE` and `npm_node_execpath` variables are cleared when Node.js cannot be found on PATH [#&#8203;7037](https://github.com/pnpm/pnpm/issues/7037). Scripts that `pnpx` and `pnx` run now get pnpm itself as `npm_execpath`. A script that ran `$npm_execpath install` there ran `pnpm dlx install`.

- `pnpm exec` now sets the `PWD` environment variable to the directory the command runs in. Shells and tools that read `PWD` now report the logical path of a workspace package reached through a symlink [#&#8203;1550](https://github.com/pnpm/pnpm/issues/1550).

- A script that runs `pnpm run` no longer adds duplicate `node_modules/.bin` and `node-gyp-bin` entries to `PATH` [#&#8203;5352](https://github.com/pnpm/pnpm/issues/5352).

- Concurrent `pnpm run` and `pnpm exec` commands now serialize their dependency installs [#&#8203;14551](https://github.com/pnpm/pnpm/issues/14551).

- `pnpm run` and `pnpm exec` with `verifyDepsBeforeRun` now accept a moved project whose store is on the project's volume. Before, the check reported that the workspace structure had changed whenever the default store was not on the home volume.

- `verifyDepsBeforeRun` checks now account for project-specific `packageConfigs` overrides in workspaces with `sharedWorkspaceLockfile: false` [#&#8203;15545](https://github.com/pnpm/pnpm/issues/15545).

- `pnpm restart` now runs the "stop" and "start" scripts when the package has no "restart" script. Previously it ran "stop" and then failed with "Missing script: restart" [#&#8203;4750](https://github.com/pnpm/pnpm/issues/4750).

- `pnpm dlx` now keeps a separate cache entry for each Node.js major version. A package built under one Node.js major version, such as a native addon, is no longer reused under another [#&#8203;8611](https://github.com/pnpm/pnpm/issues/8611).

- `pnpm pipeline` no longer fails when run in a project outside a Git work tree or on a system without `git`. Tasks in those projects run without caching, and pnpm prints a warning explaining why [#&#8203;15601](https://github.com/pnpm/pnpm/issues/15601).

- A `runtime:` version range that contains `||` or a space, such as a `devEngines.runtime` version of `^22.18.0 || ^24.0.0`, now installs the requested runtime. pnpm used to install the npm package with the same name, such as `node` [#&#8203;14817](https://github.com/pnpm/pnpm/issues/14817).

- When the configured `scriptShell` does not exist, running a script now fails with an error that names the shell. Previously pnpm printed only an exit code or the package directory [#&#8203;7562](https://github.com/pnpm/pnpm/issues/7562).

- A script killed by a signal now fails with an error that names the signal, such as `Command failed with signal SIGKILL.` [#&#8203;9821](https://github.com/pnpm/pnpm/issues/9821).

##### Publishing, packing, and deploying

- `pnpm publish` now resolves `workspace:` dependencies from workspace manifests when `node_modules` is not installed. Previously, publishing without `node_modules` failed with `ERR_PNPM_CANNOT_RESOLVE_WORKSPACE_PROTOCOL` [#&#8203;6567](https://github.com/pnpm/pnpm/issues/6567).

- `pnpm publish` now honors `publishConfig["@&#8203;scope:registry"]` for a package in that scope. It takes precedence over the registry set for the same scope in `.npmrc` and over `publishConfig.registry` [#&#8203;12071](https://github.com/pnpm/pnpm/issues/12071).

- `pnpm pack` and `pnpm publish` now include bundled dependencies when using the isolated linker. This covers workspace packages and the dependencies of each bundled package. Bundled dependencies are also included when `publishConfig.directory` selects a build directory [#&#8203;1643](https://github.com/pnpm/pnpm/issues/1643).

- `pnpm pack`, `pnpm deploy`, and installs of local directory dependencies now keep symlinks that point to files or directories included in the package. `pnpm pack` leaves out symlinks that point outside the package [#&#8203;8208](https://github.com/pnpm/pnpm/issues/8208).

- `pnpm pack` now preserves file executable permissions in the packed tarball when source files are executable on disk.

- `pnpm publish` and `pnpm pack` now report a missing `version` or `name` field on a workspace dependency. Previously, pnpm reported that the dependency was not installed [#&#8203;4164](https://github.com/pnpm/pnpm/issues/4164).

- `pnpm publish` and `pnpm pack` now report an error when a bin script has a shebang line ending with CRLF [#&#8203;7311](https://github.com/pnpm/pnpm/issues/7311).

- `pnpm deploy` now copies the `packageManager` and `devEngines.packageManager` fields of the workspace root `package.json` into the deployed `package.json`, unless the deployed project pins a package manager itself [#&#8203;9079](https://github.com/pnpm/pnpm/issues/9079).

- `pnpm deploy` now puts the virtual store at `virtualStoreDir`, resolved against the deploy directory. A shared-lockfile deploy records `virtualStoreDir` in the deployed `pnpm-workspace.yaml`. With the global virtual store enabled or an absolute `virtualStoreDir`, the deploy still uses `node_modules/.pnpm` [#&#8203;8787](https://github.com/pnpm/pnpm/issues/8787).

- `pnpm deploy` now respects `--package-import-method` passed on the command line and reports the package import method correctly [#&#8203;7593](https://github.com/pnpm/pnpm/issues/7593).

- `pnpm deploy` does not run the `prepare` scripts of the deployed project [#&#8203;7282](https://github.com/pnpm/pnpm/issues/7282).

- `pnpm deploy --legacy` no longer rewrites the source workspace's `node_modules/.pnpm-workspace-state-v1.json` to describe only the deployed project [#&#8203;15352](https://github.com/pnpm/pnpm/issues/15352).

##### Manifests and configuration files

- pnpm now reads and updates `package.json5` project manifests. Manifest updates retain comments, and workspace discovery prefers `package.json`, then `package.json5`, then `package.yaml` [#&#8203;15129](https://github.com/pnpm/pnpm/issues/15129). `pnpm pack` includes exactly one `package.json` in the archive when the project uses an alternative manifest format, even when `.npmignore` or `files` excludes the source file.

- Git-hosted dependencies that use a `package.yaml` or `package.json5` manifest now honor its `files` field [#&#8203;7906](https://github.com/pnpm/pnpm/issues/7906).

- Fixed `pnpm version` failing on projects using a `package.yaml` manifest.

  Fixed `pnpm init` creating an extra `package.json` when `package.yaml` is already present.

- `pnpm version` now applies pending bumps to private workspace packages. A private package's changelog is written to its committed `CHANGELOG.md`, also when `versioning.changelog.storage` is `registry` [#&#8203;13736](https://github.com/pnpm/pnpm/issues/13736), [#&#8203;13519](https://github.com/pnpm/pnpm/issues/13519).

- `pnpm init` now supports the `--bare` option. It creates a `package.json` file with only the required fields [#&#8203;15538](https://github.com/pnpm/pnpm/issues/15538).

- The `reporter` setting is now honored when it is configured in `pnpm-workspace.yaml`, the global configuration, or the `PNPM_CONFIG_REPORTER` environment variable. Configured `reporter: silent` makes silent output the default. An explicit `--reporter` takes precedence [#&#8203;4879](https://github.com/pnpm/pnpm/issues/4879).

- `.npmrc` and `pnpm-workspace.yaml` files now support npm's `${VAR?}` placeholder. It expands to the value of `VAR`, or to an empty string without a warning when `VAR` is unset [#&#8203;14404](https://github.com/pnpm/pnpm/issues/14404).

- pnpm now expands environment variables in `_auth.authToken` values loaded from global `config.yaml` and `pnpm_config__auth`.

- pnpm now keeps the configured default registry when `_auth` holds credentials for several registries and some of those registries serve package scopes.

  Lockfile verification checks a tarball hosted on a scoped registry against that registry's metadata, unless the package's own scope has a registry assigned [#&#8203;15530](https://github.com/pnpm/pnpm/issues/15530).

- pnpm now parses the first setting in a `.npmrc` that starts with a UTF-8 byte order mark. Previously, the leading byte order mark caused the first line's key to be ignored [#&#8203;15353](https://github.com/pnpm/pnpm/issues/15353).

- pnpm now prints a warning when a `.npmrc`, `auth.ini`, or the file set by `npmrcAuthFile` exists but cannot be read. The settings in such a file were ignored without any message. A `.npmrc` that contains invalid UTF-8 is now read [#&#8203;5065](https://github.com/pnpm/pnpm/issues/5065).

- `pnpm config set` and `pnpm config delete` now preserve comments and repeated keys such as `ca=` in `.npmrc` [#&#8203;14851](https://github.com/pnpm/pnpm/issues/14851).

- `pnpm login` now logs back in to an existing user on registries without web login, such as verdaccio. The classic login request sends the username and password as basic auth, as `npm login` does [#&#8203;12055](https://github.com/pnpm/pnpm/issues/12055).

- Commands that do not use the store no longer create a temporary file in the project directory when they load their settings. These include `pnpm view`, `pnpm config`, `pnpm root`, `pnpm bin`, `pnpm exec`, `pnpm run`, the script shortcuts such as `pnpm test`, and the registry commands such as `pnpm whoami`, `pnpm dist-tag`, and `pnpm search`. `pnpm exec`, `pnpm run`, and the script shortcuts still create one in projects that declare `configDependencies`.

##### Global packages, pnpm versions, and runtimes

- Global commands such as `pnpm add --global`, `pnpm list --global`, and `pnpm bin --global` now run with the pnpm you invoked, even in a project that pins another pnpm version. Previously, a pin with `onFail: "download"` switched them to the pinned pnpm, and a pinned pnpm 10 or older failed because its global bin directory was not in `PATH` [#&#8203;14531](https://github.com/pnpm/pnpm/issues/14531).

- `pnpm add -g`, `pnpm update -g`, and `pnpm remove -g` no longer fail with `ERR_PNPM_PACKAGE_MANIFEST_IO_ERROR` when another global package's link into the store dangles, for example after the store was pruned. The pnpm install script failed the same way on such a machine.

- `pnpm update --global` now skips a global package installed from a `file:` path that no longer exists, prints a warning, and updates the remaining global packages. Previously the whole update failed with `ERR_PNPM_LINKED_PKG_DIR_NOT_FOUND` [#&#8203;12533](https://github.com/pnpm/pnpm/issues/12533).

- `pnpm self-update` run in a project that pins pnpm through `packageManager` or `devEngines.packageManager` now also updates the global pnpm, as it does outside a project [#&#8203;14747](https://github.com/pnpm/pnpm/issues/14747).

- `pnpm self-update` no longer leaves the previous pnpm in the global packages when it was installed as `@pnpm/exe`. `pnpm ls -g` now lists a single pnpm [#&#8203;14709](https://github.com/pnpm/pnpm/issues/14709). `pnpm setup` now installs pnpm under the package name `pnpm` too, so both commands leave the same shims in the global bin directory. After a self-update on Windows, PowerShell ran pnpm through `pnpm.cmd` and asked "Terminate batch job (Y/N)?" on Ctrl+C [#&#8203;15567](https://github.com/pnpm/pnpm/issues/15567).

- `pnpm setup` failed with `Text file busy (os error 26)` when `$PNPM_HOME/bin` already held `pn`, `pnpx`, or `pnx` as links to the running pnpm executable. It now replaces those files and completes [#&#8203;15494](https://github.com/pnpm/pnpm/issues/15494).

- `pnpm setup` no longer deletes aliases and other lines that sit between a `# pnpm` comment and the pnpm block in a shell startup file [#&#8203;7067](https://github.com/pnpm/pnpm/issues/7067).

- When pnpm switches to the version a project pins, the `minimumReleaseAge` approvals for that version are now added to `minimumReleaseAgeExclude` in the project's `pnpm-workspace.yaml`. A project without that file gets one. Global commands leave the project's settings unchanged [#&#8203;15396](https://github.com/pnpm/pnpm/issues/15396).

- `pnpm env remove` now cleans up dangling Node.js executables and shims. Surviving global commands remain intact.

- Node.js runtime resolution now supports Windows ARM64. Node.js 20 and newer resolve native `win-arm64` builds, and older versions fall back to `win-x64` under emulation [#&#8203;7123](https://github.com/pnpm/pnpm/issues/7123).

##### Windows and WSL

- On Windows, `pnpm clean` and installs no longer fail immediately when another process uses a package in `node_modules`. pnpm waits up to a minute for an open file. It waits up to 5 seconds for a running program [#&#8203;15081](https://github.com/pnpm/pnpm/issues/15081).

- `pnpm install` in WSL now waits out Windows file locks on a Windows drive such as `/mnt/c`, as it already does on Windows. Before, an antivirus or indexer scan holding a file open could fail the install with `EACCES` [#&#8203;6155](https://github.com/pnpm/pnpm/issues/6155).

- On Windows, pnpm now retries saving `pnpm-lock.yaml` for up to a minute while another process holds the file open. The save used to fail at once with `EPERM`, `EBUSY`, or "Access is denied" [#&#8203;9461](https://github.com/pnpm/pnpm/issues/9461).

- pnpm now escapes trailing dots and spaces in `node_modules/.pnpm` directory names. Windows strips these characters, so a dependency such as `"parent-pkg": "file:../"` created a directory that could not be deleted or failed to install [#&#8203;8101](https://github.com/pnpm/pnpm/issues/8101).

- On Windows, bin shims run from Git Bash, MSYS2, or Cygwin now pass `NODE_PATH` to Node.js as Windows paths. A project installed from cmd or PowerShell gave its bins a `NODE_PATH` under the Git install directory when they ran from Git Bash. Installing again replaces the shims already in `node_modules` [#&#8203;3360](https://github.com/pnpm/pnpm/issues/3360).

- Fixed scripts failing with errors such as `'an-compile' is not recognized` when `scriptShell` is set to `cmd.exe` on Windows [#&#8203;7181](https://github.com/pnpm/pnpm/issues/7181).

- On Windows, the error for a `node_modules` directory that pnpm cannot move out of the way now names the directory and says that a file in it is probably in use by another process [#&#8203;7505](https://github.com/pnpm/pnpm/issues/7505).

##### Inspecting dependencies

- `pnpm audit` and `pnpm audit signatures` now check only the dependencies of the projects selected by `--filter`, `--filter-prod`, or `--workspace-root`. The filter used to be ignored, so a filtered audit reported the whole workspace [#&#8203;10982](https://github.com/pnpm/pnpm/issues/10982).

- `pnpm audit` now lists at least one dependency path from every workspace project that depends on a vulnerable package. Before, a project whose dependency was reached through more than 100 paths filled the path list, and other projects that depend on the same package were left out [#&#8203;12200](https://github.com/pnpm/pnpm/issues/12200).

- `pnpm audit --fix` now prunes redundant overrides when one vulnerable range is a subset of another for the same package [#&#8203;8577](https://github.com/pnpm/pnpm/issues/8577).

- Running `pnpm list` inside a workspace package without `--recursive` or a filter now lists only the current package [#&#8203;14494](https://github.com/pnpm/pnpm/issues/14494). `pnpm licenses list` does the same. Use `--recursive` or `--filter` to list the licenses of other workspace projects [#&#8203;5689](https://github.com/pnpm/pnpm/issues/5689).

- `pnpm list --only-projects` now prints every project selected with `--filter` or `--recursive`, including a project that has no workspace dependencies [#&#8203;9770](https://github.com/pnpm/pnpm/issues/9770). It also lists the workspace projects when `sharedWorkspaceLockfile` is `false` [#&#8203;7151](https://github.com/pnpm/pnpm/issues/7151), and a project that sets `publishConfig.directory` [#&#8203;10635](https://github.com/pnpm/pnpm/issues/10635). It no longer reports packages in `node_modules` that are missing from the lockfile [#&#8203;9528](https://github.com/pnpm/pnpm/issues/9528).

- `pnpm licenses list` failed or reported nothing in a workspace with `sharedWorkspaceLockfile: false`. It now reads the lockfile of each selected project [#&#8203;10140](https://github.com/pnpm/pnpm/issues/10140).

- With `nodeLinker: hoisted`, `pnpm licenses list` reported every license as `Unknown` and listed paths under `node_modules/.pnpm` that do not exist. It now reads each package from the directory where the hoisted linker placed it [#&#8203;8589](https://github.com/pnpm/pnpm/issues/8589).

- `pnpm outdated` and `pnpm -r outdated` now fail with `ERR_PNPM_NO_PACKAGE_IN_DEPENDENCIES` when a requested package selector does not match any dependency in the inspected projects [#&#8203;2319](https://github.com/pnpm/pnpm/issues/2319).

- `pnpm -r outdated --json` now includes every outdated workspace dependency when multiple projects depend on different versions or dependency types of the same package. Such a package is keyed by its current version and dependency type, for example `[email protected] (dev)` [#&#8203;7693](https://github.com/pnpm/pnpm/issues/7693).

- `pnpm sbom` filtered to a single workspace project now takes the `author`, `description`, `license`, `repository`, and `bugs` fields from the workspace root `package.json` when the project does not declare them. A field the project declares is never taken from the root, even when it is blank or `null` [#&#8203;14882](https://github.com/pnpm/pnpm/issues/14882).

- `pnpm store status` no longer reports a package as modified when it has build or postinstall scripts, peer dependencies, or skipped optional dependencies [#&#8203;15383](https://github.com/pnpm/pnpm/issues/15383). When packages were mutated, it now lists only those packages and no longer suggests running `pnpm install --force` [#&#8203;919](https://github.com/pnpm/pnpm/issues/919).

- `pnpm peers check` and the `ERR_PNPM_PEER_DEP_ISSUES` error now group peer dependency issues under the workspace project they were found in [#&#8203;15351](https://github.com/pnpm/pnpm/issues/15351).

##### Output and messages

- The error for an incompatible pnpm-lock.yaml now reports the lockfileVersion the file was generated with and the lockfileVersion the current pnpm supports [#&#8203;848](https://github.com/pnpm/pnpm/issues/848).

- When the registry stops sending data for longer than `fetchTimeout`, pnpm now reports that the metadata or tarball request timed out. Previously the error did not mention the timeout [#&#8203;3646](https://github.com/pnpm/pnpm/issues/3646).

- Fatal peer dependency errors and their hints are now written to stderr [#&#8203;5419](https://github.com/pnpm/pnpm/issues/5419).

- `pnpm run` with `--loglevel` set to `warn`, `error`, or `silent` (or the same `loglevel` setting) no longer prints the `$ <command>` line before a script, nor the summary of the install that `verifyDepsBeforeRun` runs first. Both are info-level output [#&#8203;8944](https://github.com/pnpm/pnpm/issues/8944).

- `pnpm run` and `pnpm exec` now print `No projects matched the filters in "<workspace>"` when `--filter` selects no project [#&#8203;8408](https://github.com/pnpm/pnpm/issues/8408).

- `pnpm dedupe` now counts each package reused from the store once in its progress output [#&#8203;15303](https://github.com/pnpm/pnpm/issues/15303).

- `pnpm add` now warns when replacing an existing dependency with a specifier pointing to a different source [#&#8203;14869](https://github.com/pnpm/pnpm/issues/14869).

- `pnpm link` now warns when linking a package that declares one or more peer dependencies, explaining that the linked dependency will not resolve peer dependencies from the target `node_modules` and suggesting the `file:` protocol instead.

- `pnpm import` now warns when package.json lists projects in a "workspaces" array and there is no "pnpm-workspace.yaml". Without that file, the import writes a lockfile for the root project only [#&#8203;5240](https://github.com/pnpm/pnpm/issues/5240).

- Bash completion now completes script names that contain a colon, such as `pnpm run test:u` to `pnpm run test:unit` [#&#8203;5482](https://github.com/pnpm/pnpm/issues/5482).

<!-- sponsors -->

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://bit.cloud/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/bit.svg" width="80" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
        <a href="https://openai.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/openai_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/openai_light.svg" />
            <img src="https://pnpm.io/img/users/openai_dark.svg" width="160" alt="OpenAI" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://notion.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/notion.svg" width="80" alt="Notion"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/coderabbit.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
            <img src="https://pnpm.io/img/users/coderabbit.svg" width="220" alt="CodeRabbit" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
        <a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/sanity.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/sanity_light.svg" />
            <img src="https://pnpm.io/img/users/sanity.svg" width="120" alt="Sanity" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/discord.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/discord_light.svg" />
            <img src="https://pnpm.io/img/users/discord.svg" width="220" alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://vite.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/vitejs.svg" width="42" alt="Vite"></a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://serpapi.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/serpapi_dark.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/serpapi_light.svg" />
            <img src="https://pnpm.io/img/users/serpapi_dark.svg" width="160" alt="SerpApi" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/stackblitz.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
            <img src="https://pnpm.io/img/users/stackblitz.svg" width="190" alt="Stackblitz" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/workleap.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/workleap_light.svg" />
            <img src="https://pnpm.io/img/users/workleap.svg" width="190" alt="Workleap" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
        <a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer">
          <picture>
            <source media="(prefers-color-scheme: light)" srcset="https://pnpm.io/img/users/nx.svg" />
            <source media="(prefers-color-scheme: dark)" srcset="https://pnpm.io/img/users/nx_light.svg" />
            <img src="https://pnpm.io/img/users/nx.svg" width="50" alt="Nx" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
        <a href="https://latitude.so/?utm_source=pnpm&utm_medium=release_notes" target="_blank" rel="noopener noreferrer"><img src="https://pnpm.io/img/users/latitude.svg" width="160" alt="Latitude"></a>
      </td>
    </tr>
  </tbody>
</table>

<!-- sponsors end -->

</details>

<details>
<summary>lovell/sharp (sharp)</summary>

### [`v0.35.5`](https://github.com/lovell/sharp/releases/tag/v0.35.5)

[Compare Source](https://github.com/lovell/sharp/compare/v0.35.4...v0.35.5)

<https://github.com/lovell/sharp-libvips/releases/tag/v1.3.4>

- Add upper bounds check on length of `linear` and GIF `delay` arrays.

- Improve error handing when WebAssembly fallback also fails.
  [#&#8203;4593](https://github.com/lovell/sharp/pull/4593)
  [@&#8203;lazerg](https://github.com/lazerg)

- TypeScript: Allow multi-frame options for JXL output.
  [#&#8203;4602](https://github.com/lovell/sharp/pull/4602)
  [@&#8203;ramin-010](https://github.com/ramin-010)

- TypeScript: Remove non-existent named export.
  [#&#8203;4604](https://github.com/lovell/sharp/issues/4604)

- Increase accepted dimensions when extending an image.
  [#&#8203;4605](https://github.com/lovell/sharp/issues/4605)

- Improve gain map support for `extract` and `rotate` operations.
  [#&#8203;4606](https://github.com/lovell/sharp/issues/4606)

- Tests: Ensure composite tests pass on big endian platforms.
  [#&#8203;4609](https://github.com/lovell/sharp/issues/4609)

</details>

<details>
<summary>HiDeoo/starlight-openapi (starlight-openapi)</summary>

### [`v0.26.3`](https://github.com/HiDeoo/starlight-openapi/blob/HEAD/packages/starlight-openapi/CHANGELOG.md#0263)

[Compare Source](https://github.com/HiDeoo/starlight-openapi/compare/[email protected]@0.26.3)

##### Patch Changes

- [#&#8203;181](https://github.com/HiDeoo/starlight-openapi/pull/181) [`e81882f`](https://github.com/HiDeoo/starlight-openapi/commit/e81882ffd4a85b1c113fd477422ee6b524715d58) Thanks [@&#8203;HiDeoo](https://github.com/HiDeoo)! - Fixes a potential spacing issue with heading anchor links.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - Between 12:00 AM and 03:59 AM, only on Monday (`* 0-3 * * 1`)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xOTEuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE5MS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

<!-- cloudflare-preview --> Preview: https://pr-575.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/575
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
2026-10-06 08:31:06 +00:00
Gitea Bot 8c2625b846 Update the latest api documents (#576)
Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the "update api spec files" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-576.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/576
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
2026-10-05 10:59:51 +00:00
Gitea Bot 140915b303 Update the runner reference pages (#577)
Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the "update runner reference" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-577.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/577
Reviewed-by: silverwind <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
2026-10-05 10:59:31 +00:00
silverwind e4cad3c2e8 docs: update session providers and cookie names (#572)
Docs for https://github.com/go-gitea/gitea/pull/39504, which removed the `mysql`, `postgres`, `couchbase` and `memcache` session providers and renamed the default cookies to `gitea_session` and `gitea_remember`. The English cheat sheet copies the `app.example.ini` wording, the zh-cn and zh-tw cheat sheets get the same values.

Reviewed-on: https://gitea.com/gitea/docs/pulls/572
Reviewed-by: Lunny Xiao <[email protected]>
Reviewed-by: wxiaoguang <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-02 20:58:18 +00:00
silverwind 784c530a5b docs: mirror app.example.ini wording in the cache section (#571)
Docs for https://github.com/go-gitea/gitea/pull/39530, which changed the `INTERVAL` description in `app.example.ini`. The cheat sheet's `[cache]` and `[cache.last_commit]` descriptions now copy the ini wording, including its memcache example.

Reviewed-on: https://gitea.com/gitea/docs/pulls/571
Reviewed-by: wxiaoguang <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-02 17:11:53 +00:00
JWheelMakerandsilverwind 8d7c0701dc docs/installation/with-docker.md Update PostgreSQL volume path for PostgreSQL 18 (#570)
The Docker Compose example currently mounts the PostgreSQL data directory to `/var/lib/postgresql/data`.

With PostgreSQL 18, the official PostgreSQL Docker image expects the volume to be mounted at `/var/lib/postgresql` instead. Mounting `/var/lib/postgresql/data` causes the container to fail during startup because the image detects PostgreSQL data at an unused mount point.

This change updates the example to use the recommended `/var/lib/postgresql` mount path for PostgreSQL 18 and newer.

---------

Co-authored-by: silverwind <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/570
Reviewed-by: silverwind <[email protected]>
Co-authored-by: JWheelMaker <[email protected]>
2026-10-01 16:12:52 +00:00
silverwind 7219c0e44d docs: fix the REPOSITORY_AVATAR_FALLBACK_IMAGE default (#569)
The cheat sheet lists `/img/repo_default.png` as the `REPOSITORY_AVATAR_FALLBACK_IMAGE` default, but public files moved under `/assets` in Gitea 1.15 (https://github.com/go-gitea/gitea/pull/15219), so that path 404s. Like `app.example.ini` in https://github.com/go-gitea/gitea/pull/39514, document the default as empty, falling back to Gitea's builtin repository avatar, and note that a custom value is used as-is without the sub-path. Applies to all documented versions and translations.

_Written by Claude Code (Opus 5.5)._

Reviewed-on: https://gitea.com/gitea/docs/pulls/569
Reviewed-by: wxiaoguang <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-01 08:28:50 +00:00
silverwind 8d93c189ac Refresh the latest api documents weekly (#568)
Reduce the frequency of these annoying "Update the latest api documents" PRs to once per week.

Reviewed-on: https://gitea.com/gitea/docs/pulls/568
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-10-01 00:13:22 +00:00
Gitea Bot 9fa74b7323 Update the latest api documents (#567)
Automated update of static/swagger-latest.json and static/openapi3-latest.json from the gitea main branch, opened by the "update api spec files" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-567.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/567
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
2026-10-01 00:09:30 +00:00
silverwind 4a0ef0480b docs: update the SSH_SERVER_HOST_KEYS default and generated keys (#566)
Since https://github.com/go-gitea/gitea/pull/33974 (1.27), `SSH_SERVER_HOST_KEYS` defaults to `ssh/gitea.rsa, ssh/gitea.ed25519, ssh/gitea.ecdsa, ssh/gogs.rsa`. When none of the keys exist, Gitea generates 4096 bit RSA, 256 bit ECDSA and ED25519 keys instead of RSA alone. This updates next, 28 and 1.27 in all three languages, matching https://github.com/go-gitea/gitea/pull/39500.

Written by Claude.

Reviewed-on: https://gitea.com/gitea/docs/pulls/566
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-09-30 23:34:35 +00:00
bircniandsilverwind 7d9a82df8d add artifact preview (#533)
Document Actions artifact previews added in https://github.com/go-gitea/gitea/pull/36754, including supported content, authentication and sandboxing behavior, navigation, and size limits.

Also document the `ARTIFACT_PREVIEW_MAX_SIZE` configuration option so administrators can limit or disable previews.

Co-authored-by: silverwind <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/533
Reviewed-by: Lunny Xiao <[email protected]>
Reviewed-by: silverwind <[email protected]>
Co-authored-by: bircni <[email protected]>
2026-09-30 11:43:03 +00:00
6934d56056 docs: document egress modes and host lists (#557)
Documents the settings changed by https://github.com/go-gitea/gitea/pull/39426: `EGRESS_MODE`, the `[migrations]` `ALLOWED_HOST_LIST`/`BLOCKED_HOST_LIST` replacing `ALLOWED_DOMAINS`, `BLOCKED_DOMAINS` and `ALLOW_LOCALNETWORKS`, and the host list syntax with ports, CGNAT and reserved addresses. Also fixes the `socks://` examples, Go only speaks `socks5://`.

_Written by Claude._

---------

Co-authored-by: Lunny Xiao <[email protected]>
Co-authored-by: TheFox0x7 <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/557
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-09-30 11:42:29 +00:00
Gitea BotandLunny Xiao c28356267d Update the runner reference pages (#563)
Automated update of the generated runner reference pages from gitea/runner (main for the develop docs, the newest stable tag for every documented series), opened by the "update runner reference" scheduled workflow.

<!-- cloudflare-preview --> Preview: https://pr-563.docs-gitea-com.pages.dev

---------

Co-authored-by: Lunny Xiao <[email protected]>
Reviewed-on: https://gitea.com/gitea/docs/pulls/563
Reviewed-by: Lunny Xiao <[email protected]>
Co-authored-by: Gitea Bot <[email protected]>
2026-09-30 11:31:16 +00:00
silverwind c3d9115328 docs: update defaults changed by the install page refactor (#565)
https://github.com/go-gitea/gitea/pull/39400 made registration disabled by default, switched the session provider default to `file`, and derives `SSH_DOMAIN` and `NO_REPLY_ADDRESS` from `ROOT_URL` now that `[server] DOMAIN` is gone. Updates the next and v28 cheat sheets with the wording from `app.example.ini` in https://github.com/go-gitea/gitea/pull/39456.

Reviewed-on: https://gitea.com/gitea/docs/pulls/565
Reviewed-by: wxiaoguang <[email protected]>
Co-authored-by: silverwind <[email protected]>
2026-09-30 11:30:26 +00:00
Lunny Xiao ba60edbbda Add version v28 (#564)
<!-- cloudflare-preview --> Preview: https://pr-564.docs-gitea-com.pages.dev

Reviewed-on: https://gitea.com/gitea/docs/pulls/564
Reviewed-by: bircni <[email protected]>
Co-authored-by: Lunny Xiao <[email protected]>
2026-09-30 06:40:44 +00:00