CLI tool
freebsd/pkg avatar
freebsd/pkg

FreeBSD pkg: the package manager and its libpkg split

Package management tool for FreeBSD. Help at #pkg on Libera Chat or [email protected]

829 stars310 forksCNOASSERTION

At a glance

What is it?
The C program that installs packages on FreeBSD, built on a separate libpkg library, shipping a tar format defaulting to zstd, and bootstrapping itself from a small placeholder binary that ships with every supported release.
Who is it for?
Adopt pkg if you administer FreeBSD systems, build them from source or package software for the ports tree, since it is the distribution's own tool and the bootstrap path works even on a system that has never had a package database.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
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

pkg and libpkg are two layers, not one program

The README opens with the architecture rather than with features: pkg is built on top of libpkg, described as a library to interface with the package registration backends. That library abstracts the details of package management, and the list it abstracts is the useful part of the design: registration, remote repositories, package creation and updating.

So the split is between policy and mechanism. The library knows how to talk to a repository, how to register an installed package, how to build one and how to update one. The pkg command on top decides what the user asked for and in what order to do it. For a user, the practical consequence is that anything that needs to drive package installation programmatically goes through libpkg rather than by parsing pkg's output, and that the C library and its headers are a separate compilation surface from the command line tool.

The repository layout matches that division. There is a `libpkg/` directory and a `src/` directory for the command itself, with `external/` holding vendored third party code, `compat/` for portability shims, `mk/` for the build fragments, `scripts/`, `docs/` and `tests/` for the rest.

The primary language is C, and the repository is set up for a classic Unix build rather than a modern package manager script. There is a `configure` script with `configure.def`, a `Makefile.in`, an `autogen.sh`, a `Doxyfile.in` for API documentation, and even a `Kyuafile`, the test framework used on FreeBSD.

The package format is a tar archive with zstd by default

The pkg package format is described precisely, which is good news for anyone who needs to inspect or unpack a package without using pkg itself. It is a tar archive that may be raw or compressed using gz, bzip2, zstd or xz, and the default compression algorithm is zstd.

The archive itself has two kinds of element. First come the special files at the beginning of the archive, each of them starting with a plus sign, and then the data. That ordering matters to anyone writing tooling: the metadata is at the front, so a reader can read the package manifest without unpacking the entire payload.

The layout of the repository backs up the idea that the format is a defined contract rather than an implementation detail. There is a `features.md` file at the top level, a `freebsd.cfg` configuration file, a `NEWS` file for release notes, `FAQ.md`, `TODO.md` and a `COPYING` file carrying the licence text, plus an `AUTHORS` file and a `CONTRIBUTING.md`.

The format description also gives you a fallback. If pkg itself is broken on a system, the archive is still a tarball with a documented layout, so extracting it by hand or with an ordinary tar tool is possible. That is a real property of the design, not just a technicality.

pkg(7) bootstraps pkg(8) on every supported release

The bootstrap story is the most interesting piece of engineering in the repository, and it is explained in detail because it solves a genuinely awkward problem. All supported versions of FreeBSD contain /usr/sbin/pkg, which is also known as pkg(7). It is not the real tool. It is a small placeholder with just the minimum functionality required to install the real pkg(8).

The flow is short. You run any pkg(8) command line. pkg(7) intercepts the command, and if you confirm that this is your intention, it downloads the pkg(8) tarball, installs pkg(8) from it, bootstraps the local package database, and then proceeds to run the command you originally requested. In other words, the placeholder is a one-shot installer that replaces itself.

Two subcommands make that mechanism scriptable. More recent versions of pkg(7) understand `pkg -N` as a test to see if pkg(8) is installed without triggering the installation, and `pkg bootstrap [-f]` installs pkg(8), or forces it to be reinstalled, without performing any other actions:

bash
pkg -N
bash
pkg bootstrap [-f]

The `-N` check is the one worth remembering. It lets an image build or an installation script find out whether the full tool is present without causing a download, which is exactly the primitive you need to write an idempotent setup script.

Packages can come from disk, HTTP or SSH

The installation section is short, and its content tells you where the flexibility lies. pkg can install a package archive from the local disk, from a remote HTTP server, or from a remote SSH server. Three transports, one archive format.

That last option is the one that differs most from the usual Linux package manager experience. Installing over SSH means the fetch and the install happen against a remote host rather than a public mirror, which suits a locked down network where the machines that need packages cannot reach the internet but can reach an internal box you control. Because the package format is a self contained tar archive, the same archive works over all three transports without repackaging.

The repository reflects a system that is developed on several platforms, not only on FreeBSD itself. The README lists build badges for Sourcehut builds on FreeBSD, Alpine and Debian, and separately a GitHub Actions build badge. A package manager that is built and tested on Linux alongside its home operating system is a reasonable signal about the portability of its C code, and the `compat/` directory in the tree points at the same intent.

The licence classification is the one thing GitHub cannot categorise, with the terms in the COPYING file at the repository root. Read that file if you intend to redistribute the tool, since a package manager is often bundled into images or appliance builds.

Building from the repository rather than installing from the ports tree

The build system is a hand rolled configure and make setup rather than a modern autotools or meson wrapper, and the top level shows every part of it: `configure`, `configure.def`, `Makefile.in`, `autogen.sh` alongside `freebsd.cfg` and the `mk/` directory, plus `external/` for vendored dependencies.

A contributor starts from `autogen.sh`, which regenerates the configure script, then configures and builds with make. The presence of `Leak.suppress` and `UndefinedBehaviour.suppress` files is a useful detail: these are suppression files for memory leak and undefined behaviour sanitizers, which tells you the project runs its test suite under leak and undefined behaviour checking and records the known exceptions rather than ignoring them.

The `tests/` directory at the top level, and the Kyuafile, indicate the test suite is driven by the FreeBSD testing framework rather than by a bespoke runner. `docs/` holds the manual pages, with `Doxyfile.in` generating API documentation for the library.

For most people, none of this is the path to take. If you want pkg on a FreeBSD machine, the bootstrap described earlier is the supported route, and the ports tree is the distribution channel. The source tree matters to you if you are working on pkg itself, porting it to a platform the build scripts do not cover yet, or auditing the code that runs as root on your systems, which is a reasonable thing to want to do with a package manager.

What pkg does not try to be

pkg is not a Linux distribution package manager that happens to run on FreeBSD, and treating it as one leads to the wrong expectations on three fronts.

First, there is no cross distribution format here. The archive format is the FreeBSD one, with its own metadata files and its own registration database, and there is no deb or rpm compatibility layer. Second, there is no dependency solver comparable to the one in apt or dnf; the README describes libpkg as abstracting registration, remote repositories, package creation and updating, and does not describe a general dependency resolution layer. Third, the tool is the operating system's package manager, so its behaviour is tuned to a single system rather than to a portable cross platform contract.

The alternative worth naming is the source based approach: build from the FreeBSD ports tree, where each port has a Makefile that declares dependencies and fetches upstream sources, or use the base system and its own package set. The difference in approach is fundamental. A binary package manager ships prebuilt artifacts and installs them, while a ports tree compiles from source and resolves dependencies at build time. The ports tree gives you version choices and patches per package; pkg gives you a fast, reproducible install of what has already been built.

For teams that need to pin exact versions across many machines, or that want a package artefact to be reproducible, that distinction decides the question, and it has nothing to do with which tool is better written.

Release cadence and the state of the tree

The recent releases are 2.8.2 on 2026-08-10, 2.8.1 on 2026-07-21 and 2.8.0 on 2026-07-20, so two point releases landed within three weeks in the middle of 2026. The repository is not archived, and the last push was on 2026-10-22, which is more recent than the newest tag. Work is therefore landing on the main branch ahead of the next release, and `NEWS` at the top level is where those changes are written down before a tag.

Support is the obvious channel. The README points to the #pkg channel on the Libera Chat IRC Network for questions, and to the pkg issue tracker on GitHub for bug reports. An IRC channel is a genuinely different support model from a ticketing system, and it suits a tool that ships with an operating system: the people answering are frequently the same people who wrote the code or maintain the ports tree.

Because the tool installs software with root privileges on a production system, the audit question deserves attention. The source is public, the build is reproducible from a standard configure and make flow, and the sanitizers are run against the test suite with recorded suppressions. Those are the properties to check before you let a package manager run inside your image build.

Editorial conclusion

Adopt pkg if you administer FreeBSD systems, build them from source or package software for the ports tree, since it is the distribution's own tool and the bootstrap path works even on a system that has never had a package database. Do not expect it to be a general purpose cross platform package manager, and do not assume the libpkg split is a stable public API for third party tools, because the project describes libpkg as the layer that abstracts package management details while pkg sits on top. Verify first which pkg(8) your installed release carries, since all supported FreeBSD versions ship only the pkg(7) placeholder and the real tool arrives through the bootstrap.

Frequently asked questions

What is the difference between pkg(7) and pkg(8) on FreeBSD?

pkg(7) is the small placeholder in /usr/sbin/pkg that ships with every supported FreeBSD release and does nothing but install the real tool. pkg(8) is the full package manager, which pkg(7) downloads and installs when you run any pkg(8) command and confirm the intention.

How do I check whether pkg(8) is installed without triggering the bootstrap?

Run `pkg -N`. More recent versions of pkg(7) understand this as a test for whether pkg(8) is present, without downloading or installing anything.

What format is a FreeBSD package archive in?

It is a tar archive that may be raw or compressed with gz, bzip2, zstd or xz, with zstd as the default. The archive starts with special metadata files whose names begin with a plus sign, followed by the data.

What is libpkg and why was it split out?

pkg is built on top of libpkg, a library that interfaces with the package registration backends and abstracts package management details such as registration, remote repositories, package creation and updating.

Where can I get help with pkg or report a bug?

Questions go to the #pkg channel on the Libera Chat IRC Network, and bugs are filed in the pkg issue tracker on GitHub.

Official sources

  1. freebsd/pkg on GitHub
  2. Issues
  3. README
  4. Releases
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/freebsd-pkg.svg)](https://hysenlabs.com/projects/freebsd-pkg)

Was this useful?