Package System
Overview
Braid's package system is based on a simple TOML manifest (braid.toml) and a C++ package manager library. Packages define a name, version, entrypoint, and dependencies. The compiler resolves imports by searching standard library paths, local files, and registered package directories.
braid.toml Format
The package manifest is a TOML file with a [package] or [project] section containing metadata, plus an optional [dependencies] section.
[package]
name = "my-app"
version = "0.1.0"
entry = "src/main.br"
description = "My Braid application"
authors = ["Developer"]
[dependencies]
junction = "1.0"
sync = "1.0"
bond = "1.0"
std.net = "1.0.0"
external-lib = "git://github.com/braid-lang/external-lib.git"| Field | Section | Description |
|---|---|---|
name | [package] | Package name (required) |
version | [package] | Semantic version string (required) |
entry | [package] | Entrypoint file (default: main.br) |
description | [package] | Human-readable description |
authors | [package] | List of authors |
dependencies | [dependencies] | Map of name → version constraint |
Package Manager API
The C++ PackageManager class (in compiler/cpp/package/) provides utilities for parsing and serializing braid.toml files.
#include "braid/compiler/package/PackageManager.hpp"
braid::compiler::package::PackageManager pm;
std::string toml = R"(
[package]
name = "my-app"
version = "1.0.0"
)";
std::string name = pm.parse_name(toml); // "my-app"
std::string ver = pm.parse_version(toml); // "1.0.0"
std::string entry = pm.parse_entrypoint(toml, "main.br"); // "main.br"
std::string dep = pm.parse_dependency(toml);
// Diagnostics
std::string err = pm.missing_field_diagnostic("name");
std::string dup = pm.duplicate_key_diagnostic("version");
// Deterministic serialization
std::string out = pm.deterministic_serialization();| Method | Returns | Description |
|---|---|---|
parse_name(toml) | string | Extract name from TOML |
parse_version(toml) | string | Extract version from TOML |
parse_entrypoint(toml, default) | string | Extract entrypoint, fallback to default |
parse_dependency(toml) | string | Parse first dependency from array |
missing_field_diagnostic(field) | string | Generate missing field error message |
duplicate_key_diagnostic(key) | string | Generate duplicate key error message |
deterministic_serialization() | string | Serialize name/version deterministically |
Import Syntax
The Braid compiler (parser.c:750-764) parses import statements as dot-separated module paths. These are resolved at compile time by the bytecode codegen (bytecode_codegen.c:936-951).
# Standard library import
import std.io
import std.math
import std.net
# Nested module path
import std.collections
import std.diameter_patterns
# Relative path import (quoted string)
import "relative/path/to/module"
# Dot-separated package path
import package.submoduleThe parser accumulates dot-separated identifiers into a single module path string (e.g. "std.io", "std.diameter_patterns"). The codegen emits an OP_IMPORT bytecode instruction with the module name as a constant, then binds the last segment as the local variable name.
Module Resolution Algorithm
The compiler resolves imports by checking the following locations in order:
- Standard library —
braid-lang/lib/std/matchesstd.*imports - Local files — Relative paths and package-local
.br/.bd/.bxfiles - Package dependencies — Resolved from
braid.tomldependencies
For each candidate, the compiler tries the following extensions in order:
.br— Braid source file.bd— Braid declaration file (headers).bx— Pre-compiled bytecode binary
Example braid.toml Files from Real Projects
trustledger_api (examples/junction_apps/trustledger_api/braid.toml):
[project]
name = "trustledger_api"
version = "1.0.0"sentinelops_control_plane (examples/junction_apps/sentinelops_control_plane/braid.toml):
[package]
name = "sentinelops_control_plane"
version = "1.0.0"
authors = ["Jules"]
description = "SentinelOps Control Plane"
[dependencies]
junction = "1.0"
sync = "1.0"ops_command_center (examples/frontend_apps/ops_command_center/braid.toml):
[app]
name = "ops_command_center"
version = "1.0.0"framework_test (examples/framework_test/braid.toml):
[package]
name = "framework_test"
version = "1.0.0"
description = "Comprehensive integration test for all Braid frameworks"
entry = "src/main.br"
[dependencies]
junction = "1.0"
sync = "1.0"
bond = "1.0"
blend = "1.0"
link = "1.0"
merge = "1.0"bpkg test project (tools/bpkg/tests/braid.toml):
[package]
name = "test-project"
version = "0.1.0"
description = "A test project for bpkg"
[dependencies]
std.net = "1.0.0"
std.io = "0.9.0"
external-lib = "git://github.com/braid-lang/external-lib.git"Dependency Management Best Practices
- Pin versions — Always specify exact or major versions in
[dependencies] - Use standard library modules — Import via
std.*for guaranteed compatibility - Specify entrypoint — Set
entryexplicitly when the main file is notmain.br - Group dependencies by domain — Junction (web), Sync (state), Bond (frontend), Blend (CSS), Link (routing), Merge (state management)
- Git dependencies — Use
git://URLs for external dependencies not in a registry
Future: Registry & Version Constraints
The Braid package ecosystem is moving toward a central registry with support for:
- Package registry — A centralized index of Braid packages with search and discovery
- Version constraints — Semantic versioning with
^,~, and range operators - Publish workflow —
bpkg publishcommand to push packages to the registry - Lock files — Deterministic dependency resolution via
braid.lock - Workspaces — Multi-package monorepo support
Source Files
compiler/cpp/package/src/PackageManager.cpp— C++ PackageManager implementationcompiler/cpp/package/include/braid/compiler/package/PackageManager.hpp— PackageManager headerbraid-lang/src/compiler/parser.c— Import statement parsing (line 750+)braid-lang/src/compiler/bytecode_codegen.c— Import bytecode generation (line 936+)