vix install
vix install installs Vix Registry dependencies.
Use it when you want to install the exact dependencies pinned in vix.lock, generate CMake integration files, or install one package globally.
vix installOverview
vix install has two modes:
project mode
global modeProject mode installs dependencies for the current project:
vix installGlobal mode installs one package globally:
vix install -g gk/jwtThe command is part of the Vix Registry workflow.
It connects:
vix.json
vix.lock
registry index
global package store
project .vix/deps
.vix/vix_deps.cmake
vix.app
CMakeUsage
vix install
vix install -g <package>
vix install --global <package>Quick Git Workflows
Try One File
For a temporary experiment, pass a Git dependency directly to vix run:
vix run main.cpp --dep https://github.com/fmtlib/fmtVix creates a temporary dependency environment, resolves the latest stable Git tag, detects the main CMake target, builds and runs the file, then removes the temporary project files. The current directory is not modified.
A compact version can be written with @:
vix run main.cpp --dep https://github.com/fmtlib/fmt@11.2.0For advanced cases use a structured dependency spec:
vix run main.cpp \
--dep "git=https://github.com/fmtlib/fmt;tag=11.2.0;target=fmt::fmt"Use --save to turn the temporary dependency into a project dependency:
vix run main.cpp --dep https://github.com/fmtlib/fmt --saveInitialize an Existing Folder
vix init makes the current directory a minimal Vix project. It does not create a full template like vix new.
mkdir fmt-test
cd fmt-test
cat > main.cpp <<'CPP'
#include <fmt/format.h>
int main()
{
fmt::print("Hello from fmt!\n");
}
CPP
vix init
vix install https://github.com/fmtlib/fmt
vix run main.cppA generated vix.app looks like this:
name = "fmt-test"
type = "executable"
standard = "c++20"
sources = ["main.cpp"]Useful options:
vix init --name hello
vix init --lib
vix init --standard c++23
vix init --forceGit Dependency Autodetection
For common CMake and header-only repositories, this is enough:
vix install https://github.com/fmtlib/fmtWhen no revision is provided, Vix reads Git tags, keeps SemVer-compatible stable tags, ignores prereleases by default, and chooses the newest stable version. The lockfile stores the exact commit, so later vix build and vix run do not move to a newer tag automatically.
Vix also tries to detect the main CMake target. For fmt, it selects:
target = "fmt::fmt"Explicit options still win when autodetection is ambiguous or when you want another target:
vix install https://github.com/fmtlib/fmt \
--tag 11.2.0 \
--target fmt::fmt-header-onlyHeader-only repositories without CMake can be detected when they expose one clear include root such as include/ or single_include/. Otherwise declare it explicitly:
vix install https://github.com/example/headers \
--header-only \
--include includeGit dependencies currently support CMake and header-only repositories. Other build systems are not configured automatically.
Basic examples
# Install project dependencies from vix.lock
vix install
# Install a global package
vix install -g gk/jwt
# Install a specific global version
vix install -g gk/jwt@1.0.0
# Install with a semver range
vix install -g gk/jwt@^1.0.0
# Scoped-style syntax is also accepted
vix install -g @gk/jwt
vix install -g @gk/jwt@~1.2.0What it does
| Mode | Command | Purpose |
|---|---|---|
| Project mode | vix install | Install exact project dependencies from vix.lock. |
| Global mode | vix install -g <pkg> | Resolve and install one package globally. |
Project mode
Run:
vix installProject mode reads:
vix.lockThen it installs the exact locked dependencies. It does not choose new versions. It does not rewrite dependency ranges. It does not behave like vix update.
The main purpose is reproducibility:
same vix.lock
same dependency versions
same commits
same install resultProject install outputs
A project install can create:
.vix/
├── deps/
│ └── ...
└── vix_deps.cmakeImportant outputs:
| Path | Purpose |
|---|---|
.vix/deps/ | Project-local links or copies of installed packages. |
.vix/vix_deps.cmake | Generated CMake integration for dependencies. |
Do not edit:
.vix/vix_deps.cmakeIt is generated by Vix.
Global mode
Run:
vix install -g gk/jwtor:
vix install --global gk/jwtGlobal mode resolves one package from the registry, fetches it, prepares its Vix dependencies, builds it with CMake when needed, runs CMake install rules when they exist, and records installed files in the global manifest.
Typical Linux/macOS layout:
~/.vix/global/
├── bin/
├── include/
├── lib/
├── share/
├── build/
├── tmp/
└── installed.jsonOn Windows the same layout is used under the Vix user root unless VIX_GLOBAL_PREFIX is set. Global install does not use /usr/local by default and does not require sudo.
Global install is useful when you want a package available outside one specific project, including CLI packages installed similarly to npm global commands.
Global install syntax
Accepted package forms:
namespace/name
namespace/name@version
namespace/name@range
@namespace/name
@namespace/name@version
@namespace/name@rangeExamples:
vix install -g gk/jwt
vix install -g gk/jwt@1.0.0
vix install -g gk/jwt@^1.0.0
vix install -g @gk/jwt
vix install -g @gk/jwt@~1.2.0Global executables
If a package installs executables into bin through CMake, those files are recorded as global commands. Example:
vix install -g vixcpp/ovi
ovi --version
ovi --help
ovi greet GaspardVix installs the real executable under ~/.vix/global/bin. If that directory is not already in PATH, Vix updates the user shell configuration for Bash, Zsh, or Fish. When a user bin directory such as ~/.local/bin is already in the current PATH, Vix also creates a command shim there so the command is available immediately in the current terminal. On Windows, Vix updates the user PATH and handles .exe, .cmd, and .bat.
CMake install and Vix fallback
Global install prefers the package's CMake install rules:
cmake -S <source> -B <build> \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=<temporary-stage-prefix>
cmake --build <build> --config Release
cmake --install <build> --config ReleaseIf a Vix package has dependencies, Vix prepares the package checkout with .vix/deps and .vix/vix_deps.cmake before configuring it, the same integration used by vix build. If CMake install produces no files for a header-only package, Vix falls back to installing headers and keeps the source checkout recorded so vix run and vix build can use the package's source CMake integration.
A package that provides a CLI should still declare CMake install rules for its executables:
add_executable(ovi_cli src/main.cpp)
set_target_properties(ovi_cli PROPERTIES OUTPUT_NAME ovi)
install(TARGETS ovi_cli RUNTIME DESTINATION bin)Declaring commands
A package may document and validate expected commands in vix.json using bin:
{
"bin": {
"ovi": "ovi_cli",
"ovi-doctor": "ovi_doctor_cli"
}
}The keys are command names exposed in bin; the values are CMake target names for documentation. This field is optional. CMake install() still decides what is installed. If bin is present, Vix verifies that every declared command was installed. Command names must be plain file names, not paths.
The older explicit form is also accepted:
{
"executables": [{ "name": "ovi", "target": "ovi_cli" }]
}Listing and uninstalling globals
vix list -g
vix uninstall -g vixcpp/ovi
vix uninstall -g @vixcpp/oviGlobal install and uninstall print a short npm-style result with elapsed time, for example vixcpp/ovi@0.1.0 installed globally in 1.2s or removed vixcpp/ovi@0.1.0 in 90ms. Uninstall removes only the files and command shims recorded for that package and then removes empty directories left behind. It does not remove unmanaged files from the global prefix.
Version resolution
When a package version is not provided, Vix selects the latest available version from the registry.
vix install -g gk/jwtWhen a version range is provided, Vix resolves the highest version that satisfies the range.
vix install -g gk/jwt@^1.0.0Supported range forms include common semver-style inputs such as:
1.2.3
^1.2.3
~1.2.3
>=1.0.0
<=2.0.0
>1.0.0
<2.0.0
*
latestRegistry requirement
vix install needs the local registry index.
If the registry has not been synced, Vix reports:
registry not synced
Run: vix registry syncFix:
vix registry sync
vix installFor global install:
vix registry sync
vix install -g gk/jwtProject install workflow
For a new project:
vix new api
cd api
vix install
vix devFor an existing project:
git clone https://github.com/example/api.git
cd api
vix install
vix devFor CI:
vix install
vix build --build-target all
vix testsRegistry dependency workflow
Use vix add when adding a new dependency.
vix add gk/json@^1.0.0Then install:
vix installA normal dependency workflow is:
vix registry sync
vix add gk/json@^1.0.0
vix install
vix buildDifference between vix add and vix install
| Command | Purpose |
|---|---|
vix add <pkg> | Add a dependency to the project and update dependency metadata. |
vix install | Install dependencies already pinned in vix.lock. |
Use vix add when you want to add something new.
Use vix install when the lockfile already exists and you want to install what it says.
Difference between vix update and vix install
| Command | Purpose |
|---|---|
vix update | Resolve newer versions and rewrite vix.lock. |
vix install | Install exact versions already pinned in vix.lock. |
Use vix update when you want newer dependency versions.
Use vix install when you want reproducible locked versions.
Difference between project and global install
| Mode | Stores packages in | Uses vix.lock | Generates .vix/vix_deps.cmake |
|---|---|---|---|
| Project install | .vix/deps/ and global store checkout cache | yes | yes |
| Global install | ~/.vix/global/packages/ | no | no |
Project install is for building a project.
Global install is for installing one package globally.
Package cache
Vix stores fetched Git checkouts under:
~/.vix/store/git/A package checkout is stored by package identity and commit.
This means repeated installs can reuse existing package checkouts.
The project then receives links or copies under:
.vix/deps/This keeps project installs fast while keeping dependency state reproducible.
Git dependencies
Vix can install a dependency directly from a Git repository when the project uses vix.app.
vix install https://github.com/fmtlib/fmt --tag 11.2.0 --target fmt::fmt
vix install https://github.com/nlohmann/json.git --tag v3.12.0 --target nlohmann_json::nlohmann_jsonThe command adds a structured dependency block to vix.app, resolves the requested revision to an exact commit, writes vix.lock, fetches the repository into the Git cache, links it into .vix/deps/, and regenerates .vix/vix_deps.cmake.
Supported revision fields are exclusive:
[dependencies.fmt]
git = "https://github.com/fmtlib/fmt"
tag = "11.2.0"
target = "fmt::fmt"[dependencies.library]
git = "https://github.com/example/library"
branch = "main"
target = "library::library"[dependencies.library]
git = "https://github.com/example/library"
rev = "a1b2c3d4e5f6"
target = "library::library"For monorepos, select a subdirectory:
[dependencies.parser]
git = "https://github.com/company/monorepo"
tag = "v2.0.0"
subdirectory = "libs/parser"
target = "company::parser"For header-only repositories without CMake:
[dependencies.sample]
git = "https://github.com/example/sample-headers"
tag = "v1.0.0"
header_only = true
include = "include"Multiple include directories are written as:
includes = ["include", "single_include"]CMake options use the nested table form:
[dependencies.spdlog]
git = "https://github.com/gabime/spdlog"
tag = "v1.15.3"
target = "spdlog::spdlog"
[dependencies.spdlog.cmake]
SPDLOG_BUILD_TESTS = false
SPDLOG_BUILD_EXAMPLE = false
SPDLOG_BUILD_BENCH = falseGit dependencies currently support CMake projects and header-only repositories. Vix does not claim universal support for Bazel, Meson, Autotools, Premake, or custom Makefiles.
Git dependencies are untrusted code: CMake configure and build scripts may execute code on the machine. Review the repository before adding it.
Git lockfile entries
A Git dependency is stored in vix.lock with source = "git" data in JSON form. The lock records the normalized URL, requested revision, resolved commit, targets, include directories, subdirectory, CMake options, and content hash. Branches are resolved to a commit and are not updated by vix build.
Git cache
Registry packages use ~/.vix/store/git/. Direct Git dependencies use:
~/.vix/cache/git/The cache identity includes the repository URL and resolved commit. The project receives a link or copy under .vix/deps/<name>/, so normal builds can run offline after vix install or vix deps has completed.
Removing a Git dependency
vix uninstall sampleThis removes the [dependencies.sample] block from vix.app, removes the lock entry, removes .vix/deps/sample, and leaves the shared Git cache intact.
Integrity checks
If a dependency in vix.lock contains a hash, Vix can verify the checkout content.
If the hash does not match, Vix reports an integrity failure.
Example shape:
integrity check failed: gk/json
expected: ...
actual: ...This protects the install from using unexpected dependency contents.
Generated CMake integration
Project install generates:
.vix/vix_deps.cmakeThis file can:
- add package roots to
CMAKE_PREFIX_PATH - add header-only packages as interface targets
- add CMake-based dependencies with
add_subdirectory - disable dependency tests, examples, benchmarks, and docs
- bridge package targets to canonical Vix aliases
- expose aliases such as
gk::json
The canonical alias for a registry package is:
namespace::nameFor:
gk/jsonthe alias is:
gk::jsonHeader-only packages
Header-only packages expose include directories through an interface target.
Example package:
gk/jsonExpected alias:
gk::jsonAfter vix install, use it from CMake through:
target_link_libraries(app PRIVATE gk::json)For vix.app, add the alias to links:
links = [
vix::vix,
gk::json,
]Compiled packages
Compiled packages can contain their own CMakeLists.txt.
When Vix detects a CMake-based package, it can load the package through generated CMake integration.
Vix also tries to bridge the package’s real CMake target to the canonical registry alias.
For example:
gk/httpshould be usable as:
gk::httpwhen the dependency exposes a compatible target.
Dependency order
When dependencies depend on other dependencies, Vix sorts them topologically before generating CMake integration.
This matters because a dependency should be available before another package tries to use it.
If Vix detects a dependency cycle, it reports an error.
Example shape:
dependency cycle detected while generating .vix/vix_deps.cmakevix.app projects
For vix.app projects, vix install is simple.
After install, Vix prints a next step like:
Dependencies ready
1 package(s) installed
CMake integration generated
Next:
run vix buildThat is because vix.app generated CMake can load the generated dependency integration automatically.
A typical vix.app dependency flow:
vix add gk/json@^1.0.0
vix install
vix buildThen in vix.app:
deps = [
gk/json@^1.0.0,
]
links = [
vix::vix,
gk::json,
]CMake projects
For manual CMake projects, Vix may print a next step like:
include(.vix/vix_deps.cmake)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE gk::json)In a real project, add:
include(.vix/vix_deps.cmake)near the top of your CMakeLists.txt after project(...).
Then link only the packages your target actually uses:
target_link_libraries(app PRIVATE gk::json)vix.app vs CMake install behavior
| Project type | What you do after vix install |
|---|---|
vix.app project | Run vix build. |
| CMake project | Include .vix/vix_deps.cmake and link needed aliases. |
Vix detects a vix.app project when:
vix.app exists
CMakeLists.txt does not existIf CMakeLists.txt exists, Vix treats the project as a CMake project.
Full vix.app example
name = api
type = executable
standard = c++20
sources = [
src/main.cpp,
]
include_dirs = [
src,
]
deps = [
gk/json@^1.0.0,
]
packages = [
vix,
]
links = [
vix::vix,
gk::json,
]
output_dir = binInstall:
vix installBuild:
vix buildRun:
vix runFull CMake example
cmake_minimum_required(VERSION 3.24)
project(api LANGUAGES CXX)
include(.vix/vix_deps.cmake)
add_executable(api
src/main.cpp
)
target_compile_features(api PRIVATE cxx_std_20)
target_link_libraries(api PRIVATE
gk::json
)Install:
vix install
vix buildGlobal install example
Install:
vix registry sync
vix install -g gk/jwt@^1.0.0This writes global install state under:
~/.vix/global/Typical structure:
~/.vix/global/
├── packages/
│ └── ...
└── installed.jsonThe global manifest records information such as:
{
"packages": [
{
"id": "gk/jwt",
"version": "1.0.0",
"repo": "https://github.com/...",
"tag": "v1.0.0",
"commit": "...",
"hash": "...",
"type": "header-only",
"include": "include",
"installed_path": "/home/user/.vix/global/packages/gk.jwt"
}
]
}Package specification
A package spec has this shape:
namespace/nameOptional version or range:
namespace/name@version
namespace/name@rangeExamples:
gk/json
gk/json@1.0.0
gk/json@^1.0.0
gk/json@~1.2.0Scoped-style syntax is also accepted:
@gk/json
@gk/json@1.0.0Invalid package spec
Wrong:
vix install -g jwtCorrect:
vix install -g gk/jwtIf the package spec is invalid or not found, Vix reports:
invalid package spec or package not found: jwt
Expected: @namespace/name[@version]
Example: vix install -g @gk/jwt@1.0.0Project mode requires vix.lock
Project mode installs from:
vix.lockIf the lockfile is missing, create it by adding or updating dependencies.
Typical flow:
vix registry sync
vix add gk/json@^1.0.0
vix installor:
vix update
vix installManual edits to vix.json
Avoid manually editing dependency ranges in vix.json without updating the lockfile.
If you change dependency ranges manually, run:
vix update
vix installor use:
vix add <package>so vix.json and vix.lock stay aligned.
CI usage
Project install is the right command for CI because it respects vix.lock.
Example:
vix registry sync
vix install
vix build --build-target all
vix testsRelease build:
vix registry sync
vix install
vix build --preset release --build-target all
vix tests --preset releaseWith validation:
vix registry sync
vix install
vix check --testsOptions
| Option | Description |
|---|---|
-g, --global | Install one package globally. |
-h, --help | Show command help. |
Commands reference
| Command | Purpose |
|---|---|
vix install | Install project dependencies from vix.lock. |
vix install -g <pkg> | Install one package globally. |
vix install --global <pkg> | Same as -g. |
Common workflows
Install project dependencies
vix installInstall after clone
git clone https://github.com/example/api.git
cd api
vix registry sync
vix install
vix buildInstall then run dev mode
vix install
vix devAdd and install a dependency
vix registry sync
vix add gk/json@^1.0.0
vix install
vix buildInstall a global package
vix registry sync
vix install -g gk/jwtInstall a specific global version
vix install -g gk/jwt@1.0.0Install a global semver range
vix install -g gk/jwt@^1.0.0Common mistakes
Expecting vix install to update dependencies
Wrong expectation:
vix install should choose newer versionsCorrect model:
vix install installs locked versionsUse:
vix outdated
vix updatewhen you want to inspect and update versions.
Editing vix.json and expecting install to resolve new ranges
If you manually edit dependencies in vix.json, update the lockfile first:
vix update
vix installBetter:
vix add gk/json@^1.0.0
vix installForgetting registry sync
If the package cannot be found, run:
vix registry sync
vix installFor global packages:
vix registry sync
vix install -g gk/jwtUsing global install when the project needs a dependency
Wrong:
vix install -g gk/json
vix buildCorrect:
vix add gk/json@^1.0.0
vix install
vix buildGlobal install does not add the dependency to your project lockfile.
Forgetting to link the package
Installing a dependency does not automatically mean your target uses it.
For vix.app, add the alias to links:
links = [
vix::vix,
gk::json,
]For CMake:
target_link_libraries(api PRIVATE gk::json)Editing .vix/vix_deps.cmake
Wrong:
edit .vix/vix_deps.cmake manuallyCorrect:
edit vix.json, vix.lock, vix.app, or CMakeLists.txtThe file is generated and can be replaced by the next install.
Confusing deps and links in vix.app
Wrong:
deps = [
gk::json,
]Correct:
deps = [
gk/json@^1.0.0,
]
links = [
gk::json,
]deps uses registry package specs.
links uses CMake target aliases.
Troubleshooting
Registry not synced
Run:
vix registry syncThen try again:
vix installPackage not found
Check the package name:
namespace/nameThen sync the registry:
vix registry syncTry:
vix install -g namespace/nameor add it to your project:
vix add namespace/nameNo version matches range
If Vix reports:
no version matches range: gk/json@^2.0.0the registry has no compatible version.
Use:
vix outdatedor check available versions in the registry.
Dependency hash mismatch
If integrity verification fails, do not ignore it.
Run:
vix registry sync
vix reset
vix installIf it still fails, the registry entry or package content may be inconsistent.
Dependency cycle detected
If Vix reports a dependency cycle, one or more packages depend on each other in a loop.
Fix the package dependency metadata.
CMake cannot find dependency target
Check that install generated:
.vix/vix_deps.cmakeFor CMake projects, make sure you included it:
include(.vix/vix_deps.cmake)For vix.app, make sure the dependency alias is in links:
links = [
gk::json,
]Header not found
Check that the dependency exposes the expected include directory.
Then make sure your target links the dependency alias.
Example:
target_link_libraries(api PRIVATE gk::json)or in vix.app:
links = [
gk::json,
]Compiled package has no CMakeLists.txt
If a package is marked as compiled but has no CMakeLists.txt, Vix cannot build it as a CMake dependency.
Fix the package metadata or add a valid package build file.
Best practices
Commit vix.json.
Commit vix.lock.
Do not commit .vix/deps.
Do not manually edit .vix/vix_deps.cmake.
Run vix registry sync before adding or resolving dependencies.
Use vix add to add dependencies.
Use vix install after clone or in CI.
Use vix update only when you intentionally want new dependency versions.
Use deps for registry specs in vix.app.
Use links for CMake aliases in vix.app.
Prefer canonical aliases:
namespace::nameKeep project installs reproducible with vix.lock.
Related commands
| Command | Purpose |
|---|---|
vix add | Add a new dependency to the project. |
vix update | Resolve newer versions and rewrite vix.lock. |
vix outdated | Check outdated dependencies. |
vix remove | Remove a dependency. |
vix list | List installed project dependencies. |
vix reset | Clean and reinstall project dependency state. |
vix registry sync | Refresh the registry index. |
vix build | Build the project after install. |
vix run | Run the app after install. |
vix dev | Start dev mode after install. |
Next step
Update dependency versions intentionally.
Global Note extensions
vix install -g is also the installation path for Vix Note extensions.
vix install -g softadastra/pyreluneThe package is resolved from the registry like any other global package. Vix fetches the resolved commit, builds it when needed, runs CMake install rules, copies installed files into the global prefix, and records the package in:
~/.vix/global/installed.jsonIf the resolved registry version contains extensions.note, Vix preserves that version-level metadata in the installed manifest. Vix Note reads that installed metadata during global extension discovery.
For executable extensions, the package should install its runtime command under the global bin/ directory and declare it in bin:
{
"bin": {
"pyrelune": "pyrelune"
}
}CMake install rules remain authoritative. If the package declares an executable command but CMake does not install it, global install fails rather than recording a broken command as installed.