Niek-HM/zig-config
A Zig parser for .env, .ini, and .toml files with variable substitution, type-safe accessors, and merging support
A lightweight configuration loader for .env, .ini, and .toml files written in Zig.
It supports variable substitution, typed access, merging, and exporting to environment maps.
✅ Parse .env, .ini, and .toml formats
✅ Access config values as []const u8, i64, f64, bool, or arrays
✅ Variable substitution (${VAR}, ${VAR:-default}, etc.)
✅ Merging with control over overwrite behavior
✅ Load from file, buffer, or environment
✅ Write back to .env, .ini, .toml
✅ Fully tested, memory-safe, leak-free
✅ No dependencies
const std = @import("std");
const Config = @import("zig-config").Config;
pub fn main() !void {
const allocator = std.heap.page_allocator;
var cfg = try Config.loadEnvFile("config.env", allocator);
defer cfg.deinit();
const port = try cfg.getAs(i64, "PORT", allocator);
defer port.deinit();
const debug = try cfg.getAs(bool, "DEBUG", allocator);
defer debug.deinit();
const host = try cfg.getAs([]const u8, "HOST", allocator);
defer host.deinit();
std.debug.print("Running on {s}:{d} (debug = {})", .{ host, port, debug });
}
Supports:
${VAR} → error if VAR missing${VAR:-default} → fallback if missing or empty${VAR-default} → fallback if missing${VAR:+alt} → use alt if set and not empty${VAR+alt} → use alt if setNested substitutions and circular reference detection are supported.
var merged = try config.merge(&other, allocator, .overwrite);
defer merged.deinit();
MergeBehavior options:
.overwrite → always use new value .skip_existing → keep existing .error_on_conflict → fail on duplicate keys.env: simple KEY=value, comments # or ;.ini: [section] headers + key/value.toml: full support for strings, arrays, inline tables, booleans, numberstry config.writeEnvFile("output.env");
try config.writeIniFile("output.ini", allocator);
try config.writeTomlFile("output.toml");
const db_port = try config.getAs(i64, "database.port", allocator);
const features = try config.getAs([]bool, "ENABLED_FLAGS", allocator);
Arrays supported: []i64, []f64, []bool, [][]const u8
✅ Short-term goals (v0.3.x)
Full TOML support (date-time)
.json config input support
.env.example validation (check for missing/extra keys)
Null-delimited EnvMap export for subprocesses
Improve write serialization (preserve formatting where possible)
CLI tool: merge, diff, validate, and export config
🔭 Long-term goals (v0.4+)
Live config reloading (file watching API)
SQLite-backed config store (persistent, reloadable)
Secrets injection from .secrets.env or Vault-compatible store
Typed schema validation (define required fields, expected types)
YAML support