Skip to content

vix.app

Experimental

vix.app is an experimental Vix feature.

It is available for testing and design feedback, but it is not production-ready yet. The file format, fields, generated CMake behavior, and registry dependency integration may change before stabilization.

vix.app is a simple application manifest for C++ projects built with Vix.

It lets small and medium C++ apps start without writing a visible CMakeLists.txt.

Vix reads vix.app, generates an internal CMake project, then uses CMake and Ninja underneath to build and run the app.

Goal

vix.app is designed for projects that need a simple entry point:

bash
vix run
vix build

without requiring the user to write CMake manually.

The generated CMake project stays internal:

.vix/generated/app/CMakeLists.txt

This means the user gets a simple project format, while Vix keeps the power of the C++ build ecosystem underneath.

What vix.app does

vix.app describes:

  • the application name
  • the target type
  • the C++ standard
  • source files
  • include directories
  • compile definitions
  • linked libraries or CMake targets

Example:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp",
  "hello.cpp"
]

include_dirs = [
  "include"
]

defines = [
  "DEMO_APP=1"
]

links = [
  "vix::core"
]

Then run:

bash
vix run

Vix generates CMake internally, builds the app, and runs the executable.

What vix.app does not replace

vix.app does not replace vix.json.

They have different roles.

FileRole
vix.appDescribes the C++ application target.
vix.jsonDescribes project metadata, registry dependencies, tasks, and workflows.
vix.lockStores resolved dependency versions.
.vix/Stores generated files, installed dependencies, cache data, and internal metadata.

The rule is simple:

  • vix.app = app build description
  • vix.json = registry, tasks, workflows, project metadata

Detection order

Vix keeps existing project behavior intact.

The resolution order is:

1. If CMakeLists.txt exists
   -> use the existing CMake project

2. Else if vix.app exists
   -> generate an internal CMake project

3. Else if a single .cpp file is passed
   -> use single-file mode

4. Else
   -> show a clear error

This means vix.app is only used when there is no CMakeLists.txt.

Existing CMake projects keep working as before.

Minimal project

Project structure:

demo/
├── main.cpp
└── vix.app

main.cpp:

cpp
#include <iostream>

int main()
{
  std::cout << "Hello from Vix app\n";
  return 0;
}

vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp"
]

Run:

bash
vix run

Expected output:

Hello from Vix app

Multi-file project

Project structure:

demo/
├── main.cpp
├── hello.cpp
├── include/
│   └── hello.hpp
└── vix.app

include/hello.hpp:

cpp
#ifndef DEMO_HELLO_HPP
#define DEMO_HELLO_HPP

void say_hello();

#endif

hello.cpp:

cpp
#include "hello.hpp"

#include <vix/print.hpp>

void say_hello()
{
  vix::print("Hello from hello.cpp");
}

main.cpp:

cpp
#include "hello.hpp"

#include <vix/print.hpp>

int main()
{
  vix::print("Hello from main.cpp");
  say_hello();
  return 0;
}

vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp",
  "hello.cpp"
]

include_dirs = [
  "include"
]

Run:

bash
vix run

Expected output:

Hello from main.cpp
Hello from hello.cpp

Generated CMake

For the previous example, Vix generates an internal file similar to this:

cmake
# Auto-generated by Vix from vix.app
# Do not edit this file directly.

cmake_minimum_required(VERSION 3.24)

project(demo LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_executable(demo
  "/absolute/path/to/main.cpp"
  "/absolute/path/to/hello.cpp"
)

target_include_directories(demo PRIVATE
  "/absolute/path/to/include"
)

The generated file is stored under:

.vix/generated/app/CMakeLists.txt

Users should not edit this file directly.

Edit vix.app instead.

Commands

Build the app

bash
vix build

For a vix.app project, Vix does this internally:

vix.app
  -> .vix/generated/app/CMakeLists.txt
  -> cmake -S .vix/generated/app -B build-ninja -G Ninja
  -> cmake --build build-ninja

Run the app

bash
vix run

For a vix.app project, Vix does this internally:

vix.app
  -> generate CMake
  -> build
  -> run build-ninja/<target>

Single-file mode still works

bash
vix run main.cpp

This keeps the existing script mode behavior.

Use this for quick experiments or one-file programs.

Use vix.app when the app has multiple source files or needs includes, definitions, links, or registry dependencies.

Fields

name

Required.

Defines the CMake project name and default target name.

toml
name = "demo"

Valid examples:

toml
name = "api"
name = "hello"
name = "softadastra_agent"

The name should be simple and filesystem-friendly.

type

Optional.

Default:

toml
type = "executable"

Supported values:

toml
type = "executable"
type = "static"
type = "static-library"
type = "shared"
type = "shared-library"
type = "library"

Recommended value for apps:

toml
type = "executable"

Example:

toml
name = "demo"
type = "executable"

standard

Optional.

Default:

toml
standard = "c++20"

Supported values:

toml
standard = "c++11"
standard = "c++14"
standard = "c++17"
standard = "c++20"
standard = "c++23"
standard = "c++26"

Recommended default:

toml
standard = "c++20"

sources

Required.

Lists source files for the app.

toml
sources = [
  "main.cpp",
  "hello.cpp"
]

Paths are relative to the project directory.

You can also use files inside src/:

toml
sources = [
  "src/main.cpp",
  "src/server.cpp",
  "src/routes.cpp"
]

include_dirs

Optional.

Lists include directories.

toml
include_dirs = [
  "include"
]

This generates:

cmake
target_include_directories(<target> PRIVATE ...)

Example project:

demo/
├── include/
│   └── demo/server.hpp
├── src/
│   ├── main.cpp
│   └── server.cpp
└── vix.app

vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "src/main.cpp",
  "src/server.cpp"
]

include_dirs = [
  "include"
]

defines

Optional.

Lists preprocessor definitions.

toml
defines = [
  "DEMO_APP=1",
  "VIX_USE_FAST_PATH"
]

This generates:

cmake
target_compile_definitions(<target> PRIVATE ...)

Example:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp"
]

defines = [
  "APP_ENV=\"dev\"",
  "ENABLE_LOGS=1"
]

Optional.

Lists libraries or CMake targets linked by the app.

toml
links = [
  "vix::core",
  "vix::json"
]

This generates:

cmake
target_link_libraries(<target> PRIVATE ...)

Use this field for:

  • Vix modules
  • registry package targets
  • local CMake targets exposed through generated dependency files
  • system libraries when appropriate

Example:

toml
name = "api"
type = "executable"
standard = "c++20"

sources = [
  "src/main.cpp"
]

links = [
  "vix::core",
  "vix::json"
]

Registry dependencies

Registry dependencies stay in vix.json and vix.lock.

vix.app only consumes the targets after they are installed.

Typical flow:

bash
vix add softadastra/kordex-runtime
vix install
vix run

The project keeps dependency metadata in:

  • vix.json
  • vix.lock

The installed dependency files live under:

.vix/

The generated CMake project can include dependency integration files from .vix/, then links can reference the exposed CMake targets.

Example vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "src/main.cpp"
]

links = [
  "softadastra::kordex-runtime"
]

The important separation is:

  • vix.json handles dependency declaration.
  • vix.lock handles resolved versions.
  • vix.app links the final targets used by the app.

For a simple app:

demo/
├── src/
│   ├── main.cpp
│   └── app.cpp
├── include/
│   └── demo/
│       └── app.hpp
├── vix.app
├── vix.json
└── vix.lock

Recommended vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "src/main.cpp",
  "src/app.cpp"
]

include_dirs = [
  "include"
]

Full REST API example

Project structure:

rest-api/
├── src/
│   └── main.cpp
└── vix.app

vix.app:

toml
name = "rest_api"
type = "executable"
standard = "c++20"

sources = [
  "src/main.cpp"
]

links = [
  "vix::core"
]

src/main.cpp:

cpp
#include <vix.hpp>

using namespace vix;

int main()
{
  App app;

  app.get("/", [](Request &, Response &res){
    res.json({
      "message", "Hello from Vix",
      "framework", "Vix.cpp"
    });
  });

  app.get("/health", [](Request &, Response &res){
    res.json({
      "ok", true,
      "service", "rest_api"
    });
  });

  app.run(8080);
  return 0;
}

Run:

bash
vix run

Test:

bash
curl -i http://127.0.0.1:8080/
curl -i http://127.0.0.1:8080/health

vix.app vs CMakeLists.txt

Use vix.app when:

  • the app is small or medium-sized
  • you want a fast start
  • you want to avoid writing CMake manually
  • your app has a simple executable target
  • your app has a few source files
  • your app links registry dependencies through Vix

Use CMakeLists.txt when:

  • the project has advanced build logic
  • the project has many targets
  • the project needs custom CMake functions
  • the project needs advanced install rules
  • the project needs custom toolchains or platform-specific build logic
  • the project is a library intended for complex packaging

The rule is:

  • vix.app for simple app description.
  • CMakeLists.txt for advanced build control.

If both files exist, CMakeLists.txt wins.

Generated files

A vix.app project may create:

.vix/generated/app/CMakeLists.txt
build-ninja/
build-dev/
build-release/

These are internal or build output paths.

Recommended .gitignore:

build/
build-*/
.vix/generated/
.vix/cache/
.vix/runs/

Depending on how the project handles dependencies, some .vix/ dependency files may be local build state and should not be committed.

Common workflows

Create a simple app manually

bash
mkdir demo
cd demo

cat > main.cpp <<'CPP'
#include <vix/print.hpp>

int main()
{
  vix::print("Hello from Vix app");
  return 0;
}
CPP

cat > vix.app <<'EOF'
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp"
]
EOF

vix run

Add another source file

bash
cat > hello.cpp <<'CPP'
#include <vix/print.hpp>

void say_hello()
{
  vix::print("Hello from hello.cpp");
}
CPP

Update main.cpp:

cpp
#include <iostream>

void say_hello();

int main()
{
  vix::print("Hello from main.cpp");

  say_hello();

  return 0;
}

Update vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp",
  "hello.cpp"
]

Run:

bash
vix run

Add an include directory

demo/
├── include/
│   └── hello.hpp
├── main.cpp
├── hello.cpp
└── vix.app

vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp",
  "hello.cpp"
]

include_dirs = [
  "include"
]

Add registry dependencies

bash
vix add namespace/package
vix install

Then link the target exposed by the package:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "src/main.cpp"
]

links = [
  "namespace::package"
]

Run:

bash
vix run

Error messages

Missing vix.app

If no CMakeLists.txt and no vix.app exist, Vix cannot resolve a project.

Fix:

bash
vix run main.cpp

or create vix.app:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp"
]

Missing sources

Invalid:

toml
name = "demo"
type = "executable"
standard = "c++20"

Fix:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp"
]

Wrong source path

Invalid:

toml
sources = [
  "src/missing.cpp"
]

Fix the path or create the file.

Invalid:

toml
links = [
  "missing::target"
]

Fix:

  • install the dependency
  • check vix.lock
  • check the target name exposed by the package
  • check .vix/ dependency integration files
  • update the links field

Best practices

Keep vix.app small.

Recommended:

toml
name = "api"
type = "executable"
standard = "c++20"

sources = [
  "src/main.cpp",
  "src/routes.cpp",
  "src/server.cpp"
]

include_dirs = [
  "include"
]

links = [
  "vix::core"
]
  • Avoid turning vix.app into a full build system.
  • Do not put registry metadata in vix.app.
  • Keep dependencies in vix.json.
  • Keep resolved versions in vix.lock.
  • Use CMakeLists.txt when the app becomes advanced enough to need custom build logic.

Reference

Complete field reference:

FieldRequiredDefaultPurpose
nameyesnoneTarget and project name.
typenoexecutableTarget type.
standardnoc++20C++ language standard.
sourcesyesnoneSource files.
include_dirsnoemptyInclude directories.
definesnoemptyCompile definitions.
linksnoemptyLibraries or CMake targets.

Supported target types:

ValueMeaning
executableBuilds an executable app.
staticBuilds a static library.
static-libraryBuilds a static library.
sharedBuilds a shared library.
shared-libraryBuilds a shared library.
libraryBuilds a static library by default.

Supported standards:

Value
c++11
c++14
c++17
c++20
c++23
c++26

Summary

vix.app gives Vix a simple project-level entry point for C++ apps.

The user writes:

toml
name = "demo"
type = "executable"
standard = "c++20"

sources = [
  "main.cpp",
  "hello.cpp"
]

Then runs:

bash
vix run

Vix handles:

  • manifest parsing
  • CMake generation
  • configure
  • build
  • run

The result is a lighter first experience for C++ apps, while keeping CMake and Ninja underneath for the real build work.

Released under the MIT License.