# Technical Documentation: vercel/turborepo

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/vercel/turborepo)

### Overview (README.md)

<p align="center">
  <a href="https://turborepo.dev">
    <picture>
      <source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/4060187/196936123-f6e1db90-784d-4174-b774-92502b718836.png">
      <img src="https://user-images.githubusercontent.com/4060187/196936104-5797972c-ab10-4834-bd61-0d1e5f442c9c.png" height="128">
    </picture>
    <h1 align="center">Turborepo</h1>
  </a>
</p>

<p align="center">
  <a aria-label="Vercel logo" href="https://vercel.com/"><img src="https://img.shields.io/badge/MADE%20BY%20Vercel-000000.svg?style=for-the-badge&logo=Vercel&labelColor=000"></a>
  <a aria-label="NPM version" href="https://www.npmjs.com/package/turbo"><img alt="" src="https://img.shields.io/npm/v/turbo.svg?style=for-the-badge&labelColor=000000"></a>
  <a aria-label="License" href="https://github.com/vercel/turborepo/blob/main/LICENSE"><img alt="" src="https://img.shields.io/npm/l/turbo.svg?style=for-the-badge&labelColor=000000&color="></a>
  <a aria-label="Join the community on GitHub" href="https://github.com/vercel/turborepo/discussions"><img alt="" src="https://img.shields.io/badge/Join%20the%20community-blueviolet.svg?style=for-the-badge&logo=turborepo&labelColor=000000&logoWidth=20&logoColor=white"></a>
</p>

Turborepo is the build system for coding agents.

## Getting Started

Visit https://turborepo.dev to get started with Turborepo.

## Contributing

See [CONTRIBUTING.md](https://github.com/vercel/turborepo/blob/main/CONTRIBUTING.md) for more information.

## Community

The Turborepo community can be found on [GitHub Discussions](https://github.com/vercel/turborepo/discussions), where you can ask questions, voice ideas, and share your projects.

To chat with other community members, you can join [Vercel Community's `#turborepo` tag](https://vercel.community/tag/turborepo).

Our [Code of Conduct](https://github.com/vercel/turborepo/blob/main/CODE_OF_CONDUCT.md) applies to all Turborepo community channels.

## Who is using Turborepo?

Turborepo is used by the world's leading companies. Check out the [Turborepo Showcase](https://turborepo.dev/showcase) to learn more.

## Updates

Follow [@turborepo](https://x.com/turborepo) on X for project updates.

## Security

If you believe you have found a security vulnerability in Turborepo, we encourage you to responsibly disclose this and not open a public issue. We will investigate all legitimate reports. Email `security@vercel.com` to disclose any security vulnerabilities.

https://security.vercel.com/

---

### Link Checker README (`docs/link-checker/README.MD`)

# GitHub Action for Validating Documentation Links

This action ensures that internal links in `.mdx` files in the `/docs/` directory are valid. It runs on every pull request that includes changes to these files.

The action is triggered by the workflow defined in `.github/workflows/docs.yml`.

## Usage

pnpm check-links

---

### Apps Docs Content Docs Index (`apps/docs/content/docs/index.mdx`)

---
title: Introduction
description: Welcome to the Turborepo documentation!
product: turborepo
type: overview
summary: Learn what Turborepo is, how it solves monorepo scaling problems, and how to navigate the documentation.
related:
  - /docs/getting-started
  - /docs/getting-started/installation
  - /docs/community
---

## What is Turborepo?

Turborepo is the build system for coding agents. It is designed for scaling monorepos and also makes workflows in [single-package workspaces](/docs/guides/single-package-workspaces) faster, too.

From individual developers to the largest enterprise engineering organizations in the world, Turborepo is saving years of engineering time and millions of dollars in compute costs through a lightweight approach to optimizing the tasks you need to run in your repository.

## The monorepo problem

Monorepos have many advantages - but **they struggle to scale**. Each workspace has its own test suite, its own linting, and its own build process. A single monorepo might have **thousands of tasks to execute**.



These slowdowns can dramatically affect the way your teams build software, especially at scale. Feedback loops need to be fast so developers can deliver high-quality code quickly.

## The monorepo solution



**Turborepo solves your monorepo's scaling problem**. [Remote Cache](/docs/core-concepts/remote-caching) stores the result of all your tasks, meaning that **your CI never needs to do the same work twice**.

Additionally, task scheduling can be difficult in a monorepo. You may need to build, _then_ test, _then_ lint...

Turborepo **schedules your tasks for maximum speed**, parallelizing work across all available cores.

Turborepo can be **adopted incrementally** and you can **add it to any repository in just a few minutes**. It uses the `package.json` scripts you've already written, the dependencies you've already declared, and a single `turbo.json` file. You can **use it with any package manager**, like `npm`, `yarn` or `pnpm` since Turborepo leans on the conventions of the npm ecosystem.

## How to use these docs

We will do our best to keep jargon to a minimum - but there are some need-to-know words that will be important to understand as you read through the docs. We've created [a glossary page](https://vercel.com/docs/glossary) to help you out in case you're learning about these terms.

## Join the community

If you have questions about anything related to Turborepo, you're always welcome to ask the community on [GitHub Discussions](https://github.com/vercel/turborepo/discussions), [Vercel Community](https://community.vercel.com/tag/turborepo), and [Twitter](https://twitter.com/turborepo).

---

### Apps Docs Content Openapi Index (`apps/docs/content/openapi/index.mdx`)

---
title: Remote Cache API
description: OpenAPI specification for self-hosted Remote Cache servers.
---

# Remote Cache API

The Turborepo Remote Cache API defines the HTTP interface that any remote cache server must implement to be compatible with Turborepo.

## Overview

The remote cache stores build artifacts identified by content-addressable hashes. When Turborepo encounters a task that matches a previously cached result, it can download the artifact instead of re-executing the task.

## Authentication

All endpoints require Bearer token authentication:

```bash
Authorization: Bearer <token>
```

For self-hosted implementations, the token format and validation logic is up to the implementer.

## Endpoints

### Artifacts

| Method | Path                                                                  | Description                                |
| ------ | --------------------------------------------------------------------- | ------------------------------------------ |
| `GET`  | [`/artifacts/status`](/repo/docs/openapi/artifacts/status)            | Check remote caching status                |
| `HEAD` | [`/artifacts/{hash}`](/repo/docs/openapi/artifacts/artifact-exists)   | Check if artifact exists                   |
| `GET`  | [`/artifacts/{hash}`](/repo/docs/openapi/artifacts/download-artifact) | Download a cache artifact                  |
| `PUT`  | [`/artifacts/{hash}`](/repo/docs/openapi/artifacts/upload-artifact)   | Upload a cache artifact                    |
| `POST` | [`/artifacts`](/repo/docs/openapi/artifacts/artifact-query)           | Query information about multiple artifacts |

### Analytics

| Method | Path                                                              | Description               |
| ------ | ----------------------------------------------------------------- | ------------------------- |
| `POST` | [`/artifacts/events`](/repo/docs/openapi/artifacts/record-events) | Record cache usage events |

## Download the spec

The full OpenAPI specification is available at [`/api/remote-cache-spec`](/api/remote-cache-spec).

---

### Examples Basic Apps Docs README (`examples/basic/apps/docs/README.md`)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

---

### Examples With Angular Apps Docs README (`examples/with-angular/apps/docs/README.md`)

# Docs

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.7.

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.

## Code scaffolding

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.

## Build

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.

## Running unit tests

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).

## Running end-to-end tests

Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.

---

### Examples With Berry Apps Docs README (`examples/with-berry/apps/docs/README.md`)

## Getting Started

From the monorepo root, run:

```sh
yarn workspace docs dev
```

Open [http://localhost:3001](http://localhost:3001). Edit `app/page.tsx` in this workspace to update the page. `app/layout.tsx` defines the root layout.

This app uses the Next.js App Router. Add API endpoints with [Route Handlers](https://nextjs.org/docs/app/getting-started/route-handlers), for example `app/api/hello/route.ts`.

## Learn More

- [Next.js App Router documentation](https://nextjs.org/docs/app)
- [Learn Next.js](https://nextjs.org/learn)
- [Deploying Next.js](https://nextjs.org/docs/app/getting-started/deploying)

---

### Examples With Biome Apps Docs README (`examples/with-biome/apps/docs/README.md`)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

---

### Examples With Gatsby Apps Docs README (`examples/with-gatsby/apps/docs/README.md`)

## Getting Started

Install dependencies from the workspace root, then start this app:

```sh
pnpm --filter docs dev
```

Open [http://localhost:3001](http://localhost:3001). Edit `pages/index.tsx` to see updates. This app uses the Next.js Pages Router and consumes `@repo/ui` through `transpilePackages`.

## Production

From the workspace root:

```sh
pnpm --filter docs build
pnpm --filter docs start
```

The production server also uses port 3001.

## Learn More

- [Next.js Pages Router documentation](https://nextjs.org/docs/pages)
- [Next.js deployment documentation](https://nextjs.org/docs/pages/getting-started/deploying)

---

### Examples With Microfrontends Apps Docs README (`examples/with-microfrontends/apps/docs/README.md`)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

---

### Examples With Npm Apps Docs README (`examples/with-npm/apps/docs/README.md`)

## Getting Started

First, run the development server:

```bash
npm run dev
```

Open [http://localhost:3001](http://localhost:3001) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello).

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

---

### Examples With Otel Apps Docs README (`examples/with-otel/apps/docs/README.md`)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

---

### Examples With Solid Apps Docs README (`examples/with-solid/apps/docs/README.md`)

# SolidStart

Everything you need to build a Solid project, powered by [SolidStart](https://docs.solidjs.com/solid-start);

## Creating a project

```bash
# create a new project in the current directory
npm init solid@latest

# create a new project in my-app
npm init solid@latest my-app
```

## Developing

Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:

```bash
npm run dev

# or start the server and open the app in a new browser tab
npm run dev -- --open
```

## Building

SolidStart v2 apps are built with [Vite](https://vite.dev/) and deployed with [Nitro](https://nitro.build/) presets, which optimise your project for deployment to different environments.

By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, configure the `nitro` plugin in your `vite.config.ts`.

## Testing

Tests are written with `vitest`, `@solidjs/testing-library` and `@testing-library/jest-dom` to extend expect with some helpful custom matchers.

To run them, simply start:

```sh
npm test
```

## This project was created with the [Solid CLI](https://solid-cli.netlify.app)

---

### Examples With Svelte Apps Docs README (`examples/with-svelte/apps/docs/README.md`)

# create-svelte

Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).

## Creating a project

If you're seeing this, you've probably already done this step. Congrats!

```bash
# create a new project in the current directory
npm create svelte@latest

# create a new project in my-app
npm create svelte@latest my-app
```

## Developing

Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:

```bash
npm run dev

# or start the server and open the app in a new browser tab
npm run dev -- --open
```

## Building

To create a production version of your app:

```bash
npm run build
```

You can preview the production build with `npm run preview`.

> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.

---

### Examples With Tailwind Apps Docs README (`examples/with-tailwind/apps/docs/README.md`)

## Getting Started

First, run the development server:

```bash
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `src/app/page.tsx`. The page auto-updates as you edit the file.

To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3000/api/hello](http://localhost:3000/api/hello).

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

---

### Examples With Typeorm Apps Docs README (`examples/with-typeorm/apps/docs/README.md`)

## Getting Started

First, run the development server:

```bash
yarn dev
```

Open [http://localhost:3001](http://localhost:3001) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello).

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

---

### Examples With Ultracite Apps Docs README (`examples/with-ultracite/apps/docs/README.md`)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

---

### Examples With Vitest Apps Docs README (`examples/with-vitest/apps/docs/README.md`)

This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

---

### Examples With Vue Nuxt Apps Docs README (`examples/with-vue-nuxt/apps/docs/README.md`)

## Getting Started

First, run the development server:

```bash
pnpm dev
```

Open [http://localhost:3001](http://localhost:3001) with your browser to see the result.

You can start editing the page by modifying `app.vue`. The page auto-updates as you edit the file.

To create [API routes](https://nuxt.com/docs/guide/directory-structure/server), add an `api/` or a `routes` directory to the `server/` directory and create `your-file.ts` which will contain your api logic. Like `server/api/hello.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello).

> See the guide for more details -> [directory-structure/server](https://nuxt.com/docs/guide/directory-structure/server)

## Learn More

To learn more about Next.js, take a look at the following resources:

- [NuxtJs Official documentation](https://nuxt.com/docs/getting-started/introduction) - learn about Nuxt to create production-grade full-stack web apps and websites features and API.

## Deploy on Vercel

You can easily deploy your Nuxt app by using the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme).

Check out our [Nuxt deployment documentation](https://vercel.com/docs/frameworks/nuxt) for more details.

---

### Examples With Yarn Apps Docs README (`examples/with-yarn/apps/docs/README.md`)

## Getting Started

First, run the development server:

```bash
yarn dev
```

Open [http://localhost:3001](http://localhost:3001) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

To create [API routes](https://nextjs.org/docs/app/building-your-application/routing/router-handlers) add an `api/` directory to the `app/` directory with a `route.ts` file. For individual endpoints, create a subfolder in the `api` directory, like `api/hello/route.ts` would map to [http://localhost:3001/api/hello](http://localhost:3001/api/hello).

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn/foundations/about-nextjs) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_source=github.com&utm_medium=referral&utm_campaign=turborepo-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

---

### Apps Docs Content Docs Core Concepts Index (`apps/docs/content/docs/core-concepts/index.mdx`)

---
title: Core concepts
description: Learn about the core concepts behind Turborepo.
product: turborepo
type: overview
summary: Explore the foundational concepts that power Turborepo's monorepo tooling.
related:
  - /docs/core-concepts/remote-caching
  - /docs/core-concepts/package-types
  - /docs/core-concepts/internal-packages
  - /docs/core-concepts/package-and-task-graph
---

Learn more about the core concepts of Turborepo:

<Cards>
<Card
title="Remote Caching"
href="/docs/core-concepts/remote-caching"
description="Save time by never doing the same work twice"
/>

<Card
  title="Package types"
  href="/docs/core-concepts/package-types"
  description="Application and Library Packages"
/>

<Card
  title="Internal Packages"
  href="/docs/core-concepts/internal-packages"
  description="Easily share code inside your repository"
/>

<Card
  title="Package and Task Graphs"
  href="/docs/core-concepts/package-and-task-graph"
  description="How Turborepo relates your tasks to each other"
/>

</Cards>

---

### Apps Docs Content Docs Crafting Your Repository Index (`apps/docs/content/docs/crafting-your-repository/index.mdx`)

---
title: Crafting your repository
description: Design and build your Turborepo.
product: turborepo
type: overview
summary: Step-by-step guides for designing, building, and optimizing a monorepo with Turborepo.
related:
  - /docs/crafting-your-repository/structuring-a-repository
  - /docs/core-concepts
---

Architecting a monorepo is a careful process. Through these guides, you'll learn how to design and build a monorepo that will make every team faster - no matter the size.

The guides in this section will take you through building a multi-package workspace, commonly referred to as a monorepo. They are meant to be read in order as they build on top of the knowledge from previous guides, but you can read them in any order or skip to the pages specific to your use case.

By the time you've read through all of this section, you should have a good understanding of how to design and build a monorepo with Turborepo.

<Callout type="info">
  Turborepo can also be used to speed up single-package workspaces. Visit the
  [single-package workspace](/docs/guides/single-package-workspaces) section for
  more information.
</Callout>

## From zero to `turbo`

<Cards>
    <Card
        href="/docs/crafting-your-repository/structuring-a-repository"
        title="1. Structuring a repository"
        description="Design the directory structure of your monorepo."
    />

    <Card
        href="/docs/crafting-your-repository/managing-dependencies"
        title="2. Managing dependencies"
        description="Using dependencies for sharing code"
    />

    <Card
        href="/docs/crafting-your-repository/creating-an-internal-package"
        title="3. Creating an internal package"
        description="Make a package in your repository"
    />

    <Card
        href="/docs/crafting-your-repository/configuring-tasks"
        title="4. Configuring tasks"
        description="Design your task patterns"
    />

    <Card
        href="/docs/crafting-your-repository/running-tasks"
        title="5. Running tasks"
        description="Run tasks as fast as possible"
    />

    <Card
        href="/docs/crafting-your-repository/caching"
        title="6. Caching"
        description="Never do the same work twice"
    />

    <Card
        href="/docs/crafting-your-repository/developing-applications"
        title="7. Developing apps"
        description="Run many apps in parallel"
    />

    <Card
        href="/docs/crafting-your-repository/using-environment-variables"
        title="8. Using environment variables"
        description="Account for variables in your environment"
    />

    <Card
        href="/docs/crafting-your-repository/constructing-ci"
        title="9. Constructing CI"
        description="Ship your applications"
    />

    <Card
        href="/docs/crafting-your-repository/upgrading"
        title="10. Upgrading"
        description="Upgrading your Turborepo version"
    />
    <Card
        href="/docs/crafting-your-repository/understanding-your-repository"
        title="11. Understanding your repository"
        description="Understanding your codebase with Turborepo"
    />

</Cards>

## More guides

We also have more guides centered around [specific tools, use cases, and other topics](/docs/guides).

---

### Apps Docs Content Docs Getting Started Index (`apps/docs/content/docs/getting-started/index.mdx`)

---
title: Getting started
description: Get started with Turborepo.
product: turborepo
type: overview
summary: Choose a learning path to start using Turborepo in a new or existing repository.
related:
  - /docs/getting-started/installation
  - /docs/getting-started/add-to-existing-repository
  - /docs/getting-started/examples
---

If you're new to Turborepo, you can follow these steps to get started.

<Steps>
<Step>
## Install Turborepo

Install the standalone `turbo` binary to run commands from your terminal. See the [installation guide](/docs/getting-started/installation#global-installation) for supported platforms and instructions.

</Step>
<Step>

## Choose your learning path

<Cards>
  <Card
    href="/docs/getting-started/installation"
    title="Use create-turbo"
    description="Start with a template"
  />
  <Card
    href="/docs/getting-started/examples"
    title="Use an example"
    description="Start with a framework-specific example"
  />
  <Card
    href="/docs/crafting-your-repository"
    title="Follow the in-depth guides"
    description="From zero to monorepo"
  />
  <Card
    href="/docs/getting-started/add-to-existing-repository"
    title="Add to an existing repository"
    description="Make your current repo fast"
  />
</Cards>
</Step>
</Steps>

---

### Apps Docs Content Docs Guides Index (`apps/docs/content/docs/guides/index.mdx`)

---
title: Guides
description: Learn how to use your favorite tooling in a Turborepo.
product: turborepo
type: overview
summary: Browse guides for frameworks, CI providers, tools, and common use cases in Turborepo.
related:
  - /docs/guides/frameworks
  - /docs/guides/ci-vendors
  - /docs/guides/tools
---

Turborepo works with your favorite frameworks, CI providers, tools, and use cases.

In our community-supported guides, you'll find examples of how to use `turbo` with the rest of your tooling.

<Cards>
<Card
  title="Using AI"
  description="Get the most out of AI coding assistants"
  href="/docs/guides/ai"
/>

<Card
  title="Frameworks"
  description="Integrate frameworks into your Turborepo"
  href="/docs/guides/frameworks"
/>
<Card
  title="Continuous Integration"
  description="Use Turborepo with your CI"
  href="/docs/guides/ci-vendors"
/>

<Card
  title="Tools"
  description="Bring your favorite tooling"
  href="/docs/guides/tools"
/>

<Card
  title="Single-package workspaces"
  description="Integrate with a standalone application"
  href="/docs/guides/single-package-workspaces"
/>

<Card
  title="Runtime dependencies"
  description="Coordinate services that depend on each other while running"
  href="/docs/guides/coordinating-runtime-dependencies"
/>

<Card
  title="Generating code"
  description="Create new code fast"
  href="/docs/guides/generating-code"
/>

<Card
  title="Skipping tasks"
  description="Go fast by doing nothing"
  href="/docs/guides/skipping-tasks"
/>

<Card
  title="Publishing packages"
  description="Use your packages outside of your Turborepo"
  href="/docs/guides/publishing-libraries"
/>

<Card
  title="Handling platforms"
  description="OS, Node.js version, and other factors"
  href="/docs/guides/handling-platforms"
/>

<Card
  title="Multi-language support"
  description="Many languages, one repository"
  href="/docs/guides/multi-language"
/>
</Cards>

---

### Apps Docs Content Docs Reference Index (`apps/docs/content/docs/reference/index.mdx`)

---
title: Turborepo API reference
description: Learn about Turborepo's APIs using the reference.
product: turborepo
type: overview
summary: Entry point for all Turborepo API reference documentation including configuration, CLI commands, and packages.
related:
  - /docs/reference/configuration
  - /docs/reference/options-overview
  - /docs/reference/run
---

Turborepo's API reference is broken up into the following sections:

## Configuration

<Cards>
    <Card
        title="Configuring turbo.json"
        href="/docs/reference/configuration"
        description="Configure the behavior of `turbo`."
    />

    <Card
        title="Package Configurations"
        href="/docs/reference/package-configurations"
        description="Create configurations specific to a package."
    />

    <Card
        title="System environment variables"
        href="/docs/reference/system-environment-variables"
        description="Change `turbo`'s behavior using environment variables."
    />

    <Card
        title="File glob specification"
        href="/docs/reference/globs"
        description="Define files for `turbo` to use."
    />

</Cards>

## Commands

<Cards>
    <Card
        title="run"
        href="/docs/reference/run"
        description="Run tasks using `turbo`."
    />

    <Card
        title="watch"
        href="/docs/reference/watch"
        description="Dependency-aware, single-process task watcher."
    />
    <Card
        title="prune"
        href="/docs/reference/prune"
        description="Create partial monorepos for target workspaces."
    />
    <Card
        title="boundaries"
        href="/docs/reference/boundaries"
        description="Enforce best practices in your monorepo."
    />
    <Card
        title="ls"
        href="/docs/reference/ls"
        description="List packages in your monorepo."
    />

    <Card
        title="query"
        href="/docs/reference/query"
        description="Run GraphQL queries against your monorepo."
    />

    <Card
        title="generate"
        href="/docs/reference/generate"
        description="Extend your Turborepo with new apps and packages."
    />

    <Card
        title="login"
        href="/docs/reference/login"
        description="Log in to your Remote Cache provider."
    />

    <Card
        title="logout"
        href="/docs/reference/logout"
        description="Log out of your Remote Cache provider."
    />

    <Card
        title="link"
        href="/docs/reference/link"
        description="Link your repository to Remote Cache."
    />

    <Card
        title="unlink"
        href="/docs/reference/unlink"
        description="Disconnect your repository from Remote Cache."
    />

    <Card
        title="scan (Deprecated)"
        href="/docs/reference/scan"
        description="Deprecated. Will be removed in a future major version."
    />

    <Card
        title="bin"
        href="/docs/reference/bin"
        description="Get the path to the `turbo` binary."
    />

    <Card
        title="docs"
        href="/docs/reference/docs"
        description="Search the Turborepo documentation."
    />

    <Card
        title="telemetry"
        href="/docs/reference/telemetry"
        description="Manage telemetry for the machine."
    />

</Cards>

## Packages

<Cards>
    <Card
        title="create-turbo"
        href="/docs/reference/create-turbo"
        description="Get started with Turborepo using an example."
    />

    <Card
        title="eslint-config-turbo"
        href="/docs/reference/eslint-config-turbo"
        description="Find environment variables not listed in `turbo.json`."
    />

    <Card
        title="turbo-ignore (Deprecated)"
        href="/docs/reference/turbo-ignore"
        description="Deprecated. Use `turbo query affected` instead."
    />

    <Card
        title="@turbo/gen"
        href="/docs/reference/turbo-gen"
        description="Type definitions for Turborepo generators."
    />

</Cards>

## Flag syntax

Options that require a value can be passed with an equals sign, using quotes when spaces are needed.

```bash title="Terminal"
--opt=value
--opt="value with a space"
--opt value
--opt "value with a space"
```

## Global flags

### `--color`

Forces the use of color, even in non-interactive terminals. This is useful for enabling color output in CI environments like GitHub Actions that have support for rendering color.

### `--no-color`

Suppresses color in terminal output, even in interactive terminals.

### `--no-update-notifier`

Disables the update notification. This notification will be automatically disabled when running in CI environments, but can also be disabled manually via this flag.

Alternatively, you can disable the notification using [the `TURBO_NO_UPDATE_NOTIFIER` environment variable](/docs/reference/system-environment-variables).

---

### Apps Docs Content Docs Reference Options Overview (`apps/docs/content/docs/reference/options-overview.mdx`)

---
title: Options overview
description: Flags, configurations, and System Environment Variables for Turborepo
product: turborepo
type: reference
summary: Quick-reference table mapping CLI flags, environment variables, and turbo.json configuration options.
related:
  - /docs/reference/configuration
  - /docs/reference/system-environment-variables
  - /docs/reference/run
---

There are three ways to manage the behavior of a `turbo` invocation:

- [Configuration in `turbo.json`](/docs/reference/configuration)
- [System Environment Variables](/docs/reference/system-environment-variables)
- [Flags passed to the CLI invocation](/docs/reference/run)

The three strategies listed above are in order of precedence. Where a flag value is provided, for the same System Environment Variable or `turbo.json` configuration, the value for the flag will be used. Because of this, we recommend using:

- `turbo.json` configuration for defaults
- System Environment Variables for per-environment overrides
- Flags for per-invocation overrides

## Options table

### Caching

<div className="options-cheat-sheet-table">

| Behavior                    | Flags                                                             | Environment Variables                                                                                                 | turbo.json                                                                 |
| --------------------------- | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Force tasks to run          | [`--force`](/docs/reference/run#--force)                          | [`TURBO_FORCE`](/docs/reference/system-environment-variables#turbo_force)                                             | [`cache`](/docs/reference/configuration#cache)                             |
| Remote Cache timeout        | [`--remote-cache-timeout`](/docs/reference/configuration#timeout) | [`TURBO_REMOTE_CACHE_TIMEOUT`](/docs/reference/system-environment-variables#turbo_remote_cache_timeout)               | [`remoteCache.timeout`](/docs/reference/configuration#timeout)             |
| Remote Cache upload timeout | -                                                                 | [`TURBO_REMOTE_CACHE_UPLOAD_TIMEOUT`](/docs/reference/system-environment-variables#turbo_remote_cache_upload_timeout) | [`remoteCache.uploadTimeout`](/docs/reference/configuration#uploadtimeout) |
| Cache signature key         | -                                                                 | [`TURBO_REMOTE_CACHE_SIGNATURE_KEY`](/docs/reference/system-environment-variables#turbo_remote_cache_signature_key)   | [`signature`](/docs/reference/configuration#signature)                     |
| Preflight request           | [`--preflight`](/docs/reference/run#--preflight)                  | [`TURBO_PREFLIGHT`](/docs/reference/system-environment-variables#turbo_preflight)                                     | [`remoteCache.preflight`](/docs/reference/configuration#preflight)         |
| Remote Cache base URL       | -                                                                 | [`TURBO_API`](/docs/reference/system-environment-variables#turbo_api)                                                 | [`remoteCache.apiUrl`](/docs/reference/configuration#remote-caching)       |
| Cache sources               | [`--cache`](/docs/reference/run#--cache-options)                  | [`TURBO_CACHE`](/docs/reference/system-environment-variables#turbo_cache)                                             | -                                                                          |
| Local cache directory       | [`--cache-dir`](/docs/reference/run#--cache-dir-path)             | [`TURBO_CACHE_DIR`](/docs/reference/system-environment-variables#turbo_cache_dir)                                     | [`cacheDir`](/docs/reference/configuration#cachedir)                       |
| Local cache max age         | -                                                                 | [`TURBO_CACHE_MAX_AGE`](/docs/reference/system-environment-variables#turbo_cache_max_age)                             | [`cacheMaxAge`](/docs/reference/configuration#cachemaxage)                 |
| Local cache max size        | -                                                                 | [`TURBO_CACHE_MAX_SIZE`](/docs/reference/system-environment-variables#turbo_cache_max_size)                           | [`cacheMaxSize`](/docs/reference/configuration#cachemaxsize)               |

</div>

### Messages

<div className="options-cheat-sheet-table">

| Behavior                       | Flags | Environment Variables                                                                                               | turbo.json                                                                                |
| ------------------------------ | ----- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| Disable version print          | -     | [`TURBO_PRINT_VERSION_DISABLED`](/docs/reference/system-environment-variables#turbo_print_version_disabled)         | -                                                                                         |
| Disable telemetry message      | -     | [`TURBO_TELEMETRY_MESSAGE_DISABLED`](/docs/reference/system-environment-variables#turbo_telemetry_message_disabled) | -                                                                                         |
| Disable global `turbo` warning | -     | [`TURBO_GLOBAL_WARNING_DISABLED`](/docs/reference/system-environment-variables#turbo_global_warning_disabled)       | -                                                                                         |
| No update notifier             | -     | [`TURBO_NO_UPDATE_NOTIFIER`](/docs/reference/system-environment-variables#turbo_no_update_notifier)                 | [`noUpdateNotifier`](https://turborepo.dev/docs/reference/configuration#noupdatenotifier) |

</div>

### Task running and logs

<div className="options-cheat-sheet-table">

| Behavior                          | Flags                                                                                                            | Environment Variables                                                                                                                             | turbo.json                                                                                                     |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| Terminal UI                       | [`--ui`](/docs/reference/run#--ui)                                                                               | [`TURBO_UI`](/docs/reference/system-environment-variables#turbo_ui)                                                                               | [`ui`](/docs/reference/configuration#ui)                                                                       |
| Run affected tasks                | [`--affected`](/docs/reference/run#--affected)                                                                   | -                                                                                                                                                 | -                                                                                                              |
| Disable package manager check     | [`--dangerously-disable-package-manager-check`](/docs/reference/run#--dangerously-disable-package-manager-check) | [`TURBO_DANGEROUSLY_DISABLE_PACKAGE_MANAGER_CHECK`](/docs/reference/system-environment-variables#turbo_dangerously_disable_package_manager_check) | [`dangerouslyDisablePackageManagerCheck`](/docs/reference/configuration#dangerouslydisablepackagemanagercheck) |
| Affected base ref                 | -                                                                                                                | [`TURBO_SCM_BASE`](/docs/reference/system-environment-variables#turbo_scm_base)                                                                   | -                                                                                                              |
| Affected head ref                 | -                                                                                                                | [`TURBO_SCM_HEAD`](/docs/reference/system-environment-variables#turbo_scm_head)                                                                   | -                                                                                                              |
| Only run directly specified tasks | [`--only`](/docs/reference/run#--only)                                                                           | -                                                                                                                                                 | -                                                                                                              |
| Task concurrency                  | [`--concurrency`](/docs/reference/run#--concurrency-number--percentage)                                          | [`TURBO_CONCURRENCY`](/docs/reference/system-environment-variables#turbo_concurrency)                                                             | -                                                                                                              |
| Task log order                    | [`--log-order`](/docs/reference/run#--log-order-option)                                                          | [`TURBO_LOG_ORDER`](/docs/reference/system-environment-variables#turbo_log_order)                                                                 | -                                                                                                              |
| Current working directory         | [`--cwd`](/docs/reference/run#--cwd-path)                                                                        | -                                                                                                                                                 | -                                                                                                              |
| Streamed logs prefix              | [`--log-prefix`](/docs/reference/run#--log-prefix-option)                                                        | -                                                                                                                                                 | -                                                                                                              |
| Task logs output level            | [`--output-logs-option`](/docs/reference/run#--output-logs-option)                                               | -                                                                                                                                                 | [`outputLogs`](/docs/reference/configuration#outputlogs)                                                       |
| Global inputs                     | [`--global-deps`](/docs/reference/run#--global-deps-file-glob)                                                   | -                                                                                                                                                 | [`globalDependencies`](/docs/reference/configuration#globaldependencies)                                       |
| Terminal colors                   | [`--color`](/docs/reference#--color)                                                                             | [FORCE_COLOR](/docs/reference/system-environment-variables#force_color)                                                                           | -                                                                                                              |

</div>

### Environment variables

<div className="options-cheat-sheet-table">

| Behavior                      | Flags                                                                | Environment Variables                                                                             | turbo.json                                         |
| ----------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| Environment variable mode     | [`--env-mode`](/docs/reference/run#--env-mode-option)                | -                                                                                                 | [`envMode`](/docs/reference/configuration#envmode) |
| Vendor environment variables  | -                                                                    | [`TURBO_CI_VENDOR_ENV_KEY`](/docs/reference/system-environment-variables#turbo_ci_vendor_env_key) | -                                                  |
| Framework variable exceptions | [`--framework-inference`](/docs/reference/run#--framework-inference) | -                                                                                                 | -                                                  |

</div>

### Debugging outputs

<div className="options-cheat-sheet-table">

| Behavior            | Flags                                              | Environment Variables                                                                 | turbo.json |
| ------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------- |
| Run Summaries       | [`--summarize`](/docs/reference/run#--summarize)   | [`TURBO_RUN_SUMMARY`](/docs/reference/system-environment-variables#turbo_run_summary) | -          |
| Graph visualization | [`--graph`](/docs/reference/run#--graph-file-name) | -                                                                                     | -          |
| Dry run             | [`--dry`](/docs/reference/run#--dry----dry-run)    | -                                                                                     | -          |

</div>

### Authentication

<div className="options-cheat-sheet-table">

| Behavior                                | Flags                                    | Environment Variables                                                       | turbo.json                                                       |
| --------------------------------------- | ---------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| Login URL                               | -                                        | [`TURBO_LOGIN`](/docs/reference/system-environment-variables#turbo_login)   | [`remoteCache.loginUrl`](/docs/reference/configuration#loginurl) |
| Team name (for multi-team Remote Cache) | [`--team`](/docs/reference/run#--team)   | [`TURBO_TEAM`](/docs/reference/system-environment-variables#turbo_team)     | -                                                                |
| Team ID (for multi-team Remote Cache)   | -                                        | [`TURBO_TEAMID`](/docs/reference/system-environment-variables#turbo_teamid) | -                                                                |
| Authentication token                    | [`--token`](/docs/reference/run#--token) | [`TURBO_TOKEN`](/docs/reference/system-environment-variables#turbo_token)   | -                                                                |

</div>

### Other

<div className="options-cheat-sheet-table">

| Behavior               | Flags                                                                      | Environment Variables                                                                                       | turbo.json                                       |
| ---------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| Binary path            | -                                                                          | [`TURBO_BINARY_PATH`](/docs/reference/system-environment-variables#turbo_binary_path)                       | -                                                |
| Download local `turbo` | -                                                                          | [`TURBO_DOWNLOAD_LOCAL_ENABLED`](/docs/reference/system-environment-variables#turbo_download_local_enabled) | -                                                |
| Daemon (deprecated)    | [`--daemon` / `--no-daemon`](/docs/reference/run#--daemon-and---no-daemon) | -                                                                                                           | [`daemon`](/docs/reference/configuration#daemon) |

</div>

---

### Apps Docs Content Openapi Artifacts Index (`apps/docs/content/openapi/artifacts/index.mdx`)

---
title: Artifacts
description: Endpoints for managing cache artifacts.
---

Endpoints for uploading, downloading, and querying cache artifacts.

---

### Apps Docs Content Docs Guides Ci Vendors Index (`apps/docs/content/docs/guides/ci-vendors/index.mdx`)

---
title: Continuous Integration
description: Recipes for using Turborepo with Vercel, GitHub Actions, and other continuous integration providers.
product: turborepo
type: overview
summary: Browse CI provider recipes for using Turborepo with Remote Caching in your pipelines.
related:
  - /docs/guides/ci-vendors/vercel
  - /docs/guides/ci-vendors/github-actions
  - /docs/guides/ci-vendors/circleci
  - /docs/guides/ci-vendors/gitlab-ci
  - /docs/guides/ci-vendors/travis-ci
  - /docs/guides/ci-vendors/buildkite
---

Turborepo not only speeds up builds, but also the rest of your Continuous Integration pipeline by using [Remote Caching](/docs/core-concepts/remote-caching). Below are a few platform recipes to use Turborepo with your CI providers.

<Cards>

<Card
  title="Vercel (Zero configuration)"
  href="/docs/guides/ci-vendors/vercel"
/>

<Card title="GitHub Actions" href="/docs/guides/ci-vendors/github-actions" />

<Card title="CircleCI" href="/docs/guides/ci-vendors/circleci" />

<Card title="GitLab CI" href="/docs/guides/ci-vendors/gitlab-ci" />

<Card title="Travis CI" href="/docs/guides/ci-vendors/travis-ci" />

<Card title="Buildkite" href="/docs/guides/ci-vendors/buildkite" />

</Cards>

## General Setup

To enable Remote Caching for your CI:

1. Setup the environment variables for Turborepo in your CI to access your Remote Cache.
   | Variable | Description |
   | ----------- | ----------- |
   | `TURBO_TOKEN` | The Bearer token to access the Remote Cache |
   | `TURBO_TEAM` | The account name associated with your repository. When using <a href="https://vercel.com/docs/monorepos/remote-caching#vercel-remote-cache" rel="noreferrer noopener" target="_blank">Vercel Remote Cache</a>, this is [your team's slug](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fsettings&title=Get+team+slug). |
2. Clone your repository.
3. Install your dependencies through your package manager.
4. Run your tasks through `turbo`.

---

### Apps Docs Content Docs Guides Frameworks Index (`apps/docs/content/docs/guides/frameworks/index.mdx`)

---
title: Frameworks
description: Integrate your favorite framework into Turborepo.
product: turborepo
type: overview
summary: Browse guides for integrating popular frontend frameworks with Turborepo.
related:
  - /docs/guides/frameworks/nextjs
  - /docs/guides/frameworks/sveltekit
  - /docs/guides/frameworks/vite
  - /docs/guides/frameworks/nuxt
---

Turborepo works with **any framework**. Below, you'll find guides for the most common frameworks being used with Turborepo.

<Cards>
<Card
  title="Next.js"
  href="/docs/guides/frameworks/nextjs"
/>

<Card title="SvelteKit" href="/docs/guides/frameworks/sveltekit" />

<Card title="Vite" href="/docs/guides/frameworks/vite" />

<Card title="Nuxt" href="/docs/guides/frameworks/nuxt" />

</Cards>

---

### Apps Docs Content Docs Guides Tools Index (`apps/docs/content/docs/guides/tools/index.mdx`)

---
title: Tools
description: Learn how to use your favorite tools in a monorepo.
product: turborepo
type: overview
summary: Browse guides for integrating popular development tools with Turborepo.
related:
  - /docs/guides/tools/eslint
  - /docs/guides/tools/typescript
  - /docs/guides/tools/vitest
  - /docs/guides/tools/docker
---

Turborepo works with **all of your favorite tooling**. Below, you'll find guides for the most common tools being used with Turborepo.

<Cards>
  <Card title="Biome" href="/docs/guides/tools/biome" />
  <Card title="Docker" href="/docs/guides/tools/docker" />
  <Card title="ESLint" href="/docs/guides/tools/eslint" />
  <Card title="Jest" href="/docs/guides/tools/jest" />
  <Card title="Oxc (oxlint, oxfmt)" href="/docs/guides/tools/oxc" />
  <Card title="Prisma" href="/docs/guides/tools/prisma" />
  <Card title="Go (experimental)" href="/docs/guides/tools/go" />
  <Card title="Rust (experimental)" href="/docs/guides/tools/rust" />
  <Card title="shadcn/ui" href="/docs/guides/tools/shadcn-ui" />
  <Card title="Storybook" href="/docs/guides/tools/storybook" />
  <Card title="TypeScript" href="/docs/guides/tools/typescript" />
  <Card title="Vitest" href="/docs/guides/tools/vitest" />
</Cards>

---

### Apps Docs AGENTS (`apps/docs/AGENTS.md`)

# Turborepo docs app

The root `AGENTS.md` also applies to this app. Geistdocs owns shared runtime behavior, while this app owns Turborepo content, routes, metadata, assets, and adapters.

## Geistdocs

- Read `node_modules/@vercel/geistdocs/docs/agents.md` and its focused package docs before changing package-backed behavior.
- Keep `createGeistdocs` as the outer Next.js wrapper. Keep `cacheComponents` and `partialPrefetching` enabled.
- Do not export `dynamic`, `revalidate`, `fetchCache`, or `dynamicParams` from App Router files. Use `use cache` and `cacheLife` for app-owned caching.
- Read `[lang]` through `next/root-params` in Server Components. Keep route-handler and Server Action `params` in their context arguments.
- Use `prefetch={true}` for app-owned links to statically generated documentation pages.
- Restart `next dev` after adding, deleting, or renaming App Router pages or route handlers.
- Do not edit `.source`, `.next`, `node_modules`, or package internals.

## Public contracts

- `/llms.txt` is the page index. `/llms-full.txt` is the complete docs corpus.
- Preserve page Markdown, content negotiation, `/agents.md`, `/sitemap.md`, both RSS feeds, the XML sitemap, robots rules, search, Ask AI, signed OG routes, schemas, and proxy exclusions.
- Static app-owned routes serve `/terms` and `/governance`. The localized not-found page owns browser 404s, while Geistdocs owns automatic agent-readable 404 recovery.
- Keep blog, OpenAPI, showcase, Devtools, redirects, version-host behavior, analytics, and the Remote Cache page action app-owned.
- Do not advertise an MCP server unless Turborepo provides one.



# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` (resolved from this file's directory; in monorepos the `next` package may not be visible from the repo root) before writing any code. Heed deprecation notices.

This block is written and re-added by `next dev` — verify at `node_modules/next/dist/server/lib/generate-agent-files.js`. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.

---

### Apps Docs Content Blog 2 10 (`apps/docs/content/blog/2-10.mdx`)

---
title: Turborepo 2.10
date: 2026/06/24
description: "Graceful task shutdown, deferred input hashing, composable `--affected` and `--filter`, local cache eviction."
product: turborepo
type: overview
summary: Release notes for Turborepo 2.10 featuring graceful task shutdown, deferred input hashing, composable `--affected` and `--filter`, and local cache eviction.
tag: "web development"
---

import { Authors } from "@/components/blog/authors";
import { Callout } from "@/components/geistdocs/callout";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Date } from "@/components/blog/date";
import { Accordion, Accordions } from "@/components/geistdocs/accordion";

# Turborepo 2.10

<Date>Wednesday, June 24th, 2026</Date>

<Authors authors={["anthonyshew"]} />

Turborepo 2.10 improves day-to-day reliability in your repository:

- [**Graceful task shutdown**](#graceful-task-shutdown): Exit your development environment cleanly
- [**Deferred input hashing**](#deferred-input-hashing): Hash generated files and dependency outputs after upstream tasks complete
- [**Combine `--affected` and `--filter`**](#combine---affected-and---filter): Narrow CI runs to affected packages within a specific scope
- [**Local cache eviction**](#local-cache-eviction): Automatically reclaim disk space from your local cache

---

Upgrade today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Use the automated upgrade CLI
pnpm dlx @turbo/codemod migrate

# Start a new repository
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Use the automated upgrade CLI
yarn dlx @turbo/codemod migrate

# Start a new repository
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Use the automated upgrade CLI
npx @turbo/codemod migrate

# Start a new repository
npx create-turbo@latest
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Use the automated upgrade CLI
bunx @turbo/codemod migrate

# Start a new repository
bunx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

Install or update your [Turborepo Agent Skill](/docs/guides/ai#agent-skill):

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Install the Turborepo Agent Skill
pnpm dlx skills add vercel/turborepo

# Update the Turborepo Agent Skill
pnpm dlx skills update vercel/turborepo
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Install the Turborepo Agent Skill
yarn dlx skills add vercel/turborepo

# Update the Turborepo Agent Skill
yarn dlx skills update vercel/turborepo
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Install the Turborepo Agent Skill
npx skills add vercel/turborepo

# Update the Turborepo Agent Skill
npx skills update vercel/turborepo
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Install the Turborepo Agent Skill
bunx skills add vercel/turborepo

# Update the Turborepo Agent Skill
bunx skills update vercel/turborepo
```

</Tab>

</PackageManagerTabs>

---

## Graceful task shutdown

It's common for a repository to have cleanup steps when closing out a development environment. For example, flushing logs, terminating a Docker Compose script, or closing a background process.

In previous versions, Turborepo exited immediately when it received a `SIGTERM` or `SIGINT` signal, abruptly killing all of your tasks. A server wouldn't close its connections, a background process wouldn't get cleaned up, and you'd be left to sort out the mess yourself.

Now, Turborepo forwards `Ctrl+C` (or `SIGINT`/`SIGTERM`) to your tasks and waits for them to finish shutting down. Your signal handling code runs, cleanup finishes, and Turborepo exits after every task is done.

```bash title="Terminal"
▲ ~ turbo dev

   • turbo 2.10.0

server:dev: cache bypass, force executing 57ef564a0dbdb237
server:dev:
server:dev: Server started...
server:dev: Handling request [GET] /
^C - Shutting down Turborepo tasks...Press CTRL+C again to exit forcefully.
server:dev: SIGINT received!
server:dev: Terminating database connection...
server:dev: Terminated database connection.

 Tasks:    1 successful, 1 total
Cached:    0 cached, 1 total
  Time:    3.6s
```

There's nothing to configure, and tasks without their own signal handling behave exactly as before.

## Deferred input hashing

By default, Turborepo creates the hashes for all of your tasks right when `turbo` starts. Hashing up front lets Turborepo execute your Task Graph as fast as possible, since it can instantly know whether each task is a cache hit or miss.

But some file inputs aren't stable while the Task Graph is executing. An upstream task like `codegen` might change files **after** `turbo` has already hashed everything. Because task hashing happened too early, you might choose to turn off caching, or risk unexpected cache hits.

Starting with this release, you can use structured `inputs` objects to defer hashing until the right moment in the run. We're introducing two new task hashing primitives.

### Just-in-Time task hashing

When you need to delay hashing for a specific task, use `"mode": "jit"`. Postponing task hashing gives your task the freedom to edit file inputs after initial hashing and still hit cache for dependent tasks.

In the example below, the `build` task needs a generated GraphQL schema from a remote source:

```jsonc title="turbo.json"
{
  "tasks": {
    "codegen": {
      "cache": false,
    },
    "build": {
      "dependsOn": ["codegen"],
      "inputs": [
        "$TURBO_DEFAULT$",
        "!src/generated/**",
        {
          "mode": "jit",
          "globs": ["src/generated/**"],
        },
      ],
    },
  },
}
```

Because the GraphQL schema must be fetched, that task is uncacheable. The `build` task can still hit cache safely if the schema doesn't change. Just-in-Time hashing delays the task hash for `build` until **after** `codegen` has completed, ensuring that `build`'s task hash uses the generated inputs.

### Output-dependent task hashing

When you want the outputs of task dependencies to affect the hash of dependent tasks, use the `dependencyOutputs` mode. Output-dependent task hashing uses the outputs of a task dependency as file inputs to a dependent task.

For example, the following configuration can increase cache hit ratios for type checking in a TypeScript repository that emits type declaration files:

```jsonc title="turbo.json"
{
  "tasks": {
    "check-types": {
      "dependsOn": ["^check-types"],
      "outputs": ["dist/**"],
      "inputs": [
        "$TURBO_DEFAULT$",
        {
          "mode": "dependencyOutputs",
          "globs": ["dist/**/*.d.ts"],
          "from": ["^check-types"]
        }
      ]
    }
  }
}
```

This configuration uses the type declaration files in `dist` as inputs to a task dependent's hash, meaning task dependents will only miss cache when the package's interface changes. Updating internal logic or comments won't result in cache misses in dependencies, but changing the interface of an export will.

[Visit the documentation](/docs/reference/configuration#deferred-hashing) to learn more.

## Combine `--affected` and `--filter`

Previously, you couldn't use `--affected` and `--filter` at the same time. Now, you can.

```bash title="Terminal"
# Only run build for "web" if it's affected by changes
turbo run build --affected --filter=web

# Run affected packages, excluding "docs"
turbo run build --affected --filter=!docs

# List "my-app" only if it's affected
turbo query ls --affected --filter=my-app
```

The two flags intersect, so only the tasks that match **both** constraints run. To learn more, [visit the documentation](/docs/reference/run#--affected).

## Local cache eviction

Turborepo saves its local cache into `.turbo/cache`, adding cache artifacts every time you run a cacheable task. This speeds up repeat runs, but the cache never stops growing.

Turborepo now supports automatic eviction through two opt-in configuration options in `turbo.json`. You can use either age-based eviction or size-based eviction:

```jsonc title="turbo.json"
{
  "cacheMaxAge": "7d",
  "cacheMaxSize": "10GB",
}
```

`cacheMaxAge` clears artifacts older than the limit. `cacheMaxSize` clears the oldest artifacts first once the cache passes the cap. Eviction runs in a background thread at the start of each `turbo run`, so it does not block tasks.

We expect to enable local cache eviction by default in Turborepo 3.0. [Read more here.](/docs/reference/configuration#cachemaxage)

## All changes

<Accordions>

  <Accordion title="Feat (13)">

    - feat: Add deferred hashing for task inputs ([#13125](https://github.com/vercel/turborepo/pull/13125))
    - feat: Add JIT task input hashing ([#13043](https://github.com/vercel/turborepo/pull/13043))
    - feat: Add Rsbuild examples ([#12942](https://github.com/vercel/turborepo/pull/12942))
    - feat: Add heap allocation profiling ([#12943](https://github.com/vercel/turborepo/pull/12943))
    - feat: Move Vercel auth to standard OAuth/device flows ([#12526](https://github.com/vercel/turborepo/pull/12526))
    - feat: Bump @vercel/sandbox from v1 to beta ([#12595](https://github.com/vercel/turborepo/pull/12595))
    - feat: Add circular package dependency detection to boundaries ([#12567](https://github.com/vercel/turborepo/pull/12567))
    - feat: Replace package manager commands in scaffolded README files ([#6747](https://github.com/vercel/turborepo/pull/6747))
    - feat: Allow `--affected` and `--filter` to be combined ([#12543](https://github.com/vercel/turborepo/pull/12543))
    - feat: Add incremental task caching ([#12531](https://github.com/vercel/turborepo/pull/12531))
    - feat: Add Next.js + Elysia full-stack starter template ([#12414](https://github.com/vercel/turborepo/pull/12414))
    - feat: Add `cacheMaxAge` and `cacheMaxSize` for local cache eviction ([#12487](https://github.com/vercel/turborepo/pull/12487))
    - feat: Handle package manager catalogs in migration codemod ([#12496](https://github.com/vercel/turborepo/pull/12496))

  </Accordion>

  <Accordion title="Perf (6)">

    - perf: Trim microfrontends proxy HTTP features ([#12931](https://github.com/vercel/turborepo/pull/12931))
    - perf: Trim OpenTelemetry crate features ([#12930](https://github.com/vercel/turborepo/pull/12930))
    - perf: Index repo gitignore matchers ([#12928](https://github.com/vercel/turborepo/pull/12928))
    - perf: Reduce `turbo watch` hash memory spikes ([#12695](https://github.com/vercel/turborepo/pull/12695))
    - perf: Parallelize `boundaries` checking with Rayon and cache DFS traversals ([#12569](https://github.com/vercel/turborepo/pull/12569))
    - perf: Increase remote cache upload chunk size from 8KB to 256KB ([#12568](https://github.com/vercel/turborepo/pull/12568))

  </Accordion>

  <Accordion title="Fix (247)">

    - fix: Hash selected dependency outputs instead of tasks ([#13129](https://github.com/vercel/turborepo/pull/13129))
    - fix: Improve watch graceful shutdown ([#13128](https://github.com/vercel/turborepo/pull/13128))
    - fix: Restart deferred hash consumers in watch ([#13127](https://github.com/vercel/turborepo/pull/13127))
    - fix: Respect task inputs when stopping interruptible persistent tasks in watch ([#13116](https://github.com/vercel/turborepo/pull/13116))
    - fix: Add ComSpec and PATHEXT to default Windows env passthrough ([#13114](https://github.com/vercel/turborepo/pull/13114))
    - fix: Relocate stranded transitive deps when promoting npm workspace-nested packages ([#13111](https://github.com/vercel/turborepo/pull/13111))
    - fix: Upgrade esbuild to patched version ([#13112](https://github.com/vercel/turborepo/pull/13112))
    - fix: Preserve terminal settings for child PTYs ([#13110](https://github.com/vercel/turborepo/pull/13110))
    - fix: Ignore symlink cycles when caching outputs ([#13107](https://github.com/vercel/turborepo/pull/13107))
    - fix: Preserve bun patchedDependencies during prune ([#13106](https://github.com/vercel/turborepo/pull/13106))
    - fix: Thread `allow_no_package_manager` to daemon and watcher ([#13091](https://github.com/vercel/turborepo/pull/13091))
    - fix: Soften force shutdown message ([#13104](https://github.com/vercel/turborepo/pull/13104))
    - fix: Upgrade tsdown in kitchen-sink api to fix dev script ([#13105](https://github.com/vercel/turborepo/pull/13105))
    - fix: Restore TUI force shutdown ([#13102](https://github.com/vercel/turborepo/pull/13102))
    - fix: Gracefully stop nested PTY processes ([#13100](https://github.com/vercel/turborepo/pull/13100))
    - fix: Refine graceful shutdown messaging ([#13098](https://github.com/vercel/turborepo/pull/13098))
    - fix: Remove accidental shell commands example changes ([#13094](https://github.com/vercel/turborepo/pull/13094))
    - fix: Prevent duplicate PTY graceful shutdown signals ([#13093](https://github.com/vercel/turborepo/pull/13093))
    - fix: Handle Windows package manager shutdown ([#13090](https://github.com/vercel/turborepo/pull/13090))
    - fix: Use repo package manager for generate ([#13089](https://github.com/vercel/turborepo/pull/13089))
    - fix: Precompute unblocked JIT descendants ([#13088](https://github.com/vercel/turborepo/pull/13088))
    - fix: Preserve pnpm peer-resolved prune entries ([#13086](https://github.com/vercel/turborepo/pull/13086))
    - fix: Speed up default create-turbo download ([#13085](https://github.com/vercel/turborepo/pull/13085))
    - fix: Preserve PNPM deps check config ([#13084](https://github.com/vercel/turborepo/pull/13084))
    - fix: Prevent ConPTY cursor query output ([#13077](https://github.com/vercel/turborepo/pull/13077))
    - fix: Cache outputs through internal symlinks ([#13076](https://github.com/vercel/turborepo/pull/13076))
    - fix: Filter pruned pnpm workspace patches ([#13075](https://github.com/vercel/turborepo/pull/13075))
    - fix: Use PTY for interactive Windows tasks ([#13073](https://github.com/vercel/turborepo/pull/13073))
    - fix: Deliver Ctrl-C to ConPTY children during graceful shutdown on Windows ([#13069](https://github.com/vercel/turborepo/pull/13069))
    - fix: Stop shim from killing local turbo on Windows Ctrl+C ([#13067](https://github.com/vercel/turborepo/pull/13067))
    - fix: Re-authenticate when stored token loses access to linked team ([#13064](https://github.com/vercel/turborepo/pull/13064))
    - fix: Block self-hosted login URLs from attempting to use Vercel's SSO ([#13061](https://github.com/vercel/turborepo/pull/13061))
    - fix: Validate OidHash hex buffers ([#13060](https://github.com/vercel/turborepo/pull/13060))
    - fix: Separate artifact signature fields ([#13059](https://github.com/vercel/turborepo/pull/13059))
    - fix: Preserve vt100 cell byte counts ([#13058](https://github.com/vercel/turborepo/pull/13058))
    - fix: Normalize Windows daemon path hash ([#13020](https://github.com/vercel/turborepo/pull/13020))
    - fix: Contain incremental cache outputs ([#13057](https://github.com/vercel/turborepo/pull/13057))
    - fix: Strip special mode bits from cache restore ([#13056](https://github.com/vercel/turborepo/pull/13056))
    - fix: Prevent git argument injection in SCM refs ([#13055](https://github.com/vercel/turborepo/pull/13055))
    - fix: Confine prune patch paths ([#13054](https://github.com/vercel/turborepo/pull/13054))
    - fix: Harden query server file access ([#13053](https://github.com/vercel/turborepo/pull/13053))
    - fix: Harden cache archive symlink restore ([#13051](https://github.com/vercel/turborepo/pull/13051))
    - fix: Send Ctrl+C to Windows PTY tasks ([#13041](https://github.com/vercel/turborepo/pull/13041))
    - fix: Defer hashes for JIT task dependents ([#13045](https://github.com/vercel/turborepo/pull/13045))
    - fix: Bypass npm command shim on Windows ([#13040](https://github.com/vercel/turborepo/pull/13040))
    - fix: Support P-521 ECDSA certificate chains over rustls ([#13036](https://github.com/vercel/turborepo/pull/13036))
    - fix: Add TUI pane padding before logs ([#13034](https://github.com/vercel/turborepo/pull/13034))
    - fix: Keep PTY stdin open for tasks ([#13033](https://github.com/vercel/turborepo/pull/13033))
    - fix: Preserve pnpm override-resolved prune deps ([#13031](https://github.com/vercel/turborepo/pull/13031))
    - fix: Ignore peer dependencies in package graph ([#13025](https://github.com/vercel/turborepo/pull/13025))
    - fix: Highlight active docs sidebar item ([#13023](https://github.com/vercel/turborepo/pull/13023))
    - fix: Preserve Bun nested dependency versions ([#13016](https://github.com/vercel/turborepo/pull/13016))
    - fix: Wait for Windows graceful shutdown ([#12979](https://github.com/vercel/turborepo/pull/12979))
    - fix: Detect affected root tasks in query ([#12977](https://github.com/vercel/turborepo/pull/12977))
    - fix: Add auth HTTP timeouts ([#12976](https://github.com/vercel/turborepo/pull/12976))
    - fix: Keep non-PTY stdin alive for persistent tasks ([#12972](https://github.com/vercel/turborepo/pull/12972))
    - fix: Don't delete existing `.git` when using `--no-git` flag ([#12968](https://github.com/vercel/turborepo/pull/12968))
    - fix: Preserve nested Bun dependency versions ([#12965](https://github.com/vercel/turborepo/pull/12965))
    - fix: Preserve nested Bun dependency versions ([#12963](https://github.com/vercel/turborepo/pull/12963))
    - fix: Retry npm tlog publish failures ([#12959](https://github.com/vercel/turborepo/pull/12959))
    - fix: Avoid hanging PTY shutdown ([#12958](https://github.com/vercel/turborepo/pull/12958))
    - fix: Harden OTEL endpoint validation ([#12954](https://github.com/vercel/turborepo/pull/12954))
    - fix: Respect root gitignore during prune ([#12953](https://github.com/vercel/turborepo/pull/12953))
    - fix: Preserve pnpm injected peer package entries ([#12940](https://github.com/vercel/turborepo/pull/12940))
    - fix: Use build-scale OTel duration buckets ([#12939](https://github.com/vercel/turborepo/pull/12939))
    - fix: Improve profile tracing coverage ([#12936](https://github.com/vercel/turborepo/pull/12936))
    - fix: Restore a few internal invariant checks ([#12933](https://github.com/vercel/turborepo/pull/12933))
    - fix: Accept `experimentalCI` object config ([#12934](https://github.com/vercel/turborepo/pull/12934))
    - fix: Restore release PR auto-merge ([#12927](https://github.com/vercel/turborepo/pull/12927))
    - fix: Preserve nested Bun workspace dependency versions ([#12924](https://github.com/vercel/turborepo/pull/12924))
    - fix: Restore task completion semantics ([#12923](https://github.com/vercel/turborepo/pull/12923))
    - fix: Remove run summary test unwrap usage ([#12916](https://github.com/vercel/turborepo/pull/12916))
    - fix: Remove turbo json test unwrap allowance ([#12918](https://github.com/vercel/turborepo/pull/12918))
    - fix: Remove shim test unwrap usage ([#12917](https://github.com/vercel/turborepo/pull/12917))
    - fix: Remove `turborepo-lib`'s `expect()` usage ([#12914](https://github.com/vercel/turborepo/pull/12914))
    - fix: Remove `turborepo-lib`'s `unwrap()` usage ([#12915](https://github.com/vercel/turborepo/pull/12915))
    - fix: Remove `turborepo-vt100`'s `unwrap()` usage ([#12913](https://github.com/vercel/turborepo/pull/12913))
    - fix: Remove `turborepo-lockfiles`'s `unwrap()` usage ([#12911](https://github.com/vercel/turborepo/pull/12911))
    - fix: Remove `turborepo-lockfiles` `expect()` usage ([#12910](https://github.com/vercel/turborepo/pull/12910))
    - fix: Remove cache unwrap usage ([#12909](https://github.com/vercel/turborepo/pull/12909))
    - fix: Remove engine expect usage ([#12908](https://github.com/vercel/turborepo/pull/12908))
    - fix: Remove filewatch unwrap usage ([#12907](https://github.com/vercel/turborepo/pull/12907))
    - fix: Remove `turborepo-engine`'s `unwrap()` usage ([#12906](https://github.com/vercel/turborepo/pull/12906))
    - fix: Remove `turborepo-daemon`'s `expect()` usage ([#12904](https://github.com/vercel/turborepo/pull/12904))
    - fix: Remove `turborepo-cache`'s `expect()` usage ([#12902](https://github.com/vercel/turborepo/pull/12902))
    - fix: Remove `turborepo-filewatch`'s `expect()` usage ([#12903](https://github.com/vercel/turborepo/pull/12903))
    - fix: Remove `turborepo-wax`'s `expect()` usage ([#12901](https://github.com/vercel/turborepo/pull/12901))
    - fix: Include lockfile-changed packages in affected tasks ([#12900](https://github.com/vercel/turborepo/pull/12900))
    - fix: Remove daemon unwrap usage ([#12898](https://github.com/vercel/turborepo/pull/12898))
    - fix: Remove `turborepo-boundaries`'s `unwrap()` usage ([#12896](https://github.com/vercel/turborepo/pull/12896))
    - fix: Remove scm unwrap usage ([#12897](https://github.com/vercel/turborepo/pull/12897))
    - fix: Remove wax unwrap usage ([#12899](https://github.com/vercel/turborepo/pull/12899))
    - fix: Remove `auth`'s `expect()` usage ([#12895](https://github.com/vercel/turborepo/pull/12895))
    - fix: Remove `turbopath`'s `unwrap()` usage ([#12884](https://github.com/vercel/turborepo/pull/12884))
    - fix: Remove auth unwrap usage ([#12886](https://github.com/vercel/turborepo/pull/12886))
    - fix: Remove scm expect usage ([#12893](https://github.com/vercel/turborepo/pull/12893))
    - fix: Remove `turborepo-process`'s `expect()` usage ([#12891](https://github.com/vercel/turborepo/pull/12891))
    - fix: Remove microfrontends unwrap allow ([#12890](https://github.com/vercel/turborepo/pull/12890))
    - fix: Remove UI unwrap usage ([#12889](https://github.com/vercel/turborepo/pull/12889))
    - fix: Remove `turborepo-process`'s `unwrap()` usage ([#12888](https://github.com/vercel/turborepo/pull/12888))
    - fix: Remove `boundaries`'s `expect()` usage ([#12887](https://github.com/vercel/turborepo/pull/12887))
    - fix: Remove microfrontends expect usage ([#12885](https://github.com/vercel/turborepo/pull/12885))
    - fix: Remove UI `expect()` usage ([#12882](https://github.com/vercel/turborepo/pull/12882))
    - fix: Remove globwalk unwrap usage ([#12883](https://github.com/vercel/turborepo/pull/12883))
    - fix: Remove api client unwrap usage ([#12881](https://github.com/vercel/turborepo/pull/12881))
    - fix: Remove microfrontends proxy unwrap usage ([#12880](https://github.com/vercel/turborepo/pull/12880))
    - fix: Remove run summary expect usage ([#12879](https://github.com/vercel/turborepo/pull/12879))
    - fix: Remove task executor unwrap usage ([#12878](https://github.com/vercel/turborepo/pull/12878))
    - fix: Remove Vercel API mock unwrap usage ([#12877](https://github.com/vercel/turborepo/pull/12877))
    - fix: Remove turbo-trace expect allow ([#12876](https://github.com/vercel/turborepo/pull/12876))
    - fix: Remove signals panic callsites ([#12874](https://github.com/vercel/turborepo/pull/12874))
    - fix: Remove `turbopath`'s `expect()` callsites ([#12872](https://github.com/vercel/turborepo/pull/12872))
    - fix: Remove `globwalk`'s `expect()` callsites ([#12871](https://github.com/vercel/turborepo/pull/12871))
    - fix: Remove turbo-json panic lint allows ([#12869](https://github.com/vercel/turborepo/pull/12869))
    - fix: Remove telemetry panic callsites ([#12868](https://github.com/vercel/turborepo/pull/12868))
    - fix: Remove pidlock panic callsites ([#12867](https://github.com/vercel/turborepo/pull/12867))
    - fix: Avoid repository NAPI unwrap calls ([#12866](https://github.com/vercel/turborepo/pull/12866))
    - fix: Remove turborepo-shim expect callsites ([#12864](https://github.com/vercel/turborepo/pull/12864))
    - fix: Remove vt100 expect lint allow ([#12861](https://github.com/vercel/turborepo/pull/12861))
    - fix: Remove Vercel API mock expect usage ([#12862](https://github.com/vercel/turborepo/pull/12862))
    - fix: Remove turbo-trace unwrap callsite ([#12863](https://github.com/vercel/turborepo/pull/12863))
    - fix: Avoid task executor expect calls ([#12860](https://github.com/vercel/turborepo/pull/12860))
    - fix: Avoid API client expect calls ([#12858](https://github.com/vercel/turborepo/pull/12858))
    - fix: Remove microfrontends proxy expect lint allow ([#12859](https://github.com/vercel/turborepo/pull/12859))
    - fix: Remove frameworks panic lint allows ([#12857](https://github.com/vercel/turborepo/pull/12857))
    - fix: Remove task hash panic lints ([#12856](https://github.com/vercel/turborepo/pull/12856))
    - fix: Remove scope panic lint allows ([#12855](https://github.com/vercel/turborepo/pull/12855))
    - fix: Remove LSP expect callsites ([#12854](https://github.com/vercel/turborepo/pull/12854))
    - fix: Avoid globwatch expect calls ([#12853](https://github.com/vercel/turborepo/pull/12853))
    - fix: Remove napi panic lint allows ([#12852](https://github.com/vercel/turborepo/pull/12852))
    - fix: Remove turborepo-types panic lint allows ([#12849](https://github.com/vercel/turborepo/pull/12849))
    - fix: Remove json rewrite panic lint allow ([#12848](https://github.com/vercel/turborepo/pull/12848))
    - fix: Remove devtools WebSocket panics ([#12850](https://github.com/vercel/turborepo/pull/12850))
    - fix: Remove fixed map panic extraction calls ([#12847](https://github.com/vercel/turborepo/pull/12847))
    - fix: Remove fs panic extraction lints ([#12846](https://github.com/vercel/turborepo/pull/12846))
    - fix: Avoid graph walker `expect()` calls ([#12845](https://github.com/vercel/turborepo/pull/12845))
    - fix: Avoid graph utility node lookup panics ([#12844](https://github.com/vercel/turborepo/pull/12844))
    - fix: Store `PackageGraph` root invariants ([#12841](https://github.com/vercel/turborepo/pull/12841))
    - fix: Validate daemon discovery responses ([#12840](https://github.com/vercel/turborepo/pull/12840))
    - fix: Refactor execsync to execfilesync for Shell command built from environment values ([#12829](https://github.com/vercel/turborepo/pull/12829))
    - fix: Prevent Windows process drain hangs ([#12838](https://github.com/vercel/turborepo/pull/12838))
    - fix: Isolate Corepack state in integration tests ([#12831](https://github.com/vercel/turborepo/pull/12831))
    - fix: Return Berry lockfile errors instead of panicking ([#12828](https://github.com/vercel/turborepo/pull/12828))
    - fix: Create daemon dirs with private permissions ([#12827](https://github.com/vercel/turborepo/pull/12827))
    - fix: Preserve non-UTF-8 Git path boundaries ([#12826](https://github.com/vercel/turborepo/pull/12826))
    - fix: Avoid UTF-8 panics at boundaries ([#12823](https://github.com/vercel/turborepo/pull/12823))
    - fix: Preserve Bun alias child packages ([#12822](https://github.com/vercel/turborepo/pull/12822))
    - fix: Make structured log symlink defense race-safe ([#12821](https://github.com/vercel/turborepo/pull/12821))
    - fix: Prevent cache restore symlink race writes ([#12817](https://github.com/vercel/turborepo/pull/12817))
    - fix: Avoid path-racy chmod during directory restore ([#12815](https://github.com/vercel/turborepo/pull/12815))
    - fix: Prevent cache archive symlink reads ([#12813](https://github.com/vercel/turborepo/pull/12813))
    - fix: Wait for process trees before task completion ([#12809](https://github.com/vercel/turborepo/pull/12809))
    - fix: Prune package.json workspaces ([#12808](https://github.com/vercel/turborepo/pull/12808))
    - fix: Avoid project-local Yarn during detection ([#12801](https://github.com/vercel/turborepo/pull/12801))
    - fix: Harden VS Code extension command execution ([#12800](https://github.com/vercel/turborepo/pull/12800))
    - fix: Validate auth callback state ([#12802](https://github.com/vercel/turborepo/pull/12802))
    - fix: Restore docs mobile menu ([#12782](https://github.com/vercel/turborepo/pull/12782))
    - fix: Allow transit nodes in LSP diagnostics ([#12773](https://github.com/vercel/turborepo/pull/12773))
    - fix: Allow TURBO_EXTENDS in LSP diagnostics ([#12770](https://github.com/vercel/turborepo/pull/12770))
    - fix: Support shimmed VS Code LSP probes ([#12767](https://github.com/vercel/turborepo/pull/12767))
    - fix: Publish VS Code extension from release tag ([#12765](https://github.com/vercel/turborepo/pull/12765))
    - fix: Remove VS Code task key gradient ([#12761](https://github.com/vercel/turborepo/pull/12761))
    - fix: Support `turbo.jsonc` in VS Code extension ([#12760](https://github.com/vercel/turborepo/pull/12760))
    - fix: Reduce VS Code extension startup popups ([#12759](https://github.com/vercel/turborepo/pull/12759))
    - fix: Prefer installed Turbo for LSP ([#12755](https://github.com/vercel/turborepo/pull/12755))
    - fix: Preserve Bun nested dependencies during prune ([#12754](https://github.com/vercel/turborepo/pull/12754))
    - fix: Resolve relative `turbo path` in VS Code extension ([#12753](https://github.com/vercel/turborepo/pull/12753))
    - fix: Handle JSON decoration visitor depth ([#12752](https://github.com/vercel/turborepo/pull/12752))
    - fix: Include file URIs in LSP lifecycle logs ([#12751](https://github.com/vercel/turborepo/pull/12751))
    - fix: Start daemon for VSCode Extension from the extension itself ([#12749](https://github.com/vercel/turborepo/pull/12749))
    - fix: Enforce cache filesystem boundaries ([#12743](https://github.com/vercel/turborepo/pull/12743))
    - fix: Hardening for daemon IPC endpoints ([#12742](https://github.com/vercel/turborepo/pull/12742))
    - fix: Keep workspace config discovery inside root ([#12741](https://github.com/vercel/turborepo/pull/12741))
    - fix: Restrict Vercel token reuse to trusted API origins ([#12740](https://github.com/vercel/turborepo/pull/12740))
    - fix: Handle clipboard exec errors ([#12739](https://github.com/vercel/turborepo/pull/12739))
    - fix: Authenticate local devtools WebSocket ([#12738](https://github.com/vercel/turborepo/pull/12738))
    - fix: Reject OTel endpoints with userinfo ([#12737](https://github.com/vercel/turborepo/pull/12737))
    - fix: Use random temp path for repo downloads ([#12736](https://github.com/vercel/turborepo/pull/12736))
    - fix: Resolve TypeScript `.js` extension imports to `.ts` files in boundaries ([#12644](https://github.com/vercel/turborepo/pull/12644))
    - fix: Validate proxy Host headers ([#12731](https://github.com/vercel/turborepo/pull/12731))
    - fix: Preserve FSEvents mount points for device-relative paths ([#12729](https://github.com/vercel/turborepo/pull/12729))
    - fix: Filter microfrontend proxy environments ([#12732](https://github.com/vercel/turborepo/pull/12732))
    - fix: Redact task hash env debug logs ([#12733](https://github.com/vercel/turborepo/pull/12733))
    - fix: Validate microfrontend proxy Host header ([#12730](https://github.com/vercel/turborepo/pull/12730))
    - fix: Retry HTTP status failures ([#12728](https://github.com/vercel/turborepo/pull/12728))
    - fix: Prevent OTEL token injection to spoofed origins ([#12727](https://github.com/vercel/turborepo/pull/12727))
    - fix: Escape graph HTML payloads ([#12726](https://github.com/vercel/turborepo/pull/12726))
    - fix: Avoid raw create-turbo example telemetry ([#12725](https://github.com/vercel/turborepo/pull/12725))
    - fix: Respect SCM env vars in `turbo query affected` ([#12722](https://github.com/vercel/turborepo/pull/12722))
    - fix: Preserve lockfiles during dry-run conversion ([#12717](https://github.com/vercel/turborepo/pull/12717))
    - fix: Harden docs security endpoints ([#12713](https://github.com/vercel/turborepo/pull/12713))
    - fix: Scope release npm publishing credentials ([#12710](https://github.com/vercel/turborepo/pull/12710))
    - fix: Harden OG image signatures ([#12709](https://github.com/vercel/turborepo/pull/12709))
    - fix: Scope repo index prefixes to Git root ([#12706](https://github.com/vercel/turborepo/pull/12706))
    - fix: Remove Unix parent death watchdogs ([#12699](https://github.com/vercel/turborepo/pull/12699))
    - fix: Reduce parent-death watchdog CPU usage ([#12697](https://github.com/vercel/turborepo/pull/12697))
    - fix: Keep tbx shell connections stable ([#12692](https://github.com/vercel/turborepo/pull/12692))
    - fix: Create prune docker bin stubs ([#12688](https://github.com/vercel/turborepo/pull/12688))
    - fix: Preserve Bun prune lockfile validity ([#12686](https://github.com/vercel/turborepo/pull/12686))
    - fix: Resolve Yarn catalog affected packages ([#12684](https://github.com/vercel/turborepo/pull/12684))
    - fix: Preserve concrete dependency precedence ([#12682](https://github.com/vercel/turborepo/pull/12682))
    - fix: Avoid rerunning non-cacheable watch dependencies ([#12678](https://github.com/vercel/turborepo/pull/12678))
    - fix: Support pnpm 11 flat patch lockfiles ([#12676](https://github.com/vercel/turborepo/pull/12676))
    - fix: Improve tbx sandbox startup defaults ([#12675](https://github.com/vercel/turborepo/pull/12675))
    - fix: Improve tbx sandbox startup ([#12674](https://github.com/vercel/turborepo/pull/12674))
    - fix: Install dotfiles during `tbx base refresh` ([#12673](https://github.com/vercel/turborepo/pull/12673))
    - fix: Allow tbx sandboxes to use stale bases ([#12672](https://github.com/vercel/turborepo/pull/12672))
    - fix: Install turbo globally in tbx base ([#12670](https://github.com/vercel/turborepo/pull/12670))
    - fix: Allow npm registry in tbx sandboxes ([#12669](https://github.com/vercel/turborepo/pull/12669))
    - fix: Prevent prune from overmatching gitignore entries ([#12662](https://github.com/vercel/turborepo/pull/12662))
    - fix: Recover Vercel auth tokens across login flows ([#12631](https://github.com/vercel/turborepo/pull/12631))
    - fix: Preserve legacy Vercel auth compatibility ([#12629](https://github.com/vercel/turborepo/pull/12629))
    - fix: Preserve PTY graceful shutdown semantics ([#12624](https://github.com/vercel/turborepo/pull/12624))
    - fix: Keep Node wrapper alive during graceful shutdown ([#12622](https://github.com/vercel/turborepo/pull/12622))
    - fix: Preserve graceful shutdown exit code ([#12620](https://github.com/vercel/turborepo/pull/12620))
    - fix: Support pnpm v11 multi-document lockfiles ([#12616](https://github.com/vercel/turborepo/pull/12616))
    - fix: Ignore SIGINT in shim after spawning local `turbo` ([#12612](https://github.com/vercel/turborepo/pull/12612))
    - fix: Preserve graceful shutdown output ([#12607](https://github.com/vercel/turborepo/pull/12607))
    - fix: Support two-dot git ranges in filter selectors ([#12599](https://github.com/vercel/turborepo/pull/12599))
    - fix: Align Markdown docs routing with docs/md endpoints ([#12596](https://github.com/vercel/turborepo/pull/12596))
    - fix: Load custom CA certificates in fast webpki-only HTTP client ([#12591](https://github.com/vercel/turborepo/pull/12591))
    - fix: Add missing `@types/node` to `with-svelte` example apps ([#12585](https://github.com/vercel/turborepo/pull/12585))
    - fix: Surface actionable message when remote cache is requested but not linked ([#12584](https://github.com/vercel/turborepo/pull/12584))
    - fix: Mention `turbo.json` in concurrency error message ([#12582](https://github.com/vercel/turborepo/pull/12582))
    - fix: Suppress telemetry alert when running on Vercel ([#12576](https://github.com/vercel/turborepo/pull/12576))
    - fix: Normalize CRLF line endings in file hashing to match git ([#12572](https://github.com/vercel/turborepo/pull/12572))
    - fix: Respect dirty .gitignore patterns during task input hashing ([#12557](https://github.com/vercel/turborepo/pull/12557))
    - fix: Bun workspace lockfile pruning producing invalid output ([#12548](https://github.com/vercel/turborepo/pull/12548))
    - fix: Retain microfrontend proxy tasks when using `filterUsingTasks` ([#12545](https://github.com/vercel/turborepo/pull/12545))
    - fix: Deep-merge nested OTEL config across priority sources ([#12513](https://github.com/vercel/turborepo/pull/12513))
    - fix: Preserve prerelease info in schema URL during codemod migration ([#12542](https://github.com/vercel/turborepo/pull/12542))
    - fix: Validate engine concurrency after task-level filtering ([#12540](https://github.com/vercel/turborepo/pull/12540))
    - fix: Only enforce signature key length for keys that exist ([#12538](https://github.com/vercel/turborepo/pull/12538))
    - fix: Prevent `filterUsingTasks` `--filter` from pulling dependents into Task Graph ([#12535](https://github.com/vercel/turborepo/pull/12535))
    - fix: Support `turbo.jsonc` in codemod transforms ([#12532](https://github.com/vercel/turborepo/pull/12532))
    - fix: Always update $schema URL to versioned format during migration ([#12529](https://github.com/vercel/turborepo/pull/12529))
    - fix: Preserve per-workspace lockfiles during pnpm pruning ([#12519](https://github.com/vercel/turborepo/pull/12519))
    - fix: Preserve shallow install strategy during npm lockfile pruning ([#12520](https://github.com/vercel/turborepo/pull/12520))
    - fix: Include transitive dependencies in engine graph pruning for affected paths using Task Graph ([#12516](https://github.com/vercel/turborepo/pull/12516))
    - fix: Update AI-generated response disclaimer to include human attribution ([#12517](https://github.com/vercel/turborepo/pull/12517))
    - fix: Backfill missing pnpm workspace importer entries during prune ([#12514](https://github.com/vercel/turborepo/pull/12514))
    - fix: Treat * as wildcard in preflight Access-Control-Allow-Headers ([#12503](https://github.com/vercel/turborepo/pull/12503))
    - fix: Unblock `watch` loop so interruptible persistent tasks restart on file changes ([#12509](https://github.com/vercel/turborepo/pull/12509))
    - fix: Resolve correct nested bun lockfile versions during prune ([#12506](https://github.com/vercel/turborepo/pull/12506))
    - fix: Add retry logic to example update workflow push step ([#12499](https://github.com/vercel/turborepo/pull/12499))
    - fix: Use previous minor/major tag for release notes on minor/major releases ([#12495](https://github.com/vercel/turborepo/pull/12495))
    - fix: Avoid panic for unanchorable/non-UTF8 git paths ([#11106](https://github.com/vercel/turborepo/pull/11106))

  </Accordion>

  <Accordion title="Docs (16)">

    - docs: Fix stderr debugging guidance ([#13122](https://github.com/vercel/turborepo/pull/13122))
    - docs: Remove ESM warning from gen page ([#13039](https://github.com/vercel/turborepo/pull/13039))
    - docs: Exclude Next dev output from cache examples ([#13019](https://github.com/vercel/turborepo/pull/13019))
    - docs: Correct attribute presence claims in turborepo-otel ([#12932](https://github.com/vercel/turborepo/pull/12932))
    - docs: Add `with-vite-module-federation` example ([#12794](https://github.com/vercel/turborepo/pull/12794))
    - docs: Add pnpm workspace flag (-w) to Oxc setup docs ([#12655](https://github.com/vercel/turborepo/pull/12655))
    - docs: Clarify root task guidance ([#12683](https://github.com/vercel/turborepo/pull/12683))
    - docs: Fix link to passthrough variables source code ([#12643](https://github.com/vercel/turborepo/pull/12643))
    - docs: Clarify package hash file inputs ([#12671](https://github.com/vercel/turborepo/pull/12671))
    - docs: Fix TURBO_PLATFORM_ENV_DISABLED value in docs (true, not false) ([#12633](https://github.com/vercel/turborepo/pull/12633))
    - docs: Remove pre-release badges ([#12592](https://github.com/vercel/turborepo/pull/12592))
    - docs: Add Bun equivalent for updating dependencies ([#12580](https://github.com/vercel/turborepo/pull/12580))
    - docs: Send siteId as label on feedback GitHub issues ([#12527](https://github.com/vercel/turborepo/pull/12527))
    - docs: Document `turbo.*` generator variables ([#12511](https://github.com/vercel/turborepo/pull/12511))
    - docs: Add documentation for cacheMaxAge and cacheMaxSize options ([#12500](https://github.com/vercel/turborepo/pull/12500))
    - docs: Release post for 2.9 ([#12441](https://github.com/vercel/turborepo/pull/12441))

  </Accordion>

  <Accordion title="Examples (1)">

    - examples: Add Ultracite example ([#12615](https://github.com/vercel/turborepo/pull/12615))

  </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew) and [Tom](https://github.com/tknickman).

We also thank everyone who contributed to this release of Turborepo: @adityasingh2400, @AndyBitz, @Balance8, @biru-codeastromer, @bitttttten, @bjormgyg, @christopherkindl, @dancrumb, @DependerKumarSoni, @eastgold15, @gioboa, @gwagjiug, @hack-313-ip, @haydenbleasel, @JRoy, @kitten, @marc-vercel, @markandrus, @maschwenk, @mattjoll, @mehulkar, @molebox, @mvanhorn, @Nsttt, @ognevny, @saiteja-madha, @sleitor, and @Wartijn.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](https://turborepo.dev/docs/community).

---

### Apps Docs Content Blog 2 11 (`apps/docs/content/blog/2-11.mdx`)

---
title: Turborepo 2.11
date: 2026/09/18
description: "Native support for Rust, Python, and Go, more package managers, and production pruning"
product: turborepo
type: overview
summary: Release notes for Turborepo 2.11 featuring experimental native support for Rust, Python, and Go, nub and aube support, devEngines.packageManager support, and production pruning.
tag: "web development"
---

import { Authors } from "@/components/blog/authors";
import { Accordion, Accordions } from "@/components/geistdocs/accordion";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Date } from "@/components/blog/date";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import MilestonesImageDark from "../../public/images/blog/turbo-2-11/milestones-dark.png";
import MilestonesImageLight from "../../public/images/blog/turbo-2-11/milestones-light.png";

# Turborepo 2.11

<Date>Friday, September 18th, 2026</Date>

<Authors authors={["anthonyshew"]} />

Turborepo 2.11 adds native support for more languages, faster startup, improved JavaScript ecosystem compatibility, and more control over your deployments:

- [**Native support for Rust, Python, and Go (Experimental)**](#native-support-for-rust-python-and-go-experimental): One Task Graph, every language toolchain
- [**Faster Time to First Task**](#up-to-4x-faster-startup): Up to 4x faster startup than Turborepo 2.9
- [**`devEngines.packageManager` support**](#devenginespackagemanager-support): Declare your package manager with modern Node.js convention
- [**nub and aube support**](#nub-and-aube-support): New JavaScript package managers
- [**Production pruning**](#production-pruning): Exclude development-only workspace packages from `turbo prune` outputs

In addition to these new features, this is the first release of Turborepo with zero known bugs.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "Turborepo reaches 20 million weekly downloads with zero open GitHub issues",
    src: MilestonesImageLight,
    props: {
      width: 2000,
      height: 1125,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "Turborepo reaches 20 million weekly downloads with zero open GitHub issues",
    src: MilestonesImageDark,
    props: {
      width: 2000,
      height: 1125,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

---

Upgrade or get started today.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Use the automated upgrade CLI
pnpm dlx @turbo/codemod migrate

# Start a new repository
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Use the automated upgrade CLI
yarn dlx @turbo/codemod migrate

# Start a new repository
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Use the automated upgrade CLI
npx @turbo/codemod migrate

# Start a new repository
npx create-turbo@latest
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Use the automated upgrade CLI
bunx @turbo/codemod migrate

# Start a new repository
bunx create-turbo@latest
```

</Tab>

<Tab value="nub">

```bash title="Terminal"
# Use the automated upgrade CLI
nubx @turbo/codemod migrate

# Start a new repository
nubx create-turbo@latest
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
# Use the automated upgrade CLI
aubx @turbo/codemod migrate

# Start a new repository
aubx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

---

## Native support for Rust, Python, and Go (Experimental)

Turborepo can now discover packages and dependency relationships from Cargo, uv, and `go.work` workspaces, putting each language toolchain into the same [Task Graph](/docs/core-concepts/package-and-task-graph#task-graph). This brings Turborepo's [task scheduling](/docs/crafting-your-repository/configuring-tasks), [filtering](/docs/crafting-your-repository/running-tasks#using-filters), [affectedness calculations](/docs/crafting-your-repository/constructing-ci#running-only-affected-tasks), [Watch Mode](/docs/crafting-your-repository/developing-applications#watch-mode), and [pruning](/docs/reference/prune) to your Rust, Python, and Go projects. You get one CLI, `turbo`, to handle all the tasks in your monorepo.

You can use any of these languages on its own or combine JavaScript, Rust, Python, and Go into one unified execution graph. Turborepo runs tasks in parallel across languages while respecting their dependencies.
| Turborepo command | Task execution |
| ---------------------------------------- | ---------------------------------------------------------------- |
| `turbo run build` | `tsc build` + `cargo build` + `uv build` + `go build ./...` |
| `turbo run test` | `vitest run` + `cargo test` + `uv run pytest` + `go test ./...` |
| `turbo run check` | `tsc` + `cargo check` + `uv run mypy` |
| `turbo run lint` | `eslint` + `cargo clippy` + `uv run ruff check` + `go vet ./...` |
| `turbo run format` | `prettier` + `cargo fmt` + `uv run ruff format` + `go fmt ./...` |
| `turbo run build test check lint format` | All of the commands above run in parallel |

You can also create cross-toolchain dependencies in `turbo.json`. For example, tests for a Python API server wait for a Rust core package to be built:

```json title="turbo.json"
{
  "futureFlags": {
    "experimentalCargoWorkspaces": true,
    "experimentalPythonWorkspaces": true
  },
  "tasks": {
    "my-dango-api#test": {
      "dependsOn": ["rust-api-core#build"]
    }
  }
}
```

Once the Rust dependency is done building, the Django server will run its Python tests.

Native Rust, Python, and Go support is [Experimental](/docs/support-policy#experimental) and subject to change. To learn more, visit the [Rust](/docs/guides/tools/rust), [Python](/docs/guides/tools/python), and [Go](/docs/guides/tools/go) guides.

Share your feedback in [GitHub Discussions](https://github.com/vercel/turborepo/discussions/categories/rfc).

## Up to 4x faster startup

Time to First Task is the time between when you invoke `turbo run` and when your first task starts running. In Turborepo 2.9, we [improved Time To First Task by up to 96%](/blog/2-9#time-to-first-task-improved-up-to-96).

In 2.11, Time to First Task is up to 4x faster than 2.9.

<div
  className="not-prose my-8 rounded-lg border border-[var(--ds-gray-400)] overflow-hidden"
  role="figure"
  aria-label="Time to First Task comparison across Turborepo versions"
>
  <div className="py-0 pr-3 pl-4 rounded-t-md border-b border-[var(--ds-gray-400)] h-10 flex items-center bg-[var(--ds-background-200)]">
    <span className="text-sm font-medium text-[var(--ds-gray-1000)]">
      Time to First Task
    </span>
  </div>
  <div className="p-4 flex flex-col gap-4 bg-[var(--ds-background-100)]">
    <div>
      <div className="flex justify-between items-baseline mb-2">
        <span className="text-sm text-[var(--ds-gray-1000)]">
          Vercel's backend monorepo (1037 packages)
        </span>
        <span
          className="text-xs font-semibold"
          style={{ color: "var(--ds-blue-700)" }}
        >
          45% faster
        </span>
      </div>
      <div
        className="flex flex-col gap-1.5"
        role="group"
        aria-label="Vercel's backend monorepo (1037 packages)"
      >
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            2.11
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={5}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="2.11: 394 milliseconds"
          >
            <div
              className="w-[5%] rounded h-full"
              style={{ backgroundColor: "var(--ds-blue-700)" }}
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                394ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            394ms
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            2.9
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={9}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="2.9: 716 milliseconds"
          >
            <div
              className="w-[9%] bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                716ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            716ms
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            {"<2.9"}
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={100}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="Before 2.9: 8.1 seconds"
          >
            <div
              className="w-full bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                8.1s
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            8.1s
          </span>
        </div>
      </div>
    </div>
    <div className="border-t border-[var(--ds-gray-400)] pt-4">
      <div className="flex justify-between items-baseline mb-2">
        <span className="text-sm text-[var(--ds-gray-1000)]">
          Vercel's frontend monorepo (132 packages)
        </span>
        <span
          className="text-xs font-semibold"
          style={{ color: "var(--ds-blue-700)" }}
        >
          43% faster
        </span>
      </div>
      <div
        className="flex flex-col gap-1.5"
        role="group"
        aria-label="Vercel's frontend monorepo (132 packages)"
      >
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            2.11
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={11}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="2.11: 206 milliseconds"
          >
            <div
              className="w-[11%] rounded h-full"
              style={{ backgroundColor: "var(--ds-blue-700)" }}
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                206ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            206ms
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            2.9
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={19}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="2.9: 361 milliseconds"
          >
            <div
              className="w-[19%] bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                361ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            361ms
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            {"<2.9"}
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={100}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="Before 2.9: 1.875 seconds"
          >
            <div
              className="w-full bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                1.9s
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            1.9s
          </span>
        </div>
      </div>
    </div>
    <div className="border-t border-[var(--ds-gray-400)] pt-4">
      <div className="flex justify-between items-baseline mb-2">
        <span className="text-sm text-[var(--ds-gray-1000)]">
          `create-turbo` (6 packages)
        </span>
        <span
          className="text-xs font-semibold"
          style={{ color: "var(--ds-blue-700)" }}
        >
          74% faster
        </span>
      </div>
      <div
        className="flex flex-col gap-1.5"
        role="group"
        aria-label="create-turbo (6 packages)"
      >
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            2.11
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={5}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="2.11: 34 milliseconds"
          >
            <div
              className="w-[5%] rounded h-full"
              style={{ backgroundColor: "var(--ds-blue-700)" }}
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                34ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            34ms
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            2.9
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={20}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="2.9: 132 milliseconds"
          >
            <div
              className="w-[20%] bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                132ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            132ms
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            {"<2.9"}
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={100}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="Before 2.9: 676 milliseconds"
          >
            <div
              className="w-full bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                676ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            676ms
          </span>
        </div>
      </div>
    </div>
    <span className="block text-xs text-[var(--ds-gray-900)] mt-3">
      Benchmarked on Apple M4 Max, 36 GB RAM, macOS 15.7.1
    </span>
  </div>
</div>

Stacked on top of the Turborepo 2.9 gains, the largest repository we benchmarked now reaches its first task over 20x faster than it did before 2.9. As with 2.9, the improvement you see will depend on the size and complexity of your repository.

## `devEngines.packageManager` support

Starting with this release, Turborepo respects the `devEngines.packageManager` field in your root `package.json`.

For JavaScript toolchains, the `devEngines.packageManager` field is the modern way to declare the package manager expected by your repository:

```json title="package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "pnpm",
      "version": "12.0.0"
    }
  }
}
```

In a future major version of Turborepo, the top-level `packageManager` field will stop being supported to align with the current and future direction of the JavaScript ecosystem. We encourage migrating your repository by removing the top-level `packageManager` field and replacing it with `devEngines.packageManager`.

[Read the package manager documentation](/docs/support-policy#package-managers) to learn more.

## nub and aube support

Turborepo now recognizes [nub](https://nubjs.com/) and [aube](https://aube.jdx.dev) as JavaScript package managers.

Both of these package managers focus on improving security and speed for dependency installation in your repo. They use your existing npm, pnpm, Yarn, or Bun lockfile, making for easy migration.

Declare nub in your root `package.json`:

<Tabs items={["nub", "aube"]}>
<Tab value="nub">

```json title="package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "nub",
      "version": "0.8.3"
    }
  }
}
```

</Tab>

<Tab value="aube">

```json title="package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "aube",
      "version": "2.2.9"
    }
  }
}
```

</Tab>
</Tabs>

To try nub or aube, create a monorepo with `create-turbo`:

```sh title="Terminal"
# nub
nubx create-turbo -m nub

# aube
aubx create-turbo -m aube
```

## Production pruning

When preparing a deployment from a monorepo, it can be tricky to right-size your Docker images. Turborepo's `prune` command solves this problem, trimming your monorepo to only the code that is needed for the application to deploy and run successfully.

Until today, Turborepo would include workspace packages referenced through both dependencies and development dependencies while calculating the pruning dependency closure. While this is a safe default, removing development-only workspace packages from the production image can optimize further.

In this release, we're giving you control to exclude workspace packages that are only reachable through `devDependencies` with the new `--production` flag for `turbo prune`:

```bash title="Terminal"
turbo prune web --production
```

This works across all natively supported languages, including the Experimental ones introduced in this release. [Visit the `turbo prune` documentation](/docs/reference/prune#--production) to learn more.

## All changes

<Accordions>

  <Accordion title="Features (91)">

    - feat: Infer Cargo and uv affectedness from static package inputs ([#14090](https://github.com/vercel/turborepo/pull/14090))
    - feat: Derive short names for Go workspace packages ([#14086](https://github.com/vercel/turborepo/pull/14086))
    - feat: Expose static repository discovery and safe affected candidates ([#14085](https://github.com/vercel/turborepo/pull/14085))
    - feat: Make package queries and pruning task-aware ([#14081](https://github.com/vercel/turborepo/pull/14081))
    - feat: Expose compact task planning through turbo query ([#14068](https://github.com/vercel/turborepo/pull/14068))
    - feat: Add NEXT_DEPLOYMENT_ID to Next.js framework inference ([#14065](https://github.com/vercel/turborepo/pull/14065))
    - feat: Add Remix inference and `NUXT_ENV_*` wildcard ([#14060](https://github.com/vercel/turborepo/pull/14060))
    - feat: Add Go-aware prune planning ([#13961](https://github.com/vercel/turborepo/pull/13961))
    - feat: Add Go change observations ([#13959](https://github.com/vercel/turborepo/pull/13959))
    - feat: Fingerprint Go toolchain environment ([#13958](https://github.com/vercel/turborepo/pull/13958))
    - feat: Add Go external resolution fingerprints ([#13957](https://github.com/vercel/turborepo/pull/13957))
    - feat: Add Go task input and output contracts ([#13955](https://github.com/vercel/turborepo/pull/13955))
    - feat: Add native Go task tables ([#13954](https://github.com/vercel/turborepo/pull/13954))
    - feat: Add experimental Go workspace graph foundation ([#13953](https://github.com/vercel/turborepo/pull/13953))
    - feat: Make daemon discovery toolchain generic ([#13952](https://github.com/vercel/turborepo/pull/13952))
    - feat: Add skipPackageGraph option to @turbo/repository Workspace.find ([#13929](https://github.com/vercel/turborepo/pull/13929))
    - feat: Link workspaces to pull requests ([#13878](https://github.com/vercel/turborepo/pull/13878))
    - feat: Improve Factory workspace statuses ([#13869](https://github.com/vercel/turborepo/pull/13869))
    - feat: Expand repository lockfile package metadata ([#13862](https://github.com/vercel/turborepo/pull/13862))
    - feat(repository): Expose flat lockfile package list for metrics ([#13859](https://github.com/vercel/turborepo/pull/13859))
    - feat: Support Cargo root packages ([#13856](https://github.com/vercel/turborepo/pull/13856))
    - feat: Support Python virtual environments ([#13849](https://github.com/vercel/turborepo/pull/13849))
    - feat: Use uv workspace metadata ([#13848](https://github.com/vercel/turborepo/pull/13848))
    - feat: Require high confidence for issue fixes ([#13842](https://github.com/vercel/turborepo/pull/13842))
    - feat: Standardize Factory meta titles to Turborepo suffix ([#13819](https://github.com/vercel/turborepo/pull/13819))
    - feat: Stream Factory sandbox as terminal ([#13807](https://github.com/vercel/turborepo/pull/13807))
    - feat: Add durable Factory workspaces ([#13804](https://github.com/vercel/turborepo/pull/13804))
    - feat: Add factory navigation ([#13802](https://github.com/vercel/turborepo/pull/13802))
    - feat: Start ad-hoc factory work from the operator page ([#13798](https://github.com/vercel/turborepo/pull/13798))
    - feat: Rebuild the factory image on every merge to main ([#13781](https://github.com/vercel/turborepo/pull/13781))
    - feat: Add SSH command affordance for factory sandboxes ([#13779](https://github.com/vercel/turborepo/pull/13779))
    - feat: Redesign factory control plane ([#13775](https://github.com/vercel/turborepo/pull/13775))
    - feat: Add security.txt endpoint ([#13778](https://github.com/vercel/turborepo/pull/13778))
    - feat: Refresh documentation social cards ([#13764](https://github.com/vercel/turborepo/pull/13764))
    - feat: Expand performance agent toolbox ([#13761](https://github.com/vercel/turborepo/pull/13761))
    - feat: Cache native uv tool tasks ([#13748](https://github.com/vercel/turborepo/pull/13748))
    - feat: Support cross-toolchain repository affectedness ([#13737](https://github.com/vercel/turborepo/pull/13737))
    - feat: Add daily performance agent ([#13729](https://github.com/vercel/turborepo/pull/13729))
    - feat: Notify Slack when agents open PRs ([#13722](https://github.com/vercel/turborepo/pull/13722))
    - feat: Add pytest task discovery ([#13720](https://github.com/vercel/turborepo/pull/13720))
    - feat: Rotate Eve example maintenance daily ([#13715](https://github.com/vercel/turborepo/pull/13715))
    - feat: Add Eve operator dashboard ([#13710](https://github.com/vercel/turborepo/pull/13710))
    - feat: Support nub.lock files ([#13699](https://github.com/vercel/turborepo/pull/13699))
    - feat: Hash Python quality task inputs ([#13674](https://github.com/vercel/turborepo/pull/13674))
    - feat: Synthesize Python quality tasks ([#13672](https://github.com/vercel/turborepo/pull/13672))
    - feat: Resolve Python quality plans ([#13670](https://github.com/vercel/turborepo/pull/13670))
    - feat: Parse Python quality tool declarations ([#13669](https://github.com/vercel/turborepo/pull/13669))
    - feat: Compose aggregate native task dependencies ([#13667](https://github.com/vercel/turborepo/pull/13667))
    - feat: Prune uv workspaces ([#13613](https://github.com/vercel/turborepo/pull/13613))
    - feat: Watch uv workspace changes ([#13612](https://github.com/vercel/turborepo/pull/13612))
    - feat: Hash uv lockfile closures ([#13611](https://github.com/vercel/turborepo/pull/13611))
    - feat: Run native uv tasks ([#13610](https://github.com/vercel/turborepo/pull/13610))
    - feat: Discover uv workspaces ([#13609](https://github.com/vercel/turborepo/pull/13609))
    - feat: Add native Cargo format task ([#13606](https://github.com/vercel/turborepo/pull/13606))
    - feat: Resolve GitHub Actions remote base refs behind future flag ([#10732](https://github.com/vercel/turborepo/pull/10732))
    - feat: Support Android (Termux) ([#12735](https://github.com/vercel/turborepo/pull/12735))
    - feat: Select runnable task entrypoints ([#13452](https://github.com/vercel/turborepo/pull/13452))
    - feat: Add crate-scoped Cargo verification tasks ([#13398](https://github.com/vercel/turborepo/pull/13398))
    - feat: Infer Cargo workspace tasks ([#13380](https://github.com/vercel/turborepo/pull/13380))
    - feat: Support Cargo-only repos ([#13378](https://github.com/vercel/turborepo/pull/13378))
    - feat: Report incremental cache reuse in the run summary ([#13327](https://github.com/vercel/turborepo/pull/13327))
    - feat: Engage the Remote Cache and sccache compile cache for Rust CI ([#13292](https://github.com/vercel/turborepo/pull/13292))
    - feat: Run the Rust workspace tests through nextest via command override ([#13316](https://github.com/vercel/turborepo/pull/13316))
    - feat: Resolve and execute task command overrides ([#13315](https://github.com/vercel/turborepo/pull/13315))
    - feat: Parse and validate the task command field ([#13313](https://github.com/vercel/turborepo/pull/13313))
    - feat: Require a user-declared name for the Cargo workspace package ([#13312](https://github.com/vercel/turborepo/pull/13312))
    - feat: Embed sccache so the Cargo compile cache needs no installation ([#13293](https://github.com/vercel/turborepo/pull/13293))
    - feat: Serve the Remote Cache as an sccache backend for Cargo tasks ([#13288](https://github.com/vercel/turborepo/pull/13288))
    - feat: Make turbo prune Cargo-aware ([#13281](https://github.com/vercel/turborepo/pull/13281))
    - feat: Make turbo watch Cargo-aware ([#13280](https://github.com/vercel/turborepo/pull/13280))
    - feat: Hash Cargo external dependencies per-crate ([#13267](https://github.com/vercel/turborepo/pull/13267))
    - feat: Derive input and output globs for Cargo tasks ([#13263](https://github.com/vercel/turborepo/pull/13263))
    - feat: Expose resolved experimentalCI task configuration in `turbo query` ([#13264](https://github.com/vercel/turborepo/pull/13264))
    - feat: Execute Cargo crate tasks via cargo ([#13261](https://github.com/vercel/turborepo/pull/13261))
    - feat: Discover Cargo crates as packages ([#13248](https://github.com/vercel/turborepo/pull/13248))
    - feat: Introduce toolchain provider abstraction ([#13235](https://github.com/vercel/turborepo/pull/13235))
    - feat: Add futureFlags.experimentalCargoWorkspaces flag (no-op) ([#13227](https://github.com/vercel/turborepo/pull/13227))
    - feat: Automatically copy TUI selection to clipboard on mouse release ([#13208](https://github.com/vercel/turborepo/pull/13208))
    - feat: Select tasks by clicking rows in the TUI task list ([#13206](https://github.com/vercel/turborepo/pull/13206))
    - feat: Toggle between the TUI and streamed logs ([#13203](https://github.com/vercel/turborepo/pull/13203))
    - feat: Accept Bun lockfile version 2 ([#13119](https://github.com/vercel/turborepo/pull/13119))
    - feat: Add --production flag to turbo prune ([#13190](https://github.com/vercel/turborepo/pull/13190))
    - feat: Add aube package manager support ([#13183](https://github.com/vercel/turborepo/pull/13183))
    - feat: Add nub to create-turbo options ([#13173](https://github.com/vercel/turborepo/pull/13173))
    - feat: Add nub package manager support to JavaScript packages ([#13169](https://github.com/vercel/turborepo/pull/13169))
    - feat: Recognize nub as a package manager ([#13120](https://github.com/vercel/turborepo/pull/13120))
    - feat: Update workspace package manager declarations ([#13154](https://github.com/vercel/turborepo/pull/13154))
    - feat: Update add package manager codemod ([#13151](https://github.com/vercel/turborepo/pull/13151))
    - feat: Support devEngines packageManager in workspaces ([#13150](https://github.com/vercel/turborepo/pull/13150))
    - feat: Support `devEngines.packageManager` ([#12388](https://github.com/vercel/turborepo/pull/12388))
    - feat: Migrate TUI virtual terminals from vt100 to Ghostty ([#13135](https://github.com/vercel/turborepo/pull/13135))

  </Accordion>

  <Accordion title="Performance (109)">

    - perf: Cache Windows archive anchor ([#14093](https://github.com/vercel/turborepo/pull/14093))
    - perf: Avoid cloning package list in turbo ls ([#14036](https://github.com/vercel/turborepo/pull/14036))
    - perf: Reuse the package graph across partial watch reruns ([#14028](https://github.com/vercel/turborepo/pull/14028))
    - perf: Share one repo index across same-package spec rehashes in watch mode ([#14027](https://github.com/vercel/turborepo/pull/14027))
    - perf: Read child output in bounded chunks instead of per-line ([#14026](https://github.com/vercel/turborepo/pull/14026))
    - perf: Replace repeated deferred-hash scans with dependency-driven readiness ([#14025](https://github.com/vercel/turborepo/pull/14025))
    - perf: Coalesce package rediscovery while a scan is already running ([#14023](https://github.com/vercel/turborepo/pull/14023))
    - perf: Bound TUI raw-output retention independently of scrollback ([#14024](https://github.com/vercel/turborepo/pull/14024))
    - perf: Index package directories for changed-file ownership lookups ([#14022](https://github.com/vercel/turborepo/pull/14022))
    - perf: Move synchronous cache archiving off Tokio runtime workers ([#14013](https://github.com/vercel/turborepo/pull/14013))
    - perf: Skip speculative content hashing for size-changed unnormalized tracked files ([#14021](https://github.com/vercel/turborepo/pull/14021))
    - perf: Keep package bundling inside a cacheable build boundary ([#14020](https://github.com/vercel/turborepo/pull/14020))
    - perf: Run the docs MDX generator once per quality task graph ([#14019](https://github.com/vercel/turborepo/pull/14019))
    - perf: Parse the lockfile once when opening a native Workspace with its graph ([#14017](https://github.com/vercel/turborepo/pull/14017))
    - perf: Share source text across boundaries diagnostics instead of copying it per error ([#14014](https://github.com/vercel/turborepo/pull/14014))
    - perf: Avoid serializing ASTs for path-only file dependency queries ([#14016](https://github.com/vercel/turborepo/pull/14016))
    - perf: Make VS Code binary discovery and LSP probes nonblocking ([#14015](https://github.com/vercel/turborepo/pull/14015))
    - perf: Build cache archives once for local and remote writes ([#14012](https://github.com/vercel/turborepo/pull/14012))
    - perf: Bound remote-cache transfer memory instead of retaining whole artifacts ([#14011](https://github.com/vercel/turborepo/pull/14011))
    - perf: Reuse archive anchor during cache creation ([#14010](https://github.com/vercel/turborepo/pull/14010))
    - perf: Batch boundaries progress updates ([#14009](https://github.com/vercel/turborepo/pull/14009))
    - perf: Deduplicate recursive glob prefixes before walking ([#14004](https://github.com/vercel/turborepo/pull/14004))
    - perf: Cache LSP task index and dedupe identities in constant time ([#14008](https://github.com/vercel/turborepo/pull/14008))
    - perf: Borrow workspace entries during dependency lookup ([#14002](https://github.com/vercel/turborepo/pull/14002))
    - perf: Reuse package manager detection during create startup ([#14006](https://github.com/vercel/turborepo/pull/14006))
    - perf: Compute Devtools graph depths without rescanning every edge ([#14001](https://github.com/vercel/turborepo/pull/14001))
    - perf: Fetch only npm dist tags in the binary version endpoint ([#14007](https://github.com/vercel/turborepo/pull/14007))
    - perf: Binary search boundaries comments before each import ([#14003](https://github.com/vercel/turborepo/pull/14003))
    - perf: Reuse resolver inference during file tracing ([#13999](https://github.com/vercel/turborepo/pull/13999))
    - perf: Coalesce glob-watcher invalidation snapshots ([#13996](https://github.com/vercel/turborepo/pull/13996))
    - perf: Limit turbo.json preloading to required task scope ([#13992](https://github.com/vercel/turborepo/pull/13992))
    - perf: Scope untracked-file discovery to filtered runs ([#13991](https://github.com/vercel/turborepo/pull/13991))
    - perf: Cache Turbo config reads across ESLint rule invocations ([#13998](https://github.com/vercel/turborepo/pull/13998))
    - perf: Index npm workspace links during subgraph extraction ([#13997](https://github.com/vercel/turborepo/pull/13997))
    - perf: Copy shared file dependencies once per destination during prune ([#13995](https://github.com/vercel/turborepo/pull/13995))
    - perf: Stream custom repository downloads to disk ([#13994](https://github.com/vercel/turborepo/pull/13994))
    - perf: Avoid materializing npm's legacy dependency tree ([#13993](https://github.com/vercel/turborepo/pull/13993))
    - perf: Fast-path package-only filter selectors with --only ([#13990](https://github.com/vercel/turborepo/pull/13990))
    - perf: Throttle TUI tick cadence ([#13988](https://github.com/vercel/turborepo/pull/13988))
    - perf: Use dense membership for task graph pruning ([#13987](https://github.com/vercel/turborepo/pull/13987))
    - perf: Use binary search for resolution states ([#13986](https://github.com/vercel/turborepo/pull/13986))
    - perf: Compile workspace glob combinators directly ([#13978](https://github.com/vercel/turborepo/pull/13978))
    - perf: Defer filesystem checks for absent configs ([#13977](https://github.com/vercel/turborepo/pull/13977))
    - perf: Skip work for disabled telemetry ([#13972](https://github.com/vercel/turborepo/pull/13972))
    - perf: Reuse canonical paths during repository discovery ([#13976](https://github.com/vercel/turborepo/pull/13976))
    - perf: Avoid regexes for simple environment matching ([#13974](https://github.com/vercel/turborepo/pull/13974))
    - perf: Cache workspace configuration lookups ([#13975](https://github.com/vercel/turborepo/pull/13975))
    - perf: Skip unnecessary glob normalization ([#13979](https://github.com/vercel/turborepo/pull/13979))
    - perf: Reuse compiled workspace matchers ([#13984](https://github.com/vercel/turborepo/pull/13984))
    - perf: Stop inference after selecting a workspace root ([#13980](https://github.com/vercel/turborepo/pull/13980))
    - perf: Fast-path numeric package manager versions ([#13973](https://github.com/vercel/turborepo/pull/13973))
    - perf: Reuse compiled workspace matchers ([#13970](https://github.com/vercel/turborepo/pull/13970))
    - perf: Parse CLI exits before starting worker pools ([#13971](https://github.com/vercel/turborepo/pull/13971))
    - perf: Batch package detail queries ([#13923](https://github.com/vercel/turborepo/pull/13923))
    - perf: Resolve Git SCM state in one process ([#13882](https://github.com/vercel/turborepo/pull/13882))
    - perf: Skip Cargo resolution for workspace-only queries ([#13903](https://github.com/vercel/turborepo/pull/13903))
    - perf: Speed up plain package listings ([#13868](https://github.com/vercel/turborepo/pull/13868))
    - perf: Batch package detail queries ([#13809](https://github.com/vercel/turborepo/pull/13809))
    - perf: Skip Factory chat verification ([#13820](https://github.com/vercel/turborepo/pull/13820))
    - perf: Skip unused repository indexing for package listings ([#13792](https://github.com/vercel/turborepo/pull/13792))
    - perf: Index Berry lockfile resolution overrides by dependency name ([#13787](https://github.com/vercel/turborepo/pull/13787))
    - perf: Replace regex captures with hand-written parsers in berry lockfile identifiers ([#13776](https://github.com/vercel/turborepo/pull/13776))
    - perf: Merge same-prefix tree-wildcard globs into one directory walk ([#13763](https://github.com/vercel/turborepo/pull/13763))
    - perf: Stream dry-run JSON output ([#13760](https://github.com/vercel/turborepo/pull/13760))
    - perf: Skip Unused Workspace Config Stats ([#13746](https://github.com/vercel/turborepo/pull/13746))
    - perf: Walk the repository once when pruning ([#13705](https://github.com/vercel/turborepo/pull/13705))
    - perf: Intern resolution identities as Arc&lt;str&gt; across closures ([#13645](https://github.com/vercel/turborepo/pull/13645))
    - perf: Build resolution identity lists in parallel ([#13643](https://github.com/vercel/turborepo/pull/13643))
    - perf: Parallelize resolution fingerprint hashing ([#13642](https://github.com/vercel/turborepo/pull/13642))
    - perf: Parse pnpm explicit-key entries in the lockfile fast path ([#13640](https://github.com/vercel/turborepo/pull/13640))
    - perf: Enable shared closure DP for npm and yarn1 lockfiles ([#13635](https://github.com/vercel/turborepo/pull/13635))
    - perf: Avoid materializing transient declarations in external_dependencies ([#13646](https://github.com/vercel/turborepo/pull/13646))
    - perf: Memoize framework inference per package during task hashing ([#13634](https://github.com/vercel/turborepo/pull/13634))
    - perf: Index Bun nested lockfile entries by name for fallback resolution ([#13633](https://github.com/vercel/turborepo/pull/13633))
    - perf: Share resolution identity lists across identical workspace closures ([#13641](https://github.com/vercel/turborepo/pull/13641))
    - perf: Index workspace nodes by name in project_relationships ([#13647](https://github.com/vercel/turborepo/pull/13647))
    - perf(lockfiles): Drop redundant human_name clone for pnpm v7/v9 ([#13649](https://github.com/vercel/turborepo/pull/13649))
    - perf(repository): Avoid discarded alias allocation in Relationship ([#13650](https://github.com/vercel/turborepo/pull/13650))
    - perf(lockfiles): Borrow field-name scalars in the pnpm fast parser ([#13648](https://github.com/vercel/turborepo/pull/13648))
    - perf: Walk literal-prefix tree globs without wax compilation ([#13522](https://github.com/vercel/turborepo/pull/13522))
    - perf: Reuse Cargo metadata discovery snapshot ([#13600](https://github.com/vercel/turborepo/pull/13600))
    - perf: Cache telemetry salt instead of re-reading config on every hash ([#13498](https://github.com/vercel/turborepo/pull/13498))
    - perf: Evaluate simple include globs without wax compilation ([#13285](https://github.com/vercel/turborepo/pull/13285))
    - perf: Skip dependency-closure assembly for toolchains that derive nothing ([#13277](https://github.com/vercel/turborepo/pull/13277))
    - perf: Remove lock and dispatch overhead from task hash precomputation ([#13273](https://github.com/vercel/turborepo/pull/13273))
    - perf: Defer the untracked-scan barrier to first file-hash use ([#13268](https://github.com/vercel/turborepo/pull/13268))
    - perf: Parse large pnpm lockfile sections in parallel ([#13266](https://github.com/vercel/turborepo/pull/13266))
    - perf: Pre-size engine task collections ([#13265](https://github.com/vercel/turborepo/pull/13265))
    - perf: Probe microfrontends configs in parallel ([#13262](https://github.com/vercel/turborepo/pull/13262))
    - perf: Compute transitive closures and external dependency hashes concurrently with run setup ([#13250](https://github.com/vercel/turborepo/pull/13250))
    - perf: Memoize resolved task definitions during engine construction ([#13257](https://github.com/vercel/turborepo/pull/13257))
    - perf: Stat workspace turbo.json files concurrently during discovery ([#13251](https://github.com/vercel/turborepo/pull/13251))
    - perf: Reuse per-package external dependency hashes in run summaries ([#13249](https://github.com/vercel/turborepo/pull/13249))
    - perf: Hash git blobs with hardware-accelerated SHA-1 ([#13245](https://github.com/vercel/turborepo/pull/13245))
    - perf: Parse Berry lockfiles in a single pass ([#13242](https://github.com/vercel/turborepo/pull/13242))
    - perf: Overhaul pnpm lockfile parsing and dependency closure computation ([#13228](https://github.com/vercel/turborepo/pull/13228))
    - perf: Release tokio runtime at exit so background DNS lookups never stall the user ([#13231](https://github.com/vercel/turborepo/pull/13231))
    - perf: Build tracked repo index concurrently with package graph ([#13232](https://github.com/vercel/turborepo/pull/13232))
    - perf: Overlap external dependency hashing with package file hashing ([#13234](https://github.com/vercel/turborepo/pull/13234))
    - perf: Stop materializing spans for the disabled daemon log layer ([#13244](https://github.com/vercel/turborepo/pull/13244))
    - perf: Parse yarn v1 lockfiles in a single pass ([#13241](https://github.com/vercel/turborepo/pull/13241))
    - perf: Use mimalloc as the global allocator ([#13237](https://github.com/vercel/turborepo/pull/13237))
    - perf: Derive dirty hash from repo index ([#13213](https://github.com/vercel/turborepo/pull/13213))
    - perf: Replace per-package graph traversals in scope filtering ([#13212](https://github.com/vercel/turborepo/pull/13212))
    - perf: Cache env wildcard matches across tasks during hashing ([#13210](https://github.com/vercel/turborepo/pull/13210))
    - perf: Cache root internal dependencies in package graph ([#13211](https://github.com/vercel/turborepo/pull/13211))
    - perf: Avoid deep-cloning dependency maps in lockfile closure cache ([#13209](https://github.com/vercel/turborepo/pull/13209))
    - perf(build): Enable thin LTO + codegen-units=1 for release builds ([#13160](https://github.com/vercel/turborepo/pull/13160))
    - perf: Avoid normalizing git index path joins ([#12944](https://github.com/vercel/turborepo/pull/12944))

  </Accordion>

  <Accordion title="Fixes (195)">

    - fix: Defer dependency output validation for lazy scopes ([#14097](https://github.com/vercel/turborepo/pull/14097))
    - fix: Harden cache archive restoration ([#14095](https://github.com/vercel/turborepo/pull/14095))
    - fix: Preserve task env mode when pruning ([#14087](https://github.com/vercel/turborepo/pull/14087))
    - fix: Follow Go default binary output paths ([#14079](https://github.com/vercel/turborepo/pull/14079))
    - fix: Isolate task logs for co-located packages ([#14077](https://github.com/vercel/turborepo/pull/14077))
    - fix: Preserve all co-located package change owners ([#14075](https://github.com/vercel/turborepo/pull/14075))
    - fix: Infer all co-located packages from cwd ([#14074](https://github.com/vercel/turborepo/pull/14074))
    - fix: Use pnpm for non-monorepo deployments ([#14071](https://github.com/vercel/turborepo/pull/14071))
    - fix: Run Go verification per module ([#14072](https://github.com/vercel/turborepo/pull/14072))
    - fix: Run Go workspace formatting per module ([#14070](https://github.com/vercel/turborepo/pull/14070))
    - fix: Discover native workspace metadata lazily ([#14053](https://github.com/vercel/turborepo/pull/14053))
    - fix: Fall back to the published tag when the dogfooded turbo version is unpublished ([#14067](https://github.com/vercel/turborepo/pull/14067))
    - fix: Return resolved package names for aliases ([#14061](https://github.com/vercel/turborepo/pull/14061))
    - fix: Pass through LOCALAPPDATA by default ([#14056](https://github.com/vercel/turborepo/pull/14056))
    - fix: Preserve native task dependencies across entrypoints ([#14047](https://github.com/vercel/turborepo/pull/14047))
    - fix: Preserve nested Bun package keys ([#14050](https://github.com/vercel/turborepo/pull/14050))
    - fix: Avoid duplicate interrupts during task shutdown ([#14046](https://github.com/vercel/turborepo/pull/14046))
    - fix: Preserve Yarn resolution declaration order ([#14045](https://github.com/vercel/turborepo/pull/14045))
    - fix: Include experimentalCI in task hashes ([#14038](https://github.com/vercel/turborepo/pull/14038))
    - fix: Restore leading flags for implicit run commands ([#14037](https://github.com/vercel/turborepo/pull/14037))
    - fix: Normalize bare directory outputs when filtering dependencyOutputs hashes ([#13932](https://github.com/vercel/turborepo/pull/13932))
    - fix: Add slug to OPTIONS request ([#13943](https://github.com/vercel/turborepo/pull/13943))
    - fix: Correct Go workspace resolution and task caching ([#13966](https://github.com/vercel/turborepo/pull/13966))
    - fix: Harden Go workspace diagnostics ([#13964](https://github.com/vercel/turborepo/pull/13964))
    - fix: Recompute eager hashing flag after prepending global inputs ([#13949](https://github.com/vercel/turborepo/pull/13949))
    - fix: Hash native workspace task inputs ([#13947](https://github.com/vercel/turborepo/pull/13947))
    - fix: Avoid oxlint false positive on Workspace.find options ([#13941](https://github.com/vercel/turborepo/pull/13941))
    - fix: Expect napi 3 artifact paths ([#13938](https://github.com/vercel/turborepo/pull/13938))
    - fix: Skip git commit in bump-version ([#13937](https://github.com/vercel/turborepo/pull/13937))
    - fix: Allow unclean tree in bump-version ([#13936](https://github.com/vercel/turborepo/pull/13936))
    - fix: Use static library bootstrap shell ([#13935](https://github.com/vercel/turborepo/pull/13935))
    - fix: Bootstrap musl builds with sh ([#13934](https://github.com/vercel/turborepo/pull/13934))
    - fix: Use Node 20 for musl library builds ([#13933](https://github.com/vercel/turborepo/pull/13933))
    - fix: Upgrade repository N-API build tooling ([#13931](https://github.com/vercel/turborepo/pull/13931))
    - fix: Use pnpm 12 in library release containers ([#13930](https://github.com/vercel/turborepo/pull/13930))
    - fix: Support pnpm 6 single-package lockfiles ([#13928](https://github.com/vercel/turborepo/pull/13928))
    - fix: Give the package changes watcher the future flags so root inputs reach the task filter ([#13926](https://github.com/vercel/turborepo/pull/13926))
    - fix: Allow release versioning with pending changes ([#13921](https://github.com/vercel/turborepo/pull/13921))
    - fix: Hash deferred inputs after dependencies ([#13919](https://github.com/vercel/turborepo/pull/13919))
    - fix: Pass merge_base and allow_unknown_objects in signature order for task-level filter ranges ([#13917](https://github.com/vercel/turborepo/pull/13917))
    - fix: Only treat files literally named .gitignore as ignore files in the untracked walk ([#13916](https://github.com/vercel/turborepo/pull/13916))
    - fix: Preserve task metadata for command overrides ([#13915](https://github.com/vercel/turborepo/pull/13915))
    - fix: Stabilize Rust builds on macOS ([#13913](https://github.com/vercel/turborepo/pull/13913))
    - fix: Resolve lint errors ([#13912](https://github.com/vercel/turborepo/pull/13912))
    - fix: Correct devtools --port default in CLI help ([#13905](https://github.com/vercel/turborepo/pull/13905))
    - fix: Bump tar to 7.5.22 in @turbo/releaser (CVE-2026-73566) ([#13911](https://github.com/vercel/turborepo/pull/13911))
    - fix: Clarify generator action reporting ([#13910](https://github.com/vercel/turborepo/pull/13910))
    - fix: Bound memory usage for streamed task output ([#13908](https://github.com/vercel/turborepo/pull/13908))
    - fix: Update --filter help links to canonical docs URL ([#13891](https://github.com/vercel/turborepo/pull/13891))
    - fix: Normalize multi-language cache environment inputs ([#13898](https://github.com/vercel/turborepo/pull/13898))
    - fix: Deduplicate multi-language watch hashes ([#13897](https://github.com/vercel/turborepo/pull/13897))
    - fix: Show native tasks in task listings ([#13889](https://github.com/vercel/turborepo/pull/13889))
    - fix: Gracefully handle native lockfile failures ([#13886](https://github.com/vercel/turborepo/pull/13886))
    - fix: Show workspace failure details ([#13884](https://github.com/vercel/turborepo/pull/13884))
    - fix: Format Slack pull request notifications ([#13877](https://github.com/vercel/turborepo/pull/13877))
    - fix: Detect package-level turbo.jsonc ([#13875](https://github.com/vercel/turborepo/pull/13875))
    - fix: Refresh Factory workspaces from main ([#13873](https://github.com/vercel/turborepo/pull/13873))
    - fix: Restore docs client navigation ([#13872](https://github.com/vercel/turborepo/pull/13872))
    - fix: Pluralize package count in run prelude ([#13865](https://github.com/vercel/turborepo/pull/13865))
    - fix: Restrict Factory to review comments ([#13864](https://github.com/vercel/turborepo/pull/13864))
    - fix: Keep Cargo tasks runnable without compiler identity ([#13857](https://github.com/vercel/turborepo/pull/13857))
    - fix: Explain disabled Cargo task caching ([#13854](https://github.com/vercel/turborepo/pull/13854))
    - fix: Explain uncached Cargo library builds ([#13855](https://github.com/vercel/turborepo/pull/13855))
    - fix: Explain uv identity probe failures ([#13853](https://github.com/vercel/turborepo/pull/13853))
    - fix: Explain disabled uv task caching ([#13852](https://github.com/vercel/turborepo/pull/13852))
    - fix: Scope uv lockfile affectedness ([#13850](https://github.com/vercel/turborepo/pull/13850))
    - fix: Copy TUI selections locally over SSH ([#13847](https://github.com/vercel/turborepo/pull/13847))
    - fix: Remove unsupported remote cache environment variable ([#13845](https://github.com/vercel/turborepo/pull/13845))
    - fix: Run pnpm directly on Windows ([#13843](https://github.com/vercel/turborepo/pull/13843))
    - fix: Escape ampersands in RSS feed enclosure URLs ([#13839](https://github.com/vercel/turborepo/pull/13839))
    - fix: Move model selector to workspace creation ([#13835](https://github.com/vercel/turborepo/pull/13835))
    - fix: Update Factory pull request branches ([#13831](https://github.com/vercel/turborepo/pull/13831))
    - fix: Prevent chat SSH command overflow ([#13828](https://github.com/vercel/turborepo/pull/13828))
    - fix: Add workspace approval controls ([#13827](https://github.com/vercel/turborepo/pull/13827))
    - fix: Include virtual tasks in affected query ([#13805](https://github.com/vercel/turborepo/pull/13805))
    - fix: Restore Factory workspaces ([#13823](https://github.com/vercel/turborepo/pull/13823))
    - fix: Install Factory publishing skill ([#13817](https://github.com/vercel/turborepo/pull/13817))
    - fix: Improve Factory terminal line spacing ([#13815](https://github.com/vercel/turborepo/pull/13815))
    - fix: Update Factory session network policy ([#13814](https://github.com/vercel/turborepo/pull/13814))
    - fix: Restore Factory workspace creation ([#13812](https://github.com/vercel/turborepo/pull/13812))
    - fix: Rebuild factory images without custom workflows ([#13801](https://github.com/vercel/turborepo/pull/13801))
    - fix: Decouple graceful shutdown tests from the shell commands example ([#13799](https://github.com/vercel/turborepo/pull/13799))
    - fix: Show invalid affected task glob ([#13793](https://github.com/vercel/turborepo/pull/13793))
    - fix: Remove incremental task caching ([#13773](https://github.com/vercel/turborepo/pull/13773))
    - fix: Prevent homepage KPI overflow ([#13770](https://github.com/vercel/turborepo/pull/13770))
    - fix: Align homepage KPIs to the right ([#13769](https://github.com/vercel/turborepo/pull/13769))
    - fix: Refine mobile homepage interactions ([#13767](https://github.com/vercel/turborepo/pull/13767))
    - fix: Preserve showcase logo sizes ([#13766](https://github.com/vercel/turborepo/pull/13766))
    - fix: Tolerate transient input files ([#13734](https://github.com/vercel/turborepo/pull/13734))
    - fix: Respect gitignore without git metadata ([#13756](https://github.com/vercel/turborepo/pull/13756))
    - fix: Isolate concurrent generator config bundles ([#13750](https://github.com/vercel/turborepo/pull/13750))
    - fix: Avoid repeated strict entrypoint traversal ([#13745](https://github.com/vercel/turborepo/pull/13745))
    - fix: Automatically approve release workflows ([#13743](https://github.com/vercel/turborepo/pull/13743))
    - fix(bun): Preserve overrides objects, trustedDependencies, workspace bins and git integrity through prune; accept lockfileVersion 3 ([#13740](https://github.com/vercel/turborepo/pull/13740))
    - fix: Scope musl library dependency installation ([#13738](https://github.com/vercel/turborepo/pull/13738))
    - fix: Expose Slack delivery diagnostics ([#13733](https://github.com/vercel/turborepo/pull/13733))
    - fix: Apply nested parent gitignore patterns in manual hashing ([#13690](https://github.com/vercel/turborepo/pull/13690))
    - fix(cli): Move EXPERIMENTAL label from ls command to --output flag ([#13709](https://github.com/vercel/turborepo/pull/13709))
    - fix: Resolve agent lint errors ([#13716](https://github.com/vercel/turborepo/pull/13716))
    - fix: Remove unsupported sandbox network policy ([#13712](https://github.com/vercel/turborepo/pull/13712))
    - fix: Enable Eve examples pull requests ([#13708](https://github.com/vercel/turborepo/pull/13708))
    - fix(deps): Upgrade js-yaml to 4.3.1 (GHSA-5p4m-2wfm-xmqj) ([#13704](https://github.com/vercel/turborepo/pull/13704))
    - fix: Prevent Windows process cleanup PID reuse ([#13695](https://github.com/vercel/turborepo/pull/13695))
    - fix: Prune Bun wildcard workspace dev dependencies ([#13694](https://github.com/vercel/turborepo/pull/13694))
    - fix: Respect aggregate task overrides ([#13668](https://github.com/vercel/turborepo/pull/13668))
    - fix: Invalidate only when Git ignore sources change ([#13632](https://github.com/vercel/turborepo/pull/13632))
    - fix: don't use eprintln! in the panic hook ([#13637](https://github.com/vercel/turborepo/pull/13637))
    - fix: Upgrade brace-expansion to 5.0.9 ([#13658](https://github.com/vercel/turborepo/pull/13658))
    - fix: Compose affected tasks with package filters ([#13656](https://github.com/vercel/turborepo/pull/13656))
    - fix: Accept semver ranges in devEngines.packageManager.version ([#13623](https://github.com/vercel/turborepo/pull/13623))
    - fix: Fall back to polling on macOS ([#13622](https://github.com/vercel/turborepo/pull/13622))
    - fix: Make Windows Cap'n Proto cache relocatable ([#13621](https://github.com/vercel/turborepo/pull/13621))
    - fix: Serialize macOS Homebrew setup ([#13549](https://github.com/vercel/turborepo/pull/13549))
    - fix: Support fork PRs in review gate ([#13516](https://github.com/vercel/turborepo/pull/13516))
    - fix: Use tokenless release review gate ([#13513](https://github.com/vercel/turborepo/pull/13513))
    - fix: Resolve gitdir for linked worktrees in repo index ([#13503](https://github.com/vercel/turborepo/pull/13503))
    - fix: Make releases resumable ([#13486](https://github.com/vercel/turborepo/pull/13486))
    - fix: Scroll TUI task list with mouse wheel ([#13479](https://github.com/vercel/turborepo/pull/13479))
    - fix: Support multiple macOS file watch roots ([#13484](https://github.com/vercel/turborepo/pull/13484))
    - fix: Preserve pnpm aliased dependencies during prune ([#13477](https://github.com/vercel/turborepo/pull/13477))
    - fix: Preserve pnpm root dependencies during prune ([#13476](https://github.com/vercel/turborepo/pull/13476))
    - fix: Prevent mobile homepage overflow ([#13453](https://github.com/vercel/turborepo/pull/13453))
    - fix: Upgrade @vercel/connect ([#13450](https://github.com/vercel/turborepo/pull/13450))
    - fix: Verify version after attempting codemod upgrade ([#13446](https://github.com/vercel/turborepo/pull/13446))
    - fix: Preserve project Yarn package extensions ([#13425](https://github.com/vercel/turborepo/pull/13425))
    - fix: Match JIT inputs for affected tasks ([#13426](https://github.com/vercel/turborepo/pull/13426))
    - fix: Refactor `turbo watch` ([#13423](https://github.com/vercel/turborepo/pull/13423))
    - fix: Check dynamic imports in boundaries ([#13418](https://github.com/vercel/turborepo/pull/13418))
    - fix: Preserve pnpm `node@runtime:` lockfile entries ([#13408](https://github.com/vercel/turborepo/pull/13408))
    - fix: Fetch release commit parent ([#13400](https://github.com/vercel/turborepo/pull/13400))
    - fix: Pin VS Code extension macOS runners ([#13391](https://github.com/vercel/turborepo/pull/13391))
    - fix: Resolve weekly security audit vulnerabilities ([#13358](https://github.com/vercel/turborepo/pull/13358))
    - fix: Retain shutdown signals for force exit ([#13382](https://github.com/vercel/turborepo/pull/13382))
    - fix: Preserve colors in TUI output ([#13381](https://github.com/vercel/turborepo/pull/13381))
    - fix: Preserve Yarn Babel extension during pruning ([#13373](https://github.com/vercel/turborepo/pull/13373))
    - fix: Resolve Cargo target output layouts ([#13370](https://github.com/vercel/turborepo/pull/13370))
    - fix: Prune Bun production workspace dev dependencies ([#13369](https://github.com/vercel/turborepo/pull/13369))
    - fix: Resolve exact cargo profile outputs ([#13366](https://github.com/vercel/turborepo/pull/13366))
    - fix: Surface create-turbo Git failures ([#13371](https://github.com/vercel/turborepo/pull/13371))
    - fix: Disable unresolved Cargo artifact caching ([#13362](https://github.com/vercel/turborepo/pull/13362))
    - fix: Preserve Yarn package extension ranges when pruning ([#13363](https://github.com/vercel/turborepo/pull/13363))
    - fix: Synchronize Cargo prune Docker lockfile ([#13350](https://github.com/vercel/turborepo/pull/13350))
    - fix: Hash Cargo build environment inputs ([#13348](https://github.com/vercel/turborepo/pull/13348))
    - fix: Include patched Ghostty crate in Cargo workspace ([#13357](https://github.com/vercel/turborepo/pull/13357))
    - fix: Isolate Command Overrides From Toolchain Cache I/O ([#13354](https://github.com/vercel/turborepo/pull/13354))
    - fix: Preserve watch rerun semantics for task inputs ([#13351](https://github.com/vercel/turborepo/pull/13351))
    - fix: Build Ghostty for baseline CPUs ([#13352](https://github.com/vercel/turborepo/pull/13352))
    - fix: Resolve Cargo lock dependencies by source ([#13343](https://github.com/vercel/turborepo/pull/13343))
    - fix: Allow outputs outside package roots ([#13342](https://github.com/vercel/turborepo/pull/13342))
    - fix: Reject unsupported Cargo local packages ([#13340](https://github.com/vercel/turborepo/pull/13340))
    - fix: Require current Cargo lockfiles for caching ([#13339](https://github.com/vercel/turborepo/pull/13339))
    - fix: Continue TUI text selection beyond viewport ([#13338](https://github.com/vercel/turborepo/pull/13338))
    - fix: Isolate Cargo cache by host platform ([#13337](https://github.com/vercel/turborepo/pull/13337))
    - fix: Prevent Cargo run tasks from being cached ([#13335](https://github.com/vercel/turborepo/pull/13335))
    - fix: Resolve EADDRINUSE in kitchen-sink api dev script ([#13328](https://github.com/vercel/turborepo/pull/13328))
    - fix: Make npm prune rehoisting deterministic and complete ([#13323](https://github.com/vercel/turborepo/pull/13323))
    - fix: Remove extraneous bun.lock entries during prune ([#13317](https://github.com/vercel/turborepo/pull/13317))
    - fix: Show toolchain tasks in the TUI and never run in silence ([#13308](https://github.com/vercel/turborepo/pull/13308))
    - fix: Keep pnpm patches with version range keys during prune ([#13307](https://github.com/vercel/turborepo/pull/13307))
    - fix: Never let compile cache storage failures fail the build ([#13299](https://github.com/vercel/turborepo/pull/13299))
    - fix: Stop ambient CARGO_INCREMENTAL from suppressing compile cache injection ([#13298](https://github.com/vercel/turborepo/pull/13298))
    - fix: Make the sccache compile cache actually cache ([#13296](https://github.com/vercel/turborepo/pull/13296))
    - fix: Pin a flag-aware turbo canary for the eve-agent deployment ([#13295](https://github.com/vercel/turborepo/pull/13295))
    - fix: Disable the sccache proxy when remote cache use is off ([#13291](https://github.com/vercel/turborepo/pull/13291))
    - fix: Reject output path traversal ([#13290](https://github.com/vercel/turborepo/pull/13290))
    - fix: Stop flagging relative imports that resolve into node_modules in boundaries ([#13284](https://github.com/vercel/turborepo/pull/13284))
    - fix: Raise the open-file soft limit at startup ([#13282](https://github.com/vercel/turborepo/pull/13282))
    - fix: Collapse nested package-manager fallback conditional ([#13279](https://github.com/vercel/turborepo/pull/13279))
    - fix: Fall back to lockfile detection in @turbo/repository when package manager is undeclared ([#13275](https://github.com/vercel/turborepo/pull/13275))
    - fix: Avoid non-reentrant libc calls in concurrent shutdown process scans ([#13256](https://github.com/vercel/turborepo/pull/13256))
    - fix: Stop root-directory packages from claiming every file in change mapping ([#13225](https://github.com/vercel/turborepo/pull/13225))
    - fix: Apply input exclusion globs to the filesystem walk ([#13224](https://github.com/vercel/turborepo/pull/13224))
    - fix: Keep ancestor-scoped bun dependencies resolvable after prune renames ([#13236](https://github.com/vercel/turborepo/pull/13236))
    - fix: Correct gitignore precedence in untracked walk and memoize matcher chains ([#13221](https://github.com/vercel/turborepo/pull/13221))
    - fix: Harden TUI terminal restore during shutdown ([#13220](https://github.com/vercel/turborepo/pull/13220))
    - fix: Remove devtools feature flag ([#13219](https://github.com/vercel/turborepo/pull/13219))
    - fix: Include untracked symlinks in repo-index dirty hash ([#13218](https://github.com/vercel/turborepo/pull/13218))
    - fix: Resolve Bun scoped package deps that share a name with a dependency ([#13207](https://github.com/vercel/turborepo/pull/13207))
    - fix(watch): recover from slow initial hash instead of timing out ([#13159](https://github.com/vercel/turborepo/pull/13159))
    - fix: Improve error messaging when platform binary is missing ([#13199](https://github.com/vercel/turborepo/pull/13199))
    - fix: Report malformed JSON parse errors instead of panicking ([#13198](https://github.com/vercel/turborepo/pull/13198))
    - fix:  Tweaks for nub support ([#13187](https://github.com/vercel/turborepo/pull/13187))
    - fix: Handle task executor join errors as internal errors ([#13148](https://github.com/vercel/turborepo/pull/13148))
    - fix: Add token exchange recovery guidance ([#13192](https://github.com/vercel/turborepo/pull/13192))
    - fix: Skip node_modules in boundaries checks ([#13191](https://github.com/vercel/turborepo/pull/13191))
    - fix: Normalize package manager version output ([#13185](https://github.com/vercel/turborepo/pull/13185))
    - fix: Support nub native lockfiles ([#13179](https://github.com/vercel/turborepo/pull/13179))
    - fix: Use singular workspace in package resolution error ([#13178](https://github.com/vercel/turborepo/pull/13178))
    - fix: Normalize package manager versions ([#13177](https://github.com/vercel/turborepo/pull/13177))
    - fix: Link ghostty-vt statically on Windows MSVC ([#13171](https://github.com/vercel/turborepo/pull/13171))
    - fix: Avoid following nested symlinked cache outputs ([#13166](https://github.com/vercel/turborepo/pull/13166))
    - fix: Preserve 3-level nested Bun lockfile entries during prune ([#13168](https://github.com/vercel/turborepo/pull/13168))
    - fix: Install Zig for LSP builds ([#13158](https://github.com/vercel/turborepo/pull/13158))
    - fix(env): Add XDG_DATA_* to pass-through ([#13145](https://github.com/vercel/turborepo/pull/13145))
    - fix: Support Corepack packageManager integrity hashes ([#13123](https://github.com/vercel/turborepo/pull/13123))

  </Accordion>

  <Accordion title="Documentation (40)">

    - docs: Document per-toolchain task commands ([#14073](https://github.com/vercel/turborepo/pull/14073))
    - docs: Fix some typos ([#14058](https://github.com/vercel/turborepo/pull/14058))
    - docs: Document circular dependencies in boundaries ([#14041](https://github.com/vercel/turborepo/pull/14041))
    - docs: Explain circular package dependencies in boundaries ([#14042](https://github.com/vercel/turborepo/pull/14042))
    - docs: Group experimental languages and link the Go RFC ([#14034](https://github.com/vercel/turborepo/pull/14034))
    - docs: Document a focused Cargo build for CLI-only development ([#14018](https://github.com/vercel/turborepo/pull/14018))
    - docs(skills): fix the dependencies-only filter caret position ([#13965](https://github.com/vercel/turborepo/pull/13965))
    - docs: Document experimental native Go workspaces ([#13963](https://github.com/vercel/turborepo/pull/13963))
    - docs: Touch-ups for Python and Rust docs ([#13940](https://github.com/vercel/turborepo/pull/13940))
    - docs: Align Python guide with Rust guide ([#13927](https://github.com/vercel/turborepo/pull/13927))
    - docs: Clean up Rust docs ([#13914](https://github.com/vercel/turborepo/pull/13914))
    - docs: Align CONTRIBUTING Node and pnpm versions ([#13883](https://github.com/vercel/turborepo/pull/13883))
    - docs: Document missing reference flags and fix query typo ([#13902](https://github.com/vercel/turborepo/pull/13902))
    - docs: Clarify turbo ls stability in Agent Skill ([#13892](https://github.com/vercel/turborepo/pull/13892))
    - docs: Upgrade Geistdocs to 1.25.1 ([#13861](https://github.com/vercel/turborepo/pull/13861))
    - docs: Fix inconsistent Yarn command in basic example ([#13825](https://github.com/vercel/turborepo/pull/13825))
    - docs: Fix reference links and validation ([#13784](https://github.com/vercel/turborepo/pull/13784))
    - docs: Redesign Turborepo homepage ([#13702](https://github.com/vercel/turborepo/pull/13702))
    - docs: Update Geistdocs to 1.19.6 ([#13701](https://github.com/vercel/turborepo/pull/13701))
    - docs: Document dependency-driven Python tasks ([#13676](https://github.com/vercel/turborepo/pull/13676))
    - docs: Fix loadTransformers reference in turbo-codemod README ([#13683](https://github.com/vercel/turborepo/pull/13683))
    - docs: Update redirected vercel.com/nextjs.org links to current targets ([#13685](https://github.com/vercel/turborepo/pull/13685))
    - docs: Use the geistdocs Turborepo logo in the navbar ([#13682](https://github.com/vercel/turborepo/pull/13682))
    - docs: Exclude Turborepo from its own OSS products menu ([#13681](https://github.com/vercel/turborepo/pull/13681))
    - docs: Update Geistdocs to 1.19.4 ([#13680](https://github.com/vercel/turborepo/pull/13680))
    - docs: Correct verified inaccuracies in the Turborepo Agent Skill ([#13644](https://github.com/vercel/turborepo/pull/13644))
    - docs: Explain worktree cache path isolation ([#13657](https://github.com/vercel/turborepo/pull/13657))
    - docs: Fix duplicated word in runtime dependencies guide summary ([#13630](https://github.com/vercel/turborepo/pull/13630))
    - docs: Explain affected package invalidation reasons ([#13594](https://github.com/vercel/turborepo/pull/13594))
    - docs: Vercel Remote Cache authentication with OIDC policies ([#13140](https://github.com/vercel/turborepo/pull/13140))
    - docs: Audit Cargo package knowledge ([#13572](https://github.com/vercel/turborepo/pull/13572))
    - docs: Fix llms.txt links to page markdown routes ([#13497](https://github.com/vercel/turborepo/pull/13497))
    - docs: Document service readiness probes ([#13472](https://github.com/vercel/turborepo/pull/13472))
    - docs: Update Geistdocs to 1.13.0 ([#13412](https://github.com/vercel/turborepo/pull/13412))
    - docs: Add Experimental Rust Guide ([#13375](https://github.com/vercel/turborepo/pull/13375))
    - docs: Update Cargo workspace support ([#13349](https://github.com/vercel/turborepo/pull/13349))
    - docs: Migrate docs site to @vercel/geistdocs package ([#13320](https://github.com/vercel/turborepo/pull/13320))
    - docs: Add filtered installs to Vercel guide ([#13196](https://github.com/vercel/turborepo/pull/13196))
    - docs: Prefer devEngines packageManager ([#13155](https://github.com/vercel/turborepo/pull/13155))
    - docs: Add Turborepo 2.10 release post and update docs ([#13096](https://github.com/vercel/turborepo/pull/13096))

  </Accordion>

  <Accordion title="Examples (28)">

    - chore: Update with-npm example ([#14083](https://github.com/vercel/turborepo/pull/14083))
    - chore: Update with-nestjs example ([#14064](https://github.com/vercel/turborepo/pull/14064))
    - chore: Update with-mcp-servers example ([#14049](https://github.com/vercel/turborepo/pull/14049))
    - chore: Update with-docker example ([#14035](https://github.com/vercel/turborepo/pull/14035))
    - chore: Update with-biome example ([#13983](https://github.com/vercel/turborepo/pull/13983))
    - chore: Update with-angular example ([#13951](https://github.com/vercel/turborepo/pull/13951))
    - chore: Update kitchen-sink example ([#13945](https://github.com/vercel/turborepo/pull/13945))
    - chore: Update basic example ([#13922](https://github.com/vercel/turborepo/pull/13922))
    - chore: Update with-vue-nuxt example ([#13901](https://github.com/vercel/turborepo/pull/13901))
    - chore: Update with-vite-react example ([#13880](https://github.com/vercel/turborepo/pull/13880))
    - chore: Update with-vite example ([#13866](https://github.com/vercel/turborepo/pull/13866))
    - chore: Update basic example ([#13824](https://github.com/vercel/turborepo/pull/13824))
    - chore: Update non-monorepo example ([#13808](https://github.com/vercel/turborepo/pull/13808))
    - chore: Update with-solid example ([#13797](https://github.com/vercel/turborepo/pull/13797))
    - chore: Update with-shell-commands example ([#13791](https://github.com/vercel/turborepo/pull/13791))
    - chore: Update with-rsbuild-module-federation example ([#13786](https://github.com/vercel/turborepo/pull/13786))
    - chore: Update with-svelte example ([#13118](https://github.com/vercel/turborepo/pull/13118))
    - chore: Update with-ultracite example ([#13772](https://github.com/vercel/turborepo/pull/13772))
    - chore: Update with-tailwind example ([#13762](https://github.com/vercel/turborepo/pull/13762))
    - chore: Update with-solid example ([#13752](https://github.com/vercel/turborepo/pull/13752))
    - chore: Update with-rsbuild example ([#13730](https://github.com/vercel/turborepo/pull/13730))
    - chore: Update non-monorepo example ([#13727](https://github.com/vercel/turborepo/pull/13727))
    - chore: Update with-rollup example ([#13718](https://github.com/vercel/turborepo/pull/13718))
    - chore: Update Next.js to 16.3.0 ([#13659](https://github.com/vercel/turborepo/pull/13659))
    - refactor: Move repository tasks into `turbo` configuration ([#13504](https://github.com/vercel/turborepo/pull/13504))
    - chore: Fix typos in with-solid example and globwatch comment ([#13416](https://github.com/vercel/turborepo/pull/13416))
    - chore: Update vitest example to vitest 4 and use native test merging ([#13202](https://github.com/vercel/turborepo/pull/13202))
    - examples: add with-mcp-servers ([#12997](https://github.com/vercel/turborepo/pull/12997))

  </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all contributors, including our core team: [Anthony](https://github.com/anthonyshew) and [Tom](https://github.com/tknickman).

We also thank everyone who contributed to this release of Turborepo: @abhiaagarwal, @akshat-OwO, @alexey-yunoshev-1, @ashusnapx, @BABTUNA, @bangseongbeom, @charpeni, @christopherkindl, @colinhacks, @cuishuang, @Divyansh151005, @dnukumamras, @DominikRusso, @floriansalihovic, @ghoullier, @gtbuchanan, @gwagjiug, @Jarred-Sumner, @lachieh, @latent-9, @louis-bompart, @lukesandberg, @markandrus, @molebox, @molofsky, @Nishant-Chaudhary5338, @Nixxx19, @ognevny, @okxint, @Pcmhacker-piro, @Sakshamm-Goyal, @smasato, @tajo, @timsnadden, @tsushanth, @XananasX7, @y-lakhdar.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](/docs/community).

---

### Apps Docs Content Blog 2 8 (`apps/docs/content/blog/2-8.mdx`)

---
title: Turborepo 2.8
date: 2026/01/26
description: "Git worktrees, Agent Skill, AI-enabled documentation, `turbo docs`, task descriptions"
product: turborepo
type: overview
summary: Release notes for Turborepo 2.8 featuring Git worktree support, Agent Skill, and AI-enabled documentation.
tag: "web development"
---

import { Authors } from "@/components/blog/authors";
import { Callout } from "@/components/geistdocs/callout";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Date } from "@/components/blog/date";
import { Accordion, Accordions } from "@/components/geistdocs/accordion";

# Turborepo 2.8

<Date>Thursday, January 23rd, 2026</Date>

<Authors authors={["anthonyshew"]} />

Turborepo 2.8 is the build system for agentic coding, with features like:

- [**Git worktree support**](#shared-cache-for-git-worktrees): Share your local cache across Git worktrees
- [**Agent Skill**](#agent-skill): Make any agent a Turborepo expert
- [**AI-enabled documentation**](#improved-ai-accessibility-for-our-docs): AI chat, versioned docs, Markdown responses for agents, and more
- [**`turbo docs`**](#turbo-docs-subcommand): Search documentation directly from your terminal
- [**Task descriptions**](#task-descriptions): Add context to your task definitions in `turbo.json`

As usage of coding agents continues to accelerate, Turborepo will keep innovating to make your workflows faster, locally and remotely. Check out [our AI guide](/docs/guides/ai) to learn how to use AI most effectively in a Turborepo.

Upgrade today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Use the automated upgrade CLI
pnpm dlx @turbo/codemod migrate

# Start a new repository
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Use the automated upgrade CLI
yarn dlx @turbo/codemod migrate

# Start a new repository
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Use the automated upgrade CLI
npx @turbo/codemod migrate

# Start a new repository
npx create-turbo@latest
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Use the automated upgrade CLI
bunx @turbo/codemod migrate

# Start a new repository
bunx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

## Shared cache for Git worktrees

Many developers want to run multiple coding agents in parallel, in the same repository. But how do you keep your agents from getting in each others' way?

[Git worktrees](https://git-scm.com/docs/git-worktree) are a common technique for this. They allow you to check out multiple branches simultaneously, in separate directories, all sharing the same Git history. However, each worktree would have a new local cache instance, so you would miss cache when creating a new worktree.

Starting with this release, Turborepo now shares the local cache across Git worktrees.

```bash title="Terminal"
# Create a cache for your task
turbo run build

# Create a worktree and change to its directory
git worktree add -B my-branch ../my-branch && cd ../my-branch

## Run the task again for a full cache hit
turbo run build
```

Combined with Remote Caching, this can tremendously speed up your agentic coding experience. The feedback loops that you create with your `turbo` commands can achieve higher cache hit rates, locally and in CI.

No configuration is required. Turborepo will automatically detect when it's running in a worktree and share the local cache.

## Agent Skill

[Agent Skills](https://agentskills.io/home) are an open standard that give new capabilities and expertise to agents. They're folders of instructions, scripts, and resources that agents can use to do things more accurately and efficiently.

You can now add the Turborepo Skill to your agent, making it an expert in Turborepo and monorepos.

```bash title="Terminal"
npx skills add vercel/turborepo
```

The Skill teaches agents best practices for Turborepo, recommendations for monorepos, anti-patterns to avoid, and other important patterns to get the most out of your repository.

Visit [our AI guide](/docs/guides/ai#agent-skill) to learn more.

## Improved AI accessibility for our docs

We've retooled this site to enable agents and AI-assisted humans to work more efficiently with Turborepo.

### Machine readability for agents

We've improved your agents' ability to fetch docs from our site in a number of ways:

- **Markdown responses for agents**: By responding with Markdown (instead of HTML), we help to preserve your context window. No configuration or special instructions are required. Run `curl -sL -H "Accept: text/markdown" https://turborepo.dev/repo/docs` in your terminal to see an example response.
- **.md routes**: You can also visit a markdown version of any documentation page by appending `.md` to a route. For example, try https://turborepo.dev/docs.md.
- **/sitemap.md**: A machine-readable sitemap is available at https://turborepo.dev/sitemap.md, allowing agents to find out what docs exist.
- **Versioned documentation**: Starting with version 2.7.6 of Turborepo, versioned docs are now available on subdomains of `turborepo.dev`. [Visit the 2.7.6 documentation here](https://v2-7-6.turborepo.dev/docs).

### AI interaction for humans

We've improved the docs for AI-assisted humans, too.

- **Chat with the docs**: We've added an "Ask AI" button to the documentation, so you can chat with a bot that knows every bit of the Turborepo documentation.
- **Sample prompts**: The docs now include prompts that you can copy for common tasks. You can paste them into your agent directly, and edit them to fit your needs. For an example, see the sample prompt for [adding Turborepo to an existing repository](/docs/getting-started/add-to-existing-repository).

## `turbo docs` subcommand

You can now search the Turborepo documentation directly from your terminal:

```bash title="Terminal"
# Search the docs for "package configurations"
turbo docs "package configurations"
```

A list of docs that fit your search query will be printed to your terminal.

[Visit the docs to learn more.](/docs/reference/docs)

## Task descriptions

You can now add a `description` field to your task definitions in `turbo.json`:

```json title="turbo.json"
{
  "tasks": {
    "build": {
      "description": "Compiles TypeScript and bundles the application",
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "description": "Runs the test suite with coverage",
      "dependsOn": ["build"]
    }
  }
}
```

Descriptions are purely informational and don't affect task execution. They're useful for providing context for cases like:

- **Onboarding**: Help new team members understand what each task does
- **Documentation**: Keep task purposes documented alongside their configuration
- **AI tools**: Provide context that AI assistants can use to understand your repository

[Visit the docs to learn more.](/docs/reference/configuration#description)

## All changes

<Accordions>

  <Accordion title="Features (18)">

    - feat: Agent Skill ([#11541](https://github.com/vercel/turborepo/pull/11541))
    - feat: Add stream-with-experimental-timestamps UI mode ([#11538](https://github.com/vercel/turborepo/pull/11538))
    - feat: Add loading spinner while AI chat looks up sources ([#11531](https://github.com/vercel/turborepo/pull/11531))
    - feat: Add md tracking for AI usage analytics ([#11526](https://github.com/vercel/turborepo/pull/11526))
    - feat: Add Rust test coverage tracking and reporting ([#11507](https://github.com/vercel/turborepo/pull/11507))
    - feat(turbo-codemod): Add update-versioned-schema-json transformer ([#11502](https://github.com/vercel/turborepo/pull/11502))
    - feat(docs): Add version warning for old docs subdomains ([#11495](https://github.com/vercel/turborepo/pull/11495))
    - feat(docs): Implement two-stage chat ([#11493](https://github.com/vercel/turborepo/pull/11493))
    - feat: Add docs subcommand for searching documentation ([#11490](https://github.com/vercel/turborepo/pull/11490))
    - feat: Add `errorsOnlyShowHash` future flag ([#11486](https://github.com/vercel/turborepo/pull/11486))
    - feat(docs): Add search icon to mobile header ([#11483](https://github.com/vercel/turborepo/pull/11483))
    - feat(turbo-json): Add optional description field to task definitions ([#11447](https://github.com/vercel/turborepo/pull/11447))
    - feat(ci): Add versioned docs aliasing to release workflow ([#11446](https://github.com/vercel/turborepo/pull/11446))
    - feat: Add Rust-based schema and TypeScript generation ([#11429](https://github.com/vercel/turborepo/pull/11429))
    - feat: Git worktree support ([#11416](https://github.com/vercel/turborepo/pull/11416))
    - feat: Extract turborepo-task-hash crate from turborepo-lib ([#11334](https://github.com/vercel/turborepo/pull/11334))
    - feat: Add Rust-based integration tests with CI workflow ([#11333](https://github.com/vercel/turborepo/pull/11333))
    - feat(query): Provide query for external dependencies ([#9929](https://github.com/vercel/turborepo/pull/9929))

  </Accordion>

  <Accordion title="Fixes (50)">

    - fix: Move md tracking to middleware for static optimization ([#11535](https://github.com/vercel/turborepo/pull/11535))
    - fix(docs): Update "Edit this page on GitHub" link to new content path ([#11534](https://github.com/vercel/turborepo/pull/11534))
    - fix: Add turbo-site label to feedback submissions ([#11536](https://github.com/vercel/turborepo/pull/11536))
    - fix: Use container queries for navbar to handle AI chat panel ([#11532](https://github.com/vercel/turborepo/pull/11532))
    - fix: Sync favicon to browser theme preference on initial load ([#11518](https://github.com/vercel/turborepo/pull/11518))
    - fix: Make showcase page logos theme-aware, grayscale ([#11517](https://github.com/vercel/turborepo/pull/11517))
    - fix: Fix AI chat not opening on home page ([#11514](https://github.com/vercel/turborepo/pull/11514))
    - fix(scope): Don't inject package name when user provides directory filter ([#11500](https://github.com/vercel/turborepo/pull/11500))
    - fix: Replace execSync with execFileSync for oxfmt ([#11463](https://github.com/vercel/turborepo/pull/11463))
    - fix(docs): Cancel active stream when clearing chat ([#11494](https://github.com/vercel/turborepo/pull/11494))
    - fix(tui): Enable mouse capture for all terminals to restore scroll functionality ([#11487](https://github.com/vercel/turborepo/pull/11487))
    - fix(docs): Fix mobile hamburger menu not opening ([#11482](https://github.com/vercel/turborepo/pull/11482))
    - fix: Remove root app package requirement for polyrepo support ([#11478](https://github.com/vercel/turborepo/pull/11478))
    - fix: Improve behavior for OOM-killed tasks ([#11477](https://github.com/vercel/turborepo/pull/11477))
    - fix(ci): Fix release workflow Vercel domain matching and docs alias ([#11469](https://github.com/vercel/turborepo/pull/11469))
    - fix(ci): Update release workflow for Vercel domain change and webhook ([#11467](https://github.com/vercel/turborepo/pull/11467))
    - fix(ci): Add project flag and show errors in versioned docs aliasing ([#11459](https://github.com/vercel/turborepo/pull/11459))
    - fix(docs): Allow search engine indexing on production domain ([#11456](https://github.com/vercel/turborepo/pull/11456))
    - fix(docs): Clean up markdown output for LLM content negotiation ([#11452](https://github.com/vercel/turborepo/pull/11452))
    - fix(ci): Use base SHA for production deployment lookup in versioned docs aliasing ([#11450](https://github.com/vercel/turborepo/pull/11450))
    - fix(ci): Filter for production deployment in versioned docs aliasing ([#11449](https://github.com/vercel/turborepo/pull/11449))
    - fix(tui): Only call `DisableMouseCapture` on Windows if mouse capture was enabled ([#11444](https://github.com/vercel/turborepo/pull/11444))
    - fix(scope): Make package inference deterministic for subdirectory filters ([#11432](https://github.com/vercel/turborepo/pull/11432))
    - fix(docs): Fix markdown content negotiation matcher ([#11425](https://github.com/vercel/turborepo/pull/11425))
    - fix(tui): Properly disable mouse mode on exit and panic ([#11418](https://github.com/vercel/turborepo/pull/11418))
    - fix(docs): Make mobile menu scrollable on small viewports ([#11422](https://github.com/vercel/turborepo/pull/11422))
    - fix(docs): OpenAPI docs generation with CI drift detection ([#11424](https://github.com/vercel/turborepo/pull/11424))
    - fix(docs): Exclude schema.json paths from middleware matcher ([#11420](https://github.com/vercel/turborepo/pull/11420))
    - fix(example): Remove @expo/webpack-config from with-react-native-web ([#11408](https://github.com/vercel/turborepo/pull/11408))
    - fix(ui): Fix text selection when TUI sidebar is hidden ([#11405](https://github.com/vercel/turborepo/pull/11405))
    - fix: Normalize workspace globs with leading `./` ([#11403](https://github.com/vercel/turborepo/pull/11403))
    - fix: Prevent infinite loop in `pnpm turbo` script and update docs ([#11400](https://github.com/vercel/turborepo/pull/11400))
    - fix: Update outdated packages to remove node/nest deprecation warning ([#11395](https://github.com/vercel/turborepo/pull/11395))
    - fix: Validate root and temp directory paths in download function ([#11311](https://github.com/vercel/turborepo/pull/11311))
    - fix(turbo-utils): Add proxy support to fetch requests ([#11389](https://github.com/vercel/turborepo/pull/11389))
    - fix(create-turbo): Lowercase bun label for consistency ([#11388](https://github.com/vercel/turborepo/pull/11388))
    - fix(create-turbo): Prevent hang when using bun package manager ([#11386](https://github.com/vercel/turborepo/pull/11386))
    - fix: Support file watching for non-root volumes on MacOS ([#11363](https://github.com/vercel/turborepo/pull/11363))
    - fix: Show TUI when using `--output-logs=errors-only|none` ([#11382](https://github.com/vercel/turborepo/pull/11382))
    - fix(ci): Prevent Test Summary job from hanging when integration tests are skipped ([#11316](https://github.com/vercel/turborepo/pull/11316))
    - fix(bun): Add GitHub/git packages ([#11268](https://github.com/vercel/turborepo/pull/11268))
    - fix: Transit nodes in Devtools ([#11307](https://github.com/vercel/turborepo/pull/11307))
    - fix: Don't flash TUI on a >>> FULL TURBO ([#11306](https://github.com/vercel/turborepo/pull/11306))
    - fix: Exclude framework-inferred env vars with wildcards ([#11303](https://github.com/vercel/turborepo/pull/11303))
    - fix(create-turbo): Loader UI states ([#11300](https://github.com/vercel/turborepo/pull/11300))
    - fix: Use newline for separator in misuse text ([#10834](https://github.com/vercel/turborepo/pull/10834))
    - fix: Correct version mismatch causing noUpdateNotifier to fail ([#11133](https://github.com/vercel/turborepo/pull/11133))
    - fix: Typo in example with-solid README.md description ([#11287](https://github.com/vercel/turborepo/pull/11287))
    - fix: Overly aggressive path checking in microfrontends loading ([#11286](https://github.com/vercel/turborepo/pull/11286))
    - fix: Correctly validate workspace root as package ([#11284](https://github.com/vercel/turborepo/pull/11284))

  </Accordion>

  <Accordion title="Documentation (14)">

    - docs: Update $schema recommendation to use versioned subdomain ([#11519](https://github.com/vercel/turborepo/pull/11519))
    - docs: Add sitemap.md and link from all docs pages ([#11515](https://github.com/vercel/turborepo/pull/11515))
    - docs: Add update-versioned-schema-json codemod documentation ([#11513](https://github.com/vercel/turborepo/pull/11513))
    - docs: Add READMEs for all Rust crates ([#11503](https://github.com/vercel/turborepo/pull/11503))
    - docs: Show 'Searching sources...' loading state in AI chat ([#11496](https://github.com/vercel/turborepo/pull/11496))
    - docs: Block search engine indexing on subdomains ([#11455](https://github.com/vercel/turborepo/pull/11455))
    - docs(fix): Add loading state after sources load in AI chat ([#11442](https://github.com/vercel/turborepo/pull/11442))
    - docs: Fix OpenAPI spec ([#11421](https://github.com/vercel/turborepo/pull/11421))
    - docs: Exclude sitemap.xml from middleware to prevent i18n rewrite ([#11419](https://github.com/vercel/turborepo/pull/11419))
    - docs: New site ([#11415](https://github.com/vercel/turborepo/pull/11415))
    - docs: Add AGENTS.md and remove .cursor rules ([#11401](https://github.com/vercel/turborepo/pull/11401))
    - docs: Add Oxc (oxlint, oxfmt) guide ([#11398](https://github.com/vercel/turborepo/pull/11398))
    - docs: Add `dependsOn` to lint task for proper cache invalidation ([#11384](https://github.com/vercel/turborepo/pull/11384))
    - docs: Release post for 2.7 ([#11272](https://github.com/vercel/turborepo/pull/11272))

  </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew) and [Tom](https://github.com/tknickman).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](https://turborepo.dev/docs/community).

We also thank everyone who contributed to this release of Turborepo: @claycurry, @Palid, @leos, @mdlawson, @richhaines, @msebi, @varmac231, and @wantop1.

---

### Apps Docs Content Blog 2 9 (`apps/docs/content/blog/2-9.mdx`)

---
title: Turborepo 2.9
date: 2026/03/25
description: "Up to 96% faster, `turbo query` is stable, easier adoption in large repos, deprecations to prepare for 3.0, and more"
product: turborepo
type: overview
summary: Release notes for Turborepo 2.9 featuring major performance improvements, `turbo query` graduating to stable, OpenTelemetry support, and structured logging.
tag: "web development"
---

import { Authors } from "@/components/blog/authors";
import { Callout } from "@/components/geistdocs/callout";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Date } from "@/components/blog/date";
import { Accordion, Accordions } from "@/components/geistdocs/accordion";

# Turborepo 2.9

<Date>Monday, March 30th, 2026</Date>

<Authors authors={["anthonyshew"]} />

Turborepo 2.9 concentrates on quality, including improvements for performance, capability, and simplifying adoption paths:

- [**Faster Time to First Task**](#time-to-first-task-improved-up-to-96): Up to 96% improvement, scaling with repository size and complexity
- [**`turbo query` is now stable**](#turbo-query-is-now-stable): Query your monorepo with GraphQL or shorthands like `turbo query affected`
- [**Easier adoption for large repos**](#easier-adoption-for-large-repositories): Circular package dependencies no longer block your Turborepo adoption
- [**OpenTelemetry (Experimental)**](#opentelemetry-experimental): Send task metrics to any OTLP-compatible observability backend
- [**Structured logging (Experimental)**](#structured-logging-experimental): Machine-readable JSON output with `--json` and `--log-file`
- [**Future Flags and deprecations**](#future-flags-and-deprecations): Prepare early for 3.0 using pre-existing migration paths

Additionally, we've closed 141 Issues since Turborepo 2.8, addressing 305 👍 reactions, reducing our total open Issue count by 70%.

---

Upgrade today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Use the automated upgrade CLI
pnpm dlx @turbo/codemod migrate

# Start a new repository
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Use the automated upgrade CLI
yarn dlx @turbo/codemod migrate

# Start a new repository
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Use the automated upgrade CLI
npx @turbo/codemod migrate

# Start a new repository
npx create-turbo@latest
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Use the automated upgrade CLI
bunx @turbo/codemod migrate

# Start a new repository
bunx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

Install or update your [Turborepo Agent Skills](/docs/guides/ai#agent-skill):

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Install the Turborepo Agent Skill
pnpm dlx skills add vercel/turborepo

# Update the Turborepo Agent Skill
pnpm dlx skills update vercel/turborepo
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Install the Turborepo Agent Skill
yarn dlx skills add vercel/turborepo

# Update the Turborepo Agent Skill
yarn dlx skills update vercel/turborepo
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Install the Turborepo Agent Skill
npx skills add vercel/turborepo

# Update the Turborepo Agent Skill
npx skills update vercel/turborepo
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Install the Turborepo Agent Skill
bunx skills add vercel/turborepo

# Update the Turborepo Agent Skill
bunx skills update vercel/turborepo
```

</Tab>

</PackageManagerTabs>

---

## Time to First Task improved up to 96%

Turborepo's most important job is to schedule your monorepo's tasks to be as fast as possible. Whenever you use `turbo run`, our first step is to analyze your monorepo's structure and scripts to create a graph of your tasks. The [Task Graph](/docs/core-concepts/package-and-task-graph#task-graph) describes what tasks depend on each other, so we know how to run and cache the work in your repository.

Once we're done creating your Task Graph, we begin executing your tasks. "Time to First Task" is our name for the time between when you invoke `turbo run` and when the first script in your monorepo begins executing. In general, Time to First Task represents Turborepo's overhead in your monorepo, and we've made it faster in this release.

<div
  className="not-prose my-8 rounded-lg border border-[var(--ds-gray-400)] overflow-hidden"
  role="figure"
  aria-label="Time to First Task comparison showing improvements"
>
  <div className="py-0 pr-3 pl-4 rounded-t-md border-b border-[var(--ds-gray-400)] h-10 flex items-center bg-[var(--ds-background-200)]">
    <span className="text-sm font-medium text-[var(--ds-gray-1000)]">
      Time to First Task (compared to 2.8.0)
    </span>
  </div>
  <div className="p-4 flex flex-col gap-4 bg-[var(--ds-background-100)]">
    <div>
      <div className="flex justify-between items-baseline mb-2">
        <span className="text-sm text-[var(--ds-gray-1000)]">
          Vercel's backend monorepo (1037 packages)
        </span>
        <span
          className="text-xs font-semibold"
          style={{ color: "var(--ds-blue-700)" }}
        >
          91% faster
        </span>
      </div>
      <div
        className="flex flex-col gap-1.5"
        role="group"
        aria-label="Vercel's backend monorepo (1037 packages)"
      >
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            Before
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={100}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="Before: 8.1 seconds"
          >
            <div
              className="w-full bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                8.1s
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            8.1s
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            After
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={9}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="After: 716 milliseconds"
          >
            <div
              className="w-[9%] rounded h-full"
              style={{ backgroundColor: "var(--ds-blue-700)" }}
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                716ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            716ms
          </span>
        </div>
      </div>
    </div>
    <div className="border-t border-[var(--ds-gray-400)] pt-4">
      <div className="flex justify-between items-baseline mb-2">
        <span className="text-sm text-[var(--ds-gray-1000)]">
          Vercel's frontend monorepo (132 packages)
        </span>
        <span
          className="text-xs font-semibold"
          style={{ color: "var(--ds-blue-700)" }}
        >
          81% faster
        </span>
      </div>
      <div
        className="flex flex-col gap-1.5"
        role="group"
        aria-label="Vercel's frontend monorepo (132 packages)"
      >
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            Before
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={100}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="Before: 1.875 seconds"
          >
            <div
              className="w-full bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                1.9s
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            1.9s
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            After
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={19}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="After: 361 milliseconds"
          >
            <div
              className="w-[19%] rounded h-full"
              style={{ backgroundColor: "var(--ds-blue-700)" }}
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                361ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            361ms
          </span>
        </div>
      </div>
    </div>
    <div className="border-t border-[var(--ds-gray-400)] pt-4">
      <div className="flex justify-between items-baseline mb-2">
        <span className="text-sm text-[var(--ds-gray-1000)]">
          `create-turbo` (6 packages)
        </span>
        <span
          className="text-xs font-semibold"
          style={{ color: "var(--ds-blue-700)" }}
        >
          80% faster
        </span>
      </div>
      <div
        className="flex flex-col gap-1.5"
        role="group"
        aria-label="create-turbo (6 packages)"
      >
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            Before
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={100}
            aria-valuemin={0}
            aria-valuemax={100}
            aria-label="Before: 676 milliseconds"
          >
            <div
              className="w-full bg-[var(--ds-gray-600)] rounded h-full"
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                676ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            676ms
          </span>
        </div>
        <div className="flex items-center gap-3">
          <span className="text-xs text-[var(--ds-gray-900)] w-12 shrink-0">
            After
          </span>
          <div
            className="flex-1 bg-[var(--ds-gray-200)] rounded h-5 relative"
            role="progressbar"
            aria-valuenow={20}
            aria-valuemin={0}
            aria-label="After: 132 milliseconds"
          >
            <div
              className="w-[20%] rounded h-full"
              style={{ backgroundColor: "var(--ds-blue-700)" }}
              aria-hidden="true"
            />
            <div className="absolute inset-0 flex items-center px-2">
              <span className="text-xs font-medium text-white sm:inline hidden">
                132ms
              </span>
            </div>
          </div>
          <span className="text-xs font-medium text-[var(--ds-gray-1000)] w-16 shrink-0 text-right sm:hidden">
            132ms
          </span>
        </div>
      </div>
    </div>
    <span className="block text-xs text-[var(--ds-gray-900)] mt-3">
      Benchmarked on Apple M4 Max, 36 GB RAM, macOS 15.7.1
    </span>
  </div>
</div>

The performance boost you see will depend on the size and complexity of your repository - but we expect **dramatic** improvement for all Turborepos. We've tested these improvements across many open and closed source Turborepos, and the largest performance upgrade we saw was 96%.

For a technical deep dive on how we accomplished this, [read our post on the Vercel blog](https://vercel.com/blog/making-turborepo-ninety-six-percent-faster-with-agents-sandboxes-and-humans).

## `turbo query` is now stable

[`turbo query`](/docs/reference/query) has graduated from Experimental status to Stable. Originally introduced in Turborepo 2.2, `turbo query` lets you run GraphQL queries against your monorepo's Package and Task Graphs.

```bash title="Terminal"
# Open the GraphiQL playground
turbo query

# Run a query inline
turbo query "{ packages { items { name } } }"

# Run a query from a file
turbo query --file=my-query.gql
```

This feature lets you quickly answer questions like:

- "How many packages are in this repository?"
- "How many of our applications depend on our `@repo/ui` package?"
- "Why does changing this file result in cache misses in our `web` application?"

And much more. We've also seen that coding agents are incredibly adept at writing queries to extract deep insights from Turborepo's knowledge of your repo, especially after putting the GraphQL schema into their context using [`turbo query --schema`](/docs/reference/query#--schema).

We're also introducing a few shorthands so you don't have to write verbose GraphQL queries to answer your most common questions.

### `turbo query affected`

The `turbo query affected` shorthand checks which packages and tasks are affected by code changes in your repository. The command outputs structured JSON data that you can use to build flexible CI pipelines.

```bash title="Terminal"
# Get all tasks affected by source code changes
turbo query affected

# Get `build` tasks affected by source code changes
turbo query affected --tasks build

# Get all packages affected by source code changes
turbo query affected --packages
```

Additionally, we encourage you to use this primitive to replace your existing usage of [`turbo-ignore`](/docs/reference/turbo-ignore), which is now deprecated. See [the migration guide](/docs/reference/query#flag-mapping) to learn more.

### `turbo query ls`

The `turbo query ls` shorthand lists packages and some useful details about them. You can also drill into a specific package to see its dependencies and tasks.

```bash title="Terminal"
# List all packages
turbo query ls

# Get details for a specific package
turbo query ls web

# List only affected packages
turbo query ls --affected

# Filter packages using selectors
turbo query ls --filter=./apps/*
```

By default, this command pretty prints for easier readability. You can also use `--output=json` for machine-readable data.

[Visit the `turbo query` documentation](/docs/reference/query) to learn more.

## Easier adoption for large repositories

Circular package dependencies are a common reality in large monorepos. While they come with significant drawbacks, they happen. The example below shows how easily packages can mutually depend on each other.

<Tabs items={["UI package", "Utilities package"]}>

<Tab value="UI package">

```json title="./packages/ui/package.json"
{
  "name": "@repo/ui",
  "dependencies": {
    "@repo/utils": "workspace:*"
  }
}
```

</Tab>

<Tab value="Utilities package">

```json title="./packages/utils/package.json"
{
  "name": "@repo/utils",
  "dependencies": {
    "@repo/ui": "workspace:*"
  }
}
```

</Tab>

</Tabs>

Previously, Turborepo would exit with an error when it detected a cycle in your package dependency graph.
This is because Turborepo needs a [Directed Acyclic Graph](https://en.wikipedia.org/wiki/Directed_acyclic_graph) to operate on - but Turborepo executes the [Task Graph](/docs/core-concepts/package-and-task-graph#task-graph), not the [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph). That's a subtle mismatch in what Turborepo was validating, and _what Turborepo actually needs to work_.

Starting with this release, Turborepo handles Package Graph cycles more gracefully. Instead of validating your Package Graph, Turborepo now validates your Task Graph.

In a monorepo with a Package Graph cycle like the example above:

```json title="./turbo.json"
{
  "tasks": {
    // Works, since there are no task dependencies
    // Task Graph cycles are impossible
    "simple-task": {},
    // Errors, since there's a Task Graph cycle
    "build": { "dependsOn": ["^build"] }
  }
}
```

In practice, this makes it much easier to incrementally adopt Turborepo on a task-by-task basis. You can slowly build up your Task Graph while unwinding the cycles in your Package Graph at your own pace.

## OpenTelemetry (Experimental)

You can now send Turborepo build metrics to any [OTLP-compatible](https://opentelemetry.io/) observability backend like Grafana, Datadog, or Honeycomb.

Enable it with [the `experimentalObservability` Future Flag](/docs/reference/configuration#experimentalobservability) in your `turbo.json`:

```json title="turbo.json"
{
  "futureFlags": { "experimentalObservability": true },
  "experimentalObservability": {
    "otel": {
      "enabled": true,
      "endpoint": "http://otel-collector.example.com:4317",
      "protocol": "grpc"
    }
  }
}
```

Turborepo will emit metrics like `turbo.run.duration_ms`, `turbo.run.tasks.cached`, and `turbo.run.tasks.failed` to your collector.

To try it out locally, use:

```bash title="Terminal"
npx create-turbo@latest -e with-otel
```

Follow the README for a Docker Compose setup with an OTel Collector and pre-configured dashboards.

To learn more about the experimental native OTel collector, [visit the documentation](/docs/reference/configuration#experimentalobservability).

## Structured logging (Experimental)

Turborepo now supports machine-readable JSON output for programmatic consumption.

### `--json`

Stream all output to the terminal as newline-delimited JSON (NDJSON):

```bash title="Terminal"
turbo run build --json
```

Each line is a JSON object with a consistent schema:

```json
{
  "timestamp": 1710000000000,
  "source": "web#build",
  "level": "stdout",
  "text": "Compiled successfully"
}
```

### `--log-file`

Write structured logs to a file while keeping normal terminal output:

```bash title="Terminal"
# Log to .turbo/logs/<epoch-millis>.json
turbo run build --log-file

# Or specify a custom path
turbo run build --log-file=./build-log.json
```

These two flags can also be combined, like `turbo run lint --json --log-file=logs.json`. [Visit the documentation](/docs/reference/run#--json) to learn more.

## Future Flags and deprecations

We're preparing Turborepo's API surface for 3.0 with [Future Flags](/docs/reference/configuration#futureflags) and deprecations. Future Flags let you opt into 3.0 behaviors now, giving you a gradual migration path instead of a big-bang upgrade. Our goal is for you to be able to upgrade from your 2.9+ codebase to 3.0 with a PR that deletes the Future Flags and increments your version - no functional change.

### Future Flags

Each Future Flag can be adopted at any time, individually, and at your own pace.

| Flag                                                                                   | Description                                                                                                                       |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| [`globalConfiguration`](/docs/reference/configuration#globalconfiguration)             | Moves top-level keys into a [`global`](/docs/reference/configuration#global) key.                                                 |
| [`affectedUsingTaskInputs`](/docs/reference/configuration#affectedusingtaskinputs)     | `--affected` selects at task-level granularity using `inputs` globs instead of selecting all tasks in a changed package.          |
| [`watchUsingTaskInputs`](/docs/reference/configuration#watchusingtaskinputs)           | `turbo watch` re-runs only tasks whose `inputs` match changed files instead of all tasks in the package.                          |
| [`filterUsingTasks`](/docs/reference/configuration#filterusingtasks)                   | `--filter` resolves at the task level, using `inputs` globs for git-range filters and traversing the Task Graph for `...` syntax. |
| [`pruneIncludesGlobalFiles`](/docs/reference/configuration#pruneincludesglobalfiles)   | `turbo prune` copies files matching `globalDependencies` globs into the output directory.                                         |
| [`errorsOnlyShowHash`](/docs/reference/configuration#errorsonlyshowhash)               | Shows task hashes when using `outputLogs: "errors-only"` for better visibility into running tasks.                                |
| [`longerSignatureKey`](/docs/reference/configuration#longersignaturekey)               | Enforces a minimum 32-byte `TURBO_REMOTE_CACHE_SIGNATURE_KEY` to prevent weak HMAC signatures.                                    |
| [`experimentalObservability`](/docs/reference/configuration#experimentalobservability) | Gates the [OpenTelemetry support](#opentelemetry-experimental) described above.                                                   |

### Deprecations

The following features are deprecated and will show warnings when used. Each deprecation has a corresponding replacement that you can use ahead of 3.0.

| Deprecated                                                                                                                       | Replacement                                                                                                               |
| -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| [`turbo-ignore`](/docs/reference/turbo-ignore)                                                                                   | [`turbo query affected`](/docs/reference/query#affected)                                                                  |
| [`turbo scan`](/docs/reference/scan)                                                                                             | None. Functionality is now obsolete.                                                                                      |
| [`--parallel`](/docs/reference/run#--parallel)                                                                                   | [`persistent`](/docs/reference/configuration#persistent) and [`with`](/docs/reference/configuration#with) in `turbo.json` |
| [`--no-cache`](/docs/reference/run#--no-cache)                                                                                   | [`--cache=local:r,remote:r`](/docs/reference/run#--cache-options)                                                         |
| [`TURBO_REMOTE_ONLY`](/docs/reference/system-environment-variables#turbo_remote_only) environment variable                       | [`--cache=remote:rw`](/docs/reference/run#--cache-options)                                                                |
| [`--remote-only`](/docs/reference/run#--remote-only)                                                                             | [`--cache=remote:rw`](/docs/reference/run#--cache-options)                                                                |
| [`TURBO_REMOTE_CACHE_READ_ONLY`](/docs/reference/system-environment-variables#turbo_remote_cache_read_only) environment variable | [`--cache=local:rw,remote:r`](/docs/reference/run#--cache-options)                                                        |
| `--remote-cache-read-only`                                                                                                       | [`--cache=local:rw,remote:r`](/docs/reference/run#--cache-options)                                                        |
| `TURBO_DAEMON` environment variable                                                                                              | Daemon no longer used                                                                                                     |
| [`--daemon` / `--no-daemon`](/docs/reference/run#--daemon-and---no-daemon)                                                       | Daemon no longer used                                                                                                     |
| [`daemon`](/docs/reference/configuration#daemon) in `turbo.json`                                                                 | Daemon no longer used                                                                                                     |
| [`--graph`](/docs/reference/run#--graph-file-name) with `.png`/`.jpg`/`.pdf`                                                     | `.svg`, `.html`, `.mermaid`, or `.dot`                                                                                    |
| [`--graph`](/docs/reference/run#--graph-file-name) with `.json`                                                                  | [`turbo query`](/docs/reference/query)                                                                                    |
| `--scope` for [`turbo prune`](/docs/reference/prune)                                                                             | Positional args (e.g. [`turbo prune web`](/docs/reference/prune))                                                         |

All deprecated features will continue to work until a future major version. We recommend migrating at your convenience to prepare for Turborepo 3.0.

## All changes

<Accordions>

  <Accordion title="Features (44)">

    - feat: Accept `experimentalCI` key in turbo.json task config ([#12480](https://github.com/vercel/turborepo/pull/12480))
    - feat: Add `packagesFromLockfile()` NAPI binding to `@turbo/repository` ([#12454](https://github.com/vercel/turborepo/pull/12454))
    - feat: Send git SHA and dirty hash to remote cache ([#12427](https://github.com/vercel/turborepo/pull/12427))
    - feat: Rework `turbo ls` to use query internals and add `turbo query ls` shorthand ([#12424](https://github.com/vercel/turborepo/pull/12424))
    - feat: Add experimental structured logging with `--json` and `--log-file` flags ([#12405](https://github.com/vercel/turborepo/pull/12405))
    - feat: Add `global` configuration key behind `futureFlags.globalConfiguration` ([#12399](https://github.com/vercel/turborepo/pull/12399))
    - feat: Deprecate `turbo-ignore` in favor of `turbo query affected` ([#12382](https://github.com/vercel/turborepo/pull/12382))
    - feat: Add `filterUsingTasks` future flag for task-level `--filter` resolution ([#12363](https://github.com/vercel/turborepo/pull/12363))
    - feat: Include `globalDependencies` in prune behind Future Flag ([#12360](https://github.com/vercel/turborepo/pull/12360))
    - feat: Deprecate `--parallel` flag ([#12357](https://github.com/vercel/turborepo/pull/12357))
    - feat: Deprecate graphviz-dependent `--graph` formats, add native SVG rendering ([#12344](https://github.com/vercel/turborepo/pull/12344))
    - feat: Route child process bytes through TaskHandle with sink-owned prefix rendering ([#12343](https://github.com/vercel/turborepo/pull/12343))
    - feat: Add `GroupingLayer` for per-task output buffering ([#12334](https://github.com/vercel/turborepo/pull/12334))
    - feat: Extend `LogSink` with task output and grouping support ([#12328](https://github.com/vercel/turborepo/pull/12328))
    - feat: Allow cyclic package graphs, validate only at task graph level ([#12327](https://github.com/vercel/turborepo/pull/12327))
    - feat: Show richer remote cache status in run prelude ([#12314](https://github.com/vercel/turborepo/pull/12314))
    - feat: Route user-facing warnings through turborepo-log and suppress tracing stderr in TUI mode ([#12299](https://github.com/vercel/turborepo/pull/12299))
    - feat: Initialize `turborepo-log` in `turbo watch` ([#12298](https://github.com/vercel/turborepo/pull/12298))
    - feat: Publish platform binaries under @turbo/ scoped packages ([#12296](https://github.com/vercel/turborepo/pull/12296))
    - feat: Add TuiSink to route log events into the TUI ([#12294](https://github.com/vercel/turborepo/pull/12294))
    - feat: Surface cache SCM metadata in Run Summary ([#12291](https://github.com/vercel/turborepo/pull/12291))
    - feat: Wire up turborepo-log with TerminalSink and convert first warning ([#12289](https://github.com/vercel/turborepo/pull/12289))
    - feat: Add git SHA and dirty hash to cache metadata ([#12288](https://github.com/vercel/turborepo/pull/12288))
    - feat: Add `turbo query affected` CLI shorthand ([#12283](https://github.com/vercel/turborepo/pull/12283))
    - feat: Use task graph for `watch` ([#12275](https://github.com/vercel/turborepo/pull/12275))
    - feat: Deprecate `--scope` flag for `turbo prune` ([#12269](https://github.com/vercel/turborepo/pull/12269))
    - feat: Send `x-ai-agent` header on all Vercel API requests ([#12261](https://github.com/vercel/turborepo/pull/12261))
    - feat: Add Node.js version to `turbo info` output ([#12260](https://github.com/vercel/turborepo/pull/12260))
    - feat: Add `affectedUsingTaskInputs` future flag for task-level `--affected` detection ([#12247](https://github.com/vercel/turborepo/pull/12247))
    - feat: Add `affectedTasks` query for task-level change detection ([#12215](https://github.com/vercel/turborepo/pull/12215))
    - feat: Remove daemon from watch mode ([#12175](https://github.com/vercel/turborepo/pull/12175))
    - feat: Include version, platform, and CPU count in Chrome trace profiles ([#12166](https://github.com/vercel/turborepo/pull/12166))
    - feat: Instrument post-hashing setup phase for trace visibility ([#12160](https://github.com/vercel/turborepo/pull/12160))
    - feat: Add AI coding agent detection telemetry ([#12159](https://github.com/vercel/turborepo/pull/12159))
    - feat: Add `runAttributes` config to OTel metrics for cardinality control ([#12144](https://github.com/vercel/turborepo/pull/12144))
    - feat: Add `futureFlags.longerSignatureKey` to enforce minimum HMAC key length ([#12142](https://github.com/vercel/turborepo/pull/12142))
    - feat: Add with-otel example with pre-configured Grafana dashboard ([#12043](https://github.com/vercel/turborepo/pull/12043))
    - feat: Remove daemon from `turbo run`, deprecate daemon flags and config ([#11910](https://github.com/vercel/turborepo/pull/11910))
    - feat: Add end-to-end lockfile pruning tests and fix bun pruning bugs ([#11894](https://github.com/vercel/turborepo/pull/11894))
    - feat: Make `--profile` and `--anon-profile` filename optional ([#11883](https://github.com/vercel/turborepo/pull/11883))
    - feat: Generate LLM-friendly markdown alongside --profile trace output ([#11880](https://github.com/vercel/turborepo/pull/11880))
    - feat: Compile @turbo/gen to standalone binary via `bun build --compile` ([#11825](https://github.com/vercel/turborepo/pull/11825))
    - feat: Add security gate to release pipeline ([#11821](https://github.com/vercel/turborepo/pull/11821))
    - feat: Add experimentalObservability with an OTel backend ([#11130](https://github.com/vercel/turborepo/pull/11130))

  </Accordion>

  <Accordion title="Performance (67)">

    - perf: Replace subprocess repo index with in-process `gix-index` ([#12339](https://github.com/vercel/turborepo/pull/12339))
    - perf: Generate cache restore manifest at save time to eliminate first-hit penalty ([#12213](https://github.com/vercel/turborepo/pull/12213))
    - perf: Skip redundant file writes during cache restore using manifests ([#12209](https://github.com/vercel/turborepo/pull/12209))
    - perf: Two-phase HTTP client init to avoid macOS Keychain blocking ([#12208](https://github.com/vercel/turborepo/pull/12208))
    - perf: Race parallel git subprocesses against filesystem walk for optimal index construction ([#12206](https://github.com/vercel/turborepo/pull/12206))
    - perf: Decouple filesystem walk from git index construction ([#12204](https://github.com/vercel/turborepo/pull/12204))
    - perf: Overlap untracked file walk with builder setup ([#12201](https://github.com/vercel/turborepo/pull/12201))
    - perf: Reuse input hashes and trim pnpm lockfile allocations ([#12199](https://github.com/vercel/turborepo/pull/12199))
    - perf: Scope Repo Index Untracked Discovery ([#12195](https://github.com/vercel/turborepo/pull/12195))
    - perf: Avoid Unconditional HTTP Client Warmup ([#12189](https://github.com/vercel/turborepo/pull/12189))
    - perf: Defer cache save to after callback to unblock dependents sooner ([#12178](https://github.com/vercel/turborepo/pull/12178))
    - perf: Defer SCM task await to overlap with setup work ([#12177](https://github.com/vercel/turborepo/pull/12177))
    - perf: Defer lockfile await until after internal dependency resolution ([#12164](https://github.com/vercel/turborepo/pull/12164))
    - perf: Fire-and-forget telemetry and analytics HTTP flushes on shutdown ([#12162](https://github.com/vercel/turborepo/pull/12162))
    - perf: Skip irrelevant packages when using package#task syntax ([#12135](https://github.com/vercel/turborepo/pull/12135))
    - perf: Disable unused zstd default features to reduce C compilation ([#12107](https://github.com/vercel/turborepo/pull/12107))
    - perf: Replace `git` subprocess in worktree detection with Rust ([#12106](https://github.com/vercel/turborepo/pull/12106))
    - perf: Reduce allocations in file hash computation ([#12102](https://github.com/vercel/turborepo/pull/12102))
    - perf: Replace SWC with oxc for JS/TS parsing ([#12098](https://github.com/vercel/turborepo/pull/12098))
    - perf: Eliminate per-directory stat syscalls in untracked file detection ([#12096](https://github.com/vercel/turborepo/pull/12096))
    - perf: Optimize npm lockfile parser ([#12093](https://github.com/vercel/turborepo/pull/12093))
    - perf: Speed up lockfile test suite ([#12078](https://github.com/vercel/turborepo/pull/12078))
    - perf: Use stack-allocated OidHash in FileHashes and skip expanded hashes on normal runs ([#12065](https://github.com/vercel/turborepo/pull/12065))
    - perf: Stream file contents during hashing to lower memory usage ([#12059](https://github.com/vercel/turborepo/pull/12059))
    - perf: Remove async-graphql from turborepo-lib ([#12017](https://github.com/vercel/turborepo/pull/12017))
    - perf: Remove libgit2/git2 dependency, replace with gix-object ([#12015](https://github.com/vercel/turborepo/pull/12015))
    - perf: Deduplicate petgraph, fixedbitset, and dashmap ([#12011](https://github.com/vercel/turborepo/pull/12011))
    - perf: Extract query module into turborepo-query crate ([#12007](https://github.com/vercel/turborepo/pull/12007))
    - perf: Reduce per-task allocations in visitor dispatch loop ([#11986](https://github.com/vercel/turborepo/pull/11986))
    - perf: Eliminate redundant syscalls in FSCache fetch and exists ([#11985](https://github.com/vercel/turborepo/pull/11985))
    - perf: Replace heap-allocated String with stack-allocated OidHash for git OIDs ([#11984](https://github.com/vercel/turborepo/pull/11984))
    - perf: Fast path for shallow wildcard glob patterns in workspace discovery ([#11972](https://github.com/vercel/turborepo/pull/11972))
    - perf: Send engine callback before tracker bookkeeping and add tracing spans ([#11970](https://github.com/vercel/turborepo/pull/11970))
    - perf: Parallelize task hash computation across topological waves ([#11969](https://github.com/vercel/turborepo/pull/11969))
    - perf: Defer TLS initialization to a background thread ([#11967](https://github.com/vercel/turborepo/pull/11967))
    - perf: Add more tracing spans into startup path ([#11965](https://github.com/vercel/turborepo/pull/11965))
    - perf: Use `Arc<str>` for task dependency hashes to avoid heap clones ([#11962](https://github.com/vercel/turborepo/pull/11962))
    - perf: Parallelize `turbo run` pre-execution hot path ([#11958](https://github.com/vercel/turborepo/pull/11958))
    - perf: Optimize engine builder, task visitor, and untracked file discovery ([#11956](https://github.com/vercel/turborepo/pull/11956))
    - perf: Resolve literal input paths via stat instead of glob walk ([#11955](https://github.com/vercel/turborepo/pull/11955))
    - perf: Replace `libgit2` git status with `gix-index` for faster file hashing ([#11950](https://github.com/vercel/turborepo/pull/11950))
    - perf: Reduce CPU overhead in `turbo run` hot path ([#11947](https://github.com/vercel/turborepo/pull/11947))
    - perf: Reduce per-package hashing overhead and eliminate SCM subprocesses ([#11942](https://github.com/vercel/turborepo/pull/11942))
    - perf: Replace git subprocesses with `libgit2` and skip unnecessary summary work ([#11938](https://github.com/vercel/turborepo/pull/11938))
    - perf: Reduce git subprocess calls on startup ([#11934](https://github.com/vercel/turborepo/pull/11934))
    - perf: Share HTTP client and improve profile instrumentation ([#11932](https://github.com/vercel/turborepo/pull/11932))
    - perf: Improve `--profile` instrumentation coverage ([#11929](https://github.com/vercel/turborepo/pull/11929))
    - perf: Optimize `turbo run` hotpath with parallelization and reduced allocations ([#11928](https://github.com/vercel/turborepo/pull/11928))
    - perf: Parallelize lockfile parsing with workspace discovery ([#11927](https://github.com/vercel/turborepo/pull/11927))
    - perf: Replace O(N) workspace path lookup with HashMap index in DependencySplitter ([#11922](https://github.com/vercel/turborepo/pull/11922))
    - perf: Cache compiled env wildcard regexes for builtin pass-through patterns ([#11920](https://github.com/vercel/turborepo/pull/11920))
    - perf: Parallelize package.json loading and reduce builder allocations ([#11918](https://github.com/vercel/turborepo/pull/11918))
    - perf: Reduce allocations in SCM hashing, glob preprocessing, and cache lookups ([#11916](https://github.com/vercel/turborepo/pull/11916))
    - perf: Reduce filesystem syscalls in globwalk, SCM hashing, and task scheduling ([#11907](https://github.com/vercel/turborepo/pull/11907))
    - perf: Improve transitive dependency resolution cache sharing across workspaces ([#11903](https://github.com/vercel/turborepo/pull/11903))
    - perf: Deduplicate file hashing and parallelize globwalks ([#11902](https://github.com/vercel/turborepo/pull/11902))
    - perf: Optimize pnpm lockfile transitive closure resolution ([#11898](https://github.com/vercel/turborepo/pull/11898))
    - perf: Pre-compile glob exclusion filter and cache path prefix in file hashing ([#11891](https://github.com/vercel/turborepo/pull/11891))
    - perf: Parallelize and pre-build RepoGitIndex ([#11889](https://github.com/vercel/turborepo/pull/11889))
    - perf: Batch per-package git subprocess calls into repo-wide index ([#11887](https://github.com/vercel/turborepo/pull/11887))
    - perf: Replace O(V³) Floyd-Warshall with O(V+E) DFS in watch mode subgraph creation ([#11878](https://github.com/vercel/turborepo/pull/11878))
    - perf: Replace twox-hash with xxhash-rust and optimize file hashing ([#11874](https://github.com/vercel/turborepo/pull/11874))
    - perf: Optimize hot-path hash computation by avoiding clones and using unstable sorts ([#11872](https://github.com/vercel/turborepo/pull/11872))
    - perf: Replace `git fetch --tags` with `git ls-remote` in release pipeline ([#11794](https://github.com/vercel/turborepo/pull/11794))
    - perf: Replace third-party crates with Rust std lib equivalents ([#11569](https://github.com/vercel/turborepo/pull/11569))
    - perf: Reduce duplicate dependency versions ([#11568](https://github.com/vercel/turborepo/pull/11568))
    - perf: Reduce allocations in globwalk ([#11528](https://github.com/vercel/turborepo/pull/11528))

  </Accordion>

  <Accordion title="Fixes (211)">

    - fix: Follow symlinks during workspace package discovery ([#12489](https://github.com/vercel/turborepo/pull/12489))
    - fix: Replace pre-existing symlinks with directories during cache restore ([#12488](https://github.com/vercel/turborepo/pull/12488))
    - fix: Skip writing unchanged files during slow-path cache restore ([#12484](https://github.com/vercel/turborepo/pull/12484))
    - fix: Prevent pnpm overrides from corrupting resolved peer-dep variants ([#12482](https://github.com/vercel/turborepo/pull/12482))
    - fix: Handle Yarn 2+ in @turbo/codemod install commands ([#12477](https://github.com/vercel/turborepo/pull/12477))
    - fix: Show run summary after TUI exits ([#12471](https://github.com/vercel/turborepo/pull/12471))
    - fix: Remove root package.json from `--affected` global triggers ([#12469](https://github.com/vercel/turborepo/pull/12469))
    - fix: Resolve generator name conflicts across workspaces ([#12467](https://github.com/vercel/turborepo/pull/12467))
    - fix: Missing deps after npm lockfile parsing ([#12464](https://github.com/vercel/turborepo/pull/12464))
    - fix: Support `turbo watch` in single-package workspaces ([#12460](https://github.com/vercel/turborepo/pull/12460))
    - fix: Prevent panic in `turbo watch` with persistent tasks ([#12459](https://github.com/vercel/turborepo/pull/12459))
    - fix: Avoid `setsid()` in PTY spawn to prevent macOS Gatekeeper CPU spikes ([#12452](https://github.com/vercel/turborepo/pull/12452))
    - fix: Resolve turbo watch hang with mixed interruptible persistent tasks ([#12449](https://github.com/vercel/turborepo/pull/12449))
    - fix: Align dry run cache status with normal run by checking caching guards ([#12448](https://github.com/vercel/turborepo/pull/12448))
    - fix: Skip Unix domain sockets and other special files during file hashing ([#12445](https://github.com/vercel/turborepo/pull/12445))
    - fix: Preserve dedupePeers and unknown pnpm lockfile settings ([#12443](https://github.com/vercel/turborepo/pull/12443))
    - fix: Use script-shell=bash for cross-platform with-shell-commands example ([#12436](https://github.com/vercel/turborepo/pull/12436))
    - fix: Upgrade tokio to 1.47.1+ to fix pidfd_reaper panic ([#12431](https://github.com/vercel/turborepo/pull/12431))
    - fix: Prevent horizontal overflow from long inline code on narrow viewports ([#12428](https://github.com/vercel/turborepo/pull/12428))
    - fix: Resolve security vulnerabilities in `tar` and `rustls-webpki` ([#12418](https://github.com/vercel/turborepo/pull/12418))
    - fix: Add NixOS environment variables to default passthroughs ([#12417](https://github.com/vercel/turborepo/pull/12417))
    - fix(eslint-plugin-turbo): Guard against missing tasks/pipeline in forEachTaskDef ([#12411](https://github.com/vercel/turborepo/pull/12411))
    - fix: Strip JSX components from heading anchors and TOC entries ([#12404](https://github.com/vercel/turborepo/pull/12404))
    - fix: Reduce inotify watch count via gitignore-aware directory walking on Linux ([#12398](https://github.com/vercel/turborepo/pull/12398))
    - fix: Prevent `stdin` from being dropped for persistent tasks in stream mode ([#12394](https://github.com/vercel/turborepo/pull/12394))
    - fix: Support legacy unscoped binary package names in Node shim ([#12391](https://github.com/vercel/turborepo/pull/12391))
    - fix: Detect scoped `@turbo/{platform}` packages in local binary resolution ([#12386](https://github.com/vercel/turborepo/pull/12386))
    - fix: Tailored `turbo-ignore` deprecation notice for Vercel users ([#12385](https://github.com/vercel/turborepo/pull/12385))
    - fix: Use previous stable tag for stable release notes ([#12379](https://github.com/vercel/turborepo/pull/12379))
    - fix: Preserve package.json key order during `turbo prune` with pnpm patches ([#12376](https://github.com/vercel/turborepo/pull/12376))
    - fix: Pass `TURBO_*` env vars through to child processes in Strict Mode ([#12372](https://github.com/vercel/turborepo/pull/12372))
    - fix: Fall back to bundled certificates when system cert store is inaccessible ([#12371](https://github.com/vercel/turborepo/pull/12371))
    - fix: Suppress noisy rustls TLS warning on stderr ([#12365](https://github.com/vercel/turborepo/pull/12365))
    - fix: Preserve all bun lockfile overrides during prune ([#12362](https://github.com/vercel/turborepo/pull/12362))
    - fix: Sort uninstalled package managers to bottom of `create-turbo` selection ([#12353](https://github.com/vercel/turborepo/pull/12353))
    - fix: Prevent `$TURBO_DEFAULT$` from matching unrelated root files in affected detection ([#12341](https://github.com/vercel/turborepo/pull/12341))
    - fix: Support private GitHub repos in `turbo gen workspace --copy` ([#12336](https://github.com/vercel/turborepo/pull/12336))
    - fix: Support private GitHub repos in `turbo gen workspace --copy` ([#12333](https://github.com/vercel/turborepo/pull/12333))
    - fix: Stop `add-package-names` codemod from silently renaming existing packages ([#12332](https://github.com/vercel/turborepo/pull/12332))
    - fix: Detect affected tasks with `$TURBO_ROOT$` inputs when using `affectedUsingTaskInputs` ([#12331](https://github.com/vercel/turborepo/pull/12331))
    - fix: Filter phantom tasks from affectedTasks query results ([#12324](https://github.com/vercel/turborepo/pull/12324))
    - fix: Add check:toml to pre-push hook ([#12322](https://github.com/vercel/turborepo/pull/12322))
    - fix: Flush stale mouse tracking events from stdin during TUI cleanup ([#12311](https://github.com/vercel/turborepo/pull/12311))
    - fix: Infer monorepo root in LSP instead of trusting editor `root_uri` ([#12308](https://github.com/vercel/turborepo/pull/12308))
    - fix: Expand directory inputs to `dir/**` in manual SCM and git literal-path optimization ([#12305](https://github.com/vercel/turborepo/pull/12305))
    - fix: Handle parent directory inputs in non-git repos ([#12304](https://github.com/vercel/turborepo/pull/12304))
    - fix: Resolve git diff warning in fresh repos and make SCM state lazy ([#12300](https://github.com/vercel/turborepo/pull/12300))
    - fix: Inline PlopTypes in @turbo/gen to fix implicit any for consumers ([#12292](https://github.com/vercel/turborepo/pull/12292))
    - fix: Ensure `pkg#task` CLI args are always included in filtered packages ([#12287](https://github.com/vercel/turborepo/pull/12287))
    - fix: Sync yarn lockfile before upgrading turbo in examples updater ([#12286](https://github.com/vercel/turborepo/pull/12286))
    - fix: Remove redundant online check from create-turbo ([#12281](https://github.com/vercel/turborepo/pull/12281))
    - fix: Fix non-deterministic hashOfExternalDependencies with Bun lockfiles ([#12279](https://github.com/vercel/turborepo/pull/12279))
    - fix: Replace dns.lookup with https.get for create-turbo online check ([#12277](https://github.com/vercel/turborepo/pull/12277))
    - fix: Initialize TUI terminal in watch mode even when all tasks hit cache ([#12273](https://github.com/vercel/turborepo/pull/12273))
    - fix: Align query affectedTasks with run `--affected` for `$TURBO_ROOT$` inputs ([#12270](https://github.com/vercel/turborepo/pull/12270))
    - fix: Validate task names when `--affected` yields empty package scope ([#12268](https://github.com/vercel/turborepo/pull/12268))
    - fix: Use BTreeMap for bundled_deps in bun PackageIndex ([#12266](https://github.com/vercel/turborepo/pull/12266))
    - fix: Deflake watch_edit_during_build_triggers_rebuild test ([#12263](https://github.com/vercel/turborepo/pull/12263))
    - fix: Improve create-turbo connectivity check and offline error messages ([#12257](https://github.com/vercel/turborepo/pull/12257))
    - fix: Use BTreeMap for deterministic lockfile dependency ordering ([#12254](https://github.com/vercel/turborepo/pull/12254))
    - fix: Cap rayon thread pool and `block_in_place` in tokio to prevent deadlock potential ([#12253](https://github.com/vercel/turborepo/pull/12253))
    - fix: Deflake `watch_rapid_edits_produce_single_rebuild` test ([#12245](https://github.com/vercel/turborepo/pull/12245))
    - fix: Prevent run summary `SendError` panic on shutdown ([#12244](https://github.com/vercel/turborepo/pull/12244))
    - fix: Resolve root-level tasks not executing with //# CLI syntax ([#12242](https://github.com/vercel/turborepo/pull/12242))
    - fix: Remove stale build-gen references from release workflow ([#12241](https://github.com/vercel/turborepo/pull/12241))
    - fix: Guard against missing `pipeline` key in `clean-globs` codemod ([#12235](https://github.com/vercel/turborepo/pull/12235))
    - fix: Prevent tsdown from cleaning @turbo/gen binaries during release ([#12230](https://github.com/vercel/turborepo/pull/12230))
    - fix: Promote nested bun lockfile entries when hoisted version is pruned ([#12228](https://github.com/vercel/turborepo/pull/12228))
    - fix: Remove all remaining pnpm dependency overrides ([#12227](https://github.com/vercel/turborepo/pull/12227))
    - fix: Bump quinn-proto to 0.11.14 to resolve RUSTSEC-2026-0037 ([#12226](https://github.com/vercel/turborepo/pull/12226))
    - fix: Resolve pnpm audit vulnerabilities via dependency bumps ([#12224](https://github.com/vercel/turborepo/pull/12224))
    - fix: Replace Chocolatey with direct download for Windows capnproto setup ([#12222](https://github.com/vercel/turborepo/pull/12222))
    - fix: Resolve pnpm audit vulnerabilities via dependency bumps ([#12220](https://github.com/vercel/turborepo/pull/12220))
    - fix: Use FilterMode enum for root task scoping with exclude-only filters ([#12212](https://github.com/vercel/turborepo/pull/12212))
    - fix: Match `vite` and `@vitejs/plugin-react` versions on example ([#12193](https://github.com/vercel/turborepo/pull/12193))
    - fix: Resolve pnpm catalog: specifiers to workspace dependencies in task graph ([#12185](https://github.com/vercel/turborepo/pull/12185))
    - fix: Add `FORCE_COLOR` and `NO_COLOR` to builtin passthrough env vars ([#12158](https://github.com/vercel/turborepo/pull/12158))
    - fix: Resolve $turbo-get-mfe-port by packageName when application key differs ([#12149](https://github.com/vercel/turborepo/pull/12149))
    - fix: Preserve deeply nested workspace deps during npm lockfile pruning ([#12146](https://github.com/vercel/turborepo/pull/12146))
    - fix: Treat Bun runtime modules as builtins in Boundaries ([#12141](https://github.com/vercel/turborepo/pull/12141))
    - fix: Use delta temporality for OTel metrics export ([#12136](https://github.com/vercel/turborepo/pull/12136))
    - fix: Correct dependency iteration order so `dependencies` takes precedence over `devDependencies` ([#12129](https://github.com/vercel/turborepo/pull/12129))
    - fix: Omit None otel fields during turbo prune serialization ([#12126](https://github.com/vercel/turborepo/pull/12126))
    - fix: Microfrontends merges `with` into root config instead of replacing it ([#12125](https://github.com/vercel/turborepo/pull/12125))
    - fix: Stabilize flaky watch_file_change_reruns_affected_package test ([#12123](https://github.com/vercel/turborepo/pull/12123))
    - fix: Install capnproto on Windows for fork PRs that lack remote cache ([#12121](https://github.com/vercel/turborepo/pull/12121))
    - fix: Install capnproto-dev on Alpine to get capnp compiler binary ([#12115](https://github.com/vercel/turborepo/pull/12115))
    - fix: Build capnproto statically in source build fallback ([#12114](https://github.com/vercel/turborepo/pull/12114))
    - fix: Disable capnproto cache for container builds in library release ([#12113](https://github.com/vercel/turborepo/pull/12113))
    - fix: Skip capnproto cache in container builds to avoid glibc/musl mismatch ([#12112](https://github.com/vercel/turborepo/pull/12112))
    - fix: Handle capnproto installation across all container environments ([#12111](https://github.com/vercel/turborepo/pull/12111))
    - fix: Install capnproto in library release workflow ([#12110](https://github.com/vercel/turborepo/pull/12110))
    - fix: Pre-warm corepack cache to prevent yarn/pnpm tests from hanging ([#12099](https://github.com/vercel/turborepo/pull/12099))
    - fix: Exclude turborepo-repository from JS smoke test in release workflow ([#12097](https://github.com/vercel/turborepo/pull/12097))
    - fix: Prevent lockfile-aware yarn test from hanging on corepack downloads ([#12095](https://github.com/vercel/turborepo/pull/12095))
    - fix: Prevent turbo dev from hanging when daemon file watching fails ([#12091](https://github.com/vercel/turborepo/pull/12091))
    - fix: Prevent yarn integration tests from hanging on corepack prompts ([#12090](https://github.com/vercel/turborepo/pull/12090))
    - fix: Align experimentalObservability on object maps rather than arrays ([#12089](https://github.com/vercel/turborepo/pull/12089))
    - fix: duplicate /signup? in Vercel URL ([#12088](https://github.com/vercel/turborepo/pull/12088))
    - fix: Filter orphaned Yarn packageExtensions entries during lockfile pruning ([#12084](https://github.com/vercel/turborepo/pull/12084))
    - fix: Stop running unnecessary npm install in engines tests ([#12081](https://github.com/vercel/turborepo/pull/12081))
    - fix: Preserve `file:` and `link:` protocol entries in pruned bun lockfile ([#12076](https://github.com/vercel/turborepo/pull/12076))
    - fix: Retain injected workspace package entries during pnpm lockfile pruning ([#12073](https://github.com/vercel/turborepo/pull/12073))
    - fix: Resolve Berry prune failure when resolutions contain patch overrides ([#12069](https://github.com/vercel/turborepo/pull/12069))
    - fix: Support pnpm per-workspace lockfiles in turbo prune ([#12067](https://github.com/vercel/turborepo/pull/12067))
    - fix: Preserve file: protocol entries in pruned yarn v1 lockfile ([#12064](https://github.com/vercel/turborepo/pull/12064))
    - fix: Treat `npm: alias` dependencies as external, not workspace references ([#12061](https://github.com/vercel/turborepo/pull/12061))
    - fix(frameworks): Also check devDependencies when inferring framework in single-package mode ([#12056](https://github.com/vercel/turborepo/pull/12056))
    - fix: Exclude peer dependencies from workspace external dep resolution ([#12050](https://github.com/vercel/turborepo/pull/12050))
    - fix: Address root causes of 9 flaky tests and remove retry workarounds ([#12045](https://github.com/vercel/turborepo/pull/12045))
    - fix: Send OTEL metrics without requiring `--summarize` flag ([#12042](https://github.com/vercel/turborepo/pull/12042))
    - fix: Resolve all lockfile pruning test failures ([#12009](https://github.com/vercel/turborepo/pull/12009))
    - fix: Resolve correct nested package version in bun lockfile pruning ([#12008](https://github.com/vercel/turborepo/pull/12008))
    - fix: Prevent peerDependencies from overwriting concrete dependency specifiers ([#12004](https://github.com/vercel/turborepo/pull/12004))
    - fix: Resolve package-name-shaped tsconfig path aliases ([#11998](https://github.com/vercel/turborepo/pull/11998))
    - fix: Restore daemon client in `RunCache` for `turbo watch` ([#11995](https://github.com/vercel/turborepo/pull/11995))
    - fix: Use versioned schema URLs in Turborepo skill files ([#11994](https://github.com/vercel/turborepo/pull/11994))
    - fix: Add repository field to @turbo/repository package.json ([#11982](https://github.com/vercel/turborepo/pull/11982))
    - fix: Use repo setup-node action in library release package job ([#11981](https://github.com/vercel/turborepo/pull/11981))
    - fix: Resolve git_root to worktree root in linked worktrees ([#11974](https://github.com/vercel/turborepo/pull/11974))
    - fix: Wait for dependsOn on first run of turbo watch ([#11953](https://github.com/vercel/turborepo/pull/11953))
    - fix: Preserve source dependencies when adding workspace deps in `turbo-gen` ([#11935](https://github.com/vercel/turborepo/pull/11935))
    - fix: Honor --output-logs errors-only for non-cached tasks ([#11926](https://github.com/vercel/turborepo/pull/11926))
    - fix: Ensure noUpdateNotifier from turbo.json is respected ([#11925](https://github.com/vercel/turborepo/pull/11925))
    - fix: Resolve npm packages in @turbo/gen compiled binary ([#11900](https://github.com/vercel/turborepo/pull/11900))
    - fix: Get all pnpm lockfile pruning tests passing ([#11897](https://github.com/vercel/turborepo/pull/11897))
    - fix: Sanitize git command inputs in create-turbo ([#11876](https://github.com/vercel/turborepo/pull/11876))
    - fix: Restrict credential file permissions to owner-only ([#11870](https://github.com/vercel/turborepo/pull/11870))
    - fix: Move `node-plop` to dependencies so `PlopTypes` resolves for consumers ([#11862](https://github.com/vercel/turborepo/pull/11862))
    - fix: Resolve external npm packages in @turbo/gen compiled binary ([#11855](https://github.com/vercel/turborepo/pull/11855))
    - fix: Replace unsafe `pre_exec`/`setsid` with `tokio process_group(0)` ([#11854](https://github.com/vercel/turborepo/pull/11854))
    - fix: Prevent premature git tag push during release staging ([#11851](https://github.com/vercel/turborepo/pull/11851))
    - fix: Clean up release tag on workflow failure ([#11848](https://github.com/vercel/turborepo/pull/11848))
    - fix: Sync lockfile with @turbo/gen optionalDependencies ([#11845](https://github.com/vercel/turborepo/pull/11845))
    - fix: Use pre-built turbo in build-gen release job ([#11837](https://github.com/vercel/turborepo/pull/11837))
    - fix: Harden token protection with `secrecy` crate and close exposure gaps ([#11831](https://github.com/vercel/turborepo/pull/11831))
    - fix: Clean up orphaned Windows child processes on shutdown ([#11829](https://github.com/vercel/turborepo/pull/11829))
    - fix: Avoid panic in sandboxed environments by removing system-configuration dependency ([#11828](https://github.com/vercel/turborepo/pull/11828))
    - fix: Use `secret_key_override` in tests to eliminate env var race condition ([#11824](https://github.com/vercel/turborepo/pull/11824))
    - fix: Pin @turbo/gen version to match the running turbo binary ([#11822](https://github.com/vercel/turborepo/pull/11822))
    - fix: Repair audit fixer log streaming and replace git push with patch upload ([#11818](https://github.com/vercel/turborepo/pull/11818))
    - fix: Resolve Windows TUI hang caused by portable-pty 0.9.0 ConPTY changes ([#11816](https://github.com/vercel/turborepo/pull/11816))
    - fix: Allow overwriting existing blobs in run updates and log appends ([#11813](https://github.com/vercel/turborepo/pull/11813))
    - fix: Pass non-empty body when initializing blob log files ([#11812](https://github.com/vercel/turborepo/pull/11812))
    - fix: Normalize bare LF to CRLF in TUI output to prevent garbled logs ([#11804](https://github.com/vercel/turborepo/pull/11804))
    - fix: Handle subpath package imports in `turbo boundaries` ([#11798](https://github.com/vercel/turborepo/pull/11798))
    - fix: Keep stdin alive for persistent tasks in stream mode ([#11793](https://github.com/vercel/turborepo/pull/11793))
    - fix: Emit space for empty vt100 cells to fix TUI repaint on task switch ([#11789](https://github.com/vercel/turborepo/pull/11789))
    - fix: Enhance path validation in assertSafeGitArgument ([#11788](https://github.com/vercel/turborepo/pull/11788))
    - fix: Rename cli workspace package to avoid false audit match ([#11767](https://github.com/vercel/turborepo/pull/11767))
    - fix: Upgrade tsdown to fix valibot and diff vulnerabilities ([#11766](https://github.com/vercel/turborepo/pull/11766))
    - fix: Upgrade semver to fix ReDoS vulnerability ([#11765](https://github.com/vercel/turborepo/pull/11765))
    - fix: Upgrade node-plop to 0.32.3 ([#11756](https://github.com/vercel/turborepo/pull/11756))
    - fix: Replace `serde_yml` with `serde_yaml_ng` to fix RUSTSEC-2025-0067/0068 ([#11755](https://github.com/vercel/turborepo/pull/11755))
    - fix: Replace `oxc_resolver` with `unrs_resolver` to fix yanked `papaya` dependency ([#11754](https://github.com/vercel/turborepo/pull/11754))
    - fix: Upgrade rustls chain to resolve RUSTSEC-2025-0134 ([#11739](https://github.com/vercel/turborepo/pull/11739))
    - fix: Upgrade test-case to resolve transitive proc-macro-error ([#11737](https://github.com/vercel/turborepo/pull/11737))
    - fix: Replace unic-segment with unicode-segmentation in globwatch ([#11736](https://github.com/vercel/turborepo/pull/11736))
    - fix: Upgrade futures/futures-util to resolve yanked futures-util 0.3.30 ([#11735](https://github.com/vercel/turborepo/pull/11735))
    - fix: Upgrade pest/pest_derive to resolve yanked version ([#11734](https://github.com/vercel/turborepo/pull/11734))
    - fix: Upgrade oxc_resolver to resolve yanked papaya dependency ([#11733](https://github.com/vercel/turborepo/pull/11733))
    - fix: Upgrade portable-pty to resolve RUSTSEC-2017-0008 ([#11732](https://github.com/vercel/turborepo/pull/11732))
    - fix: Upgrade pprof to fix RUSTSEC-2024-0408 ([#11730](https://github.com/vercel/turborepo/pull/11730))
    - fix: Upgrade git2 to fix RUSTSEC-2026-0008 ([#11729](https://github.com/vercel/turborepo/pull/11729))
    - fix: Upgrade ratatui to 0.30.0 to drop unmaintained paste crate ([#11723](https://github.com/vercel/turborepo/pull/11723))
    - fix: Upgrade test-case and merge to drop unmaintained proc-macro-error ([#11721](https://github.com/vercel/turborepo/pull/11721))
    - fix: Migrate from unmaintained serde_yaml to serde_yml ([#11720](https://github.com/vercel/turborepo/pull/11720))
    - fix: Upgrade async-io to 2.x to drop unmaintained instant crate ([#11719](https://github.com/vercel/turborepo/pull/11719))
    - fix: Upgrade indicatif to 0.18.3 to drop unmaintained number_prefix ([#11716](https://github.com/vercel/turborepo/pull/11716))
    - fix: Upgrade bytes to >=1.11.1 to fix RUSTSEC-2026-0007 ([#11715](https://github.com/vercel/turborepo/pull/11715))
    - fix: Upgrade inquirer to remove lodash dependency ([#11709](https://github.com/vercel/turborepo/pull/11709))
    - fix: Replace ts-node with tsx to resolve diff DoS vulnerability ([#11708](https://github.com/vercel/turborepo/pull/11708))
    - fix: Upgrade jest to v30 to resolve brace-expansion ReDoS vulnerability ([#11706](https://github.com/vercel/turborepo/pull/11706))
    - fix: Upgrade eslint to v10 to resolve @eslint/plugin-kit ReDoS vulnerability ([#11705](https://github.com/vercel/turborepo/pull/11705))
    - fix: Upgrade tsdown in create-turbo to resolve valibot ReDoS vulnerability ([#11702](https://github.com/vercel/turborepo/pull/11702))
    - fix: Upgrade ts-json-schema-generator to fix glob command injection vulnerability ([#11684](https://github.com/vercel/turborepo/pull/11684))
    - fix: Upgrade semver to fix ReDoS vulnerability ([#11683](https://github.com/vercel/turborepo/pull/11683))
    - fix: Upgrade Next.js to 16.1.5 to fix DoS vulnerabilities ([#11681](https://github.com/vercel/turborepo/pull/11681))
    - fix: Upgrade tar to 7.5.7 to address security vulnerabilities ([#11680](https://github.com/vercel/turborepo/pull/11680))
    - fix: Auto-merge release PRs by posting required check statuses ([#11670](https://github.com/vercel/turborepo/pull/11670))
    - fix: Replace unmaintained adler with adler2 ([#11661](https://github.com/vercel/turborepo/pull/11661))
    - fix: Upgrade openssl to 0.10.75 ([#11660](https://github.com/vercel/turborepo/pull/11660))
    - fix: Upgrade rustls and ring ([#11659](https://github.com/vercel/turborepo/pull/11659))
    - fix: Upgrade h2 to fix CONTINUATION Flood ([#11658](https://github.com/vercel/turborepo/pull/11658))
    - fix: Upgrade crossbeam-channel to 0.5.15 ([#11657](https://github.com/vercel/turborepo/pull/11657))
    - fix: Upgrade capnp to 0.24 ([#11656](https://github.com/vercel/turborepo/pull/11656))
    - fix: Add sitemap link to 404 page and fix TurborepoLogo gradient ([#11655](https://github.com/vercel/turborepo/pull/11655))
    - fix: Upgrade js-yaml to address CVE-2025-64718 ([#11650](https://github.com/vercel/turborepo/pull/11650))
    - fix: escaping for link titles in LinksService ([#11632](https://github.com/vercel/turborepo/pull/11632))
    - fix: Upgrade ts-jest to 29.4.6 to fix brace-expansion ReDoS vulnerabilities ([#11623](https://github.com/vercel/turborepo/pull/11623))
    - fix: Upgrade inquirer to 8.2.7 to fix tmp vulnerability ([#11622](https://github.com/vercel/turborepo/pull/11622))
    - fix: Upgrade diff to fix DoS vulnerabilities ([#11621](https://github.com/vercel/turborepo/pull/11621))
    - fix: Add explicit secrets declarations to release workflow_call trigger ([#11619](https://github.com/vercel/turborepo/pull/11619))
    - fix: Upgrade rehype packages to fix mdast-util-to-hast vulnerability ([#11616](https://github.com/vercel/turborepo/pull/11616))
    - fix: Upgrade esbuild to fix arbitrary request vulnerability ([#11615](https://github.com/vercel/turborepo/pull/11615))
    - fix: Upgrade mermaid to fix lodash-es vulnerability ([#11611](https://github.com/vercel/turborepo/pull/11611))
    - fix: Upgrade eslint devDependency to fix stack overflow vulnerability ([#11610](https://github.com/vercel/turborepo/pull/11610))
    - fix: Upgrade @vercel/blob and @actions packages to fix undici vulnerability ([#11608](https://github.com/vercel/turborepo/pull/11608))
    - fix: Upgrade @actions/github to fix @octokit vulnerabilities ([#11607](https://github.com/vercel/turborepo/pull/11607))
    - fix: Upgrade recharts to fix lodash vulnerability ([#11606](https://github.com/vercel/turborepo/pull/11606))
    - fix: Upgrade tar to fix security vulnerabilities ([#11602](https://github.com/vercel/turborepo/pull/11602))
    - fix: Upgrade tsup to fix rollup and glob vulnerabilities ([#11601](https://github.com/vercel/turborepo/pull/11601))
    - fix: Replace axios with native fetch in turbo-codemod ([#11600](https://github.com/vercel/turborepo/pull/11600))
    - fix: Upgrade axios to fix SSRF vulnerability ([#11599](https://github.com/vercel/turborepo/pull/11599))
    - fix: Upgrade fast-xml-parser to fix RangeError DoS ([#11598](https://github.com/vercel/turborepo/pull/11598))
    - fix: Upgrade next to fix HTTP deserialization DoS ([#11597](https://github.com/vercel/turborepo/pull/11597))
    - fix: Upgrade semver to fix ReDoS vulnerability ([#11596](https://github.com/vercel/turborepo/pull/11596))
    - fix: Extract git argument validation into reusable helper ([#11593](https://github.com/vercel/turborepo/pull/11593))
    - fix: Validate turbo version from lockfile for all package managers ([#11587](https://github.com/vercel/turborepo/pull/11587))
    - fix: Add `allowComments` and `allowTrailingCommas` to turbo.json schema ([#11579](https://github.com/vercel/turborepo/pull/11579))
    - fix: Support trailing commas in microfrontends JSONC files ([#11573](https://github.com/vercel/turborepo/pull/11573))

  </Accordion>

  <Accordion title="Documentation (46)">

    - docs: Add AI agent detection and automatic markdown rewrites ([#12462](https://github.com/vercel/turborepo/pull/12462))
    - docs: Add missing --force flag documentation ([#12440](https://github.com/vercel/turborepo/pull/12440))
    - docs: Move `experimentalObservability` into `futureFlags` section ([#12439](https://github.com/vercel/turborepo/pull/12439))
    - docs: Add AI guide to sidebar navigation ([#12438](https://github.com/vercel/turborepo/pull/12438))
    - docs: Add Git history requirements to `turbo query affected` docs ([#12426](https://github.com/vercel/turborepo/pull/12426))
    - docs: Clarify `turbo-ignore`'s future ([#12422](https://github.com/vercel/turborepo/pull/12422))
    - docs: Promote `turbo query` from experimental to stable ([#12421](https://github.com/vercel/turborepo/pull/12421))
    - docs: Expand subpath imports example ([#12412](https://github.com/vercel/turborepo/pull/12412))
    - docs: Downgrade Next.js ([#12408](https://github.com/vercel/turborepo/pull/12408))
    - fix: Move docs app icons into app/ directory ([#12403](https://github.com/vercel/turborepo/pull/12403))
    - docs: Add link to Docker guide in prune --docker flag section ([#12401](https://github.com/vercel/turborepo/pull/12401))
    - docs: Clarify environment variables across packages dependency behavior ([#12390](https://github.com/vercel/turborepo/pull/12390))
    - fix: Improve accessibility for docs ([#12375](https://github.com/vercel/turborepo/pull/12375))
    - docs: Fix typo in Turbo 2.7 blog post ([#12367](https://github.com/vercel/turborepo/pull/12367))
    - docs: Clean up futureFlags description ([#12355](https://github.com/vercel/turborepo/pull/12355))
    - docs: Add VS Code Jest extension workaround to Jest guide ([#12303](https://github.com/vercel/turborepo/pull/12303))
    - docs: Note that future flags affect global hash ([#12271](https://github.com/vercel/turborepo/pull/12271))
    - docs: missing `migrate` word ([#12234](https://github.com/vercel/turborepo/pull/12234))
    - docs: Remove CONSOLE DO NOT TRACK link ([#12232](https://github.com/vercel/turborepo/pull/12232))
    - docs: Clarification in oxc guide ([#12207](https://github.com/vercel/turborepo/pull/12207))
    - docs: Improve Oxc tooling guide for type-aware linting and fix race conditions ([#12200](https://github.com/vercel/turborepo/pull/12200))
    - docs: Remove bespoke AI prompts from documentation pages ([#12167](https://github.com/vercel/turborepo/pull/12167))
    - docs: Document Yarn v1 pass-through args workaround ([#12150](https://github.com/vercel/turborepo/pull/12150))
    - docs: Fix experimentalObservability config reference ([#12052](https://github.com/vercel/turborepo/pull/12052))
    - docs: Fix incorrect otel future flag bypass claim ([#12047](https://github.com/vercel/turborepo/pull/12047))
    - docs: Mention inputs key in package hash inputs table ([#11990](https://github.com/vercel/turborepo/pull/11990))
    - docs: Fix same-page anchor links that don't scroll to target ([#11989](https://github.com/vercel/turborepo/pull/11989))
    - fix(docs): update sitemap.md to single-line pipe-delimited format ([#11976](https://github.com/vercel/turborepo/pull/11976))
    - docs: Replace mysql refs with postgres ([#11827](https://github.com/vercel/turborepo/pull/11827))
    - docs: Geistdocs update 2 ([#11814](https://github.com/vercel/turborepo/pull/11814))
    - docs: Geistdocs update ([#11807](https://github.com/vercel/turborepo/pull/11807))
    - docs: Replace mermaid with reactflow-based diagram components ([#11770](https://github.com/vercel/turborepo/pull/11770))
    - docs: Capitalizaiton in update github-actions.mdx ([#11762](https://github.com/vercel/turborepo/pull/11762))
    - docs: Update Vitest guide with projects configuration ([#11760](https://github.com/vercel/turborepo/pull/11760))
    - fix: Add Vary: Accept header to docs markdown endpoint ([#11759](https://github.com/vercel/turborepo/pull/11759))
    - fix(docs): Fix code syntax highlighting by using correct Shiki CSS variable names ([#11726](https://github.com/vercel/turborepo/pull/11726))
    - fix: Upgrade fumadocs and shiki in docs to resolve mdast-util-to-hast vulnerability ([#11704](https://github.com/vercel/turborepo/pull/11704))
    - fix: Remove smooth scrolling from docs ([#11654](https://github.com/vercel/turborepo/pull/11654))
    - docs: Update using-environment-variables.mdx ([#11652](https://github.com/vercel/turborepo/pull/11652))
    - docs: Running Root Tasks ([#11630](https://github.com/vercel/turborepo/pull/11630))
    - feat: Add requestType tracking for header-negotiated markdown ([#11585](https://github.com/vercel/turborepo/pull/11585))
    - docs: Rename command to subcommand ([#11584](https://github.com/vercel/turborepo/pull/11584))
    - docs: Fix worktree command in blog post ([#11583](https://github.com/vercel/turborepo/pull/11583))
    - docs: Fix curl markdown Accept header syntax in 2.8 release blog ([#11580](https://github.com/vercel/turborepo/pull/11580))
    - docs: Update oxc.mdx to include cache false ([#11571](https://github.com/vercel/turborepo/pull/11571))
    - docs: Release post for 2.8 ([#11559](https://github.com/vercel/turborepo/pull/11559))

  </Accordion>

  <Accordion title="Examples (5)">

    - examples: Upgrade with-react-native-web example to use latest versions ([#12085](https://github.com/vercel/turborepo/pull/12085))
    - fix(examples): Update of `with-svelte` example ([#11952](https://github.com/vercel/turborepo/pull/11952))
    - examples: Fix markdown links inside code blocks in basic README ([#11946](https://github.com/vercel/turborepo/pull/11946))
    - examples: Update NODE_VERSION to 24.13.1 in Dockerfile ([#11679](https://github.com/vercel/turborepo/pull/11679))
    - examples: Update NODE_VERSION to 24.13.1 in Dockerfile ([#11591](https://github.com/vercel/turborepo/pull/11591))

  </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew) and [Tom](https://github.com/tknickman).

We also thank everyone who contributed to this release of Turborepo: @04cb, @alexmkio, @antoinelyset, @attehuhtakangas, @bestickley, @bkonkle, @ddmoney420, @EmojiPati, @floriansalihovic, @frankeld, @GabrielBB, @Goldyvaiiii, @haydenbleasel, @i5d6, @Jaredw2289-svg, @kyedavey, @lilianakatrina684-a11y, @marko-hologram, @mehulkar, @molebox, @MrNaif2018, @Netail, @odaysec, @PeterPCW, @prudentbird, @ramanverse, @Rohan5commit, @serjooo, @sleitor, @styfle, and @veeceey.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](https://turborepo.dev/docs/community).

---

### Apps Docs Content Blog Free Vercel Remote Cache (`apps/docs/content/blog/free-vercel-remote-cache.mdx`)

---
title: Vercel Remote Cache is now free
description: Free Remote Caching for repositories linked to Vercel
product: turborepo
type: overview
summary: Vercel Remote Cache is now free for any Turborepo linked to Vercel.
date: "2024/12/20"
tag: "web development"
---

# Vercel Remote Cache is now free

One of Turborepo's most important features is [Remote Caching](/docs/core-concepts/remote-caching), a distributed caching layer that ensures your developers and CI never do the same work twice.

As of today, [Vercel Remote Cache](https://vercel.com/docs/monorepos/remote-caching) is now a free, zero-configuration option for any Turborepo linked to Vercel, joining the [open-source Remote Caches created by the community](/docs/core-concepts/remote-caching#community-implementations) as free options for speeding up your development.

## Linking a repository to Vercel Remote Cache

### On Vercel

Commands using `turbo` on Vercel are automatically configured to use Vercel Remote Cache. Your builds will benefit from Remote Caching with zero-configuration.

### On other Continuous Integration providers

Create the `TURBO_TOKEN` and `TURBO_TEAM` environment variables to authenticate to Vercel Remote Cache with their respective values. Visit [our CI provider documentation](/docs/guides/ci-vendors) to learn how to connect to:

- [GitHub Actions](/docs/guides/ci-vendors/github-actions)
- [GitLab CI](/docs/guides/ci-vendors/gitlab-ci)
- [CircleCI](/docs/guides/ci-vendors/circleci)
- [GitLab CI](/docs/guides/ci-vendors/gitlab-ci)
- [Travis CI](/docs/guides/ci-vendors/travis-ci)
- [Any other CI provider](/docs/guides/ci-vendors#general-setup)

### On your local machine

To get started locally, run:

```bash title="Terminal"
npx turbo login
npx turbo link
```

## More information

To learn more, visit [Vercel's changelog announcement](https://vercel.com/changelog/free-vercel-remote-cache) or [Vercel Remote Cache documentation](https://vercel.com/docs/monorepos/remote-caching).

---

### Apps Docs Content Blog Joining Vercel (`apps/docs/content/blog/joining-vercel.mdx`)

---
title: Turborepo is joining Vercel
description: Turborepo is joining Vercel to make the web even faster.
product: turborepo
type: overview
summary: Turborepo has been acquired by Vercel and the CLI is now open-source.
date: "2021/12/09"
tag: "web development"
---

# Turborepo is joining Vercel

import { Authors } from "@/components/blog/authors";

<Authors authors={["jaredpalmer"]} />

Turborepo has been acquired by Vercel and the Turborepo CLI is now open-source! Also, Turborepo now provides zero-config remote caching through [Vercel](https://vercel.com/?utm_source=turborepo.dev&utm_medium=referral&utm_campaign=docs-link)!

beta.turborepo.dev and its remote caching service will be shut down on January 15th, 2022 and older versions of the `turbo` CLI will not be installable.

This is a milestone moment for the project and for all of you who have supported and adopted Turborepo. With Vercel's infrastructure and team backing, I'll expand on the capabilities of Turborepo and build out a team focused on improving their world-class build system. I can't wait to bring you along for this [next chapter](https://vercel.com/blog/vercel-acquires-turborepo).

Join me this [Friday, December 10 at 4:00 p.m. ET | 9:00 p.m GMT for a livestream Q&A](https://www.youtube.com/watch?v=YX5yoApjI3M) with Vercel's Head of Developer Relations, Lee Robinson. We'll go over what's in store for Turborepo and Vercel as we work toward improving the developer experience together.

This is just the beginning. We're about to embark on a world of even faster builds, even more flexibility, and even better workflows. Thanks for joining us on this amazing journey.

---

### Apps Docs Content Blog Saml Sso Now Available (`apps/docs/content/blog/saml-sso-now-available.mdx`)

---
title: SAML SSO is now available
description: SAML Single Sign-on (SSO) is now available to Enterprise customers thanks to our friends over at WorkOS.
product: turborepo
type: overview
summary: Turborepo now supports SAML SSO from multiple identity providers for enterprise customers.
tag: "web development"
date: "2021/08/03"
---

# SAML SSO is now available

import { Authors } from "@/components/blog/authors";

<Authors authors={["jaredpalmer"]} />

Thanks to our friends over at [WorkOS](https://workos.com/), in addition to GitHub, GitLab, and Passwordless auth, Turborepo now supports Single Sign-on (SSO) from the following SAML providers for enterprise customers:

- AD FS SAML
- Auth0 SAML
- Azure AD SAML
- CyberArk SAML
- Generic SAML
- G Suite OAuth
- G Suite SAML
- JumpCloud SAML
- Microsoft OAuth
- Okta SAML
- OneLogin SAML
- OpenID Connect
- PingFederate SAML
- PingOne SAML
- Shibboleth
- VMWare SAML

We also support SCIM (a.k.a. "Directory Sync") via:

- Azure AD SCIM
- BambooHR
- G Suite
- Gusto
- Hibob
- Okta SCIM v1.1
- Okta SCIM v2.0
- Rippling
- SCIM v1.1
- SCIM v2.0
- Workday

If you're team in interested in activating SAML SSO, please contact us [turborepo@vercel.com](mailto:turborepo@vercel.com).

## What's next?

We take security extremely seriously. And while SSO is certainly a must in 2021, we are also currently undergoing a third-party SOC 2 Type 2 examination as well. Last but not least, we are adding biometric/U2F access controls and audit logs this fall. Stay tuned for updates.

---

### Apps Docs Content Blog Turbo 0 4 0 (`apps/docs/content/blog/turbo-0-4-0.mdx`)

---
title: Turborepo 0.4.0
description: Turborepo 0.4.0 introduces 10x faster hashing, pruned workspaces with sparse installs, a new pipeline configuration API, and improved cache control.
product: turborepo
type: overview
summary: Release notes for Turborepo 0.4.0 featuring a Go rewrite, smarter hashing, and pruned workspaces.
tag: "web development"
date: "2021/04/02"
---

# Turborepo 0.4.0

import { Authors } from "@/components/blog/authors";

import TurboSchedulerImage from "../../public/images/blog/turbo-0-4-0/turbo-vs-lerna-execution.png";

<Authors authors={["jaredpalmer"]} />

I'm excited to announce the release of Turborepo v0.4.0!

- **10x faster**: `turbo` has been rewritten from the ground up in Go to make it even more blazing fast
- **Smarter hashing**: Improved hashing algorithm now considers resolved dependencies instead of just the contents of the entire root lockfile
- **Partial lockfiles / sparse installs**: Generate a pruned subset of your root lockfile and monorepo that includes only the necessary packages needed for a given target
- **Fine-grained scheduling**: Improved task orchestration and options via `pipeline` configuration
- **Better cache control**: You can now specify cache outputs on a per-task basis

## Rewritten in Go

Although I initially prototyped `turbo` in TypeScript, it became clear that certain items on the roadmap would require better performance. After around a month or so of work, I'm excited to finally release Go version of the `turbo` CLI. Not only does it boot in a milliseconds, but the new Go implementation is somewhere between 10x and 100x faster at hashing than the Node.js implementation. With this new foundation (and some features you're about to read about), Turborepo can now scale to intergalactic sized projects while remaining blazing fast all thanks to Go's awesome concurrency controls.

## Better Hashing

Not only is hashing faster in v0.4.0, but also _a lot_ smarter.

The major change is that `turbo` no longer includes the hash of the contents of the root lockfile in its hasher (the algorithm responsible for determining if a given task exists in the cache or needs to be executed). Instead, `turbo` now hashes the set of the resolved versions of a package's `dependencies` and `devDependencies` based on the root lockfile.

The old behavior would explode the cache whenever the root lockfile changed in any way. With this new behavior, changing the lockfile will only bust the cache for those package's impacted by the added/changed/removed dependencies. While this sounds complicated, again all it means is that when you install/remove/update dependencies from npm, only those packages that are actually impacted by the changes will need to be rebuilt.

## Experimental: Pruned Workspaces

One of our biggest customer pain points/requests has been improving Docker build times when working with large Yarn Workspaces (or really any workspace implementation). The core issue is that workspaces' best feature--reducing your monorepo to a single lockfile--is also its worst when it comes to Docker layer caching.

To help articulate the problem and how `turbo` now solves it, let's look at an example.

Say we have a monorepo with Yarn workspaces that includes a set of packages called `frontend`, `admin`, `ui`, and `backend`. Let's also assume that `frontend` and `admin` are Next.js applications that both depend on the same internal React component library package `ui`. Now let's also say that `backend` contains an Express TypeScript REST API that doesn't really share much code with any other part of our monorepo.

Here's what the Dockerfile for the `frontend` Next.js app might look like:

```docker title="Dockerfile"
FROM node:alpine AS base
RUN apk update
WORKDIR /app

# Add lockfile and package.jsons
FROM base AS builder
COPY *.json yarn.lock ./
COPY packages/ui/*.json ./packages/ui/
COPY packages/frontend/*.json ./packages/frontend/
RUN yarn install

# Copy source files
COPY packages/ui/ ./packages/ui/
COPY packages/frontend/ ./packages/frontend/

# Build
RUN yarn --cwd=packages/ui/ build
RUN yarn --cwd=packages/frontend/ build

# Start the Frontend Next.js application
EXPOSE 3000
RUN ['yarn', '--cwd', 'packages/frontend', 'start']
```

While this works, there are some things that could be a lot better:

- You manually `COPY` in the internal packages and files needed to build the target app and need to remember which need to be built first.
- You `COPY` the root `yarn.lock` lockfile into the correct position very early in the Dockerfile, but this lockfile is the lockfile for the _entire_ monorepo.

This last issue is especially painful as your monorepo gets larger and larger because any change to this lockfile triggers a nearly full rebuild regardless of whether or not the app is actually impacted by the new/changed dependencies.

....until now.

With the all new `turbo prune` command, you can now fix this nightmare by deterministically generating a sparse/partial monorepo with a pruned lockfile for a target package--without installing your `node_modules`.

Let's look at how to use `turbo prune` inside of Docker.

```docker title="Dockerfile"
FROM node:alpine AS base
RUN apk update && apk add git

## Globally install `turbo`
RUN npm i turbo

# Prune the workspace for the `frontend` app
FROM base as pruner
WORKDIR /app
COPY . .
RUN turbo prune frontend --docker

# Add pruned lockfile and package.json's of the pruned subworkspace
FROM base AS installer
WORKDIR /app
COPY --from=pruner /app/out/json/ .
COPY --from=pruner /app/out/yarn.lock ./yarn.lock
# Install only the deps needed to build the target
RUN yarn install

# Copy source code of pruned subworkspace and build
FROM base AS builder
WORKDIR /app
COPY --from=pruner /app/.git ./.git
COPY --from=pruner /app/out/full/ .
COPY --from=installer /app/ .
RUN turbo run build frontend

# Start the app
FROM builder as runner
EXPOSE 3000
RUN ['yarn', '--cwd', 'packages/frontend', 'start']
```

So what exactly is the output of the `turbo prune`? A folder called `out` with the following inside of it:

- A folder `json` with the pruned workspace's package.jsons
- A folder `full` with the pruned workspace's full source code, but only including the internal packages that are needed to build the target
- A _new_ pruned lockfile that only contains the pruned subset of the original root lockfile with the dependencies that are actually used by the packages in the pruned workspace.

Thanks to the above, Docker can now be set up to only rebuild each application when there is a real reason to do so. So `frontend` will only rebuild when its source or dependencies (either internal or from npm) have actually changed. Same same for `admin` and `backend`. Changes to `ui`, either to its source code or dependencies, will trigger rebuilds of both `frontend` and `admin`, but _not_ `backend`.

While this example seems trivial, just imagine if each app takes up to 20 minutes to build and deploy. These savings really start to add up quickly, especially on large teams.

## Pipelines

To give you even more control over your Turborepo, we've added `pipeline` to `turbo`'s configuration. This new field in lets you specify how the npm scripts in your monorepo relate to each other as well as some additional per-task options. `turbo` then uses this information to optimally schedule your tasks in your monorepo, collapsing waterfalls that would otherwise exist.

Here's how it works:

```json title="./package.json"
{
  "turbo": {
    "pipeline": {
      "build": {
        // This `^` tells `turbo` that this pipeline target relies on a topological target being completed.
        // In english, this reads as: "this package's `build` command depends on its dependencies' or
        // devDependencies' `build` command being completed"
        "dependsOn": ["^build"]
      },
      "test": {
        //  `dependsOn` without `^` can be used to express the relationships between tasks at the package level.
        // In English, this reads as: "this package's `test` command depends on its `lint` and `build` command first being completed"
        "dependsOn": ["lint", "build"]
      },
      "lint": {},
      "dev": {}
    }
  }
}
```

The above config would then be interpreted by `turbo` to optimally schedule execution.

What's that actually mean? In the past (like Lerna and Nx), `turbo` could only run tasks in topological order. With the addition of pipelines, `turbo` now constructs a topological "action" graph in addition to the actual dependency graph which it uses to determine the order in which tasks should be executed with maximum concurrency. The end result is that you no longer waste idle CPU time waiting around for stuff to finish (i.e. no more waterfalls).

<ThemeAwareImage
  light={{
    alt: "Turborepo scheduler compared to Lerna execution",
    src: TurboSchedulerImage,
    props: { width: 800, height: 400 },
  }}
  dark={{
    alt: "Turborepo scheduler compared to Lerna execution",
    src: TurboSchedulerImage,
    props: { width: 800, height: 400 },
  }}
/>

## Improved Cache Control

Thanks to `pipeline`, we now have a great place to open up `turbo`'s cache behavior on a per-task basis.

Building on the example from above, you can now set cache output conventions across your entire monorepo like so:

```json title="./package.json"
{
  "turbo": {
    "pipeline": {
      "build": {
        // Cache anything in dist or .next directories emitted by a `build` command
        "outputs": ["dist/**", ".next/**", "!.next/cache/**"]
        "dependsOn": ["^build"]
      },
      "test": {
        // Cache the test coverage report
        "outputs": ["coverage/**"],
        "dependsOn": ["lint", "build"]
      },
      "dev": {
        // Never cache the `dev` command
        "cache": false
      },
      "lint": {}
    }
  }
}
```

_Note: Right now, `pipeline` exists at the project level,
but in later releases these will be overridable on per-package basis._

## What's Next?

I know this was a lot, but there's even more to come. Here's what's up next on the Turborepo roadmap.

- A landing page!
- [Remote caching w/ `@turborepo/server`](https://x.com/jaredpalmer/status/1359627800840462341)
- Build scans, telemetry, and metrics and dependency and task graph visualization
- [Desktop Console UI](https://x.com/jaredpalmer/status/1360315387372572672)
- Intelligent `watch` mode
- Official build rules for TypeScript, React, Jest, Node.js, Docker, Kubernetes, and more

## Credits

- [Iheanyi Ekechukwu](https://x.com/kwuchu) for guiding me through the Go ecosystem
- [Miguel Oller](https://x.com/ollermi) and the team from [Makeswift](https://www.makeswift.com/) for iterating on the new `prune` command

---

### Apps Docs Content Blog Turbo 1 1 0 (`apps/docs/content/blog/turbo-1-1-0.mdx`)

---
title: Turborepo 1.1
description: Turborepo 1.1 introduces automatic migrations, turbo.json configuration, environment variable dependencies, partial Yarn v2 support, and more!
product: turborepo
type: overview
summary: Release notes for Turborepo 1.1 featuring automatic migrations, turbo.json, and environment variable dependencies.
date: "2022/01/31"
tag: "web development"
---

# Turborepo 1.1

import { Authors } from "@/components/blog/authors";

import NpmDownloadsImage from "../../public/images/blog/turbo-1-1-0/turborepo-weekly-npm-downloads.png";

<Authors authors={["jaredpalmer", "becca__z", "gaspargarcia", "gregsoltis"]} />

Since releasing Turborepo v1.0 in mid-December, we've seen incredible adoption:

- 5.5k+ GitHub Stars
- 70k+ weekly npm downloads
- 65+ OSS contributors
- In production at [Vercel](https://github.com/vercel/next.js), [AWS](https://github.com/aws-amplify/amplify-ui), [PayPal](https://x.com/jaredpalmer/status/1485617973477978121), [Twilio](https://github.com/twilio-labs/function-templates), [Contentful](https://github.com/contentful/forma-36), [Miro](https://github.com/miroapp/app-examples), [Framer](https://github.com/framer/motion), [Discord.js](https://github.com/discordjs/discord.js), [Rocket.chat](https://github.com/RocketChat/fuselage), [Astro.build](https://github.com/withastro/astro)
- 585+ members of the [Turborepo Community Discord](https://turborepo.dev/discord)

<ThemeAwareImage
  light={{
    alt: "Weekly npm downloads of turbo",
    src: NpmDownloadsImage,
    props: { width: 800, height: 400 },
  }}
  dark={{
    alt: "Weekly npm downloads of turbo",
    src: NpmDownloadsImage,
    props: { width: 800, height: 400 },
  }}
/>

We're further improving build performance and caching with Turborepo v1.1, featuring:

- [**Automatic Migrations:**](#automatic-migrations) Official idempotent migration scripts to assist with upgrading.
- [**`turbo.json` Support:**](#turbojson-support) Turborepo configuration now lives in its own file.
- [**Faster Package Manager Detection:**](#faster-package-manager-detection) Turborepo now respects the `packageManager` key in the root `package.json`.
- [**Environment Variable Dependencies:**](#environment-variable-dependencies) Define how environment variables impact global and task-specific caching.
- [**Partial Support for Yarn v2+:**](#partial-yarn-v2v3-support) Support for yarn v2+ with `nodeLinker: "node-modules"`.

Update today by running `npm install turbo@latest`. After running `turbo`, you'll see instructions about how to use `@turbo/codemod` to run automatic migrations for `v1.1`.

## Automatic Migrations

Turborepo now provides idempotent code transformations and automatic migration scripts (a.k.a "codemods") to help upgrade your Turborepo codebase when a feature is deprecated or will be deprecated in the future.

Codemods are transformations that run on your codebase programmatically. This saves you time by applying a large number of changes to your code automatically, without having to manually go through and edit every file.

### Usage

```bash title="Terminal"
npx @turbo/codemod <transform> <path>
```

- `transform` - the name of transform, [see available transforms in the docs](/docs/reference/turbo-codemod#turborepo-1x).
- `path` - files or directory to transform.
- `--dry` - Do a dry run, no code will be edited.
- `--print` - Prints the changed output for comparison.

For more information about specific transforms, check out the [new Codemods documentation](/docs/reference/turbo-codemod#turborepo-1x).

## `turbo.json` Support

Turborepo configuration is now defined in a `turbo.json` file in the root of your monorepo. This is an improvement over having a `turbo` key in `package.json` for those who want to quickly jump straight to their Turborepo configuration in their code editors.

To automatically migrate from your current configuration in `package.json`, check out a new branch, navigate to the root of your monorepo and run the following codemod:

```bash title="Terminal"
npx @turbo/codemod create-turbo-config .
```

For more information on this transformation, [check out the documentation](/docs/reference/turbo-codemod#create-turbo-config).

## Faster Package Manager Detection

Turborepo now supports the recently established `packageManager` field in `package.json` for faster package manager detection. Previously, `turbo` would check for specific files to infer this information. To automatically set this field, check out a new branch, navigate to the root of your monorepo and run:

```bash title="Terminal"
npx @turbo/codemod add-package-manager .
```

For more information on this transformation, [check out the documentation](/docs/reference/turbo-codemod#add-package-manager).

## Environment Variable Dependencies

When you use `turbo` with tools that inline environment variables at build time (e.g. Next.js or Create React App), it is important you tell `turbo` about it to avoid shipping a cached artifact with the wrong environment variables.

You can now control `turbo`'s [cache fingerprinting (a.k.a. hashing)](/docs/crafting-your-repository/caching#task-inputs) behavior based on the values of both environment variables and the contents of files:

- Including environment variables in a `dependsOn` in your `pipeline` definition prefixed by a `$` will impact the cache fingerprint on a per-task or per-package-task basis.
- Including environment variables in `globalDependencies` list prefixed by a `$` will impact the cache fingerprint of _all_ tasks.
- Including files or globs of files in `globalDependencies` will impact the cache fingerprint of _all_ tasks.

```jsonc title="./turbo.json"
{
  "pipeline": {
    "build": {
      "dependsOn": {
        "^build"
        // env vars will impact hashes of all "build" tasks
        "$SOME_ENV_VAR"
      },
      "outputs": ["dist/**"]
    },
    "web#build": { // override settings for the "build" task for the "web" app
      "dependsOn": [
        "^build",
          // env vars that will impact the hash of "build" task for only "web" app
          "$STRIPE_SECRET_KEY",
          "$NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
          "$NEXT_PUBLIC_ANALYTICS_ID"
      ],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "docs#build": { // override settings for the "build" task for the "docs" app
      "dependsOn": [
        "^build",
          // env vars that will impact the hash of "build" task for only "web" app
          "$STRIPE_SECRET_KEY",
          "$NEXT_PUBLIC_STRIPE_PUBLIC_KEY",
          "$NEXT_PUBLIC_ANALYTICS_ID"
      ],
      "outputs": [".next/**", "!.next/cache/**"]
    }
  },
  "globalDependencies": [
    "$GITHUB_TOKEN"// env var that will impact the hashes of all tasks,
    "tsconfig.json" // file contents will impact the hashes of all tasks,
    ".env.*" // glob file contents will impact the hashes of all tasks
  ]
}
```

Note: In most monorepos, you don't often use environment variables in shared packages, but mostly in applications. Thus, to get higher cache hit rates, you should only include environment variables in the app-specific tasks where they are used/inlined.

For more information, read the [caching and hashing documentation](/docs/crafting-your-repository/caching#task-inputs).

## Partial Yarn v2/v3 support

In addition to Yarn v1, npm, and pnpm package managers, Turborepo now supports Yarn v2+ with [`nodeLinker: "node-modules"` set in `.yarnrc.yml`](https://yarnpkg.com/configuration/yarnrc#nodeLinker). This key tells Yarn v2+ to mimic Yarn v1's `node_modules` installation behavior. Yarn v2+ Plug'n'Play (a.k.a. "PnP") is not currently supported.

## What's next?

[Since our launch](/blog/joining-vercel), Turborepo has focused on seamless incremental adoption/migration and speeding up CI/CD. We are committed to both of those values, but now we'll also be focusing on improving Turborepo's day-to-day ergonomics for local development and observability. We're really excited about this next chapter and will be sharing more details soon.

## We're hiring!

The Turborepo team at [Vercel](https://vercel.com/) is hiring! We're specifically looking for full time [Senior Full Stack Software Engineers](https://vercel.com/careers) and [Senior DevOps/Infrastructure Engineers](https://vercel.com/careers) to help us make Turborepo even better.

---

### Apps Docs Content Blog Turbo 1 10 0 (`apps/docs/content/blog/turbo-1-10-0.mdx`)

---
title: Turborepo 1.10
description: Turborepo 1.10 introduces new features to improve your local development experience.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.10 featuring code generators, improved env var inputs, and environment modes.
date: "2023/06/01"
tag: "web development"
---

# Turborepo 1.10

import { Authors } from "@/components/blog/authors";
import { Callout } from "@/components/geistdocs/callout";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import { Date } from "@/components/blog/date";
import TurboGenLight from "../../public/images/blog/turbo-1-10-0/turbo-gen-light.gif";
import TurboGenDark from "../../public/images/blog/turbo-1-10-0/turbo-gen-dark.gif";

<Date>Thursday, June 1st, 2023</Date>

<Authors
  authors={["nathanhammond", "tomknickman", "anthonyshew", "mehulkar"]}
/>

Turborepo 1.10 introduces new features to improve your local development experience:

- [**Code Generators**](#code-generators): Use `turbo gen` to generate source code, including creating new workspaces and copying existing ones.
- [**Improved Environment Variable Inputs**](#improved-environment-variable-inputs): It's now easier to depend on environment variables with wildcards and `.env` support.
- [**New Environment Modes**](#environment-modes): You can now specify `--env-mode=strict` to control environment variables that are included in your task hashes.

Update today with

```bash title="Terminal"
npx @turbo/codemod migrate
```

## Code Generators

<ThemeAwareImage
  className="my-4 rounded-xl border-2 border-[#f3f7fd] p-4 dark:border-[#1c2428]"
  light={{
    alt: "turbo-gen",
    src: TurboGenLight,
    props: {
      width: 600,
      height: 205,
    },
  }}
  dark={{
    alt: "turbo-gen",
    src: TurboGenDark,
    props: {
      width: 600,
      height: 215,
    },
  }}
/>

Turborepo Generators allow you to add new code to your repository in a predictable, structured way.
Previously, you would need to copy code yourself and manually add dependencies to your new workspace. With Generators,
we've automated the process of creating new workspaces and integrating them into your repository.

You can [create a blank workspace from scratch](/docs/guides/generating-code#add-an-empty-package), [copy an existing workspace](/docs/guides/generating-code#copy-an-existing-package), or even create custom generators
for more control. Custom generators leverage [Plop](https://plopjs.com/) configurations, a common template definition strategy used in the JavaScript ecosystem.

[Custom generators](/docs/guides/generating-code#custom-generators) can also be used to scaffold more granular sets of code than workspaces. You can significantly speed up tasks like:

- [Adding new components to your UI library](https://github.com/vercel/turbo/blob/main/examples/basic/packages/ui/turbo/generators/config.ts)
- Creating new unit tests
- Generating a new MDX blog post

Get started with your first generator by running:

```bash title="Terminal"
turbo gen
```

For more, check out the [documentation](/docs/guides/generating-code).

## Improved Environment Variable Inputs

### Support for `.env` files

[`.env` files](https://www.dotenv.org/docs/) are commonly used to load environment variables. This can cause problems when running with `turbo`, because these variables can be [invisible](/docs/crafting-your-repository/using-environment-variables#avoid-creating-or-mutating-environment-variables-at-runtime), and are not easily
included in the hash for your task. This problem could cause unintended cache hits while working locally.

Turborepo now makes this much easier with automatic support for `.env` files.

To ensure that Turborepo includes these variables in your hash, use the `dotEnv` key. For example, here is a configuration for a Next.js application:

```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "globalDotEnv": [".env"],
  "pipeline": {
    "build": {
      "dotEnv": [
        ".env.production.local",
        ".env.local",
        ".env.production",
        ".env"
      ]
    },
    "dev": {
      "dotEnv": [
        ".env.development.local",
        ".env.local",
        ".env.development",
        ".env"
      ]
    },
    "test": {
      "dotEnv": [".env.test.local", ".env.test", ".env"]
    }
  }
}
```

<Callout>
  This feature does **not** handle system environment variables. If you are not
  using `.env` files outside of development, make sure your environment
  variables are still enumerated in either
  [env](/docs/reference/configuration#env), or
  [globalEnv](/docs/reference/configuration#globalenv) to ensure they are
  included in your hash.
</Callout>

For more, check out the documentation.

### Environment Variable Wildcards

Large applications can end up with many environment variables in their `turbo.json`. This can make your configuration difficult to manage and maintain.

With wildcards, you can now specify patterns of variables to include in your hash.

```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "pipeline": {
    "build": {
      "env": ["ACME_*"]
    }
  }
}
```

For more, check out the [documentation](/docs/reference/configuration#wildcards).

### Environment modes

Turborepo environment modes are now out of experimental mode and are available for general use.

By default, and when `turbo run` is invoked with `--env-mode=loose`, all environment variables from the machine are made available to every single Turborepo task.
This ensures the greatest compatibility while accepting some risk that a task will implicitly have access to a environment variable that is not specified in your `turbo.json`.

In the new strict mode, when `turbo` is invoked with `--env-mode=strict`, only [important system environment variables](/docs/reference/system-environment-variables) and environment variables enumerated inside of `turbo.json` will be made available to a task.

For more, check out the [documentation](/docs/crafting-your-repository/using-environment-variables#environment-modes).

## Community

Since releasing [Turborepo v1.9](/blog/turbo-1-9-0) we've seen incredible adoption and community growth:

- [21.5k+ GitHub Stars](https://github.com/vercel/turbo)
- [1.2M+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 85 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team:

- [Jared](https://github.com/jaredpalmer), [Greg](https://github.com/gsoltis), [Nathan](https://github.com/nathanhammond), [Thomas](https://github.com/tknickman), [Mehul](https://github.com/mehulkar), [Chris](https://github.com/chris-olszewski), [Nicholas](https://github.com/NicholasLYang), and [Alexander](https://github.com/arlyon)

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 11 0 (`apps/docs/content/blog/turbo-1-11-0.mdx`)

---
title: Turborepo 1.11
description: Turborepo 1.11 sets the Rust-based foundation for the future of Turborepo.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.11 completing the migration from Go to Rust.
date: "2023/12/05"
tag: "web development"
---

# Turborepo 1.11

import { Authors } from "@/components/blog/authors";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import { Date } from "@/components/blog/date";
import LogOrderGroupsLight from "../../public/images/blog/turbo-1-11-0/log-order-groups-light.png";
import LogOrderGroupsDark from "../../public/images/blog/turbo-1-11-0/log-order-groups-dark.png";

<Date>Tuesday, December 5th, 2023</Date>

<Authors
  authors={["gregsoltis", "chrisolszewski", "nicholasyang", "alexanderlyon"]}
/>

Turborepo 1.11 completes our migration to Rust and ships several developer experience improvements:

- [**Our new Rust-based foundation**](#unlocking-the-future-of-turbo-with-rust): We've finished the port from Go to lay the groundwork for better performance, improved stability, and new features.
- [**Group logs for improved readability**](#group-logs-for-improved-readability): You can now specify `--log-order=grouped` to organize your logs into distinct sections separated by tasks.
- [**Updated examples**](#updated-examples): Start with an example for Next.js, Svelte, Remix, Nuxt, and more.

Update today by running `npx @turbo/codemod migrate`.

## Unlocking the future of `turbo` with Rust

As we wrote about in [our blog post about the migration](https://vercel.com/blog/turborepo-migration-go-rust), we're excited to start seeing the benefits of our porting effort for Turborepo users. Rust has allowed us to surface more complexity in _our_ code so we're able to create a better experience in _your_ codebase in several ways:

- We've noticed a slight performance improvement right away for some use cases, even without doing much performance tuning in our code yet. We look forward to diving deeper into making `turbo` **even faster soon**.
- We were able to move incidental behaviors of globbing, paths, and encoding support to tested and supported behavior, giving us better confidence that we're handling your configuration as expected. Going forward, we'll be able to build features like validation and automatic bug-fixing codemods into Turborepo for **better stability**.
- We've quickly iterated on **enhancing error messages** in your monorepo as a feature for next release, giving you critical information for find the source of misconfigurations.
- We've been able to catch possible platform-related bugs much sooner, as Rust forces us to think about the differences between platforms and environments much more closely than Go. This **deepened reliability** removes an entire category of possible bugs from your repository.

If you find any problems that you believe are related to the new Rust codepath, you can opt back to the Go codepath using the `--go-fallback` flag and [report an issue on GitHub](https://github.com/vercel/turbo/issues/new?assignees=&labels=kind%3A+bug%2Cowned-by%3A+turborepo%2Cneeds%3A+triage&projects=&template=0-turborepo-bug-report.yml&title=%5Bturborepo%5D+).

## Group logs for improved readability

To make it easier to review your task logs, we've introduced the `--log-order` flag to output all logs from a task **after it finishes** rather than _as it writes_. This results in logs that are separated per-task, improving readability on a specific task's logs.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "Using `--log-order=grouped` to output task logs to the terminal as separated chunks separated by task.",
    src: LogOrderGroupsLight,
    props: {
      width: 682,
      height: 746.5,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "Using `--log-order=grouped` to output task logs to the terminal as separated chunks separated by task.",
    src: LogOrderGroupsDark,
    props: {
      width: 682,
      height: 746.5,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

Enable this behavior using `--log-order=grouped`. [Check out the documentation](/docs/reference/run#--log-order-option) to learn more

## Updated examples

Our repository contains [`an examples directory`](https://github.com/vercel/turbo/tree/main/examples) with starter monorepos for your projects.

To get started with an example, run:

```bash title="Terminal"
# Two Next.js applications
npx create-turbo@latest
```

```bash title="Terminal"
# Next.js and Remix
npx create-turbo@latest -e kitchen-sink
```

```bash title="Terminal"
# Vue and Nuxt
npx create-turbo@latest -e with-vue-nuxt
```

We're putting a renewed effort towards ensuring our examples are kept up-to-date. Additionally, we've re-architected our examples to advocate for best practices in monorepos. For example:

- In-editor go-to-definition across packages
- Dependencies updated to latest versions
- Tooling like ESLint, Prettier, jest, and vitest pre-configured
- Hot-reloading across packages

[Use an example](/docs/getting-started/examples) to get started, or [browse the code directly](https://github.com/vercel/turbo/tree/main/examples) for more.

## Community

Since releasing [Turborepo 1.10](/blog/turbo-1-10-0) we've seen incredible adoption and community growth:

- [23.6k+ GitHub Stars](https://github.com/vercel/turbo)
- [1.8M+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 206 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 12 0 (`apps/docs/content/blog/turbo-1-12-0.mdx`)

---
title: Turborepo 1.12
date: 2024/01/30
description: Turborepo 1.12 adds popular community-requested features and feedback improvements.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.12 featuring colored task logs, improved errors, and telemetry.
tag: "web development"
---

# Turborepo 1.12

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import ColorsInLogsLight from "../../public/images/blog/turbo-1-12-0/log-colors-light.png";
import ColorsInLogsDark from "../../public/images/blog/turbo-1-12-0/log-colors-dark.png";
import ErrorsOverhaulLight from "../../public/images/blog/turbo-1-12-0/light-errors-overhaul.png";
import ErrorsOverhaulDark from "../../public/images/blog/turbo-1-12-0/errors-overhaul-dark.png";

<Date>Tuesday, January 30th, 2024</Date>

<Authors authors={["mehulkar", "tomknickman", "gregsoltis"]} />

Turborepo 1.12 adds popular community-requested features and feedback improvements, including:

- [**Colors in task logs**](#colors-in-task-logs): Colors from original shell logs used by default
- [**Errors overhaul**](#errors-overhaul): Improved error messages for misconfigurations
- [**Improved `inputs` ergonomics**](#improved-inputs-ergonomics): Use Turborepo's defaults with your input customizations
- [**Telemetry**](#telemetry): Help us focus on what matters most to Turborepo users

We're also done cleaning up our migration to Rust in this release by removing the `--go-fallback` flag and shrinking the `turbo` binary by 58% compared to 1.11.

Update today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

## Colors in task logs

Color is a great way to quickly surface important information in user interfaces. It's common for developer tooling to highlight success in green, warnings in yellow, or errors in red.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "A screenshot of a terminal running a `turbo` task with colors from the underlying shell logs.",
    src: ColorsInLogsLight,
    props: {
      width: 625,
      height: 1000,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "A screenshot of a terminal running a `turbo` task with colors from the underlying shell logs.",
    src: ColorsInLogsDark,
    props: {
      width: 625,
      height: 1000,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

In this release, we're now showing the colors from your underlying tasks in your local environment by default. This has been a popular request from the community and we're excited to ship support for macOS and Linux today. We will be following up with Windows support in a future release.

## Errors overhaul

An important part of developer experience is ensuring that, when things go wrong, it's clear how to get back to the happy path. In this release, we've improved the error messages that come from Turborepo misconfigurations.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "A screenshot of a terminal attempting to run a `turbo` task but receiving an informative error that an unknown key `output`, was found in the `turbo.json` file.",
    src: ErrorsOverhaulLight,
    props: {
      width: 682,
      height: 746.5,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "A screenshot of a terminal attempting to run a `turbo` task but receiving an informative error that an unknown key `output`, was found in the `turbo.json` file.",
    src: ErrorsOverhaulDark,
    props: {
      width: 682,
      height: 746.5,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

In this enhanced UI, we are:

- Showing you the errorful code
- Improving the help text in your terminal for each type of error
- Providing a link to documentation when it can provide you with useful context

## Improved `inputs` ergonomics

Turborepo intelligently understands the inputs to your tasks by default. But there are also situations where you may want to include or exclude specific files or directories from your task inputs.

Importantly, using the `inputs` key on a task opts you out of all of the default inputs for a task, like omitting gitignored files from your inputs. Until today, you had to manually bring back these defaults by creating glob patterns for them yourself.

Today, we're adding `$TURBO_DEFAULT$` as a special value when used in the `inputs` array.

```json title="turbo.json"
{
  "pipeline": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", "!README.md", "!**.test.**"]
    }
  }
}
```

This microsyntax allows you to use the Turborepo defaults you're used to while adding in your own custom globs to fine tune the default input behavior.

[Check out the `inputs` documentation](/docs/reference/configuration#inputs) for more information.

## Telemetry

Turborepo was released almost two years ago, and `turbo` has developed considerably over the past two years. As the community has grown, the value of your feedback is immeasurable in helping us stay focused on what matters most to Turborepo users.

Until now, our feedback gathering process has been manual, slow, and error prone. While we will always highly appreciate users who file [GitHub Issues](https://github.com/vercel/turbo/issues), speak to us in [GitHub Discussions](https://github.com/vercel/turbo/discussions), and chat with the community in [Discord](https://turborepo.dev/discord), this feedback only captures the sentiment of a small corner of the Turboverse.

Today, we're introducing a **completely anonymous**, automated approach to feedback to learn more about the ways that the community is using Turborepo. As we continue to iterate on `turbo`, this information will help us ensure performance, confirm stability, design new features, and drive the project's direction.

We're creating the build system of the future and this information will be highly valuable to guide us in that effort. For more information, visit [turborepo.dev/docs/telemetry](https://turborepo.dev/docs/telemetry).

If you'd like to opt out of telemetry, run:

```bash title="Terminal"
turbo telemetry disable
```

You may also opt-out by setting an environment variable:

- `TURBO_TELEMETRY_DISABLED=1`
- `DO_NOT_TRACK=1` (per the [Console Do Not Track (DNT)](https://consoledonottrack.com/) specification)

## Other Improvements

- **[Feature]**: Enable pty usage [(PR)](https://github.com/vercel/turbo/pull/7128)
- **[Feature]**: Support `$TURBO_DEFAULT$` in inputs [(PR)](https://github.com/vercel/turbo/pull/7113)
- **[Feature]**: Support Yarn 4 patches [(PR)](https://github.com/vercel/turbo/pull/6974)
- **[Feature]**: Enable telemetry [(PR)](https://github.com/vercel/turbo/pull/7122)
- **[Improvement]**: Treat empty environment variables as unset [(PR)](https://github.com/vercel/turbo/pull/6929)
- **[Improvement]**: Error out if dependent flags are provided without their parent [(PR)](https://github.com/vercel/turbo/pull/6780)
- **[Improvement]**: Make sure that our concurrency check ignore packages without tasks [(PR)](https://github.com/vercel/turbo/pull/6790)
- **[Improvement]**: Avoid panic on invalid directory filters [(PR)](https://github.com/vercel/turbo/pull/6955)
- **[Improvement]**: Ignore permission errors during globbing [(PR)](https://github.com/vercel/turbo/pull/6957)
- **[Improvement]**: Avoid retry panic [(PR)](https://github.com/vercel/turbo/pull/6926)
- **[Improvement]**: Rewrite prefix after carriage return [(PR)](https://github.com/vercel/turbo/pull/6989)
- **[Improvement]**: Validate graph extension [(PR)](https://github.com/vercel/turbo/pull/6995)
- **[Improvement]**: Truncate metadata file when writing [(PR)](https://github.com/vercel/turbo/pull/7016)
- **[Improvement]**: Correctly create symlinks to directories [(PR)](https://github.com/vercel/turbo/pull/6983)
- **[Improvement]**: Make sure cookie dir exists before writing cookie [(PR)](https://github.com/vercel/turbo/pull/7015)
- **[Improvement]**: Examples turbo.json outputs key [(PR)](https://github.com/vercel/turbo/pull/7071)
- **[Improvement]**: Filter package.json files that are subfolders of other packages [(PR)](https://github.com/vercel/turbo/pull/7025)
- **[Improvement]**: Sort dependents and dependencies during normalization [(PR)](https://github.com/vercel/turbo/pull/7018)
- **[Improvement]**: Swap fallback logs to debug [(PR)](https://github.com/vercel/turbo/pull/7102)
- **[Improvement]**: Include gitignored files in fallback [(PR)](https://github.com/vercel/turbo/pull/7105)
- **[Improvement]**: Include default files in fallback [(PR)](https://github.com/vercel/turbo/pull/7106)

## Community

Since releasing [Turborepo 1.11](/blog/turbo-1-11-0) we've seen incredible adoption and community growth:

- [24.0k+ GitHub Stars](https://github.com/vercel/turbo)
- [1.9M+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 238 years of compute time saved using [Vercel Remote Cache](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 13 0 (`apps/docs/content/blog/turbo-1-13-0.mdx`)

---
title: Turborepo 1.13
date: 2024/03/21
description: Turborepo 1.13 brings a new and improved local development experience along with other enhancements.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.13 featuring a new terminal UI, turbo scan, and CI logging improvements.
tag: "web development"
---

# Turborepo 1.13

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Callout } from "@/components/geistdocs/callout";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import { ExperimentalBadge } from "@/components/geistdocs/experimental-badge";
import ExperimentalUiGif from "../../public/images/blog/turbo-1-13-0/experimental-ui.gif";
import TurboScanDark from "../../public/images/blog/turbo-1-13-0/turbo-scan-dark.png";
import TurboScanLight from "../../public/images/blog/turbo-1-13-0/turbo-scan-light.png";
import GitHubActionImage from "../../public/images/blog/turbo-1-13-0/github-action.png";

<Date>Thursday, March 21st, 2024</Date>

<Authors authors={["gregsoltis", "chrisolszewski"]} />

Turborepo 1.13 brings a new and improved local development experience along with other enhancements, including:

- [**New terminal UI**](#new-terminal-ui) <ExperimentalBadge />: Interact with your tasks locally in an enhanced terminal experience
- [**Enable the fastest defaults**](#enable-the-fastest-defaults): Make your local development environment faster with `turbo scan`
- [**CI logging improvements**](#ci-logging-improvements): Support for four major providers and automatic unfurling of errored tasks
- [**Enhanced `prune` support**](#enhanced-package-manager-support-for-prune): Bug fixes and improved stability for `turbo prune`

Update today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

## New terminal UI

Until today, `turbo` would output logs as a stream while you were working on your libraries and applications. This could be overwhelming at times since the interleaved logs made it difficult to understand what was going on with a specific task.

With this release, we’re shipping a new, experimental terminal UI, which allows you to:

- **Toggle through the logs of each of your tasks**, making them easier to follow and read
- **Interact with your persistent tasks** by entering and exiting the task’s shell, giving you the ability to re-run unit tests, for example
- **See the duration for each of your tasks** in a bar graph

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "The new experimental terminal UI",
    src: ExperimentalUiGif,
    props: {
      width: 800,
      height: 350,
      className: "dark:hidden block",
    },
  }}
  dark={{
    alt: "The new experimental terminal UI",
    src: ExperimentalUiGif,
    props: {
      width: 800,
      height: 350,
      className: "hidden dark:block",
    },
  }}
/>

To enable the new UI, either use the `--experimental-ui` flag or add the `experimentalUI` flag to your `turbo.json`:

```json title="./turbo.json"
{
  "experimentalUI": true
}
```

**We are looking forward to hearing your feedback on this new feature.** Please [visit the RFC on GitHub Discussions](https://github.com/vercel/turbo/discussions/7802) to share your thoughts.

## Enable the fastest defaults

We want your local development experience to be as fast as possible - through even more than the parallelization and caching of `turbo`.

Running `turbo scan` will inspect your machine for optimizations that make your experience faster.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "A screenshot of a terminal running `turbo scan`.",
    src: TurboScanLight,
    props: {
      width: 934,
      height: 869,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "A screenshot of a terminal running `turbo scan`.",
    src: TurboScanDark,
    props: {
      width: 1868,
      height: 1800,
      className: "hidden dark:block rounded-xl dark:border-gray-700",
    },
  }}
/>

For more information, [visit the documentation](/docs/reference/scan).

<Callout type="info">
  This command is for your local development environment. It will not optimize
  your CI.
</Callout>

## CI logging improvements

This release adds support for automatically grouping successful logs in:

- Azure Pipelines
- TeamCity
- Travis CI

These providers join GitHub Actions, which was already supported.

Additionally, Turborepo now ungroups any tasks that did not complete successfully so you can find errorful tasks faster.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "A screenshot of a GitHub Action that ran a `turbo` task. The logs for tasks that completed successfully are folded while the errored task shows it's logs in full with red highlighting.",
    src: GitHubActionImage,
    props: {
      width: 3306,
      height: 2607,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "A screenshot of a GitHub Action that ran a `turbo` task. The logs for tasks that completed successfully are folded while the errored task shows it's logs in full with red highlighting.",
    src: GitHubActionImage,
    props: {
      width: 3306,
      height: 2607,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

## Enhanced package manager support for `prune`

Turborepo’s `prune` command is an important optimization for Docker users, helping them to create lightweight images from monorepos.

pnpm lockfile support has been upgraded by adding support for [Workspace relative path references](https://pnpm.io/workspaces#referencing-workspace-packages-through-their-relative-path) and respecting the [`link-workspace-packages` property in `.npmrc`](https://pnpm.io/npmrc#link-workspace-packages).

Yarn4 support has been improved by supporting [`resolutions` in `package.json`](https://yarnpkg.com/configuration/manifest#resolutions) at the root of your Workspace.

## Community

Since releasing [Turborepo 1.12](/blog/turbo-1-12-0) we've seen incredible adoption and community growth:

- [24.6k+ GitHub Stars](https://github.com/vercel/turbo)
- [2.3M+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 283 years of compute time saved using [Vercel Remote Cache](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 2 0 (`apps/docs/content/blog/turbo-1-2-0.mdx`)

---
title: Turborepo 1.2
description: Turborepo 1.2 introduces improved task filtering, artifact signing and integrity, human-readable and JSON dry runs, and more!
product: turborepo
type: overview
summary: Release notes for Turborepo 1.2 featuring task filtering, artifact signing, and dry run support.
date: "2022/04/08"
tag: "web development"
---

# Turborepo 1.2

import { Date } from "@/components/blog/date";
import { Authors } from "@/components/blog/authors";

import TurboDryRunImage from "../../public/images/blog/turbo-1-2-0/turbo-dry-run.png";

<Date>Friday, April 8th, 2022</Date>

<Authors authors={["jaredpalmer", "becca__z", "gaspargarcia", "gregsoltis"]} />

Since releasing Turborepo v1.1 in late January, we've seen incredible adoption and community growth:

- **6.5k+** [GitHub Stars](https://github.com/vercel/turbo)
- **140k+** weekly npm downloads (doubling since our [last blog post for v1.1](/blog/turbo-1-1-0))
- **95+** OSS contributors
- **900+** members of the [Turborepo Community Discord](https://turborepo.dev/discord)
- **1.6 years** of Time Saved through Remote Caching on Vercel, saving more than 2.5 months every week

We've further improved ergonomics, observability, and security with Turborepo v1.2 featuring:

- [**New Task Filtering API**](#new-task-filtering-api): `--filter` adds more powerful task filtering capabilities to `turbo run`
- [**Human-readable and JSON dry runs**](#debug-and-automate-with---dry-run): `--dry-run` flag can print out information about a `turbo run` without executing any tasks, in both human and JSON-parse friendly formats
- [**Improved Internal Scheduler and Graph**](#improved-internal-scheduler-and-graph): We refactored `turbo` 's internal scheduler and graph to be more ergonomic and predictable
- [**Enhanced Remote Cache Security**](#cache-outputs-integrity-and-signature-verification): Cryptographically sign remote cache artifacts with your own secret key

Update today by running `npm install turbo@latest`. After running `turbo run` for the first time, you'll see instructions about how to use `@turbo/codemod` to run automatic migrations for `v1.2`.

## New Task Filtering API

We are excited to release one of our most requested features: the ability to expressively filter tasks through a `--filter` flag. The `--filter` flag is the much more powerful successor to the current combination of `--scope`, `--include-dependencies`, `--since`, and `--no-deps` flags.

With `--filter` you can tell `turbo` to restrict executing commands to a subset of matched packages in your monorepo based on name, folder, or even if it has changed since a git commit ref.

Take a look at some examples of what you can accomplish with the new `--filter` command:

- `--filter=<package_name>` - match by exact package name or glob pattern
- `--filter=...<package_name>`- match by package name/glob and include all dependent packages of matches
- `--filter=...^<package_name>`- match by package name/glob and include all dependent packages of matches, but exclude the matches themselves
- `--filter=<package_name>...` - match by package name/glob and include all the matched packages' dependencies
- `--filter=<package_name>^...` - match by package name/glob and include all matched package dependencies, but exclude the matches themselves
- `--filter={./path/to/package}` - match by path or filesystem glob pattern
- `--filter=[origin/main]` - match by changed packages since a git commit ref

You can use multiple filters together to get even more granular filtering as well as combine each part of the above patterns `{}`, `[]` , `^` , and `...` to express more complex behavior.

For example, if you had an app located in `./apps/web` directory with local packages used as dependencies, and a Turborepo pipeline where `test` depends on `^build` topologically, running:

```bash title="Terminal"
turbo run test --filter={./apps/web}[HEAD^1]^...
```

would tell `turbo` to ensure dependencies are built and to run the `test` script in all of the local dependencies of the app located in `./apps/web`, not including that app itself, if the app has changed since HEAD^1.

For more details and examples, refer to the new [filtering documentation](/docs/crafting-your-repository/running-tasks#using-filters).

## Debug and Automate with `--dry-run`

You can now see the impact of `turbo run` without actually executing any commands by appending either `--dry-run` or `--dry-run=json` to any `turbo run` command. This will result in either human or JSON output.

Dry runs are incredibly useful for two situations:

- Debugging and testing run options
- Using `turbo` filtering and task graphs for building automations

<div className="overflow-hidden lg:rounded-xl">
  <ThemeAwareImage
    light={{
      alt: "Turborepo Dry Run output showing task information",
      src: TurboDryRunImage,
      props: { width: 800, height: 500 },
    }}
    dark={{
      alt: "Turborepo Dry Run output showing task information",
      src: TurboDryRunImage,
      props: { width: 800, height: 500 },
    }}
  />
</div>

We hope that this will improve visibility into what `turbo` is doing, speeding up debugging, and make it easier to leverage `turbo` in dynamic CI/CD systems.

## Improved Internal Scheduler and Graph

When using `turbo run`, every `package.json` task is added to an internal graph to map dependencies based on the inferred relationships defined in your Turborepo `pipeline`. This task graph allows Turborepo to efficiently schedule incremental concurrent task running and cache task outputs for later use.

We have made major improvements to the internal task scheduler and resulting graph structure, resulting in better performance and a better developer experience. For example, in many cases, you will no longer need to use `--include-dependencies`. Instead, after specifying your task entry points, the new and improved graph will automatically handle this graph resolution on your behalf.

## Cache Outputs Integrity and Signature Verification

You can now configure Turborepo to sign remote cache outputs using HMAC-SHA256 with a secret key before uploading them to the Remote Cache. When Turborepo downloads signed cache artifacts, it will now verify the artifact's integrity and authenticity. Any artifact that fails to verify will be ignored, discarded, and treated as a cache miss by Turborepo.

To enable this feature, set the `remoteCache` options in your `turbo.json` config file to include `signature: true`. Then specify your secret key by declaring the `TURBO_REMOTE_CACHE_SIGNATURE_KEY` environment variable.

```jsonc title="./turbo.json"
{
  "$schema": "[https://turborepo.dev/schema.json](https://turborepo.dev/schema.json)",
  "remoteCache": {
    // Indicates if signature verification is enabled.
    "signature": true,
  },
}
```

## Other bug fixes and improvements

- `--sso-team` flag now enables teams with SAML tokens to log in through `turbo login` with correct team permissions
- `--log-output` flag allows you to control what logs are printed to the terminal, and when, allowing you to focus only on what's new
- `FORCE_COLOR` environment variable is now supported
- `TURBO_FORCE=true` environment variable will now force execution
- `--remote-only` and `TURBO_REMOTE_ONLY=true` will tell `turbo` to only use Remote Caching
- We now show `>>> FULL TURBO` when there's at least one task attempted
- Yarn v2+ with Plug'n'Play (PnP linker) is supported for the `turbo run` command, but `turbo prune` is still not fully supported
- Fixed regression with chrome tracing if `--profile` is specified
- You can now set concurrency by percentage of CPUs with `--concurrency=50%`

## We're hiring!

The Turborepo team at [Vercel](https://vercel.com/) is hiring! We're up to five core team members already this year and are looking to hire even more. We're specifically looking for full-time [Senior Build Systems Engineers](https://vercel.com/careers).

## What's next?

Along with seamless incremental adoption/migration and speeding up CI/CD, we've been focusing on improving Turborepo's day-to-day ergonomics, security, and observability. The new `--filter` flag, signed artifacts, and dry runs are important steps toward those goals.

Next up, we'll be focusing an enhanced local development experience, codebase automations, and overall CLI performance.

## Thank you, contributors

Turborepo is the result of the combined work of over 95 individual developers and our core team.

This release was brought to you by the contributions of: @gsoltis09, @jaredpalmer, @gaspar09, @shuding, @rajatkulkarni95, @VanTanev, @Kikobeats, @tknickman, @thebanjomatic, @chelkyl, @elado, @finn-orsini, @becca, @weyert, @ekosz

---

### Apps Docs Content Blog Turbo 1 3 0 (`apps/docs/content/blog/turbo-1-3-0.mdx`)

---
title: Turborepo 1.3
description: Turborepo 1.3 introduces restricted hash inputs, root script running and caching, new CI/CD Recipes, and more!
product: turborepo
type: overview
summary: Release notes for Turborepo 1.3 featuring restricted hash inputs and root script caching.
date: "2022/06/23"
tag: "web development"
---

# Turborepo 1.3

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Callout } from "@/components/geistdocs/callout";

<Date>Thursday, June 23rd, 2022</Date>

<Authors
  authors={[
    "gregsoltis",
    "nathanhammond",
    "tomknickman",
    "jaredpalmer",
    "gaspargarcia",
    "becca__z",
  ]}
/>

With Turborepo 1.3 we are bringing improved caching and flexibility which includes:

- [**Restricted hash inputs:**](#pipeline-inputs) Specify the files in a package folder that impact caching with `inputs`.
- [**Root script running and caching:**](#run-and-cache-scripts-from-the-root-of-your-monorepo) Run and cache `package.json` scripts from the root of the monorepo.
- [**New CI/CD Recipes:**](#new-cicd-recipes) We added recipes for using Turborepo with popular CI providers.

Update today by running `npm install turbo@latest`.

## Pipeline `inputs`

In addition to [environment variables, dependencies, and pipeline configurations,](/docs/crafting-your-repository/caching#task-inputs) `turbo` will consider all non-gitignored files in package folder when calculating each `package.json` script's hash fingerprint (the key that `turbo` uses to index its cache and to determine if a script needs to be re-executed). **With Turborepo 1.3+, you can now specify globs of `inputs` in your `turbo.json` `pipeline` to control which files are relevant for a particular script for caching.** This means that you can now express the following in `turbo.json`

- Ignore changes to all markdown files in a package or app's folder.
- Don't bother rebuilding an app if only its test files have changed.
- Only re-run tests if either source files or test files have been changed in a package or folder.
- and more.

Let's walk through a concrete example: imagine we have a monorepo with a Next.js application for a documentation website in `./apps/docs-site`, some packages, and some markdown files in the root of the monorepo in a `./docs` folder.

```bash title="Example monorepo"
.
├── docs/
│   ├── api-reference.md
│   ├── getting-started.md
│   └── intro.md
├── apps/
│   ├── docs-site/
│   │   ├── components/
│   │   ├── pages/
│   │   │   └── [slug].js
│   │   ├── README.md
│   │   └── package.json
│   └── web-site/
│       ├── pages/
│       ├── README.md
│       └── package.json
├── packages/
│   ├── configs/
│   └── ui/
├── package.json
└── turbo.json
```

Let's assume that the Next.js `docs-site` renders the markdown files from the `./docs` folder. We can now set up the `build` script in the app's `package.json` to use `inputs` in `turbo.json` to better specify exactly which files are relevant (and which should impact caching) as follows:

```jsonc title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "pipeline": {
    // ... omitted for brevity
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "dist/**"],
    },
    "docs#build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**"],
      // Define set of relevant globs which impact caching of docs site
      // builds
      "inputs": [
        "../../docs/**/*.md",
        "pages/**",
        "components/**",
        "package.json",
      ],
    },
  },
}
```

Note: Like `outputs`, `inputs` are defined relative to the related `package.json` , but they can be outside of a given folder (`e.g. ../../docs/**`).

## Run and cache scripts from the root of your monorepo

As of 1.3, **`turbo` can now run and cache scripts from the `package.json` file at the root of the monorepo**, which will help significantly when migrating to Turborepo.

To set this up, specify a root script in your `pipeline` configuration in your `turbo.json` using the form `"//#<script>": {...}`. The `//` tells `turbo` that the script is relative to the root of the monorepo and not each workspace package.

There are 2 important things to note about root scripts and execution scope:

- If you already have `"build": {...}` in your `pipeline`, but want to include the `build` script defined in the monorepo's root `package.json` file when running `turbo run build`, you may opt the root into the execution's scope by also including `"//#build": {...}` in your configuration as well.
- Conversely, you _do not_ need to define a generic `"my-script": {...}` entry if all you need is `"//#my-script": {...}`.

A sample pipeline that defines the root script `check-examples` and opts the root into `test` might look like:

```json title="./package.json"
{
  "name": "my-turborepo",
  "private": true,
  "scripts": {
    "test": "echo 'test!'",
    "check-examples": "./check-examples.sh"
  },
  "devDependencies": {
    "turbo": "latest"
  }
}
```

```jsonc title="./turbo.json" highlight="20"
{
  "$schema": "https://turborepo.dev/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
    },
    "test": {
      "dependsOn": ["^build"],
      "outputs": [],
    },
    // This will cause the "test" script from all workspace package.json's
    // AND the root package.json to be included when "turbo run test" is run
    "//#test": {
      "dependsOn": [],
      "outputs": [],
    },
    // This will cause the "check-examples" script in the root package.json
    // to be run when "turbo run check-examples" is run. Since a general
    // "check-examples" script is not defined in the pipeline, only the root
    // package.json's "check-examples" script will be included
    // when "turbo run check-examples" is run
    "//#check-examples": {
      "dependsOn": [],
      "outputs": [],
      "inputs": [
        "examples/**/*.ts",
        "examples/**/*.tsx",
        "examples/**/*.json",
        "examples/**/*.js",
        "examples/**/*.yaml",
        "cli/**/*.ts",
        "./scripts/run-example.sh",
      ],
    },
  },
}
```

Note: We suggest specifying `inputs` whenever declaring a root task in your `pipeline` to improve caching.

## New CI/CD Recipes

We added recipes for using Turborepo and Remote Caching with:

- [CircleCI](/docs/guides/ci-vendors/circleci)
- [GitHub Actions](/docs/guides/ci-vendors/github-actions)
- [Gitlab CI](/docs/guides/ci-vendors/gitlab-ci)
- [Travis CI](/docs/guides/ci-vendors/travis-ci)

If there are other recipes you would like to see here please let us know by opening up a [GitHub Discussion](https://github.com/vercel/turbo/discussions/categories/ideas).

## Other Bug Fixes and Improvements

- Improved git operations and hashing
- Better cycle detection in dependency graph analysis
- Added support for Windows ARM 64-bit architectures
- Improved Remote Cache error logging
- Added Storybook to the Design System example

## Community

Since releasing [Turborepo v1.2 in early April](/blog/turbo-1-2-0), we've seen incredible adoption and community growth:

- [8.1k+ GitHub Stars](https://github.com/vercel/turbo)
- 275k+ weekly NPM downloads (up ~2x)
- 1,200+ members of the [Turborepo Community Discord](https://turborepo.dev/discord)
- 5.8 years of compute time saved through Remote Caching on Vercel (up ~5x), saving +7 months per week now

Turborepo is the result of the combined work of over 136 contributors including our core team.

This release was brought to you by the contributions of: @gsoltis, @nathanhammond, @tknickman, @jaredpalmer, @zvictor, @ObliviousHarmony, @O4epegb, @rafaeltab, @mcmontseny, @bertspaan, @Jastor11, and @enBonnet

Thank you for your continued support, feedback, and collaboration with us to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 4 0 (`apps/docs/content/blog/turbo-1-4-0.mdx`)

---
title: Turborepo 1.4
description: Turborepo 1.4 has new examples, automatically includes environment variables, and more!
product: turborepo
type: overview
summary: Release notes for Turborepo 1.4 featuring automatic environment variable inclusion and eslint-config-turbo.
date: "2022/08/09"
tag: "web development"
---

# Turborepo 1.4

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Callout } from "@/components/geistdocs/callout";

<Date>Tuesday, August 9th, 2022</Date>

<Authors
  authors={[
    "gregsoltis",
    "nathanhammond",
    "tomknickman",
    "anthonyshew",
    "jaredpalmer",
    "mehulkar",
  ]}
/>

Turborepo 1.4 brings:

- [**Automatic environment variable inclusion:**](#automatic-environment-variable-inclusion) We'll automatically infer popular framework environment variables for you. No need to declare them yourself in `turbo.json`.
- [**`eslint-config-turbo`:**](#eslint-config-turbo) Enhanced feedback with a new ESLint plugin.
- [**New framework and library examples:**](#new-framework-and-library-examples) New starters and examples requested by the community.

Update today by running `npm install turbo@latest`.

## Automatic environment variable inclusion

To help ensure correct caching across environments Turborepo will now automatically infer and include public environment variables when calculating cache keys for apps built with Astro, Create React App, Gatsby, Next.js, Nuxt, SvelteKit, Vite, Vue, and more. You can safely remove framework-specific public environment variables from `turbo.json` if you manually declared them.

```diff title="turbo.json"
{
  "pipeline": {
    "build": {
      "dependsOn": [
        "^build"
-       // Include build time public inlined environment variables that
-       // are different in development and production, so that
-       // Turborepo does not use the same cached build
-       // across environments
-       "$NEXT_PUBLIC_EXAMPLE_ENV_VAR"
      ]
    }
  }
}
```

Note that this automatic detection and inclusion only works if Turborepo successfully infers the framework your apps are built with. Additionally, the environment variables will only be included in the cache key for tasks in workspaces where that framework is used. In other words, environment variables inferred for Next.js apps, will only be included in the cache key for workspaces detected as Next.js apps. Tasks in other workspaces in the monorepo will not be impacted.

For example, consider a monorepo with three workspaces: a Next.js project, a Create React App project, and a TypeScript package. Each has a `build` script, and both apps depend on the TypeScript project. Let's say that this Turborepo has a standard `turbo.json` pipeline that builds them all in order:

```jsonc title="turbo.json"
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
    },
  },
}
```

As of 1.4, when you run `turbo run build`, Turborepo will not consider any build time environment variables relevant when building the TypeScript package. However, when building the Next.js app, Turborepo will infer that environment variables starting with `NEXT_PUBLIC_` could alter the output of the `.next` folder and should thus be included when calculating the hash. Similarly, when calculating the hash of the Create React App's `build` script, all build time environment variables starting with `REACT_APP_PUBLIC_` will be included.

This improvement in hash specificity by framework is a significant step toward optimal, safe, and correct caching.

## `eslint-config-turbo`

We've also created a new ESLint config for further in-editor assistance to help ensure your Turborepo cache can be correctly shared across every environment. While our new hashing algorithm should cover most situations with most frameworks, this ESLint config will provide in-editor feedback for teams using other build time inlined environment variables that are not framework-prefixed but impact build outputs (i.e. caching), and teams using their own in-house frameworks that we cannot detect automatically.

To get started, extend from `eslint-config-turbo` in your root [`eslintrc`](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#configuration-file-formats) file:

```jsonc title=".eslint.config.js"
{
  // Automatically flag env vars missing from turbo.json
  "extends": ["next/core-web-vitals", "turbo"],
}
```

If you prefer more control over the rules - use can install and configure the `eslint-plugin-turbo` _plugin_ directly by first adding it to plugins and then configuring the desired rules:

```jsonc title=".eslint.config.js"
{
  "extends": ["next/core-web-vitals"],
  "plugins": ["turbo"],
  "rules": {
    // Automatically flag env vars missing from turbo.json
    "turbo/no-undeclared-env-vars": "error",
  },
}
```

The plugin will warn you if you are using non-framework-related environment variables in your code that have not been declared in your `turbo.json`.

As of 1.4.x, we now include `eslint-config-turbo` in all of our examples and in new projects generated via `npx create-turbo`.

Learn more about ESLint configs and plugins in the [ESLint docs](https://eslint.org/docs/latest/).

## New framework and library examples

Based on your feedback and suggestions, we've created new examples to integrate Turborepo into your workflow:

- [Svelte](https://github.com/vercel/turbo/tree/main/examples/with-svelte)
- [Docker](https://github.com/vercel/turbo/tree/main/examples/with-docker)
- [React Native](https://github.com/vercel/turbo/tree/main/examples/with-react-native-web)
- [Prisma](https://github.com/vercel/turbo/tree/main/examples/with-prisma)
- [Tailwind](https://github.com/vercel/turbo/tree/main/examples/with-tailwind)
- … [and more!](https://github.com/vercel/turbo/tree/main/examples)

## Other bug fixes and improvements

- Allow both sides of git comparison ([#1442](https://github.com/vercel/turbo/pull/1442))
- Properly rebuild packages that share a name prefix ([#1538](https://github.com/vercel/turbo/pull/1538))
- Cache files with the correct file permissions ([#1429](https://github.com/vercel/turbo/pull/1429))

## Community

Since releasing [Turborepo v1.3 in June](https://turborepo.dev/blog/turbo-1-3-0), we've seen incredible adoption and community growth:

- [8.65k+ GitHub Stars](https://github.com/vercel/turbo)
- 365k weekly NPM downloads, up 2x since late April
- 10 years of compute time saved through Remote Caching on Vercel, saving 10 months per week

Turborepo is the result of the combined work of all of our contributors including our core team.

This release was brought to you by the contributions of: @B2o5T, @chitchu, @elis, @gsoltis, @harshcut, @jaredpalmer, @kocisov, @nathanhammond, @neolivz, @NuroDev, @oneezy, @samouri, @shayc, @StevenMatchett, @tknickman, @trevorr, @zsoldosp, and more!

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 5 0 (`apps/docs/content/blog/turbo-1-5-0.mdx`)

---
title: Turborepo 1.5
description: Turborepo 1.5 brings the Monorepo Handbook, drops the 'run' command, improves pruning, and much more!
product: turborepo
type: overview
summary: Release notes for Turborepo 1.5 featuring the Monorepo Handbook and improved pruning.
date: "2022/09/19"
tag: "web development"
---

# Turborepo 1.5

import { Authors } from "@/components/blog/authors";
import { Callout } from "@/components/geistdocs/callout";
import { Date } from "@/components/blog/date";

<Date>Monday, September 19th, 2022</Date>

<Authors
  authors={[
    "mattpocock",
    "gregsoltis",
    "nathanhammond",
    "tomknickman",
    "anthonyshew",
    "jaredpalmer",
    "mehulkar",
    "chrisolszewski",
  ]}
/>

Turborepo 1.5 is a **huge leap forward for our documentation and DX**, as well as bringing big improvements to `turbo prune`:

- [**The Monorepo Handbook**](/docs/guides): We've built the missing manual for your monorepo - a guide on workspaces, code sharing, integrating common tools and much more.
- [**Drop the `run`**](#drop-the-run): `turbo run <task>` can now be shortened to `turbo <task>`
- [**`turbo prune` now supports pnpm and yarn 2+**](#prune-now-supported-on-pnpm-and-yarn-2): Pruning your monorepo is now supported in `pnpm` and `yarn@berry`.
- [**Improved environment variables in `turbo.json`**](#environment-variables-in-turbojson): Environment variables are now first-class citizens in your Turborepo pipeline configuration.
- [**Changes to `package.json` hashing**](#changes-to-packagejson-hashing): We've improved how we hash `package.json` when running tasks.

Update today by running `npm install turbo@latest`.

## The Monorepo Handbook

Setting up a monorepo for the first time often means navigating a lot of new concepts. You'll need to understand workspaces, package installation, sharing code and dependency management - and a lot more.

This often meant that folks who wanted to set up a monorepo from scratch had to piece information together from different documentation sites. First `pnpm`, then `tsup`, then back to `changesets`, then back to Turborepo for dessert.

We want to fill this gap with [the Monorepo Handbook](/docs/guides). We've built guides on how to integrate all the tools you'll need to make ship happen with your monorepo, including guides on:

- [Installing Packages](/docs/crafting-your-repository/managing-dependencies)
- [Linting](/docs/guides/tools/eslint)
- [Development Tasks](/docs/crafting-your-repository/developing-applications)
- [Building Apps](/docs/crafting-your-repository/constructing-ci)
- [Publishing Packages](/docs/guides/publishing-libraries)

## Drop the `run`

<iframe
  className="mt-6 h-72 w-full max-w-xl sm:h-96"
  src="https://www.youtube.com/embed/PEgk2v6KntY"
  title="YouTube video player"
  frameborder="0"
  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
></iframe>

You can now run tasks with the Turborepo CLI using `turbo <task>`.

```diff title="Terminal"
- turbo run build
+ turbo build


- turbo run lint build test
+ turbo lint build test
```

If your task name conflicts with a built-in `turbo` subcommand, we'll run our subcommand instead. That means you shouldn't name your tasks things like `prune`, `run`, or `login` - since those are built-in subcommands.

`turbo run <task>` will continue to work, and there are no plans to deprecate it.

## Prune now supported on pnpm and yarn 2+

We're delighted to announce that [`turbo prune`](/docs/reference/prune) now supports in pnpm, yarn, and yarn 2+.

You can use `turbo prune` to create a pruned subset of your monorepo with a dedicated lockfile--with the correct dependencies needed for a given target application and its dependencies. This is especially useful for using efficiently Turborepo within a Docker image.

As part of the new handbook, we've also added a section on using `turbo prune` to [build docker images](/docs/guides/tools/docker).

Check out our previous [blog on prune](/blog/turbo-0-4-0#experimental-pruned-workspaces) to learn more.

## Environment variables in `turbo.json`

We've introduced two new keys to `turbo.json` - `env` and `globalEnv`. These allow environment variables to be configured _separately_ from tasks:

```diff title="turbo.json"
{
  "globalDependencies": [
-   "$DATABASE_URL"
  ],
+ "globalEnv": [
+   "DATABASE_URL"
+ ],
  "pipeline": {
    "build": {
      "dependsOn": [
-       "$BUILD_ENV"
      ],
+     "env": [
+       "BUILD_ENV"
+     ]
    }
  }
}
```

`globalEnv` and `env` allow you to specify a list of environment variables _without_ `$` prefixes. This makes the configuration file significantly easier to read. Read more [in our updated docs](/docs/crafting-your-repository/using-environment-variables#adding-environment-variables-to-task-hashes).

To help migrate from the previous syntax, we've prepared a codemod. You can run `npx @turbo/codemod migrate-env-var-dependencies`.

This work builds on the [automatic env variable detection](/blog/turbo-1-4-0) we added in 1.4.0.

## Changes to `package.json` hashing

The `package.json` file in each workspace is now _always_ considered an input for tasks in that workspace. This means that if you change the _definition_ for a task in `package.json`, we want to invalidate any caches from the previous definition.

This also counts for the `package.json` in the root. Changes to the root `package.json` will invalidate tasks in the root workspace.

This helps make Turborepo's cache a bit smarter, and less likely to trip up when task definitions change.

## Community

Since releasing [Turborepo v1.4 in August](/blog/turbo-1-4-0), we've seen incredible adoption and community growth:

- [9.5k+ GitHub Stars](https://github.com/vercel/turbo)
- [440k weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 15 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching), saving over a 1 year per week, up 2x since July

Turborepo is the result of the combined work of all of our contributors including our core team.

This release was brought to you by the contributions of: @7flash, @afady, @alexander-young, @atilafassina, @bguedes-moz, @bobaaaaa, @brunojppb, @chris-olszewski, @DoctorJohn, @erj826, @futantan, @gsoltis, @HosseinAgha, @ivov, @jaredpalmer, @joelhooks, @knownasnaffy, @laurentlucian, @leerob, @MarceloAlves, @mattpocock, @mauricekleine, @mehulkar, @Misikir, @nareshbhatia, @nathanhammond, @pakaponk, @PhentomPT, @renovate, @ruisaraiva19, @samuelhorn, @shemayas, @shuding, @t-i-0414, @theurgi, @tknickman, @yanmao-cc, and more!

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 6 0 (`apps/docs/content/blog/turbo-1-6-0.mdx`)

---
title: Turborepo 1.6
description: Turborepo 1.6 lets you use Turborepo in non-monorepos, prune for npm, and improves cache performance.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.6 featuring non-monorepo support, npm pruning, and cache performance.
date: "2022/10/21"
tag: "web development"
---

import { Tabs, Tab } from "fumadocs-ui/components/tabs";

# Turborepo 1.6

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Callout } from "@/components/geistdocs/callout";

<Date>Friday, October 21st, 2022</Date>

<Authors
  authors={[
    "mattpocock",
    "gregsoltis",
    "nathanhammond",
    "tomknickman",
    "anthonyshew",
    "jaredpalmer",
    "mehulkar",
    "chrisolszewski",
  ]}
/>

Turborepo 1.6 changes the game for Turborepo - you can now use it in **any project**.

- [**Turborepo in non-monorepos**](#any-codebase-can-use-turborepo): Seeing slow builds on your project? You can now use Turborepo to speed up builds in any codebase with a `package.json`.
- [**`turbo prune` now supports npm**](#prune-now-supported-on-npm): Pruning your monorepo is now supported in monorepos using `npm`, completing support for all major workspace managers.
- [**Faster caching**](#performance-improvements-in-the-cache): We've improved the way we handle local file writes, meaning a big speed-up of Turborepo's cache.

Update today by running `npm install turbo@latest`.

## Any codebase can use Turborepo

Turborepo helps speed up tasks in your codebase. Until now, we'd built Turborepo specifically for monorepos - codebases which contain multiple applications and packages.

Turborepo is fantastic in monorepos because they have so many tasks to handle. Each package and app needs to be built, linted, and tested.

But we got to thinking: lots of codebases that _aren't_ monorepos run plenty of tasks. Most CI/CD processes do a lot of duplicated work that would benefit from a [cache](/docs/crafting-your-repository/caching).

So we're excited to announce that **any codebase can now use Turborepo**.

Try it out now by [starting from the example](https://github.com/vercel/turbo/tree/main/examples/non-monorepo), or by adding Turborepo to an existing project:

### Add Turborepo to your project

1. **Install `turbo`:**

<Tabs items={["npm", "yarn", "pnpm"]} id="selected-pkg-manager">
  <Tab value="npm">
  ```bash title="Terminal"
  npm install turbo --save-dev
  ```

  </Tab>
  <Tab value="yarn">
  ```bash title="Terminal"
  yarn add turbo --dev
  ```

   </Tab>
  <Tab value="pnpm">
  ```bash title="Terminal"
  pnpm add turbo --save-dev
   ```

  </Tab>
</Tabs>

2. **Add a `turbo.json` file at the base of your new repository:**

<Tabs items={['Next.js', 'Vite']} storageKey="framework-preference">
  <Tab value="Next.js">
```json title="./turbo.json"
{
  "pipeline": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "lint": {
      "outputs": []
    }
  }
}
```
  </Tab>
  <Tab value="Vite">
```json title="./turbo.json"
{
  "pipeline": {
    "build": {
      "outputs": ["dist/**"]
    },
    "lint": {
      "outputs": []
    }
  }
}
```

Some Vite starters ship with a `package.json` that looks like this:

```json title="package.json"
{
  "scripts": {
    "build": "tsc && vite build"
  }
}
```

We recommend splitting these into a `lint` and `build` script.

```json title="package.json"
{
  "scripts": {
    "build": "vite build",
    "lint": "tsc"
  }
}
```

This enables `turbo` to schedule them separately.

  </Tab>
</Tabs>

3. **Try running `build` and `lint` with `turbo`:**

```bash title="Terminal"
turbo build lint
```

Congratulations - **you just ran your first build with `turbo`**. You can try:

- Running through the full [Quickstart](/docs).
- Check out our updated [Core Concepts docs](/docs/crafting-your-repository/caching) to understand what makes Turborepo special.

## When should I use Turborepo?

Turborepo being available for non-monorepos opens up a lot of new use cases. But when is it at its best?

### When scripts depend on each other

You should use `turbo` to run your `package.json` scripts. If you've got multiple scripts which all rely on each other, you can express them as Turborepo tasks:

```json title="turbo.json"
{
  "pipeline": {
    "build": {
      "outputs": ["dist/**"]
    },
    "lint": {
      // 'build' should be run before 'lint'
      "dependsOn": ["build"]
    },
    "test": {
      // 'build' should be run before 'test'
      "dependsOn": ["build"]
    }
  }
}
```

Then, you can run:

```bash title="Terminal"
turbo run lint test
```

Because you've said that `build` should be run before `lint` and `test`, it'll _automatically run `build` for you_ when you run `lint` or `test`.

Not only that, but it'll figure out the optimal schedule for you. Head to our core concepts doc on [optimizing for speed](/docs/crafting-your-repository/configuring-tasks).

### When you want to run tasks in parallel

Imagine you're running a [Next.js](https://nextjs.org/) app, and also running the [Tailwind CLI](https://tailwindcss.com/docs/installation). You might have two scripts - `dev` and `dev:css`:

```json title="package.json"
{
  "scripts": {
    "dev": "next",
    "dev:css": "tailwindcss -i ./src/input.css -o ./dist/output.css --watch"
  }
}
```

Without anything being added to your `turbo.json`, you can run:

```bash title="Terminal"
turbo run dev dev:css
```

Just like tools like [`concurrently`](https://www.npmjs.com/package/concurrently), Turborepo will automatically run the two scripts in parallel.

This is extremely useful for dev mode, but can also be used to speed up tasks on CI - imagine you have multiple scripts to run:

```bash title="Terminal"
turbo run lint unit:test e2e:test integration:test
```

Turborepo will figure out the fastest possible way to run all your tasks in parallel.

## Prune now supported on npm

Over the last several releases, we've been adding support for [`turbo prune`](/docs/reference/prune) on different workspace managers. This has been a challenge - `turbo prune` creates a subset of your monorepo, including pruning the dependencies in your lockfile. This means we've had to implement logic for each workspace manager separately.

We're delighted to announce that `turbo prune` now works for `npm`, completing support for all major package managers. This means that if your monorepo uses `npm`, `yarn`, `yarn 2+` or `pnpm`, you'll be able to deploy to Docker with ease.

Check out our previous [blog on `turbo prune`](/blog/turbo-0-4-0#experimental-pruned-workspaces) to learn more.

## Performance improvements in the cache

Before 1.6, Turborepo's local cache was a recursive copy of files on the system to another place on disk. This was _slow_. It meant that for every file that we needed to cache, we'd need to perform six system calls: open, read, and close on the source file; open, write, and close on the destination file.

In 1.6, we've cut that nearly in half. Now, when creating a cache, we create a single `.tar` file (_one_ open), we write to it in 1mb chunks (_batched_ writes), and then close it (_one_ close). The halving of system calls _also_ happens on the way back out of cache.

And we didn't stop there. Over the past month we've invested significantly in our build toolchain to enable CGO which unlocks usage of best-in-class libraries written in C. This enabled us to adopt [Zstandard](https://facebook.github.io/zstd/)'s `libzstd` for compression which gets us an algorithmic 3x performance improvement for compression.

After all of these changes we're regularly seeing performance improvements of more than 2x on local cache creation and more than 3x on remote cache creation. This gets even better the bigger your repository is, or the slower your device is (looking at you, CI). This means we've been able to deliver performance wins precisely to those who needed it the most.

---

### Apps Docs Content Blog Turbo 1 7 0 (`apps/docs/content/blog/turbo-1-7-0.mdx`)

---
title: Turborepo 1.7
description: Turborepo 1.7 focuses on improving developer experience by bringing more clarity to your tasks.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.7 featuring improved task clarity and developer experience.
date: "2023/01/11"
tag: "web development"
---

import { Tabs, Tab } from "fumadocs-ui/components/tabs";

import TurboInferenceImage from "../../public/images/blog/turbo-1-7-0/turbo-inference.png";

# Turborepo 1.7

import { Badge } from "@/components/ui/badge";
import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";

<Date>Wednesday, January 11th, 2023</Date>

<Authors
  authors={[
    "gregsoltis",
    "nathanhammond",
    "tomknickman",
    "anthonyshew",
    "jaredpalmer",
    "mehulkar",
    "chrisolszewski",
    "nicholasyang",
  ]}
/>

Turborepo 1.7 focuses on improving developer experience by bringing more clarity to your tasks:

- [**Improved support for long running tasks**](#schedule-your-long-running-tasks-with-confidence): Use `persistent: true` to mark non-terminating tasks so that `turbo` can alert you if you have dependencies on them.
- [**Better clarity for outputs**](#declare-your-outputs-for-improved-clarity): You'll now always need to declare your task outputs, improving transparency to what your tasks will cache.
- [**Globally installable**](#global-turbo): Install once, use everywhere. Turborepo can now be installed globally, and ran from any directory, not just from your repo root.
- [**“Error only” output mode**](#errors-only-output-mode-for-quieter-logs): Quiet your output logs to only show when a task fails.

Update today by running `npm install turbo@latest`, or by [installing globally](#global-turbo) <Badge>NEW</Badge> and running the [`set-default-outputs`](/docs/reference/turbo-codemod#set-default-outputs) codemod.

## Schedule your long-running tasks with confidence

To avoid misconfigurations that could result in tasks that never run, you can now tell Turborepo about tasks that won't exit on their own (like `dev` scripts) with a `persistent: true` [configuration option](/docs/reference/configuration#persistent). When this config is set on a task, Turborepo will ensure no other task can depend on this task. This is useful for `dev` tasks or test runners with `--watch` flags.

```diff title="turbo.json"
{
	"pipeline": {
		"dev": {
+			"persistent": true
		}
	}
}
```

Previously, if `Task B` depended on a persistent `Task A`, `Task B` would never execute, because `Task A` never exited. By declaring `Task A` as `persistent`, Turborepo will prevent this error scenario from happening.

Before this release, we had been recommending the use of `turbo run <task> --parallel` for persistent tasks. With `--parallel`, `turbo` would ignore your dependency graph and execute all your tasks at once.

While `--parallel` did provide a helpful escape hatch, it meant that users had to tell Turborepo **_how_** to run their tasks rather than declaring **_what_** a task is.

Rather than throwing away your entire topological dependency graph, it's much more precise for Turborepo to keep your dependency graph while guaranteeing that you don't depend on a process that won't exit with `persistent: true`.

## Global `turbo`

You can now run your Turborepo tasks from anywhere in your project once you've installed `turbo` globally. To do so, use:

<Tabs items={["npm", "yarn", "pnpm"]} storageKey="selected-pkg-manager">
  <Tab value="npm">
  ```bash title="Terminal"
  npm install turbo --global
  ```

</Tab>
<Tab value="yarn">
```bash title="Terminal"
yarn global add turbo
```

</Tab>
<Tab value="pnpm">
```bash title="Terminal"
pnpm add turbo --global
```

</Tab>
</Tabs>

`turbo` will now work in any project. To find your local `turbo` version, `turbo` will walk through a few steps, always looking upward from your current directory:

1. Find the nearest turbo.json.
2. If one is not found, find the first `package.json` with a `workspaces` property.
3. If one is not found, find the first `package.json`.

Your globally installed version of `turbo` will only be used when a locally installed version of `turbo` does not exist or cannot be found.

<ThemeAwareImage
  light={{
    alt: "Turborepo inference diagram showing how turbo finds your local turbo version",
    src: TurboInferenceImage,
    props: { width: 800, height: 400 },
  }}
  dark={{
    alt: "Turborepo inference diagram showing how turbo finds your local turbo version",
    src: TurboInferenceImage,
    props: { width: 800, height: 400 },
  }}
/>

`turbo --version` and `turbo bin` will show you the version and binary location, respectively, of the copy of `turbo` that will execute your tasks.
Additionally, running with `-vv` or `--verbosity=2` will always show if your local, or global `turbo` is being used.

```bash title="Terminal"
turbo --version --verbosity=2
2023-01-11T10:49:04.042-0500 [DEBUG] turborepo_lib::shim: No local turbo binary found at: /Users/knickman/Developer/vercel/my-awesome-monorepo/node_modules/.bin/turbo
2023-01-11T10:49:04.042-0500 [DEBUG] turborepo_lib::shim: Running command as global turbo
1.7.0
```

## Declare your `outputs` for improved clarity

Previously, if you did not specify an `outputs` key for a task, Turborepo would automatically attempt to cache all files in the `dist/` and `build/` directories.

This worked well for `build` tasks of specific frameworks, but this implicit behavior did not scale well as it applied to _all_ tasks. We've found that, across the many developers, teams, projects, and codebases using Turborepo, the assumption to automatically cache `dist/` and `build/` directories was causing problems for users.

In version 1.7, this behavior is removed and you will now need to explicitly tell turborepo what to cache.

```diff title="turbo.json"
{
  "pipeline": {
    "build": {
+     "outputs": ["dist/**", "build/**"]
    }
  }
}
```

If you were relying on the default cache output in Turborepo versions below 1.7, you can get the same behavior by running the [`@turbo/codemod set-default-outputs`](/docs/reference/turbo-codemod#set-default-outputs) codemod:

```bash title="Terminal"
npx @turbo/codemod set-default-outputs
```

Also note that you will no longer need to specify `outputs: []` because not caching anything is now the default behavior. The codemod will also remove this configuration from your tasks.

## “Errors only” output mode for quieter logs

To bring visibility to errors, community member [@dobesv](https://github.com/dobesv) contributed [a solution to only show errors instead of all logs from a task run](https://github.com/vercel/turbo/pull/2588). While debugging a pipeline, `--output-logs=errors-only` can be used to keep your signal-to-noise ratio high so you can focus on ensuring successful runs for your pipelines.
This can be used as a [configuration option](/docs/reference/configuration#outputlogs) or as a [CLI flag](/docs/reference/run#--output-logs-option)

```bash title="Terminal"
turbo build --output-logs=errors-only
```

## Community

Since releasing [Turborepo v1.6](/blog/turbo-1-6-0) and merging with [Turbopack](https://turborepo.dev/pack), we've seen incredible adoption and community growth:

- [18.7k+ GitHub Stars](https://github.com/vercel/turbo)
- [750k weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 30 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of our contributors including our core team.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 8 0 (`apps/docs/content/blog/turbo-1-8-0.mdx`)

---
title: Turborepo 1.8
description: Turborepo 1.8 brings better flexibility and more control to your codebase by improving turbo's understanding of your workspaces.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.8 featuring improved workspace understanding and codebase flexibility.
date: "2023/02/22"
tag: "web development"
---

import { Tabs, Tab } from "fumadocs-ui/components/tabs";

# Turborepo 1.8

import { Authors } from "@/components/blog/authors";
import { Badge } from "@/components/ui/badge";
import { Date } from "@/components/blog/date";

<Date>Wednesday, February 22th, 2023</Date>

<Authors
  authors={[
    "gregsoltis",
    "nathanhammond",
    "tomknickman",
    "anthonyshew",
    "jaredpalmer",
    "mehulkar",
    "chrisolszewski",
    "nicholasyang",
    "alexanderlyon",
  ]}
/>

Turborepo 1.8 brings better flexibility and more control to your codebase by improving `turbo`'s understanding of your workspaces.

- [**Workspace Configurations**](#workspace-configurations): You can now add a `turbo.json` configuration file in a workspace to override the root configuration in your repository.
- [**Automatic Workspace Scoping**](#automatic-workspace-scoping): Global `turbo` now automatically infers your current workspace so that it only runs that workspace’s tasks.
- [**Easier Migrations**](#easier-migrations): Automatically migrate to new versions of `turbo` with `npx @turbo/codemod migrate`.

Update today by running `npx @turbo/codemod migrate`.

## Workspace Configurations

In workspace directories, you can now add a `turbo.json` to:

- add tasks specific to that workspace
- override configuration for tasks

This will enable teams to scale ownership of the projects in their monorepos by moving away from global configuration to fine-grain control over tasks in workspaces.

For example, imagine your monorepo has a Next.js app and a SvelteKit app, and you want to use Turborepo to cache outputs of the `build` task. The Next.js `build` script creates a `.next` directory, whereas SvelteKit creates a `.svelte-kit` directory. Instead of adding both build directories in your root `outputs`, you can define the `outputs` key in the workspace instead:

```jsonc title="turbo.json"
{
  "pipeline": {
    "build": {
      "dependsOn": ["^codegen"],
      // no need to define outputs here!
    },
  },
}
```

```jsonc title="apps/my-nextjs-app/turbo.json"
{
  "extends": ["//"],
  "pipeline": {
    "build": {
      // dependsOn is inherited from root
      "outputs": [".next/**", "!.next/cache/**"],
    },
  },
}
```

```jsonc title="apps/my-sveltekit-app/turbo.json"
{
  "extends": ["//"],
  "pipeline": {
    "build": {
      // dependsOn is inherited from root
      "outputs": [".svelte-kit/**"],
    },
  },
}
```

The `extends` key in the Workspace Configurations enables workspace owners to use the best of the root `turbo.json` and customize the parts that makes their app different (The `"//"` sigil will look familiar if you’re used to [defining tasks to run from your root](/docs/crafting-your-repository/configuring-tasks#registering-root-tasks)).

Keys that **are** declared will replace the key from the root if those keys exist, overriding what is defined in your root configuration. Keys that **are not** declared are inherited from the root config.

In the example above, `outputs` is customized for both apps, while `dependsOn` is configured by the root `turbo.json` and remains `"^codegen"`.

[Learn more in the docs](/docs/crafting-your-repository/structuring-a-repository#specifying-packages-in-a-monorepo).

## Automatic Workspace Scoping

In [Turborepo v1.7](/blog/turbo-1-7-0), `turbo` became globally installable, giving you the power to run your tasks from anywhere in your codebase. However, `turbo` would still run tasks from the root, running tasks in other workspaces that you may not have intended to run.

With 1.8, `turbo` will automatically detect the workspace you are in and generate [the `--filter` syntax](/docs/reference/run#--filter-string) to scope your task to that workspace.

As an example, if your current directory is `apps/admin` and you use the `turbo build` command, `turbo` will run `turbo build --filter=admin` under the hood, focusing on the workspace that you are working on.

## Easier Migrations

Manually running individual codemods in the correct order is no longer required when upgrading Turborepo versions. `@turbo/codemod` now provides a simple `migrate` command which both upgrades your repo to the specified version (`latest` by default) of `turbo`, _and_ runs any codemods required.

Try it out now with `npx @turbo/codemod migrate`.

## Community

Since releasing [Turborepo v1.7](/blog/turbo-1-7-0) we've seen incredible adoption and community growth:

- [19.6k+ GitHub Stars](https://github.com/vercel/turbo)
- [987k weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 42 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 1 9 0 (`apps/docs/content/blog/turbo-1-9-0.mdx`)

---
title: Turborepo 1.9
description: Turborepo 1.9 focuses on improving observability for your task runs to better understand your caching behavior.
product: turborepo
type: overview
summary: Release notes for Turborepo 1.9 featuring improved task run observability and caching insights.
date: "2023/04/11"
tag: "web development"
---

# Turborepo 1.9

import { Authors } from "@/components/blog/authors";
import { ExperimentalBadge } from "@/components/geistdocs/experimental-badge";
import { Date } from "@/components/blog/date";

<Date>Monday, April 11th, 2023</Date>

<Authors
  authors={[
    "gregsoltis",
    "nathanhammond",
    "tomknickman",
    "anthonyshew",
    "jaredpalmer",
    "mehulkar",
    "chrisolszewski",
    "nicholasyang",
    "alexanderlyon",
  ]}
/>

Turborepo 1.9 focuses on improving observability for your task runs to better understand your caching behavior:

- [**Run Summaries**](#view-and-compare-task-runs): Use the `--summarize` flag to generate a summary of your task to compare against previous runs.
- [**Easier Starters**](#bring-your-own-starter): Use the `--example` flag with `npx create-turbo` to start from official Turborepo examples or custom repositories.
- [**Strict Environments** <ExperimentalBadge isLink={false} />](#strict-environments): Try enabling strict mode to restrict the environment variables your tasks have access to.

Update today by running `npx @turbo/codemod migrate`.

## View and compare task runs

You can now produce a JSON summary of your task run using the `--summarize` flag:

```bash title="Terminal"
turbo build --summarize
```

When this flag is enabled, Turborepo will generate a summary in `.turbo/runs/` that contains all the information necessary to understand how `turbo` interpreted your task's configuration and code.

```bash title="Terminal"
Tasks:    3 successful, 3 total
Cached:   0 cached, 3 total
Time:     1.707s
Summary:  /Users/acme/projects/acme/.turbo/runs/2Nn3X6nWDhP9ag8BnmivWRxHpHC.json
```

You can then compare summaries using your favorite JSON diffing tool to understand why you got a cache hit or a cache miss.

Learn more in the [docs](/docs/reference/run#--summarize).

## Bring your own starter

`create-turbo` now supports starting a new project from any of the official [Turborepo examples](https://github.com/vercel/turbo/tree/main/examples). Get started with an example using a single command:

```bash title="Terminal"
npx create-turbo@latest -e kitchen-sink
```

In your terminal UI, choose your preferred package manager and `create-turbo` will automatically convert the chosen example to your package manager of choice.

Additionally, you can use `create-turbo` with custom repository sources, allowing you to re-use your own custom starter or another starter from around the community:

```bash title="Terminal"
npx create-turbo -e https://github.com/your-org/turbo-starter
```

## Strict Environments <ExperimentalBadge>Experimental</ExperimentalBadge>

You can now use the `--env-mode=strict` flag to restrict the environment variables your tasks have access to. Your tasks will only be aware of the variables you explicitly state, creating a safer caching environment.

In `strict` mode, Turborepo will pass environment variables declared in:

- `globalEnv` and `globalPassThroughEnv` to all tasks
- `env` and `passThroughEnv` for each task

```json title="./turbo.json"
{
  // Available to all tasks
  "globalPassThroughEnv": ["GLOBAL_VAR_1"],

  // Available to all tasks and invalidates caches
  "globalEnv": ["GLOBAL_VAR_2"],

  "pipeline": {
    "build": {
      // Only available to `build` tasks
      "passThroughEnv": ["VAR_1"],

      // Available to `build` task and invalidates caches
      "env": ["VAR_2"]
    }
  }
}
```

In `strict` mode, this configuration will only expose four environment variables to your `build` tasks, helping you catch missing variables earlier in the development process.

`--env-mode` also supports `loose` and `infer`.

Learn more in the [docs](/docs/reference/run#--env-mode-option).

## Community

Since releasing [Turborepo v1.8](/blog/turbo-1-8-0) we've seen incredible adoption and community growth:

- [20.5k+ GitHub Stars](https://github.com/vercel/turbo)
- [1.1M weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 64 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 2 0 (`apps/docs/content/blog/turbo-2-0.mdx`)

---
title: Turborepo 2.0
date: 2024/6/4
description: Turborepo 2.0 is a milestone for the ergonomics of JavaScript and TypeScript monorepos.
product: turborepo
type: overview
summary: Release notes for Turborepo 2.0 featuring a new terminal UI, Watch Mode, and all-new documentation.
tag: "web development"
---

# Turborepo 2.0

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Callout } from "@/components/geistdocs/callout";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import UiGif from "../../public/images/blog/turbo-2-0/interactive-ui.gif";

<Date>Tuesday, June 4, 2024</Date>

<Authors authors={["chrisolszewski", "nicholasyang"]} />

Turborepo 2.0 improves the developer experience of JavaScript and TypeScript repositories, with features including:

- [**New terminal UI**](#new-terminal-ui): Interactive tasks and clearer logs
- [**Watch Mode**](#watch-mode): Dependency-aware task watcher for any tooling in your repository
- [**All-new documentation**](#all-new-documentation): Core monorepo concepts, refreshed API reference, and ecosystem tooling guides
- **Licensing and maintenance updates**: Upgraded to MIT license and added [Long Term Support policy](/docs/support-policy#lts-policy)

Update today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

Visit [the upgrading guide](/docs/crafting-your-repository/upgrading#upgrading-to-20) for update instructions. [Breaking changes](#breaking-changes) are listed below.

## New terminal UI

In [Turborepo 1.13](https://turborepo.dev/blog/turbo-1-13-0), we released an experimental interface to learn how a refined terminal UI could improve development velocity. Through [the RFC process](https://github.com/vercel/turbo/discussions/7802), we were able to work with the community on designing a revamped local experience, driven by your feedback. Thank you to those who participated.

Today, we’re releasing the new UI as stable, along with the highly requested features that it enables.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "The new terminal UI",
    src: UiGif,
    props: {
      width: 928,
      height: 522,
      className: "dark:hidden block rounded",
    },
  }}
  dark={{
    alt: "The new terminal UI",
    src: UiGif,
    props: {
      width: 928,
      height: 522,
      className: "hidden dark:block rounded",
    },
  }}
/>

### Improved clarity for logs

Before 2.0, `turbo` would output logs as a stream while you were working on your libraries and applications. This could be overwhelming at times, since the intermixed logs made it difficult to understand what was going on with a specific task.

In this iteration of the UI, you can select individual tasks using your arrow keys to inspect their logs one at a time, making it easier to read the logs that you want to focus on.

<Callout type="good-to-know">
  The streamed logs view from prior versions of `turbo` is still available for
  local development by using the `--log-order` flag. Note that tasks will not be
  interactive with this option and some tools may clear the terminal
  unexpectedly.
</Callout>

### Interactive tasks

Many tools allow for interacting with a script for important functionality. But, in previous versions of Turborepo, your scripts were trapped inside `turbo` so you couldn’t interact with them.

You can now enter the shell of individual tasks and pass inputs to your scripts via `stdin` by typing directly into the interface. This enables workflows like running specific test suites with [Jest](https://jestjs.io) or [Vitest](https://vitest.dev/), handling database migrations with [Drizzle](https://orm.drizzle.team/) or [Prisma](https://www.prisma.io/), and much more.

To mark a task as interactive, add `"persistent": true` to its definition:

```json title="./turbo.json"
{
  "tasks": {
    "dev": {
      "cache": false,
      "persistent": true // [!code highlight]
    }
  }
}
```

With the task selected in the UI, use the `Enter` key to enter the task’s shell and `CTRL+Z` to exit.

To learn more about persistent and interactive tasks, [visit the documentation](/docs/reference/configuration#persistent).

## Watch Mode

Turborepo's ability to run many tasks at once gives you tighter feedback loops that help you ship faster. To get the most out of Turborepo's parallelization when working locally, your tools need to have a "watcher" feature available to re-run your code whenever you make changes. Unfortunately, many common tools don't, and most tools aren't monorepo-aware, leading to problems with scripts that depend on other scripts in your repository.

Today, we're releasing Watch Mode to bring this functionality to all your tooling:

```bash title="Terminal"
turbo watch dev lint test
```

Using `turbo watch`, Turborepo will re-run tasks whenever you make changes to your source code. Tasks will be run using your dependency graph and configuration from `turbo.json`, just like `turbo run`.

[Learn more about Watch Mode in the documentation.](/docs/crafting-your-repository/developing-applications#watch-mode)

## All-new documentation

With this release, we’re also publishing revitalized documentation that builds on the strengths of prior versions. We’ve heard your feedback, so the docs now include:

- More monorepo fundamentals and how-tos
- Guides on integrating your favorite tools with Turborepo
- Clearer information architecture and improved search

[Visit the Turborepo documentation.](/docs)

## Breaking changes

Visit [the upgrading guide](/docs/crafting-your-repository/upgrading#upgrading-to-20) for instructions on how to update to 2.0.

### Configuration

<Callout type="info">
  Breaking changes for `turbo.json` can be updated using `npx @turbo/codemod
  migrate`.
</Callout>

- Ignore `turbo` field in `package.json` ([PR](https://github.com/vercel/turbo/pull/8023))
- Turborepo’s default disk cache location moved to `.turbo/cache` from `node_modules/.cache` ([PR](https://github.com/vercel/turbo/pull/8126))
- `pipeline` key in `turbo.json` renamed to `tasks` ([PR](https://github.com/vercel/turbo/pull/8157))
- File globs for directories in `inputs`/`outputs` include the directory's contents (e.g. `dist` and`dist/` equal `dist/**`) ([PR](https://github.com/vercel/turbo/pull/8180))
- `outputMode` key renamed to `outputLogs` for clarity and to match the `--output-logs` flag ([PR](https://github.com/vercel/turbo/pull/8149))
  - This change will be reflected in Run Summaries in `resolvedTaskConfig`
- Error on environment variable syntax in `dependsOn` and `globalDependencies` (deprecated since 1.4) ([PR](https://github.com/vercel/turbo/pull/8026))
- `globalDotEnv` and `dotEnv` removed in favor of including `.env` files in `inputs` ([PR](https://github.com/vercel/turbo/pull/8181))
- `--ignore` removed in favor of `--filter` and graph correctness changes below ([PR](https://github.com/vercel/turbo/pull/8201))

### Correctness

- Strict Mode for environment variables is now the default, moving from Loose Mode ([PR](https://github.com/vercel/turbo/pull/8182))
- Workspace root directory is now an implicit dependency of all packages ([PR](https://github.com/vercel/turbo/pull/8202))
- Removed `--scope` flag (deprecated since 1.2) ([PR](https://github.com/vercel/turbo/pull/7970))
- Packages must have a `name` in `package.json` ([PR](https://github.com/vercel/turbo/pull/8152))
- `packageManager` field in root `package.json` is now required ([PR](https://github.com/vercel/turbo/pull/8017))
- `engines` field in root `package.json` is now used in hashing ([PR](https://github.com/vercel/turbo/pull/8173))
- `--filter` no longer infers namespaces for package names ([PR](https://github.com/vercel/turbo/pull/8137))
- `--filter` now errors when no package names or directories are matched ([PR](https://github.com/vercel/turbo/pull/8142))
- `--only` restricts task dependencies instead of only package dependencies ([PR](https://github.com/vercel/turbo/pull/8163))

### Other

- Minimum package manager version support for npm and pnpm updated to 8 ([Source](/docs/support-policy#package-managers))
- Remove package manager argument from `create-turbo`, replaced by option ([PR](https://github.com/vercel/turbo/pull/8150))

## Community

We're excited to see the continued growth and adoption of Turborepo:

- [25.2k+ GitHub Stars](https://github.com/vercel/turbo)
- [2.3m+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 347 years of compute time saved using [Vercel Remote Cache](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew), [Chris](https://github.com/chris-olszewski), [Greg](https://github.com/gsoltis), [Mehul](https://github.com/mehulkar), [Mitch](https://github.com/Zertsov), [Nicholas](https://github.com/NicholasLYang), and [Tom](https://github.com/tknickman).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. If you haven't already, join the conversation on [GitHub](https://github.com/vercel/turbo) and [Discord](/discord).

---

### Apps Docs Content Blog Turbo 2 1 0 (`apps/docs/content/blog/turbo-2-1-0.mdx`)

---
title: Turborepo 2.1
date: 2024/08/27
description: Turborepo 2.1 improves integration with your repository with affected package detection, and repository exploration tools.
product: turborepo
type: overview
summary: Release notes for Turborepo 2.1 featuring affected package detection and repository exploration tools.
tag: "web development"
---

# Turborepo 2.1

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Callout } from "@/components/geistdocs/callout";

<Date>Tuesday, August 27th, 2024</Date>

<Authors
  authors={[
    "tomknickman",
    "anthonyshew",
    "chrisolszewski",
    "nicholasyang",
    "dimitrimitropoulos",
  ]}
/>

Turborepo 2.1 improves integration with your repository, with features like:

- [**Affected package graph detection**](#run-tasks-for-changed-packages-with---affected): Only run tasks with changes using `--affected`
- [**Repository exploration tools**](#repository-exploration-tools): Find packages and tasks faster with `turbo ls` and `turbo run`
- [**Terminal UI improvements**](#terminal-ui-improvements): Log selection, task search, resizing, and more
- [**Expanded configuration options**](#expanded-configuration-options): More flexibility for defaults using `turbo.json`

Update today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

## Run tasks for changed packages with `--affected`

Turborepo’s [Remote Caching](/docs/core-concepts/remote-caching) shares a single cache across all of your machines,
so you never have to do the same work twice. But, what if you could ignore unchanged packages altogether?

You can now use the `--affected` flag with `turbo run` to automatically target packages with changes between the latest commit of your current branch, and the default branch of your repository (usually `main` or `master`).
`turbo` will use your [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph) to ensure tasks are run for packages with direct changes or changes to internal dependencies.

```bash title="Terminal"
turbo run lint test --affected
```

You'll want to use this flag in situations like:

- You're running many tasks across packages in your monorepo, and only want to run those tasks in packages with code changes.
- You’re _not_ using a Remote Cache, but still want to do as little work as possible in CI.
- You _are_ using a Remote Cache, and you’re in a large repository. By minimizing the amount of tasks that will be restored from cache, there will be less data to send across the network, resulting in faster cache restoration.
- You’re already using [advanced filtering techniques](/docs/reference/run#advanced-filtering-examples) or [`turbo-ignore`](/docs/reference/turbo-ignore) to create the same or similar behavior as `--affected`. You likely have the opportunity to simplify your scripting using this new flag.

To learn more, [visit the documentation](/docs/reference/run#--affected).

## Repository exploration tools

As a repository grows and changes, it can be difficult to quickly find what you’re looking for.
We want to quickly surface your tasks, packages, and their relationships to make understanding your repository faster and easier.

### `turbo run`

Use `turbo run` (with no task arguments) to get a list of the available tasks in your repository. This command also works with [filters](/docs/crafting-your-repository/running-tasks#using-filters) and [Automatic Package Scoping](/docs/crafting-your-repository/running-tasks#automatic-package-scoping).

```bash title="Terminal"
# List all tasks in the repository
turbo run

# List tasks in a specific package
turbo run --filter=@repo/ui

# Using Automatic Package Scoping
cd packages/ui && turbo run
```

[Visit the documentation](/docs/reference/run) to learn more.

### `turbo ls`

Use `turbo ls` to get a list of all the packages in your repository with their locations, or filter to a specific package to see a summary of its internal dependencies and tasks.
`turbo ls` also supports `--filter`, and `--affected`, making it easy to gather a list of changed packages.

```bash title="Terminal"
# List all packages in the repository
turbo ls

# List dependencies and tasks for the `web` package
turbo ls web

## List affected packages
turbo ls --affected
```

<Callout>
  `turbo ls` supports an experimental `--output` flag that can be used to return
  results in a specific format. For example, `--output=json` can be used to more
  easily create inputs for other tools or custom scripts. If you were previously using
  `turbo build --dry=json` _only_ to retrieve a list of changed packages,
  give `turbo ls --affected --output=json` a try. Visit the docs for more information and
  leave feedback on output format on the `turbo ls`
[RFC](https://github.com/vercel/turborepo/discussions/8811).

</Callout>

[Visit the documentation](/docs/reference/ls) to learn more.

## Terminal UI Improvements

In Turborepo 2.0, we released a [new terminal UI](https://turborepo.dev/blog/turbo-2-0#new-terminal-ui) to improve clarity for logs and allow for interactive tasks in local development. We heard your feedback, and prioritized polishing this UI, releasing improvements in patches to 2.0 and in this 2.1 release:

- Highlighting of logs for copying to clipboard ([PR](https://github.com/vercel/turborepo/pull/8713))
- Search through task list ([PR](https://github.com/vercel/turborepo/pull/9042))
- Cleaner layout resizing when your terminal changes size ([PR](https://github.com/vercel/turborepo/pull/8996))
- New icon for cache hits in task list ([PR](https://github.com/vercel/turborepo/pull/8869))
- Task status indicators updated when Watch Mode triggers a restart ([PR](https://github.com/vercel/turborepo/pull/8960))
- Output logs are respected after the terminal UI exits ([PR](https://github.com/vercel/turborepo/pull/8612))

Building a great terminal UI experience has unique challenges, and we’re continuing to iterate on this experience. We appreciate your continued feedback as we keep up our work on creating great UI for monorepos.

## Expanded configuration options

In this release, we’re adding more keys to `turbo.json` to give you more flexibility for your repository’s defaults. The following keys are new in this release:

```json title="turbo.json"
{
  "envMode": "loose",
  "daemon": false,
  "cacheDir": "./my-custom-directory/"
}
```

You may have been using the flag equivalents for these configurations on many or all of your `turbo` invocations, littering your codebase with commands like:

```bash title="Terminal"
turbo run build --env-mode=loose --no-daemon --cache-dir=./my-custom-directory
```

These can now be simplified with a centralized configuration in `turbo.json` using Turborepo’s existing configuration model:

- `turbo.json` sets the defaults for your repository.
- [System environment variables](/docs/reference/system-environment-variables) customize behavior in a specific environment.
- Flags customize behavior for specific invocations of `turbo`.

To learn more about available options and configurations, [visit the documentation](/docs/reference/configuration).

## Other improvements

- We’d like to especially thank [Shaharking](https://github.com/Shaharking) for their contribution in [#9023](https://github.com/vercel/turborepo/pull/9023) to make the colors for task names in streamed UIs deterministic, closing [#2564](https://github.com/vercel/turborepo/issues/2564). This makes it easier to compare tasks across `turbo run` invocations.

View the full changelog at [`vercel/turborepo`](https://github.com/vercel/turborepo/releases/tag/v2.1.0).

## Community

Since releasing [Turborepo 2.0](/blog/turbo-2-0) we've seen incredible adoption and community growth:

- [25.9k+ GitHub Stars](https://github.com/vercel/turbo)
- [2.9M+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 428 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team.

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 2 2 0 (`apps/docs/content/blog/turbo-2-2-0.mdx`)

---
title: Turborepo 2.2
date: 2024/10/18
description: Turborepo 2.2 adds a new command to query your repository, cache safety improvements, and intelligent affected filters.
product: turborepo
type: overview
summary: Release notes for Turborepo 2.2 featuring repository queries, cache safety, and affected filters.
tag: "web development"
---

# Turborepo 2.2

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Callout } from "@/components/geistdocs/callout";
import { ExperimentalBadge } from "@/components/geistdocs/experimental-badge";

<Date>Friday, October 18th, 2024</Date>

<Authors
  authors={[
    "tomknickman",
    "anthonyshew",
    "chrisolszewski",
    "nicholasyang",
    "dimitrimitropoulos",
  ]}
/>

Turborepo 2.2 brings a new repository query command, along with other improvements, including:

- [**Repository queries** <ExperimentalBadge isLink={false} />](#query-your-repository): Explore your repository like never before with `turbo query`
- [**Improved cache safety**](#improved-cache-safety): Easily diagnose and fix missing environment variable dependencies, and incorrect cache configurations
- [**Zero-configuration comparisons for affected packages**](#zero-configuration-comparisons-with---affected): Automatically target packages with changes in GitHub workflows

Update today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

## Query your repository <ExperimentalBadge>Experimental</ExperimentalBadge>

In Turborepo 2.2, we're introducing [`turbo query`](/docs/reference/query)—a new command that
allows running [GraphQL](https://graphql.org/) queries against Turborepo's repository data. Turborepo computes lots of data about your repository
in order to execute your tasks with maximum efficiency. This includes your package dependency graph, changed packages, task dependencies, log output from your tasks, and more.
This data can be useful for scripting, refactoring, determine what to run in CI, and discovering other insights into your codebase.

To get started, run `turbo query` to open GraphiQL—a local IDE for writing GraphQL queries
that supports interactive schema exploration, documentation, and sending queries.

You can also pass queries directly as a string or file path:

```bash title="Terminal"
turbo query "query { package(name: \"web\") { name } }"
turbo query query.gql
```

### Examples

Get the name and path for all [affected packages](/docs/reference/run#--affected) that have a `test` task.

```graphql title="affected-packages.gql"
{
  affectedPackages(
    base: "main"
    head: "HEAD"
    filter: { has: { field: TASK_NAME, value: "test" } }
  ) {
    items {
      name
      path
    }
  }
}
```

Get a specific package and its direct dependencies.

```graphql title="direct-dependencies.gql"
query {
  package(name: "cli") {
    directDependencies {
      name
    }
  }
}
```

Find all packages with more than 10 immediate dependents.

```graphql title="filter.gql"
query {
  packages(
    filter: { greaterThan: { field: DIRECT_DEPENDENT_COUNT, value: 10 } }
  ) {
    name
  }
}
```

Turborepo has added APIs for structured data in the past, such as [run summaries](/docs/reference/run#--summarize), [dry run](/docs/reference/run#--dry----dry-run), and [`ls`](/docs/reference/ls).
However, these APIs have some limitations. First, they're centered around a single run, not general repository info. Second, as we added more fields, the output quickly became very large.
We needed a way to query repository data in a run-agnostic fashion, and make the returned data more customizable.

We would like to thank [@maschwenk](https://github.com/maschwenk), [@rafaeltab](https://github.com/rafaeltab) and [@weyert](https://github.com/weyert) for their early feedback on this feature.

To learn more, [visit the documentation](/docs/reference/query), and leave feedback for this new experimental command on the `turbo query` [RFC](https://github.com/vercel/turborepo/discussions/9170).

## Improved cache safety

Caching tasks is one of the most powerful features of Turborepo, speeding up builds and other tasks by only re-running what has changed.
With Turborepo 2.2, we're releasing some improvements to help configure cache inputs and outputs, and warn you when things don't look quite correct.

### Platform environment variables

When deploying your applications, you likely already have environment variables configured in your production environment. Now, for supported platforms, Turborepo will
automatically check these environment variables against your `turbo.json` configuration to ensure that you've correctly [accounted for them](/docs/crafting-your-repository/using-environment-variables#adding-environment-variables-to-task-hashes),
and will warn you about any missing environment variables.

Any platform can support this feature by implementing the [`TURBO_PLATFORM_ENV`](/docs/reference/system-environment-variables) environment variable in to the build environment.

[Vercel](https://vercel.com) is supported today, and we will update documentation as more platforms become available.

Learn more about [platform environment variables](/docs/crafting-your-repository/using-environment-variables#platform-environment-variables).

### Warnings for empty cache configurations

When running tasks, Turborepo will now warn you if a task is configured to cache an empty directory.
This can be a common mistake, and can lead to accidental broken builds. This is enabled by default in 2.2.

Learn more about [configuring outputs](/docs/crafting-your-repository/configuring-tasks#specifying-outputs).

### Improvements to `eslint-config-turbo`

Turborepo automatically adds prefix wildcards to your env key for [common frameworks](/docs/crafting-your-repository/using-environment-variables#framework-inference).
If you're using one of the supported frameworks, you don't need to specify environment variables that begin with the framework's prefix.

Now in Turborepo 2.2, `eslint-config-turbo` supports this feature as well, ensuring the warnings from the plugin are accurate and actionable.

Learn more about [`eslint-config-turbo`](/docs/reference/eslint-config-turbo).

## Zero-configuration comparisons with `--affected`

In Turborepo 2.1, we released the [`--affected`](/docs/reference/run#--affected) flag which can be used with [`turbo run`](/docs/reference/run) and [`turbo ls`](/docs/reference/ls) to automatically target changed packages.
In 2.2, we're taking it a step further by introducing automatic comparisons when running [`--affected`](/docs/reference/run#--affected) in a GitHub workflow—making common use cases even smarter.

- For workflows running in response to a [pull request](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request), the base of the comparison is automatically set to the base of the pull request. This ensures `turbo` considers any files changed in the pull request when determining the affected packages.
- For workflows running in response to a [push](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#push), the base of the comparison is automatically set to commit before your latest push.

Learn more about [`--affected`](/docs/crafting-your-repository/constructing-ci#using---affected-in-github-actions).

## Community

Since releasing [Turborepo 2.1](/blog/turbo-2-1-0) we've seen incredible adoption and community growth:

- [26.2k+ GitHub Stars](https://github.com/vercel/turbo)
- [3.2M+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 477 years of compute time saved through [Remote Caching on Vercel](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team.

View the full [changelog](https://github.com/vercel/turborepo/releases/tag/v2.2.0).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 2 3 (`apps/docs/content/blog/turbo-2-3.mdx`)

---
title: Turborepo 2.3
date: 2024/11/14
description: Turborepo 2.3 introduces the Boundaries RFC, along with several ergonomics improvements.
product: turborepo
type: overview
summary: Release notes for Turborepo 2.3 featuring the Boundaries RFC, package task shortcuts, and cache control.
tag: "web development"
---

# Turborepo 2.3

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Callout } from "@/components/geistdocs/callout";

<Date>Tuesday, November 14th, 2024</Date>

<Authors authors={["chrisolszewski", "nicholasyang", "anthonyshew"]} />

Turborepo 2.3 introduces several ergonomics improvements:

- [**Boundaries RFC**](#boundaries-rfc): Enforce constraints to maintain developer experience
- [**Package task shortcuts**](#package-task-shortcuts): Execute tasks with `turbo run package#task`
- [**Simplified cache control**](#simplified-cache-control): Easier management of cache sources using a single flag

Update today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

## Boundaries RFC

Monorepos unlock greater iteration speed and incredible flexibility, but also introduce new challenges:

- How do we make sure the public API of a package is respected?
- How do we communicate where code can and cannot be used to all of our developers?
- How can we ensure packages are only used in the right context?

These are only a few examples of a key question when building in monorepos: How do we communicate and enforce the structural integrity of the Workspace?

<Callout type="info">
  At the time of publishing this post, the Boundaries RFC is only an initial
  draft. The implementation described below is subject to change. Please see the
  RFC itself for the most up to date information.
</Callout>

[The Boundaries RFC](https://github.com/vercel/turborepo/discussions/9435) is our initial proposal for this problem. In our current approach, we want you to be able to incrementally adopt Boundaries in one line of code:

```json title="turbo.json"
{
  "boundaries": true
}
```

Additionally, we want to create a tagging system so you can mark domains, concerns, contexts, and other useful metadata with custom Boundaries.

```json title="apps/ui/turbo.json"
{
  "extends": ["//"],
  "boundaries": {
    "tags": ["library", "ui", "frontend", "beta"],
    "allowDependencyOn": ["library", "frontend"],
    "denyDependencyFrom": ["backend", "stable"]
  }
}
```

We also plan for you to be able to allowlist existing diagnostics with a flag:

```bash title="Terminal"
turbo boundaries --exclude-errors
```

This way, you can enforce Boundaries for new code and gradually fix existing issues.

We're looking forward to hearing your ideas and feedback on [the Boundaries RFC](https://github.com/vercel/turborepo/discussions/9435).

## Package task shortcuts

You can now run tasks using the fully qualified task identifier:

```bash title="Terminal"
turbo run web#build
```

This is more convenient than the equivalent command using `--filter` (`turbo run build --filter=web`) and allows for more precision if you have multiple tasks that you'd like to target:

```bash title="Terminal"
turbo run web#build docs#lint
```

[Learn more in the documentation.](/docs/crafting-your-repository/running-tasks#filtering-by-package)

## Simplified cache control

Previously, the `--remote-only` and `--no-cache` flags were used to manage the sources and caching for your output artifacts. However, we've seen how they can cause confusion, and there are gaps in control as far as reading and writing to local and Remote Caches.

To refine this, we've introduced a new `--cache` flag that brings these flags together - and provides more power.

```bash title="Terminal"
turbo run build --cache=local:rw,remote:r
```

Using `local` and `remote`, you can control the reading and writing behavior of the `turbo` invocation. Learn more in the [documentation](/docs/reference/run#--cache-options).

## Continued improvements for `turbo query`

In 2.2, we introduced `turbo query`, a feature built for examining your repository using Turborepo's knowledge of your package and task graphs. We've iterated further on this feature to provide you with even more powerful queries:

- Implemented reverse file tracing to find which files depend on a specific file
- Filters for file tracing to find type-only dependencies
- Package names that you provide are now validated to ensure that they exist

## Community

Since releasing [Turborepo 2.2](/blog/turbo-2-2-0), we've seen great adoption and community growth:

- [26.3+ GitHub Stars](https://github.com/vercel/turbo)
- [3.4M+ weekly NPM downloads](https://www.npmjs.com/package/turbo)
- 496 years of compute time saved using [Vercel Remote Cache](https://vercel.com/docs/concepts/monorepos/remote-caching)

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew), [Chris](https://github.com/chris-olszewski), [Nicholas](https://github.com/NicholasLYang), and [Tom](https://github.com/tknickman).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice.

---

### Apps Docs Content Blog Turbo 2 4 (`apps/docs/content/blog/turbo-2-4.mdx`)

---
title: Turborepo 2.4
date: 2025/1/31
description: "Experimental Boundaries, Terminal UI improvements, experimental Watch Mode caching, and more."
product: turborepo
type: overview
summary: Release notes for Turborepo 2.4 featuring Boundaries, TUI improvements, and Watch Mode caching.
tag: "web development"
---

# Turborepo 2.4

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Accordions, Accordion } from "@/components/geistdocs/accordion";
import { ExperimentalBadge } from "@/components/geistdocs/experimental-badge";
import { Kbd } from "@/components/ui/kbd";
import { Callout } from "@/components/geistdocs/callout";

<Date>Friday, January 31st, 2025</Date>

<Authors authors={["nicholasyang", "anthonyshew", "chrisolszewski"]} />

Turborepo 2.4 includes a number of improvements to enhance your repository:

- [**Boundaries <ExperimentalBadge>Experimental</ExperimentalBadge>**](#boundaries): A first look at Boundaries in Turborepo
- [**Terminal UI improvements**](#terminal-ui-improvements): Persistent preferences and new features
- [**Watch Mode caching <ExperimentalBadge>Experimental</ExperimentalBadge>**](#watch-mode-caching): Develop faster in Watch Mode
- [**Circular dependency recommendations**](#circular-dependency-recommendations): Adopt Turborepo in large repos more easily
- [**`schema.json` in `node_modules`**](#schemajson-in-node_modules): Versioned configuration validation from within your repository
- [**ESLint Flat Config support**](#eslint-flat-config-support): `eslint-config-turbo` and `eslint-plugin-turbo` updated for ESLint v9

Upgrade today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

## Boundaries <ExperimentalBadge>Experimental</ExperimentalBadge>

Turborepo is built on top of package manager Workspaces, leaning on ecosystem conventions as a part of determining your repository's task caching. However, this requires that all developers in the repository know and adhere to those conventions.

We're introducing Boundaries, an experimental feature to catch places in the repository where these best practices aren't being followed. This makes caching safer, and ensures your repository is prepared to use future Turborepo features safely.

Try it today using:

```bash title="Terminal"
turbo boundaries
```

This early iteration of Boundaries includes finding two types of monorepo mistakes:

- Importing a file outside of the package's directory
- Importing a package that is not specified in dependencies

<Callout type="info" title="Boundaries RFC">
  We look forward to hearing your feedback on [the Boundaries
  RFC](https://github.com/vercel/turborepo/discussions/9435), which includes
  proposals for these built-in diagnostics as well as custom-built Boundaries.
</Callout>

To learn more, [visit the documentation](/docs/reference/boundaries).

## Terminal UI improvements

We've continued iterating on the terminal UI, originally released in [Turborepo 2.0](/blog/turbo-2-0).

### Persistent preferences

In previous versions of Turborepo, you would need to reset the terminal UI to your desired state every time you would run `turbo`. In Turborepo 2.4, we'll persist several of the UI selections that you've made, including:

- The task that you had previously selected will be pre-selected the next time you run `turbo`. Give your up and down arrow keys a rest.
- Task list visibility, as described below
- Task selection pinning, as described below

Together, persisting these preferences creates a more seamless experience across `turbo` invocations, restoring the UI to the state from the previous run of `turbo`.

### New keybinds

We've added more functionality to the terminal UI to make it easier to work with your tasks and logs.

- **<Kbd>h</Kbd> to toggle task list**: You're often focused on one of your tasks, so you don't need to see your task list, all the time. Press the <Kbd>h</Kbd> key to show and hide the task list. This feature is a persistent preference, as described above.
- **<Kbd>c</Kbd> to copy logs**: Once you've highlighted a set of logs with your mouse, press <Kbd>c</Kbd> to copy the logs to your system clipboard.
- **<Kbd>j</Kbd> and <Kbd>k</Kbd> to select tasks**: You can now use <Kbd>j</Kbd> and <Kbd>k</Kbd> in addition to <Kbd>↑</Kbd> and <Kbd>↓</Kbd> to cycle through the task list. Vim users rejoice.
- **<Kbd>p</Kbd> to pin the selected task**: Selecting a task sets a "pin", meaning it will continue to be selected as your tasks change states. You can release the pin (or pin the task you're hovering) by pressing <Kbd>p</Kbd>. This feature is a persistent preference, as described above.
- **<Kbd>u</Kbd> and <Kbd>d</Kbd> to scroll logs**: You can now press <Kbd>u</Kbd> to scroll your logs up and <Kbd>d</Kbd> to scroll your logs down.
- **<Kbd>m</Kbd> to learn more**: Pressing <Kbd>m</Kbd> will show a popup listing all of the available keybinds.

[Visit the documentation to learn more.](/docs/crafting-your-repository/developing-applications)

## Watch Mode caching <ExperimentalBadge>Experimental</ExperimentalBadge>

[Watch Mode](/docs/crafting-your-repository/developing-applications#watch-mode) is a monorepo-aware watcher that re-runs tasks according to your [Task Graph](/docs/core-concepts/package-and-task-graph#task-graph). This opens up brand new ways to work in monorepos by leveraging a single, global, dependency-aware watcher, rather than many smaller, less powerful watcher scripts.

In this release, we're adding caching as an experimental feature in Watch Mode. To activate it, use the `--experimental-write-cache` flag:

```bash title="Terminal"
turbo watch dev --experimental-write-cache
```

To learn more about Watch Mode, [visit the documentation](/docs/reference/watch).

## Circular dependency recommendations

Circular dependencies are loops in your package graph that create non-deterministic cycles in Turborepo's [Task Graph](/docs/core-concepts/package-and-task-graph#task-graph). However, if there is a loop in your task graph, Turborepo is unable to determine which task comes before which, since they both depend on each other.

While adopting Turborepo in your monorepo, you may find circular dependencies as Turborepo create a more sophisticated, faster Task Graph than your previous task runner. Previously, Turborepo would naively list all of the packages involved in the cycle or cycles that exist in the repository's [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph). Now, Turborepo will include the dependency relationships that need to be broken up to get rid of the cycles in your graph.

Compare the before and after of the terminal printouts below:

<Tabs items={["After", "Before"]}>
<Tab value="After">

```txt title="Terminal"
  × Invalid package dependency graph:
  ╰─▶ Cyclic dependency detected:
  │     @repo/logger, blog, storefront, @repo/ui
  │     The cycle can be broken by removing any of these sets of dependencies:
  │     { @repo/ui -> @repo/logger, @repo/ui -> storefront }
  │     { @repo/logger -> @repo/ui, @repo/ui -> storefront }
  │
  ╰─▶   api, admin
        The cycle can be broken by removing any of these sets of dependencies:
        { admin -> api }
        { api -> admin }
```

</Tab>

<Tab value="Before">

```txt title="Terminal"
  × Invalid package dependency graph: Cyclic dependency detected:
  │     @repo/logger, storefront, @repo/ui, blog
  │     api, admin
  ╰─▶ Cyclic dependency detected:
        @repo/logger, storefront, @repo/ui, blog
        api, admin
```

</Tab>
</Tabs>

## `schema.json` in `node_modules`

A `schema.json` file provides auto-complete and validation in your editor for JSON files. We have a web-accessible version of the `schema.json` for `turbo.json` hosted at [`https://turborepo.dev/schema.json`](https://turborepo.dev/schema.json), but some developers prefer to get the file from `node_modules` to stay synced with the installed version of `turbo`.

Starting in this release, `schema.json` is available in `node_modules` once you've run your package manager's install command:

```json title="turbo.json"
{
  "$schema": "./node_modules/turbo/schema.json"
}
```

<Callout title="node_modules location">
  We recommend installing `turbo` at the root of your repository, so the path
  for the schema should point to `node_modules` at the root of your repository.
  In [Package Configurations](/docs/reference/package-configurations), you may
  need to use a path like `../../node_modules/turbo/schema.json`.
</Callout>

[Visit the documentation](/docs/getting-started/editor-integration#sourcing-from-node_modules) for more information.

## ESLint Flat Config support

Turborepo 2.4 introduces support for ESLint v9 in `eslint-config-turbo` and `eslint-plugin-turbo`, following the end-of life for ESLint v8 on October 5, 2024.

<Tabs items={["eslint-config-turbo", "eslint-plugin-turbo"]}>

<Tab value="eslint-config-turbo">

```ts title="./packages/eslint-config/index.js"
import turboConfig from "eslint-config-turbo/flat";

export default [
  ...turboConfig,
  // Other configuration
];
```

</Tab>

<Tab value="eslint-plugin-turbo">

```ts title="./packages/eslint-config/index.js"
import turbo from "eslint-plugin-turbo";

export default [
  {
    plugins: {
      turbo,
    },
    rules: {
      "turbo/no-undeclared-env-vars": "error",
    },
  },
  // Other configuration
];
```

</Tab>

</Tabs>

The configuration and plugin remain backward compatible for those still using ESLint v8 to ensure a smooth transition.

For more information, [visit the documentation](/docs/reference/eslint-config-turbo).

## Other changes

<Accordions>
  <Accordion title="Features (5)">

    - feat(link): add `--yes` and `--scope` flags to `link`
    ([#9466](https://github.com/vercel/turborepo/pull/9466))
    - feat(prune): add `--use-gitignore` flag ([#9797](https://github.com/vercel/turborepo/pull/9797))
    - feat: remote cache upload timeout ([#9491](https://github.com/vercel/turborepo/pull/9491))
    - feat: update `eslint-config-turbo` to support ESLint Flat Config. ([#9502](https://github.com/vercel/turborepo/pull/9502))
    - feat: respect gitignore during turbo prune ([#9711](https://github.com/vercel/turborepo/pull/9711))

  </Accordion>
  <Accordion title="Fixes (29)">

    - fix(windows): fix env var glob casing ([#9429](https://github.com/vercel/turborepo/pull/9429))
    - fix(cache): allow force to override any cache settings ([#9454](https://github.com/vercel/turborepo/pull/9454))
    - fix(cache): no longer let remoteCache.enable override force ([#9684](https://github.com/vercel/turborepo/pull/9684))
    - fix(cache): suggest proper --cache flag for --remote-cache-read-only ([#9701](https://github.com/vercel/turborepo/pull/9701))
    - fix(cache): avoid warning if TURBO_FORCE, TURBO_REMOTE_ONLY, and TURBO_CACHE ([#9704](https://github.com/vercel/turborepo/pull/9704))
    - fix(affected): consider both source and destination as changed ([#9422](https://github.com/vercel/turborepo/pull/9422))
    - fix(env): add DISPLAY to default pass through ([#9511](https://github.com/vercel/turborepo/pull/9511))
    - fix(env): allow `passThroughEnv` to negate built ins and `globalPassThroughEnv` ([#9680](https://github.com/vercel/turborepo/pull/9680))
    - fix(cli): error on out of place run args ([#9445](https://github.com/vercel/turborepo/pull/9445))
    - fix(daemon): limit number of git children ([#9572](https://github.com/vercel/turborepo/pull/9572))
    - fix(examples): create-turbo dependencies with npm ([#9580](https://github.com/vercel/turborepo/pull/9580))
    - fix(examples): add missing ESLint dependency ([#9640](https://github.com/vercel/turborepo/pull/9640))
    - fix(examples): basic generator ([#9687](https://github.com/vercel/turborepo/pull/9687))
    - fix(examples): bug in design system example ([#9284](https://github.com/vercel/turborepo/pull/9284))
    - fix(example): remove conflict css property from with-tailwind example ([#9816](https://github.com/vercel/turborepo/pull/9816))
    - fix(berry): add yarn berry support for built dependencies meta when pruning ([#9605](https://github.com/vercel/turborepo/pull/9605))
    - fix(watch): watch command require tasks argument ([#9598](https://github.com/vercel/turborepo/pull/9598))
    - fix(watch): fix output text when no tasks are provided ([#9612](https://github.com/vercel/turborepo/pull/9612))
    - fix(watch): correctly derive opts from watch mode args ([#9761](https://github.com/vercel/turborepo/pull/9761))
    - fix(package-manager): allow custom URL for `packageManager` version ([#9624](https://github.com/vercel/turborepo/pull/9624))
    - fix(repository): honour handleTransparentWorkspaces setting in Yarn/Berry ([#9626](https://github.com/vercel/turborepo/pull/9626))
    - fix(prune): fix Yarn1 entries getting merged erroneously ([#9627](https://github.com/vercel/turborepo/pull/9627))
    - fix(create-turbo): correct repo name ([#9708](https://github.com/vercel/turborepo/pull/9708))
    - fix(tui): avoid zombie process on clipboard write failure ([#9713](https://github.com/vercel/turborepo/pull/9713))
    - fix(filewatcher): handle removed directories #8800 ([#9406](https://github.com/vercel/turborepo/pull/9406))
    - fix: correct TUI vim binds direction ([#9529](https://github.com/vercel/turborepo/pull/9529))
    - fix: packages listed twice in watch mode ([#9644](https://github.com/vercel/turborepo/pull/9644))
    - fix: respect output mode 'none' even when caching is disabled ([#9670](https://github.com/vercel/turborepo/pull/9670))
    - fix: upgrade the turbo package in Yarn 4 ([#8076](https://github.com/vercel/turborepo/pull/8076))

    </Accordion>
    <Accordion title="Documentation (42)">

    - docs: changesets configuration ([#9325](https://github.com/vercel/turborepo/pull/9325))
    - docs: clarify output globs relativeness. ([#9449](https://github.com/vercel/turborepo/pull/9449))
    - docs: add `TURBO_CACHE` to System Environment Variables. ([#9450](https://github.com/vercel/turborepo/pull/9450))
    - docs(turbopack): Add incremental-computation page, intended to replace core-concepts page ([#9456](https://github.com/vercel/turborepo/pull/9456))
    - docs(turbopack): Remove old core-concepts page ([#9457](https://github.com/vercel/turborepo/pull/9457))
    - docs: small stylistic change for footnote. ([#9451](https://github.com/vercel/turborepo/pull/9451))
    - docs: improve clarity on `--cache`. ([#9489](https://github.com/vercel/turborepo/pull/9489))
    - docs: mark `--no-cache` and `--remote-only` as deprecated. ([#9488](https://github.com/vercel/turborepo/pull/9488))
    - docs: describe using a custom URL with `create-turbo`. ([#9507](https://github.com/vercel/turborepo/pull/9507))
    - docs: fix formatting on `/docs/getting-started/installation` ([#9509](https://github.com/vercel/turborepo/pull/9509))
    - docs: fix formatting on `/docs/getting-started/installation` ([#9514](https://github.com/vercel/turborepo/pull/9514))
    - docs: update ESLint documentation with ESLint v9 ([#9515](https://github.com/vercel/turborepo/pull/9515))
    - docs: options one-pager ([#9533](https://github.com/vercel/turborepo/pull/9533))
    - docs(typo): fix typo on turbo-ignore page ([#9576](https://github.com/vercel/turborepo/pull/9576))
    - docs: clarify default daemon usage ([#9566](https://github.com/vercel/turborepo/pull/9566))
    - docs: provide reasoning on why Turborepo doesn't support nested workspaces ([#9586](https://github.com/vercel/turborepo/pull/9586))
    - docs: update CONTRIBUTING.md ([#9590](https://github.com/vercel/turborepo/pull/9590))
    - docs: change path of options overview page ([#9600](https://github.com/vercel/turborepo/pull/9600))
    - docs: remove old options page ([#9601](https://github.com/vercel/turborepo/pull/9601))
    - docs: add community implementations of Remote Cache ([#9631](https://github.com/vercel/turborepo/pull/9631))
    - docs: fix CONTRIBUTING.md typo ([#9637](https://github.com/vercel/turborepo/pull/9637))
    - docs: mention capnp in the dependencies ([#9643](https://github.com/vercel/turborepo/pull/9643))
    - docs: add missing `api` folder in `turbo prune api --docker` example ([#9648](https://github.com/vercel/turborepo/pull/9648))
    - docs: add missing `apps` folder in `prune` command reference ([#9658](https://github.com/vercel/turborepo/pull/9658))
    - docs: correct Bun support status ([#9664](https://github.com/vercel/turborepo/pull/9664))
    - docs: mention module resolution differences for package managers ([#9665](https://github.com/vercel/turborepo/pull/9665))
    - docs(errors): improve error message for recursive calls ([#9650](https://github.com/vercel/turborepo/pull/9650))
    - docs: guide for Playwright ([#9662](https://github.com/vercel/turborepo/pull/9662))
    - docs: mention --graph on graphs page ([#9661](https://github.com/vercel/turborepo/pull/9661))
    - docs: document creating packages with framework bindings ([#9222](https://github.com/vercel/turborepo/pull/9222))
    - docs: add note about packaging patterns ([#9673](https://github.com/vercel/turborepo/pull/9673))
    - docs: guide for shadcn/ui ([#9675](https://github.com/vercel/turborepo/pull/9675))
    - docs: add link to shadcn/ui page ([#9678](https://github.com/vercel/turborepo/pull/9678))
    - docs: mention free remote caching earlier on page ([#9688](https://github.com/vercel/turborepo/pull/9688))
    - docs: typo fix ([#9690](https://github.com/vercel/turborepo/pull/9690))
    - docs(fix): correct line highlighting by removing extra comma ([#9696](https://github.com/vercel/turborepo/pull/9696))
    - docs: add community-built Run Summaries web viewer ([#9679](https://github.com/vercel/turborepo/pull/9679))
    - docs: edits for Prisma guide ([#9682](https://github.com/vercel/turborepo/pull/9682))
    - docs: update docs to use correct changeset dir ([#9722](https://github.com/vercel/turborepo/pull/9722))
    - docs: update CONTRIBUTING.md ([#9759](https://github.com/vercel/turborepo/pull/9759))
    - docs: migration guide for users coming from Nx ([#9762](https://github.com/vercel/turborepo/pull/9762))
    - docs: fix typo ([#9814](https://github.com/vercel/turborepo/pull/9814))

    </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew), [Chris](https://github.com/chris-olszewski), [Dimitri](https://github.com/dimitropoulos), [Nicholas](https://github.com/NicholasLYang), and [Tom](https://github.com/tknickman).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](/docs/community).

We also thank everyone who contributed to this release of Turborepo: @aaronccasanova, @AlvaroParker, @ankur-arch, @arosequist, @atimmer, @bgw, @bitttttten, @chaficnajjar, @codexshell, @eps1lon, @gianelli99, @glitched-w0rld, @JasonnnW3000, @jbrocksfellas, @jeremy-code, @jonathandsouza, @Juneezee, @kayumuzzaman, @krlvi, @maciej-ka, @ognevny, @olets, @pkerschbaum, @romanofski, @shivam-pawar, @takaebato, @tevem1207, @thebrubaker, @Tofandel, @trivikr, @yamz8, and @zsh77.

---

### Apps Docs Content Blog Turbo 2 5 (`apps/docs/content/blog/turbo-2-5.mdx`)

---
title: Turborepo 2.5
date: 2025/4/3
description: "Sidecar tasks, `--continue` flexibility, turbo.jsonc, Bun pruning, `$TURBO_ROOT$`, OpenAPI viewer, and more."
product: turborepo
type: overview
summary: Release notes for Turborepo 2.5 featuring sidecar tasks, turbo.jsonc, and Bun pruning.
tag: "web development"
---

import { Authors } from "@/components/blog/authors";
import { Date } from "@/components/blog/date";
import { Accordion, Accordions } from "@/components/geistdocs/accordion";

# Turborepo 2.5

<Date>Thursday, April 3rd, 2025</Date>

<Authors authors={["nicholasyang", "anthonyshew", "chrisolszewski"]} />

Turborepo 2.5 includes a number of improvements to enhance your repository:

- [**Sidecar tasks**](#sidecar-tasks): Use `with` to ensure persistent tasks always run together
- [**Flexibility for `--continue`**](#improved-control-for---continue-behavior): Only continue running tasks when dependencies are successful
- [**`turbo.jsonc`**](#add-comments-to-your-turborepo-configuration-files): Write comments directly in your configuration file
- [**`prune` for Bun**](#pruned-monorepos-for-bun-repositories): You can now use `turbo prune` in Bun repositories
- [**`$TURBO_ROOT$`**](#reference-your-workspace-root-with-the-turbo_root-microsyntax): Reference the Workspace root in `turbo.json`
- [**OpenAPI viewer**](#openapi-specification-viewer-for-self-hosting): Human-readable OpenAPI spec for self-hosted Remote Caches

Upgrade today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

## Sidecar tasks

In some cases, you want to ensure two long-running tasks are always running at the same time. For example, you may have a web application that makes requests to another application in your monorepo. Running the web application by itself may not be useful, since the backend API application won’t be available to serve its requests.

You may have tried to use `dependsOn` to create this relationship - but quickly discovered that depending on a long-running task isn’t allowed. A long-running task never exits, so the dependent task would never run. This meant you’d have to carefully craft a [`--filter`](/docs/reference/run#--filter-string) to ensure those resources are available—and make sure everyone in the repo knows to use it.

Instead, we’re introducing the `with` key so you can guarantee that a dependent long-running task always runs _with_ the long-running tasks that it depends on at runtime.

```json title="apps/web/turbo.json"
{
  "tasks": {
    "dev": {
      "with": ["api#start"],
      "persistent": true,
      "cache": false
    }
  }
}
```

Using this [Package Configuration](/docs/reference/package-configurations), anytime that the `web` application’s `dev` task is started, the `api`'s `start` task will also run using [the `package#task` microsyntax](/docs/crafting-your-repository/configuring-tasks#depending-on-a-specific-task-in-a-specific-package).

[Visit the documentation](/docs/reference/configuration#with) to learn more.

## Improved control for `--continue` behavior

By default, Turborepo stops running tasks when it encounters a task that has failed. You can alter this behavior using the `--continue` flag, instructing Turborepo to continue running tasks, even when one or more tasks have failed.

While the `--continue` flag is useful, there are times when running tasks whose dependencies have failed will only result in more failures. For these situations, we’ve added a new value to the `--continue` flag in this release: `--continue=dependencies-successful`.

```bash title="Terminal"
turbo run test --continue=dependencies-successful
```

When using this value, all dependencies for a task must be successful for the dependent task to run.

[Learn more in the documentation](/docs/reference/run#--continueoption).

The Turborepo core team would like to thank @jenseng for contributing this feature.

## Add comments to your Turborepo configuration files

You can now use JSONC (`turbo.jsonc`) for your configuration files, allowing you to add useful comments to your configuration.

```json title="./turbo.jsonc"
{
  "tasks": {
    "test": {
      // Our tests need their dependencies to be built first
      "dependsOn": ["^build"]
    }
  }
}
```

## Pruned monorepos for Bun repositories

`turbo prune` creates a partial monorepo for a target package, and is especially useful for [creating lightweight Docker images from monorepos](/docs/guides/tools/docker). This command has been available for pnpm, npm, and Yarn repositories in previous versions of Turborepo.

In this release, `turbo prune` is now available for Bun v1.2+, which has introduced a text-based lockfile that we can now read and analyze.

```bash title="Terminal"
turbo prune web
```

To learn more about `turbo prune`, [visit the documentation](/docs/reference/prune).

The Turborepo core team would like to thank @camero2734 for contributing this feature.

## Reference your workspace root with the `$TURBO_ROOT$` microsyntax

In some situations, you’re forced to break out of package boundaries in a monorepo. This could be due to a number of constraints, like tooling that doesn’t conform to modern package manager workspaces or incremental migration workflows that take you out of ideal conditions.

In the past, you’d need to write paths in `turbo.json` that traverse to the workspace root, since globs are anchored to the root of packages:

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "inputs": ["../../important-file.txt"]
    }
  }
}
```

While this pattern does work, it can lead to inconsistencies in some cases:

- Some packages may need `../` while others need `../../`
- A developer could potentially move a package to a different location so that the path isn’t correct

Instead, you can now use the `$TURBO_ROOT$` microsyntax:

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "inputs": ["$TURBO_ROOT$/important-file.txt"]
    }
  }
}
```

Now, this file glob is guaranteed to always start at the root of your workspace.

[Visit the documentation](/docs/reference/configuration#turbo_root) to learn more.

## OpenAPI specification viewer for self-hosting

Turborepo is proudly open-source with a public specification for its Remote Caching protocol. While [Vercel Remote Cache is a free-to-use managed option](https://vercel.com/docs/monorepos/remote-caching), the OpenAPI spec allows the community to create implementations for Remote Caching of their own.

We’ve published [the Remote Cache spec as JSON to the web](/api/remote-cache-spec) for some time, and have recently added a human-friendly version of the spec at [https://turborepo.dev/docs/openapi](https://turborepo.dev/docs/openapi).

[Visit the Remote Caching documentation](/docs/core-concepts/remote-caching#remote-cache-api) to learn more.

## Other changes

<Accordions>

  <Accordion title="Features (9)">

    - feat(boundaries): package rules ([#10160](https://github.com/vercel/turborepo/pull/10160))
    - feat(boundaries): package name as tag punning ([#10151](https://github.com/vercel/turborepo/pull/10151))
    - feat(boundaries): implicit dependencies ([#10117](https://github.com/vercel/turborepo/pull/10117))
    - feat(process): distinguish between signals used to kill children ([#10049](https://github.com/vercel/turborepo/pull/10049))
    - feat(boundaries): auto ignore ([#10147](https://github.com/vercel/turborepo/pull/10147))
    - feat(clone): turbo clone ([#9904](https://github.com/vercel/turborepo/pull/9904))
    - feat(boundaries): support tsconfig path aliases ([#10002](https://github.com/vercel/turborepo/pull/10002))
    - feat(query): add schema flag ([#10052](https://github.com/vercel/turborepo/pull/10052))
    - feat(ls): add package path to ls ([#10079](https://github.com/vercel/turborepo/pull/10079))

  </Accordion>

  <Accordion title="Fixes (19)">

    - fix(turbo_json): avoid workspace validation errors ([#10211](https://github.com/vercel/turborepo/pull/10211))
    - fix(bun): deserialize correctly and use optionalPeers ([#10219](https://github.com/vercel/turborepo/pull/10219))
    - fix: update env variables supported by nitro ([#10176](https://github.com/vercel/turborepo/pull/10176))
    - fix: mark type of flat config export to satisfy Linter.Config[] ([#10128](https://github.com/vercel/turborepo/pull/10128))
    - fix(eslint): array type lints ([#10139](https://github.com/vercel/turborepo/pull/10139))
    - fix(bun): properly handle bun lockfile keys ([#10137](https://github.com/vercel/turborepo/pull/10137))
    - fix: eslint-config-turbo module export ([#10105](https://github.com/vercel/turborepo/pull/10105))
    - fix: correctly forward passthrough arguments when using pkg#task format ([#10087](https://github.com/vercel/turborepo/pull/10087))
    - fix(boundaries): support import attributes ([#10078](https://github.com/vercel/turborepo/pull/10078))
    - fix(boundaries): unnecessary tsconfig warnings ([#10104](https://github.com/vercel/turborepo/pull/10104))
    - fix(affected): consider turbo.jsonc as a default global dependency ([#10106](https://github.com/vercel/turborepo/pull/10106))
    - fix(prune): support copying turbo.jsonc ([#10107](https://github.com/vercel/turborepo/pull/10107))
    - fix(cli): no longer attempt to parse task name as continue value ([#10097](https://github.com/vercel/turborepo/pull/10097))
    - fix: affected_packages's optimization flow ([#9950](https://github.com/vercel/turborepo/pull/9950))
    - fix(@turbo/repository): revert "chore(deps): update git2 to 0.20.0" ([#10045](https://github.com/vercel/turborepo/pull/10045))
    - fix(process): revert "feat(process): differentiate between child interruption and killing" ([#10046](https://github.com/vercel/turborepo/pull/10046))
    - fix: filter logic ([#9653](https://github.com/vercel/turborepo/pull/9653))
    - fix(packages): no longer match versionless packages ([#10056](https://github.com/vercel/turborepo/pull/10056))
    - fix(engine): no longer error if provided task is omitted by filter ([#10051](https://github.com/vercel/turborepo/pull/10051))

  </Accordion>

  <Accordion title="Documentation (33)">

    - docs: layout redesign ([#10178](https://github.com/vercel/turborepo/pull/10178))
    - docs: fix text colors in a few spots ([#10213](https://github.com/vercel/turborepo/pull/10213))
    - docs: remove stale callout ([#10217](https://github.com/vercel/turborepo/pull/10217))
    - docs: links for OpenAPI spec for both human-readable and JSON ([#10216](https://github.com/vercel/turborepo/pull/10216))
    - docs: add a snippet to with ([#10215](https://github.com/vercel/turborepo/pull/10215))
    - docs: mention JSONC support ([#10214](https://github.com/vercel/turborepo/pull/10214))
    - docs: fix the incorrect export keyword ([#10235](https://github.com/vercel/turborepo/pull/10235))
    - docs: add checkout optimization for --affected ([#10188](https://github.com/vercel/turborepo/pull/10188))
    - docs: use schema from current @turbo/types ([#10197](https://github.com/vercel/turborepo/pull/10197))
    - docs: switch turbo run to turbo watch for --experimental-write-cache ([#10199](https://github.com/vercel/turborepo/pull/10199))
    - docs(run): fix passthrough arg behavior ([#10167](https://github.com/vercel/turborepo/pull/10167))
    - docs: bump openapi framework version ([#10172](https://github.com/vercel/turborepo/pull/10172))
    - docs: fix typos ([#10182](https://github.com/vercel/turborepo/pull/10182))
    - docs: update fallback OG image ([#10174](https://github.com/vercel/turborepo/pull/10174))
    - docs: enhance examples tables ([#10173](https://github.com/vercel/turborepo/pull/10173))
    - docs: fix typos in documentation files ([#10192](https://github.com/vercel/turborepo/pull/10192))
    - docs: fix typos in documentation files ([#10124](https://github.com/vercel/turborepo/pull/10124))
    - docs: update storybook initiation instructions ([#10145](https://github.com/vercel/turborepo/pull/10145))
    - docs: clarify TURBO_TEAM slug usage ([#10102](https://github.com/vercel/turborepo/pull/10102))
    - fix: adds callout for installation instructions for PNPM ([#10100](https://github.com/vercel/turborepo/pull/10100))
    - docs: add release phases to support policy ([#10091](https://github.com/vercel/turborepo/pull/10091))
    - docs: remove ls from Experimental phase in Support Policy ([#10108](https://github.com/vercel/turborepo/pull/10108))
    - docs: fix code black background colors ([#10141](https://github.com/vercel/turborepo/pull/10141))
    - fix(docs): prefix environment variable for search dialog ([#10142](https://github.com/vercel/turborepo/pull/10142))
    - fix(docs): fix commas in package exports example ([#10143](https://github.com/vercel/turborepo/pull/10143))
    - docs: open source site source code ([#10127](https://github.com/vercel/turborepo/pull/10127))
    - docs: remove experimental warning from ls command ([#10096](https://github.com/vercel/turborepo/pull/10096))
    - docs: add hybrid approach to vitest guide ([#10092](https://github.com/vercel/turborepo/pull/10092))
    - docs: fix typo on continue docs ([#10041](https://github.com/vercel/turborepo/pull/10041))
    - docs: add explicit mention for capturing multiple .env files ([#10061](https://github.com/vercel/turborepo/pull/10061))
    - docs: fix json title for Watch Mode docs ([#10085](https://github.com/vercel/turborepo/pull/10085))
    - docs: upgrades for Vitest doc and add with-vitest example ([#10063](https://github.com/vercel/turborepo/pull/10063))
    - fix(docs): asset importing failure for OG images ([#10159](https://github.com/vercel/turborepo/pull/10159))

  </Accordion>

  <Accordion title="Examples (5)">

    - fix: unexpected top-level property default in base.js eslint config ([#10240](https://github.com/vercel/turborepo/pull/10240))
    - fix(example): remove obsolete @types/react-native from with-react-native-web ([#10190](https://github.com/vercel/turborepo/pull/10190))
    - docs: update README.md in examples with-tailwind to correctly reference .ts config files instead of .js ([#10057](https://github.com/vercel/turborepo/pull/10057))
    - docs: fix JSDoc annotation for ESLint flat configs of basic example ([#10089](https://github.com/vercel/turborepo/pull/10089))
    - feat(examples): add example with-solid ([#10144](https://github.com/vercel/turborepo/pull/10144))

  </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew), [Chris](https://github.com/chris-olszewski), [Dimitri](https://github.com/dimitropoulos), [Nicholas](https://github.com/NicholasLYang), and [Tom](https://github.com/tknickman).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](/docs/community).

We also thank everyone who contributed to this release of Turborepo: @beaussan, @bohongu, @camero2734, @cprussin, @dinglindong, @jenseng, @jimmycathy, @kevincatty, @mm-webx, @ognevny, @pi0, @pudongair, @rootdiae, @shinjith-dev, @sicarius97, @ssshashank, @Tigatok, @todaymoon, @Tyoneb, @victorlagerfors, @vinayaksodar, @wmjae, @x-N0, and @xiaobei0715.

---

### Apps Docs Content Blog Turbo 2 6 (`apps/docs/content/blog/turbo-2-6.mdx`)

---
title: Turborepo 2.6
date: 2025/10/28
description: "Microfrontends, Bun package manager to stable, task search in TUI"
product: turborepo
type: overview
summary: Release notes for Turborepo 2.6 featuring microfrontends, stable Bun support, and TUI task search.
tag: "web development"
---

import { Authors } from "@/components/blog/authors";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Date } from "@/components/blog/date";
import { Accordion, Accordions } from "@/components/geistdocs/accordion";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import MicrofrontendsImageDark from "../../public/images/blog/turbo-2-6/microfrontends-dark.png";
import MicrofrontendsImageLight from "../../public/images/blog/turbo-2-6/microfrontends-light.png";
import TaskSearchImageDark from "../../public/images/blog/turbo-2-6/task-search-dark.png";
import TaskSearchImageLight from "../../public/images/blog/turbo-2-6/task-search-light.png";

# Turborepo 2.6

<Date>Tuesday, October 28th, 2025</Date>

<Authors authors={["anthonyshew", "tomknickman"]} />

Turborepo 2.6 includes a number of improvements to developer experience for your repository:

- [**Microfrontends**](#microfrontends): Develop many applications on one `localhost` port
- [**Bun package manager to stable**](#bun-package-manager-to-stable): Granular lockfile analysis and pruning for `bun.lock`
- [**Task list search in terminal UI**](#task-list-search-in-terminal-ui): Use `/` to focus tasks faster

Upgrade today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Use the automated upgrade CLI
pnpm dlx @turbo/codemod migrate

# Start a new repository
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Use the automated upgrade CLI
yarn dlx @turbo/codemod migrate

# Start a new repository
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Use the automated upgrade CLI
npx @turbo/codemod migrate

# Start a new repository
npx create-turbo@latest
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Use the automated upgrade CLI
bunx @turbo/codemod migrate

# Start a new repository
bunx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

## Microfrontends

Vertical microfrontends are an architecture where multiple applications are served on one production domain, split into "zones". Each path for the domain is handled by one of the applications.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "",
    src: MicrofrontendsImageLight,
    props: {
      width: 1600,
      height: 750,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "",
    src: MicrofrontendsImageDark,
    props: {
      width: 1600,
      height: 750,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

This strategy gives teams at scale the ability to ship more independently. Release cycles become decoupled, build times can be brought down, and CI pipelines can get more focused, among other benefits.

While this does help production deployments, it can create difficulty for local development since you’ll have to run many applications instead of just one. Each application ends up needing its own development command and port to use.

Today, we’re releasing a microfrontend proxy for local development, so that all of your applications can run on one port, with one command. Add a `microfrontends.json` file to your parent application and Turborepo will automatically proxy `localhost:3024` to the ports for your other applications.

```json title="./apps/web/microfrontends.json"
{
  "$schema": "https://turborepo.dev/microfrontends/schema.json"
  "applications": {
    "web": {
      "development": {
        "local": 3000
      }
    },
    "docs": {
      "development": {
        "local": 3001
      },
      "routing": [
        {
          "paths": ["/docs", "/docs/:path*"]
        }
      ]
    }
  }
}
```

Just run `turbo dev`. In this configuration, your `docs` app runs its development server on `localhost:3001` and will handle requests for `/docs` and all nested paths in `/docs`. The `web` app runs on `localhost:3000` and handles all other requests.

[Visit the documentation](/docs/guides/microfrontends) to learn more.

### Integrating with production infrastructure

While Turborepo’s native microfrontend proxy is meant for working locally, we’re deeply integrating with infrastructure providers to help you bring your microfrontends architecture to production.

For example, we’ve designed the Turborepo-native microfrontends proxy to work with [Vercel’s microfrontends product](http://vercel.com/microfrontends), which is also releasing to GA today. In fact, Vercel’s microfrontends feature provided the research for Turborepo-native microfrontends. We explored how to build microfrontends, locally and in production, with some of the largest customers at Vercel, and are now extracting those learnings from closed-source to open-source.

When you install [`@vercel/microfrontends`](https://www.npmjs.com/package/@vercel/microfrontends?activeTab=readme) into your repository, Turborepo will dynamically adjust your local environment to use the proxy provided by the package, deeply integrating with your production infrastructure. [Visit the Vercel microfrontends documentation](https://vercel.com/docs/microfrontends) to learn more.

We look forward to working with more providers to integrate seamless microfrontends across your stack. If you are an infrastructure provider looking to integrate, please reach out.

## Bun package manager to stable

Bun is a fast, incrementally adoptable all-in-one JavaScript, TypeScript & JSX toolkit. Today, Bun as a package manager is now stable in Turborepo.

This means that, when you use Bun as your package manager, Turborepo will only miss cache for packages that have changes in their dependencies. If you update a dependency for your `web` application, your `docs` application’s tasks will still hit cache.

Since September 2023, Turborepo has had Beta support for Bun’s package manager capabilities. Our first iteration worked with the original `bun.lockb` lockfile, though it didn’t have granular change detection, so any change to your dependencies would result in cache misses for your whole repository. Since then, Bun’s lockfiles have undergone several changes:

- In December 2024, Bun introduced the text-based `bun.lock`, with a `v0` version. Because this file is text-based, Turborepo could parse it to intelligently cache tasks for your packages based on dependency changes.
- In January 2025, `bun.lock`'s format changed from a `v0` to `v1`, breaking the parser we created for `v0`. A package manager’s lockfile isn’t part of its public API, and Bun got much faster because of this change, so we were excited to see the improvement. But we didn't know if we were going to need to rewrite a new parser every month...

After a few months of stability and [an inspiring blog post about the new lockfile format by the Bun team](https://bun.com/blog/behind-the-scenes-of-bun-install), Turborepo now handles the latest `v1` lockfile format for Bun.

We’ve updated [our Support Policy](/docs/support-policy#package-managers) and the rest of our documentation to reflect this update. We also want to thank the Bun team for [sending `robobun` to help us with the first draft of the PR](https://github.com/vercel/turborepo/pull/10729).

## Task list search in terminal UI

The terminal UI in Turborepo was early to today’s trend of TUI-based experiences that we’re seeing in many AI-based workflows. Turborepo’s terminal UI brings many benefits compared to streamed logs, including improved readability for task logs, easy copy-paste for a specific task, interactive tasks, and more.

But in large repositories, it can be slow to scroll through a large list of tens or hundreds of tasks, one-by-one.

Today, we’re improving on our task search to make it one of the fundamental ways that you interact with a large Turborepo. When using the terminal UI, press `/` to filter to only the tasks that you’re interested in.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: 'A terminal window showing Turborepo\'s terminal UI. The top bar shows a search query for "docs" and the task list has dimmed every task except the tasks containing the name "docs".',
    src: TaskSearchImageLight,
    props: {
      width: 682,
      height: 746.5,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: 'A terminal window showing Turborepo\'s terminal UI. The top bar shows a search query for "docs" and the task list has dimmed every task except the tasks containing the name "docs".',
    src: TaskSearchImageDark,
    props: {
      width: 682,
      height: 746.5,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

Only the tasks that match your search query will be selected. [Visit the terminal UI documentation](/docs/crafting-your-repository/developing-applications#using-the-terminal-ui) to learn more.

## Other changes

<Accordions>

  <Accordion title="Features (17)">

    - feat(tui): more keybinds for scrolling ([#10248](https://github.com/vercel/turborepo/pull/10248))
    - feat(tui): configurable scrollback length ([#10247](https://github.com/vercel/turborepo/pull/10247))
    - feat(codemod): update `$schema` when versioned ([#10319](https://github.com/vercel/turborepo/pull/10319))
    - feat(sidebar): improve folder link accessibility and UX ([#10349](https://github.com/vercel/turborepo/pull/10349))
    - feat(ls): add dependents to json output ([#10367](https://github.com/vercel/turborepo/pull/10367))
    - feat(dry): include `with` in dry run/summary output ([#10373](https://github.com/vercel/turborepo/pull/10373))
    - feat(ui): remove gutter from persisted task output ([#10406](https://github.com/vercel/turborepo/pull/10406))
    - feat(tui): momentum-based scrolling ([#10420](https://github.com/vercel/turborepo/pull/10420))
    - feat(turbo.json): allow for trailing commas ([#10537](https://github.com/vercel/turborepo/pull/10537))
    - feat(env): add Windows user profile variables to pass-through ([#10588](https://github.com/vercel/turborepo/pull/10588))
    - feat(auth): optional callback port ([#10666](https://github.com/vercel/turborepo/pull/10666))
    - feat(create-turbo): `--no-git` flag ([#10720](https://github.com/vercel/turborepo/pull/10720))
    - feat(tui): add shortcut for clearing task logs ([#10828](https://github.com/vercel/turborepo/pull/10828))
    - feat: new OAuth flow for Turborepo CLI with Vercel ([#10911](https://github.com/vercel/turborepo/pull/10911))
    - feat: update `create-turbo` Bun prompt text ([#10918](https://github.com/vercel/turborepo/pull/10918))
    - feat(microfrontends): schema.json for microfrontends.json ([#11008](https://github.com/vercel/turborepo/pull/11008))
    - feat: Add support for custom microfrontends.json naming ([#11022](https://github.com/vercel/turborepo/pull/11022))

  </Accordion>

  <Accordion title="Fixes (30)">

    - fix(microfrontends): ensure that local proxy is loose ([#10289](https://github.com/vercel/turborepo/pull/10289))
    - fix(codemod): check for pipeline key before using it ([#10295](https://github.com/vercel/turborepo/pull/10295))
    - fix(@turbo/repository): no longer require packageManager to detect npm ([#10314](https://github.com/vercel/turborepo/pull/10314))
    - fix(watch): allow usage of turbo.jsonc ([#10340](https://github.com/vercel/turborepo/pull/10340))
    - fix(dry): do not perform runtime validations on dry runs ([#10375](https://github.com/vercel/turborepo/pull/10375))
    - fix(microfrontends): respect packageName field ([#10383](https://github.com/vercel/turborepo/pull/10383))
    - fix(pnpm): read linkWorkspacePackages from pnpm-workspace.yaml ([#10391](https://github.com/vercel/turborepo/pull/10391))
    - fix(query): use patched version of async-graphql ([#10448](https://github.com/vercel/turborepo/pull/10448))
    - fix(turbo-ignore): no longer attempt to use catalog protocol ([#10458](https://github.com/vercel/turborepo/pull/10458))
    - fix(@turbo/repository): correct exports from native lib ([#10475](https://github.com/vercel/turborepo/pull/10475))
    - fix(turbo): pass through pnpm store env vars by default ([#10520](https://github.com/vercel/turborepo/pull/10520))
    - fix(pnpm): respect deep for linkWorkspacePackages ([#10558](https://github.com/vercel/turborepo/pull/10558))
    - fix(query): pin to last graphiql version with artifacts ([#10685](https://github.com/vercel/turborepo/pull/10685))
    - fix(logs): no longer output group prefixes if no logs present ([#10760](https://github.com/vercel/turborepo/pull/10760))
    - fix(turbo): graceful shutdown on sighup ([#10764](https://github.com/vercel/turborepo/pull/10764))
    - fix(logs): create log files for non-cached tasks ([#10806](https://github.com/vercel/turborepo/pull/10806))
    - fix(security): update dependencies to resolve warning for `node-plop` ([#10847](https://github.com/vercel/turborepo/pull/10847))
    - fix: revert #10847 ([#10882](https://github.com/vercel/turborepo/pull/10882))
    - fix: update `ui` suggested value in error message for turbo.json ([#10896](https://github.com/vercel/turborepo/pull/10896))
    - fix(eslint-config-turbo): use module.exports for ESLint v8 compatibility ([#10902](https://github.com/vercel/turborepo/pull/10902))
    - fix(turborepo-lockfiles): handle missing optional dependencies in Bun lockfiles ([#10909](https://github.com/vercel/turborepo/pull/10909))
    - fix(lockfiles): include bundled dependencies in Bun lockfile subgraphs ([#10915](https://github.com/vercel/turborepo/pull/10915))
    - fix: update remote cache OAuth refresh flow ([#10916](https://github.com/vercel/turborepo/pull/10916))
    - fix: --graph=foo.dot should not require graphviz installed ([#10942](https://github.com/vercel/turborepo/pull/10942))
    - fix: `injectWorkspacePackages` for `turbo prune` with pnpm ([#10945](https://github.com/vercel/turborepo/pull/10945))
    - fix: adjust binary call for microfrontends proxy on Windows ([#10962](https://github.com/vercel/turborepo/pull/10962))
    - fix: added Linux env vars to global passthroughs ([#10984](https://github.com/vercel/turborepo/pull/10984))
    - fix: windows symlinking bug ([#10992](https://github.com/vercel/turborepo/pull/10992))
    - fix: path validation in `microfrontends.json` ([#11006](https://github.com/vercel/turborepo/pull/11006))

  </Accordion>

  <Accordion title="Documentation (37)">

    - docs: clarification on Transit Nodes docs ([#9181](https://github.com/vercel/turborepo/pull/9181))
    - fix(docs): fix SVG attribute casing to remove React warnings ([#10297](https://github.com/vercel/turborepo/pull/10297))
    - fix(docs): update redirects rule to resolve access issue on `getting-started` index page ([#10296](https://github.com/vercel/turborepo/pull/10296))
    - docs(fix): persist tabs state ([#10313](https://github.com/vercel/turborepo/pull/10313))
    - docs(chore): remove classnames dependency ([#10339](https://github.com/vercel/turborepo/pull/10339))
    - docs(chore): remove `/repo` references from a few places ([#10370](https://github.com/vercel/turborepo/pull/10370))
    - docs(chore): add robots.txt ([#10371](https://github.com/vercel/turborepo/pull/10371))
    - docs(fix): better usability on feedback form ([#10382](https://github.com/vercel/turborepo/pull/10382))
    - docs(fix): logos when using system theme ([#10388](https://github.com/vercel/turborepo/pull/10388))
    - docs(chore): switch to ESM ([#10405](https://github.com/vercel/turborepo/pull/10405))
    - docs(fix): date of 2.5 release post ([#10419](https://github.com/vercel/turborepo/pull/10419))
    - docs(chore): temporarily revert to webpack ([#10421](https://github.com/vercel/turborepo/pull/10421))
    - docs(fix): layout shift on home page ([#10424](https://github.com/vercel/turborepo/pull/10424))
    - docs(chore): cleaning up a few todos ([#10426](https://github.com/vercel/turborepo/pull/10426))
    - docs(chore): reenable Turbopack ([#10428](https://github.com/vercel/turborepo/pull/10428))
    - docs(examples): drop JS config from Tailwind example ([#10445](https://github.com/vercel/turborepo/pull/10445))
    - docs(fix): correct `globalDependencies` defaults ([#10484](https://github.com/vercel/turborepo/pull/10484))
    - docs(example): use npx turbo and show filtering ([#10500](https://github.com/vercel/turborepo/pull/10500))
    - docs(fix): use `pnpm add <pkg>` instead of `pnpm install <pkg>` ([#10529](https://github.com/vercel/turborepo/pull/10529))
    - docs(fix): missing commas in package.json files of jest docs ([#10560](https://github.com/vercel/turborepo/pull/10560))
    - docs(fix): css import order bug in tailwindcss docs and example ([#10561](https://github.com/vercel/turborepo/pull/10561))
    - docs(fix): incorrect CSS filename in Tailwind CSS setup example ([#10573](https://github.com/vercel/turborepo/pull/10573))
    - docs(fix): inconsistent command with the illustration ([#10596](https://github.com/vercel/turborepo/pull/10596))
    - docs(fix): inconsistent turbo command with the illustration ([#10602](https://github.com/vercel/turborepo/pull/10602))
    - docs: fix JSDoc type for ESLint config in basic example ([#10727](https://github.com/vercel/turborepo/pull/10727))
    - docs(run): correct --graph formats; remove incorrect default mention ([#10744](https://github.com/vercel/turborepo/pull/10744))
    - docs(run): fix --log-prefix options to match CLI (task, not prefix) ([#10743](https://github.com/vercel/turborepo/pull/10743))
    - fix(docs): fix broken anchor links to --graph option ([#10773](https://github.com/vercel/turborepo/pull/10773))
    - docs: add GitHub Actions reusable workflow documentation for remote caching ([#10923](https://github.com/vercel/turborepo/pull/10923))
    - docs: generate blog release OG images ([#10936](https://github.com/vercel/turborepo/pull/10936))
    - docs: fix correct package name from eslint-config-turbo to eslint-plugin-turbo ([#10954](https://github.com/vercel/turborepo/pull/10954))
    - docs: adjust compute hours saved component initial value ([#10958](https://github.com/vercel/turborepo/pull/10958))
    - docs: align tailwindcss 4 guide to the with-tailwind example  ([#10963](https://github.com/vercel/turborepo/pull/10963))
    - docs: fix typos and formatting issues in Playwright guide ([#10980](https://github.com/vercel/turborepo/pull/10980))
    - docs: clarify passthrough args comparison ([#10990](https://github.com/vercel/turborepo/pull/10990))
    - docs: fix profile images on home page ([#10993](https://github.com/vercel/turborepo/pull/10993))
    - docs: Clarify passthrough args cache miss ([#11026](https://github.com/vercel/turborepo/pull/11026))

  </Accordion>

  <Accordion title="Examples (17)">

    - refactor(examples): enhance `with-nestjs` (#8131) ([#10964](https://github.com/vercel/turborepo/pull/10964))
    - fix(examples): fix build in fresh vue example project ([#10277](https://github.com/vercel/turborepo/pull/10277))
    - fix(non-monorepo): correct devDependency from 'turb' to 'turbo' ([#10526](https://github.com/vercel/turborepo/pull/10526))
    - fix(examples): change docker command ([#10362](https://github.com/vercel/turborepo/pull/10362))
    - fix(examples): `with-svelte` classes ([#10363](https://github.com/vercel/turborepo/pull/10363))
    - feat(examples): upgrade with-tailwind to TailwindCSS v4 ([#10432](https://github.com/vercel/turborepo/pull/10432))
    - fix(examples): TypeScript in with-svelte example ([#10450](https://github.com/vercel/turborepo/pull/10450))
    - feat(example): update with-react-native-web, Expo SDK 52 ([#10466](https://github.com/vercel/turborepo/pull/10466))
    - fix(examples): use entry instead of entryPoints ([#10503](https://github.com/vercel/turborepo/pull/10503))
    - fix(example/with-docker): jest can't resolve @repo/jest-presets/node ([#10551](https://github.com/vercel/turborepo/pull/10551))
    - fix(example): add missing Tailwind import to shared ui styles ([#10579](https://github.com/vercel/turborepo/pull/10579))
    - refactor(examples): remove duplicate Next.js plugin from app tsconfig files ([#10612](https://github.com/vercel/turborepo/pull/10612))
    - fix(examples): css specificity in Tailwind example ([#10657](https://github.com/vercel/turborepo/pull/10657))
    - refactor(examples): update CSS variable names to use consistent --color- prefix in tailwind examples ([#10662](https://github.com/vercel/turborepo/pull/10662))
    - fix(examples): vitest version upgrade ([#10667](https://github.com/vercel/turborepo/pull/10667))
    - fix(examples): update vitest config paths for packages and apps in `with-vitest` ([#10675](https://github.com/vercel/turborepo/pull/10675))
    - fix(examples): correct 'test:projects' script to use vitest directly ([#10683](https://github.com/vercel/turborepo/pull/10683))
    - fix(examples): add missing extension to with-react-native-web ui tsconfig ([#10694](https://github.com/vercel/turborepo/pull/10694))
    - examples: Upgrade core-team-maintained examples to Next.js 16 ([#11014](https://github.com/vercel/turborepo/pull/11014))

  </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew) and [Tom](https://github.com/tknickman).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](/docs/community).

We also thank everyone who contributed to this release of Turborepo: @0ri0nexe, @0xmuon, @ahlimanhuseynov, @Alvi24, @andrewjdimola, @ashishkumar901336, @aviramha, @brunoapaulino, @chris-olszewski, @d0lwl0b, @DiegoDev2, @dstewart1911, @emilbjorklund, @eric-hjh, @esauri, @eug-vs, @evsasse, @felipetau, @Franck-Fernandez-pro, @grgsh, @haklee, @hijuliancode, @hugomassing, @JacksonSL, @JamesHenry, @jeonghwan-park, @jferrettiboke, @jihwan1211, @JoeyKamsteeg, @kade-robertson, @kenfdev, @kitfoster, @leopardracer, @mamuso, @mcky, @melroy, @MendyLanda, @mischnic, @mknichel, @mrr11k, @namidapoo, @NathanM2000, @neonerdy, @nivekithan, @ognevny, @oliveirabalsa, @pawbor, @pzion, @Redddy, @richardhuf84, @robbym, @robobun, @safaiyeh, @sahyl, @Satheeshsk369, @schwenkm, @sdavids, @shinjith-dev, @sitek94, @tedw, @tetzng, @vikhyathdevadiga, @xcfio, @yam-codes, and @yamadayutaka

---

### Apps Docs Content Blog Turbo 2 7 (`apps/docs/content/blog/turbo-2-7.mdx`)

---
title: Turborepo 2.7
date: 2025/12/19
description: "Devtools, Composable configuration, Biome rule, Yarn 4 catalogs"
product: turborepo
type: overview
summary: Release notes for Turborepo 2.7 featuring Devtools, composable configuration, and Yarn 4 catalogs.
tag: "web development"
---

import { Authors } from "@/components/blog/authors";
import { Callout } from "@/components/geistdocs/callout";
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
import { Date } from "@/components/blog/date";
import { Accordion, Accordions } from "@/components/geistdocs/accordion";
import { ThemeAwareImage } from "@/components/geistdocs/theme-aware-image";
import DevtoolsImageDark from "../../public/images/blog/turbo-2-7/devtools-dark.png";
import DevtoolsImageLight from "../../public/images/blog/turbo-2-7/devtools-light.png";

# Turborepo 2.7

<Date>Friday, December 19th, 2025</Date>

<Authors authors={["anthonyshew", "tomknickman"]} />

Turborepo 2.7 is now available, including new features like:

- [**Devtools**](#devtools): Visualize your Package Graph and Task Graph
- [**Composable configuration**](#compose-configuration-with-extends): Extend Package Configurations from other configurations
- [**New Turborepo rule in Biome**](#new-biome-rule-noundeclaredenvvars): Lint with Biome to find unsafe usage of environment variables
- [**Yarn 4 catalogs**](#yarn-4-catalogs): Centralized dependency management for Yarn

Upgrade today by running `npx @turbo/codemod migrate` or get started with `npx create-turbo@latest`.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Use the automated upgrade CLI
pnpm dlx @turbo/codemod migrate

# Start a new repository
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Use the automated upgrade CLI
yarn dlx @turbo/codemod migrate

# Start a new repository
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Use the automated upgrade CLI
npx @turbo/codemod migrate

# Start a new repository
npx create-turbo@latest
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Use the automated upgrade CLI
bunx @turbo/codemod migrate

# Start a new repository
bunx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

## Devtools

We’ve shipped a brand new experience at [turborepo.dev/devtools](http://turborepo.dev/devtools). Starting with this version of Turborepo, you can run `turbo devtools` to visually explore your Package Graph and Task Graph.

<ThemeAwareImage
  className="my-4 flex justify-center"
  light={{
    alt: "",
    src: DevtoolsImageLight,
    props: {
      width: 1600,
      height: 750,
      className: "dark:hidden block rounded-xl",
    },
  }}
  dark={{
    alt: "",
    src: DevtoolsImageDark,
    props: {
      width: 1600,
      height: 750,
      className: "hidden dark:block rounded-xl",
    },
  }}
/>

The graphs will hot-reload as you make changes to your repository, and help you to answer questions like:

- Which packages will miss cache when I change my utilities package?
- What tasks does this task depend on, directly and indirectly?
- What packages does _this specific package_ depend on that makes it miss cache so often?

And much, much more. Visit [turborepo.dev/devtools](http://turborepo.dev/devtools) to get started, or [learn more in the documentation](/docs/reference/devtools).

## Compose configuration with `extends`

We’ve expanded the capabilities of [Package Configurations](/docs/reference/package-configurations) so you can write your configuration once, and share it to anywhere in your repository.

### A more powerful `extends` key

Previously, you could only extend from your root `turbo.json` when you used the `extends` key. Now, you can reference `turbo.json` from any other package in your workspace by the package name:

<Tabs items={["./apps/docs/turbo.json", "./apps/web/turbo.json"]}>

<Tab value="./apps/docs/turbo.json">

```json title="./apps/docs/turbo.json"
{
  "extends": ["//", "web"]
}
```

This configuration inherits the `build` and `prepare-build` tasks from apps/web/turbo.json.

</Tab>

<Tab value="./apps/web/turbo.json">

```json title="./apps/web/turbo.json"
{
  "tasks": {
    "build": {
      "dependsOn": ["prepare-build"],
      "outputs": ["dist/**"]
    },
    "prepare-build": {}
  }
}
```

</Tab>

</Tabs>

[Visit the docs to learn more.](/docs/reference/package-configurations#extending-from-other-packages)

### Extending array configurations

Additionally, we’re introducing a new keyword: `$TURBO_EXTENDS$`.

```json title="./apps/web/turbo.json"
{
  "extends": ["//"],
  "tasks": {
    "build": {
      // Inherits "dist/**" from root AND adds ".next/**"
      "outputs": ["$TURBO_EXTENDS$", ".next/**"]
    }
  }
}
```

Previously, you could only overwrite array configurations completely. But now, in the example above, you can use `$TURBO_EXTENDS$` to append to an existing array. This gives you a greater degree of control so you can choose to completely overwrite or extend from existing configuration.

[Visit the docs to learn more.](/docs/reference/package-configurations#extending-arrays-with-turbo_extends)

## New Biome rule: `noUndeclaredEnvVars`

Turborepo users love going fast, so its no surprise they enjoy using [Biome](https://biomejs.dev/) for linting and formatting. However, until today, the only linting support we had for finding unsafe environment variable usage was in ESLint, with [our `eslint-plugin-turbo` plugin](/docs/reference/eslint-plugin-turbo).

In [Biome 2.3.10](https://github.com/biomejs/biome/releases/tag/%40biomejs%2Fbiome%402.3.10) and above, you can find environment variables that can cause unexpected cache hits faster with [the new Turborepo domain](https://biomejs.dev/linter/domains/#turborepo) in Biome.

Biome will read your dependencies in your repository, and activate the Turborepo domain automatically. The `noUndeclaredEnvVars` rule is currently in the “nursery” group, so must be activated manually:

```json title="biome.json"
{
  "linter": {
    "rules": {
      "nursery": {
        "noUndeclaredEnvVars": "error"
      }
    }
  }
}
```

Once the rule is promoted out of the nursery group in a future release of Biome, the rule will be automatically activated for Turborepo projects, requiring zero-configuration. To learn more about Biome, visit [the Biome documentation](https://biomejs.dev/).

## Yarn 4 catalogs

[Yarn’s 4.10.0 release](https://github.com/yarnpkg/berry/releases/tag/%40yarnpkg%2Fcli%2F4.10.0) introduced “catalogs”, inspired by [pnpm’s catalogs feature](https://pnpm.io/catalogs). Catalogs allow you to define a specific version of a dependency once, and reuse that version as a constant in the rest of your repository.

```yaml title=".yarnrc.yml"
catalog:
  react: ^19.2.3
  lodash: ^4.17.21
```

We’ve updated our lockfile parser to work with this new Yarn feature, ensuring our smart lockfile detection doesn’t cause global invalidations in your repository. Only the packages and tasks that are affected by the change to your catalogs will see cache misses, improving your cache hit rates.

[Visit our Support Policy](/docs/support-policy#package-managers) to learn more about our package manager support, or learn more about catalogs in [the Yarn documentation](https://yarnpkg.com/features/catalogs).

## Other changes

<Accordions>

  <Accordion title="Features (5)">

    - feat: Add GitHub Actions environment variable as default passthrough ([#10740](https://github.com/vercel/turborepo/pull/10740))
    - feat(tui): Add padding to task names and icons ([#11104](https://github.com/vercel/turborepo/pull/11104))
    - feat: Cross-platform microfrontends port command ([#11098](https://github.com/vercel/turborepo/pull/11098))
    - feat: Move icon to left side in TUI ([#11097](https://github.com/vercel/turborepo/pull/11097))
    - feat: Add Windows-specific env var to default passthroughs ([#11126](https://github.com/vercel/turborepo/pull/11126))

  </Accordion>

  <Accordion title="Fixes (31)">

    - fix: Improve layouts and task graph sourcing for devtools ([#11269](https://github.com/vercel/turborepo/pull/11269))
    - fix: Allow root microfrontends.json config for @vercel/microfrontends ([#11264](https://github.com/vercel/turborepo/pull/11264))
    - fix: Compose tasks when composing turbo.json ([#11248](https://github.com/vercel/turborepo/pull/11248))
    - fix: React Server Components CVE vulnerabilities ([#11245](https://github.com/vercel/turborepo/pull/11245))
    - fix: Quoting in turbo-ignore commands ([#11239](https://github.com/vercel/turborepo/pull/11239))
    - fix: Add fine grained interruptible task restarts in watch mode ([#11135](https://github.com/vercel/turborepo/pull/11135))
    - fix: Add Windows-specific env var to default passthroughs ([#11233](https://github.com/vercel/turborepo/pull/11233))
    - fix: Upgrade Next.js to 15.5.7 (CVE-2025-55182) ([#11232](https://github.com/vercel/turborepo/pull/11232))
    - fix(turbo-utils): Add test for conflicting configs and remove stale TODO ([#11201](https://github.com/vercel/turborepo/pull/11201))
    - fix(cli): Preserve exit codes in notifyUpdate functions ([#11153](https://github.com/vercel/turborepo/pull/11153))
    - fix: Command injection in `turbo-ignore` ([#11154](https://github.com/vercel/turborepo/pull/11154))
    - fix(vercel-api): Add `VIEWER_FOR_PLUS` and `SECURITY` role variants ([#11169](https://github.com/vercel/turborepo/pull/11169))
    - fix: Normalize config dir env vars to absolute ([#11146](https://github.com/vercel/turborepo/pull/11146))
    - fix: Handle pidlock AlreadyOwned without failing init in LSP ([#10831](https://github.com/vercel/turborepo/pull/10831))
    - fix: Prevent vt100 TUI crash during column wrap ([#11170](https://github.com/vercel/turborepo/pull/11170))
    - fix(with-vite-react): Remove unused React import to fix build error ([#11162](https://github.com/vercel/turborepo/pull/11162))
    - fix: Validate missing \<cwd-path\> argument in test-codemod server script ([#11166](https://github.com/vercel/turborepo/pull/11166))
    - fix: Use -z option to git commands to handle unicode file paths ([#10844](https://github.com/vercel/turborepo/pull/10844))
    - fix(config-dir): Resolve relative `TURBO_CONFIG_DIR_PATH` before validation ([#11122](https://github.com/vercel/turborepo/pull/11122))
    - fix: Make selected task highlight use reverse video for accessibility ([#11090](https://github.com/vercel/turborepo/pull/11090))
    - fix: Improve version resolution in Bun lockfiles ([#11095](https://github.com/vercel/turborepo/pull/11095))
    - fix: Bun lockfile pruner adjustment ([#11092](https://github.com/vercel/turborepo/pull/11092))
    - fix: Revert "fix(logs): create log files for non-cached tasks" ([#11072](https://github.com/vercel/turborepo/pull/11072))
    - fix: Improve determinism for graceful shutdown ([#11063](https://github.com/vercel/turborepo/pull/11063))
    - fix(boundaries): Enable import attributes parsing ([#11053](https://github.com/vercel/turborepo/pull/11053))
    - fix(prune): Handle `patchedDependencies` for bun ([#11027](https://github.com/vercel/turborepo/pull/11027))
    - fix(prune): Add bunfig.toml to list of copied files ([#11055](https://github.com/vercel/turborepo/pull/11055))
    - fix: Labels for k + j backwards in binds list ([#11036](https://github.com/vercel/turborepo/pull/11036))
    - fix: add some Linux variables to default passthrough env vars ([#10959](https://github.com/vercel/turborepo/pull/10959))
    - fix: Improve parity with real Bun lockfile format for `prune` ([#11048](https://github.com/vercel/turborepo/pull/11048))
    - fix: path validation in `microfrontends.json` ([#11006](https://github.com/vercel/turborepo/pull/11006))

  </Accordion>

  <Accordion title="Documentation (25)">

    - docs: Devtools ([#11270](https://github.com/vercel/turborepo/pull/11270))
    - docs: Add `turbo.json` composition docs ([#11247](https://github.com/vercel/turborepo/pull/11247))
    - docs: Fix Bun filtered install commands ([#11260](https://github.com/vercel/turborepo/pull/11260))
    - docs: Add `turboExtendsKeyword` future flag and `$TURBO_EXTENDS$` microsyntax ([#11246](https://github.com/vercel/turborepo/pull/11246))
    - docs: fix typo in design-system.css comment ([#11231](https://github.com/vercel/turborepo/pull/11231))
    - docs: Move search to built-in ([#11224](https://github.com/vercel/turborepo/pull/11224))
    - docs: Revert "Comment out Tinybird" ([#11223](https://github.com/vercel/turborepo/pull/11223))
    - docs(fix): Sitemap ([#11207](https://github.com/vercel/turborepo/pull/11207))
    - docs: Remove spellchecker ([#11214](https://github.com/vercel/turborepo/pull/11214))
    - docs: Comment out Tinybird ([#11211](https://github.com/vercel/turborepo/pull/11211))
    - docs: Cleanup Sentry from gitignore ([#11210](https://github.com/vercel/turborepo/pull/11210))
    - docs: Remove flags code ([#11209](https://github.com/vercel/turborepo/pull/11209))
    - docs(security): Update Next.js ([#11208](https://github.com/vercel/turborepo/pull/11208))
    - docs: Updating READMEs ([#11190](https://github.com/vercel/turborepo/pull/11190))
    - docs: Fix vitest merged code coverage example ([#11158](https://github.com/vercel/turborepo/pull/11158))
    - docs: Update Prisma integration guide link ([#11155](https://github.com/vercel/turborepo/pull/11155))
    - docs(internal): Document release pipeline ([#11141](https://github.com/vercel/turborepo/pull/11141))
    - docs: Fix typo in tailwind set up guide ([#11143](https://github.com/vercel/turborepo/pull/11143))
    - docs: Fix copy-pasted testimonial quote ([#11117](https://github.com/vercel/turborepo/pull/11117))
    - docs: Add new testimonial to home page ([#11116](https://github.com/vercel/turborepo/pull/11116))
    - docs: Add mentions to `turborepo-summary` and `turborepo-summary-action` ([#11023](https://github.com/vercel/turborepo/pull/11023))
    - docs: Fix grammar, consistency, and formatting issues in CONTRIBUTING.md ([#11105](https://github.com/vercel/turborepo/pull/11105))
    - docs: Fix grammatical mistake on structuring-a-repository.mdx ([#11091](https://github.com/vercel/turborepo/pull/11091))
    - docs: update typo'd link ([#11032](https://github.com/vercel/turborepo/pull/11032))
    - docs: Clarify passtrhough args cache miss ([#11026](https://github.com/vercel/turborepo/pull/11026))

  </Accordion>

  <Accordion title="Examples (33)">

    - examples(deps): bump react from 19.2.0 to 19.2.3 in /examples/non-monorepo ([#11255](https://github.com/vercel/turborepo/pull/11255))
    - examples(dev-deps): bump typescript-eslint from 8.48.1 to 8.49.0 in /examples/basic in the basic group ([#11253](https://github.com/vercel/turborepo/pull/11253))
    - examples(dev-deps): bump the with-svelte group in /examples/with-svelte with 2 updates ([#11254](https://github.com/vercel/turborepo/pull/11254))
    - examples: Use slim image (debian) for prepare and builder stage, use latest no… ([#11228](https://github.com/vercel/turborepo/pull/11228))
    - examples(dev-deps): bump the with-svelte group in /examples/with-svelte with 3 updates ([#11219](https://github.com/vercel/turborepo/pull/11219))
    - examples(dev-deps): bump the basic group in /examples/basic with 2 updates ([#11218](https://github.com/vercel/turborepo/pull/11218))
    - examples(dev-deps): bump turbo from 2.6.1 to 2.6.3 in /examples/with-shell-commands ([#11217](https://github.com/vercel/turborepo/pull/11217))
    - examples(security): Upgrade `Next.js` versions ([#11195](https://github.com/vercel/turborepo/pull/11195))
    - examples: Add `with-biome` example ([#11145](https://github.com/vercel/turborepo/pull/11145))
    - examples(security): Upgrade Next.js versions ([#11188](https://github.com/vercel/turborepo/pull/11188))
    - examples: Fix lockfile in kitchen-sink ([#11174](https://github.com/vercel/turborepo/pull/11174))
    - examples(kitchen-sink): Use simpler eslint config for kitchen-sink ([#11163](https://github.com/vercel/turborepo/pull/11163))
    - examples(dev-deps): bump @types/react from 19.2.5 to 19.2.7 in /examples/non-monorepo ([#11151](https://github.com/vercel/turborepo/pull/11151))
    - examples(dev-deps): bump typescript-eslint from 8.46.3 to 8.47.0 in /examples/basic in the basic group ([#11149](https://github.com/vercel/turborepo/pull/11149))
    - examples(dev-deps): bump the with-svelte group in /examples/with-svelte with 2 updates ([#11152](https://github.com/vercel/turborepo/pull/11152))
    - examples(with-nestjs): Add missing eslint devDependency ([#11138](https://github.com/vercel/turborepo/pull/11138))
    - examples(dev-deps): bump @types/react from 19.2.2 to 19.2.5 in /examples/non-monorepo ([#11125](https://github.com/vercel/turborepo/pull/11125))
    - examples: Remove unneeded microfrontends.json property ([#11101](https://github.com/vercel/turborepo/pull/11101))
    - examples: Bump `turbo` to latest ([#11100](https://github.com/vercel/turborepo/pull/11100))
    - examples(deps): bump next from 16.0.0 to 16.0.1 in /examples/kitchen-sink ([#11088](https://github.com/vercel/turborepo/pull/11088))
    - examples(dev-deps): bump svelte from 5.43.3 to 5.43.5 in /examples/with-svelte ([#11087](https://github.com/vercel/turborepo/pull/11087))
    - examples(fix): Gradient in `with-tailwind` ([#11073](https://github.com/vercel/turborepo/pull/11073))
    - examples(dev-deps): bump eslint-config-next from 16.0.0 to 16.0.1 in /examples/non-monorepo ([#11086](https://github.com/vercel/turborepo/pull/11086))
    - examples(deps): bump next from 16.0.0 to 16.0.1 in /examples/with-tailwind ([#11083](https://github.com/vercel/turborepo/pull/11083))
    - examples(deps): bump next from 16.0.0 to 16.0.1 in /examples/basic ([#11082](https://github.com/vercel/turborepo/pull/11082))
    - examples(deps): bump next from 16.0.0 to 16.0.1 in /examples/non-monorepo ([#11051](https://github.com/vercel/turborepo/pull/11051))
    - examples(deps-dev): bump the with-tailwind group in /examples/with-tailwind with 6 updates ([#11038](https://github.com/vercel/turborepo/pull/11038))
    - examples(deps): bump the basic group in /examples/basic with 9 updates ([#11040](https://github.com/vercel/turborepo/pull/11040))
    - examples(deps-dev): bump the with-svelte group in /examples/with-svelte with 7 updates ([#11041](https://github.com/vercel/turborepo/pull/11041))
    - examples(deps-dev): bump turbo from 2.5.6 to 2.6.0 in /examples/with-shell-commands in the with-shell-commands group ([#11039](https://github.com/vercel/turborepo/pull/11039))
    - examples: Remove redundant border declaration ([#11042](https://github.com/vercel/turborepo/pull/11042))
    - examples(deps-dev): bump the kitchen-sink group in /examples/kitchen-sink with 9 updates ([#11043](https://github.com/vercel/turborepo/pull/11043))
    - examples(deps-dev): bump @types/node from 18.17.4 to 24.10.0 in /examples/non-monorepo ([#11037](https://github.com/vercel/turborepo/pull/11037))

  </Accordion>

</Accordions>

## Acknowledgments and community

Turborepo is the result of the combined work of all of its contributors, including our core team: [Anthony](https://github.com/anthonyshew) and [Tom](https://github.com/tknickman).

Thank you for your continued support, feedback, and collaboration to make Turborepo your build tool of choice. To learn how to get involved, [visit the Community page](https://turborepo.dev/docs/community).

We also thank everyone who contributed to this release of Turborepo: @2qp, @AdelFetner, @AndrewPynch, @AryanBagade, @birajitsaikia, @ctate, @dsmurdoch357, @deepakpathik, @mrr11k, @lishaduck, @ethan-fraser, @eug-vs, @GAMMA_Demon, @hanlee, @jnsamines, @kitfoster, @louisbompart, @ognevny, @cmg8431, @chosim-dvlpr, @amond, @nicolascharpentier, @progyansen, @pyrytakala, @sakena1303, @vanshagarwal, @yairopro, @YASHRDX0001, @Yeom-JinHo, @Gabrola, @zacowan, @hookim, @johnpyp, @mahi656, and @neel.

Additionally, the core team would like to thank:

- [moklick](https://github.com/moklick) for their work on [xyflow](https://xyflow.com/), an open-source library for building node-based UIs with React and Svelte. xyflow is the basis of the package and task graph visualizations in Turborepo Devtools.

- [The Biome core team](https://biomejs.dev/internals/people-and-credits/#core-contributors) for their help in adding [the `noUndeclaredEnvVars` rule to Biome](https://biomejs.dev/linter/rules/no-undeclared-env-vars/).

---

### Apps Docs Content Blog You Might Not Need Typescript Project References (`apps/docs/content/blog/you-might-not-need-typescript-project-references.mdx`)

---
title: You might not need TypeScript project references
description: As it turns out, you might not even references or even an interim TypeScript build step with a pattern I am about to show you, which I dub "internal packages."
product: turborepo
type: overview
summary: An internal packages pattern that eliminates the need for TypeScript project references.
date: "2021/04/23"
tag: "web development"
---

<h1>You might not need TypeScript project references</h1>

import { Authors } from "@/components/blog/authors";
import { Callout } from "@/components/geistdocs/callout";

<Authors authors={["jaredpalmer"]} />

If you've worked in a larger TypeScript codebase or monorepo, you are likely familiar with [project references](https://www.typescriptlang.org/docs/handbook/project-references.html). They are indeed fairly powerful.

When you reference a project in your `tsconfig.json`, new things happen:

- Importing modules from a referenced project will instead load its output declaration file (`.d.ts`)
- If the referenced project produces an `outFile`, the output file `.d.ts` file’s declarations will be visible in this project
- Running build mode (`tsc -b`) will automatically build the referenced project if it hasn't been built but is needed
- By separating into multiple projects, you can greatly improve the speed of typechecking and compiling, reduce memory usage when using an editor, and improve enforcement of the logical groupings of your program.

Sounds awesome! Right?! Well...maybe. Once you add references to your project you now need to continuously update them whenever you add or remove packages. That kinda blows.

Well...what if you didn't need to?

## "Internal" TypeScript Packages

As it turns out, you might not even need references or even an interim TypeScript build step with a pattern I am about to show you, which I dub "internal packages."

**An "internal package" is a TypeScript package without a `tsconfig.json` with _both_ its `types` and `main` fields in its `package.json` pointing to the package's untranspiled entry point (e.g. `./src/index.tsx`).**

```json title="package.json"
{
  "name": "@sample/my-internal-package"
  "main": "./src/index.ts"
  "types": "./src/index.ts", // yes, this works!
  "dependencies": {
    ...
  },
  "devDependencies": {
    ...
  }
}
```

As it turns out, the TypeScript Language Server (in VSCode) and Type Checker can treat both a raw `.ts` or `.tsx` file as its own valid type declaration. This last sentence is obvious once you read it twice. What isn't so obvious, though, is that you can point the `types` field directly to raw source code.

Once you do this, this package can then be used _without_ project references or a TypeScript build step (either via `tsc` or `esbuild` etc) as long as you adhere to 2 rules:

- **The consuming application of an internal package must transpile and typecheck it.**
- **You should never publish an internal package to npm.**

As far as I can tell, this internal package pattern works with all yarn/npm/pnpm workspace implementations regardless of whether you are using Turborepo or some other tool. I have personally tested this pattern with several different meta frameworks (see below), but I'm sure that it works with others as well.

### Next.js

Next.js 13 can automatically transpile and bundle dependencies from local packages (like monorepos) or from external dependencies (`node_modules`).

```js title="next.config.js"
/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ["@acme/ui", "lodash-es"],
};

module.exports = nextConfig;
```

<Callout type="info">
  As of Next.js 13.1, you no longer need the `next-transpile-modules` package.
  For more information, visit the Next.js [Built-in module
  transpilation](https://nextjs.org/blog/next-13-1#built-in-module-transpilation-stable)
  blog post.
</Callout>

### Vite

Internal packages just work. No extra config is needed.

### React Native

If you use [Expo](https://expo.dev/) and use the [`expo-yarn-workspaces`](https://github.com/expo/expo/tree/master/packages/expo-yarn-workspaces) or [`@turborepo/adapter-expo`](https://www.npmjs.com/package/@turborepo/adapter-expo) package, you can use internal packages as long as you are targeting iOS or Android. When you run Expo for these platforms, all of `node_modules` are automatically transpiled with [Metro](https://facebook.github.io/metro/). However, if you are targeting Expo for web, internal packages will not work because `node_modules` are oddly not transpiled for web.

_I reached out to the Expo team about this inconsistency. They are aware of it. It's a legacy wart I'm told._

## The beauty of this pattern

This pattern rocks because it saves you from extra needless or duplicative build steps. It also gives you all the editor benefits of project references, but without any configuration.

## Caveats

When you use an internal package, it's kind of like telling the consuming application that you have another source directory—which has pros and cons. As your consuming application(s) grow, adding more internal packages is identical to adding more source code to that consuming application. Thus, when you add more source code, there is more code to transpile/bundle/typecheck...so this can result in slower builds of the consuming application (as there is just more work to do) but potentially faster (and less complicated) overall build time. When/if overall build time begins to suffer, you might decide to convert your larger internal packages back into "regular" packages with `.d.ts` files and with normal TypeScript build steps.

As previously mentioned, this pattern actually has very little to do with Turborepo. It's just super duper awesome and I think you should be aware of it. As we are actively working on preset package build rules (i.e. "builders") for Turborepo, we'll using the internal package pattern to skip build steps.

## Speaking of long build times...

Shameless plug here. If you are reading this post, and you're struggling with slow build and test times, I'd love to show you how Turborepo can help. I guarantee that Turborepo will cut your monorepo's build time by 50% or more. [You can request a live demo right here.](https://vercel.com/contact/sales?utm_source=turborepo.dev&utm_medium=referral&utm_campaign=blog-project-references)

---

### Apps Docs Content Docs Acknowledgments (`apps/docs/content/docs/acknowledgments.mdx`)

---
title: Acknowledgements
description: Thank you to all these developers, build systems, and monorepo tools for their support and assistance.
product: turborepo
type: overview
summary: Credits and thanks to the developers, build systems, and monorepo tools that inspired Turborepo.
related:
  - /docs/community
---

Turborepo was originally created by [Jared Palmer](https://x.com/jaredpalmer) as a closed-source enterprise software offering. In late 2021, [Vercel acquired Turborepo](https://vercel.com/blog/vercel-acquires-turborepo) and open sourced the codebase.

Today, Turborepo has a dedicated full-time team working on it as well as a growing list of [open source contributors](https://github.com/vercel/turborepo/graphs/contributors).

## Inspiration and Prior Art

At [Vercel](https://vercel.com/), we believe deeply in the open source movement and in the power of open collaboration. To that end, it's important to provide meaningful attribution to the projects and people that inspire(d) us and our work.

We'd like to make a special shoutout to other build systems, monorepo tools, and prior art:

- Bazel - https://bazel.build
- Buck - https://buck.build
- Please - https://please.build
- Pants - https://www.pantsbuild.org
- Scoot - https://github.com/twitter/scoot
- TSDX - https://tsdx.io
- Lerna - https://lerna.js.org
- Lage - https://microsoft.github.io/lage
- Backfill - https://github.com/microsoft/backfill
- Bolt - https://github.com/boltpkg/bolt
- Rush - https://rushjs.io
- Preconstruct - https://preconstruct.tools
- Nx - https://nx.dev
- Yarn - https://yarnpkg.com
- npm - https://www.npmjs.com
- pnpm - https://pnpm.js.org

Throughout the documentation, wherever applicable, we also provide inline callouts and links to the projects and people that have inspired us.

## Additional Thanks

Additionally, we're grateful to:

- [Rick Button](https://x.com/rickbutton) for donating the `turbo` package name on npm
- [Iheanyi Ekechukwu](https://x.com/kwuchu) for helping Jared pick up Golang during the Pandemic!
- [Kenneth Chau](https://x.com/kenneth_chau) for Lage's Scope and Pipeline API and docs
- [Miguel Oller](https://x.com/ollermi) and [MakeSwift.com](https://www.makeswift.com/) for piloting Turborepo
- [Eric Koslow](https://x.com/ekosz1), [Jack Hanford](https://x.com/jackhanford), and [Lattice.com](https://lattice.com/) for piloting Turborepo

---

### Apps Docs Content Docs Community (`apps/docs/content/docs/community.mdx`)

---
title: Community
description: Learn about the Turborepo community.
product: turborepo
type: overview
summary: Find ways to contribute, ask questions, and connect with other Turborepo developers.
related:
  - /docs/acknowledgments
---

Turborepo has a large and active community of developers across the world. Here's how you can get involved.

## Contributing

- [Documentation](https://github.com/vercel/turborepo/tree/main/docs): Suggest improvements or even write new sections to help build understanding of how to use Turborepo.
- [Examples](https://github.com/vercel/turborepo/tree/main/examples): Help developers integrate Turborepo with other tools and services by improving an example.
- [Code](https://github.com/vercel/turborepo/blob/main/CONTRIBUTING.md): Learn more about the underlying architecture, contribute bug fixes, and suggest new features.

## Discussions

If you have a question about Turborepo or want to help others, join the conversation:

- [GitHub Discussions](https://github.com/vercel/turborepo/discussions)
- [Vercel Community](https://community.vercel.com/tag/turborepo)

## Acknowledgements

Turborepo was originally created by [Jared Palmer](https://x.com/jaredpalmer) as a closed-source enterprise software offering. In late 2021, [Vercel acquired Turborepo](https://vercel.com/blog/vercel-acquires-turborepo) and open sourced the codebase.

Today, Turborepo has dedicated full-time team working on it as well as a growing list of [open source contributors](https://github.com/vercel/turborepo/graphs/contributors).

### Inspiration / Prior Art

At [Vercel](https://vercel.com/), we believe deeply in the open source movement and in the power of open collaboration. To that end, it's important to provide meaningful attribution to the projects and people that inspire(d) us and our work.

We'd like to make a special shoutout to other build systems, monorepo tools, and prior art:

- Bazel - https://bazel.build
- Buck - https://buck.build
- Please - https://please.build
- Pants - https://www.pantsbuild.org
- Scoot - https://github.com/twitter/scoot
- TSDX - https://tsdx.io
- Lerna - https://lerna.js.org
- Lage - https://microsoft.github.io/lage
- Backfill - https://github.com/microsoft/backfill
- Bolt - https://github.com/boltpkg/bolt
- Rush - https://rushjs.io
- Preconstruct - https://preconstruct.tools
- Nx - https://nx.dev
- Yarn - https://yarnpkg.com
- npm - https://www.npmjs.com
- pnpm - https://pnpm.js.org

### Additional Thanks

Additionally, we're grateful to:

- [Rick Button](https://x.com/rickbutton) for donating the `turbo` package name on npm
- [Iheanyi Ekechukwu](https://x.com/kwuchu) for helping Jared pick up Golang during the Pandemic!
- [Kenneth Chau](https://x.com/kenneth_chau) for Lage's Scope and Pipeline API and docs
- [Miguel Oller](https://mobile.x.com/ollermi) and [MakeSwift.com](https://www.makeswift.com/) for piloting Turborepo
- [Eric Koslow](https://x.com/ekosz1), [Jack Hanford](https://x.com/jackhanford), and [Lattice.com](https://lattice.com/) for piloting Turborepo

---

### Apps Docs Content Docs Support Policy (`apps/docs/content/docs/support-policy.mdx`)

---
title: Support policy
description: Learn about Turborepo's Support policy.
product: turborepo
type: reference
summary: Supported package managers, platforms, Node.js versions, and LTS policy for Turborepo.
---

## Package managers

Core `turbo` functionality depends on the package managers in the JavaScript ecosystem and their implementations of Workspaces and
lockfile formats.

| Package manager | Support                            |
| --------------- | ---------------------------------- |
| pnpm 8+         | Stable                             |
| npm 8+          | Stable                             |
| yarn 1+         | Stable (Includes Yarn Plug'n'Play) |
| bun 1.2+        | Stable                             |
| nub 0.8+        | Stable                             |
| aube 2.2+       | Stable                             |

<Callout type="info">
  Package managers have their own release schedules, bugs, and features. While
  we intend to keep up with new major versions, we likely will not be able to
  release support immediately.
</Callout>

## Platforms

`turbo` is generally supported on Debian-based Linux distributions, macOS, and
Windows on both x86_64 and ARM 64 architectures. Specifically, we build and ship
the following binaries via npm:

- `turbo-darwin-64` (macOS with Intel chips)
- `turbo-darwin-arm64` (macOS with Apple Silicon)
- `turbo-linux-64`
- `turbo-linux-arm64`
- `turbo-windows-64`\*
- `turbo-windows-arm64`\*

<small>
  \*: Requires [Windows C Runtime
  Libraries](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist)
</small>

## Node.js

Core `turbo` functionality does not depend on the
active Node.js version on your system, but [some packages in the Turborepo ecosystem](/docs/reference#packages)
such as [`create-turbo`](/docs/reference/create-turbo), [`turbo-ignore`](/docs/reference/turbo-ignore), and [`eslint-config-turbo`](/docs/reference/eslint-config-turbo) do. For these features,
we intend to support the [Active and Maintenance LTS versions of Node.js](https://nodejs.org/en/about/previous-releases).

Turborepo's [examples](/docs/getting-started/examples) are also expected to work with these Node.js versions.

## Version control

We support repositories that are version controlled with Git and repositories that don't have
version control at all. Any other version control system will be ignored.

Note that we use Git to hash files, so repositories without git may perform and behave differently.

## LTS policy

Major versions of Turborepo will be supported for two years from the release date of the next major version.

Changes required for critical security fixes in older versions will be backported. Such situations will be rare and will land as semver-minor releases, even if they are breaking changes.

We highly encourage you to use the most current version of Turborepo whenever possible.

| Major version | Release date | End-of-life date |
| ------------- | ------------ | ---------------- |
| 2.x           | Jun. 4, 2024 | -                |
| 1.x           | Dec. 9, 2021 | Jun. 4, 2026     |

## Release phases

Stable builds of Turborepo follow semantic versioning (semver) and are thoroughly tested before being released.

Turborepo also offers specific APIs that may be released in an earlier phase of development. This is to allow early adopters to give valuable feedback and help the core team gain confidence in APIs ahead of their stable release. APIs that are available pre-stable will be marked as such in the documentation and within `turbo` itself whenever possible.

Not every API will be released in every phase. We use our best judgment to determine the phase for an API based on our confidence for the feature, weighing factors like the feature's complexity, possible use cases, and feedback from early users of the API.

The Turborepo core team would like to thank any users who do use features early and express our appreciation for any feedback you provide.

### Stable

When an API reaches stability, it is considered ready for use in production. APIs marked as stable will only change in a backward-compatible way in a major release.

- If a stable API is going to **have breaking changes** in an upcoming major release, warnings and documentation will be provided to help with migrations and next steps.
- If a stable API is going to be **removed** in an upcoming major release, it will be marked as [Deprecated](#deprecated) to provide early notice of future removal.

### Beta

Beta APIs require more confidence around reliability before a stable release. In the Beta phase, we are confident about the overall design of the feature and expect to be able to promote the feature to stable with relatively few changes. In rare cases, an API may require a breaking change and will not be covered by semver.

We encourage early adopters to use Beta APIs to help us gain certainty around the feature's design and stability. Depending on your risk tolerance, you can use the feature in production as you see fit.

**APIs currently in the Beta phase:**

- None

### Experimental

Experimental APIs lack essential capabilities required to be ready for stability. The design of the feature is considered to be under active development and can change at any time.

We encourage you to help us test experimental APIs in side projects, proof-of-concepts, and other environments where stability is non-essential. This gives you the opportunity to aid in the API's development by providing early feedback to the core team as the feature develops. We do not recommend using experimental APIs where reliability is essential.

**APIs currently in the Experimental phase:**

- [Rust support](/docs/guides/tools/rust)
- [uv support](/docs/guides/tools/python)
- [Go support](/docs/guides/tools/go)
- [`turbo boundaries`](/docs/reference/boundaries) and [Tags](/docs/reference/boundaries#tags)
- [`--experimental-write-cache` for `turbo watch`](/docs/reference/watch#caching)
- [`--output` for `turbo ls`](/docs/reference/ls#--output-format)

### Deprecated

Deprecated APIs are in the process of being removed. Any feature we intend to remove will include documentation for existing users with next steps and information on when to expect the feature to be removed.

**APIs that are currently deprecated:**

- [`turbo-ignore`](/docs/reference/turbo-ignore): Use [`turbo query affected`](/docs/reference/query#affected) instead.
- [`turbo scan`](/docs/reference/scan): This command has been removed and will be fully deleted in a future major version.
- `--parallel`: Use [`persistent`](/docs/reference/configuration#persistent) and [`with`](/docs/reference/configuration#with) in `turbo.json` instead.
- `--no-cache`: Use [`--cache=local:r,remote:r`](/docs/reference/run#--cache-options) instead.
- `TURBO_REMOTE_ONLY` and `--remote-only`: Use [`TURBO_CACHE`](/docs/reference/system-environment-variables) or [`--cache=remote:rw`](/docs/reference/run#--cache-options) instead.
- `--remote-cache-read-only`: Use [`--cache=local:rw,remote:r`](/docs/reference/run#--cache-options) instead.
- `--daemon` / `--no-daemon` / `daemon` key in `turbo.json`: The daemon is no longer used and these options will be removed in a future major version.
- `--graph` with `.png`, `.jpg`, `.pdf`, or `.json` output: These formats require an external Graphviz installation and will be removed in version 3.0. Use `.svg`, `.html`, `.mermaid`, or `.dot` instead. For programmatic access to the task graph, use [`turbo query`](/docs/reference/query).
- `--scope` for [`turbo prune`](/docs/reference/prune): Use positional arguments instead (e.g. `turbo prune web`).
- `globalDependencies`, `globalEnv`, and `globalPassThroughEnv` at the root level: Use the [`globalConfiguration` Future Flag](/docs/reference/configuration#globalconfiguration) to migrate to the new [`global` key](/docs/reference/configuration#global).

---

### Apps Docs Content Docs Telemetry (`apps/docs/content/docs/telemetry.mdx`)

---
title: Telemetry
description: Learn more about Turborepo's anonymous telemetry.
product: turborepo
type: conceptual
summary: Understand what anonymous telemetry data Turborepo collects and how to opt out.
---

Vercel Inc. (Vercel) may collect telemetry data about your use of Turborepo as explained below.
Telemetry data allows us to monitor and improve Turborepo and the Vercel platform by
collecting anonymous data about its usage and host information. The data may be used to broadly identify,
troubleshoot, or respond to issues that impact users.

Collection of telemetry data is optional. If you do not want telemetry data collected, you may [opt-out](#how-do-i-opt-out).

## Why

Telemetry allows us to accurately gauge Turborepo feature usage, pain points, and customization across all users.
This data enables us to better tailor Turborepo to the masses, ensuring its continued growth, relevance, and best-in-class developer experience.
Furthermore, this data allows us to verify if improvements are improving the baseline of all applications.

## What is collected

We track general usage information, specifically, we track the following with anonymized telemetry data using random identifiers:

- Command invoked ([turbo run](/docs/reference/run), [turbo prune](/docs/reference/prune), [turbo gen](/docs/reference/generate), etc.)
- Version of `turbo`
- General machine information (e.g. number of CPUs, macOS/Windows/Linux, whether or not the command was run within CI)
- Size of application (total number of workspaces)
- We **DO NOT** collect any metrics which may contain sensitive data. This includes, but is not limited to: task names, package names, sensitive argument or flag values, environment variables, file paths, or contents of files.

**Note**: This list is regularly audited to ensure its accuracy.

You can view exactly what is being collected by setting the following environment variable: `TURBO_TELEMETRY_DEBUG=1`.

Additionally, all possible events can be viewed by browsing the [events](https://github.com/vercel/turborepo/blob/main/crates/turborepo-telemetry/src/events) file directly.

## How do I opt out?

### Disable

You may opt out-by running:

```bash title="Terminal"
turbo telemetry disable
```

You can also opt out by setting any of the following environment variables:

- `TURBO_TELEMETRY_DISABLED=1`
- `DO_NOT_TRACK=1`

### Status

You may check the status of telemetry collection at any time by running:

```sh title="Terminal"
turbo telemetry status
```

### Enable

You may re-enable telemetry if you'd like to re-join the program by running the following:

```sh title="Terminal"
turbo telemetry enable
```

---

### Apps Docs Content External Blog How Turborepo Is Porting From Go To Rust (`apps/docs/content/external-blog/how-turborepo-is-porting-from-go-to-rust.mdx`)

---
title: "How Turborepo is porting from Go to Rust"
description: "Our strategy for making updates and maintaining stability while we migrate languages."
product: turborepo
type: overview
summary: Turborepo's strategy for porting from Go to Rust while maintaining stability.
isExternal: true
href: "https://vercel.com/blog/how-turborepo-is-porting-from-go-to-rust"
date: "2023/07/21"
---

# External Entry

---

### Apps Docs Content External Blog How We Continued Porting Turborepo To Rust (`apps/docs/content/external-blog/how-we-continued-porting-turborepo-to-rust.mdx`)

---
title: Using Zig in our incremental Turborepo migration from Go to Rust
description: Learn how we're cross-compiling a Rust-Go-Rust sandwich to 6 platforms.
product: turborepo
type: overview
summary: How Zig enables cross-compiling Turborepo's Rust-Go-Rust stack to multiple platforms.
isExternal: true
date: "2023/09/08"
href: "https://vercel.com/blog/how-we-continued-porting-turborepo-to-rust"
---

# External Entry

---

### Apps Docs Content External Blog Turbopack Moving Homes (`apps/docs/content/external-blog/turbopack-moving-homes.mdx`)

---
title: "Turbopack updates: Moving homes"
description: "Progress with Turbopack, current priorities, and a move to a different repository."
product: turbopack
type: overview
summary: Turbopack moves to a new repository with updates on priorities and progress.
isExternal: true
href: "https://vercel.com/blog/turbopack-moving-homes"
date: "2024/07/23"
---

# External Entry

---

### Apps Docs Content Extra Governance (`apps/docs/content/extra/governance.mdx`)

---
title: Governance
description: Turborepo by Vercel is the next-generation build system for the web.
product: turborepo
type: overview
summary: Governance structure and team information for the Turborepo open-source project.
---

Turborepo was created by the team at [Vercel](https://vercel.com) in 2020.

The research and development of Turborepo is led by the core team working full-time at Vercel. Turborepo is a collaborative open-source effort to build tools for web developers.

## Teams

**Core Team**: The Turborepo team at [Vercel](https://vercel.com) manages the direction of Turborepo and leads the project.

**Documentation**: DevRel teams at [Vercel](https://vercel.com) manage documentation and learning platforms.

## Roadmap and RFC Process

Large architecture decisions and features start as a [Request for Comments (RFC)](https://github.com/vercel/turborepo/discussions/categories/rfc) inside GitHub Discussions. The entire Turborepo community is invited to be involved in the process and discuss the tradeoffs of proposed work.

This process is essential to ensure features are built together with the community and our collaborators. More minor changes including bug fixes and documentation improvements are still implemented through GitHub pull requests. However, for larger initiatives, we believe it's essential to follow the RFC process.

## Stability and release phases

- **Experimental**: Experimental features lack essential capabilities required to be ready for stability. The feature is considered to be under active development and is being built to transition into Beta.
- **Beta**: Beta means the feature does not yet meet our quality standards for a stable release. There is also usually a need for more information or feedback from Turborepo developers to validate this feature works as expected in a variety of environments.
- **Stable**: When the features reach stability, it is considered ready for production use. APIs marked as stable will only change in a backward-compatible way unless there is a major release.
- **Deprecated**: A feature is in the process of being removed. Deprecated features include documentation for existing users with the next steps and information on when to expect the feature to be removed.

## Turborepo Support

For individual developers looking for free support on their Turborepo repositories, they can ask questions in [GitHub Discussions](https://github.com/vercel/turborepo/discussions) or in [Vercel Community's `#turborepo` tag](https://community.vercel.com/tag/turborepo).

For companies looking for paid support on their Turborepo repositories, they can [contact the Turborepo team at Vercel](https://vercel.com/contact) for more information.

## Additional Resources

- [Logo Policy and Brand Guidelines](https://vercel.com/design/brands#turbo)
- [Reporting Security Issues](https://github.com/vercel/turbo/blob/main/SECURITY.md)
- [Code of Conduct](https://github.com/vercel/turbo/blob/main/CODE_OF_CONDUCT.md)
- [Contributing Guidelines](https://github.com/vercel/turbo/blob/main/CONTRIBUTING.md)

---

### Apps Docs Content Extra Terms (`apps/docs/content/extra/terms.mdx`)

---
title: Terms of Service
description: See our terms of our service and how they relate to you.
product: turborepo
type: reference
summary: Terms of service governing use of the Turborepo website.
---

THE TERMS AND CONDITIONS SET FORTH BELOW (THE "TERMS") GOVERN YOUR USE OF THIS SITE. THESE TERMS ARE A LEGAL CONTRACT BETWEEN YOU AND VERCEL INC. ("Vercel", "WE" OR "US") AND GOVERN YOUR ACCESS TO, AND USE OF, THE TURBOREPO.ORG WEBSITE (THE "SITE"). IF YOU DO NOT AGREE WITH ANY OF THESE TERMS, DO NOT ACCESS OR OTHERWISE USE THIS SITE OR ANY INFORMATION CONTAINED ON THIS SITE. YOUR USE OF THIS SITE SHALL BE DEEMED TO BE YOUR AGREEMENT TO ABIDE BY EACH OF THE TERMS SET FORTH BELOW. VERCEL MAY MAKE CHANGES TO THE CONTENT OFFERED ON THIS SITE AT ANY TIME. VERCEL CAN CHANGE THESE TERMS AT ANY TIME. IF VERCEL MAKES ANY CHANGES, VERCEL WILL POST AN UPDATED TERMS OF USE ON THIS SITE AND MAY SEND REGISTERED USERS AN EMAIL NOTICE OF THE CHANGES. IF ANY MODIFICATION IS UNACCEPTABLE TO YOU, YOU SHALL CEASE USING THIS SITE. IF YOU DO NOT CEASE USING THIS SITE, YOU WILL BE DEEMED TO HAVE ACCEPTED THE CHANGE.

TURBOREPO SOFTWARE IS SEPARATELY MADE AVAILABLE PURSUANT TO AN OPEN SOURCE LICENSE AND YOU MAY FIND LINKS TO THE TURBOREPO SOFTWARE AND ITS ASSOCIATED LICENSES ON THIS SITE.

## General Use Restrictions

Vercel provides various content through this Site. Certain information, documents, documentation, products and services provided on and through this Site, including content, logos, graphics and images (together, the "Materials") are made available to you by Vercel and are the copyrighted and/or trademarked work of Vercel or Vercel's licensors.

Vercel grants you a limited, personal, non-exclusive and non-transferable license to use and to display and to make one copy of the Materials solely for your personal or internal business use. Except for the license set forth in the preceding sentence above, you acknowledge and agree that you have no right to modify, edit, copy, reproduce, create derivative works of, reverse engineer, alter, enhance or in any way exploit any of the Materials in any manner. This limited license terminates automatically, without notice to you, if you breach any of these Terms. Except as stated herein, you acknowledge that you have no right, title or interest in or to this Site, or any Materials.

## Privacy Policy

Your use of this Site is governed by Vercel's Privacy Policy, which is available at https://vercel.com/legal/privacy-policy (the "Privacy Policy").

## Third Party Content

Certain information and other content on the Site may be the material of third party licensors and suppliers to Vercel ("Third Party Content"). The Third Party Content is, in each case, the copyrighted and/or trademarked work of the creator/licensor. You agree to only display the Third Party Content on your computer solely for your personal or internal business use. You acknowledge and agree that you have no right to download, cache, reproduce, modify, display (except as set forth in this paragraph), edit, alter or enhance any of the Third Party Content in any manner unless you have permission from the owner of the Third Party Content. Vercel DISCLAIMS ALL EXPRESS, IMPLIED AND STATUTORY WARRANTIES AND CONDITIONS WITH REGARD TO THIRD PARTY CONTENT, INCLUDING, BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.

## Links to Other Vercel Sites and Third Party Sites

This Site may be linked to other Vercel sites where you may find other information regarding Vercel and its services.
This Site also links to other sites that are not Vercel sites. Vercel is providing these links to you only as a convenience, and Vercel is not responsible for such linked sites, including, without limitation, the content or links displayed on such sites.

## Unauthorized Activities

Unauthorized use of any Materials or Third Party Content contained on this Site may violate certain laws and regulations. You agree to indemnify and hold Vercel and its officers, directors, employees, affiliates, agents, licensors, and business partners harmless from and against any and all costs, damages, liabilities, and expenses (including attorneys' fees and costs of defense) Vercel or any other indemnified party suffers in relation to, arising from, or for the purpose of avoiding, any claim or demand from a third party that your use of this Site violates any applicable law or regulation, or the copyrights, trademark rights or other rights of any third party.

## Proprietary Rights

Vercel and Turborepo are trademarks of Vercel. Other trademarks, names and logos on this Site are the property of their respective owners.

Unless otherwise specified in these Terms, all information and screens appearing on this Site, including documents, services, site design, text, graphics, logos, images and icons, as well as the arrangement thereof, are the sole property of Vercel Inc., Copyright © 2021-2022 Vercel Inc. All rights not expressly granted herein are reserved. Except as otherwise required or limited by applicable law, any reproduction, distribution, modification, retransmission, or publication of any copyrighted material is strictly prohibited without the express written consent of the copyright owner or license.

## Disclaimer of Warranties

Your use of this Site is at your own risk. Neither the Materials nor the Third Party Content have been verified or authenticated in whole or in part by Vercel, and they may include inaccuracies or typographical or other errors. Vercel does not warrant the accuracy or timeliness of the Materials or the Third Party Content contained on this Site. Vercel has no liability for any errors or omissions in the Materials and/or the Third Party Content, whether provided by Vercel or our licensors.

VERCEL, FOR ITSELF AND ITS LICENSORS, MAKES NO EXPRESS, IMPLIED OR STATUTORY REPRESENTATIONS, WARRANTIES, OR GUARANTEES IN CONNECTION WITH THIS SITE, ANY MATERIALS, OR THIRD PARTY CONTENT, RELATING TO THE QUALITY, SUITABILITY, TRUTH, ACCURACY OR COMPLETENESS OF ANY INFORMATION OR MATERIAL CONTAINED OR PRESENTED ON THIS SITE AND/OR THE RESULTS OBTAINED FROM THE USE OF THIS SITE, INCLUDING WITHOUT LIMITATION THE MATERIALS AND THE THIRD PARTY CONTENT. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SITE, THE SERVICES, MATERIALS, THIRD PARTY CONTENT, AND ANY INFORMATION OR MATERIAL CONTAINED OR PRESENTED ON THIS SITE IS PROVIDED TO YOU ON AN "AS IS," "AS AVAILABLE" AND "WHERE-IS" BASIS WITH NO WARRANTY OF IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT OF THIRD PARTY RIGHTS. VERCEL DOES NOT PROVIDE ANY WARRANTIES AGAINST VIRUSES, SPYWARE OR MALWARE THAT MAY BE INSTALLED ON YOUR COMPUTER. VERCEL HAS SOLE DISCRETION WHETHER TO ACCEPT OR REJECT YOU AS AN EXPERT OR A CLIENT.

## Limitation of Liability

VERCEL SHALL NOT BE LIABLE TO YOU FOR ANY DAMAGES RESULTING FROM YOUR DISPLAYING, COPYING, OR DOWNLOADING ANY MATERIAL OR THIRD PARTY CONTENT TO OR FROM THIS SITE. IN NO EVENT SHALL VERCEL BE LIABLE TO YOU FOR ANY INDIRECT, EXTRAORDINARY, EXEMPLARY, PUNITIVE, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES (INCLUDING LOSS OF DATA, REVENUE, PROFITS, USE OR OTHER ECONOMIC ADVANTAGE) HOWEVER ARISING, EVEN IF VERCEL KNOWS THERE IS A POSSIBILITY OF SUCH DAMAGE OR FOR DAMAGES IN THE AGGREGATE EXCEEDING THE AMOUNT OF ONE HUNDRED DOLLARS.

## Local Laws; Export Control

Vercel controls and operates this Site from its headquarters in the United States of America and the Materials and/or Third Party Content may not be appropriate or available for use in other locations. If you use this Site outside the United States of America, you are responsible for following applicable local laws.

## General

If you violate these Terms, Vercel may terminate and/or suspend your access to this Site without notice. The proprietary rights, disclaimer of warranties, representations made by you, indemnities, limitations of liability and general provisions shall survive any termination of these Terms.

Vercel may change these Terms from time to time by providing thirty (30) days prior notice either by posting a notice at the Site. You can review the most current version of these Terms at any time at this Site. The revised Terms will become effective thirty (30) days after Vercel posts or sends you notice of such changes, and if you use the Site after that date, your use will constitute acceptance of the revised Terms. If any change to these Terms are not acceptable to you, your only remedy is to stop using the Site. If any provision of these Terms are found to be unenforceable or invalid, that provision will be limited or eliminated to the minimum extent necessary so that these Terms will otherwise remain in full force and effect and enforceable. You may not assign, transfer or sublicense without the prior written consent of Vercel, but Vercel may assign or transfer these Terms, in whole or in part, without restriction. Any attempted assignment or transfer of these Terms by the parties in contravention of the foregoing shall be null and void. These Terms are the complete and exclusive statement of the mutual understanding of the parties and supersedes and cancels all previous written and oral agreements, communications and other understandings relating to the subject matter of these Terms, and that all amendments must be in writing signed by both parties, except as otherwise provided herein. Vercel's failure to exercise or enforce any right or provision of these Terms shall not be a waiver of that right. No agency, partnership, joint venture, or employment is created as a result of these Terms and neither party has any authority of any kind to bind the other party in any respect whatsoever. In any action or proceeding to enforce rights under these Terms, the prevailing party will be entitled to recover costs and attorneys' fees. Except as stated above, all notices under these Terms will be in writing and will be deemed to have been duly given when received, if personally delivered or sent by certified or registered mail, return receipt requested; when receipt is electronically confirmed, if transmitted by facsimile or e-mail; or the day after it is sent, if sent for next day delivery by recognized overnight delivery service.

Any delays in or failure of performance of Vercel shall not constitute a default hereunder or give rise to any claims for damages if, to the extent that, and for such period that, such delays or failures of performance are caused by any events beyond the reasonable control of Vercel including, without limitation, any of the following specific occurrences: acts of God or the public enemy, acts of terrorism, pandemics, epidemics, labor strikes, expropriation or confiscation of facilities, compliance with any unanticipated duly promulgated governmental order, acts of war, rebellion or sabotage or damage resulting therefrom, fires, floods, explosion, or riots.

## Governing Law; Disputes; Arbitration.

**Law.** These Terms shall be governed by the laws of the State of California without regard to its conflict of laws provisions and the parties agree to the exclusive jurisdiction of the state and federal courts in San Francisco county.

**Binding Contract.** You acknowledge that these Terms are a contract between you and Vercel, even though it is electronic and is not physically signed by you and Vercel, and it governs your use of the Site.

**Arbitration.** Certain portions of this Section are deemed to be a "written agreement to arbitrate" pursuant to the Federal Arbitration Act ("FAA"). You and Vercel expressly agree and intend that this Section satisfies the "writing" requirement of the Federal Arbitration Act. This Section can only be amended by mutual agreement. For purposes of this Section, "Claims" means collectively, and without limitation, any and all claims, injuries, demands, liabilities, disputes, causes of action (including statutory, contract, negligence, or other tort theories), proceedings, obligations, debts, liens, fines, charges, penalties, contracts, promises, costs, expenses (including attorneys' fees, whether incurred pre-litigation, pre-trial, at trial, on appeal, or otherwise), damages of any kind whatsoever (including consequential, compensatory, or punitive damages), or losses (whether known, unknown, asserted, non-asserted, fixed, conditional, or contingent) that arise from or relate to (i) the Site, including any and all contents, materials and software related thereto, and/or (ii) your use of the Site.

**Informal Dispute Resolution.** If any Claim arises out of or relates to the Site or these Terms, other than as may be provided herein, then you and Vercel agree to send notice to the other providing a reasonable description of the Claim, along with a proposed resolution of it. Vercel notice to you will be sent based on the most recent contact information that you provided Vercel. If no such information exists or if such information is not current, Vercel has no obligation under this Section. For a period of sixty (60) days from the date of receipt of notice from the other party, you and Vercel will engage in a dialog to attempt to resolve the Claim, though nothing will require either you or Vercel to resolve the Claim on terms with respect to which you and Vercel, in each of the parties' sole discretion, is not comfortable.

**Applicable Law.** If you and Vercel cannot resolve a Claim, within sixty (60) days of the receipt of the notice, then you agrees that that any such Claim and all other disputes arising out of or relating to the interpretation, applicability, enforceability or formation of these Terms, including, but not limited to any claim that all or any part of these Terms are void or voidable, or whether a claim is subject to arbitration relating to your use of the Site, will be resolved by binding arbitration, rather than in court. The FAA, not state law, shall govern the arbitrability of such disputes, including the class action waiver below. However, you and Vercel agree that California state law or United States federal law shall apply to, and govern, as appropriate, any and all Claims or disputes arising between you and Vercel regarding these Terms and the Site, whether arising or stated in contract, statute, common law, or any other legal theory, without regard to choice of law principles. There is no judge or jury in arbitration, and court review of an arbitration award is limited. However, an arbitrator must follow the terms of these Terms as a court would. THIS SECTION, INCLUDING THE PROVISIONS ON BINDING ARBITRATION AND CLASS ACTION WAIVER, SHALL SURVIVE ANY TERMINATION OF YOUR ACCOUNT OR THE SERVICE.

**Arbitration Request.** To begin an arbitration proceeding, you must send a letter requesting arbitration and describing your claim to Vercel at 340 S Lemon Ave #4133, Walnut CA, 91789. The arbitration will be conducted by JAMS in accordance with the JAMS Streamlined Arbitration Procedure Rules in effect at the time the arbitration is initiated, excluding any rules or procedures governing or permitting class actions. Payment of all filing, administration and arbitrator fees will be governed by JAMS's rules. The arbitration shall take place in San Francisco, California or at such other venue (and pursuant to such procedures) as is mutually agreed upon. You can obtain JAMS procedures, rules, and fee information as follows: JAMS: 800.352.5267 and https://www.jamsadr.com.

**Fees.** You and Vercel will pay the administrative and arbitrator's fees and other costs in accordance with the applicable arbitration rules; but if applicable arbitration rules or laws require Vercel to pay a greater portion or all of such fees and costs in order for this Section to be enforceable, then Vercel will have the right to elect to pay the fees and costs and proceed to arbitration. Arbitration rules may permit Vercel to recover attorneys' fees. Vercel will not seek to recover attorneys' fees and costs in arbitration unless the arbitrator determines the claims are frivolous.

**Class Action Waiver.** YOU AND VERCEL EACH AGREE THAT ANY DISPUTE RESOLUTION PROCEEDING WILL BE CONDUCTED ONLY ON AN INDIVIDUAL BASIS AND NOT IN A CLASS, CONSOLIDATED OR REPRESENTATIVE ACTION. You and Vercel each agree that such proceeding shall take solely by means of judicial reference pursuant to California Code of Civil Procedure section 638.

**Exceptions.** Notwithstanding the agreement to resolve all disputes through arbitration, you or Vercel may bring suit in court to enjoin infringement or other misuse of intellectual property rights (including patents, copyrights, trademarks, trade secrets, and moral rights, but not including privacy rights). You or Vercel may also seek relief in small claims court for Claims within the scope of that court's jurisdiction. In the event that the arbitration provisions above are found not to apply to you or to a particular Claim, either as a result of your decision to opt-out of the arbitration provisions or as a result of a decision by the arbitrator or a court order, you agree that the venue for any such Claim or dispute is exclusively that of a state or federal court located in San Francisco County, California. You and Vercel agree to submit to the personal jurisdiction of the courts located within San Francisco County, California for the purpose of litigating all such Claims or any other disputes arising out of or relating to the interpretation, applicability, enforceability or formation of these Terms or your use of the Site in the event that the arbitration provisions are found not to apply. In such a case, should Vercel prevail in litigation against you to enforce its rights under these Terms, Vercel shall be entitled to its costs, expenses, and reasonable attorneys' fees (whether incurred at or in preparation for trial, appeal or otherwise) incurred in resolving or settling the dispute, in addition to all other damages or awards to which Vercel may be entitled.

**Restrictions.** TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, IF YOU OR VERCEL WANT TO ASSERT A DISPUTE AGAINST THE OTHER, THEN YOU OR VERCEL MUST COMMENCE IT (BY DELIVERY OF WRITTEN NOTICE AS SET FORTH HEREIN) WITHIN ONE (1) YEAR AFTER THE DISPUTE ARISES OR IT WILL BE FOREVER BARRED. "Commencing" means, as applicable: (i) by delivery of written notice as set forth herein; (ii) filing for arbitration with JAMS as set forth herein; or (iii) filing an action in state or federal court. This provision will not apply to any legal action taken by Vercel to seek an injunction or other equitable relief in connection with any losses (or potential losses) relating to the Site, intellectual property rights of Vercel, and/or Vercel's provision of the Site.

**Opt-Out.** You have the right to opt-out and not be bound by the arbitration and class action waiver provisions set forth above by sending written notice of your decision to opt-out to: privacy@vercel.com with the subject line "COMPANY ARBITRATION AND CLASS ACTION WAIVER OPT-OUT". The notice must be sent within thirty (30) days of your first use of the Site, otherwise you shall be bound to arbitrate any disputes in accordance with these Terms providing for binding arbitration. If you opt-out of these arbitration provisions, Vercel also will not be bound by them.

Date last updated: December 8th, 2021

---

### Apps Docs Public .Well Known Security (`apps/docs/public/.well-known/security.txt`)

Contact: https://hackerone.com/vercel
Expires: 2027-09-30T12:00:00.000Z
Preferred-Languages: en
Policy: https://security.vercel.com/
Canonical: https://turborepo.dev/.well-known/security.txt
Hiring: https://vercel.com/careers?function=Security+%26+IT#positions

---

### Packages Eslint Plugin Turbo Docs Rules No Undeclared Env Vars (`packages/eslint-plugin-turbo/docs/rules/no-undeclared-env-vars.md`)

# Ensure all environment variables are correctly included in cache keys (`no-undeclared-env-vars`)

Ensures that all detectable usage of environment variables are correctly included in cache keys. This ensures build outputs remain correctly cacheable across environments.

## Rule Details

This rule aims to prevent users from forgetting to include an environment variable in their `turbo.json` configuration.

The following examples assume the following code:

```js
const client = MyAPI({ token: process.env.MY_API_TOKEN });
```

Examples of **incorrect** code for this rule:

```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**", "!.next/dev/**"]
    },
    "lint": {},
    "dev": {
      "cache": false
    }
  }
}
```

Examples of **correct** code for this rule:

```json
{
  "globalEnv": ["MY_API_TOKEN"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**", "!.next/dev/**"]
    },
    "lint": {},
    "dev": {
      "cache": false
    }
  }
}
```

```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "env": ["MY_API_TOKEN"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**", "!.next/dev/**"]
    },
    "lint": {},
    "dev": {
      "cache": false
    }
  }
}
```

## Options

| Option      | Required | Default | Details                                                                                                                                     | Example                                      |
| ----------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
| `allowList` | No       | []      | An array of strings (or regular expressions) to exclude. NOTE: an env variable should only be excluded if it has no effect on build outputs | `["MY_API_TOKEN", "^MY_ENV_PREFIX_[A-Z]+$"]` |

## Further Reading

- [Environment Variable Inputs](https://turborepo.dev/docs/crafting-your-repository/using-environment-variables)

---

### Apps Docs Content Docs Core Concepts Internal Packages (`apps/docs/content/docs/core-concepts/internal-packages.mdx`)

---
title: Internal Packages
description: Learn how to build Internal Packages in your monorepo.
product: turborepo
type: conceptual
summary: Understand how internal packages work and their compilation strategies for sharing code across your monorepo.
prerequisites:
  - /docs/core-concepts/package-types
related:
  - /docs/crafting-your-repository/creating-an-internal-package
  - /docs/core-concepts/package-and-task-graph
  - /docs/guides/publishing-libraries
---

Internal Packages are libraries whose source code is inside your Workspace. You can quickly make Internal Packages to share code within your monorepo and choose to [publish them to the npm registry](/docs/guides/publishing-libraries) if you need to later.

Internal Packages are used in your repository by installing them in `package.json` similar to an external package coming from the npm registry. However, instead of marking a version to install, you can reference the package using your package manager's workspace installation syntax:

<PackageManagerTabs>

<Tab value="pnpm">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "@repo/ui": "workspace:*" // [!code highlight]
  }
}
```
</Tab>

<Tab value="yarn">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "@repo/ui": "*" // [!code highlight]
  }
}
```
</Tab>

<Tab value="npm">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "@repo/ui": "*" // [!code highlight]
  }
}
```
</Tab>

<Tab value="bun">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "@repo/ui": "workspace:*" // [!code highlight]
  }
}
```
</Tab>

<Tab value="nub">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "@repo/ui": "workspace:*" // [!code highlight]
  }
}
```
</Tab>

<Tab value="aube">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "@repo/ui": "workspace:*" // [!code highlight]
  }
}
```
</Tab>

</PackageManagerTabs>

In the [Creating an Internal Package guide](/docs/crafting-your-repository/creating-an-internal-package), you can build an Internal Package from the beginning using [the Compiled Package strategy](#compiled-packages). On this page, we'll describe other strategies for creating Internal Packages and their tradeoffs, including [publishing the package to the npm registry](#publishable-packages) to create an External Package.

You can then import the package into your code like you're used to doing with an external package:

```tsx title="./apps/web/app/page.tsx"
import { Button } from "@repo/ui"; // [!code highlight]

export default function Page() {
  return <Button>Submit</Button>;
}
```

## Compilation Strategies

Depending on what you need from your library, you can choose one of three compilation strategies:

- [**Just-in-Time Packages**](#just-in-time-packages): Create minimal configuration for your package by allowing application bundlers to compile the package as it uses it.
- [**Compiled Packages**](#compiled-packages): With a moderate amount of configuration, compile your package using a build tool like `tsc` or a bundler.
- [**Publishable Packages**](#publishable-packages): Compile and prepare a package to publish to the npm registry. This approach requires the most configuration.

### Just-in-Time Packages

A Just-in-Time package is compiled by the application that uses it. This means you can use your TypeScript (or uncompiled JavaScript) files directly, requiring much less configuration than the other strategies on this page.

This strategy is most useful when:

- Your applications are built using a modern bundler like Turbopack, webpack, or Vite.
- You want to avoid configuration and setup steps.
- You're satisfied with your applications' build times, even when you can't hit cache for the package.

A `package.json` for a Just-in-Time package may look like this one:

```json title="./packages/ui/package.json"
{
  "name": "@repo/ui",
  "exports": {
    "./button": "./src/button.tsx", // [!code highlight]
    "./card": "./src/card.tsx" // [!code highlight]
  },
  "scripts": {
    "lint": "eslint . --max-warnings 0", // [!code highlight]
    "check-types": "tsc --noEmit" // [!code highlight]
  }
}
```

There are a few important things to notice in this `package.json`:

- **Directly exporting TypeScript**: The `exports` field marks the entrypoints for the package and, in this case, you're **referencing TypeScript files directly**. This is possible because the bundler for the application will compile the code as it uses it in its build process.
- **No `build` script**: Because this package is exporting TypeScript, it doesn't need a build step for transpiling the package. This means you don't have to configure a build tool in this package to make it work in your Workspace.

#### Limitations and tradeoffs

- **Only applicable when consumers do transpiling**: This strategy can only be used when the package is going to be used in tooling that uses a bundler or natively understands TypeScript. The consumer's bundler is responsible for transpiling the TypeScript packages to JavaScript. If your builds or other usages of the package are not able to consume TypeScript, you will need to move to the [Compiled Packages](#compiled-packages) strategy.
- **No TypeScript `paths`**: A library that is being transpiled by its consumer cannot use the `compilerOptions.paths` configuration because TypeScript assumes that source code is being transpiled in the package where it is written. If you're using TypeScript 5.4 or later, we recommend [using Node.js subpath imports](https://devblogs.microsoft.com/typescript/announcing-typescript-5-4/#auto-import-support-for-subpath-imports). To learn how, visit [our TypeScript page](/docs/guides/tools/typescript#use-nodejs-subpath-imports-instead-of-typescript-compiler-paths).
- **Turborepo cannot cache a build for a Just-in-Time Package**: Because the package doesn't have its own `build` step, it can't be cached by Turborepo. This tradeoff may make sense for you if you want to keep configuration to a minimum and are okay with the build times for your applications.
- **Errors in internal dependencies will be reported**: When directly exporting TypeScript, type-checking in a dependent package will fail if code in an internal dependency has TypeScript errors. You may find this confusing or problematic in some situations.

### Compiled Packages

A Compiled Package is a package that handles its own compilation using a build tool, like [`tsc` (the TypeScript compiler)](https://www.typescriptlang.org/docs/handbook/compiler-options.html#handbook-content).

```json title="./packages/ui/package.json"
{
  "name": "@repo/ui",
  "exports": {
    "./button": {
      "types": "./src/button.tsx", // [!code highlight]
      "default": "./dist/button.js" // [!code highlight]
    },
    "./card": {
      "types": "./src/card.tsx", // [!code highlight]
      "default": "./dist/card.js" // [!code highlight]
    }
  },
  "scripts": {
    "build": "tsc" // [!code highlight]
  }
}
```

Compiling your library produces compiled JavaScript outputs into a directory (`dist`, `build`, etc.) that you will use for the entrypoints for your package. The build outputs will be cached by Turborepo once they're added to the [`outputs` key of the task](/docs/reference/configuration#outputs), allowing you to have faster build times.

#### Limitations and tradeoffs

- **Using the TypeScript compiler**: The majority of Compiled Packages should use `tsc`. Since the package is highly likely to be consumed by an application that is using a bundler, the application's bundler will prepare the library package for distribution in the application's final bundles, handling polyfilling, downleveling, and other concerns. A bundler should only be used if you have a specific use case that requires it, like bundling static assets into your package's outputs.
- **More configuration**: Compiled Packages require deeper knowledge and configuration to create build outputs. There are [many configurations for the TypeScript compiler](https://www.typescriptlang.org/docs/handbook/compiler-options.html#compiler-options) that can be difficult to manage and understand, and further configuration to optimize for bundlers, like [the `sideEffects` key in `package.json`](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free). You can find some of our recommendations in [our dedicated TypeScript guide](/docs/guides/tools/typescript).

### Publishable packages

Publishing a package to the npm registry comes with the most strict requirements of the packaging strategies on this page. Because you don't know anything about how your package will be used by consumers who download the package from the registry, you may find it difficult due to the numerous configurations required for a robust package.

Additionally, the process of publishing a package to the npm registry requires specialized knowledge and tooling. We recommend [`changesets`](https://github.com/changesets/changesets) for managing versioning, changelogs, and the publishing process.

For a detailed guide, visit [our Publishing packages guide](/docs/guides/publishing-libraries).

---

### Apps Docs Content Docs Core Concepts Package And Task Graph (`apps/docs/content/docs/core-concepts/package-and-task-graph.mdx`)

---
title: Package and Task Graphs
description: Turborepo builds a Task Graph based on your configuration and repository structure.
product: turborepo
type: conceptual
summary: Learn how Turborepo uses directed acyclic graphs to model package dependencies and task relationships.
prerequisites:
  - /docs/core-concepts/internal-packages
related:
  - /docs/crafting-your-repository/configuring-tasks
  - /docs/crafting-your-repository/running-tasks
---

## Package Graph

The Package Graph is the structure of your monorepo created by your package manager. When you install [Internal Packages](/docs/core-concepts/internal-packages) into each other, Turborepo will automatically identify those dependency relationships to build a foundational understanding of your Workspace.

For a deeper explanation of how to set up your Workspace, [visit our Structuring a repository page](/docs/crafting-your-repository/structuring-a-repository#anatomy-of-a-workspace). This sets the groundwork for the Task Graph, where you'll define how **tasks** relate to each other.

## Task Graph

In `turbo.json`, you express how tasks relate to each other. You can think of these relationships as
dependencies between tasks, but we have a more formal name for them: the Task Graph.

<Callout type="info">
  You can generate a visualization of the task graph for your tasks using [the
  `--graph` flag](/docs/reference/run#--graph-file-type).
</Callout>

Turborepo uses a data structure called a [directed acyclic graph (DAG)](https://en.wikipedia.org/wiki/Directed_acyclic_graph) to
understand your repository and its tasks. A graph is made up of "nodes" and
"edges". In the Task Graph, the nodes are tasks and the edges are the
dependencies between tasks. A _directed_ graph indicates that the edges
connecting each node have a direction, so if Task A points to Task B, we can say
that Task A depends on Task B. The direction of the edge depends on which task
depends on which.

For example, let's say you have a monorepo with an application in `./apps/web` that
depends on two packages: `@repo/ui` and `@repo/utils`:

<Files>
  <Folder name="apps" defaultOpen>
    <Folder name="web" />
  </Folder>
  <Folder name="packages" defaultOpen>
    <Folder name="ui" />
    <Folder name="utils" />
  </Folder>
</Files>

You also have a `build` task that depends on `^build`:

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"]
    }
  }
}
```

Turborepo will build a task graph like this:



### Transit Nodes

A challenge when building a Task Graph is handling nested dependencies. For
example, let's say your monorepo has a `docs` app that depends on the `ui`
package, which depends on the `core` package:

<Files>
  <Folder name="apps" defaultOpen>
    <Folder name="docs" />
  </Folder>
  <Folder name="packages" defaultOpen>
    <Folder name="ui" />
    <Folder name="core" />
  </Folder>
</Files>

Let's assume the `docs` app and the `core` package each have a `build` task, but
the `ui` package does not. You also have a `turbo.json` that configures the
`build` task the same way as above with `"dependsOn": ["^build"]`. When you run
`turbo run build`, what would you expect to happen?

Turborepo will build this Task Graph:



You can think of this graph in a series of steps:

- The `docs` app only depends on `ui`.
- The `ui` package does **not** have a build script.
- The `ui` package's _dependencies_ have a `build` script, so the task graph knows to include those.

Turborepo calls the `ui` package a Transit Node in this scenario, because it
doesn't have its own `build` script. Since it doesn't have a `build` script,
Turborepo won't execute anything for it, but it's still part of the graph for
the purpose of including its own dependencies.

#### Transit Nodes as entry points

What if the `docs/` package didn't implement the `build` task? What would
you expect to happen in this case? Should the `ui` and `core` packages still
execute their build tasks? Should _anything_ happen here?

Turborepo's mental model is that all nodes in the Task Graph are the same. In other words,
Transit Nodes are included in the graph regardless of where they appear in the graph.
This model can have unexpected consequences. For example, let's say you've configured
your `build` task to depend on `^test`:

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "dependsOn": ["^test"]
    }
  }
}
```

Let's say your monorepo has many apps and many packages. All packages have
`test` tasks, but only one app has a `build` task. Turborepo's mental model
says that when you run `turbo run build`, even if an app doesn't implement `build`
the `test` task of all packages that are dependencies will show up in the graph.

---

### Apps Docs Content Docs Core Concepts Package Types (`apps/docs/content/docs/core-concepts/package-types.mdx`)

---
title: Package types
description: Learn about the different types of packages in a workspace.
product: turborepo
type: conceptual
summary: Understand the difference between Application Packages and Library Packages in a workspace.
related:
  - /docs/core-concepts/internal-packages
  - /docs/core-concepts/package-and-task-graph
  - /docs/crafting-your-repository/structuring-a-repository
---

In Turborepo, we talk about two types of packages:

- [Application Packages](#application-packages)
- [Library Packages](#library-packages)

## Application Packages

An Application Package is a package in your workspace that will be deployed from your workspace. Examples of Application Packages are Next.js, Svelte, Vite, or CLI applications that are commonly found in the `./apps` directory.

It's best practice that your Application Packages are the "end" of your [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph), not being installed into other packages of your repository. Your CI/CD pipelines will most often finalize at these nodes of your Package and Task Graphs.

### Installing an application package into another package

In rare cases, you may need to install an Application Package into another package. This should be the exception. If you find you are doing this often, you may want to rethink your package structure.

An example of an exception for this rule is installing your Application Package into a package that handles end-to-end testing. Once installed, you can depend on the Application Package in your end-to-end testing package so it is aware of re-deploys of the application.

## Library Packages

Library Packages contain code that you intend to share around your workspace. They aren't independently deployable. Instead, they support the Application Packages to create the final deployables from your repository. You might also refer to these packages as [Internal Packages](/docs/core-concepts/internal-packages), which have their own sub-types.

---

### Apps Docs Content Docs Core Concepts Remote Caching (`apps/docs/content/docs/core-concepts/remote-caching.mdx`)

---
title: Remote Caching
description: Share cache artifacts across machines for even faster builds.
product: turborepo
type: conceptual
summary: Share a single Turborepo cache across your team and CI to avoid duplicated work.
prerequisites:
  - /docs/crafting-your-repository/caching
related:
  - /docs/crafting-your-repository/constructing-ci
  - /docs/crafting-your-repository/using-environment-variables
---

import LocalCachingDarkImage from "../../../public/images/docs/local-caching-dark.png";
import LocalCachingLightImage from "../../../public/images/docs/local-caching-light.png";
import RemoteCachingDarkImage from "../../../public/images/docs/remote-caching-dark.png";
import RemoteCachingLightImage from "../../../public/images/docs/remote-caching-light.png";

Turborepo's [task cache](/docs/crafting-your-repository/caching) saves time by never doing the same work twice.

But there's a problem: **the cache is local to your machine**. When you're working with a Continuous Integration system, this can result in a lot of duplicated work:

<ThemeAwareImage
  dark={{
    alt: "Local caching creates a cache on each system.",
    src: LocalCachingDarkImage,
    props: {
      width: 896,
      height: 345,
    },
  }}
  light={{
    alt: "Local caching creates a cache on each system.",
    src: LocalCachingLightImage,
    props: {
      width: 896,
      height: 345,
    },
  }}
/>

Since Turborepo only caches to the local filesystem by default, the same task (`turbo run build`) must be **re-executed on each machine** (by you, by your teammates, by your CI, by your PaaS, etc.) even when all of the task inputs are identical — which **wastes time and resources**.

<Callout type="info">
  You don't have to use Remote Caching to use Turborepo. While Remote Caching
  will bring the most significant speedups, you can make your existing workflows
  faster without Remote Caching, too.
</Callout>

## A single, shared cache

What if you could share a single Turborepo cache across your entire team (and even your CI)?

<ThemeAwareImage
  dark={{
    alt: "Remote caching creates a shared cache for your entire team.",
    src: RemoteCachingDarkImage,
    props: {
      width: 896,
      height: 489,
    },
  }}
  light={{
    alt: "Remote caching creates a shared cache for your entire team.",
    src: RemoteCachingLightImage,
    props: {
      width: 896,
      height: 489,
    },
  }}
/>

Turborepo can securely communicate with a remote cache - a cloud server that stores the results of your tasks. This can save enormous amounts of time by **preventing duplicated work across your entire organization**.

Remote Caching is free and can be used with both [managed providers](https://turborepo.dev/docs/core-concepts/remote-caching#managed-remote-cache-with-vercel) or as a [self-hosted cache](https://turborepo.dev/docs/core-concepts/remote-caching#self-hosting).

<Callout type="info">
  Remote Caching is a powerful feature of Turborepo, but, with great power,
  comes great responsibility. Make sure you are caching correctly first and
  double check [handling of environment
  variables](/docs/crafting-your-repository/using-environment-variables). Please
  also remember Turborepo treats logs as artifacts, so be aware of what you are
  printing to the console.
</Callout>

## Vercel

[Vercel Remote Cache](https://vercel.com/docs/monorepos/remote-caching) is free to use on all plans, even if you do not host your applications on Vercel. Follow the steps below to enable Remote Caching for your repository.

### For Local Development

To link your local Turborepo to your Remote Cache, authenticate the Turborepo CLI with your Vercel account:

```bash title="Terminal"
turbo login
```

You can also use your package manager if you do not have [global `turbo`](/docs/getting-started/installation#global-installation) installed:

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
pnpm dlx turbo login
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
yarn dlx turbo login
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
npx turbo login
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
bunx turbo login
```

</Tab>

<Tab value="nub">

```bash title="Terminal"
nubx turbo login
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
aubx turbo login
```

</Tab>

</PackageManagerTabs>

<Callout type="info">
  If your Remote Cache is configured to use single-sign-on you will need to run
  `npx turbo login --sso-team=team-name` in order to get a cache token with the
  correct privileges.
</Callout>

Now, link your Turborepo to your Remote Cache:

```bash title="Terminal"
turbo link
```

Once enabled, make some changes to a package you are currently caching and run tasks against it with `turbo run`.
Your cache artifacts will now be stored locally _and_ in your Remote Cache.

To verify, delete your local Turborepo cache with:

<PlatformTabs>
  <Tab>

    ```bash title="Terminal"
    rm -rf ./.turbo/cache
    ```

  </Tab>
  <Tab>

    ```bash title="Terminal"
    rd /s /q "./.turbo/cache"
    ```

  </Tab>
</PlatformTabs>

Then, run the same build again. If things are working properly, `turbo` should not execute tasks locally. Instead, it will download the logs and artifacts from your Remote Cache and replay them back to you.

### Remote Caching on Vercel

If you are building and hosting your apps on Vercel, Remote Caching will be automatically set up on your behalf once you use `turbo`. Refer to the [Vercel documentation](https://vercel.com/docs/monorepos/remote-caching?utm_source=turborepo.dev&utm_medium=referral&utm_campaign=docs-link) for more information.

### Artifact Integrity and Authenticity Verification

Turborepo can sign artifacts with a secret key before uploading them to the Remote Cache. Turborepo uses `HMAC-SHA256` signatures on artifacts using a secret key you provide.
Turborepo will verify the Remote Cache artifacts' integrity and authenticity when they're downloaded.
Any artifacts that fail to verify will be ignored and treated as a cache miss by Turborepo.

To enable this feature, set the `remoteCache` options on your `turbo.json` config to include `signature: true`. Then specify your secret key by declaring the `TURBO_REMOTE_CACHE_SIGNATURE_KEY` environment variable.

```jsonc title="./turbo.json"
{
  "remoteCache": {
    "signature": true, // [!code highlight]
  },
}
```

## Remote Cache API

A Remote Cache can be implemented by any HTTP server that meets Turborepo's Remote Caching API specification.

### Managed Remote Cache with Vercel

[Vercel](https://vercel.com), the creators and maintainers of Turborepo, provide a managed Remote Cache that is fully compatible with Turborepo.

Using [Vercel Remote Cache](https://vercel.com/docs/monorepos/remote-caching) is zero-configuration and automatically integrates with [Vercel deployments](https://vercel.com/docs/deployments) through the open-source [Vercel Remote Cache SDK](https://github.com/vercel/remote-cache).

Learn more about [Turborepo on Vercel](https://vercel.com/docs/monorepos/turborepo) or [deploy a template for free](https://vercel.com/templates?search=turborepo) to try it out.

### Self-hosting

You can also self-host your own Remote Cache and log into it using the `--manual` flag to provide API URL, team, and token information.

```bash title="Terminal"
turbo login --manual
```

#### OpenAPI specification

- [Human-readable viewer](/docs/openapi)
- [JSON](/api/remote-cache-spec)

At this time, all versions of `turbo` are compatible with the `v8` endpoints.

#### Community implementations

The Turborepo community has created open-source implementations of the Remote Cache.

- [`brunojppb/turbo-cache-server`](https://github.com/brunojppb/turbo-cache-server)
- [`ducktors/turborepo-remote-cache`](https://github.com/ducktors/turborepo-remote-cache)
- [`Tapico/tapico-turborepo-remote-cache`](https://github.com/Tapico/tapico-turborepo-remote-cache)

---

### Apps Docs Content Docs Crafting Your Repository Caching (`apps/docs/content/docs/crafting-your-repository/caching.mdx`)

---
title: Caching
description: Learn about caching in Turborepo.
product: turborepo
type: guide
summary: Configure task caching to avoid repeating work, using fingerprinting for inputs and restoring outputs from cache.
prerequisites:
  - /docs/crafting-your-repository/running-tasks
related:
  - /docs/core-concepts/remote-caching
  - /docs/crafting-your-repository/using-environment-variables
  - /docs/reference/configuration
---

import { ExperimentalBadge } from "@/components/geistdocs/experimental-badge";

Turborepo uses caching to speed up builds, ensuring you **never do the same work twice**. When your task is cacheable, Turborepo will restore the results of your task from cache using a fingerprint from the first time the task ran.



Turborepo's caching results in significant time savings when working locally - and is even more powerful when [Remote Caching](/docs/core-concepts/remote-caching) is enabled, sharing a cache among your entire team and CI.

On this page, you'll learn:

- [How to hit your first Turborepo cache](#hit-your-first-turborepo-cache)
- [How to enable Remote Caching](/docs/core-concepts/remote-caching)
- [What Turborepo uses for the inputs and outputs to a hash](#task-inputs)
- [How to troubleshoot caching issues](#troubleshooting)

<Callout type="info">
  Turborepo assumes that your tasks are **deterministic**. If a task is able to
  produce different outputs given the set of inputs that Turborepo is aware of,
  caching may not work as expected.
</Callout>

## Hit your first Turborepo cache

You can try out Turborepo's caching behavior in three steps:

<Steps>
<Step>
### Create a new Turborepo project

Use `npx create-turbo@latest` and follow the prompts to create a new Turborepo.

```bash title="Terminal"
npx create-turbo@latest
```

</Step>
<Step>
### Run a build for the first time

If you have [`turbo` installed globally](/docs/getting-started/installation#global-installation), run `turbo build` in your repository.

Alternatively, you can run the `build` script in `package.json` using your package manager.

<PackageManagerTabs>

<Tab value="pnpm">
```bash title="Terminal"
pnpm run build
```

</Tab>

<Tab value="yarn">
```bash title="Terminal"
yarn build
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
npm run build
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
bun run build
```

</Tab>

<Tab value="nub">

```bash title="Terminal"
nub run build
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
aube run build
```

</Tab>

</PackageManagerTabs>

This will result in a cache miss, since you've never ran `turbo` before with this [set of inputs](#task-inputs) in this repository. The inputs are turned into a hash to check for in your local filesystem cache or in [the Remote Cache](/docs/core-concepts/remote-caching).

</Step>

<Step>

### Hit the cache

Run `turbo build` again. You will see a message like this:



</Step>

</Steps>

Because the inputs' fingerprint is already in the cache, there's no reason to rebuild your applications from zero again. You can restore the results of the previous build from cache, saving resources and time.

## Remote Caching

Turborepo stores the results of tasks in the `.turbo/cache` directory on your machine. However, you can make your entire organization even faster by sharing this cache with your teammates and CI.

To learn more about Remote Caching and its benefits, visit the [Remote Caching page](/docs/core-concepts/remote-caching).

### Enabling Remote Cache

First, authenticate with your Remote Cache provider:

```bash title="Terminal"
npx turbo login
```

Then, link the repository on your machine to Remote Cache:

```bash title="Terminal"
npx turbo link
```

Now, when you run a task, Turborepo will automatically send the outputs of the task to Remote Cache. If you run the same task on a different machine that is also authenticated to your Remote Cache, it will hit cache the first time it runs the task.

For information on how to connect your CI machines to Remote Cache, visit [the Constructing CI guide](/docs/crafting-your-repository/constructing-ci#enabling-remote-caching).

<Callout type="info">
  By default, Turborepo uses [Vercel Remote
  Cache](https://vercel.com/docs/monorepos/remote-caching) with zero
  configuration. If you'd like to use a different Remote Cache, visit the
  [Remote Caching API
  documentation](/docs/core-concepts/remote-caching#self-hosting)
</Callout>

## Git Worktree Cache Sharing

When working with [Git worktrees](https://git-scm.com/docs/git-worktree), Turborepo automatically shares the local filesystem cache between the main worktree and any linked worktrees. This enables:

- **Cache hits across branches**: Work done on one branch is available when you switch to another branch in a different worktree
- **Reduced disk usage**: Avoids duplicate cache entries across worktrees
- **Faster iteration**: Switching between feature branches benefits from existing cache

### How it works

Git worktrees allow you to have multiple working directories attached to the same repository, each checked out to a different branch. When you create a linked worktree with `git worktree add`, Turborepo detects this configuration and automatically redirects the cache to the main worktree's `.turbo/cache` directory.

```bash title="Terminal"
# Create a linked worktree for a feature branch
git worktree add ../my-feature feature-branch

# Run turbo in the linked worktree - cache is shared with main worktree
cd ../my-feature
turbo build
```

When worktree cache sharing is active, you'll see a message in the output:

```
• Remote caching enabled, using shared worktree cache
```

<Callout type="info">
  If you set an explicit [`cacheDir`](/docs/reference/configuration#cachedir) in
  your `turbo.json`, worktree cache sharing is disabled and each worktree will
  use its own cache directory as specified.
</Callout>

<Callout type="warn" title="Outputs containing absolute paths">
  Cache artifacts are restored without rewriting their contents. If a task
  output contains the absolute path to its worktree, sharing that artifact can
  restore an output that points to another checkout. Set an explicit
  [`cacheDir`](/docs/reference/configuration#cachedir), such as `.turbo/cache`,
  to keep the local cache isolated to each worktree.
</Callout>

### With Remote Caching

Git worktree cache sharing works alongside [Remote Caching](/docs/core-concepts/remote-caching). When both are enabled:

- **Local cache** is shared between worktrees on the same machine
- **Remote cache** is shared across all machines and CI

This means a task built in one worktree can be restored from the shared local cache in another worktree instantly, without a network request. If the local cache doesn't have the artifact, Turborepo will fall back to the Remote Cache as usual.

## What gets cached?

Turborepo caches two types of outputs: Task outputs and Logs.

### Task outputs

Turborepo caches the file outputs of a task that are defined in [the `outputs` key](/docs/reference/configuration#outputs) of `turbo.json`. When there's a cache hit, Turborepo will restore the files from the cache.

The `outputs` key is optional, see [the API reference](/docs/reference/configuration#outputs) for how Turborepo behaves in this case.

<Callout type="warn" title="Providing file outputs">
If you do not declare file outputs for a task, Turborepo will not cache them. This might be okay for some tasks (like linters) - but many tasks produce files that you will want to be cached.

If you're running into errors with files not being available when you hit cache, make sure that you have defined the outputs for your task.

</Callout>

### Logs

Turborepo always captures the terminal outputs of your tasks, restoring those logs to your terminal from the first time that the task ran.

You can configure the verbosity of the replayed logs using [the `--output-logs` flag](/docs/reference/run#--output-logs-option) or [`outputLogs` configuration option](/docs/reference/configuration#outputlogs).

## Task inputs

Inputs are hashed by Turborepo, creating a "fingerprint" for the task run. When "fingerprints" match, running the task will hit the cache.

Under the hood, Turborepo creates two hashes: a global hash and a task hash. If either of the hashes change, the task will miss cache.

### Global hash inputs

| Input                                                                                  | Example                                                                                                                                                                                                         |
| -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Resolved task definition from root `turbo.json` and package `turbo.json`               | Changing [`outputs`](/docs/reference/configuration#outputs) in either root `turbo.json` or [Package Configuration](/docs/reference/package-configurations)                                                      |
| Lockfile changes that affect the Workspace root                                        | Updating dependencies in root `package.json` will cause **all** tasks to miss cache                                                                                                                             |
| Source files in internal packages used by the Workspace root                           | If the root `package.json` depends on `@repo/tooling`, changing `packages/tooling/src/index.ts` will cause **all** tasks to miss cache                                                                           |
| [`globalDependencies`](/docs/reference/configuration#globaldependencies) file contents | Changing `./.env` when it is listed in `globalDependencies` will cause **all** tasks to miss cache                                                                                                              |
| Values of variables listed in [`globalEnv`](/docs/reference/configuration#globalenv)   | Changing the value of `GITHUB_TOKEN` when it is listed in `globalEnv`                                                                                                                                           |
| Flag values that affect task runtime                                                   | Using behavior-changing flags like `--cache-dir`, `--framework-inference`, or `--env-mode`                                                                                                                      |
| Arbitrary passthrough arguments                                                        | `turbo build -- --arg=value` will cause **all** tasks to miss cache when compared to either `turbo build` or `turbo build -- --arg=diff` (including dependencies of `build` that did not receive `--arg=value`) |

#### Root workspace dependencies

Turborepo includes the source files of every internal workspace package that the
root `package.json` depends on, directly or transitively, in the global hash.
This keeps cache entries correct when root-level scripts or tooling use those
packages.

For example, if the root package depends on `@repo/tooling`, changing a source
file in `@repo/tooling` causes every cacheable task to miss cache. A change to
an internal package outside this root dependency closure only changes the
relevant package and task hashes.

When comparing Git revisions, `turbo query affected --packages` reports this
repository-wide result with the `RootInternalDepChanged` reason. See
[Understanding affected-package reasons](/docs/reference/query#understanding-affected-package-reasons)
for the diagnostic reason types.

### Package hash inputs

| Input                                                                   | Example                                                 |
| ----------------------------------------------------------------------- | ------------------------------------------------------- |
| [Package Configuration](/docs/reference/package-configurations) changes | Changing a package's `turbo.json`                       |
| Lockfile changes that affect the package                                | Updating dependencies in a package's `package.json`     |
| Package's `package.json` changes                                        | Updating the `name` field in a package's `package.json` |
| File changes | Defaults to all source-controlled files in the package directory. Configurable with [`inputs`](/docs/reference/configuration#inputs) |

## Troubleshooting

### Using dry runs

Turborepo has a [`--dry` flag](/docs/reference/run#--dry----dry-run) that can be used to see what would happen if you ran a task without actually running it. This can be useful for debugging caching issues when you're not sure which tasks you're running.

For more details, visit the [`--dry` API reference](/docs/reference/run#--dry----dry-run).

### Using Run Summaries

Turborepo has a [`--summarize` flag](/docs/reference/run#--summarize) that can be used to get an overview of all of a task's inputs, outputs, and more. Comparing two summaries will show why two task's hashes are different. This can be useful for:

- Debugging inputs: There are many inputs to a task in Turborepo. If a task is missing cache when you expect it to hit, you can use a Run Summary to check which inputs are different that you weren't expecting.
- Debugging outputs: If cache hits aren't restoring the files you're expecting, a Run Summary can help you understand what outputs are being restored from cache.

<Callout type="info" title="Summaries viewer">
  While there is not a Turborepo-native Run Summaries UI viewer, there are
  several community-built tools available:

- [https://turbo.nullvoxpopuli.com](https://turbo.nullvoxpopuli.com) - Web-based UI viewer for Run Summaries
- [`turborepo-summary`](https://github.com/charpeni/turborepo-summary) - Generate human-readable reports from Turborepo run summary JSON output
- [`turborepo-summary-action`](https://github.com/charpeni/turborepo-summary-action) - GitHub Action wrapping `turborepo-summary` to append them to GitHub Actions Job Summary

</Callout>

### Turning off caching

Sometimes, you may not want to write the output of tasks to the cache. This can be set permanently for a task using [`"cache": false`](/docs/reference/configuration#cache) or for a whole run using [ the `--cache <options>` flag](/docs/reference/run#--no-cache).

### Overwriting a cache

If you want to force `turbo` to re-execute a task that has been cached, use [the `--force` flag](/docs/reference/run#--force). Note that this disables **reading** the cache, **not writing**.

### Caching a task is slower than executing the task

It's possible to create scenarios where caching ends up being slower than not caching. These cases are rare, but a few examples include:

- **Tasks that execute extremely fast**: If a task executes faster than a network round-trip to the [Remote Cache](/docs/core-concepts/remote-caching), you should consider not caching the task.
- **Tasks whose output assets are enormous**: It's possible to create an artifact that is so big that the time to upload or download it exceeds the time to regenerate it, like a complete Docker Container. In these cases, you should consider not caching the task.
- **Scripts that have their own caching**: Some tasks have their own internal caching behavior. In these cases, configuration can quickly become complicated to make Turborepo's cache and the application cache work together.

While these situations are rare, be sure to test the behavior of your projects to determine if disabling caching in specific places provides a performance benefit.

## Next steps

Now that you've seen how Turborepo's caching makes your repository faster, let's take a look at how to develop applications and libraries in your Turborepo.

---

### Apps Docs Content Docs Crafting Your Repository Configuring Tasks (`apps/docs/content/docs/crafting-your-repository/configuring-tasks.mdx`)

---
title: Configuring tasks
description: Learn how to describe the workflows in your repository to get them done as fast as possible.
product: turborepo
type: guide
summary: Define task dependencies, outputs, and inputs in turbo.json to orchestrate your repository's workflows.
prerequisites:
  - /docs/crafting-your-repository/creating-an-internal-package
related:
  - /docs/crafting-your-repository/running-tasks
  - /docs/crafting-your-repository/caching
  - /docs/core-concepts/package-and-task-graph
  - /docs/reference/configuration
---

A task is a script that Turborepo runs. You can express relationships between tasks in your [`turbo.json` configuration](/docs/reference/configuration) and [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph).

Turborepo will always parallelize any work that it can to ensure everything runs as fast as possible. This is faster than running tasks one at a time, and it's a part of what makes Turborepo so fast.

For example, `yarn workspaces run lint && yarn workspaces run build && yarn workspaces run test` would look like this:



But, to get the same work done **faster** with Turborepo, you can use `turbo run lint build test`:



## Getting started

The root `turbo.json` file is where you'll register the tasks that Turborepo will run. Once you have your tasks defined, you'll be able to run one or more tasks using [`turbo run`](/docs/reference/run).

- If you're starting fresh, we recommend [creating a new repository using `create-turbo`](/docs/getting-started/installation) and editing the `turbo.json` file to try out the snippets in this guide.
- If you're adopting Turborepo in an existing repository, create a `turbo.json` file in the root of your repository. You'll be using it to learn about the rest of the configuration options in this guide.

<Files>
  <File name="turbo.json" green />
  <File name="package.json" />
  <Folder name="apps" />
  <Folder name="packages" />
</Files>

## Defining tasks

Each key in the `tasks` object is a task that can be executed by `turbo run`. Turborepo will search your packages for **scripts in their `package.json` that have the same name as the task**.

To define a task, use [the `tasks` object](/docs/reference/configuration#tasks) in `turbo.json`. For example, a basic task with no dependencies and no outputs named `build` might look like this:

```json title="./turbo.json"
{
  "tasks": {
    "build": {} // Incorrect! // [!code highlight]
  }
}
```

If you run `turbo run build` at this point, Turborepo will run all `build` scripts in your packages in parallel and won't cache any file outputs. **This will quickly lead to errors.** You're missing a few important pieces to make this work how you'd expect.

### Running tasks in the right order

[The `dependsOn` key](/docs/reference/configuration#dependson) is used to specify the tasks that must complete before a different task begins running. For example, in most cases, you want the `build` script for your libraries to complete before your application's `build` script runs. To do this, you'd use the following `turbo.json`:

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"] // [!code highlight]
    }
  }
}
```

You now have the build order you would expect, building _dependencies_ before _dependents_.

**But be careful.** At this point, you haven't marked the build outputs for caching. To do so, jump to the [Specifying outputs](#specifying-outputs) section.

#### Depending on tasks in dependencies with `^`

The `^` microsyntax tells Turborepo to run the task in direct dependencies before the target package. If your application depends on a library named `ui` and the library has a `build` task, the `build` script in `ui` will run **first**. Once it has successfully completed, the `build` task in your application will run.

This is an important pattern as it ensures that your application's `build` task will have all of the necessary dependencies that it needs to compile. This concept also applies as your dependency graph grows to a more complex structure with many levels of task dependencies.

#### Depending on tasks in the same package

Sometimes, you may need to ensure that two tasks in the same package run in a specific order. For example, you may need to run a `build` task in your library before running a `test` task in the same library. To do this, specify the script in the `dependsOn` key as a plain string (without the `^`).

```json title="./turbo.json"
{
  "tasks": {
    "test": {
      "dependsOn": ["build"] // [!code highlight]
    }
  }
}
```

#### Depending on a specific task in a specific package

You can also specify an individual task in a specific package to depend on. In the example below, the `build` task in `utils` must be run before any `lint` tasks.

```json title="./turbo.json"
{
  "tasks": {
    "lint": {
      "dependsOn": ["utils#build"] // [!code highlight]
    }
  }
}
```

You can also be more specific about the dependent task, limiting it to a certain package:

```json title="./turbo.json"
{
  "tasks": {
    "web#lint": {
      "dependsOn": ["utils#build"] // [!code highlight]
    }
  }
}
```

With this configuration, the `lint` task in your `web` package can only be run after the `build` task in the `utils` package is complete.

#### No dependencies

Some tasks may not have any dependencies. For example, a task for finding typos in Markdown files likely doesn't need to care about the status of your other tasks. In this case, you can omit the `dependsOn` key or provide an empty array.

```json title="./turbo.json"
{
  "tasks": {
    "spell-check": {
      "dependsOn": [] // [!code highlight]
    }
  }
}
```

### Specifying `outputs`

<Callout type="info">
  Turborepo caches the outputs of your tasks so that you never do the same work
  twice. We'll discuss this in depth in [the Caching
  guide](/docs/crafting-your-repository/caching), but let's make sure your tasks
  are properly configured first.
</Callout>

The `outputs` key tells Turborepo **files and directories** it should cache when the task has successfully completed. **Without this key defined, Turborepo will not cache any files. Hitting cache on subsequent runs will not restore any file outputs.**

Below are a few examples of outputs for common tools:

<Tabs items={["Next.js", "Vite", "tsc"]} storageKey="outputs-tools">
<Tab value="Next.js">
```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "outputs": [".next/**", "!.next/cache/**", "!.next/dev/**"] // [!code highlight]
    }
  }
}
```
</Tab>

<Tab value="Vite">
```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "outputs": ["dist/**"] // [!code highlight]
    }
  }
}
```
</Tab>
<Tab value="tsc">
```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "outputs": ["dist/**"] // [!code highlight]
    }
  }
}
```
</Tab>
</Tabs>

Globs are relative to the package, so `dist/**` will handle the `dist` that is outputted for each package, respectively. For more on building globbing patterns for the `outputs` key, see [the globbing specification](/docs/reference/globs).

### Specifying `inputs`

The `inputs` key is used to specify the files that you want to include in the task's hash for [caching](/docs/crafting-your-repository/caching). By default, Turborepo will include all files in the package that are tracked by Git. However, you can be more specific about which files are included in the hash using the `inputs` key.

As an example, a task for finding typos in Markdown files could be defined like this:

```json title="./turbo.json"
{
  "tasks": {
    "spell-check": {
      "inputs": ["**/*.md", "**/*.mdx"] // [!code highlight]
    }
  }
}
```

Now, **only** changes in Markdown files will cause the `spell-check` task to miss cache.

<Callout type="error">
This feature opts out of all of Turborepo's default `inputs` behavior, including following along with changes tracked by source control. This means that your `.gitignore` file will no longer be respected, and you will need to ensure that you do not capture those files with your globs.

To restore the default behavior, use [the `$TURBO_DEFAULT$` microsyntax](#restoring-defaults-with-turbo_default).

</Callout>

#### Restoring defaults with `$TURBO_DEFAULT$`

[The default `inputs` behavior](/docs/reference/configuration#inputs) is often what you will want for your tasks. However, you can increase your cache hit ratios for certain tasks by fine-tuning your `inputs` to ignore changes to files that are known to not affect the task's output.

For this reason, you can use the `$TURBO_DEFAULT$` microsyntax to fine-tune the default `inputs` behavior:

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", "!README.md"] // [!code highlight]
    }
  }
}
```

In this task definition, Turborepo will use the default `inputs` behavior for the `build` task, but will ignore changes to the `README.md` file. If the `README.md` file is changed, the task will still hit cache.

#### Deferred hashing

Some tasks need to hash files that are created by another task in the same run.
Use structured [`inputs`](/docs/reference/configuration#deferred-hashing) with
`mode: "jit"` or `mode: "dependencyOutputs"` to defer hashing until the task's
dependencies have completed.

### Registering Root Tasks

You can also run scripts in the `package.json` in the Workspace root using `turbo`. For example, you may want to run a `lint:root` task for the files in your Workspace's root directory in addition to the `lint` task in each package:

<Tabs items={["turbo.json", "package.json"]}>
<Tab value="turbo.json">
```json title="./turbo.json"
{
  "tasks": {
    "lint": {
      "dependsOn": ["^lint"]
    },
    "//#lint:root": {} // [!code highlight]
  }
}
```

</Tab>
<Tab value="package.json">
```json title="./package.json"
{
  "scripts": {
    "lint": "turbo run lint lint:root",
    "lint:root": "eslint ." // [!code highlight]
  }
}
```
</Tab>
</Tabs>

With the Root Task now registered, you can use `turbo run lint:root` from the root or `turbo run //#lint:root` in any of the workspaces to run the task. You can also run `turbo run lint lint:root` to run all your linting tasks.

#### When to use Root Tasks

- **Linting and formatting of the Workspace root**: You might have code in your Workspace root that you want to lint and format. For example, you might want to run ESLint or Prettier in your root directory.
- **Incremental migration**: While you're migrating to Turborepo, you might have an in-between step where you have some scripts that you haven't moved to packages yet. In this case, you can create a Root Task to start migrating and fan the tasks out to packages later.
- **Scripts without a package scope**: You may have some scripts that don't make sense in the context of specific packages. Those scripts can be registered as Root Tasks so you can still run them with `turbo` for caching, parallelization, and workflow purposes.

## Advanced use cases

### Using Package Configurations

[Package Configurations](/docs/reference/package-configurations) are `turbo.json` files that are placed directly into a package. This allows a package to define specific behavior for its own tasks without affecting the rest of the repository.

In large monorepos with many teams, this allows teams greater control over their own tasks. To learn more, visit [the Package Configurations documentation](/docs/reference/package-configurations)

### Composing configurations

[Package Configurations](/docs/reference/package-configurations) can be composed for greater control with less configuration:

- [**Extending from other packages**](/docs/reference/package-configurations#extending-from-other-packages): Create shared configuration packages that multiple packages can extend from, enabling shared `turbo.json` configurations.
- [**Adding to extended configurations**](/docs/reference/package-configurations#extending-arrays-with-turbo_extends): Use the `$TURBO_EXTENDS$` microsyntax to add to inherited array values like `outputs` and `env` instead of replacing them.

### Long-running tasks with runtime dependencies

You might have a long-running task that requires another task to always be running at the same time. For this, use [the `with` key](/docs/reference/configuration#with).

```json title="./apps/web/turbo.json"
{
  "tasks": {
    "dev": {
      "with": ["api#dev"],
      "persistent": true,
      "cache": false
    }
  }
}
```

A long-running task never exits, meaning you can't depend on it. Instead, the `with` keyword will run the `api#dev` task whenever the `web#dev` task runs.

### Performing side-effects

Some tasks should always be run no matter what, like a deployment script after a cached build. For these tasks, add `"cache": false` to your task definition.

```json title="./turbo.json"
{
  "tasks": {
    "deploy": {
      "dependsOn": ["^build"],
      "cache": false // [!code highlight]
    },
    "build": {
      "outputs": ["dist/**"]
    }
  }
}
```

### Dependent tasks that can be run in parallel

Some tasks can be run in parallel despite being dependent on other packages. An example of tasks that fit this description are type checkers, since a type checker doesn't need to wait for outputs in dependencies to run successfully.

Because of this, you may be tempted to define your `check-types` task like this:

```json title="./turbo.json"
{
  "tasks": {
    "check-types": {} // Incorrect! // [!code highlight]
  }
}
```

This runs your tasks in parallel - but doesn't account for source code changes in dependencies. This means you can:

1. Make a breaking change to the interface of your `ui` package.
2. Run `turbo check-types`, hitting cache in an application package that depends on `ui`.

This is incorrect, since the application package will show a successful cache hit, despite not being updated to use the new interface. Checking for TypeScript errors in your application package manually in your editor is likely to reveal errors.

Because of this, you make a small change to your `check-types` task definition:

```json title="./turbo.json"
{
  "tasks": {
    "check-types": {
      "dependsOn": ["^check-types"] // This works...but could be faster! // [!code highlight]
    }
  }
}
```

If you test out making breaking changes in your `ui` package again, you'll notice that the caching behavior is now correct. However, tasks are no longer running in parallel.

To meet both requirements (correctness and parallelism), you can introduce [Transit Nodes](/docs/core-concepts/package-and-task-graph#transit-nodes) to your Task Graph:

```json title="./turbo.json"
{
  "tasks": {
    "transit": {
      "dependsOn": ["^transit"]
    },
    "check-types": {
      "dependsOn": ["transit"]
    }
  }
}
```

These Transit Nodes create a relationship between your package dependencies using a task that doesn't do anything because it doesn't match a script in any `package.json`s. Because of this, your tasks can run in parallel **and** be aware of changes to their internal dependencies.

<Callout type="info">
  In this example, we used the name `transit` - but you can name the task
  anything that isn't already a script in your Workspace.
</Callout>

## Next steps

There are more options available in [the Configuring `turbo.json` documentation](/docs/reference/configuration) that you will explore in the coming guides. For now, you can start running a few tasks to see how the basics work.

---

### Apps Docs Content Docs Crafting Your Repository Constructing Ci (`apps/docs/content/docs/crafting-your-repository/constructing-ci.mdx`)

---
title: Constructing CI
description: Learn how Turborepo can help you efficiently complete all the necessary tasks and accelerate your development workflow.
product: turborepo
type: guide
summary: Set up CI pipelines with Remote Caching, task filtering, Docker support, and affected package detection for maximum speed.
prerequisites:
  - /docs/crafting-your-repository/using-environment-variables
related:
  - /docs/core-concepts/remote-caching
  - /docs/guides/ci-vendors
  - /docs/reference/query
---

Turborepo speeds up builds, lints, tests, and any other tasks that you need to do in your Continuous Integration pipelines. Through parallelization and [Remote Caching](/docs/core-concepts/remote-caching), Turborepo makes your CI dramatically faster.

For examples of how to connect your CI vendor to Remote Cache and run tasks, visit our [CI guides](/docs/guides/ci-vendors).

## Enabling Remote Caching

To enable Remote Caching for your CI, setup the environment variables for Turborepo to access your Remote Cache.

| Environment Variable | Description                                                                                                                                                                                                                         |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TURBO_TOKEN`        | The Bearer token to access the Remote Cache                                                                                                                                                                                         |
| `TURBO_TEAM`         | The account name associated with your repository. When using [Vercel Remote Cache](https://vercel.com/docs/monorepos/remote-caching), this is [your team's slug](https://vercel.com/docs/accounts#creating-a-team). |

When you run tasks through `turbo`, your CI will be able to hit cache, speeding up your pipelines.

<Callout type="info" title="Remote Cache hosting">
Vercel's built-in CI/CD is automatically connected to your managed Vercel Remote Cache with zero configuration. To retrieve a token for connecting your other CI vendors to Vercel Remote Cache, visit the [Vercel Remote Cache documentation](https://vercel.com/docs/monorepos/remote-caching#use-remote-caching-from-external-ci/cd).

For self-hosted Remote Cache options, visit [Turborepo's Remote Cache documentation](/docs/core-concepts/remote-caching#remote-cache-api).

</Callout>

## Running tasks in CI

By [installing `turbo` globally](/docs/getting-started/installation#global-installation) onto your development and CI machines, you can use one mental model to run your entire repository, from development to ship. The tasks that you've registered in your `turbo.json` will work exactly the same in CI.

- For more information on how to set up tasks, visit the [Configuring Tasks](/docs/crafting-your-repository/configuring-tasks) page.
- For examples of running tasks in CI, visit our [CI guides](/docs/guides/ci-vendors).

### Filtering for entry points

You can filter your tasks using [the `--filter` flag](/docs/reference/run#--filter-string) exactly the same as when you're working with `turbo` locally. Filtering by packages, directories, and Git history are all supported in CI.

<Callout type="info" title="Using Git history in CI">
  Filtering using source control changes is only possible when history is
  available on the machine. If you are using shallow clones, history will not be
  available.
</Callout>

You can also use [the `--affected` flag](#running-only-affected-tasks) to only run tasks in packages that have changes.

## Docker

Docker is an important part of many deployment pipelines. [Turborepo's `prune` subcommand](/docs/reference/prune) helps you ship lightweight images by removing unnecessary dependencies and code from your images.

For more on how to deploy from a Turborepo with Docker, visit [the dedicated Docker guide](/docs/guides/tools/docker).

## Skipping tasks and other unnecessary work

### Running only affected tasks

You can use the `--affected` flag to only run tasks that have changes.

```bash title="Terminal"
turbo run build --affected
```

You'll want to use this flag in situations like:

- You're running many tasks across packages in your monorepo, and only want to run those tasks in packages with code changes.
- You're _not_ using a Remote Cache, but still want to do as little work as possible in CI.
- You _are_ using a Remote Cache, and you're in a large repository. By minimizing the amount of tasks that will be restored from cache, there will be less data to send across the network, resulting in faster cache restoration.
- You're already using [advanced filtering techniques](/docs/reference/run#advanced-filtering-examples) to create similar behavior. You likely have the opportunity to simplify your scripting using this new flag.
  - `--affected` will can handle shallow clones more gracefully than bespoke filtering because it falls back to running all tasks.

#### Using `--affected` in GitHub Actions

CI/CD pipelines are a perfect place to use `--affected`. With `--affected`, Turborepo can automatically detect that you're running in GitHub Actions by inspecting environment variables set by GitHub, like `GITHUB_BASE_REF`.

In the context of a PR, this means that Turborepo can determine which packages have changed between the PR's base branch and the PR's head branch. This allows you to run tasks only for the packages that are affected by the changes in the PR.

While `GITHUB_BASE_REF` works well in `pull_request` and `pull_request_target` events, it is not available during regular push events. In those cases, we use `GITHUB_EVENT_PATH` to determine the base branch to compare your commit to. In force pushes and pushing branch with no additional commits, we compare to the parent of the first commit on the branch.

### Skipping packages with `turbo query affected`

As your codebase and CI grow, you may start to look for more ways to get even faster. While hitting cache is useful, you also may be able to skip work entirely. Using `turbo query affected`, you can skip lengthy container preparation steps like dependency installation that will end up resulting in a cache hit, anyway.

<Steps>
<Step>
### Checkout the repository

Start by cloning your repository. A clone with sufficient history is necessary for comparisons — if the checkout is too shallow, all packages will be considered changed. For example, cloning with `--filter=blob:none --depth=0` will ensure the right history is available.

By default, `turbo query affected` compares against the merge-base with your default branch.

</Step>
<Step>
### Check if the package is affected

Use `turbo query affected` to check if a package has changes. The command outputs JSON that you can parse with a tool like `jq`:

<Tabs items={["Check a package", "Check a specific task", "Quick check with --exit-code"]}>
<Tab value="Check a package">

```bash title="Terminal"
affected=$(turbo query affected --packages web)
count=$(echo "$affected" | jq '.data.affectedPackages.length')

if [ "$count" -gt 0 ]; then
  echo "web is affected, proceeding with build"
  # Run your build steps
else
  echo "web is not affected, skipping"
  exit 0
fi
```

</Tab>

<Tab value="Check a specific task">

Check if the `test` task for the `docs` package is affected. This respects [`inputs`](/docs/reference/configuration#inputs) configuration, so only relevant file changes are considered:

```bash title="Terminal"
affected=$(turbo query affected --tasks test --packages docs)
count=$(echo "$affected" | jq '.data.affectedTasks.length')

if [ "$count" -gt 0 ]; then
  echo "docs#test is affected, proceeding"
else
  echo "docs#test is not affected, skipping"
  exit 0
fi
```

</Tab>

<Tab value="Quick check with --exit-code">

If you only need a binary "affected or not" signal, use `--exit-code` as a shorthand. It exits with code `1` when results are found, `0` when nothing is affected, or `2` on errors:

```bash title="Terminal"
turbo query affected --packages web --exit-code
```

</Tab>
</Tabs>
</Step>

<Step>
### Handle the result

The JSON output includes a `length` field that tells you how many packages or tasks are affected. When `length` is `0`, you can safely skip the rest of your CI pipeline.

The output also includes the reason each package is affected (e.g., `FileChanged`, `DependencyChanged`), which is useful for debugging unexpected builds.

</Step>
</Steps>
For more details, see the [`turbo query affected` reference](/docs/reference/query#affected) and the [skipping tasks guide](/docs/guides/skipping-tasks).

## Best practices

### Rely on caching

Turborepo's caching abilities allow you to create fast CI pipelines with minimal complexity. Through [Remote Caching](/docs/core-concepts/remote-caching) and using the `--filter` flag to target packages for builds, Turborepo will handle change detection for large monorepos with little overhead.

For example, your CI could run these two commands to quickly handle quality checks and build your target application:

- `turbo run lint check-types test`: Run quality checks for your entire repository. Any packages that haven't changed will hit cache.
- `turbo build --filter=web`: Build the `web` package using the `build` task you've registered in `turbo.json`. If the `web` package or its dependencies haven't changed, the build will also hit cache.

As your codebase scales, you may find more specific opportunities to optimize your CI - but relying on caching is a great place to start.

### Global `turbo` in CI

Using global `turbo` is convenient in CI workflows, allowing you to easily run commands specific to your CI and take advantage of [Automatic Workspace Scoping](/docs/crafting-your-repository/running-tasks#automatic-package-scoping).

However, in some cases, you may be running `turbo` commands or scripts that use `turbo` **before installing packages with your package manager**. One example of this is [using `turbo prune` to create a Docker image](/docs/guides/tools/docker#example). In this situation, global `turbo` will not be able to use the version from `package.json` because the binary for that version hasn't been installed yet.

For CI steps before dependencies are installed, pin the standalone binary to an exact version compatible with your repository's `turbo` dependency. Set `TURBO_VERSION` when running the [installer](/docs/getting-started/installation#global-installation):

<Tabs items={["macOS and Linux", "Windows x64"]}>
  <Tab value="macOS and Linux">

```sh title="Terminal"
curl -fsSL https://turborepo.dev/install | TURBO_VERSION=2.11.5 sh
```

  </Tab>
  <Tab value="Windows x64">

```powershell title="PowerShell"
$env:TURBO_VERSION = '2.11.5'
irm https://turborepo.dev/install.ps1 | iex
```

  </Tab>
</Tabs>

<Callout type="info">
  Standalone releases start at 2.11.5. To use an older version, install it with your package manager instead.
</Callout>

### Use `turbo run` in CI

`turbo run` is the most common command you will use when working in your Turborepo so it is aliased to `turbo` for convenience. While this is great for working locally, there are other subcommands for `turbo` like [`turbo prune`](/docs/reference/prune) and [`turbo generate`](/docs/reference/generate).

We're always working to make `turbo` better so we may add more subcommands in the future. For this reason, you can prevent naming collisions by using `turbo run` in your CI.

As an example, if you have a `turbo deploy` command in your CI pipelines, it may conflict with a potential `deploy` subcommand built directly into the `turbo` CLI. To avoid this, use `turbo run deploy` in your CI pipeline instead.

## Troubleshooting

### Hitting cache results in broken builds

If your task is **passing when you miss cache but failing when you hit cache**, you likely haven't configured [the `outputs` key](/docs/reference/configuration#outputs) for your task correctly.

### Deployment using the wrong environment variables

If you haven't defined the `env` or `globalEnv` keys for your task, Turborepo will not be able to use them when creating hashes. This means your task can hit cache despite being in a different environment.

Check your configuration for the `env` and `globalEnv` keys.

## Next steps

You now have everything you need to ship applications with Turborepo. To learn more about specific use cases, [check the Guides](/docs/guides) or [dive deeper into core concepts](/docs/core-concepts).

---

### Apps Docs Content Docs Crafting Your Repository Creating An Internal Package (`apps/docs/content/docs/crafting-your-repository/creating-an-internal-package.mdx`)

---
title: Creating an Internal Package
description: Learn how to create an Internal Package for your monorepo.
product: turborepo
type: guide
summary: Build a new internal package from scratch to share code across your monorepo.
prerequisites:
  - /docs/crafting-your-repository/structuring-a-repository
  - /docs/crafting-your-repository/managing-dependencies
related:
  - /docs/core-concepts/internal-packages
  - /docs/core-concepts/package-types
  - /docs/crafting-your-repository/configuring-tasks
---

[Internal Packages](/docs/core-concepts/internal-packages) are the building blocks of your workspace, giving you a powerful way to share code and functionality across your repo. Turborepo automatically understands the relationships between Internal Packages using the dependencies in `package.json`, creating a [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph) under the hood to optimize your repository's workflows.



Let's create your first Internal Package to share math utilities in your repo using the guidance in the [Anatomy of a package](/docs/crafting-your-repository/structuring-a-repository#anatomy-of-a-package) section and the [Compiled Packages](/docs/core-concepts/internal-packages#compiled-packages) pattern. In the steps below, we assume you've [created a new repository using `create-turbo`](/docs/getting-started/installation) or are using a similarly structured repository.

<Steps>
<Step>
### Create an empty directory

You'll need a directory to put the package in. Let's create one at `./packages/math`.

<Files>
  <File name="package.json" />
  <File name="turbo.json" />
  <Folder name="apps" />
  <Folder name="packages" defaultOpen>
    <Folder name="math" green defaultOpen />
    <Folder name="ui">
      <File name="package.json" />
    </Folder>
    <Folder name="eslint-config">
      <File name="package.json" />
    </Folder>
    <Folder name="typescript-config">
      <File name="package.json" />
    </Folder>
  </Folder>
</Files>

</Step>
<Step>
### Add a package.json

Next, create the `package.json` for the package. By adding this file, you'll fulfill [the two requirements for an Internal Package](/docs/crafting-your-repository/structuring-a-repository#specifying-packages-in-a-monorepo), making it discoverable to Turborepo and the rest of your Workspace.

<Callout type="warn">
  The `name` field in your `package.json` determines how your package can be
  imported throughout your workspace. The name you choose here (e.g.
  `@repo/math`) is exactly how other packages will import it (e.g. `import {add}
  from '@repo/math/add'`).
</Callout>

<PackageManagerTabs>

<Tab value="pnpm">
```json title="./packages/math/package.json"
{
  "name": "@repo/math",
  "type": "module",
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc"
  },
  "exports": {
    "./add": {
      "types": "./src/add.ts",
      "default": "./dist/add.js"
    },
    "./subtract": {
      "types": "./src/subtract.ts",
      "default": "./dist/subtract.js"
    }
  },
  "devDependencies": {
    "@repo/typescript-config": "workspace:*",
    "typescript": "latest"
  }
}
```
</Tab>

<Tab value="yarn">
```json title="./packages/math/package.json"
{
  "name": "@repo/math",
  "type": "module",
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc"
  },
  "exports": {
    "./add": {
      "types": "./src/add.ts",
      "default": "./dist/add.js"
    },
    "./subtract": {
      "types": "./src/subtract.ts",
      "default": "./dist/subtract.js"
    }
  },
  "devDependencies": {
    "@repo/typescript-config": "workspace:*",
    "typescript": "latest"
  }
}
```
</Tab>

<Tab value="npm">
```json title="./packages/math/package.json"
{
  "name": "@repo/math",
  "type": "module",
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc"
  },
  "exports": {
    "./add": {
      "types": "./src/add.ts",
      "default": "./dist/add.js"
    },
    "./subtract": {
      "types": "./src/subtract.ts",
      "default": "./dist/subtract.js"
    }
  },
  "devDependencies": {
    "@repo/typescript-config": "*",
    "typescript": "latest"
  }
}
```

</Tab>

<Tab value="bun">
```json title="./packages/math/package.json"
{
  "name": "@repo/math",
  "type": "module",
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc"
  },
  "exports": {
    "./add": {
      "types": "./src/add.ts",
      "default": "./dist/add.js"
    },
    "./subtract": {
      "types": "./src/subtract.ts",
      "default": "./dist/subtract.js"
    }
  },
  "devDependencies": {
    "@repo/typescript-config": "workspace:*",
    "typescript": "latest"
  }
}
```

</Tab>

<Tab value="nub">
```json title="./packages/math/package.json"
{
  "name": "@repo/math",
  "type": "module",
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc"
  },
  "exports": {
    "./add": {
      "types": "./src/add.ts",
      "default": "./dist/add.js"
    },
    "./subtract": {
      "types": "./src/subtract.ts",
      "default": "./dist/subtract.js"
    }
  },
  "devDependencies": {
    "@repo/typescript-config": "workspace:*",
    "typescript": "latest"
  }
}
```

</Tab>

<Tab value="aube">
```json title="./packages/math/package.json"
{
  "name": "@repo/math",
  "type": "module",
  "scripts": {
    "dev": "tsc --watch",
    "build": "tsc"
  },
  "exports": {
    "./add": {
      "types": "./src/add.ts",
      "default": "./dist/add.js"
    },
    "./subtract": {
      "types": "./src/subtract.ts",
      "default": "./dist/subtract.js"
    }
  },
  "devDependencies": {
    "@repo/typescript-config": "workspace:*",
    "typescript": "latest"
  }
}
```

</Tab>

</PackageManagerTabs>

Let's break down this `package.json` piece-by-piece:

- **`name`**: This is the most critical field for package discoverability. The value `@repo/math` becomes the exact identifier used in import statements throughout your workspace. If you change this name, you must update all import statements accordingly.
- **`scripts`**: The `dev` and `build` script compile the package using [the TypeScript compiler](https://www.typescriptlang.org/docs/handbook/compiler-options.html). The `dev` script will watch for changes to source code and automatically recompile the package.
- **`devDependencies`**: `typescript` and `@repo/typescript-config` are `devDependencies` so you can use those packages in the `@repo/math` package. In a real-world package, you will likely have more `devDependencies` and `dependencies` - but we can keep it simple for now.
- **`exports`**: Defines multiple entrypoints for the package so it can be used in other packages (`import { add } from '@repo/math/add'`).

Notably, this `package.json` declares an Internal Package, `@repo/typescript-config`, as a dependency. Turborepo will recognize `@repo/math` as a dependent of `@repo/typescript-config` for ordering your tasks.

</Step>

<Step>
  ### Add a `tsconfig.json`

Specify the TypeScript configuration for this package by adding a `tsconfig.json` file to **the root of the package**. TypeScript has [an `extends` key](https://www.typescriptlang.org/tsconfig#extends), allowing you to use a base configuration throughout your repository and overwrite with different options as needed.

```json title="./packages/math/tsconfig.json"
{
  "extends": "@repo/typescript-config/base.json",
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src"
  },
  "include": ["src"],
  "exclude": ["node_modules", "dist"]
}
```

You've done four important things here:

- The `@repo/typescript-config/base.json` configuration that lives in `./packages/typescript-config` has all the configuration you need so you extend from it.
- [The `outDir` key](https://www.typescriptlang.org/tsconfig/#outDir) in `compilerOptions` tells TypeScript where to put the compiled output. It matches the directory specified in your `exports` in `package.json`.
- [The `rootDir` key in `compilerOptions`](https://www.typescriptlang.org/tsconfig/#rootDir) ensures that the output in `outDir` uses the same structure as the `src` directory.
- The [`include`](https://www.typescriptlang.org/tsconfig/#include) and [`exclude`](https://www.typescriptlang.org/tsconfig/#exclude) keys are not inherited from the base configuration, [according to the TypeScript specification](https://www.typescriptlang.org/tsconfig#include), so you've included them here.

<Callout type="info">
  There's a lot more to learn about TypeScript configuration, but this is a good
  place to start for now. If you'd like to learn more, visit [the official
  TypeScript documentation](https://www.typescriptlang.org/tsconfig) or [our
  TypeScript guide](/docs/guides/tools/typescript).
</Callout>

</Step>

<Step>
### Add a `src` directory with source code

You can now write some code for your package. Create two files inside a `src` directory:

<Tabs items={['add.ts', 'subtract.ts']}>
  <Tab value="add.ts">

    ```ts title="./packages/math/src/add.ts"
    export const add = (a: number, b: number) => a + b;
    ```

  </Tab>
  <Tab value="subtract.ts">

    ```ts title="./packages/math/src/subtract.ts"
    export const subtract = (a: number, b: number) => a - b;
    ```

  </Tab>
</Tabs>

These files map to the outputs that will be created by `tsc` when you run `turbo build` in a moment.

</Step>

<Step>
### Add the package to an application

You're ready to use your new package in an application. Let's add it to the `web` application.

<PackageManagerTabs>

<Tab value="pnpm">
```diff title="apps/web/package.json"
  "dependencies": {
+   "@repo/math": "workspace:*",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
```
</Tab>

<Tab value="yarn">
```diff title="apps/web/package.json"
  "dependencies": {
+   "@repo/math": "*",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
```
</Tab>

<Tab value="npm">
```diff title="apps/web/package.json"
  "dependencies": {
+   "@repo/math": "*",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
```
</Tab>

<Tab value="bun">
```diff title="apps/web/package.json"
  "dependencies": {
+   "@repo/math": "workspace:*",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
```
</Tab>

<Tab value="nub">
```diff title="apps/web/package.json"
  "dependencies": {
+   "@repo/math": "workspace:*",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
```
</Tab>

<Tab value="aube">
```diff title="apps/web/package.json"
  "dependencies": {
+   "@repo/math": "workspace:*",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
```
</Tab>

</PackageManagerTabs>

<Callout type="warn">
  You just changed the dependencies in your repo. Make sure to run your package
  manager's installation command to update your lockfile.
</Callout>

`@repo/math` is now available in the `web` application, you can use it in your code:

```tsx title="apps/web/src/app/page.tsx"
import { add } from "@repo/math/add";

function Page() {
  return <div>{add(1, 2)}</div>;
}

export default Page;
```

</Step>

<Step>
### Edit `turbo.json`

Add the artifacts for the new `@repo/math` library to the `outputs` for the `build` task in `turbo.json`. This ensures that its build outputs will be cached by Turborepo, so they can be restored instantly when you start running builds.

```json title="./turbo.json"
// [!code word:"dist/**"]
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "!.next/dev/**", "dist/**"]
    }
  }
}
```

</Step>

<Step>
### Run `turbo build`

If you've [installed `turbo` globally](/docs/getting-started/installation#global-installation), run `turbo build` in your terminal at the root of your Workspace. You can also run the `build` script from `package.json` with your package manager, which will use `turbo run build`.

The `@repo/math` package built before the `web` application built so that the runtime code in `./packages/math/dist` is available to the `web` application when it bundles.

<Callout type="info">
  You can run `turbo build` again to see your `web` application rebuild in
  **milliseconds**. We'll discuss this at length in [the Caching
  guide](/docs/crafting-your-repository/caching).
</Callout>

</Step>
</Steps>

## Best practices for Internal Packages

### One "purpose" per package

When you're creating Internal Packages, it's recommended to create packages that have a single "purpose". This isn't a strict science or rule, but a best practice depending on your repository, your scale, your organization, what your teams need, and more. This strategy has several advantages:

- **Easier to understand**: As a repository scales, developers working in the repository will more easily be able to find the code they need.
- **Reducing dependencies per package**: Using fewer dependencies per package makes it so Turborepo can more effectively [prune the dependencies of your package graph](/docs/reference/prune).

Some examples include:

- **`@repo/ui`**: A package containing all of your shared UI components
- **`@repo/tool-specific-config`**: A package for managing configuration of a specific tool
- **`@repo/graphs`**: A domain-specific library for creating and manipulating graphical data

### Application Packages do not contain shared code

When you're creating [Application Packages](/docs/core-concepts/package-types#application-packages), it's best to avoid putting shared code in those packages. Instead, you should create a separate package for the shared code and have the application packages depend on that package.

Additionally, Application Packages are not meant to be installed into other packages. Instead, they should be thought of as an entrypoint to your [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph).

<Callout type="info">
  There are [rare
  exceptions](/docs/core-concepts/package-types#installing-an-applicaiton-package-into-another-package)
  to this rule.
</Callout>

## Next steps

With a new Internal Package in place, you can start [configuring tasks](/docs/crafting-your-repository/configuring-tasks).

---

### Apps Docs Content Docs Crafting Your Repository Developing Applications (`apps/docs/content/docs/crafting-your-repository/developing-applications.mdx`)

---
title: Developing applications
description: Learn how to develop applications in your repository.
product: turborepo
type: guide
summary: Run long-lived development tasks with the terminal UI, watch mode, and package filtering.
prerequisites:
  - /docs/crafting-your-repository/caching
related:
  - /docs/crafting-your-repository/configuring-tasks
  - /docs/crafting-your-repository/using-environment-variables
  - /docs/reference/watch
---

Developing applications in a monorepo unlocks powerful workflows, enabling you to make atomic commits to source control with easy access to code.

Most development tasks are long-running tasks that watch for changes to your code. Turborepo enhances this experience with a powerful terminal UI and other capabilities like:

- [Configuration for `dev` tasks](#configuring-development-tasks)
- [Interacting with tasks](#interacting-with-tasks)
- [Watch Mode](#watch-mode)
- [Running setup scripts](#running-setup-tasks-before-dev)
- [Filtering tasks to run a subset of your packages](#running-a-specific-application)

## Configuring development tasks

Defining a development task in `turbo.json` tells Turborepo that you'll be running a long-lived task. This is useful for things like running a development server, running tests, or building your application.

To register a `dev` task, add it to your `turbo.json` with two properties:

```json title="./turbo.json"
{
  "tasks": {
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
```

- **"cache": false**: Tells Turborepo to not attempt to cache the results of the task. Since this is a development task, you're likely to be making frequent changes to your code, so caching the results is not useful.
- **"persistent": true**: Tells Turborepo to keep the task running until you stop it. This key serves as a signal for your terminal UI to treat the task as long-running and interactive. Additionally, it prevents you from accidentally depending on a task that will not exit.

You can now run your `dev` task to start your development scripts in parallel:

```bash title="Terminal"
turbo dev
```

### Running setup tasks before `dev`

You may also want to run scripts that set up your development environment or pre-build packages. You can make sure those tasks run before the `dev` task with `dependsOn`:

```json title="./turbo.json"
{
  "tasks": {
    "dev": {
      "cache": false,
      "persistent": true,
      "dependsOn": ["//#dev:setup"]
    },
    "//#dev:setup": {
      "outputs": [".codegen/**"]
    }
  }
}
```

In this example, we're using a [Root Task](/docs/crafting-your-repository/configuring-tasks#registering-root-tasks) but you can use the same idea for [arbitrary tasks in packages](/docs/crafting-your-repository/configuring-tasks#depending-on-a-specific-task-in-a-specific-package).

### Running a specific application

The `--filter` flag allows you to pick a subset of your [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph) so you can run your `dev` task for a specific application and its dependencies:

```bash title="Terminal"
turbo dev --filter=web
```

## Using the terminal UI

Turborepo's terminal UI enables a number of features that create a highly interactive experience around your tasks.

### Customizing your view

You can quickly adjust the UI to your needs using keybinds.

| Keybind | Action                                                            |
| ------- | ----------------------------------------------------------------- |
| `m`     | Toggle popup listing keybinds                                     |
| `↑`/`↓` | Select the next/previous task in the task list                    |
| `j`/`k` | Select the next/previous task in the task list                    |
| `p`     | Toggle selection pinning for selected task                        |
| `h`     | Toggle visibility of the task list                                |
| `c`     | When logs are highlighted, copy selection to the system clipboard |
| `u`/`d` | Scroll logs `u`p and `d`own                                       |

### Interacting with tasks

Some of your tools may allow you to type input into them. Examples of this include Drizzle ORM's interactive migrations or Jest's filtering and re-running of test suites.

You can interact with tasks that are [marked as interactive](/docs/reference/configuration#interactive) to give them input.

| Keybind  | Action            |
| -------- | ----------------- |
| `i`      | Begin interacting |
| `Ctrl+z` | Stop interacting  |

## Watch Mode

Many tools have a built-in watcher, like [`tsc --watch`](https://www.typescriptlang.org/docs/handbook/compiler-options.html#compiler-options),
that will respond to changes in your source code. However, some don't.

`turbo watch` adds a dependency-aware watcher to any tool. Changes to source code will follow [the Task Graph](/docs/core-concepts/package-and-task-graph#task-graph) that you've described in `turbo.json`, just like all your other tasks.

For example, using a package structure like [`create-turbo`](/docs/reference/create-turbo) with the following tasks and scripts:

<Tabs items={["turbo.json", "packages/ui", "apps/web"]}>
<Tab value="turbo.json">

```json title="turbo.json"
{
  "tasks": {
    "dev": {
      "persistent": true,
      "cache": false
    },
    "lint": {
      "dependsOn": ["^lint"]
    }
  }
}
```

</Tab>

<Tab value="packages/ui">

```json title="package.json"
{
  "name": "@repo/ui"
  "scripts": {
    "dev": "tsc --watch",
    "lint": "eslint ."
  }
}
```

</Tab>

<Tab value="apps/web">

```json title="package.json"
{
  "name": "web"
  "scripts": {
    "dev": "next dev",
    "lint": "eslint ."
  },
  "dependencies": {
      "@repo/ui": "workspace:*"
    }
}
```

</Tab>
</Tabs>

When you run `turbo watch dev lint`, you'll see the `lint` scripts are re-run whenever you make source code changes, despite ESLint not having a built-in watcher. `turbo watch` is also aware of internal dependencies, so a code change in `@repo/ui` will re-run the task in both `@repo/ui` and `web`.

The Next.js development server in `web` and the TypeScript Compiler's built-in watcher in `@repo/ui` will continue to work as usual, since they are marked with `persistent`.

For more information, [visit the `turbo watch` reference](/docs/reference/watch).

## Limitations

### Teardown tasks

In some cases, you may want to run a script when the `dev` task is stopped. Turborepo is unable to run those teardown scripts when exiting because `turbo` exits when your `dev` tasks exit.

Instead, create a `turbo dev:teardown` script that you run separately after you've exited your primary `turbo dev` task.

## Next steps

Once you have a version of your application that you'd like to deploy, it's time to learn how to configure environment variables in Turborepo.

---

### Apps Docs Content Docs Crafting Your Repository Managing Dependencies (`apps/docs/content/docs/crafting-your-repository/managing-dependencies.mdx`)

---
title: Managing dependencies
description: Learn how to manage dependencies in your monorepo's workspace.
product: turborepo
type: guide
summary: Install, organize, and maintain external and internal dependencies across packages in your workspace.
prerequisites:
  - /docs/crafting-your-repository/structuring-a-repository
related:
  - /docs/crafting-your-repository/creating-an-internal-package
  - /docs/core-concepts/internal-packages
---

- **External dependencies** come from [the npm registry](https://www.npmjs.com/), allowing you to leverage valuable code from the ecosystem to build your applications and libraries faster.
- **Internal dependencies** let you share functionality within your repository, dramatically improving discoverability and usability of shared code. We will discuss how to build an Internal Package in [the next guide](/docs/crafting-your-repository/creating-an-internal-package).

<PackageManagerTabs>

<Tab value="pnpm">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "next": "latest", // External dependency
    "@repo/ui": "workspace:*" // Internal dependency
  }
}
```
</Tab>

<Tab value="yarn">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "next": "latest", // External dependency
    "@repo/ui": "*" // Internal dependency
  }
}
```
</Tab>

<Tab value="npm">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "next": "latest", // External dependency
    "@repo/ui": "*" // Internal dependency
  }
}
```
</Tab>

<Tab value="bun">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "next": "latest", // External dependency
    "@repo/ui": "workspace:*" // Internal dependency
  }
}
```
</Tab>

<Tab value="nub">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "next": "latest", // External dependency
    "@repo/ui": "workspace:*" // Internal dependency
  }
}
```
</Tab>

<Tab value="aube">
```json title="./apps/web/package.json"
{
  "dependencies": {
    "next": "latest", // External dependency
    "@repo/ui": "workspace:*" // Internal dependency
  }
}
```
</Tab>

</PackageManagerTabs>

## Best practices for dependency installation

### Install dependencies where they're used

When you install a dependency in your repository, you should install it directly in the package that uses it. The package's `package.json` will have every dependency that the package needs. This is true for both external and internal dependencies.

<Callout type="info">
  Note that your package manager may choose to [use a different node_modules
  location than the package](#node_modules-locations).
</Callout>

To quickly install dependencies in multiple packages, you can use your package manager:

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
pnpm add jest --save-dev --recursive --filter=web --filter=@repo/ui --filter=docs
```

<LinkToDocumentation href="https://pnpm.io/cli/recursive" text="pnpm documentation" />
</Tab>

<Tab value="yarn">
Yarn 1:

```bash title="Terminal"
yarn workspace web add jest --dev
yarn workspace @repo/ui add jest --dev
```

<LinkToDocumentation href="https://classic.yarnpkg.com/en/docs/cli/add" text="Yarn 1 documentation" />

Yarn 2+:

```bash title="Terminal"
yarn workspaces foreach -R --from '{web,@repo/ui}' add jest --dev
```

<LinkToDocumentation href="https://yarnpkg.com/cli/workspaces/foreach#usage" text="Yarn 2+ documentation" />
</Tab>

<Tab value="npm">

```bash title="Terminal"
npm install jest --workspace=web --workspace=@repo/ui --save-dev
```

<LinkToDocumentation href="https://docs.npmjs.com/cli/v7/using-npm/config#workspace" text="npm documentation" />
</Tab>

<Tab value="bun">

```bash title="Terminal"
cd apps/web && bun install jest --dev
cd packages/ui && bun install jest --dev
```

<LinkToDocumentation href="https://bun.sh/docs/install/workspaces" text="bun documentation" />
</Tab>

<Tab value="nub">

```bash title="Terminal"
cd apps/web && nub add jest --save-dev
cd packages/ui && nub add jest --save-dev
```

<LinkToDocumentation href="https://nub.dev" text="nub documentation" />
</Tab>

<Tab value="aube">

```bash title="Terminal"
cd apps/web && aube add jest --save-dev
cd packages/ui && aube add jest --save-dev
```

<LinkToDocumentation href="https://aube.jdx.dev" text="aube documentation" />
</Tab>

</PackageManagerTabs>

This practice has several benefits:

- **Improved clarity**: It's easier to understand what a package depends on when its dependencies are listed in its `package.json`. Developers working in the repository can see at a glance what dependencies are used within the package.
- **Enhanced flexibility**: In a monorepo at scale, it can be unrealistic to expect each package to use the same version of an external dependency. When there are many teams working in the same codebase, there will be differing priorities, timelines, and needs due to the realities of [operating at scale](https://vercel.com/blog/how-to-scale-a-large-codebase). By installing dependencies in the package that uses them, you can enable your `ui` team to bump to the latest version of TypeScript, while your `web` team can prioritize shipping new features and bumping TypeScript later. Additionally, if you still want to keep dependency versions in sync, [you can do that, too](#keeping-dependencies-on-the-same-version).
- **Better caching ability**: If you install too many dependencies in the root of your repository, you'll be changing the workspace root whenever you add, update, or delete a dependency, leading to unnecessary cache misses.
- **Pruning unused dependencies**: For Docker users, [Turborepo's pruning feature](/docs/reference/prune) can remove unused dependencies from Docker images to create lighter images. When dependencies are installed in the packages that they are meant for, Turborepo can read your lockfile and remove dependencies that aren't used in the packages you need.

### Few dependencies in the root

Following the first principle above to [install dependencies in the package where they're used](#install-dependencies-where-theyre-used), you'll find that you naturally end up with few dependencies in the root of your workspace.

The only dependencies that belong in the workspace root are **tools for managing the repository** whereas dependencies for building applications and libraries are installed in their respective packages. Some examples of dependencies that make sense to install in the root are [`turbo`](https://www.npmjs.com/package/turbo), [`husky`](https://www.npmjs.com/package/husky), or [`lint-staged`](https://www.npmjs.com/package/lint-staged).

## Managing dependencies

### Turborepo does not manage dependencies

Note that Turborepo does not play a role in managing your dependencies, leaving that work up to your package manager of choice.

It's up to the package manager to handle things like downloading the right external dependency version, symlinking, and resolving modules. The recommendations on this page are best practices for managing dependencies in a Workspace, and are not enforced by Turborepo.

### Module resolution differs amongst package managers

Package managers have different module resolution algorithms, which leads to differences in behavior that can be difficult to predict.

In the Turborepo documentation, we make many recommendations according to the expected behaviors of the package managers. Our coverage of how to handle dependencies is best effort and you may need to adapt the documented behavior for your package manager or repository's needs.

However, if you find an issue with the documentation that appears to be universally incorrect for all package managers or a specific one, please let us know with a GitHub Issue so we can improve.

### node_modules locations

Depending on your choice of package manager, version, settings, and where your dependencies are installed in your Workspace, you may see `node_modules` and the dependencies inside it in various locations within the Workspace. Dependencies could be found in the root `node_modules`, in packages' `node_modules`, or both.

As long as your scripts and tasks are able to find the dependencies they need, your package manager is working correctly.

<Callout type="info" title="Referencing `node_modules` in your code">
The specific locations for `node_modules` within the Workspace are not a part of the public API of package managers. This means that referencing `node_modules` directly (like `node ./node_modules/a-package/dist/index.js`) can be brittle, since the location of the dependency on disk can change with other dependency changes around the Workspace.

Instead, rely on conventions of the Node.js ecosystem for accessing dependency modules whenever possible.

</Callout>

### Keeping dependencies on the same version

Some monorepo maintainers prefer to keep dependencies on the same version across all packages by rule. There are several ways to achieve this:

#### Using purpose-built tooling

Tools like [`syncpack`](https://www.npmjs.com/package/syncpack), [`manypkg`](https://www.npmjs.com/package/@manypkg/cli), and [`sherif`](https://www.npmjs.com/package/sherif) can be used for this specific purpose.

#### Using your package manager

You can use your package manager to update dependency versions in one command.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
pnpm up --recursive typescript@latest
```

<small>[-> pnpm documentation](https://pnpm.io/cli/update#--recursive--r)</small>

</Tab>

<Tab value="yarn">
Yarn 1:
```bash title="Terminal"
yarn upgrade-interactive --latest
```
<small>[-> Yarn 1 documentation](https://classic.yarnpkg.com/en/docs/cli/upgrade-interactive)</small>

Yarn 2+:

```bash title="Terminal"
yarn upgrade typescript@latest --upgrade
```

<small>[-> Yarn 2+ documentation](https://yarnpkg.com/cli/up)</small>

</Tab>

<Tab value="npm">
```bash title="Terminal"
npm install typescript@latest --workspaces
```
  <small>[-> npm documentation](https://docs.npmjs.com/cli/v7/using-npm/config#workspaces)</small>

</Tab>

<Tab value="bun">

```bash title="Terminal"
bun update typescript --latest
```

<small>[-> Bun documentation](https://bun.sh/docs/cli/update)</small>

</Tab>

<Tab value="nub">

```bash title="Terminal"
nub update typescript --latest
```

<small>[-> nub documentation](https://nub.dev)</small>

</Tab>

<Tab value="aube">

```bash title="Terminal"
aube update typescript --latest
```

<small>[-> aube documentation](https://aube.jdx.dev)</small>

</Tab>

</PackageManagerTabs>

#### pnpm catalogs

In pnpm v9.5+, you can use catalogs to define dependency version ranges as reusable constants. This will keep dependencies on the same version since you're referencing the same value across the workspace.

To learn more, [visit the pnpm catalogs documentation](https://pnpm.io/catalogs).

#### Using an IDE

Your IDE's refactoring tooling can find and replace the version of a dependency across all `package.json` files in your repository at once. Try using a regex like `"next": ".*"` on `package.json` files to find all instances of the `next` package and replace them with the version you want. When you're done, make sure to run your package manager's install command to update your lockfile.

## Next steps

Now that you know how to manage dependencies effectively in a workspace, let's [create an Internal Package](/docs/crafting-your-repository/creating-an-internal-package) to be used as a dependency in your monorepo.

---

### Apps Docs Content Docs Crafting Your Repository Running Tasks (`apps/docs/content/docs/crafting-your-repository/running-tasks.mdx`)

---
title: Running tasks
description: Learn how to run tasks in your repository through the `turbo` CLI.
product: turborepo
type: guide
summary: Execute tasks using the turbo CLI with scripts, global turbo, filters, and multi-task parallelization.
prerequisites:
  - /docs/crafting-your-repository/configuring-tasks
related:
  - /docs/crafting-your-repository/caching
  - /docs/core-concepts/package-and-task-graph
  - /docs/reference/run
---

Turborepo optimizes the developer workflows in your repository by automatically parallelizing and caching tasks. Once a task is [registered in `turbo.json`](/docs/crafting-your-repository/configuring-tasks), you have a powerful new toolset for running the scripts in your repository:

- [Use `scripts` in `package.json` for tasks you need to run often](#using-scripts-in-packagejson)
- [Use global `turbo` to quickly run custom tasks on-demand](#using-global-turbo)
- [Filter tasks by directories, package names, source control changes, and more](#using-filters)

Running tasks through `turbo` is powerful because you get one model for executing workflows throughout your repository in development and in your CI pipelines.

## Using `scripts` in `package.json`

For tasks that you run frequently, you can write your `turbo` commands directly into your root `package.json`.

```jsonc title="./package.json"
{
  "scripts": {
    "dev": "turbo run dev",
    "build": "turbo run build",
    "test": "turbo run test",
    "lint": "turbo run lint"
  }
}
```

<Callout type="info">
  `turbo` is an alias for `turbo run` - but we recommend using `turbo run` in
  `package.json` and CI workflows to avoid potential collisions with possible
  `turbo` subcommands that could be added in the future.
</Callout>

These scripts can then be run using your package manager.

<PackageManagerTabs>

  <Tab value="pnpm">
  ```bash title="Terminal"
  pnpm dev
  ```

  </Tab>

  <Tab value="yarn">

```bash title="Terminal"
yarn dev
```

  </Tab>

  <Tab value="npm">

```bash title="Terminal"
npm run dev
```

  </Tab>

  <Tab value="bun">

```bash title="Terminal"
bun run dev
```

  </Tab>

<Tab value="nub">

```bash title="Terminal"
nub run dev
```

  </Tab>

<Tab value="aube">

```bash title="Terminal"
aube run dev
```

  </Tab>

</PackageManagerTabs>

<Callout type="warn">
You only want to write `turbo` commands in your root `package.json`. Writing `turbo` commands into the `package.json` of packages can lead to recursively
calling `turbo`.

</Callout>

## Using global `turbo`

[Installing `turbo` globally](/docs/getting-started/installation#global-installation) lets you run commands directly from your terminal. This improves your local development experience since it makes it easier to run exactly what you need, when you need it.

Additionally, global `turbo` is useful in your CI pipelines, giving you maximum control of exactly which tasks to run at each point in your pipeline.

### Automatic Package Scoping

When you're in a package's directory, `turbo` will automatically scope commands to the [Package Graph](/docs/core-concepts/package-and-task-graph#package-graph) for that package. This means you can quickly write commands without having to [write filters](/docs/reference/run#--filter-string) for the package.

```bash title="Terminal"
cd apps/docs
turbo build
```

In the example above, the `turbo build` command will run the `build` task for the `docs` package using the `build` task registered in `turbo.json`.

<Callout type="info">
  [Using a filter](#using-filters) will override Automatic Package Scoping.
</Callout>

### Customizing behavior

In [the documentation for the `run` subcommand](/docs/reference/run), you'll find many useful flags to tailor the behavior of `turbo run` for what you need. When running global `turbo`, you can go faster using workflows like:

- **Variations of your most common commands**: The `build` script in `package.json` has the most utility when it is `turbo build` - but you might only be interested in a specific package at the moment. You can quickly filter for the specific package you're interested in using `turbo build --filter=@repo/ui`.
- **One-off commands**: Commands like `turbo build --dry` aren't needed often so you likely won't create a script in your `package.json` for it. Instead, you can run it directly in your terminal whenever you need it.
- **Overriding `turbo.json` configuration**: Some CLI flags have an equivalent in `turbo.json` that you can override. For instance, you may have a `turbo build` command configured to use [`"outputLogs": "full"` in `turbo.json`](/docs/reference/configuration#outputlogs) - but you're only interested in seeing errors at the moment. Using global `turbo`, you can use `turbo lint --output-logs=errors-only` to only show errors.

## Running multiple tasks

`turbo` is able to run multiple tasks, parallelizing whenever possible.

```bash title="Terminal"
turbo run build test lint check-types
```

This command will run all of the tasks, automatically detecting where it can run a script as early as possible, according to your task definitions.

<Callout type="info" title="Ordering of tasks">
`turbo test lint` will run tasks exactly the same as `turbo lint test`.

If you want to ensure that one task blocks the execution of another, express that relationship in your [task configurations](/docs/crafting-your-repository/configuring-tasks#defining-tasks).

</Callout>

## Using filters

While [caching](/docs/crafting-your-repository/running-tasks) ensures you stay fast by never doing the same work twice, you can also filter tasks to run only a subset of [the Task Graph](/docs/core-concepts/package-and-task-graph#task-graph).

There are many advanced use cases for filtering in [the `--filter` API reference](/docs/reference/run#--filter-string) but the most common use cases are discussed below.

### Filtering by package

Filtering by package is a simple way to only run tasks for the packages you're currently working on.

```bash title="Terminal"
turbo build --filter=@acme/web
```

<InVersion version="2.2.4">

You can also filter to a specific task for the package directly in your CLI command without needing to use `--filter`:

```bash title="Terminal"
# Run the `build` task for the `web` package
turbo run web#build

# Run the `build` task for the `web` package, and the `lint` task for the `docs` package
turbo run web#build docs#lint
```

</InVersion>

### Filtering by directory

Your repository might have a directory structure where related packages are grouped together. In this case, you can capture the glob for that directory to focus `turbo` on those packages.

```bash title="Terminal"
turbo lint --filter="./packages/utilities/*"
```

### Filtering to include dependents

When you're working on a specific package, you might want to run tasks for the package and its dependents. The `...` microsyntax is useful when you're making changes to a package and want to ensure that the changes don't break any of its dependents.

```bash title="Terminal"
turbo build --filter=...ui
```

### Filtering to include dependencies

To limit the scope to a package and its dependencies, append `...` to the package name. This runs the task for the specified package and all packages it depends on.

```bash title="Terminal"
turbo dev --filter=web...
```

### Filtering by source control changes

Using filters to run tasks based on changes in source control is a great way to run tasks only for the packages that are affected by your changes. **Source control filters must be wrapped in `[]`**.

- **Comparing to the previous commit**: `turbo build --filter=[HEAD^1]`
- **Comparing to the main branch**: `turbo build --filter=[main...my-feature]`
- **Comparing specific commits using SHAs**: `turbo build --filter=[a1b2c3d...e4f5g6h]`
- **Comparing specific commits using branch names**: `turbo build --filter=[your-feature...my-feature]`

<Callout type="info">
  In general, you can rely on caching to keep your repository fast. When you're
  using [Remote Caching](/docs/core-concepts/remote-caching), you can count on
  hitting cache for unchanged packages.
</Callout>

### Combining filters

For even more specificity, you can combine filters to further refine the entrypoints into your [Task Graph](/docs/core-concepts/package-and-task-graph#task-graph).

```bash title="Terminal"
turbo build --filter=...ui --filter={./packages/*} --filter=[HEAD^1]
```

Multiple filters are combined as a **union**, meaning that the [Task Graph](/docs/core-concepts/package-and-task-graph#task-graph) will include tasks that match any of the filters. For more information on advanced usage of filters, see [the `--filter` API reference](/docs/reference/run#--filter-string).

## Next steps

When you start running tasks in your repository, you might start noticing that your tasks get faster. Next, you'll explore [caching](/docs/crafting-your-repository/caching) and how `turbo` makes it so you never do the same work twice.

---

### Apps Docs Content Docs Crafting Your Repository Structuring A Repository (`apps/docs/content/docs/crafting-your-repository/structuring-a-repository.mdx`)

---
title: Structuring a repository
description: Start by creating a repository using the conventions of the ecosystem.
product: turborepo
type: guide
summary: Set up a multi-package workspace with the directory structure, package.json files, and lockfile that Turborepo expects.
related:
  - /docs/crafting-your-repository/managing-dependencies
  - /docs/core-concepts/internal-packages
  - /docs/core-concepts/package-types
---

`turbo` is built on top of [Workspaces](https://vercel.com/docs/glossary#workspace), a feature of package managers in the JavaScript ecosystem that allows you to group multiple packages in one repository.

Following these conventions is important because it allows you to:

- Lean on those conventions for all your repo's tooling
- Quickly, incrementally adopt Turborepo into an existing repository

In this guide, we'll walk through setting up a multi-package workspace (monorepo) so we can set the groundwork for `turbo`.

## Getting started

Setting up a workspace's structure can be tedious to do by hand. If you're new to monorepos, we recommend [using `create-turbo` to get started](/docs/getting-started/installation) with a valid workspace structure right away.

<PackageManagerTabs>

<Tab value="pnpm">
```bash title="Terminal"
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">
```bash title="Terminal"
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">
```bash title="Terminal"
npx create-turbo@latest
```

</Tab>

<Tab value="bun">
```bash title="Terminal"
bunx create-turbo@latest
```

</Tab>


<Tab value="nub">
```bash title="Terminal"
nubx create-turbo@latest
```

</Tab>

<Tab value="aube">
```bash title="Terminal"
aubx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

You can then review the repository for the characteristics described in this guide.

## Anatomy of a workspace

In JavaScript, a workspace can either be [a single package](/docs/guides/single-package-workspaces) or a collection of packages. In these guides, we'll be focusing on [a multi-package workspace](https://vercel.com/docs/glossary#monorepo), often called a "monorepo".

Below, the structural elements of `create-turbo` that make it a valid workspace are highlighted.

<PackageManagerTabs>

<Tab value="pnpm">
  <Files>
    <File name="package.json" green />
    <File name="pnpm-lock.yaml" green />
    <File name="pnpm-workspace.yaml" green />
    <File name="turbo.json" />
    <Folder name="apps" defaultOpen>
      <Folder name="docs" className="text-foreground" defaultOpen>
        <File name="package.json" green />
      </Folder>
      <Folder name="web">
        <File name="package.json" green />
      </Folder>
    </Folder>
    <Folder name="packages">
      <Folder name="ui">
        <File name="package.json" green />
      </Folder>
    </Folder>
  </Files>
</Tab>

<Tab value="yarn">
  <Files>
    <File name="package.json" green />
    <File name="yarn.lock" green />
    <File name="turbo.json" />
    <Folder name="apps" defaultOpen>
      <Folder name="docs" className="text-foreground" defaultOpen>
        <File name="package.json" green />
      </Folder>
      <Folder name="web">
        <File name="package.json" green />
      </Folder>
    </Folder>
    <Folder name="packages">
      <Folder name="ui">
        <File name="package.json" green />
      </Folder>
    </Folder>
  </Files>
</Tab>

<Tab value="npm">
  <Files>
    <File name="package.json" green />
    <File name="package-lock.json" green />
    <File name="turbo.json" />
    <Folder name="apps" defaultOpen>
      <Folder name="docs" className="text-foreground" defaultOpen>
        <File name="package.json" green />
      </Folder>
      <Folder name="web">
        <File name="package.json" green />
      </Folder>
    </Folder>
    <Folder name="packages">
      <Folder name="ui">
        <File name="package.json" green />
      </Folder>
    </Folder>
  </Files>
</Tab>

<Tab value="bun">
  <Files>
    <File name="package.json" green />
    <File name="bun.lock" green />
    <File name="turbo.json" />
    <Folder name="apps" defaultOpen>
      <Folder name="docs" className="text-foreground" defaultOpen>
        <File name="package.json" green />
      </Folder>
      <Folder name="web">
        <File name="package.json" green />
      </Folder>
    </Folder>
    <Folder name="packages">
      <Folder name="ui">
        <File name="package.json" green />
      </Folder>
    </Folder>
  </Files>
</Tab>


<Tab value="nub">
  <Files>
    <File name="package.json" green />
    <File name="nub.lock" green />
    <File name="turbo.json" />
    <Folder name="apps" defaultOpen>
      <Folder name="docs" className="text-foreground" defaultOpen>
        <File name="package.json" green />
      </Folder>
      <Folder name="web">
        <File name="package.json" green />
      </Folder>
    </Folder>
    <Folder name="packages">
      <Folder name="ui">
        <File name="package.json" green />
      </Folder>
    </Folder>
  </Files>
</Tab>

<Tab value="aube">
  <Files>
    <File name="package.json" green />
    <File name="aube-lock.yaml" green />
    <File name="turbo.json" />
    <Folder name="apps" defaultOpen>
      <Folder name="docs" className="text-foreground" defaultOpen>
        <File name="package.json" green />
      </Folder>
      <Folder name="web">
        <File name="package.json" green />
      </Folder>
    </Folder>
    <Folder name="packages">
      <Folder name="ui">
        <File name="package.json" green />
      </Folder>
    </Folder>
  </Files>
</Tab>

</PackageManagerTabs>

### Minimum requirements

- [Packages as described by your package manager](#specifying-packages-in-a-monorepo)
- [A package manager lockfile](#package-manager-lockfile)
- [Root `package.json`](#root-packagejson)
- [Root `turbo.json`](#root-turbojson)
- [`package.json` in each package](#packagejson-in-each-package)

### Specifying packages in a monorepo

<Steps>
<Step>

#### Declaring directories for packages

First, your package manager needs to describe the locations of your packages. We recommend starting with splitting your packages into `apps/` for applications and services and `packages/` for everything else, like libraries and tooling.

<PackageManagerTabs>

  <Tab value="pnpm">
  ```json title="pnpm-workspace.yaml"
 packages:
    - "apps/*"
    - "packages/*"
  ```
  <LinkToDocumentation href="https://pnpm.io/pnpm-workspace_yaml" text="pnpm workspace documentation" />

  </Tab>

  <Tab value="yarn">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://yarnpkg.com/features/workspaces#how-are-workspaces-declared" text="yarn workspace documentation" />
   </Tab>

  <Tab value="npm">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://docs.npmjs.com/cli/v7/using-npm/workspaces#defining-workspaces" text="npm workspace documentation" />
  </Tab>

  <Tab value="bun">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://bun.sh/docs/install/workspaces" text="bun workspace documentation" />
  </Tab>


<Tab value="nub">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://nub.dev" text="nub documentation" />
  </Tab>

<Tab value="aube">

```yaml title="aube-workspace.yaml"
packages:
  - "apps/*"
  - "packages/*"
```

  <LinkToDocumentation href="https://aube.jdx.dev" text="aube workspace documentation" />
  </Tab>

</PackageManagerTabs>

Using this configuration, every directory **with a `package.json`** in the `apps` or `packages` directories will be considered a package.

<Callout type="error">
Turborepo does not support nested packages like `apps/**` or `packages/**` due to ambiguous behavior among package managers in the JavaScript ecosystem. Using a structure that would put a package at `apps/a` and another at `apps/a/b` will result in an error.

If you'd like to group packages by directory, you can do this using globs like `packages/*` and `packages/group/*` and **not** creating a `packages/group/package.json` file.

</Callout>
</Step>

<Step>

#### `package.json` in each package

In the directory of the package, there must be a `package.json` to make the package discoverable to your package manager and `turbo`. The [requirements for the `package.json` of a package](#anatomy-of-a-package) are below.

</Step>
</Steps>

### Root `package.json`

The root `package.json` is the base for your workspace. Below is a common example of what you would find in a root `package.json`:

<PackageManagerTabs>

<Tab value="pnpm">

```json title="./package.json"
{
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "latest"
  },
  "devEngines": {
    "packageManager": {
      "name": "pnpm",
      "version": "9.0.0"
    }
  }
}
```

</Tab>

<Tab value="yarn">

```json title="./package.json"
{
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "latest"
  },
  "devEngines": {
    "packageManager": {
      "name": "yarn",
      "version": "1.22.19"
    }
  },
  "workspaces": ["apps/*", "packages/*"]
}
```

</Tab>

<Tab value="npm">

```json title="./package.json"
{
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "latest"
  },
  "devEngines": {
    "packageManager": {
      "name": "npm",
      "version": "10.0.0"
    }
  },
  "workspaces": ["apps/*", "packages/*"]
}
```

</Tab>

<Tab value="bun">

```json title="./package.json"
{
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "latest"
  },
  "devEngines": {
    "packageManager": {
      "name": "bun",
      "version": "1.2.0"
    }
  },
  "workspaces": ["apps/*", "packages/*"]
}
```

</Tab>

<Tab value="nub">

```json title="./package.json"
{
  "private": true,
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint"
  },
  "devDependencies": {
    "turbo": "latest"
  },
  "devEngines": {
    "packageManager": {
      "name": "nub",
      "version": "0.8.3"
    }
  },
  "workspaces": ["apps/*", "packages/*"]
}
```

</Tab>

<Tab value="aube">

```yaml title="aube-workspace.yaml"
packages:
  - "apps/*"
  - "packages/*"
```

</Tab>

</PackageManagerTabs>

### Root `turbo.json`

`turbo.json` is used to configure the behavior of `turbo`. To learn more about how to configure your tasks, visit the [Configuring tasks](/docs/crafting-your-repository/configuring-tasks) page.

### Package manager lockfile

A lockfile is key to reproducible behavior for both your package manager and `turbo`. Additionally, Turborepo uses the lockfile to understand the dependencies between your [Internal Packages](/docs/core-concepts/internal-packages) within your Workspace.

<Callout type="warn">
  If you do not have a lockfile present when you run `turbo`, you may see
  unpredictable behavior.
</Callout>

## Anatomy of a package

It's often best to start thinking about designing a package as its own unit within the Workspace. At a high-level, each package is almost like its own small "project", with its own `package.json`, tooling configuration, and source code. There are limits to this idea—but its a good mental model to _start_ from.

Additionally, a package has specific entrypoints that other packages in your Workspace can use to access the package, specified by [`exports`](#exports).

### `package.json` for a package

#### `name`

[The `name` field](https://nodejs.org/api/packages.html#name) is used to identify the package. It should be unique within your workspace.

<Callout type="info">
It's best practice to use a namespace prefix for your [Internal Packages](/docs/core-concepts/internal-packages) to avoid conflicts with other packages on the npm registry. For example, if your organization is named `acme`, you might name your packages `@acme/package-name`.

We use `@repo` in our docs and examples because it is an unused, unclaimable namespace on the npm registry. You can choose to keep it or use your own prefix.

</Callout>

#### `scripts`

The `scripts` field is used to define scripts that can be run in the package's context. Turborepo will use the name of these scripts to identify what scripts to run (if any) in a package. We talk more about these scripts on the [Running Tasks](/docs/crafting-your-repository/running-tasks) page.

#### `exports`

[The `exports` field](https://nodejs.org/api/packages.html#exports) is used to specify the entrypoints for other packages that want to use the package. When you want to use code from one package in another package, you'll import from that entrypoint.

For example, if you had a `@repo/math` package, you might have the following `exports` field:

```json title="./packages/math/package.json"
{
  "exports": {
    ".": "./src/constants.ts",
    "./add": "./src/add.ts",
    "./subtract": "./src/subtract.ts"
  }
}
```

Note that this example uses the [Just-in-Time Package](/docs/core-concepts/internal-packages#just-in-time-packages) pattern for simplicity. It exports TypeScript directly, but you might choose to use the [Compiled Package](/docs/core-concepts/internal-packages#compiled-packages) pattern instead.

<Callout type="info">
  The `exports` field in this example requires modern versions of Node.js and
  TypeScript.
</Callout>

This would allow you to import `add` and `subtract` functions from the `@repo/math` package like so:

```ts title="./apps/my-app/src/index.ts"
import { GRAVITATIONAL_CONSTANT, SPEED_OF_LIGHT } from "@repo/math";
import { add } from "@repo/math/add";
import { subtract } from "@repo/math/subtract";
```

Using exports this way provides three major benefits:

- **Avoiding barrel files**: Barrel files are files that re-export other files in the same package, creating one entrypoint for the entire package. While they might appear convenient, they're [difficult for compilers and bundlers to handle](https://vercel.com/blog/how-we-optimized-package-imports-in-next-js#what's-the-problem-with-barrel-files) and can quickly lead to performance problems.
- **More powerful features**: `exports` also has other powerful features compared to [the `main` field](https://nodejs.org/api/packages.html#main) like [Conditional Exports](https://nodejs.org/api/packages.html#conditional-exports). In general, we recommend using `exports` over `main` whenever possible as it is the more modern option.
- **IDE autocompletion**: By specifying the entrypoints for your package using `exports`, you can ensure that your code editor can provide auto-completion for the package's exports.

#### `imports` (optional)

[The `imports` field](https://nodejs.org/api/packages.html#imports) gives you a way to create subpaths to other modules within your package. You can think of these like "shortcuts" to write simpler import paths that are more resilient to refactors that move files. To learn how, visit [the TypeScript page](/docs/guides/tools/typescript#use-nodejs-subpath-imports-instead-of-typescript-compiler-paths).

<Callout type="info">
You may be more familiar with TypeScript's `compilerOptions#paths` option, which accomplishes a similar goal. As of TypeScript 5.4, TypeScript can infer subpaths from `imports`, making it a better option since you'll be working with Node.js conventions. For more information, visit [our TypeScript guide](/docs/guides/tools/typescript#use-nodejs-subpath-imports-instead-of-typescript-compiler-paths).

</Callout>

### Source code

Of course, you'll want some source code in your package. Packages commonly use a `src` directory to store their source code and compile to a `dist` directory (that should also be located within the package), although this is not a requirement.

## Common pitfalls

- If you're using TypeScript, you likely don't need a `tsconfig.json` in the root of your workspace. Packages should independently specify their own configurations, usually building off of a shared `tsconfig.json` from a separate package in the workspace. For more information, visit [the TypeScript guide](/docs/guides/tools/typescript#you-likely-dont-need-a-tsconfigjson-file-in-the-root-of-your-project).
- You want to avoid accessing files across package boundaries as much as possible. If you ever find yourself writing `../` to get from one package to another, you likely have an opportunity to re-think your approach by installing the package where it's needed and importing it into your code.

## Next steps

With your Workspace configured, you can now use your package manager to [install dependencies into your packages](/docs/crafting-your-repository/managing-dependencies).

---

### Apps Docs Content Docs Crafting Your Repository Understanding Your Repository (`apps/docs/content/docs/crafting-your-repository/understanding-your-repository.mdx`)

---
title: Understanding your repository
description: Learn how to understand your repository structure using Turborepo.
product: turborepo
type: guide
summary: Use turbo devtools, ls, run, and query to visualize and inspect your monorepo's package and task graphs.
related:
  - /docs/core-concepts/package-and-task-graph
  - /docs/crafting-your-repository/running-tasks
  - /docs/reference/devtools
---

Turborepo includes tools for understanding your repository structure, that can help you use and optimize your codebase.

## `turbo devtools`

`turbo devtools` provides a browser-based visualization of your package graph. This tool can be helpful for diagnosing issues with your task graph and understanding the structure of your monorepo.

```bash title="Terminal"
turbo devtools
```

For more information, see the [reference documentation](/docs/reference/devtools).

## `turbo ls`

To list your packages, you can run `turbo ls`. This will show the packages in your repository and where they're located.

```bash title="Terminal"
> turbo ls

  @repo/eslint-config packages/eslint-config
  @repo/typescript-config packages/typescript-config
  @repo/ui packages/ui
  docs apps/docs
  web apps/web
```

You can [apply filters](/docs/crafting-your-repository/running-tasks#using-filters) to `ls`, just like `run`:

```bash title="Terminal"
> turbo ls --filter ...ui
3 packages (pnpm9)

  @repo/ui packages/ui
  docs apps/docs
  web apps/web
```

## `turbo run`

To determine which tasks can be run in your monorepo, simply call `turbo run` without any tasks. You will get a list of
tasks and the packages in which they are defined:

```bash title="Terminal"
> turbo run
No tasks provided, here are some potential ones

  lint
    @repo/ui, docs, web
  build
    docs, web
  dev
    docs, web
  start
    docs, web
  generate:component
    @repo/ui
```

## `turbo query`

If you wish to dig into your repository structure, since `2.2.0`, Turborepo provides a GraphQL interface into your repository
via `turbo query`. You can execute queries such as finding all packages that have a `test` task:

```bash title="Terminal"
> turbo query "query { packages(filter: { has: { field: TASK_NAME, value: \"build\"}}) { items { name } } }"
{
  "data": {
    "packages": {
      "items": [
        {
          "name": "//"
        },
        {
          "name": "docs"
        },
        {
          "name": "web"
        }
      ]
    }
  }
}
```

This can be helpful for diagnosing potential problems in your package or task dependency graph. For instance, let's say
you're getting a lot of cache misses in your builds. This could be because there's a package that keeps getting changed
and is imported throughout your codebase.

To do this, we can run a query to find packages that are directly imported more than 10 times in your monorepo:

```bash title="Terminal"
> turbo query "query { packages(filter: { greaterThan: { field: DIRECT_DEPENDENT_COUNT, value: 10 } }) { items { name } } }"
{
  "data": {
    "packages": {
      "items": [
        {
          "name": "utils"
        }
      ]
    }
  }
}
```

Now that we've found this package, we can try to split it up into smaller packages so that a small change won't
invalidate the whole dependency graph.

Or let's say you're using our new `--affected` flag, but you're still running more tasks than you'd like.
With `turbo query`, you can find all the packages and the reason why they were invalidated:

```bash title="Terminal"
> turbo query "query { affectedPackages(base: \"HEAD^\", head: \"HEAD\") { items { reason {  __typename } } } }"
{
  "data": {
    "affectedPackages": {
      "items": [
        {
          "name": "utils",
          "reason": {
            "__typename": "FileChanged"
          }
        },
        {
          "name": "web",
          "reason": {
            "__typename": "DependencyChanged"
          }
        },
        {
          "name": "docs",
          "reason": {
            "__typename": "DependencyChanged"
          }
        },
        {
          "name": "cli",
          "reason": {
            "__typename": "DependencyChanged"
          }
        },
      ]
    }
  }
}
```

---

### Apps Docs Content Docs Crafting Your Repository Upgrading (`apps/docs/content/docs/crafting-your-repository/upgrading.mdx`)

---
title: Upgrading
description: Learn how to upgrade `turbo` to get the latest improvements to your repository.
product: turborepo
type: guide
summary: Migrate from Turborepo 1.x to 2.0 using codemods and handle breaking changes.
related:
  - /docs/reference/turbo-codemod
  - /docs/reference/configuration
---

## Upgrading to 2.0

<Steps>
<Step>

### Update `turbo.json`

Get started upgrading from 1.x to 2.0 by running:

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
pnpm dlx @turbo/codemod migrate
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
yarn dlx @turbo/codemod migrate
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
npx @turbo/codemod migrate
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
bunx @turbo/codemod migrate
```

</Tab>


<Tab value="nub">

```bash title="Terminal"
nubx @turbo/codemod migrate
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
aubx @turbo/codemod migrate
```

</Tab>

</PackageManagerTabs>

This will update your `turbo.json`(s) for many of the breaking changes from 1.x to 2.0.

Additionally, a `name` field will be added to any `package.json` in the Workspace that doesn't have one.

<Callout type="info">
  You may also manually run each codemod individually. Visit [the codemods
  page](/docs/reference/turbo-codemod#turborepo-2x) for more information.
</Callout>

</Step>

<Step>

### Add `devEngines.packageManager` to root `package.json`

The `devEngines.packageManager` field declares which package manager is expected to be used in the Workspace. The legacy top-level [`packageManager`](https://nodejs.org/api/packages.html#packagemanager) field is also supported for backwards compatibility.

Turborepo 2.0 requires that your Workspace define a package manager declaration as a way to improve the stability and behavioral predictability of your codebase. If you do not have one already, add this field to your root `package.json`:

<PackageManagerTabs>

<Tab value="pnpm">

```diff title="./package.json"
{
+ "devEngines": {
+   "packageManager": {
+     "name": "pnpm",
+     "version": "9.2.0"
+   }
+ }
}
```

</Tab>

<Tab value="yarn">

```diff title="./package.json"
{
+ "devEngines": {
+   "packageManager": {
+     "name": "yarn",
+     "version": "1.22.19"
+   }
+ }
}
```

</Tab>

<Tab value="npm">

```diff title="./package.json"
{
+ "devEngines": {
+   "packageManager": {
+     "name": "npm",
+     "version": "10.8.1"
+   }
+ }
}
```

</Tab>

<Tab value="bun">

```diff title="./package.json"
{
+ "devEngines": {
+   "packageManager": {
+     "name": "bun",
+     "version": "1.2.0"
+   }
+ }
}
```

</Tab>

<Tab value="nub">

```diff title="./package.json"
{
+ "devEngines": {
+   "packageManager": {
+     "name": "nub",
+     "version": "0.8.3"
+   }
+ }
}
```

</Tab>

<Tab value="aube">

```diff title="./package.json"
{
+ "devEngines": {
+   "packageManager": {
+     "name": "aube",
+     "version": "2.2.9"
+   }
+ }
}
```

</Tab>

</PackageManagerTabs>

</Step>
<Step>

### Update `eslint-config-turbo`

[`eslint-config-turbo`](/docs/reference/eslint-config-turbo) helps identify environment variables that need to be added to the [`env`](/docs/reference/configuration#env) key for caching. If you're using it, make sure you update it to match your major version.

</Step>

<Step>

### Update `turbo run` commands

Turborepo 2.0 includes behavioral and correctness improvements with behavior of `turbo run` commands. Listed below is the summary of changes, which may or may not have an affect on your codebase:

- Strict Mode for environment variables is now the default, moving from Loose Mode ([PR](https://github.com/vercel/turborepo/pull/8182))
  - If it appears that the scripts in your tasks are missing environment variables, you can opt back out of this behavior using [the `--env-mode` option](/docs/reference/run#--env-mode-option) on a per-command basis to incrementally migrate. We encourage you to update [the `env` key](/docs/reference/configuration#env) in your task to account for all of its environment variables so you can drop the `--env-mode` option as soon as possible.
  - If you'd like to set the default for the repository back to Loose Mode, you can do so [using the `envMode` configuration](/docs/reference/configuration#envmode).
- Workspace root directory is now an implicit dependency of all packages ([PR](https://github.com/vercel/turborepo/pull/8202))
  - The repository should have as little code in the root as possible, since changes to the root can affect all tasks in your repository. Additionally, if you're using [Internal Packages](/docs/core-concepts/internal-packages) in the Workspace root, changes to those dependencies will also cause cache misses for all tasks. In both cases, consider moving the code out of the root and [into a package](/docs/crafting-your-repository/structuring-a-repository).
- `--ignore` removed in favor of `--filter` and graph correctness changes below ([PR](https://github.com/vercel/turborepo/pull/8201))
- Removed `--scope` flag (deprecated since 1.2) ([PR](https://github.com/vercel/turborepo/pull/7970))
- `engines` field in root `package.json` is now used in hashing ([PR](https://github.com/vercel/turborepo/pull/8173))
- `--filter` no longer infers namespaces for package names ([PR](https://github.com/vercel/turborepo/pull/8137))
- `--filter` now errors when no package names or directories are matched ([PR](https://github.com/vercel/turborepo/pull/8142))
- `--only` restricts task dependencies instead of package dependencies ([PR](https://github.com/vercel/turborepo/pull/8163))

</Step>
</Steps>

---

### Apps Docs Content Docs Crafting Your Repository Using Environment Variables (`apps/docs/content/docs/crafting-your-repository/using-environment-variables.mdx`)

---
title: Using environment variables
description: Learn how to handle environments for your applications.
product: turborepo
type: guide
summary: Account for environment variables in task hashing, configure environment modes, and handle .env files.
prerequisites:
  - /docs/crafting-your-repository/developing-applications
related:
  - /docs/crafting-your-repository/caching
  - /docs/crafting-your-repository/constructing-ci
  - /docs/reference/configuration
---

Environment variable inputs are a vital part of your applications that you'll need to account for in your Turborepo configuration.

There are three important questions when working with environment variables in Turborepo:

- [Are my environment variables accounted for in the task hash?](#adding-environment-variables-to-task-hashes)
- [Which Environment Mode will `turbo` use?](#environment-modes)
- [Have I handled my `.env` files?](#handling-env-files)

<Callout type="error">
  Failing to account for environment variables in your configuration can result
  in shipping your application with the wrong configuration. This can cause
  serious issues like shipping your preview deployments to production.
</Callout>

<Callout type="info">
  Turborepo also uses [System Environment
  Variables](/docs/reference/system-environment-variables) to configure its own
  behavior. Below, you'll find information about environment variables for your
  task's runtime and how they affect task hashing.
</Callout>

## Adding environment variables to task hashes

Turborepo needs to be aware of your environment variables to account for changes in application behavior. To do this, use the `env` and `globalEnv` keys in your `turbo.json` file.

```json title="./turbo.json"
{
  "globalEnv": ["IMPORTANT_GLOBAL_VARIABLE"],
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"]
    }
  }
}
```

- **globalEnv**: Changes to the values of any environment variables in this list will change the hash for all tasks.
- **env**: Includes changes to the values of environment variables that affect the task, allowing for better granularity. For example, a `lint` task probably doesn't need to miss cache when the value of `API_KEY` changes, but a `build` task likely should.

<Callout type="info">
  Turborepo supports wildcards for environment variables so you can easily
  account for all environment variables with a given prefix. Visit [the API
  reference for `env`](/docs/reference/configuration#wildcards) for more.
</Callout>

### Framework Inference

Turborepo automatically adds prefix wildcards to your [`env`](/docs/reference/configuration#env) key for common frameworks. If you're using one of the frameworks below in a package, you don't need to specify environment variables with these prefixes:

| Framework        | `env` wildcards        |
| ---------------- | ---------------------- |
| Next.js          | `NEXT_PUBLIC_*`        |
| Vite             | `VITE_*`               |
| Create React App | `REACT_APP_*`          |
| Gatsby           | `GATSBY_*`             |
| Nuxt             | `NUXT_*`, `NUXT_ENV_*` |
| Expo             | `EXPO_PUBLIC_*`        |
| Astro            | `PUBLIC_*`             |
| SvelteKit        | `PUBLIC_*`             |
| Remix            | `REMIX_*`              |
| SolidStart       | `VITE_*`               |
| RedwoodJS        | `REDWOOD_ENV_*`        |
| Sanity           | `SANITY_STUDIO_*`      |

<Callout type="info">Framework inference is per-package.</Callout>

If you'd like to opt out of Framework Inference, you can do so by:

- Running your tasks with `--framework-inference=false`
- Adding a negative wildcard to the `env` key (for example, `"env": ["!NEXT_PUBLIC_*"]`)

## Environment Modes

Turborepo's Environment Modes allow you to control which environment variables are available to a task at runtime:

- [Strict Mode](#strict-mode) (Default): Filter environment variables to **only** those that are specified in the `env` and `globalEnv` keys in `turbo.json`.
- [Loose Mode](#loose-mode): Allow all environment variables for the process to be available.

### Strict Mode

Strict Mode filters the environment variables available to a task's runtime to **only** those that are specified in the `globalEnv` and `env` keys in `turbo.json`.

This means that tasks that do not account for all of the environment variables that they need are likely to fail. This is a good thing, since you don't want to cache a task that can potentially have different behavior in a different environment.

<Callout type="warn" title="Cache safety with Strict Mode">
  While Strict Mode makes it much more likely for your task to fail when you
  haven't accounted for all of your environment variables, it doesn't guarantee
  task failure. If your application is able to gracefully handle a missing
  environment variable, you could still successfully complete tasks and get
  unintended cache hits.
</Callout>

#### Passthrough variables

In advanced use cases, you may want to make some environment variables
available to a task without including them in the hash. Changes to these variables don't affect task outputs but still need to be available for the task to run successfully.

For these cases, add those environment variables to [`globalPassThroughEnv`](/docs/reference/configuration#globalpassthroughenv) and [`passThroughEnv`](/docs/reference/configuration#passthroughenv).

#### CI vendor compatibility

Strict Mode will filter out environment variables that come from your CI vendors until you've accounted for them using [`env`](/docs/reference/configuration#env), [`globalEnv`](/docs/reference/configuration#globalenv), [`passThroughEnv`](/docs/reference/configuration#passthroughenv), or [`globalPassThroughEnv`](/docs/reference/configuration#globalpassthroughenv).

If any of these variables are important to your tasks and aren't included by [Framework Inference](#framework-inference), make sure they are in your `turbo.json` configuration.

### Loose Mode

Loose Mode does not filter your environment variables according to your `globalEnv` and `env` keys. This makes it easier to get started with incrementally migrating to Strict Mode.

Use [the `--env-mode` flag](/docs/reference/run#--env-mode-option) to enable Loose Mode on any invocation where you're seeing environment variables cannot be found by your scripts:

```bash title="Terminal"
turbo run build --env-mode=loose
```

As long as the environment variable is available when `turbo` is ran, your script will be able to use it. However, this also **lets you accidentally forget to account for an environment variable in your configuration much more easily**, allowing the task to hit cache when it shouldn't.

For example, you may have some code in your application that fetches data from an API, using an environment variable for the base URL:

```ts title="./apps/web/data-fetcher.ts"
const data = fetch(`${process.env.MY_API_URL}/resource/1`);
```

You then build your application using a value for `MY_API_URL` that targets your preview environment. When you're ready to ship your application, you build for production and see a cache hit - even though the value of the `MY_API_URL` variable has changed! `MY_API_URL` changed - but Turborepo restored a version of your application from cache that uses the preview environment's `MY_API_URL` rather than production's.

When you're using Loose Mode, `MY_API_URL` is available in the task runtime **even though it isn't accounted for in the task hash**. To make this task more likely to fail and protect you from this misconfiguration, we encourage you to opt for [Strict Mode](#strict-mode).

### Platform Environment Variables

When deploying your application to [Vercel](https://vercel.com/new?ref=turborepo), you likely already have [environment variables](https://vercel.com/docs/environment-variables) configured on your project. Turborepo will automatically check these variables against your `turbo.json` configuration to ensure that you've [accounted for them](#adding-environment-variables-to-task-hashes),
and will warn you about any missing variables.

This functionality can be disabled by setting `TURBO_PLATFORM_ENV_DISABLED=true`

## Handling `.env` files

`.env` files are great for working on an application locally. **Turborepo does not load .env files into your task's runtime**, leaving them to be handled by your framework, or tools like [`dotenv`](https://www.npmjs.com/package/dotenv).

However, it's important that `turbo` knows about changes to values in your `.env` files so that it can use them for hashing. If you change a variable in your `.env` files between builds, the `build` task should miss cache.

To do this, add the files to the [`inputs`](/docs/reference/configuration#inputs) key:

```json title="./turbo.json"
{
  "globalDependencies": [".env"], // All task hashes
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", ".env"] // Only the `build` task hash
    }
  }
}
```

### Multiple `.env` files

You can capture multiple `.env` files at once using a `*`.

```json title="./turbo.json"
{
  "globalDependencies": [".env"], // All task hashes
  "tasks": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", ".env*"] // Only the `build` task hash
    }
  }
}
```

<Callout type="info">
  `.env` files can load variables into the task runtime even when the
  environment variables have not been added to [the `env`
  key](/docs/reference/configuration#env). Ensure that you add your environment
  variables for your builds the `env` key for CI and production builds.
</Callout>

## Best practices

### Environment variables from dependencies

When an application consumes a package that relies on environment variables, those variables must be accounted for in your `turbo.json` to ensure cache correctness.

For example, if an app called `docs` depends on a package `common`, there are two scenarios for handling environment variables:

1. **The application depends on the package's task**
   If the `docs` app's `build` task depends on the `common` package's `build` task (e.g., `"dependsOn": ["^build"]`), and `common` declares an environment variable in its own `turbo.json`, Turborepo handles this automatically. Changing the environment variable will cause `common` to miss the cache and rebuild, which in turn causes `docs` to rebuild because of the dependency relationship.

2. **The application imports the package directly without a build step**
   If the `common` package does not have a build step, but exposes variables that the `docs` app uses at build time (like `process.env.MY_VAR`), the `docs` application _must_ declare the environment variable directly in its own `env` or `globalEnv` key in its `turbo.json`.

```json title="./apps/docs/turbo.json"
{
  "tasks": {
    "build": {
      "env": ["MY_VAR"]
    }
  }
}
```

### Use `.env` files in Application Packages

Using a `.env` file at the root of the repository is not recommended. Instead, we recommend placing your `.env` files into the [Application Packages](/docs/core-concepts/package-types#application-packages) where they're used.

This practice more closely models the runtime behavior of your applications since environment variables exist in each application's runtime individually. Additionally, as your monorepo scales, this practice makes it easier to manage each application's environment, preventing environment variable leakage across applications.

<Callout type="info">
  You may find it easier to use a root `.env` file when incrementally migrating
  to a monorepo. Tools like [dotenv](https://www.npmjs.com/package/dotenv) can
  load `.env` files from different locations. We encourage making a goal of not
  using a root `.env` file after completing your migration.
</Callout>

### Use `eslint-config-turbo`

[The `eslint-config-turbo` package](/docs/reference/eslint-config-turbo) helps you find environment variables that are used in your code that aren't listed in your `turbo.json`. This helps ensure that all your environment variables are accounted for in your configuration.

### Avoid creating or mutating environment variables at runtime

Turborepo hashes the environment variables for your task at the beginning of the task. If you create or mutate environment variables during the task, Turborepo will not know about these changes and will not account for them in the task hash.

For instance, Turborepo will not be able to detect the inline variable in the example below:

```json title="./apps/web/package.json"
{
  "scripts": {
    "dev": "export MY_VARIABLE=123 && next dev"
  }
}
```

`MY_VARIABLE` is being added to the environment _after_ the `dev` task has started, so `turbo` will not be able to use it for hashing.

## Examples

Below are examples of proper environment variable configuration for a few popular frameworks:

<Accordions>
<Accordion title="Next.js">

The `turbo.json` below expresses:

- The `build` and `dev` tasks will have different hashes for changes to `MY_API_URL` and `MY_API_KEY`.
- The `build` and `dev` tasks include the supported .env files for Next.js.
- The `test` task does not use environment variables, so the `env` key is omitted. (Depending on your testing structure, your `test` task may need an `env` key.)

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"],
      "inputs": [
        "$TURBO_DEFAULT$",
        ".env.production.local",
        ".env.local",
        ".env.production",
        ".env"
      ]
    },
    "dev": {
      "inputs": [
        "$TURBO_DEFAULT$",
        ".env.development.local",
        ".env.local",
        ".env.development",
        ".env"
      ]
    },
    "test": {}
  }
}
```

</Accordion>
<Accordion title="Vite">
The `turbo.json` below expresses:
- The `build` and `dev` tasks will have different hashes for changes to `MY_API_URL` and `MY_API_KEY`.
- The `build` and `dev` tasks include the supported .env files for Vite.
- The `test` task does not use environment variables, so the `env` key is omitted. (Depending on your testing structure, your `test` task may need an `env` key.)

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "env": ["MY_API_URL", "MY_API_KEY"],
      "inputs": [
        "$TURBO_DEFAULT$",
        ".env.production.local",
        ".env.local",
        ".env.production",
        ".env"
      ]
    },
    "dev": {
      "inputs": [
        "$TURBO_DEFAULT$",
        ".env.development.local",
        ".env.local",
        ".env.development",
        ".env"
      ]
    },
    "test": {}
  }
}
```

</Accordion>
</Accordions>

## Troubleshooting

### Use `--summarize`

[The `--summarize` flag](/docs/reference/run#--summarize) can be added to your `turbo run` command to produce a JSON file summarizing data about your task. Checking the diff for the `globalEnv` and `env` key can help you identify any environment variables that may be missing from your configuration.

## Next steps

Once you've accounted for your environment variables, you're ready to start building the CI pipelines that build, check, and deploy your applications, at the speed of `turbo`.

---

### Apps Docs Content Docs Getting Started Add To Existing Repository (`apps/docs/content/docs/getting-started/add-to-existing-repository.mdx`)

---
title: Add to an existing repository
description: Using Turborepo with your existing repository
product: turborepo
type: guide
summary: Incrementally adopt Turborepo in an existing single-package or multi-package repository.
prerequisites:
  - /docs/getting-started
  - /docs/getting-started/installation
related:
  - /docs/crafting-your-repository/structuring-a-repository
  - /docs/crafting-your-repository/caching
  - /docs/guides/single-package-workspaces
---

Turborepo can be incrementally adopted in **any repository, single or multi-package**, to speed up the developer and CI workflows of the repository.

After installing `turbo` and configuring your tasks in `turbo.json`, you'll notice how [caching](/docs/crafting-your-repository/caching) helps you run tasks much faster.

## Preparing a single-package workspace

A [single-package workspace](https://vercel.com/docs/glossary#single-package-workspace) is, for example, what you get after running `npx create-next-app` or `npm create vite`. You don't need to do any extra work for Turborepo to handle your repo so you can jump to the first step below.

To learn more about Turborepo in single-package workspaces, visit [the dedicated guide](/docs/guides/single-package-workspaces).

## Preparing a multi-package workspace (monorepo)

`turbo` is built on top of Workspaces, a feature of the major package managers in the JavaScript ecosystem. This makes it easy to adopt in your existing codebase.

<Callout type="info">
  If you're finding that `turbo` is having issues like not being able to
  discover packages in your workspace or not following your dependency graph,
  visit our [Structuring a
  repository](/docs/crafting-your-repository/structuring-a-repository) page for
  tips.
</Callout>

Note that you don't have to start running _all_ your tasks for _all_ your
packages using `turbo` right away. You can start with a single task in just a
few packages and incrementally add more tasks and packages as you get more
familiar with Turborepo.

## Adding Turborepo to your repository

<Steps>
<Step>
### Install `turbo`

Install `turbo` globally.

<Tabs items={["macOS and Linux", "Windows x64"]}>
  <Tab value="macOS and Linux">

```sh title="Terminal"
curl -fsSL https://turborepo.dev/install | sh
```

  </Tab>
  <Tab value="Windows x64">

```powershell title="PowerShell"
irm https://turborepo.dev/install.ps1 | iex
```

  </Tab>
</Tabs>

<Callout type="info">
  The binaries are also available in the [GitHub release assets](https://github.com/vercel/turborepo/releases).
</Callout>

Then pin `turbo` in your repository's root:

<PackageManagerTabs>
  <Tab value="pnpm">
      Ensure you have created a `pnpm-workspace.yaml` file before you begin the installation. Failure to have this file will result in an error that says: ` --workspace-root may only be used inside a workspace`.

    ```bash title="Terminal"
    pnpm add turbo --save-dev --workspace-root
    ```

  </Tab>
  <Tab value="yarn">

    ```bash title="Terminal"
    yarn add turbo --dev
    ```

  </Tab>
  <Tab value="npm">

    ```bash title="Terminal"
    npm install turbo --save-dev
    ```

  </Tab>
  <Tab value="bun">

    ```bash title="Terminal"
    bun install turbo --dev
    ```

  </Tab>

<Tab value="nub">

    ```bash title="Terminal"
    nub add turbo --save-dev
    ```

  </Tab>

<Tab value="aube">

    ```bash title="Terminal"
    aube add turbo --save-dev
    ```

  </Tab>

</PackageManagerTabs>

The installed local version takes precedence when you run the global binary in your repository. See [Installation](/docs/getting-started/installation#repository-installation) for details.

</Step>
<Step>

### Add a `turbo.json` file

In the root of your repository, create a `turbo.json` file.

We'll be using `build` and `check-types` tasks in this guide but you can replace these with other tasks that interest you, like `lint` or `test`.

<Tabs items={['Next.js', 'Vite']} storageKey="framework-preference">
  <Tab value="Next.js">
```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "!.next/dev/**"]
    },
    "check-types": {
      "dependsOn": ["^check-types"]
    },
    "dev": {
      "persistent": true,
      "cache": false
    }
  }
}
```

For more information on configuring your `turbo.json`, see the [Configuration Options](/docs/reference/configuration) documentation.

In your Next.js application, make sure you have a `check-types` script for `turbo` to run.

```diff title="apps/web/package.json"
{
  "scripts": {
+   "check-types": "tsc --noEmit"
  }
}
```

  </Tab>
  <Tab value="Vite">
```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "build": {
      "outputs": ["dist/**"]
    },
    "check-types": {
      "dependsOn": ["^check-types"]
    },
    "dev": {
      "persistent": true,
      "cache": false
    }
  }
}
```

Some Vite starters ship with a `package.json` that looks like this:

```json title="package.json"
{
  "scripts": {
    "build": "tsc && vite build"
  }
}
```

We recommend splitting these into a `check-types` and `build` script so that `turbo` can run them in parallel.

```json title="apps/web/package.json"
{
  "scripts": {
    "build": "vite build",
    "check-types": "tsc --noEmit"
  }
}
```

  </Tab>
</Tabs>

In a multi-package workspace, you may also want to add a `check-types` script
to one or more of your library packages to see how multiple scripts across
different packages run with one `turbo` command.

</Step>
<Step>
### Edit `.gitignore`

Add `.turbo` to your `.gitignore` file. The `turbo` CLI uses these folders for persisting logs, outputs, and other functionality.

```diff title=".gitignore"
+ .turbo
```

</Step>
<Step>
### Add `devEngines.packageManager` to root `package.json`

Turborepo optimizes your repository using information from your package manager. To declare which package manager you're using, add `devEngines.packageManager` to your root `package.json` if you don't have a package manager declaration already. The legacy top-level [`packageManager`](https://nodejs.org/api/packages.html#packagemanager) field is also supported.

<PackageManagerTabs>

<Tab value="pnpm">

```diff title="package.json"
{
+  "devEngines": {
+    "packageManager": {
+      "name": "pnpm",
+      "version": "10.0.0"
+    }
+  }
}
```

</Tab>

<Tab value="yarn">

```diff title="package.json"
{
+  "devEngines": {
+    "packageManager": {
+      "name": "yarn",
+      "version": "1.22.19"
+    }
+  }
}
```

</Tab>

<Tab value="npm">

```diff title="package.json"
{
+  "devEngines": {
+    "packageManager": {
+      "name": "npm",
+      "version": "8.5.0"
+    }
+  }
}
```

</Tab>

<Tab value="bun">

```diff title="package.json"
{
+  "devEngines": {
+    "packageManager": {
+      "name": "bun",
+      "version": "1.2.0"
+    }
+  }
}
```

</Tab>


<Tab value="nub">

```diff title="package.json"
{
+  "devEngines": {
+    "packageManager": {
+      "name": "nub",
+      "version": "0.8.3"
+    }
+  }
}
```

</Tab>

<Tab value="aube">

```diff title="package.json"
{
+  "devEngines": {
+    "packageManager": {
+      "name": "aube",
+      "version": "2.2.9"
+    }
+  }
}
```

</Tab>

</PackageManagerTabs>

<Callout type="info">
  Depending on your repository, you may need to use the
  [`dangerouslyDisablePackageManagerCheck`](/docs/reference/configuration#dangerouslydisablepackagemanagercheck)
  while migrating or in situations where you can't use a package manager
  declaration yet.
</Callout>

</Step>
<Step>
### Set up package manager workspaces

For [multi-package workspaces](https://vercel.com/docs/glossary#multi-package-workspace), you'll need to configure your package manager to recognize your workspace structure.

The `workspaces` field tells your package manager which directories contain your packages. Common patterns include `apps/*` for applications and `packages/*` for shared libraries.

<Callout type="info">
  If you're working with a single-package repository, you can skip this step as
  workspaces aren't needed.
</Callout>

<PackageManagerTabs>

  <Tab value="pnpm">
  ```json title="pnpm-workspace.yaml"
 packages:
    - "apps/*"
    - "packages/*"
  ```
  <LinkToDocumentation href="https://pnpm.io/pnpm-workspace_yaml" text="pnpm workspace documentation" />

  </Tab>

  <Tab value="yarn">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://yarnpkg.com/features/workspaces#how-are-workspaces-declared" text="yarn workspace documentation" />
   </Tab>

  <Tab value="npm">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://docs.npmjs.com/cli/v7/using-npm/workspaces#defining-workspaces" text="npm workspace documentation" />
  </Tab>

  <Tab value="bun">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://bun.sh/docs/install/workspaces" text="bun workspace documentation" />
  </Tab>


<Tab value="nub">
  ```json title="./package.json"
  {
    "workspaces": [
      "apps/*",
      "packages/*"
    ]
  }
  ```

  <LinkToDocumentation href="https://nub.dev" text="nub documentation" />
  </Tab>

<Tab value="aube">

```yaml title="aube-workspace.yaml"
packages:
  - "apps/*"
  - "packages/*"
```

  <LinkToDocumentation href="https://aube.jdx.dev" text="aube workspace documentation" />
  </Tab>

</PackageManagerTabs>

For more details on how to structure your repository, see [Structuring a Repository](/docs/crafting-your-repository/structuring-a-repository#declaring-directories-for-packages).

</Step>
<Step>
### Run tasks with `turbo`

You can now run the tasks you added to `turbo.json` earlier using Turborepo. Using the example tasks from above:

```bash title="Terminal"
turbo build check-types
```

This runs the `build` and `check-types` tasks at the same time. The dependency graph of your [Workspace](/docs/crafting-your-repository/structuring-a-repository#anatomy-of-a-workspace) will be used to run tasks in the right order.

</Step>
<Step>
**Without making any changes to the code, try running `build` and `check-types` again:**

```bash title="Terminal"
turbo check-types build
```

You should see terminal output like this:

```bash title="Terminal"
Tasks:    2 successful, 2 total
Cached:    2 cached, 2 total
Time:    185ms >>> FULL TURBO
```

Congratulations! **You just built and type checked your code in milliseconds**.

To learn more about how `turbo` makes this possible, check out [the caching documentation](/docs/crafting-your-repository/caching).

</Step>
<Step>

### Begin developing by running `dev` with `turbo`

In a multi-package workspace, you can run `turbo dev` to start the development tasks for all your packages at once.

```bash title="Terminal"
turbo dev
```

You can also [use a filter](/docs/crafting-your-repository/running-tasks#using-filters) to focus on a specific package and its dependencies.

<Callout type="info">
Note that this step doesn't provide much value in a single-package workspace since:

- You don't cache the outputs for a development task.
- There's only one development script so there's nothing to run in parallel.

</Callout>

</Step>

<Step>

## Next steps

You're now up and running with Turborepo! To learn about more ways you can improve your workflow and get the most out of `turbo`, we recommend checking out the following pages:

- [Enabling Remote Caching for development machines](/docs/crafting-your-repository/constructing-ci#enabling-remote-caching)
- [Enabling Remote Caching in CI](/docs/crafting-your-repository/constructing-ci)
- [Handling environment variables](/docs/crafting-your-repository/using-environment-variables)
- [Filtering tasks](/docs/reference/run#--filter-string)

</Step>
</Steps>

---

### Apps Docs Content Docs Getting Started Editor Integration (`apps/docs/content/docs/getting-started/editor-integration.mdx`)

---
title: Editor integration
description: Making the most of Turborepo
product: turborepo
type: guide
summary: Set up JSON Schema validation, ESLint integration, and the Turborepo LSP in your editor.
prerequisites:
  - /docs/getting-started/installation
related:
  - /docs/reference/configuration
  - /docs/reference/eslint-config-turbo
---

To get the best experience with `turbo`, Turborepo provides a few utilities for integrating with your editor.

## JSON Schema for `turbo.json`

Turborepo uses [JSON Schema](https://json-schema.org/) to give you auto-complete in your
`turbo.json` files. By including the `$schema` key in your `turbo.json`, your editor is able to
provide full documentation and linting for invalid configuration.

### Sourcing from web

Starting with Turborepo 2.5.7, versioned schemas are available via subdomain, following the format `https://v<version>.turborepo.dev/schema.json`. The version uses a dash separator.

```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json"
}
```

This has the advantage of not needing to run your package manager's install command to see in-editor validation, while also ensuring you're using the schema that matches your installed version of `turbo`.

<Callout type="info" title="Unversioned schema">
  If you're using a version of Turborepo older than 2.5.7 or prefer an
  unversioned schema, you can use `https://turborepo.dev/schema.json` instead.
</Callout>

### Sourcing from `node_modules`

Starting in Turborepo 2.4, `schema.json` is available in `node_modules` once you've run your package manager's install command:

```json title="turbo.json"
{
  "$schema": "./node_modules/turbo/schema.json"
}
```

<Callout type="info" title="node_modules location">
  We recommend installing `turbo` at the root of your repository, so the path
  for the schema should point to `node_modules` at the root of your repository.
  In [Package Configurations](/docs/reference/package-configurations), you may
  need to use a path like `../../node_modules/turbo/schema.json`.
</Callout>

## Linting for environment variables

Handling environment variables is an important part of building applications in a Turborepo.

[The `eslint-config-turbo` package](/docs/reference/eslint-config-turbo) extends your ESLint setup to help you make sure you've taken care of all of your environment variables.

## Turborepo LSP

Enable even more auto-complete and linting than provided by JSON Schema, with in-editor hinting for invalid globs, references to non-existent tasks or packages, and
extra repository visibility tools.

Visit the [VSCode Extension Marketplace](https://marketplace.visualstudio.com/items?itemName=Vercel.turbo-vsc) to install.

<Callout type="info" title="Not using Visual Studio Code?">
  The language server can be used on any editors that support the [Language
  Server Protocol](https://microsoft.github.io/language-server-protocol/). Log a
  request in our [issue tracker](https://github.com/vercel/turborepo/issues) to
  express your interest.
</Callout>

---

### Apps Docs Content Docs Getting Started Examples (`apps/docs/content/docs/getting-started/examples.mdx`)

---
title: Start with an example
description: Start with an example Turborepo.
product: turborepo
type: overview
summary: Browse core-maintained and community examples to bootstrap a Turborepo with your favorite tools.
prerequisites:
  - /docs/getting-started
related:
  - /docs/getting-started/installation
  - /docs/getting-started/add-to-existing-repository
---

Use `create-turbo` to bootstrap an example with your favorite tooling.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
# Use an example listed below
pnpm dlx create-turbo@latest --example [example-name]

# Use a GitHub repository from the community
pnpm dlx create-turbo@latest --example [github-url]
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
# Use an example listed below
yarn dlx create-turbo@latest --example [example-name]

# Use a GitHub repository from the community
yarn dlx create-turbo@latest --example [github-url]
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
# Use an example listed below
npx create-turbo@latest --example [example-name]

# Use a GitHub repository from the community
npx create-turbo@latest --example [github-url]
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
# Use an example listed below
bunx create-turbo@latest --example [example-name]

# Use a GitHub repository from the community
bunx create-turbo@latest --example [github-url]
```

</Tab>


<Tab value="nub">

```bash title="Terminal"
# Use an example listed below
nubx create-turbo@latest --example [example-name]

# Use a GitHub repository from the community
nubx create-turbo@latest --example [github-url]
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
# Use an example listed below
aubx create-turbo@latest --example [example-name]

# Use a GitHub repository from the community
aubx create-turbo@latest --example [github-url]
```

</Tab>

</PackageManagerTabs>

## Core-maintained examples

The following examples are maintained by the Turborepo core team. Dependencies are kept as up-to-date as possible and GitHub Issues are accepted and addressed for these examples.

<ExamplesTable coreMaintained />

## Community-maintained examples

The community curates a set of examples to showcase ways to use common tools and libraries with Turborepo. To bootstrap your monorepo with one of the examples, use the `--example` flag:

<Callout type="info">
  GitHub Issues for these examples will be closed. If you find problems, please
  submit a pull request with fixes.
</Callout>

<ExamplesTable />

---

### Apps Docs Content Docs Getting Started Installation (`apps/docs/content/docs/getting-started/installation.mdx`)

---
title: Installation
description: Learn how to get started with Turborepo.
product: turborepo
type: guide
summary: Install Turborepo globally and in your repository.
prerequisites:
  - /docs/getting-started
related:
  - /docs/getting-started/add-to-existing-repository
  - /docs/getting-started/examples
---

Get started with Turborepo in a few moments using:

<PackageManagerTabs>

<Tab value="pnpm">
```bash title="Terminal"
pnpm dlx create-turbo@latest
```

</Tab>

<Tab value="yarn">
```bash title="Terminal"
yarn dlx create-turbo@latest
```

</Tab>

<Tab value="npm">
```bash title="Terminal"
npx create-turbo@latest
```

</Tab>

<Tab value="bun">
```bash title="Terminal"
bunx create-turbo@latest
```

</Tab>


<Tab value="nub">
```bash title="Terminal"
nubx create-turbo@latest
```

</Tab>

<Tab value="aube">
```bash title="Terminal"
aubx create-turbo@latest
```

</Tab>

</PackageManagerTabs>

The starter repository will have:

- Two deployable applications
- Three shared libraries for use in the rest of the monorepo

For more details on the starter, [visit the README for the basic starter on GitHub](https://github.com/vercel/turborepo/tree/main/examples/basic). You can also [use an example](/docs/getting-started/examples) that more closely fits your tooling interests.

## Installing `turbo`

You can install `turbo` globally and pin a version in your repository. When a local binary is installed, the global binary defers to it.

### Global installation

A global install of `turbo` brings flexibility and speed to your local workflows.

<Tabs items={["macOS and Linux", "Windows x64"]}>
  <Tab value="macOS and Linux">

```sh title="Terminal"
curl -fsSL https://turborepo.dev/install | sh
```

  </Tab>
  <Tab value="Windows x64">

```powershell title="PowerShell"
irm https://turborepo.dev/install.ps1 | iex
```

  </Tab>
</Tabs>

<Callout type="info">
  See the [support policy](/docs/support-policy#platforms) for supported platforms.
</Callout>

<Callout type="info">
  The binaries are also available directly in the [GitHub release assets](https://github.com/vercel/turborepo/releases), starting with 2.11.5. To install an older version, use your package manager.
</Callout>

After installing `turbo`, you can run commands from your terminal. For example:

- `turbo build`: Run `build` scripts following your repository's dependency graph
- `turbo build --filter=docs --dry`: Quickly print an outline of the `build` task for your `docs` package (without running it)
- `turbo generate`: Run [Generators](/docs/guides/generating-code) to add new code to your repository
- `cd apps/docs && turbo build`: Run the `build` script in the `docs` package and its dependencies. For more, visit the [Automatic Package Scoping section](/docs/crafting-your-repository/running-tasks#automatic-package-scoping).

<Callout type="info">
  `turbo` is an alias for [`turbo run`](/docs/reference/run). For example,
  `turbo build` and `turbo run build` will both run your `build` task.
</Callout>

#### Using global `turbo` in CI

To use the global binary in CI, see [Constructing CI](/docs/crafting-your-repository/constructing-ci#global-turbo-in-ci).

### Repository installation

To pin the `turbo` version used in a repository, add it as a `devDependency` at the root:

<PackageManagerTabs>

  <Tab value="pnpm">
    ```bash title="Terminal"
    pnpm add turbo --save-dev --ignore-workspace-root-check
    ```

  </Tab>

  <Tab value="yarn">
    ```bash title="Terminal"
    yarn add turbo --dev --ignore-workspace-root-check
    ```

  </Tab>

  <Tab value="npm">
  ```bash title="Terminal"
  npm install turbo --save-dev
  ```

  </Tab>

  <Tab value="bun">
  ```bash title="Terminal"
  bun install turbo --dev
  ```

  </Tab>

  
<Tab value="nub">
  ```bash title="Terminal"
  nub add turbo --save-dev
  ```

  </Tab>

<Tab value="aube">
  ```bash title="Terminal"
  aube add turbo --save-dev
  ```

  </Tab>

</PackageManagerTabs>

When you invoke the global binary from this repository, it uses the installed local version instead.

---

### Apps Docs Content Docs Guides Ai (`apps/docs/content/docs/guides/ai.mdx`)

---
title: Using AI with Turborepo
description: Get the most out of AI coding assistants in your Turborepo.
product: turborepo
type: guide
summary: Optimize your AI coding assistant workflows with Turborepo features like agent skills, task descriptions, and machine-readable docs.
related:
  - /docs/guides/generating-code
---

import { Callout } from "@/components/geistdocs/callout";

Turborepo is designed to work seamlessly with AI coding assistants. Turborepo provides features that help AI understand your repository and work more efficiently.

## Version-matched agent guidance

Turborepo configuration, task behavior, and CLI commands can vary between installed versions and may differ from an AI agent's training data. When `turbo` detects an AI coding agent, it maintains a managed block in the repository-root `AGENTS.md` that tells the agent to use documentation bundled with the installed package.

The block tells agents to resolve the `turbo` package from the repository or relevant workspace instead of assuming it is at the root `node_modules/turbo`. It points them to that package's `docs/README.md` first, then to the relevant pages under `docs/`. These bundled pages match the installed version and work without network access.

Turborepo creates `AGENTS.md` if needed and updates only its uniquely marked block, preserving existing project instructions and other tools' managed blocks. Set `"agentGuidance": true` in the root `turbo.json` or `turbo.jsonc` to opt in; this does not remove an existing block. Keep the generated block committed with your work to avoid an uncommitted change on a later agent invocation. New projects created from the default starter include it from the start.

## Agent Skill

[Agent Skills](https://agentskills.io) are an open standard that give new capabilities and expertise to agents. They're folders of instructions, scripts, and resources that agents can use to do things more accurately and efficiently.

You can add the Turborepo Skill to your agent, making it an expert in Turborepo and monorepos:

```bash title="Terminal"
npx skills add vercel/turborepo
```

The Skill teaches agents:

- Best practices for Turborepo configuration
- Monorepo patterns and conventions
- Anti-patterns to avoid
- Performance optimization techniques

## Git worktrees for parallel agents

When running multiple AI agents in parallel on the same repository, [Git worktrees](https://git-scm.com/docs/git-worktree) prevent conflicts by allowing each agent to work in its own directory while sharing Git history.

Turborepo automatically shares the local cache across worktrees, so agents benefit from each other's cached task results:

```bash title="Terminal"
# Agent 1 creates a cache
turbo run build

# Create a worktree for Agent 2
git branch feature-branch && git worktree add ../agent-2-worktree feature-branch

# Agent 2 gets a cache hit from Agent 1's work
cd ../agent-2-worktree && turbo run build
```

Combined with [Remote Caching](/docs/core-concepts/remote-caching), this enables fast feedback loops across multiple agents working simultaneously.

## Task descriptions

Add a `description` field to your task definitions in `turbo.json` to help AI tools understand what each task does:

```json title="turbo.json"
{
  "tasks": {
    "build": {
      "description": "Compiles TypeScript and bundles the application",
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "test": {
      "description": "Runs the test suite with coverage",
      "dependsOn": ["build"]
    },
    "lint": {
      "description": "Checks code style and catches common errors"
    }
  }
}
```

Descriptions help AI assistants:

- **Understand your repository**: AI can quickly grasp what each task does without reading implementation details
- **Make better suggestions**: With context about task purposes, AI can provide more relevant recommendations
- **Onboard faster**: New team members (human or AI) can understand your build system at a glance

## Searching documentation

The `turbo docs` command lets you search the Turborepo documentation directly from your terminal:

```bash title="Terminal"
turbo docs "package configurations"
```

Results link to versioned documentation matching your installed version of `turbo`, ensuring you get accurate information for your setup.

This is particularly useful when working with AI assistants that can execute shell commands. Instead of searching the web, you can get precise documentation links directly.

## Machine-readable documentation

Turborepo's documentation site is optimized for AI consumption in several ways:

### Markdown responses

When fetching documentation with appropriate headers, the site returns Markdown instead of HTML, preserving your AI's context window:

```bash title="Terminal"
curl -sL -H "Accept: text/markdown" https://turborepo.dev/docs
```

### Direct Markdown routes

Append `.md` to any documentation URL to get a Markdown version:

- `https://turborepo.dev/docs.md`
- `https://turborepo.dev/docs/crafting-your-repository/caching.md`

### Machine-readable sitemap

A sitemap is available at `https://turborepo.dev/sitemap.md`, allowing agents to discover what documentation exists.

### Versioned documentation

Documentation for specific Turborepo versions is available on subdomains. For example, the 2.7.6 documentation is at `https://v2-7-6.turborepo.dev/docs`.

This is useful when your AI needs to reference documentation matching your exact Turborepo version.

---

### Apps Docs Content Docs Guides Coordinating Runtime Dependencies (`apps/docs/content/docs/guides/coordinating-runtime-dependencies.mdx`)

---
title: Coordinating development runtime dependencies
description: Learn how to coordinate development services that depend on each other at runtime.
product: turborepo
type: guide
summary: Combine a readiness probe with `with` and `dependsOn` to coordinate runtime dependencies between development services.
prerequisites:
  - /docs/crafting-your-repository/developing-applications
related:
  - /docs/reference/configuration
  - /docs/reference/run
---

Some development tasks need another service to be available before they can start. For example, a frontend may need an API to be accepting requests before its development server starts.

<Callout type="info">
  This pattern is intended for coordinating services during local development. For CI and production, use the service orchestration and readiness capabilities provided by your CI provider or deployment platform.
</Callout>

Turborepo can coordinate this workflow by combining:

- [`with`](/docs/reference/configuration#with) to start the service alongside the task that needs it
- [`dependsOn`](/docs/reference/configuration#dependson) to wait for a finite readiness probe to succeed
- [`persistent`](/docs/reference/configuration#persistent) to mark the service as long-running

This guide configures packages named `web` and `api`, where the API's development server exposes a health endpoint at `http://localhost:3001/health`.

## Create a readiness probe

The readiness probe should retry until the service is available, exit successfully when it is ready, and fail after a timeout. Keep the readiness condition specific to your service so it can check everything the dependent task requires, such as a database connection or completed initialization.

```js title="./apps/api/scripts/wait-for-ready.mjs"
const healthUrl = "http://localhost:3001/health";
const deadline = Date.now() + 60_000;

while (Date.now() < deadline) {
  try {
    const response = await fetch(healthUrl, {
      signal: AbortSignal.timeout(1_000),
    });

    if (response.ok) {
      console.log(`API is ready at ${healthUrl}`);
      process.exit(0);
    }
  } catch {
    // The service may still be starting. Try again until the deadline.
  }

  await new Promise((resolve) => setTimeout(resolve, 500));
}

console.error(`API did not become ready at ${healthUrl} within 60 seconds`);
process.exit(1);
```

Add scripts for the long-running service and its finite readiness probe:

```json title="./apps/api/package.json"
{
  "name": "api",
  "scripts": {
    "dev": "node ./server.mjs",
    "dev:ready": "node ./scripts/wait-for-ready.mjs"
  }
}
```

The `api#dev:ready` script does not start the API. It only reports whether the API started by `api#dev` is ready.

The `web` application also needs a `dev` script:

```json title="./apps/web/package.json"
{
  "name": "web",
  "scripts": {
    "dev": "start-web"
  }
}
```

## Register the tasks

Register both task names in the root `turbo.json`. The readiness probe must not be cached because its result depends on the state of a running service rather than files in the repository.

```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "dev": {
      "cache": false,
      "persistent": true
    },
    "dev:ready": {
      "cache": false
    }
  }
}
```

Next, use a [Package Configuration](/docs/reference/package-configurations) to describe the `web` application's runtime requirements:

```json title="./apps/web/turbo.json"
{
  "extends": ["//"],
  "tasks": {
    "dev": {
      "with": ["api#dev"],
      "dependsOn": ["api#dev:ready"]
    }
  }
}
```

When `web#dev` is selected, Turborepo:

1. Adds the persistent `api#dev` task to the run because of `with`.
2. Starts `api#dev` and the non-persistent `api#dev:ready` probe.
3. Starts `web#dev` after the probe exits successfully.
4. Continues monitoring `api#dev` and `web#dev` until you stop Turborepo or either task exits.

Do not add `api#dev` to `dependsOn`. A persistent task does not exit, so it cannot complete and unblock a dependent task. The finite `api#dev:ready` probe provides that completion signal instead.

## Run the application

Select the `web` application to start the complete workflow:

```bash title="Terminal"
turbo run dev --filter=web
```

The default concurrency has enough capacity for this workflow. If you set [`--concurrency`](/docs/reference/run#--concurrency-number--percentage), use at least `3` so Turborepo has a slot for each persistent task and another for the readiness probe.

If the API does not become ready before the probe's timeout, the probe exits with an error and `web#dev` does not start. Turborepo stops all tasks when you interrupt the run.

## Probe other readiness conditions

An HTTP endpoint is only one way to determine readiness. The probe script can wait for any condition your service exposes, including:

- A TCP port accepting connections
- A file or Unix socket being created
- A database accepting queries
- A specific initialization check succeeding

You can implement the probe yourself, as shown above, or use a utility such as [`wait-on`](https://www.npmjs.com/package/wait-on). In either case, ensure the probe retries transient failures, has a timeout, and exits with a non-zero status when the service does not become ready.

---

### Apps Docs Content Docs Guides Generating Code (`apps/docs/content/docs/guides/generating-code.mdx`)

---
title: Generating code
description: Learn how to generate code using Turborepo.
product: turborepo
type: guide
summary: Use Turborepo's built-in generators and custom Plop configurations to scaffold new packages and code.
related:
  - /docs/guides/publishing-libraries
---

Splitting your monorepo into packages is a great way to organize your code, speed up tasks, and improve the local development
experience. With Turborepo's code generation, it's easy to generate new source code for packages, modules,
and even individual UI components in a structured way that integrates with the rest of your repository.

## Add an empty package

Add a new, empty app or package to your monorepo.

```sh title="Terminal"
turbo gen workspace
```

View all available [options](/docs/reference/generate#workspace) for `gen workspace`.

## Copy an existing package

You can use an existing workspace as a template for your new app or package. This works for both workspaces within your existing monorepo,
and remote workspaces from other repositories (specified via GitHub URL).

### Examples

Create a new package in your monorepo by copying from an existing package in your repo.

```sh title="Terminal"
turbo gen workspace --copy
```

Create a new workspace in your monorepo by copying from a remote package.

```sh title="Terminal"
turbo gen workspace --copy https://github.com/vercel/turborepo/tree/main/examples/with-tailwind/packages/tailwind-config
```

<Callout type="info">
  **Note**: When adding from a remote source, Turborepo is unable to verify that your repo has all of the required dependencies, and is using the correct package manager. In this case, some manual modifications may be required to get the new workspace working as expected within your repository.

</Callout>

View all available [options](/docs/reference/generate#workspace) for `gen workspace --copy`.

## Custom generators

If a built-in generator does not fit your needs, you can create your own custom generator using [Plop](https://plopjs.com/) configurations.
Turborepo will automatically detect any generator configurations within your repo, and make them available to run from the command line.

<Callout type="info">
  While Turborepo Generators are built on top of Plop, they don't require `plop`
  to be installed as a dependency in your repo.
</Callout>

While Turborepo understands all Plop configuration options and features, it provides a few additional features to improve the experience of writing
generators within a repo configured with Turborepo.

1. Generators are automatically discovered, loaded, and organized per workspace (no need to manually `load` them within a single configuration file)
2. Generators are automatically run from the root of the workspace where they are defined
3. Generators can be invoked from anywhere within your repo (or outside it via the [`--root`](/docs/reference/generate#--root-path) flag)
4. TypeScript generators are supported with zero configuration
5. `plop` is not required to be installed as a dependency of your repo

### Getting started

To build and run a custom generator, run the following command from anywhere within your monorepo using Turborepo.

```sh title="Terminal"
turbo gen
```

You'll be prompted to select an existing generator or to create one if you don't have any yet. You can also create your configuration
manually at `turbo/generators/config.ts` (or `config.js`) at the root of your repo - or within _any_ workspace.

<Callout type="info">
  If you are using TypeScript, you will need to install [the `@turbo/gen`
  package](https://github.com/vercel/turborepo/tree/main/packages/turbo-gen) as
  a `devDependency` to access the required TS types.
</Callout>

For example, the following illustrates a monorepo with three locations for generators:

<PackageManagerTabs>

<Tab value="pnpm">
  <Files>
    <Folder name="apps" defaultOpen>
      <Folder name="docs">
        <File name="package.json" />
      </Folder>
      <Folder name="web" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="packages" defaultOpen>
      <Folder name="ui" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="turbo" green defaultOpen>
      <Folder name="generators">
        <File name="config.ts" />
        <File name="templates" />
      </Folder>
    </Folder>
    <File name="package.json" />
    <File name="package-lock.yaml" />
    <File name="pnpm-workspace.yaml" />
    <File name="turbo.json" />
  </Files>
</Tab>

<Tab value="yarn">
  <Files>
    <Folder name="apps" defaultOpen>
      <Folder name="docs">
        <File name="package.json" />
      </Folder>
      <Folder name="web" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="packages" defaultOpen>
      <Folder name="ui" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="turbo" green defaultOpen>
      <Folder name="generators">
        <File name="config.ts" />
        <File name="templates" />
      </Folder>
    </Folder>
    <File name="package.json" />
    <File name="yarn.lock" />
    <File name="turbo.json" />
  </Files>
</Tab>

<Tab value="npm">
  <Files>
    <Folder name="apps" defaultOpen>
      <Folder name="docs">
        <File name="package.json" />
      </Folder>
      <Folder name="web" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="packages" defaultOpen>
      <Folder name="ui" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="turbo" green defaultOpen>
      <Folder name="generators">
        <File name="config.ts" />
        <File name="templates" />
      </Folder>
    </Folder>
    <File name="package.json" />
    <File name="package-lock.json" />
    <File name="turbo.json" />
  </Files>
</Tab>

<Tab value="bun">
  <Files>
    <Folder name="apps" defaultOpen>
      <Folder name="docs">
        <File name="package.json" />
      </Folder>
      <Folder name="web" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="packages" defaultOpen>
      <Folder name="ui" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="turbo" green defaultOpen>
      <Folder name="generators">
        <File name="config.ts" />
        <File name="templates" />
      </Folder>
    </Folder>
    <File name="package.json" />
    <File name="bun.lock" />
    <File name="turbo.json" />
  </Files>
</Tab>

<Tab value="nub">
  <Files>
    <Folder name="apps" defaultOpen>
      <Folder name="docs">
        <File name="package.json" />
      </Folder>
      <Folder name="web" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="packages" defaultOpen>
      <Folder name="ui" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="turbo" green defaultOpen>
      <Folder name="generators">
        <File name="config.ts" />
        <File name="templates" />
      </Folder>
    </Folder>
    <File name="package.json" />
    <File name="nub.lock" />
    <File name="turbo.json" />
  </Files>
</Tab>

<Tab value="aube">
  <Files>
    <Folder name="apps" defaultOpen>
      <Folder name="docs">
        <File name="package.json" />
      </Folder>
      <Folder name="web" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="packages" defaultOpen>
      <Folder name="ui" defaultOpen>
        <File name="package.json" />
        <Folder name="turbo" green defaultOpen>
          <Folder name="generators">
            <File name="config.ts" />
            <File name="templates" />
          </Folder>
        </Folder>
      </Folder>
    </Folder>
    <Folder name="turbo" green defaultOpen>
      <Folder name="generators">
        <File name="config.ts" />
        <File name="templates" />
      </Folder>
    </Folder>
    <File name="package.json" />
    <File name="aube-lock.yaml" />
    <File name="turbo.json" />
  </Files>
</Tab>

</PackageManagerTabs>

Generators created within workspaces are automatically run from the workspace root, **not** the repo root, nor the location of the generator configuration.

This makes your generators more simple to write. Creating a file at `[workspace-root]` only needs to be specified as `<file>` rather than `../../<file>`.

Learn more about [creating custom generators using Plop](https://plopjs.com/documentation/#creating-a-generator).

### Writing generators

A generator configuration file is a function that returns a [Plop](https://plopjs.com/) configuration object. The configuration object is
used to define the generator's prompts, and actions.

In its simplest form, a generator configuration file looks like:

```ts title="turbo/generators/config.ts"
import type { PlopTypes } from "@turbo/gen";

export default function generator(plop: PlopTypes.NodePlopAPI): void {
  // create a generator
  plop.setGenerator("Generator name", {
    description: "Generator description",
    // gather information from the user
    prompts: [
      ...
    ],
    // perform actions based on the prompts
    actions: [
      ...
    ],
  });
}
```

#### Prompts

Prompts are written using [Plop prompts](https://plopjs.com/documentation/#using-prompts) and are used to gather information from the user.

#### Actions

Actions can use [built-in Plop actions](https://plopjs.com/documentation/#built-in-actions), or [custom action functions](https://plopjs.com/documentation/#functionsignature-custom-action) that you define yourself:

```ts title="turbo/generators/config.ts"
import type { PlopTypes } from "@turbo/gen";

const customAction: PlopTypes.CustomActionFunction = async (answers) => {
  // fetch data from a remote API
  const results = await fetchRemoteData();
  // add the response to the answers, making this data available to actions
  answers.results = results;
  // return a status string
  return 'Finished data fetching!';
}

export default function generator(plop: PlopTypes.NodePlopAPI): void {
  // create a generator
  plop.setGenerator("Generator name", {
    description: "Generator description",
    prompts: [
      ...
    ],
    actions: [
      customAction
      {/* actions now have access to `answers.results` */}
      ...
    ],
  });
}
```

### Turborepo variables

When running actions, Turborepo automatically injects a `turbo` object into the answers data. This gives your templates and custom actions access to useful information about the repository without needing to discover it yourself.

#### Using in templates

In [Handlebars templates](https://plopjs.com/documentation/#built-in-actions), access the variables using double curly braces:

```hbs title="turbo/generators/templates/component.hbs"
// Generated at {{ turbo.paths.root }}/src/components
```

#### Using in custom actions

In [custom action functions](https://plopjs.com/documentation/#functionsignature-custom-action), the `turbo` object is available on the `answers` parameter:

```ts title="turbo/generators/config.ts"
import type { PlopTypes } from "@turbo/gen";

export default function generator(plop: PlopTypes.NodePlopAPI): void {
  plop.setGenerator("example", {
    description: "An example using turbo variables",
    prompts: [],
    actions: [
      async (answers) => {
        const { turbo } = answers;
        console.log(`Monorepo root: ${turbo.paths.root}`);
        return "Done!";
      },
    ],
  });
}
```

The available variables are documented in the [`@turbo/gen` reference](/docs/reference/turbo-gen#turborepo-variables).

### Running generators

Once you have created your generator configuration file, you can skip the selection prompt and directly run a specified generator with:

```sh title="Terminal"
turbo gen [generator-name]
```

Arguments can also be passed directly to the generator prompts using `--args`

```sh title="Terminal"
turbo gen [generator-name] --args answer1 answer2 ...
```

See [bypassing prompts](https://plopjs.com/documentation/#bypassing-prompts) in the Plop documentation for more information.

View all available [options](/docs/reference/generate#run-generator-name) for `gen`.

---

### Apps Docs Content Docs Guides Handling Platforms (`apps/docs/content/docs/guides/handling-platforms.mdx`)

---
title: Handling platforms
description: Learn how to handle caching around operating systems, architectures, and other arbitrary conditions for Turborepo tasks.
product: turborepo
type: guide
summary: Account for OS, architecture, and Node.js version differences in your Turborepo cache hash.
prerequisites:
  - /docs/crafting-your-repository/caching
related:
  - /docs/guides/ci-vendors
---

## Node.js versions

To account for Node.js versions, use [the engines key in package.json](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines). Turborepo will account for changes to this field and miss cache accordingly.

## Operating systems, architecture, and other arbitrary conditions

For advanced use cases, you may want the operating system (OS), architecture, or other external factors to contribute to your hash.

### 1. Write an arbitrary file to disk

First, create a script that accounts for the hash contributors that you are interested in. For example, here is a Node.js script that identifies platform and architecture and writes those details to a file (`turbo-cache-key.json`):

```js title="./scripts/create-turbo-cache-key.js"
#!/usr/bin/env node

const { writeFileSync } = require("fs");

const { platform, arch } = process;
const file = "turbo-cache-key.json";
const str = JSON.stringify({ platform, arch });
console.log(`Generating cache key: ${str}`);
writeFileSync(file, str);
```

### 2. Add the file to your .gitignore

You won't want to commit this file to source control since it's dependent on environment. Add it to your `.gitignore`:

```diff title=".gitignore"
+ turbo-cache-key.json
```

### 3. Add the file to the hash

Now, make sure that `turbo` is aware of the file by adding it to task inputs. You can do this two ways:

- **For specific tasks**: Include the file in [the `inputs` array](/docs/reference/configuration#inputs) of the task(s):

```json title="./turbo.json"
{
  "tasks": {
    "build-for-platforms": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", "turbo-cache-key.json"]
    }
  }
}
```

- **For all tasks**: Add the file to [`globalDependencies`](/docs/reference/configuration#globaldependencies)

```json title="./turbo.json"
{
  "globalDependencies": ["turbo-cache-key.json"],
  "tasks": {
    ...
  }
}
```

### 4. Generate the file before running `turbo`

Last, you'll want to ensure that you run the script before running `turbo`. For example:

```json title="./package.json"
{
  "scripts": {
    "build-for-platforms": "node ./scripts/create-turbo-cache-key.js && turbo run build"
  }
}
```

`turbo run build` will now take into account the contents of `turbo-cache-key.json` when calculating the hash for the `build` task.

---

### Apps Docs Content Docs Guides Microfrontends (`apps/docs/content/docs/guides/microfrontends.mdx`)

---
title: Microfrontends
description: Learn how to use Turborepo's built-in microfrontends proxy for local development.
product: turborepo
type: guide
summary: Set up Turborepo's built-in proxy to route traffic between multiple frontend applications during local development.
related:
  - /docs/guides/frameworks
  - /docs/guides/frameworks/nextjs
  - /docs/guides/frameworks/vite
  - /docs/guides/frameworks/rsbuild
---

Microfrontends are an architectural pattern where a web application is decomposed into smaller, independently developed and deployed applications that work together.

Turborepo provides built-in support for running vertical microfrontends (sometimes called "zones") locally during development through an integrated proxy server. The proxy coordinates multiple applications and routes traffic between them.

Let's imagine you have a monorepo with multiple frontend applications:

<Files>
  <Folder name="apps" defaultOpen>
    <Folder name="web">
      <File name="package.json" />
      <File name="next.config.js" />
    </Folder>
    <Folder name="docs">
      <File name="package.json" />
      <File name="next.config.js" />
    </Folder>
    <Folder name="marketing">
      <File name="package.json" />
      <File name="vite.config.ts" />
    </Folder>
  </Folder>
  <File name="package.json" />
  <File name="turbo.json" />
</Files>

In production, these applications might be deployed separately and composed together using a reverse proxy or edge routing. But during development, you want to:

- Run all applications simultaneously with a single command
- Access them through a unified URL (e.g., `http://localhost:3024`)
- Route requests to the correct application based on path patterns
- Support hot module reloading and WebSocket connections
- Avoid port conflicts and manual coordination

## Getting started

Turborepo provides a built-in proxy server that automatically routes traffic between your microfrontend applications during development. The proxy reads a `microfrontends.json` configuration file and starts when you run `turbo dev`.

<Callout type="info">
  You can try the following instructions with the monorepo created by `npx
  create-turbo@latest -e with-microfrontends`.
</Callout>

### Create `microfrontends.json`

Create a `microfrontends.json` file in your parent application. This application is the one that all requests will fall through to when not matched by another application.

```json title="./apps/web/microfrontends.json"
{
  "$schema": "https://turborepo.dev/microfrontends/schema.json",
  "applications": {
    "web": {
      "development": {
        "local": {
          "port": 3000
        }
      }
    },
    "docs": {
      "development": {
        "local": {
          "port": 3001
        }
      },
      "routing": [
        {
          "paths": ["/docs", "/docs/:path*"]
        }
      ]
    }
  }
}
```

### Set application ports

Next, use the `turbo get-mfe-port` command to set the ports in your application's development scripts. This command injects the port number when running `turbo dev`:

<Tabs items={['Next.js', 'Vite']} storageKey="framework-preference">

  <Tab value="Next.js">

```json title="./apps/web/package.json"
{
  "scripts": {
    "dev": "next dev --port $(turbo get-mfe-port)"
  }
}
```

  </Tab>

  <Tab value="Vite">

```json title="./apps/web/package.json"
{
  "scripts": {
    "dev": "vite dev --port $TURBO_MFE_PORT"
  }
}
```

  </Tab>

</Tabs>

### Handle base paths

If you're using a framework, set the base path according to the needs of the framework.

<Tabs items={['Next.js', 'Vite']} storageKey="framework-preference">

  <Tab value="Next.js">

```ts title="./apps/my-app/next.config.ts"
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  basePath: "/docs",
};

export default nextConfig;
```

  </Tab>

  <Tab value="Vite">

```ts title="./apps/my-app/vite.config.ts"
import { defineConfig } from "vite";

export default defineConfig({
  base: "/admin",
});
```

  </Tab>

</Tabs>

[Visit the Microfrontends section of your framework](/docs/guides/frameworks) for framework-specific guidance.

### Run `turbo dev`

When you run `turbo dev`, Turborepo will:

1. **Start the proxy server** on the configured port (default: `3024`)
1. **Inject the `TURBO_MFE_PORT` environment variable** in tasks to set the applications' port
1. **Run development tasks** for all configured applications
1. **Route incoming requests** based on path patterns to the appropriate application

Now you can access all of your microfrontends applications at `http://localhost:3024`.

<Callout type="info">
  Turborepo's microfrontends proxy and Module Federation solve different parts
  of local development. The proxy composes independently running applications by
  route. Module Federation composes JavaScript modules at runtime inside an
  application. For Module Federation examples, use
  [`with-vite-module-federation`](https://github.com/vercel/turborepo/tree/main/examples/with-vite-module-federation)
  or
  [`with-rsbuild-module-federation`](https://github.com/vercel/turborepo/tree/main/examples/with-rsbuild-module-federation).
</Callout>

## Configuration

Each application in the `applications` object can have the following properties:

If not provided, the application key is used to match the name in `package.json.

### `development.local`

The port where the application runs locally.

```json title="./apps/web/microfrontends.json"
{
  "development": {
    "local": {
      "port": 3000
    }
  }
}
```

If you omit the port, Turborepo will generate a deterministic port based on the application name (between 3000-8000).

### `development.fallback`

Optionally provide a target to proxy to when an application is not running locally. This is most frequently used to route to production to make commands like `turbo dev --filter=web` that only run a subset of applications a seamless experience.

```json title="./apps/web/microfrontends.json"
{
  "development": {
    "fallback": "example.com"
  }
}
```

### `routing`

An array of path groups that should route to this application. If no routing is provided, the application becomes the **default application** that catches all unmatched routes.

Only one application can have no `routing` configuration. This is your "root" application that handles all routes not matched by other applications.

```json title="./apps/web/microfrontends.json"
{
  "routing": [
    {
      "paths": ["/api/:version/users/:id"]
    },
    {
      "paths": ["/docs", "/docs/:path*"]
    }
  ]
}
```

- Paths are **case-sensitive**: `/Blog` and `/blog` are different routes
- Trailing slashes are normalized: `/home` and `/home/` match the same route

#### Exact matches

```json title="./apps/web/microfrontends.json"
{
  "paths": ["/pricing", "/about", "/contact"]
}
```

These paths match exactly as written.

#### Parameters

```json title="./apps/web/microfrontends.json"
{
  "paths": ["/blog/:slug", "/users/:id/profile"]
}
```

Segments starting with `:` match any single path segment. For example, `/blog/:slug` matches `/blog/hello` but not `/blog/hello/world`.

#### Wildcards

```json title="./apps/web/microfrontends.json"
{
  "paths": ["/docs/:path*", "/api/:version*"]
}
```

Parameters ending with `*` match zero or more path segments. For example, `/docs/:path*` matches `/docs`, `/docs/intro`, and `/docs/api/reference`.

You can also use the `+` modifier to match one or more segments (excluding the empty path):

```json title="./apps/web/microfrontends.json"
{
  "paths": ["/api/:path+"]
}
```

This matches `/api/users` and `/api/users/123`, but not `/api` or `/api/`.

#### Complex routing patterns

You can define sophisticated routing with nested parameters:

```json title="./apps/web/microfrontends.json"
{
  "routing": [
    {
      "paths": [
        "/api/:version/users",
        "/api/:version/users/:id",
        "/api/:version/posts/:postId/comments/:commentId"
      ]
    }
  ]
}
```

#### Group labels

Organize routes into logical groups for better maintainability:

```json title="./apps/web/microfrontends.json"
{
  "$schema": "https://turborepo.dev/microfrontends/schema.json",
  "applications": {
    "marketing": {
      "development": {
        "local": 3002
      },
      "routing": [
        {
          "group": "blog",
          "paths": ["/blog", "/blog/:slug*"]
        },
        {
          "group": "sales",
          "paths": ["/pricing", "/contact", "/demo"]
        }
      ]
    }
  }
}
```

The `group` field is for organizational purposes and doesn't affect routing behavior.

### `packageName`

Optionally use the name of the package from `package.json` in your workspace.

```json title="./apps/main/microfrontends.json"
{
  "applications": {
    "main-site": {
      "packageName": "web"
    }
  }
}
```

### `options.localProxyPort`

Optionally change the proxy port using the `localProxyPort` option

Defaults to `3024`.

```json title="./apps/web/microfrontends.json"
{
  "options": {
    "localProxyPort": 8080
  }
}
```

## Integrating with production

The Turborepo microfrontends proxy is meant for local usage only. How you implement and integrate your production microfrontends depends on your production infrastructure. However, we can integrate your local and production environments to create a seamless experience across environments.

To start, we've built Turborepo's local proxy to integrate with Vercel's microfrontends. We look forward to working with any infrastructure providers that would also like to integrate.

### Microfrontends on Vercel

Vercel has native support for microfrontends that provide:

- Production proxy implementation with enhance performance
- Fallback URL support across environments
- Vercel toolbar integration
- Feature flag support
- Asset prefix handling

[Learn more in Vercel's documentation](https://vercel.com/docs/microfrontends).

#### Migrating to `@vercel/microfrontends`

If you install [`@vercel/microfrontends`](https://www.npmjs.com/package/@vercel/microfrontends) in any package or add it to your workspace, Turborepo will automatically defer to it instead of using the built-in proxy. This allows for a gradual migration path.

You can use the same `microfrontends.json` configuration as for Turborepo. Turborepo's `microfrontends.json` schema is a subset of Vercel's schema, so it is compatible with `@vercel/microfrontends`.

To learn more about `@vercel/microfrontends`, [visit the package on npm](https://www.npmjs.com/package/@vercel/microfrontends).

## Troubleshooting

### Port already in use

By default, the microfrontends proxy will try to use port 3024. If you already use that port for a different purpose, you can change Turborepo's port using the [`options.localProxyPort`](#optionslocalproxyport).

### Missing CSS, images, or other assets, or routes not matching

Ensure that the paths that the microfrontends matches for in its [`routing` configuration](#routing) include the routes for the assets. Check your network tab to find paths that are or aren't matching as expected.

### Links across applications causing errors

If you use a Single-Page Application (SPA) link (like the Next.js `<Link>` component) to link across applications, this can result in errors. Even though the port and domain remain the same, the applications are different. This means the routing is, by definition, not a "single-page application".

### Visiting a proxied port does not redirect

You are still be able to reach a proxied port directly. For example, if `localhost:3000` is proxied to `localhost:3042`, you can still visit `localhost:3000` in your browser.

If you would like for `localhost:3000` to redirect to `localhost:3024`, you must set this up manually in your application.

### Applications not starting

Verify that:

1. The `packageName` matches your actual package name
2. The `task` specified exists in the package's `package.json`
3. Each application's port is available
4. All dependencies are installed

### `turbo get-mfe-port` not working

If you're getting an error when running `turbo get-mfe-port`, ensure that:

1. You're running the command from a package directory (not the repository root)
2. The package has a `name` field in its `package.json`
3. A `microfrontends.json` file exists in one of the packages
4. The current package is listed in the `applications` section of `microfrontends.json`
5. If using `--skip-infer`, you must also specify `--cwd` pointing to your repository root:

```bash title="Terminal"
turbo --skip-infer --cwd ../.. get-mfe-port
```

## Complete example

Here's a full example of a microfrontends configuration for an e-commerce platform:

```json title="./apps/web/microfrontends.json"
{
  "$schema": "https://turborepo.dev/microfrontends/schema.json",
  "options": {
    "localProxyPort": 3024
  },
  "applications": {
    "web": {
      "packageName": "web",
      "development": {
        "local": {
          "port": 3000
        }
      }
    },
    "docs": {
      "packageName": "documentation",
      "development": {
        "local": {
          "port": 3001
        }
      },
      "routing": [
        {
          "group": "documentation",
          "paths": [
            "/docs",
            "/docs/:path*",
            "/api-reference",
            "/api-reference/:path*"
          ]
        }
      ]
    },
    "blog": {
      "development": {
        "local": {
          "port": 3002
        }
      },
      "routing": [
        {
          "group": "content",
          "paths": [
            "/blog",
            "/blog/:slug",
            "/blog/category/:category",
            "/authors/:author"
          ]
        }
      ]
    },
    "shop": {
      "development": {
        "local": {
          "port": 3003
        }
      },
      "routing": [
        {
          "group": "commerce",
          "paths": [
            "/products",
            "/products/:id",
            "/cart",
            "/checkout",
            "/orders/:orderId"
          ]
        }
      ]
    }
  }
}
```

With this configuration:

- The `web` app handles the homepage and any unmatched routes
- The `docs` app handles all documentation
- The `blog` app handles blog posts and author pages
- The `shop` app handles e-commerce functionality

---

### Apps Docs Content Docs Guides Migrating From Nx (`apps/docs/content/docs/guides/migrating-from-nx.mdx`)

---
title: Migrating from Nx
description: Learn how to migrate to Turborepo from Nx.
product: turborepo
type: guide
summary: Step-by-step instructions for migrating your Nx monorepo to Turborepo.
prerequisites:
  - /docs/crafting-your-repository/structuring-a-repository
related:
  - /docs/guides/multi-language
---

This guide will help you migrate an existing Nx repository to Turborepo.

- Explore key concepts by [migrating from an Nx starter to Turborepo](#migration-steps)
- Considerations for [more complex migration scenarios](#advanced-migration-considerations)

## Why switch?

There are many reasons why you may be choosing to migrate from Nx to Turborepo. Below, we've listed the most common motivations that developers have referenced for their migrations.

### Using ecosystem standards

Turborepo's goal is to be lightweight, leaning on your repository as the source of truth. An example of this is Turborepo being [built on top of JavaScript package manager workspaces](/docs/crafting-your-repository/structuring-a-repository) for it's JavaScript/TypeScript support.

By contrast, Nx uses layers of plugins, dependencies, and other Nx-specific code to infer information about your repository. While these plugins can provide a layer of functionality and are optional, Nx users looking to migrate often cite removing Nx-specific code from their codebase as a key motivation for their change.

### Greater control of source code

Nx's philosophy involves wrapping your code with layers of plugins, dependencies, and Nx-specific code. While these layers of code are optional, they provide a great deal of Nx's value and are recommended by Nx, so most Nx repos have them. When migrating to Turborepo, many developers explain that these layers tend to create a layer of obfuscation that abstracts their repository away from their control, causing issues.

Turborepo chooses to let you handle your tooling on your own terms, configuring (or not configuring) any of your tooling as you please.

### Less configuration for your repository manager

Migrating to Turborepo will likely require deleting previous configuration that you had for Nx and replacing it with less configuration for Turborepo, since Turborepo will automatically infer your repository's needs. For example, here are the tool-specific configurations you'll find in the equivalent starters for Turborepo and Nx [used below](#migration-steps).

<Tabs items={["Turborepo", "Nx"]}>

<Tab value="Turborepo">

```json title="turbo.json"
{
  "$schema": "/schema.json",
  "ui": "tui",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", ".env*"],
      "outputs": [".next/**", "!.next/cache/**", "!.next/dev/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "check-types": {
      "dependsOn": ["^check-types"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
```

</Tab>

<Tab value="Nx">

```json title="nx.json"
{
  "$schema": "./node_modules/nx/schemas/nx-schema.json",
  "namedInputs": {
    "default": ["{projectRoot}/**/*", "sharedGlobals"],
    "production": [
      "default",
      "!{projectRoot}/.eslintrc.json",
      "!{projectRoot}/eslint.config.cjs",
      "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
      "!{projectRoot}/tsconfig.spec.json",
      "!{projectRoot}/jest.config.[jt]s",
      "!{projectRoot}/src/test-setup.[jt]s",
      "!{projectRoot}/test-setup.[jt]s"
    ],
    "sharedGlobals": ["{workspaceRoot}/.github/workflows/ci.yml"]
  },
  "nxCloudId": "6789ec521d90a2165398f39a",
  "plugins": [
    {
      "plugin": "@nx/next/plugin",
      "options": {
        "startTargetName": "start",
        "buildTargetName": "build",
        "devTargetName": "dev",
        "serveStaticTargetName": "serve-static"
      }
    },
    {
      "plugin": "@nx/playwright/plugin",
      "options": {
        "targetName": "e2e"
      }
    },
    {
      "plugin": "@nx/eslint/plugin",
      "options": {
        "targetName": "lint"
      }
    },
    {
      "plugin": "@nx/jest/plugin",
      "options": {
        "targetName": "test"
      }
    }
  ],
  "targetDefaults": {
    "e2e-ci--**/*": {
      "dependsOn": ["^build"]
    }
  },
  "generators": {
    "@nx/next": {
      "application": {
        "style": "tailwind",
        "linter": "eslint"
      }
    }
  }
}
```

```json title="project.json"
{
  "name": "starter",
  "$schema": "../../node_modules/nx/schemas/project-schema.json",
  "sourceRoot": "apps/starter",
  "projectType": "application",
  "tags": [],
  "// targets": "to see all targets run: nx show project starter --web",
  "targets": {}
}
```

</Tab>

</Tabs>

## Migration steps

Our goal for this migration is to get a working Turborepo task as quickly as possible, so that you can adopt Turborepo features incrementally. We'll start by using the Nx scaffolder to create a repository with a Next.js app.

```bash title="Terminal"
npx create-nx-workspace --preset=next --ci=skip --e2eTestRunner=none --style=tailwind --nextAppDir=true --nextSrcDir=false --packageManager=pnpm --appName=starter
```

### Step 1: Update .gitignore

Turborepo uses the .turbo directory to hold local caches and other information about your repository. For this reason, it should be added to your `.gitignore`.

```txt title=".gitignore"
.turbo
```

### Step 2: Add a workspace definition

Turborepo is built on top of package manager workspaces, a JavaScript ecosystem standard. Add the directory paths to the workspace that will contain packages.

<PackageManagerTabs>

<Tab value="pnpm">

```yml title="pnpm-workspace.yaml"
packages:
  - apps/*
```

</Tab>

<Tab value="yarn">

```json title="package.json"
{
  "workspaces": ["apps/*"]
}
```

</Tab>

<Tab value="npm">

```json title="package.json"
{
  "workspaces": ["apps/*"]
}
```

</Tab>

<Tab value="bun">

```json title="package.json"
{
  "workspaces": ["apps/*"]
}
```

</Tab>


<Tab value="nub">

```json title="package.json"
{
  "workspaces": ["apps/*"]
}
```

</Tab>

<Tab value="aube">

```yaml title="aube-workspace.yaml"
packages:
  - "apps/*"
```

</Tab>

</PackageManagerTabs>

### Step 3: Add a package.json to the application

Rather than adding additional configuration files like `project.json`, Turborepo uses the standard `package.json` file.

Add a `package.json` to the `starter` application. Create a `package.json` at `./apps/starter/package.json` that contains a `dev` and `build` script.

```json title="./apps/starter/package.json"
{
  "name": "starter",
  "scripts": {
    "dev": "next dev",
    "build": "next build"
  }
}
```

### Step 4: Remove Nx plugin

Remove the Nx plugin from ./apps/starter/next.config.js. The example file below doesn't have configuration, though your existing Next.js application may need some.

```js title="./apps/starter/next.config.js"
/** @type {import('next').NextConfig} */
const nextConfig = {};

module.exports = nextConfig;
```

### Step 5: Add `devEngines.packageManager`

The root package.json needs to have a package manager declaration. We recommend `devEngines.packageManager`. This ensures developers in the repository use the correct package manager, and that Turborepo can optimize your package graph based on your lockfile.

<PackageManagerTabs>

<Tab value="pnpm">

```json title="./package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "pnpm",
      "version": "9.0.0"
    }
  }
}
```

</Tab>

<Tab value="yarn">

```json title="./package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "yarn",
      "version": "1.22.19"
    }
  }
}
```

</Tab>

<Tab value="npm">

```json title="./package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "npm",
      "version": "10.0.0"
    }
  }
}
```

</Tab>

<Tab value="bun">

```json title="./package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "bun",
      "version": "1.2.0"
    }
  }
}
```

</Tab>


<Tab value="nub">

```json title="./package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "nub",
      "version": "0.8.3"
    }
  }
}
```

</Tab>

<Tab value="aube">

```json title="./package.json"
{
  "devEngines": {
    "packageManager": {
      "name": "aube",
      "version": "2.2.9"
    }
  }
}
```

</Tab>

</PackageManagerTabs>

### Step 6: Run you package manager's install command

Update your lockfile by running your installation command.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
pnpm install
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
yarn install
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
npm install
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
bun install
```

</Tab>


<Tab value="nub">

```bash title="Terminal"
nub install
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
aube install
```

</Tab>

</PackageManagerTabs>

Once you've done this, you should see a lockfile diff, indicating that the package has been added to the package manager's workspace.

### Step 7: Install Turborepo

Add Turborepo to the root `package.json` of the workspace.

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
pnpm add turbo --save-dev --workspace-root
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
 yarn add turbo --save-dev --ignore-workspace-root-check
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
npm install turbo --save-dev
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
bun install turbo --dev
```

</Tab>


<Tab value="nub">

```bash title="Terminal"
nub add turbo --save-dev
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
aube add turbo --save-dev
```

</Tab>

</PackageManagerTabs>

To run `turbo` directly from your terminal, install the global binary:

<Tabs items={["macOS and Linux", "Windows x64"]}>
  <Tab value="macOS and Linux">

```sh title="Terminal"
curl -fsSL https://turborepo.dev/install | sh
```

  </Tab>
  <Tab value="Windows x64">

```powershell title="PowerShell"
irm https://turborepo.dev/install.ps1 | iex
```

  </Tab>
</Tabs>

### Step 8: Add a `turbo.json`

Create a `turbo.json` at the root to register your tasks and describe their task dependencies.

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", "!.next/dev/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}
```

### Step 9: Run `turbo build`

Build the application with Turborepo. Using global `turbo`, this would be `turbo build`. You can also run the command through your package manager:

<PackageManagerTabs>

<Tab value="pnpm">

```bash title="Terminal"
pnpm exec turbo build
```

</Tab>

<Tab value="yarn">

```bash title="Terminal"
 yarn dlx turbo build
```

</Tab>

<Tab value="npm">

```bash title="Terminal"
npx turbo run build
```

</Tab>

<Tab value="bun">

```bash title="Terminal"
bunx turbo run build
```

</Tab>


<Tab value="nub">

```bash title="Terminal"
nubx turbo run build
```

</Tab>

<Tab value="aube">

```bash title="Terminal"
aubx turbo run build
```

</Tab>

</PackageManagerTabs>

### Step 10: Enable Remote Caching (optional)

By default, Turborepo will connect to the free-to-use Vercel Remote Cache when you run:

```bash title="Terminal"
turbo login
turbo link
```

You may also configure a self-hosted Remote Cache.

## Advanced migration considerations

While the migration guide above is a good starting point, the breadth of possibilities and capabilities of monorepos means that its difficult to create generalized instructions for all cases. Below, we've listed some common next steps that you may be thinking about.

### Migrate complex monorepos incrementally

We encourage incremental migration, meaning you will have both of Nx and Turborepo in your repository at the same time. Make sure to spend time understanding how your Nx task graph is constructed. Splitting up the task graph may include strategies like:

- **Migrating one task at a time**: Changing `nx run lint` to `turbo run lint`
- **Migrating one package/project at a time**: Changing `nx run-many lint test --projects=web` to `turbo run lint test --filter=web`
- **Double-running some of your tasks**: To ensure stability, you may choose to run `turbo run lint` **and** `nx run lint` while you're still getting comfortable and building certainty in the early phases of your migration.

### Installing dependencies where they're used

Turborepo recommends [installing packages where they're used](/docs/crafting-your-repository/managing-dependencies#best-practices-for-dependency-installation) to improve cache hit ratios, help dependency pruning capability, and clarify for developers which dependencies are meant for which packages. This is different from the Nx strategy, where all dependencies are installed at the root of the repository, making all dependencies available to all packages in the workspace.

Historically, Nx has recommended installing all dependencies in the root of the repository, making all dependencies available to all packages in the Workspace. If you followed this guidance, we highly recommend that you move dependencies to the `package.json`'s for packages and applications that need them. [Visit our documentation on managing dependencies](/docs/crafting-your-repository/managing-dependencies) to learn more.

### Creating shared packages

You'll follow roughly the same set of steps as above to add a package to your package manager's workspace.

1. Ensure the package's directory is included in the workspace definition (like `./packages/*` ).
2. Add a `package.json` to the package with the scripts it needs to run.
3. Check task dependencies in `turbo.json` to make sure your dependency graph meets your requirements.

### Multi-language monorepos

Turborepo natively supports JavaScript and TypeScript, with secondary support for any other languages you'd like to use. [Visit the Multi-Language support documentation](/docs/guides/multi-language) to learn more.

## Configuration equivalents

Configuration found in `nx.json` can be mapped to `turbo.json` using the tables below.

<Callout type="info">
  The majorify of globs for capturing files are the same between Nx and
  Turborepo. See [our file glob specification](/docs/reference/globs) for
  details and edge cases.
</Callout>

### Global configuration

| Nx                         | Turborepo                                                                |
| -------------------------- | ------------------------------------------------------------------------ |
| `sharedGlobals`            | [`globalDependencies`](/docs/reference/configuration#globaldependencies) |
| `sharedGlobals.env`        | [`globalEnv`](/docs/reference/configuration#globalenv)                   |
| `sharedGlobals.namedInput` | [`globalDependencies`](/docs/reference/configuration#globaldependencies) |
| `cacheDirectory`           | [`cacheDir`](/docs/reference/configuration#cachedir)                     |

### Task configuration

| Nx              | Turborepo                                                      |
| --------------- | -------------------------------------------------------------- |
| `inputs` files  | [`tasks[task].inputs`](/docs/reference/configuration#inputs)   |
| `inputs.env`    | [`tasks[task].env`](/docs/reference/configuration#env)         |
| `outputs` files | [`tasks[task].outputs`](/docs/reference/configuration#outputs) |
| `cache`         | [`tasks[task].cache`](/docs/reference/configuration#cache)     |

### CLI equivalents

| Nx               | Turborepo                                                               |
| ---------------- | ----------------------------------------------------------------------- |
| `nx generate`    | [`turbo generate`](/docs/reference/generate)                            |
| `nx run`         | [`turbo run`](/docs/reference/run)                                      |
| `nx run-many`    | [`turbo run`](/docs/reference/run)                                      |
| `nx reset`       | [`--force`](/docs/reference/run#--force)                                |
| `--parallel`     | [`--concurrency`](/docs/reference/run#--concurrency-number--percentage) |
| `--nxBail`       | [`--continue`](/docs/reference/run#--continueoption)                    |
| `--projects`     | [`--filter`](/docs/reference/run#--filter-string)                       |
| `--graph`        | [`--graph`](/docs/reference/run#--graph-file-name)                      |
| `--output-style` | [`--log-order`](/docs/reference/run#--log-order-option)                 |
| `--no-cloud`     | [`--cache`](/docs/reference/run#--cache-options)                        |
| `--verbose`      | [`--verbosity`](/docs/reference/run#--verbosity)                        |

---

### Apps Docs Content Docs Guides Multi Language (`apps/docs/content/docs/guides/multi-language.mdx`)

---
title: Multi-language support
description: Run other language toolchains alongside JavaScript packages.
product: turborepo
type: guide
summary: Use package scripts to build JavaScript and .NET projects in one task graph.
prerequisites:
  - /docs/crafting-your-repository/structuring-a-repository
  - /docs/crafting-your-repository/configuring-tasks
related:
  - /docs/guides/tools/rust
  - /docs/guides/tools/python
  - /docs/guides/tools/go
  - /docs/guides/migrating-from-nx
---

Turborepo can run other language toolchains through scripts in `package.json`. Add a package for each independently cacheable project and declare its dependencies so Turborepo can order tasks and invalidate cached results.

For experimental native workspace support, see the [Rust](/docs/guides/tools/rust), [Python](/docs/guides/tools/python), and [Go](/docs/guides/tools/go) guides. Those integrations discover projects and dependencies from their native workspace files.

This example combines a JavaScript package with a .NET console application and a C# library. Start with [Turborepo installed](/docs/getting-started/installation) in your repository, and install the [.NET 10 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0) so `dotnet` is available on `PATH`.

```text
.
├── apps/api/
│   ├── Api.csproj
│   ├── Program.cs
│   └── package.json
├── packages/
│   ├── lib/
│   │   ├── Lib.csproj
│   │   ├── Message.cs
│   │   └── package.json
│   └── web/
│       └── package.json
├── .gitignore
├── global.json
├── package.json
└── turbo.json
```

## Add the package-manager workspaces

Include both the application and library directories. Their `package.json` files make the .NET projects visible to Turborepo:

<PackageManagerTabs>
  <Tab value="pnpm">

```yaml title="./pnpm-workspace.yaml"
packages:
  - "apps/*"
  - "packages/*"
```

  <LinkToDocumentation href="https://pnpm.io/pnpm-workspace_yaml" text="pnpm workspace documentation" />

  </Tab>

  <Tab value="yarn">

```json title="./package.json"
{
  "private": true,
  "workspaces": ["apps/*", "packages/*"]
}
```

  <LinkToDocumentation href="https://yarnpkg.com/features/workspaces#how-are-workspaces-declared" text="Yarn workspace documentation" />

  </Tab>

  <Tab value="npm">

```json title="./package.json"
{
  "private": true,
  "workspaces": ["apps/*", "packages/*"]
}
```

  <LinkToDocumentation href="https://docs.npmjs.com/cli/using-npm/workspaces" text="npm workspace documentation" />

  </Tab>

  <Tab value="bun">

```json title="./package.json"
{
  "private": true,
  "workspaces": ["apps/*", "packages/*"]
}
```

  <LinkToDocumentation href="https://bun.sh/docs/install/workspaces" text="Bun workspace documentation" />

  </Tab>
</PackageManagerTabs>

The JavaScript package has a normal package name and script:

```json title="./packages/web/package.json"
{
  "name": "web",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "build": "node -e \"console.log('web build')\""
  }
}
```

## Add the .NET projects

Pin the .NET SDK at the repository root so machines sharing cached builds use the same compiler. Install the version specified here:

```json title="./global.json"
{
  "sdk": {
    "version": "10.0.401",
    "rollForward": "disable"
  }
}
```

`rollForward: "disable"` requires the exact SDK version. This prevents a compiler upgrade from reusing cached outputs without a corresponding change to `global.json`.

Create the library project and its source file:

```xml title="./packages/lib/Lib.csproj"
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <DefaultItemExcludes>$(DefaultItemExcludes);node_modules/**</DefaultItemExcludes>
  </PropertyGroup>
</Project>
```

```csharp title="./packages/lib/Message.cs"
namespace Acme.Lib;

public static class Message
{
    public static string Text() => "API ready";
}
```

The application uses a `ProjectReference` to resolve the library in .NET:

```xml title="./apps/api/Api.csproj"
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <DefaultItemExcludes>$(DefaultItemExcludes);node_modules/**</DefaultItemExcludes>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="../../packages/lib/Lib.csproj" />
  </ItemGroup>
</Project>
```

```csharp title="./apps/api/Program.cs"
System.Console.WriteLine(Acme.Lib.Message.Text());
```

## Connect the projects to Turborepo

Add a `package.json` beside each `.csproj` with a script that invokes the [.NET CLI](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-build):

```json title="./packages/lib/package.json"
{
  "name": "lib",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "build": "dotnet build Lib.csproj --configuration Release"
  }
}
```

```json title="./apps/api/package.json"
{
  "name": "api",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "build": "dotnet build Api.csproj --configuration Release"
  },
  "dependencies": {
    "lib": "workspace:*"
  }
}
```

For npm, use `"lib": "*"` instead of `"workspace:*"`. Run your package manager's install command from the repository root to link the workspaces and update its lockfile.

Keep the `package.json` dependency in sync with the `ProjectReference`. .NET uses the project reference to compile the application, while Turborepo uses the package dependency to build `lib` before `api` and invalidate `api`'s cache when the library changes. Turborepo does not read `.csproj` references or manage NuGet dependencies. Review both declarations whenever you add or remove a project reference.

The `DefaultItemExcludes` entries keep .NET from compiling source files reached through workspace links in `node_modules`.

## Configure tasks and caching

Ignore `bin/` and `obj/` to keep generated files out of the default input hash. The `outputs` setting below still lets Turborepo cache and restore `bin/`:

```text title="./.gitignore"
node_modules/
.turbo/
bin/
obj/
```

Configure the build task and cache the binaries produced by each .NET project:

```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "globalDependencies": ["global.json"],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["bin/**"]
    },
    "web#build": {
      "outputs": []
    }
  }
}
```

Output paths are relative to each package. The .NET builds write to `bin/Release/net10.0`; the JavaScript script only prints a message and has no files to cache. `obj/` contains intermediate and restore state and is not cached here. A build that needs it can recreate it through `dotnet build`'s implicit restore.

Adding `global.json` to [`globalDependencies`](/docs/reference/configuration#globaldependencies) makes SDK version changes in that file invalidate cached tasks. Update the pinned version when upgrading the SDK; Turborepo does not detect the installed .NET SDK version automatically. If you add shared files such as `Directory.Build.props`, `Directory.Build.targets`, or `NuGet.Config`, include those in your task inputs or global dependencies too. Keep the build environment consistent between machines that share cached outputs.

Run all builds, or select the .NET application:

```bash title="Terminal"
turbo run build
turbo run build --filter=api
dotnet apps/api/bin/Release/net10.0/Api.dll
```

The application prints `API ready`. A second unchanged `turbo run build` restores the cached results. Editing `packages/lib/Message.cs` causes both `lib` and its dependent `api` to rebuild, while `web` can still use its cache.

.NET still checks project references during the application's build and normally skips recompilation when they are up to date. The package dependency lets Turborepo schedule and cache each project independently; it does not replace .NET's dependency resolution.

---

### Apps Docs Content Docs Guides Publishing Libraries (`apps/docs/content/docs/guides/publishing-libraries.mdx`)

---
title: Publishing libraries
description: Learn how to publish libraries to the npm registry from a monorepo.
product: turborepo
type: guide
summary: Bundle, version, and publish packages from your monorepo to npm using tsup and Changesets.
prerequisites:
  - /docs/crafting-your-repository/creating-an-internal-package
related:
  - /docs/guides/generating-code
  - /docs/guides/tools/typescript
---

Publishing a package to the npm registry from a monorepo can be a smooth experience, with the right tools.

While this guide cannot solve for every possible compiling, bundling, and publishing configuration needed for robust packages, it will explain some of the basics.

<Callout type="info">
  You should follow this setup if you want to publish some of your monorepo's
  packages to npm. If you don't need to publish to npm, you should use an
  [Internal
  Package](/docs/crafting-your-repository/creating-an-internal-package) instead.
  They're much easier to set up and use.
</Callout>

## Bundling

Unlike [Internal Packages](/docs/crafting-your-repository/creating-an-internal-package), external packages can be deployed to [npm](https://www.npmjs.com) _and_ used locally. In this guide, we'll bundle a package to both [ECMAScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) (`esm`) and [CommonJS modules](https://en.wikipedia.org/wiki/CommonJS) (`cjs`), the most commonly used formats on npm.

## Setting up a build script

Let's start with a package created using the [Internal Packages](/docs/crafting-your-repository/creating-an-internal-package) tutorial.

There, we created a `@repo/math` package which contained a few helper functions for adding and subtracting numbers. We've decided that this package is good enough for npm, so we're going to bundle it.

We're going to add a `build` script to `@repo/math`, using a bundler. If you're unsure which one to choose, we recommend [`tsup`](https://tsup.egoist.dev/).

Install `tsup` inside the `./packages/math` package using your package manager and then create a build script for it:

```json title="./packages/math/package.json"
{
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts"
  }
}
```

`tsup` outputs files to the `dist` directory by default, so you should:

1. Add `dist` to your `.gitignore` files to make sure they aren't committed to source control.
2. Add `dist` to the outputs of `build` in your `turbo.json`.

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "outputs": ["dist/**"]
    }
  }
}
```

That way, when `tsup` is run the outputs can be [cached](/docs/crafting-your-repository/caching) by Turborepo.

Finally, we should update our package entrypoints. Inside `package.json`, change `main` to point at `./dist/index.js` for clients using CommonJS modules (`cjs`), `module` to point at `./dist/index.mjs` for clients using ECMAScript modules (`esm`), and `types` to the type definition file - `./dist/index.d.ts`:

```json title="./packages/math/package.json"
{
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts"
}
```

<Callout type="info">

It is not required to bundle to both `cjs` and `esm`. However, it is recommended, as it allows your package to be used in a wider variety of environments.

If you run into errors by using `main`, `module` and `types`, take a look at the [tsup docs](https://tsup.egoist.dev/#bundle-formats).

Bundling is a complicated topic, and we don't have space here to cover everything!

</Callout>

### Building our package before our app

Before we can run `turbo run build`, there's one thing we need to consider. We've just added a [task dependency](/docs/crafting-your-repository/running-tasks) into our monorepo. The `build` of `packages/math` needs to run **before** the `build` of `apps/web`.

Fortunately, we can use [`dependsOn`](/docs/reference/configuration#dependson) to easily configure this.

```json title="./turbo.json"
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"]
    }
  }
}
```

Now, we can run `turbo run build`, and it'll automatically build our packages _before_ it builds our app.

### Setting up a dev script

There's a small issue with our setup. We are building our package just fine, but it's not working great in dev. Changes that we make to our `@repo/math` package aren't being reflected in our app.

That's because we don't have a `dev` script to rebuild our packages while we're working. We can add one easily:

```json title="./packages/math/package.json"
// [!code word:--watch]
{
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts",
    "dev": "tsup src/index.ts --format cjs,esm --dts --watch"
  }
}
```

This passes the `--watch` flag to `tsup`, meaning it will watch for file changes.

If we've already set up [dev scripts](/docs/crafting-your-repository/developing-applications#configuring-development-tasks) in our `turbo.json`, running `turbo run dev` will run our `packages/math` dev task in parallel with our `apps/web` dev task.

Our package is now in a spot where we can consider deploying to npm. In our [versioning and publishing](#versioning-and-publishing) section, we'll do just that.

## Versioning and publishing

Manually versioning and publishing packages in a monorepo can be tiresome. Luckily, there's a tool that makes things easy - the [Changesets](https://github.com/changesets/changesets) CLI.

We recommend Changesets because it's intuitive to use, and - just like Turborepo - fits with the monorepo tools you're already used to.

Some alternatives are:

- [intuit/auto](https://github.com/intuit/auto) - Generate releases based on semantic version labels on pull requests
- [microsoft/beachball](https://github.com/microsoft/beachball) - The Sunniest Semantic Version Bumper

## Publishing

Once your package has been bundled, you can then publish it to the npm registry.

We recommend taking a look at the Changesets docs. Here's our recommended reading order:

1. [Why use changesets?](https://github.com/changesets/changesets/blob/main/docs/intro-to-using-changesets.md) - an intro that takes you through the fundamentals.
1. [Installation instructions](https://github.com/changesets/changesets/blob/main/packages/cli/README.md)
1. If you're using GitHub, consider using the [Changeset GitHub bot](https://github.com/apps/changeset-bot) - a bot to nudge you to add changesets to PR's.
1. You should also consider adding the [Changesets GitHub action](https://github.com/changesets/action) - a tool which makes publishing extremely easy.

## Using Changesets with Turborepo

Once you've started using Changesets, you'll gain access to three useful commands:

```bash title="Terminal"
# Add a new changeset
changeset

# Create new versions of packages
changeset version

# Publish all changed packages to npm
changeset publish
```

Linking your publishing flow into Turborepo can make organizing your deploy a lot simpler and faster.

Our recommendation is to configure Changesets to automatically commit `changeset version`'s changes

```json title="./.changeset/config.json"
{
  // …
  "commit": true
  // …
}
```

and add a `publish-packages` script into your root `package.json`:

```json title="./package.json"
{
  "scripts": {
    // Include build, lint, test - all the things you need to run
    // before publishing
    "publish-packages": "turbo run build lint test && changeset version && changeset publish"
  }
}
```

If your packages are public, set Changeset's `access` to `public`:

```json title="./.changeset/config.json"
{
  // …
  "access": "public"
  // …
}
```

<Callout type="info">
  We recommend `publish-packages` so that it doesn't conflict with npm's
  built-in `publish` script.
</Callout>

This means that when you run `publish-packages`, your monorepo gets built, linted, tested and published - and you benefit from all of Turborepo's speedups.

---

### Apps Docs Content Docs Guides Single Package Workspaces (`apps/docs/content/docs/guides/single-package-workspaces.mdx`)

---
title: Single-package workspaces
description: Learn how to use Turborepo in a single-package workspace.
product: turborepo
type: guide
summary: Use Turborepo's caching and task parallelization in a standalone application without a monorepo.
related:
  - /docs/guides/skipping-tasks
---

While Turborepo is highly effective in [multi-package workspaces](https://vercel.com/docs/glossary#multi-package-workspace) (commonly referred to as monorepos), it can also be used to make [single-package workspaces](https://vercel.com/docs/glossary#single-package-workspace) faster.

Turborepo's most important features work in single-package workspaces including local and [Remote Caching](/docs/core-concepts/remote-caching) and task parallelization. Features that don't work are ones that don't make sense in the context of a single package, like package tasks (`app#build`).

<Callout type="info">
  Examples of single-package workspaces are the output of `npx create-next-app`
  or `npm create vite`.
</Callout>

## Installation

Install `turbo` into your application:

<PackageManagerTabs>

  <Tab value="pnpm">
    ```bash title="Terminal"
    pnpm add turbo --save-dev
    ```

  </Tab>

  <Tab value="yarn">
    ```bash title="Terminal"
    yarn add turbo --dev
    ```

  </Tab>

  <Tab value="npm">
  ```bash title="Terminal"
  npm install turbo --save-dev
  ```

  </Tab>

  <Tab value="bun">
    ```bash title="Terminal"
    bun install turbo --dev
    ```

  </Tab>

<Tab value="nub">
    ```bash title="Terminal"
    nub add turbo --save-dev
    ```

  </Tab>

<Tab value="aube">
    ```bash title="Terminal"
    aube add turbo --save-dev
    ```

  </Tab>

</PackageManagerTabs>

### Running a `package.json` script using global `turbo` (optional)

For even faster developer workflows, you can [install `turbo` globally](/docs/getting-started/installation#global-installation), too, and run commands directly from the command line.

Once installed, you can run `turbo build` and Turborepo will run your `build` script from `package.json`. Running `turbo build` again will hit the cache.

At this point, `turbo` isn't providing much value since you're likely to only be rebuilding your application when code changes and, when your code changes, `turbo` will miss the cache. In two short steps, you can get more out of `turbo`.

## Running many scripts with one command

In many repositories, there are setup tasks or pre-build steps to run. These tasks are often run one at a time - but you can easily turn them into one script with `turbo`.

For example, let's say you have a project where we always have to set up a development environment whenever you start working. You need to:

1. Start a Docker container for a database.
2. Push a database schema to the database.
3. Seed the database with data.
4. Start the development server.

You can schedule these tasks into one command using Turborepo. First, create scripts in your `package.json`:

```json title="package.json"
{
  "name": "@acme/my-app",
  "version": "0.0.0",
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "check-types": "tsc --noEmit",
    "db:up": "docker-compose up -d",
    "db:push": "your-orm-tool schema-push",
    "db:seed": "node ./db-seed.js"
  }
}
```

Then, create tasks in `turbo.json` to run these scripts in order:

```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "dev": {
      "dependsOn": ["db:seed"],
      "cache": false,
      "persistent": true
    },
    "db:seed": {
      "dependsOn": ["db:push"],
      "cache": false
    },
    "db:push": {
      "dependsOn": ["db:up"],
      "cache": false
    },
    "db:up": {
      "cache": false
    }
  }
}
```

The `dependsOn` arrays in the tasks above create a sequential order for the tasks. When you run `turbo dev`, the scripts for `db:up`, then `db:push`, then `db:seed` will be run first.

## Parallelizing tasks

Using `turbo` to parallelize tasks results in speeding up tasks by running all at once, when they can be. For instance, you can run your ESLint, TypeScript, and Prettier checks at the same time. Given scripts like:

```json title="./package.json"
{
  "scripts": {
    "lint": "eslint .",
    "format": "prettier .",
    "check-types": "tsc --noEmit"
  }
}
```

You can create a configuration like this one:

```json title="turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "lint": {},
    "format": {},
    "check-types": {}
  }
}
```

Then, to run all tasks at the same time:

```bash title="Terminal"
turbo check-types lint format
```

## Optimizing task using inputs

Because Turborepo will treat a single-package workspace as one package, it can help to optimize inputs to tasks to make sure unrelated changes don't create cache misses.

For instance, a script for checking types using `tsc --noEmit` can be configured with inputs that only include TypeScript files:

```json title="./turbo.json"
{
  "$schema": "https://turborepo.dev/schema.json",
  "tasks": {
    "check-types": {
      "inputs": ["**/*.{ts,tsx}"]
    }
  }
}
```

---

--- METRICS ---
- Files Extracted: 100
- Estimated Token Budget: ~200878 tokens
- Canonical Reference: https://codewiki.google/github.com/vercel/turborepo
