# Turborepo: a Rust task runner for JavaScript monorepos

> Turborepo is Vercel's MIT-licensed build system for JavaScript and TypeScript monorepos, written in Rust. Its README points new users at turborepo.dev, and the repository keeps a large example tree for the workflows it targets.

**vercel/turborepo** — Build system optimized for JavaScript and TypeScript, written in Rust

- Repository: https://github.com/vercel/turborepo
- Website: https://turborepo.dev
- Stars: 31,127 · Forks: 2,444
- Language: Rust
- License: MIT
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/vercel-turborepo

## The monorepo task problem Turborepo targets

A JavaScript monorepo holds many packages in one repository, each with its own package.json and scripts. Running a build, test or lint across all of them means invoking the package manager once per package, in an order you have to work out yourself. Turborepo's job is to take that graph away from you: you declare tasks in a turbo.json file, and the turbo binary decides what to run, in what order, and what it can skip.

The README frames the project in one line: "Turborepo is the build system for coding agents." The repository topics describe the same thing more plainly: build-system, build-tool, javascript, monorepo, typescript. That is the audience. If your repository is one package with one build script, the task graph is trivial and Turborepo adds a configuration file for nothing.

The project is MIT licensed, maintained under the vercel organization, and the source is a Cargo workspace of Rust crates. The root package.json is private and named turbo-monorepo, so the repository is itself a monorepo that uses the tool it ships.

## How the task graph and cache work

The mechanism visible in the repository is a Rust workspace plus a JavaScript-facing package. Cargo.toml lists members such as crates/turborepo*, crates/turbo-trace and packages/turbo-repository/rust, and it declares workspace groups so that the libraries can be built without the Go code: turborepo-libraries covers path:crates/turborepo-* and turborepo covers path:crates/turborepo*. That grouping is itself used by the task runner, since the same file notes that the workspace name turborepo-crates is what task keys like turborepo-crates#test and filters like --filter=turborepo-crates resolve against.

On the JavaScript side, the entry point is the turbo package published to npm. You describe tasks in turbo.json, and the runner reads each package's scripts to build a dependency graph. The repository ships examples/turbo.json as a reference file, and the examples directory contains a variant per stack: with-npm, with-berry, with-docker, with-nextjs, with-angular, with-otel, with-prisma, with-microfrontends and others. Those directories are the closest thing to a specification of supported setups.

The caching behaviour is the part that changes how a CI pipeline is written. Because the runner owns the graph, it can decide that a task whose inputs have not changed does not need to execute again. The README does not document the cache key format or the remote cache protocol, so treat the documentation site as the source for those details rather than the repository text.

## Installing Turborepo and running a first task

The README does not contain install commands. It says only: "Visit https://turborepo.dev to get started with Turborepo." That page, not this repository, is where the project puts its setup instructions. What the repository does give you is the shape of a working setup, through examples/ and the root turbo.json.

If you already have a workspace repository, the tool is distributed as the npm package turbo, so it is installed as a development dependency with your existing package manager. The repository's own package.json declares pnpm@12.0.0 in packageManager and requires node 24.x in engines, which tells you the toolchain the maintainers build against, not necessarily the minimum your project needs.

A minimal turbo.json follows the structure of examples/turbo.json. Task names are keys under tasks, and dependsOn expresses ordering between them:

```json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"]
    },
    "test": {
      "dependsOn": ["build"]
    }
  }
}
```

The caret in ^build means the build task of upstream workspace dependencies runs before this package's build. After adding the file, the runner is invoked through your package manager's script runner so that the local binary is used:

```bash
pnpm turbo build
pnpm turbo test
```

You should see one line per package as tasks start, and packages whose inputs have not changed reported as cache hits rather than rebuilt. If a package never appears, its name is probably missing from your workspace configuration, not from turbo.json.

## Where Turborepo stops helping

The first limit is scope. Turborepo schedules JavaScript and TypeScript package tasks. The repository shows awareness of this boundary in Cargo.toml, where the turborepo-libraries group exists specifically so that the Go code does not have to be built during library work. A polyglot repository can still use the runner for its JS packages, but the Rust and Go parts of this very project are built with cargo, not turbo.

The second limit is that the runner does not replace your package manager. Dependency installation, workspace linking and registry resolution stay with npm, pnpm or Yarn. If your problem is slow installs, a task runner will not fix it.

The third is configuration surface. Task ordering lives in turbo.json, and the repository does not document rollback or migration away from the tool. If you adopt it, you are adopting a config file that other tooling in the repository may also need to understand. The repository also carries a lockfile-tests directory and a turborepo-tests directory, which suggests the maintainers treat lockfile and integration behaviour as areas that need dedicated test coverage rather than assuming it.

Finally, the release channel matters. The most recent tags listed are v2.10.13-canary.4, v2.10.13-canary.3 and v2.10.13-canary.2, all published on 2026-09-09 and 2026-09-10. Canary tags are not the stable line, so a version range that floats will eventually pull prerelease builds.

## Turborepo compared with Nx

The most common search around this project is turborepo vs nx, and the difference is architectural rather than cosmetic. Turborepo is a single Rust binary plus a turbo.json file. It reads the scripts your packages already declare and orders them. It does not want to own how a package is built.

Nx takes the opposite approach. It ships plugins and generators that know how to build a Next.js app or a NestJS service, and it maintains its own project graph that can be extended by those plugins. The cost is more configuration and a stronger opinion about project structure; the benefit is that tasks beyond the ones you write yourself have a supported implementation.

Both are monorepo tools and both are alternatives to running scripts by hand. The practical question is whether you want a runner that reads your existing scripts, or a framework that supplies them. Turborepo's repository layout, with an examples/ directory holding one folder per stack, reflects the first position: the tool adapts to the stack rather than the reverse.

## Maintenance, licensing and upgrade cost

The repository is not archived, and its last push was on 2026-09-10, one week before this writing. Releases are frequent and currently on a canary cadence. The project is MIT licensed, which permits commercial use and modification; the LICENSE file sits at the repository root and the npm badge in the README points at the same licence. That is the extent of what the repository states, and it is not legal advice.

Upgrade cost is concentrated in turbo.json and in the version pin. The root package.json uses exact versions for its devDependencies rather than ranges, and the Cargo workspace pins dependency versions centrally under workspace.dependencies with a comment explaining that a single bump is the point. The same discipline applies to consumers: pin turbo to an exact version, because the tags published around the last push are canaries.

The repository also carries AGENTS.md, plans/, skills/ and a docs/ directory, plus RELEASE.md and SECURITY.md. Security reports go to security@vercel.com rather than a public issue, per the README. None of these files are described in the README, so their contents are not something this article can summarise.

## Conclusion

Adopt Turborepo when you already run a JavaScript or TypeScript monorepo on npm, pnpm or Yarn workspaces and want one binary to schedule and cache package tasks. Skip it when your repository is a single package, or when your build graph depends on a language ecosystem the task pipeline does not cover. Before committing, verify that your package manager workspaces are declared correctly, check the turbo.json in examples/turbo.json against your own task names, and confirm the release channel you install from. The repository's last push was 2026-09-10 and the newest tags are canary releases, so pin an exact version rather than tracking a floating range.

## FAQ

### What is Turborepo used for?

It schedules and caches build, test and lint tasks across the packages of a JavaScript or TypeScript monorepo. Tasks are declared in turbo.json, and the runner executes them in dependency order.

### What problem does Turborepo solve?

It removes the need to invoke your package manager once per package and work out the ordering yourself. The runner reads each package's scripts, builds the task graph, and skips tasks whose inputs have not changed.

### What are the key differences between a monorepo and a Turborepo?

A monorepo is a repository layout holding several packages. Turborepo is a tool you run inside that layout: it adds a turbo.json file and a turbo binary that schedules the packages' tasks.

### Is Turborepo better than NX?

The repository does not compare the two. Turborepo reads the scripts your packages already declare and orders them, while Nx supplies plugins and generators that know how to build specific frameworks.

### How to install Turborepo?

The README does not give install commands and instead says to visit turborepo.dev to get started. The tool is distributed as the npm package turbo and is installed as a development dependency with your package manager.

### How to setup Turborepo in a monorepo?

Add a turbo.json file describing your tasks, using examples/turbo.json as a reference, then invoke the runner through your package manager's script runner. The repository also ships examples for npm, Yarn Berry, Docker, Next.js and other stacks.

## Sources

- [License: MIT](https://github.com/vercel/turborepo/blob/main/LICENSE)
- [Project website](https://turborepo.dev)
- [README](https://github.com/vercel/turborepo/blob/main/README.md)
- [Releases](https://github.com/vercel/turborepo/releases)
- [vercel/turborepo on GitHub](https://github.com/vercel/turborepo)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/vercel-turborepo
