Skip to content

Architecture

This page describes the internal architecture of cuenv, explaining how the different components work together to provide typed environment management and task orchestration.

cuenv is built as a layered system with clear separation of concerns:

┌─────────────────────────────────────────────────────────────┐
│ cuenv-cli │
│ (Command-line interface & user interaction) │
├─────────────────────────────────────────────────────────────┤
│ cuenv-core │
│ (Tasks, environments, hooks, secrets, shell) │
├─────────────────────────────────────────────────────────────┤
│ cuengine │
│ (CUE evaluation via Go FFI) │
├─────────────────────────────────────────────────────────────┤
│ Go CUE Runtime │
│ (cuelang.org/go/cue) │
└─────────────────────────────────────────────────────────────┘

The CUE evaluation engine providing a safe Rust interface to the Go-based CUE evaluator.

Key responsibilities:

  • FFI bridge between Rust and Go
  • Safe memory management with RAII wrappers
  • CUE expression evaluation
  • Caching of evaluation results
  • Retry logic for transient failures

Notable features:

  • CueEvaluator - Main evaluator type with builder pattern configuration
  • CStringPtr - RAII wrapper for C strings returned from FFI
  • Response envelope parsing with structured error handling
  • LRU cache for evaluation results
use cuengine::CueEvaluatorBuilder;
let evaluator = CueEvaluatorBuilder::new()
.directory("./project")
.package("cuenv")
.build()?;
let result = evaluator.evaluate()?;

Core library containing shared types, configuration parsing, and domain logic.

Modules:

  • manifest - CUE manifest parsing and the Cuenv type
  • tasks - Task definitions, execution, and dependencies
  • environment - Environment variable handling and validation
  • hooks - Shell hooks for onEnter/onExit events
  • secrets - Secret resolution and policy enforcement
  • shell - Shell integration and export formatting
  • cache - Task caching with content-aware invalidation
  • config - Configuration file handling

Error handling: Uses miette for rich diagnostic errors with:

  • Source code snippets
  • Error spans
  • Contextual help messages
  • Suggestions for fixes
use cuenv_core::{Error, Result};
#[derive(Error, Debug, Diagnostic)]
pub enum Error {
#[error("Configuration error: {message}")]
#[diagnostic(
code(cuenv::config::invalid),
help("Check your env.cue configuration")
)]
Configuration { message: String },
}

The command-line interface built with clap.

Commands:

  • cuenv task [name] - Execute or list tasks
  • cuenv env print|check|load - Environment operations
  • cuenv exec -- <cmd> - Run commands with environment
  • cuenv shell init <shell> - Generate shell integration
  • cuenv allow|deny - Security approval management
  • cuenv version - Version information

Workspace management for monorepos.

Features:

  • Detect and configure workspaces
  • Package manager integration (bun, pnpm, yarn, cargo)
  • Workspace-aware task execution

The Go-Rust FFI bridge is a critical component enabling CUE evaluation from Rust.

// Exported functions callable from Rust
//export cue_eval_package
func cue_eval_package(pathPtr *C.char, packagePtr *C.char) *C.char
//export cue_free_string
func cue_free_string(ptr *C.char)
//export cue_bridge_version
func cue_bridge_version() *C.char
// FFI declarations
extern "C" {
fn cue_eval_package(path: *const c_char, package: *const c_char) -> *mut c_char;
fn cue_free_string(ptr: *mut c_char);
fn cue_bridge_version() -> *mut c_char;
}

All FFI responses use a structured JSON envelope:

{
"version": "1.0.0",
"ok": {
/* evaluation result */
},
"error": null
}

Or on error:

{
"version": "1.0.0",
"ok": null,
"error": {
"code": "LOAD_INSTANCE",
"message": "failed to load CUE instance",
"hint": "Check that the package exists"
}
}
CodeDescription
INVALID_INPUTInvalid input parameters
LOAD_INSTANCEFailed to load CUE instance
BUILD_VALUEFailed to build CUE value
ORDERED_JSONJSON serialization failed
PANIC_RECOVERRecovered from Go panic
JSON_MARSHAL_ERRORJSON marshaling failed
REGISTRY_INITRegistry initialization failed

cuenv implements multiple caching layers:

LRU cache for CUE evaluation results:

pub struct EvaluationCache {
cache: LruCache<CacheKey, CachedResult>,
max_size: usize,
}

Cache key components:

  • Directory path
  • Package name
  • File content hashes

Content-aware caching for task outputs:

~/.cache/cuenv/tasks/<hash>/
├── metadata.json # Task metadata and input hashes
├── stdout # Captured stdout
├── stderr # Captured stderr
└── outputs/ # Task output files

Cache invalidation triggers:

  • Input file changes (content hash)
  • Task definition changes
  • Environment variable changes
  • cuenv version changes

Tasks form a directed acyclic graph (DAG) based on dependsOn:

┌─────┐
│build│
└──┬──┘
┌─────┴─────┐
▼ ▼
┌─────┐ ┌─────┐
│lint │ │test │
└─────┘ └──┬──┘
┌──┴──┐
▼ ▼
┌────┐┌────┐
│unit││e2e │
└────┘└────┘
  1. Sequential (array tasks): Execute in order
  2. Parallel (object tasks): Execute concurrently
  3. Dependent: Wait for dependencies to complete
tasks: {
// Single command
build: {
command: "cargo"
args: ["build"]
}
// Sequential list
deploy: [
{command: "build"},
{command: "push"},
]
// Nested (parallel groups)
test: {
unit: {command: "test-unit"}
e2e: {command: "test-e2e"}
}
}
cd /project/dir
┌──────────────┐
│ cuenv detect │
└──────┬───────┘
│ env.cue found
┌──────────────┐
│ Check approval│
└──────┬───────┘
│ approved
┌──────────────┐
│ Load hooks │
│ (background) │
└──────┬───────┘
┌──────────────┐
│ Execute │
│ onEnter │
└──────┬───────┘
┌──────────────┐
│ Export env │
│ to shell │
└──────────────┘
  1. Approval Gate: Configurations must be explicitly approved before hooks run
  2. Content Hashing: Approval is invalidated when configuration changes
  3. Policy Enforcement: Secrets are only accessible to authorized tasks
env.cue ──► cuengine ──► Cuenv struct ──► Environment vars
│ │
└── schema validation ────┘
cuenv task build
┌──────────────┐
│ Parse config │
└──────┬───────┘
┌──────────────┐
│ Resolve deps │
└──────┬───────┘
┌──────────────┐
│ Check cache │
└──────┬───────┘
│ miss
┌──────────────┐
│ Load env │
└──────┬───────┘
┌──────────────┐
│ Resolve │
│ secrets │
└──────┬───────┘
┌──────────────┐
│ Execute │
└──────┬───────┘
┌──────────────┐
│ Update cache │
└──────────────┘
  • Linux namespaces: Process isolation
  • Landlock: Filesystem access control
  • eBPF: System call monitoring
  • Remote cache backends
  • Distributed task execution
  • Build farm integration