Library / SDK
r-lib/pak avatar
r-lib/pak

pak and the rework of how R packages get installed

A fresh approach to package installation

821 stars90 forksCLicense varies

At a glance

What is it?
pak is an R package installer from the r-lib team that replaces install.packages and devtools::install_github, adding a dependency solver, parallel downloads, caching, time travel and a prebuilt binary repository. It is written in C and calls itself stable.
Who is it for?
pak fits an R team that installs many packages, mixes sources such as CRAN, Bioconductor, GitHub and local directories, and wants to see the dependency graph before it commits to an install. It is the wrong tool for a one-off install of a single CRAN package, and the wrong choice on a macOS machine running a non-CRAN R build, which the prebuilt binary repository does not support.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A second front end for the same job install.packages already does

pak installs R packages from CRAN, Bioconductor, GitHub, plain URLs, git repositories, local files and local directories. The project describes itself as an alternative to `install.packages()` and `devtools::install_github()`, and that framing matters: this is not a new package format and not a new repository, it is a different way of resolving and fetching the same artefacts.

The audience is R developers who install packages often, in bulk, from more than one source. The base R function installs from a repository and asks little about the shape of the dependency graph. pak adds a solver, which is the difference that shows up in daily use.

The project states the goals in three words, fast, safe and convenient, and the README expands them into parallel downloads and installation with caching, a dependency solver and a system dependency solver, packages from multiple sources, and time travel. Those are the project's own claims rather than measurements, and none of them can be verified from the documentation alone, so it is worth asking what each one means in practice before switching a team over.

The dependency solver is the part that changes daily work

Two functions make the solver visible. The first draws the tree:

r
pak::pkg_deps_tree("tibble")

The second explains a single edge in it:

r
pak::pkg_deps_explain("tibble", "rlang")

That pairing is the argument for the whole package. Before installing, you can see what a package depends on and why a particular dependency is present, which is the question people end up asking in a chat when an install pulls in something unexpected. With `install.packages()` the resolution happens and the reasoning is not shown.

A separate system dependency solver sits alongside the R level one, addressing the packages that have to be present on the operating system for a build to succeed. On Linux that is the difference between an install that works on your laptop and one that fails on a fresh container, and it is the part of the tool that a team provisioning machines will care about most.

Parallel downloads, caching and what time travel actually means

The speed claim rests on parallel downloads and installation, plus caching, so repeated installs avoid refetching artefacts that are already on disk. For a team that runs the same install step across a build matrix, that is where the time goes.

Time travel is the feature with the least explanation in the top-level documentation, and it is the one worth understanding before relying on it. The concept is installing a package as it existed at a chosen point in the past rather than as it stands today, which requires the package metadata and sources for that point in time to be available from somewhere the installer can reach. It is the mechanism that makes a paper reproducible a year later, and it is also the mechanism with the largest dependency on a particular repository and on that repository's retention.

Local installs complete the picture. A package in a working directory can be installed together with its dependencies, which is the everyday loop for someone developing a package and its tests in the same session:

r
pak::local_install("cli")

The two function calls that matter most for a working setup are the plain installer and the GitHub one:

r
pak::pkg_install("tibble")
r
pak::pkg_install("tidyverse/tibble")

Getting pak installed before you can use pak

The tool that installs packages needs to be installed too, and the project offers two routes.

The first is a prebuilt binary from the r-lib GitHub repository, chosen for your platform at install time:

r
install.packages("pak", repos = sprintf("https://r-lib.github.io/p/pak/stable/%s/%s/%s", .Platform$pkgType, R.Version()$os, R.Version()$arch))

That repository covers Linux on x86_64 and aarch64, macOS on x86_64 from High Sierra and aarch64 from Big Sur, and Windows on x86_64, each with R 3.5.0 up to R-devel, except that the aarch64 macOS build starts at R 4.1.0. There is one restriction worth knowing before you try it: on macOS only the official CRAN build of R is supported, and other builds such as Homebrew R are not.

The second route is the ordinary CRAN install:

r
install.packages("pak")

This potentially needs a C compiler on platforms where CRAN does not publish binary packages, which is the practical reason to prefer the binary route on macOS. Nightly builds and other platforms are handled on the project's installation page, and the full reference documentation lives at pak.r-lib.org, with a get started guide and a separate FAQ page for specific situations.

A C core under an R interface

The implementation is C, with the R layer in the `R/` directory and the native code in `src/`, which is the arrangement the project uses for the parts that need to be fast. Two configure scripts, `configure` and `configure.win`, are present at the root, and the `tools/` directory holds the package development helpers. The repository also carries a `Makefile` that regenerates the README from its source:

code
README.md: README.Rmd
	R -q -e 'rmarkdown::render("README.Rmd")'

The project publishes through CRAN, and the badge set in the README shows a stable lifecycle status, a current version badge, a download badge, code coverage through codecov, and an R-CMD-check workflow badge. The stable lifecycle marker is a signal about the project's own promise, not about compatibility with a particular R version.

It is also worth knowing how the documentation is produced. The README is generated from README.Rmd by rmarkdown, and the user-facing reference is a pkgdown site built from the `man/` directory, with a separate development reference. A team that wants to extend pak is looking at a C core with a generated R-facing layer, not at a pure R script collection.

Where pak is the wrong tool, and what the alternative looks like

For a single package from CRAN, `install.packages()` is the smaller answer. It ships with R, it is already understood by everyone on the machine, and pak's advantages, a solver, parallel fetching and caching, only pay off when there are many packages or several sources involved. Reaching for a new installer for one package is how a team ends up with a machine that only the person who set it up can rebuild.

The other alternative worth naming is a lockfile based workflow, where a file records the exact versions a project uses and the environment is rebuilt from that record. The difference in approach is worth being precise about. A lockfile pins versions and lets you reproduce an environment, and it does not need a solver at install time because the answer is already written down. pak works from the live state of a repository, resolves dependencies as it goes, and offers time travel to reach a past state. A project that needs byte-identical environments across machines and over years will want the lockfile as the source of truth, and can still use pak to fetch what the lockfile names.

The two are complementary rather than competing, and the mistake is choosing one and assuming the other is unnecessary.

Stable badge, GPL-3 licence and a recent release history

The licence is GPL-3, as stated in the README, and the source is published in the r-lib repository under the same organisation that maintains the wider R tooling ecosystem. GPL-3 is a copyleft licence, so a distributed modified version carries the obligation to offer its corresponding source. For a package used internally as an installed tool, that is rarely in tension with anything, but a team embedding pak code into a product it ships should read the licence rather than rely on the one-line statement.

The release record shows regular work. Version 0.11.1 was released on 2026-07-22, 0.11.0 on 2026-07-16 and 0.10.0 on 2026-06-07, and the last push to the repository was on 2026-10-19, with the default branch named main. The version is still below 1.0, which is normal for a package of this kind and means the API surface can still move.

The support channel is public. The project points bug reports at the GitHub issue tracker, general questions at the RStudio community forum using the `pak` tag, and there is a Telegram group for discussions. A maintained project with an open issue tracker and a documentation site is a reasonable thing to depend on, and the stable lifecycle badge is the closest thing here to a compatibility promise.

Editorial conclusion

pak fits an R team that installs many packages, mixes sources such as CRAN, Bioconductor, GitHub and local directories, and wants to see the dependency graph before it commits to an install. It is the wrong tool for a one-off install of a single CRAN package, and the wrong choice on a macOS machine running a non-CRAN R build, which the prebuilt binary repository does not support. Before switching, confirm that your R installation is one the binary repository covers, and decide whether the time travel and system dependency solvers are features you will use or features you will have to review for each new machine.

Frequently asked questions

What is pak in R and what does it replace?

pak is an R package installer that installs packages from CRAN, Bioconductor, GitHub, URLs, git repositories, local files and local directories. The project describes it as an alternative to `install.packages()` and `devtools::install_github()` that adds a dependency solver, parallel downloads, caching and time travel.

How do I install pak itself?

Either install a prebuilt binary from the r-lib GitHub repository using `install.packages("pak", repos = sprintf(...))` with the platform, OS and architecture substituted, or install the released version from CRAN with `install.packages("pak")`, which potentially needs a C compiler where CRAN has no binary packages.

Which platforms have prebuilt pak binaries?

Linux on x86_64 and aarch64, macOS on x86_64 from High Sierra and aarch64 from Big Sur, and Windows on x86_64, each covering R 3.5.0 to R-devel, with the aarch64 macOS build starting at R 4.1.0. On macOS only the official CRAN build of R is supported, so Homebrew R is not.

How do I see what a package depends on before installing it?

Use `pak::pkg_deps_tree("tibble")` to print the dependency tree and `pak::pkg_deps_explain("tibble", "rlang")` to explain why a specific dependency is present. A separate system dependency solver handles the packages needed on the operating system itself.

Is pak stable and how often is it released?

The project marks pak with a stable lifecycle badge, publishes it on CRAN, and released 0.11.1 on 2026-07-22, 0.11.0 on 2026-07-16 and 0.10.0 on 2026-06-07. The last push to the repository was on 2026-10-19, and the package is licensed GPL-3.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. r-lib/pak on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/r-lib-pak.svg)](https://hysenlabs.com/projects/r-lib-pak)

Was this useful?