Getting Started with cvcpkg

Install pre-built C/C++ libraries in seconds. No compilation required.

Installation

Linux, macOS, or BSD — install the standalone binary (no Python required):

curl -fsSL https://cvcpkg.org/install.sh | sh

Windows (PowerShell):

irm https://cvcpkg.org/install.ps1 | iex

Or install from PyPI:

pip install cvcpkg

Or install from the repository:

git clone https://github.com/transfix/libcvc-deps.git
cd cvcpkg
pip install .

Verify the installation:

cvcpkg --version

Quick Start

Install a package into a local prefix:

# Install zlib into ./deps
cvcpkg install zlib --prefix ./deps

# Install multiple packages
cvcpkg install boost hdf5 fftw3 --prefix ./deps

Choose build configuration and link mode:

# Release + shared (default)
cvcpkg install qt6 --prefix ./deps

# Debug + static
cvcpkg install qt6 --prefix ./deps --config debug --link static

List installed packages:

cvcpkg list --prefix ./deps

Your Project's Recipe Set

A project describes its dependencies with a recipe that lives beside its source, in a recipes/ directory the project vendors and version-controls. cvcpkg picks that directory up automatically when run from the project root — no flag, no separate manifest to keep in sync with the build.

Already have a project that builds? Generate the recipe from it:

# Detects CMake, autotools, Meson, a plain Makefile, or Python packaging
cvcpkg generate .

# Or scaffold a blank one to fill in by hand
cvcpkg init myapp

Declare what you depend on in recipes/myapp/recipe.yaml:

depends:
  build:
    - name: boost
      version: ">=1.86"
    - name: hdf5
    - name: qt6
    - name: vtk
  host_tools:
    - cmake
    - ninja

Install that dependency closure as prebuilt bundles, then build only your own code against them:

cvcpkg install-deps myapp --prefix ./deps
cvcpkg build myapp --prefix ./deps

Lock versions for reproducible builds:

cvcpkg lock     # creates cvc-lock.yaml
cvcpkg sync     # installs exactly what's in the lockfile
cvcpkg verify   # check the prefix still matches the lockfile

Migrating from a requirements file? cvcpkg install --from <file> and cvcpkg world still read a components list, and keep working through v2.0. New projects should carry a recipe instead: it is the same information in the file that already describes how the project builds, so the two cannot drift apart.

CLI Reference

Every top-level command, grouped the same way cvcpkg --help groups them. Any command takes --help for its full option list. CVCPKG_SERVER_URL and CVCPKG_TOKEN save repeating --server/--token.

Find and install packages

CommandWhat it doesExample
searchSearch the catalog by name, tag, or description cvcpkg search hdf5 --tag io
infoShow a component's versions, platforms, and deps cvcpkg info boost
installInstall prebuilt bundles into a prefix cvcpkg install boost hdf5 --prefix ./deps
install-depsInstall a recipe's whole dependency closure cvcpkg install-deps myapp --prefix ./deps
listList what is installed, or what is available cvcpkg list --prefix ./deps
upgradeMove installed components to newer catalog versions cvcpkg upgrade --prefix ./deps
downloadFetch archives without extracting them cvcpkg download qt6 --platform linux --dest ./dl

Reproducible prefixes

CommandWhat it doesExample
lockWrite/refresh cvc-lock.yaml pinning exact builds cvcpkg lock --prefix ./deps
syncMake the prefix match the lockfile exactly cvcpkg sync --prefix ./deps
verifyCheck prefix integrity against the lockfile cvcpkg verify --prefix ./deps
imageLocate and check VM/disk images in a prefix cvcpkg image list --prefix ./deps
cpkgInterop with a cpkg (getcpkg.net) project cvcpkg cpkg import ./cpkg.lua

Recipes and building

CommandWhat it doesExample
initScaffold a blank recipe from a template cvcpkg init mylib --build-system meson
generateDerive a recipe from a project that already builds cvcpkg generate ../mylib --dry-run
recipesList or inspect the recipes cvcpkg can see cvcpkg recipes --show grpc
buildBuild named recipes from source into a prefix cvcpkg build mylib --prefix ./deps
build-allBuild every recipe, in dependency order cvcpkg build-all --prefix ./prefix
packBuild, then archive the result for publishing cvcpkg pack mylib --prefix ./deps
pack-allBuild and archive every recipe cvcpkg pack-all --prefix ./prefix
validateCheck recipes against the JSON schema and each other cvcpkg validate recipes/mylib
worldLegacy. Build everything a requirements file names cvcpkg world --from requirements.yaml

Remote build fleet

CommandWhat it doesExample
builds monitor Live top-style dashboard of builders and running jobs cvcpkg builds monitor
builds submitQueue one remote build job cvcpkg builds submit zlib --platform linux
builds submit-dagQueue a whole dependency graph of jobs cvcpkg builds submit-dag --platform linux,freebsd gsl
builds listList build jobs, filtered by state cvcpkg builds list --status running
builds logView or follow a job's build log cvcpkg builds log 4821 -f
builds follow-dagFollow every job in a DAG at once cvcpkg builds follow-dag dag-91c2
builds cancel / pause / resume Control queued or running jobs (-dag variants act on a whole DAG) cvcpkg builds cancel-dag dag-91c2
builder listList registered builders and their state cvcpkg builder list --status online
builder statusShow one builder in detail cvcpkg builder status 4
builder logsRecent build activity, optionally per builder cvcpkg builder logs --builder star-00
builder runRegister this machine as a builder and poll for work cvcpkg builder run --name star-00 --max-jobs 4
builder fleetRun one builder against several servers at once cvcpkg builder fleet --config /etc/cvcpkg/fleet.yaml
builder gcReclaim disk from orphaned build scratch dirs cvcpkg builder gc --work-dir /tmp/cvcpkg-builder

Publishing

CommandWhat it doesExample
publishUpload bundle archives to a server cvcpkg publish dist/mylib-*.tar.zst --org my-team
recipe pushUpload a recipe directory so the server can build it cvcpkg recipe push mylib --recipes-dir recipes
recipe pullFetch a recipe (and its scripts) back down cvcpkg recipe pull mylib --dest ./recipes
yank / unyankHide a version from resolution, or restore it cvcpkg yank mylib --version 2.1.0
nukePermanently delete a yanked bundle (admin) cvcpkg nuke mylib --version 2.1.0
rev-bumpBump cvc_revision for a recipe and its dependents cvcpkg rev-bump openssl
next-revisionPrint the revision a --bump pack would use cvcpkg next-revision zlib
cascade-bumpPublished-aware family bump across a recipe tree cvcpkg cascade-bump boost

Signing

CommandWhat it doesExample
keyCreate, list, and trust Ed25519 signing keys cvcpkg key generate --name release
signSign an archive cvcpkg sign dist/mylib-2.1.0.tar.zst --key release
verify-sigVerify an archive against the trusted keys cvcpkg verify-sig dist/mylib-2.1.0.tar.zst

Catalog and cache

CommandWhat it doesExample
catalogBrowse or refresh the component catalog cvcpkg catalog refresh
catalog-generateBuild a unified catalog from per-platform indexes cvcpkg catalog-generate --out catalog/latest.yaml
cacheInspect or clear the local build cache cvcpkg cache stats
gcPrune the download cache cvcpkg gc --older-than 30d
cleanRemove leftover build work directories cvcpkg clean

Server, orgs, and accounts

CommandWhat it doesExample
loginSign in with your SSO identity (browser or device code) cvcpkg login --server https://cvcpkg.org
logoutSign out and revoke the local session cvcpkg logout
whoamiShow who you are signed in as, and your orgs cvcpkg whoami
authManage sessions/devices; list identity providers cvcpkg auth providers
registerRequest an API token from a server cvcpkg register --server https://cvcpkg.org
tokenCreate, list, and revoke API tokens cvcpkg token list
userLook up a user profile cvcpkg user show alice
orgCreate organizations and manage their members cvcpkg org create my-team --display-name "My Team"
serverAdminister a running server cvcpkg server stats
webhookManage server webhooks cvcpkg webhook add https://ci.example/hook

Diagnostics and legacy

CommandWhat it doesExample
doctorCheck this machine can build and install packages cvcpkg doctor
telemetryOpt in/out of anonymous environment telemetry cvcpkg telemetry status
add / remove Legacy. Edit a requirements file's component list cvcpkg add boost --from requirements.yaml

CMake Integration

Point CMAKE_PREFIX_PATH at your cvcpkg prefix:

cmake -B build \
  -DCMAKE_PREFIX_PATH=$(pwd)/deps \
  -DCMAKE_BUILD_TYPE=Release

Use find_package() in your CMakeLists.txt as usual — all packages install standard CMake config files:

find_package(Boost REQUIRED COMPONENTS system filesystem)
find_package(HDF5 REQUIRED COMPONENTS CXX)
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
find_package(VTK REQUIRED)

Creating Recipes

A recipe describes how to fetch, build, and package a library. Each recipe lives in its own directory under recipes/ with a recipe.yaml and one or more build scripts.

Create a recipe directory:

mkdir -p recipes/mylib
cd recipes/mylib

Write recipe.yaml — the full schema:

schema_version: 1

recipe:
  name: mylib
  upstream_version: "2.1.0"
  cvc_revision: 1
  maintainer: "Your Name"
  maintainer_email: "you@example.com"
  description: "A great library"
  homepage: https://example.com/mylib
  license: MIT
  tags: [utils, io]

source:
  type: tarball
  url: https://example.com/mylib-2.1.0.tar.gz
  sha256: abc123...   # required for tarball sources
  strip_components: 1

depends:
  build:
    - name: zlib      # build-time dependency
    - name: boost
      version: ">=1.86"
  host_tools:
    - cmake
    - ninja

build:
  matrix:
    - platform: linux
      script: build.sh
    - platform: macos
      script: build.sh
    - platform: windows
      script: build.ps1

package:
  files:
    - lib/libmylib*
    - include/mylib/**
  cmake_packages:
    - { name: mylib, targets: [mylib::mylib] }

test:
  script: test.sh

Write a build script (build.sh). Standard CVC_* environment variables are provided:

#!/usr/bin/env bash
set -euo pipefail

cmake -S "$CVC_SOURCE_DIR" -B "$CVC_BUILD_DIR" -G Ninja \
  -DCMAKE_INSTALL_PREFIX="$CVC_INSTALL_DIR" \
  -DCMAKE_PREFIX_PATH="$CVC_DEPS_PREFIX" \
  -DCMAKE_BUILD_TYPE="$CMAKE_BUILD_TYPE" \
  -DBUILD_SHARED_LIBS="$BUILD_SHARED_LIBS"

cmake --build "$CVC_BUILD_DIR" --parallel
cmake --install "$CVC_BUILD_DIR"

Validate your recipe and build locally:

# Validate recipe.yaml schema
cvcpkg validate recipes/mylib

# Build and package
cvcpkg build recipes/mylib --prefix ./deps

# The archive is written to dist/
ls dist/mylib-*.tar.gz

Source types: tarball, git, vcpkg, brew, apt, vendored, and prebuilt. For tarballs, the sha256 field is required. A mirror URL can be specified as a fallback.

Accounts & Signing In

You sign in to cvcpkg with your SSO identity (an OIDC provider such as a tx.wtf ring). Signing in gives you a named identity — a handle like alice — that org owners can add to their organizations by name, and lets you mint your own API tokens. Machines (CI, builders) keep using API tokens directly; humans sign in.

On the website

Click Sign in (or open /login) and choose your identity provider. If the server is connected to several providers you pick which one; if it has just one you go straight there.

You land on /account, where you can see your handle and role and mint API tokens for use with the CLI or CI. Each token is named <you>.<label> and the secret is shown once.

From the CLI

Sign in from a terminal. On a desktop this opens your browser; over SSH or on a headless box it prints a short code to approve in any browser:

cvcpkg login --server https://cvcpkg.org

# force the device-code flow (no local browser)
cvcpkg login --server https://cvcpkg.org --code

If the server offers several identity providers, list them and pick one (otherwise you choose in the browser):

cvcpkg auth providers
cvcpkg login --server https://cvcpkg.org --provider ringb

Check who you are, and sign out when done. Once you are signed in, other commands (install, search, org, publish…) use that session automatically — no --token needed:

cvcpkg whoami
cvcpkg auth devices     # your active sessions
cvcpkg logout

CI and automation should not use cvcpkg login. Mint a machine token on /account and export it as CVCPKG_TOKEN instead.

Publishing Builds

Publishing requires a token with the publisher or admin role. Publishing to the community archive is admin-gated — contact an administrator for access. Organization members can publish to their own org namespace.

Publish an archive to a cvcpkg server:

cvcpkg publish dist/mylib-2.1.0-linux-x86_64-release-shared.tar.gz \
  --server https://cvcpkg.org \
  --token cvctok_...

Publish to an organization namespace:

cvcpkg publish dist/mylib-*.tar.gz \
  --server https://cvcpkg.org \
  --token cvctok_... \
  --org my-team

Tag a release (optional; untagged builds are "live"):

cvcpkg publish dist/mylib-*.tar.gz \
  --server https://cvcpkg.org \
  --token cvctok_... \
  --release-tag v2.1.0

Token roles: reader (read-only access), publisher (publish + yank), admin (full access including token/org management and hard deletes). Use CVCPKG_SERVER_URL and CVCPKG_TOKEN environment variables to avoid passing flags every time.

Organizations

Organizations let teams publish and manage packages under a shared namespace. Each org has a configurable storage quota (default 10 GiB) set by the CVCPKG_ORG_STORAGE_LIMIT_BYTES environment variable. Admins can adjust the limit per-org via the API.

You create and administer organizations two ways: from the website after signing in, or from the CLI. Creating an org needs a publisher or admin role; managing its members needs to be an owner of that org (or a global admin).

Create an organization

From the CLI — you become its first owner:

cvcpkg login --server https://cvcpkg.org      # once, if not already signed in
cvcpkg org create my-team --display-name "My Team"

# optional: --description, --homepage, --private (members-only visibility)

Or over the REST API directly:

curl -X POST https://cvcpkg.org/v1/orgs \
  -H "Authorization: Bearer cvctok_..." \
  -H "Content-Type: application/json" \
  -d '{"slug": "my-team", "display_name": "My Team"}'

Administer members — on the website

Open your org at /org/<slug> and click Manage (owners only). From /org/<slug>/manage you can add a member by their handle, choose their role, and remove members — no command line needed. Grant owner to make someone a co-administrator of the org.

Administer members — from the CLI

A member is either an SSO username (a person — use --user; they must have signed in at least once so the handle exists) or a machine-token name (use --token-name). Grant --role owner to make them an org admin.

# add a person as a co-owner
cvcpkg org add-member my-team --user alice --role owner

# add a CI/machine token as a plain member
cvcpkg org add-member my-team --token-name acme-ci --role member

# list members (shows each one's kind: user / token / orphan)
cvcpkg org members my-team

# remove a member
cvcpkg org remove-member my-team --user alice

The same over the REST API (principal_kind is user, token, or auto):

curl -X POST "https://cvcpkg.org/v1/orgs/my-team/members?token_name=alice&role=owner&principal_kind=user" \
  -H "Authorization: Bearer cvctok_..."

Update the storage limit (admin only):

# Set to 50 GiB
curl -X PATCH https://cvcpkg.org/v1/orgs/my-team \
  -H "Authorization: Bearer cvctok_..." \
  -H "Content-Type: application/json" \
  -d '{"storage_limit_bytes": 53687091200}'

Storage enforcement: When publishing to an organization, the server checks that storage_used + upload_size ≤ storage_limit. If the limit is exceeded the upload is rejected with HTTP 413. Organizations require the database backend (CVCPKG_DATABASE_URL).

Self-Hosting a Package Server

Run a local server for development or private packages:

cvcpkg-server run --state-dir ./my-packages --port 8420

Or use the Docker Compose production stack:

# from the repo root
cp .env.production.example .env.production
# Edit .env.production with your secrets
docker compose -f docker-compose.production.yml \
  --env-file .env.production up -d

Create an API token and publish packages:

# Create a publisher token
cvcpkg-server token create --name ci-bot --role publisher

# Publish an archive
cvcpkg publish my-lib-1.0-linux-x86_64-release-shared.tar.zst \
  --server http://localhost:8420 \
  --token cvctok_...

Remote Builders

Remote builders are worker machines that automatically build packages from recipes. The server dispatches build jobs to registered builders via WebSocket. Results (archives and logs) are streamed back and published to the package index.

Push recipes to the server — recipes define how to build a package:

cvcpkg recipe push zlib \
  --server https://cvcpkg.org --token cvctok_...

# Or push all local recipes at once
cvcpkg recipe push-all --server https://cvcpkg.org --token cvctok_...

Register a builder — create a builder token and start the worker:

# Create a builder token (on the server)
cvcpkg-server token create --name builder-01 --role builder

# Start the builder worker
cvcpkg builder run \
  --server https://cvcpkg.org \
  --token cvctok_... \
  --max-jobs 2

Submit build jobs — build a single recipe or a full dependency graph:

# Single build
cvcpkg builds submit zlib --platform linux --arch x86_64 \
  --server https://cvcpkg.org --token cvctok_...

# DAG build (resolves dependencies automatically)
cvcpkg builds submit-dag tiff --platform linux --arch x86_64 \
  --server https://cvcpkg.org --token cvctok_...

Monitor builds — use the web UI or CLI to track progress:

# List recent builds
cvcpkg builds list --server https://cvcpkg.org --token cvctok_...

# Or visit the web dashboard:
#   /builders  — registered builders and status
#   /builds    — all build jobs with filters
#   /build/42  — single build with live log

DAG builds automatically resolve recipe dependencies and submit them in the correct order. Leaf dependencies build first; the target recipe builds only after all its dependencies succeed. Use the Build Jobs dashboard to view DAG progress.

Server Configuration

Server settings are controlled via environment variables or cvcpkg-server run CLI flags. State (index, tokens, audit log, archives) is stored under the state directory (CVCPKG_SERVER_STATE_DIR, default /var/lib/cvcpkg-server). The HMAC signing key is stored in <state-dir>/hmac_key (mode 0600).

Variable / Flag Default Description
CVCPKG_DATABASE_URL
--database-url
empty PostgreSQL URL; enables DB backend (required for orgs)
CVCPKG_SERVER_STATE_DIR
--state-dir
./cvcpkg-server-data Directory for index, tokens, audit log, and archives
CVCPKG_SERVER_STORAGE_URI
--storage
file://<state-dir> Storage backend URI (file, S3, etc.)
CVCPKG_MAX_UPLOAD_BYTES
--max-upload-bytes
4 GiB Maximum bundle upload size. Accepts a byte count or a human size (8GB, 512MB); units are binary.
CVCPKG_CHUNK_SIZE 8 MiB Chunk size for chunked uploads
CVCPKG_UPLOAD_SESSION_TTL 3600 s Chunked upload session timeout
CVCPKG_RATE_LIMIT_RPM 300 Write-endpoint rate limit (requests/min, 0 = disabled)
CVCPKG_ORG_STORAGE_LIMIT_BYTES 10 GiB Default per-organization storage quota
CVCPKG_CORS_ORIGINS empty Comma-separated allowed CORS origins
CVCPKG_SERVER_REQUIRE_AUTH_READS
--require-auth-reads
false Require auth token for read endpoints
CVCPKG_LOG_JSON
--log-json
false Structured JSON log output
--host 0.0.0.0 Bind address
--port 8420 Listen port
--workers 1 Number of uvicorn workers

For Docker deployments, copy .env.production.example and set POSTGRES_PASSWORD, POSTGRES_USER, POSTGRES_DB, BACKEND_PORT, and CVCPKG_RELEASE. See docker-compose.production.yml.

Branding: Customize the landing page with CVCPKG_SITE_TITLE, CVCPKG_SITE_TAGLINE, and CVCPKG_SITE_HERO. Set CVCPKG_GITHUB_REPO to change the GitHub link (default: transfix/libcvc-deps). CVCPKG_SITE_LOGO overrides the favicon and social image — either an https:// URL or a path to a local image file (png/svg/ico/jpg/webp); unset serves the bundled CyberPC Angel, LLC gears logo. CVCPKG_SITE_URL sets the origin used to build absolute social-image URLs (default: https://cvcpkg.org).

REST API

The cvcpkg server exposes a full REST API. Key endpoints:

Method Endpoint Description
GET /v1/packages List all packages (filterable, paginated)
GET /v1/packages/{name} Get builds for a specific package
GET /v1/catalog Full catalog (YAML)
GET /v1/deps Dependency graph and recipe metadata
GET /v1/download/{file} Download a package archive
POST /v1/publish Publish a new package
POST /v1/packages/{name}/{ver}/yank Yank a package version
DEL /v1/packages/{name}/{ver} Delete a package (admin)

See the full interactive API documentation at /docs (Swagger UI) or /redoc (ReDoc).