brig docs

Getting started

Install

On this page

Use Homebrew on macOS. Use install.sh on Linux, or on a Mac without Homebrew.

Method What it installs
Homebrew on macOS brig, brigd, hull, and the shell completions
install.sh on macOS brig, brigd, hull with vz-runner and hvi, and cosign
install.sh on Linux the runtime bundle (nerdctl, containerd, the urunc shim), brig and brigd from the Brig release, and cosign
Source build brig and brigd only, never a runtime

macOS with Homebrew #

You need a Mac with Apple silicon, macOS 15 or newer, and Homebrew (brew.sh).

brew tap brig-sh/brig
brew trust brig-sh/brig
brew install --cask brig

Homebrew puts the binaries on PATH and installs the bash, zsh and fish completions.

brew trust is required. The cask comes from a third-party tap, and Homebrew refuses to install a cask from a tap that is not trusted.

What you see What to do
Unknown command: trust Run brew update, then run the command again.
brew install gives an older version than you expected The tap can lag the newest release. Use install.sh.
brew install fails Use install.sh.

If the host runs macOS 14, read Platform support before you run an agent.

Unreleased builds #

Two extra casks carry builds that are not releases. Use them to try a feature before it reaches a release.

brew install --cask brig-sh/brig/brig@main           # the tip of main
brew install --cask brig-sh/brig/brig@experimental   # a branch someone promoted
Cask When it moves Runtime it pulls
brig@main On every merge to main, so brew upgrade follows what is coming hull@main
brig@experimental When a maintainer promotes a particular ref to it hull@experimental

To get an unmerged branch onto brig@experimental, ask on the pull request, or run the channel workflow with that ref.

Warning Neither cask is supported. They can break, and they move without notice. Do not file a bug report against one, unless the bug is the reason you were asked to install it.

Only one of the three casks can be installed at a time. To go back to the supported build, remove the channel's hull as well:

brew uninstall --cask brig@main hull@main
brew install --cask brig

If you remove only brig@main, hull@main stays. The stable brig then asks for hull, which conflicts with it.

install.sh #

You need curl, tar, and either sha256sum or shasum on PATH.

curl -fsSL https://raw.githubusercontent.com/brig-sh/brig/main/install.sh | sh

The script downloads the newest release for your OS and architecture. It checks every archive against a SHA-256 checksum. It installs to BRIG_INSTALL_DIR. If that directory is not writable, it uses sudo.

hull ships as one archive that holds three executables. All three go into the same directory, because hull looks for a runner next to its executable.

Executable What it is
hull the CLI Brig drives
vz-runner the Virtualization.framework backend
hvi the Hypervisor.framework backend

See Linux for what the script installs and where the files go.

The script stops in two cases:

Host Result
Neither sha256sum nor shasum on PATH The install stops. It does not skip the checksum.
Intel Mac The install is refused before anything is written. hull runs on Apple silicon only, so there is no runtime to drive.

install.sh does not install shell completions. See Completions to add them.

install.sh checks each archive by hash. It does not check the cosign signature on checksums.txt. To check the signature, see Release verification.

Settings #

BRIG_INSTALL_DIR=~/bin BRIG_VERSION=v0.2.0 sh install.sh
Variable Effect
BRIG_INSTALL_DIR Overrides the destination. Unset, the destination is /usr/local/bin.
BRIG_VERSION Pins a Brig release instead of fetching the newest one.
HULL_VERSION Pins a hull release. Brig and hull are versioned independently.
BRIG_INSTALL_HULL=0 Skips hull, and leaves macOS without a runtime.
BRIG_INSTALL_COSIGN=0 Skips cosign, and leaves the boot chain unverified.
BRIG_INSTALL_ROOTLESS=1 Linux only. Asks for the rootless bundle from a node-wide install. See Rootless installs.
BRIG_INSTALL_RUNTIME=0 Linux only. Skips the runtime bundle. See Existing runtime.

Put BRIG_INSTALL_DIR on your PATH, because hull finds cosign there. If the destination is not on PATH, the boot check reports "no tooling" and install.sh warns you.

cosign #

cosign checks the kernel, initrd and guest agent that every sandbox boots. It also checks the container image behind an agent. If a cosign is already on PATH, install.sh does not install another.

Without cosign on PATH, those checks report "no tooling". In the default mode, Brig prints a warning and still fetches, writes and boots the assets. On a host without Homebrew, HULL_VERIFY=require and BRIG_VERIFY=require are usable only after you install cosign.

cosign is a 130 MB download, the largest item that install.sh installs. install.sh pins it by version and by hash, because the cosign release cannot be checked without cosign.

The macOS build of cosign is ad-hoc signed upstream, and Gatekeeper rejects such a binary. It runs because a curl download carries no quarantine attribute.

Linux #

Brig drives nerdctl over containerd. The urunc shim boots the container as a microVM, so a Linux sandbox does not share the host kernel. The boundary is not identical to the one on macOS: see Security.

install.sh installs all of it from the runtime bundle that brig-standalone-linux publishes. The bundle packages nerdctl, a private containerd and urunc with the monitors and the guest kernel. install.sh pins the bundle tag. The bundle's install.sh is a release asset, checked against the same signed checksums.txt as the bundle.

The bundle also carries a brig and a brigd. install.sh replaces them with the ones from the Brig release, so BRIG_VERSION chooses the Brig version on Linux too. The runtime and Brig are versioned separately.

The bundle puts its launcher on PATH. The launcher sets the environment that points brig at the private containerd.

With the bundle, install.sh ignores BRIG_INSTALL_DIR and reports this, because the binaries go into the bundle's tree.

Install modes #

A node-wide install is the default.

Node-wide Per-user
How to run install.sh Under sudo. It needs root. As a normal user. It asks for sudo at no point.
Tree /var/lib/brig ~/.local/share/brig
Launcher /usr/local/bin/brig ~/.local/bin
containerd The bundle's private containerd Your own containerd, under a systemd user unit
Bundle The plain bundle, or the rootless one with BRIG_INSTALL_ROOTLESS=1 Always the rootless one
cosign Installed by install.sh The one the bundle carries

A per-user install writes nothing outside your home.

A host can have both installs. The node-wide launcher then runs whenever /usr/local/bin comes first on PATH. To run the per-user install, put ~/.local/bin ahead of it:

export PATH="$HOME/.local/bin:$PATH"

After it installs the launcher, install.sh checks the order. If another brig comes first, it prints this line.

Rootless installs #

There are two rootless routes:

  • A per-user install always takes the rootless bundle. The plain bundle cannot serve it. It reports this and does not install a part of itself.
  • BRIG_INSTALL_ROOTLESS=1 asks for the same bundle from a node-wide install. Each user can then run brig-ctl rootless against the shared tree.

For either route, a user with root must prepare the host once:

  • a subuid range
  • access to /dev/kvm and /dev/vhost-vsock
  • the uidmap package
  • an AppArmor profile, on Ubuntu 24.04 and later

Before it unpacks anything, the installer reports which of those are missing. The bundle's docs/rootless.md says what each one is for.

oras #

oras fetches the boot bundle for a genericBoot profile. The boot bundle is the kernel and container-initrd that let an ordinary container image boot as a guest.

Profiles Need oras
claude-code, codex, gemini, grok, opencode, ubuntu Yes
claude-desktop, cursor No

Without oras on PATH, a genericBoot run fails. The error names the artifact to fetch by hand and the directory to put it in.

claude-desktop cannot run on Linux. See Platform support.

Existing runtime #

BRIG_INSTALL_RUNTIME=0 skips the bundle and installs brig and brigd alone. Use it on a host that already has nerdctl, containerd and urunc.

That urunc must be a build of the branch that the bundle uses. No urunc release reads the boot annotations, so a genericBoot profile never becomes ready on one. A genericBoot profile also needs oras and cloud-hypervisor, which the bundle carries.

Runtimes covers the full command surface each runtime needs.

docker and runc

docker. docker is accepted in place of nerdctl for an image that carries its own kernel. A genericBoot profile is refused on docker, because docker does not pass the boot annotations urunc needs through to the runtime. Six of the eight shipped profiles are genericBoot.

runc. BRIG_CONTAINERD_RUNTIME=runc asks for a plain container, using runc directly:

BRIG_CONTAINERD_RUNTIME=runc brig run claude

A runc sandbox shares the host kernel with the agent. That is a weaker boundary than a microVM. brig info reports which one a run got.

Source build #

You need Go 1.25.0 or newer, the minimum that go.mod states.

git clone https://github.com/brig-sh/brig
cd brig
make build

make build writes brig and brigd into the current directory. It does not build a runtime.

A source build of Brig needs no signing and no entitlement, because Brig reaches the hypervisor only through hull.

A hull built from source cannot boot a sandbox without a Developer ID certificate. See Runtimes for what that needs.

Verify the install #

brig version
brig doctor

brig version prints the version you installed. brig doctor prints one line per check: host, virtual, runtime, boot, verify, profiles, secrets, brigd and image. Each line carries one of three marks: ok, !! or --.

Line Meaning
ok beside runtime Brig found the hull or nerdctl it drives, and where.
!! beside boot Normal before you run an agent. Brig fetches boot assets on first use.
!! anywhere else The line names the fix beside it.

Next: Quickstart.

Release verification #

This step is optional. You need cosign. You also need checksums.txt, checksums.txt.pem and checksums.txt.sig, downloaded with the archive from the release page.

cosign verify-blob \
  --certificate checksums.txt.pem \
  --signature checksums.txt.sig \
  --certificate-identity-regexp \
    '^https://github\.com/brig-sh/brig/\.github/workflows/release\.yml@refs/tags/v' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  checksums.txt

shasum -a 256 -c checksums.txt --ignore-missing

The first command checks the signature on checksums.txt with keyless cosign. There is no key. A short-lived certificate, bound to the identity of the release workflow, takes its place.

The second command checks the archives against the hashes in checksums.txt.

The macOS binaries also carry a Developer ID signature, notarized with Apple. Gatekeeper checks that signature, and does not check the cosign one.

spctl -a -vv -t install "$(which brig)"   # source=Notarized Developer ID

Security says what each check proves, and why Brig signs releases this way.

Platform support #

Host Supported
Mac, Apple silicon, macOS 15 or newer Yes
Mac, Apple silicon, macOS 14 Yes, with BRIG_HYPERVISOR=vz BRIG_NETWORK=shared
Intel Mac No
Linux, x86-64 or arm64 Yes, with the runtime bundle install.sh installs

macOS 15 is the minimum that Brig enforces for hull's hvi backend. The project tests on macOS 26. Neither Brig nor hull refuses macOS 15 or macOS 16 because it is older than 26.

claude-desktop limits #

claude-desktop is a graphical profile, and it has three limits:

Limit Reason
It cannot run on Linux. The Linux runtime refuses a graphical profile, on nerdctl and on docker alike. The refusal names macOS as where it can run.
On macOS it needs Apple silicon. Its image is published for arm64 only.
It needs the vz backend. vz is the only one of the three backends with a console. A graphical profile is refused on hvi and qemu.

brig agent ls lists claude-desktop on every platform, with no marker of these limits.

macOS 14 and Intel Macs

macOS 14. Set both variables before you run an agent:

export BRIG_HYPERVISOR=vz
export BRIG_NETWORK=shared

Six of the eight shipped profiles ask for hvi. hvi depends on an in-kernel interrupt controller that Apple first shipped in macOS 15. On an older macOS, Brig refuses the run before the virtual machine monitor can crash. BRIG_HYPERVISOR=vz avoids that minimum.

Those profiles also ask for isolated networking, which vz cannot provide. BRIG_NETWORK=shared covers that for every run. You can pass --network shared on each run instead. The shared network does not promise to separate sandboxes. See Policies for the network postures.

The refusal needs a version that Brig can read from the host. If the host does not report its version, Brig does not refuse the run and proceeds to the boot.

Intel Macs. Brig's source does not check the host architecture. The release publishes a darwin/amd64 archive of brig and brigd with the arm64 one. A manual download or a source build of brig succeeds on an Intel Mac. A run then fails at the runtime check, because Brig finds no hull to drive. hull needs Apple silicon, and no amd64 build of hull exists.

Type a command, a flag or an error message.