The env module provides a modern, consistent, and cross-platform API
for working with environment variables and .env files in C++.
It is designed to be:
- simple to use
- explicit (no hidden behavior)
- predictable across platforms
- aligned with modern developer workflows
Environment handling in Vix follows strict principles:
- no global magic
- explicit loading
- explicit parsing
- structured errors (
Result<T>) - layered configuration support
The goal is to bring a Node.js / Deno-like DX to environment management in C++ without breaking C++ principles.
Using Vix:
vix add @vix/env#include <vix/env/Env.hpp>
#include <iostream>
int main()
{
auto app = vix::env::get_or("APP_NAME", "Vix");
std::cout << "APP_NAME = " << app << std::endl;
}vix::env::has("PORT");auto result = vix::env::get("PORT");
if (result)
{
std::cout << result.value();
}auto port = vix::env::get_or("PORT", "3000");vix::env::set("APP_ENV", "production");Overwrite control:
vix::env::set("APP_ENV", "production", true);vix::env::unset("APP_ENV");auto debug = vix::env::get_bool("APP_DEBUG");
if (debug && debug.value())
{
// debug mode
}Accepted values:
- true: 1, true, yes, on
- false: 0, false, no, off
auto port = vix::env::get_int("PORT");auto workers = vix::env::get_uint("WORKERS");auto ratio = vix::env::get_double("RATIO");auto file = vix::env::load_file(".env");
if (file)
{
for (const auto &entry : file.value().entries)
{
std::cout << entry.key << " = " << entry.value << "\n";
}
}auto err = vix::env::load_into_process(".env");
if (err)
{
std::cerr << err.message();
}Vix supports modern layered configuration:
.env.env.local.env.production.env.production.local
vix::env::EnvFileOptions options;
options.mode = vix::env::EnvFileMode::Layered;
options.environment_name = "production";
options.ignore_missing_files = true;
auto files = vix::env::load_layered(options);auto err = vix::env::load_layered_into_process(options);.env.env.local.env.production.env.production.local
Later files override earlier ones.
vix::env::EnvFileOptions options;
options.base_dir = ".";
options.filename = ".env";
options.environment_name = "production";
options.mode = vix::env::EnvFileMode::Layered;
options.load_base_file = true;
options.load_local_file = true;
options.load_environment_file = true;
options.load_environment_local_file = true;
options.ignore_missing_files = true;
options.env.overwrite_existing = true;All operations use Result<T> or Error.
auto result = vix::env::get("PORT");
if (!result)
{
std::cerr << result.error().message();
}- supports
KEY=value - supports
export KEY=value - ignores empty lines
- ignores
#comments
Supports inline comments:
APP_NAME=vix # comment
Supports quoted values:
TITLE="Hello World"
- no filesystem access in parsing logic
.envloading is explicit (never automatic)- environment injection is controlled (
overwrite_existing) - layered resolution is deterministic
- cross-platform (POSIX + Windows)
vix_errorvix_path
vix::env::EnvFileOptions options;
options.environment_name = "production";
vix::env::load_layered_into_process(options);
auto port = vix::env::get_or("PORT", "8080");The env module gives you:
- simple env access
- typed values
.envparsing- layered configuration
- process injection
All with:
- explicit behavior
- strong error handling
- zero magic