vix publish
vix publish publishes a tagged version of the current package to the Vix Registry.
Use it when your package is ready, committed, tagged, pushed to origin, and should become available through the registry workflow.
vix publishOverview
vix publish prepares a registry entry for the current package.
It does not publish random local files.
It publishes a Git tag.
That means the package version must already exist as a Git tag locally and on the remote origin.
The command can:
- detect the current Git repository
- require a clean working tree
- resolve the publish version from a Git tag
- verify that the tag exists locally
- verify that the tag exists on
origin - resolve the commit behind the tag
- read package metadata from
vix.json - infer package namespace and name from Git remote when needed
- update the local registry clone
- create or update the registry package entry
- create a publish branch in the registry clone
- commit the registry update
- push the registry branch
- optionally create a GitHub pull request with
gh - run in dry-run mode
- attach release notes
- clean old local publish branches
The important model is:
package repo tag
-> registry entry
-> registry branch
-> registry PR
-> package available after PR merge2
3
4
5
Usage
vix publish [version] [--notes "..."] [--dry-run]Basic examples
# Publish latest local SemVer tag
vix publish
# Publish an explicit version
vix publish 0.2.0
# Publish with notes
vix publish 0.2.0 --notes "Add JSON helpers"
# Validate without writing or pushing
vix publish 0.2.0 --dry-run
# Remove older local publish branches in the registry clone
vix publish 0.2.0 --cleanup2
3
4
5
6
7
8
9
10
11
12
13
14
Required Git tag format
The Git tag must use this format:
v<version>Example:
v0.2.0When you run:
vix publish 0.2.0Vix looks for:
v0.2.0Do not pass the v prefix to vix publish.
Correct:
vix publish 0.2.0Wrong:
vix publish v0.2.0Requirements
Before publishing, the package repository must satisfy these conditions:
inside a Git repository
working tree is clean
publish tag exists locally
publish tag exists on origin
local registry clone exists
registry index exists2
3
4
5
6
The local registry clone comes from:
vix registry syncRecommended publish flow
git status
vix fmt --check
vix check --tests
vix build --preset release
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0
vix registry sync
vix publish 0.2.0 --dry-run
vix publish 0.2.0 --notes "Add helpers"2
3
4
5
6
7
8
9
10
11
After the registry PR is merged, users can refresh the registry and add the package:
vix registry sync
vix add namespace/name@0.2.0
vix install2
3
Version resolution
vix publish can resolve the version in two ways.
Explicit version
vix publish 0.2.0Vix checks:
local tag: v0.2.0
remote tag: origin v0.2.02
If the local tag is missing, Vix fails.
If the remote tag is missing, Vix fails and tells you to push it.
Latest local SemVer tag
vix publishWhen no version is provided, Vix lists local Git tags and finds the latest SemVer tag.
Examples of publishable tags:
v0.1.0
v0.2.0
v1.0.02
3
Then Vix verifies that the selected tag exists on origin.
If the latest local tag has not been pushed, Vix fails.
Clean working tree requirement
vix publish requires a clean working tree.
If your repository has uncommitted changes, Vix reports:
working tree is not clean
Commit your changes before publishing.2
This is intentional.
A registry entry should point to a stable Git tag, not to a dirty local state.
Check:
git statusCommit or discard changes before publishing.
Package identity
A package has this identity:
namespace/nameExample:
gk/jsonVix resolves the package identity from vix.json first.
Example:
{
"namespace": "gk",
"name": "json",
"description": "A small JSON helper package for Vix."
}2
3
4
5
If vix.json contains namespace and name, Vix uses them.
Both values are normalized to lowercase.
Required package fields in vix.json
When vix.json exists, vix publish requires:
{
"namespace": "gk",
"name": "json"
}2
3
4
If one is missing, Vix fails.
Example error:
invalid vix.json: missing string field `namespace`or:
invalid vix.json: missing string field `name`Package name validation
namespace and name may contain:
letters
numbers
-
_
.2
3
4
5
Valid:
gk
json
softadastra
http-client
json_utils
vix.core2
3
4
5
6
Invalid:
gk/json
json helper
@scope
name!2
3
4
Inferring package identity from Git remote
If vix.json does not provide package identity, Vix tries to infer it from Git remote origin.
Example remote:
https://github.com/gk/json.gitor:
git@github.com:gk/json.gitVix infers:
namespace: gk
name: json
id: gk/json2
3
If Vix cannot infer the identity, it reports:
cannot infer package namespace/name
Fix: add { "namespace": "...", "name": "..." } in vix.json or ensure git remote origin is set.2
Registry location
vix publish expects the local registry clone at:
~/.vix/registry/indexInside that repository, registry entries live under:
~/.vix/registry/index/indexFor package:
gk/jsonthe registry entry file is:
~/.vix/registry/index/index/gk.json.jsonThe filename format is:
<namespace>.<name>.jsonRegistry sync requirement
If the local registry clone is missing, Vix reports:
registry is not available locally: ~/.vix/registry/index
Run: vix registry sync2
Fix:
vix registry sync
vix publish 0.2.02
Existing registry entry
If the package already exists in the registry, Vix reads its registry entry.
The entry must contain:
{
"versions": {}
}2
3
If the selected version already exists, Vix fails.
Example:
version already registered: gk/json@0.2.0
This tag/version is already present in the registry.2
This prevents publishing the same package version twice.
New registry entry
If the package does not exist yet, Vix creates a new registry entry.
It can use metadata from vix.json, including:
description
displayName
license
documentation
keywords
exports
constraints
dependencies
maintainers2
3
4
5
6
7
8
9
If some fields are missing, Vix fills safe defaults.
Generated registry metadata
For a new package, Vix can generate fields like:
{
"api": {
"format": "vix-api-1",
"generatedBy": "vix-cli",
"path": "vix.api.json",
"updatedAt": "2026-05-28T10:00:00Z"
},
"name": "json",
"namespace": "gk",
"displayName": "json",
"description": "",
"documentation": "https://github.com/gk/json#readme",
"keywords": [],
"license": "MIT",
"manifestPath": "vix.json",
"homepage": "https://github.com/gk/json",
"repo": {
"url": "https://github.com/gk/json",
"defaultBranch": "main"
},
"type": "header-only",
"versions": {}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Version entry
For each published version, Vix adds:
{
"versions": {
"0.2.0": {
"tag": "v0.2.0",
"commit": "..."
}
}
}2
3
4
5
6
7
8
The package version points to:
tag
commit2
This makes the registry version reproducible.
Default package type
For new entries, the current generated default is:
{
"type": "header-only"
}2
3
If your package needs more precise metadata, define the correct package metadata in vix.json or update the registry entry through the registry workflow.
Exports
If vix.json defines exports, Vix uses it.
Example:
{
"exports": {
"headers": ["json/json.hpp"],
"modules": ["json/json.hpp"],
"namespaces": ["gk::json"]
}
}2
3
4
5
6
7
If exports is missing, Vix tries a simple header convention.
For package name:
jsonit looks for:
include/json/json.hppIf the file exists, Vix adds:
{
"exports": {
"headers": ["json/json.hpp"],
"modules": ["json/json.hpp"],
"namespaces": []
}
}2
3
4
5
6
7
Constraints
If vix.json defines constraints, Vix uses them.
Example:
{
"constraints": {
"minCppStandard": "c++20",
"platforms": ["linux", "macos", "windows"]
}
}2
3
4
5
6
If missing, Vix uses defaults:
{
"minCppStandard": "c++17",
"platforms": ["linux", "macos", "windows"]
}2
3
4
Dependencies metadata
If vix.json defines registry package dependencies for publication metadata, Vix can use them.
Example:
{
"dependencies": {
"git": [],
"registry": [],
"system": []
}
}2
3
4
5
6
7
If missing, Vix creates:
{
"dependencies": {
"git": [],
"registry": [],
"system": []
}
}2
3
4
5
6
7
This field is registry package metadata.
It is separate from project dependency management fields used by vix add, vix update, and vix install.
Maintainers
If vix.json defines maintainers, Vix uses them.
Example:
{
"maintainers": [
{
"name": "Gaspard Kirira",
"github": "gk"
}
]
}2
3
4
5
6
7
8
If missing, Vix creates a maintainer from the namespace and local Git user name when available.
Quality metadata
Vix can generate basic quality metadata:
{
"quality": {
"ci": [],
"hasDocs": true,
"hasExamples": true,
"hasTests": true
}
}2
3
4
5
6
7
8
It detects examples and tests from folders such as:
examples
tests
test
unittests2
3
4
Dry run
Use:
vix publish 0.2.0 --dry-runDry run validates the publish flow and prints the registry entry that would be written.
It does not:
write registry entry
create registry branch
commit changes
push branch
create PR2
3
4
5
Example:
vix publish 0.2.0 --dry-runOutput shape:
Publish
repo: /home/user/json
version: 0.2.0
tag: v0.2.0
commit: 8f3a...
id: gk/json
registry: /home/user/.vix/registry/index
entry: /home/user/.vix/registry/index/index/gk.json.json
dry-run: would update: /home/user/.vix/registry/index/index/gk.json.json2
3
4
5
6
7
8
9
Then it prints the generated JSON.
Publishing for real
Run:
vix publish 0.2.0Vix then:
- Writes or updates the registry entry.
- Runs
git pull --ff-onlyin the registry clone. - Creates a publish branch.
- Adds the registry entry.
- Commits the registry update.
- Pushes the branch to origin.
- Creates a GitHub PR when
ghis installed and authenticated.
Registry branch name
For package:
gk/jsonversion:
0.2.0Vix creates a branch like:
publish-gk-json-0.2.0Branch format:
publish-<namespace>-<name>-<version>Registry commit message
Vix commits with a message shaped like:
registry: gk/json v0.2.0GitHub PR creation
If GitHub CLI is installed and authenticated, Vix tries to create a PR automatically.
Requirements:
gh installed
gh authenticated for github.com2
Check:
gh auth status -h github.comIf available, Vix runs a PR creation flow against:
vixcpp/registrywith:
base: main
head: publish branch
title: registry: add <package> v<version>2
3
Example PR title:
registry: add gk/json v0.2.0PR body
The PR body includes:
package id
version
tag
commit
notes2
3
4
5
Example:
Publish package `gk/json` version `0.2.0`.
- tag: `v0.2.0`
- commit: `8f3a...`
Notes:
Add helpers2
3
4
5
6
7
If GitHub PR creation fails
If gh pr create fails, Vix does not fail the whole publish.
It prints a warning and keeps the pushed branch.
You can create the PR manually.
Example output:
branch pushed: publish-gk-json-0.2.0
Create a PR on GitHub: vixcpp/registry <- publish-gk-json-0.2.0
Tip: install/auth gh to auto-create PR next time.2
3
Cleanup
Use:
vix publish 0.2.0 --cleanupAfter pushing the current publish branch, Vix removes older local publish branches for the same package inside the registry clone.
It does not remove the current publish branch.
It does not delete remote branches.
This only cleans local registry clone branches.
Notes
Use --notes to attach release notes to the generated PR body.
vix publish 0.2.0 --notes "Add helpers and improve diagnostics"You can also use:
vix publish 0.2.0 --notes="Add helpers and improve diagnostics"Full vix.json example for a package
{
"namespace": "gk",
"name": "json",
"displayName": "Vix JSON",
"description": "Small JSON helpers for Vix projects.",
"license": "MIT",
"documentation": "https://github.com/gk/json#readme",
"keywords": ["json", "vix", "cpp"],
"exports": {
"headers": ["json/json.hpp"],
"modules": ["json/json.hpp"],
"namespaces": ["gk::json"]
},
"constraints": {
"minCppStandard": "c++20",
"platforms": ["linux", "macos", "windows"]
},
"dependencies": {
"git": [],
"registry": [],
"system": []
},
"maintainers": [
{
"name": "Gaspard Kirira",
"github": "gk"
}
]
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Minimal vix.json example
{
"namespace": "gk",
"name": "json",
"description": "Small JSON helpers for Vix projects."
}2
3
4
5
This is enough for Vix to resolve package identity and generate a registry entry.
Full publish workflow
# Make sure the package is clean and valid
git status
vix fmt --check
vix check --tests
vix build --preset release
# Create and push the release tag
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0
# Make sure registry clone exists locally
vix registry sync
# Preview registry entry
vix publish 0.2.0 --dry-run
# Publish registry branch and create PR if gh is available
vix publish 0.2.0 --notes "Add helpers"2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
After the registry PR merges
Once the registry PR is merged, users can refresh their registry index:
vix registry syncThen add the package:
vix add gk/json@0.2.0
vix install2
For a vix.app project, use the package target in links when needed:
deps = [
gk/json@0.2.0,
]
links = [
vix::vix,
gk::json,
]2
3
4
5
6
7
8
Then build:
vix buildOptions
| Option | Description |
|---|---|
--notes "..." | Attach release notes to the PR body. |
--notes=... | Same as --notes "...". |
--dry-run | Validate and print the registry entry without writing or pushing. |
--cleanup | Remove older local publish branches in the registry clone. |
-h, --help | Show command help. |
Commands reference
| Command | Description |
|---|---|
vix publish | Publish latest local SemVer tag. |
vix publish 0.2.0 | Publish explicit version using tag v0.2.0. |
vix publish 0.2.0 --dry-run | Preview generated registry entry. |
vix publish 0.2.0 --notes "..." | Publish with notes for the PR body. |
vix publish 0.2.0 --cleanup | Publish and remove old local publish branches. |
Common workflows
Publish latest tag
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0
vix registry sync
vix publish2
3
4
Publish explicit version
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0
vix registry sync
vix publish 0.2.02
3
4
Dry run before publishing
vix publish 0.2.0 --dry-runPublish with notes
vix publish 0.2.0 --notes "Add helpers"Publish and clean old local branches
vix publish 0.2.0 --cleanupAdd package after publish PR merges
vix registry sync
vix add gk/json@0.2.0
vix install
vix build2
3
4
Common mistakes
Publishing with uncommitted changes
Wrong:
vix publish 0.2.0while git status is not clean.
Correct:
git status
git add .
git commit -m "chore: prepare release"
vix publish 0.2.02
3
4
Creating a tag but not pushing it
Wrong:
git tag -a v0.2.0 -m "Release v0.2.0"
vix publish 0.2.02
Correct:
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0
vix publish 0.2.02
3
Passing the version with v
Wrong:
vix publish v0.2.0Correct:
vix publish 0.2.0The Git tag uses v0.2.0.
The command argument uses 0.2.0.
Forgetting registry sync
Wrong:
vix publish 0.2.0when the registry clone is missing.
Correct:
vix registry sync
vix publish 0.2.02
Trying to publish an already registered version
If the version already exists in the registry entry, Vix refuses to publish it again.
Create a new version tag instead.
git tag -a v0.2.1 -m "Release v0.2.1"
git push origin v0.2.1
vix publish 0.2.12
3
Expecting publish to merge the registry PR
vix publish can push a branch and create a PR.
It does not merge the PR.
The version becomes available after the registry PR is merged and users run:
vix registry syncExpecting publish to install the package
vix publish updates the registry workflow.
It does not install the package into a project.
Use:
vix add namespace/name@version
vix install2
after the registry PR has been merged.
Troubleshooting
Not inside a Git repository
Run the command inside your package repository.
cd /path/to/package
vix publish 0.2.02
Working tree is not clean
Check:
git statusCommit or discard changes.
Tag not found locally
Create the tag:
git tag -a v0.2.0 -m "Release v0.2.0"Then publish it to origin:
git push origin v0.2.0Tag not found on remote origin
Push the tag:
git push origin v0.2.0or push all tags:
git push --tagsNo publishable Git tag found
Create and push a SemVer tag:
git tag -a v0.2.0 -m "Release v0.2.0"
git push origin v0.2.0
vix publish2
3
Cannot infer package namespace/name
Add package identity to vix.json:
{
"namespace": "gk",
"name": "json"
}2
3
4
or configure a valid Git remote origin.
Invalid vix.json
Make sure vix.json is valid JSON and has the required fields:
{
"namespace": "gk",
"name": "json"
}2
3
4
Registry is not available locally
Run:
vix registry syncThen retry:
vix publish 0.2.0Failed to update local registry repo
Vix runs a fast-forward pull in the local registry clone.
If it fails, refresh the registry clone:
vix registry syncThen retry.
Failed to push branch
Check Git authentication for the registry remote.
You may need access to push a branch to the registry repository or fork workflow, depending on how the registry is configured.
GitHub PR was not created
Check GitHub CLI:
gh --version
gh auth status -h github.com2
If gh is missing or not authenticated, create the PR manually using the branch printed by Vix.
Best practices
Keep the package repository clean before publishing.
Use annotated Git tags for releases.
Push the tag before publishing.
Run vix publish --dry-run before the real publish.
Define namespace and name explicitly in vix.json.
Add package metadata in vix.json before first publish.
Run vix registry sync before publishing.
Use --notes to make the registry PR easier to review.
Do not publish the same version twice.
After the PR merges, test the package from a clean project with:
vix registry sync
vix add namespace/name@version
vix install
vix build2
3
4
Related commands
| Command | Purpose |
|---|---|
vix registry sync | Clone or refresh the local registry index. |
vix search | Search packages in the local registry index. |
vix add | Add a published package to a project. |
vix install | Install locked project dependencies. |
vix update | Update dependency versions. |
vix outdated | Check whether locked dependencies are outdated. |
vix list | List project dependencies. |
vix pack | Create a local package artifact. |
vix verify | Verify a package artifact. |
Next step
Manage the local registry index.
