Skip to content

Instantly share code, notes, and snippets.

@rawkode
Created December 8, 2025 23:07
Show Gist options
  • Select an option

  • Save rawkode/64fb139c197cd803bdd88d73c7075cc1 to your computer and use it in GitHub Desktop.

Select an option

Save rawkode/64fb139c197cd803bdd88d73c7075cc1 to your computer and use it in GitHub Desktop.
cuenv --llms
# cuenv
> A modern application build toolchain with typed environments and CUE-powered task orchestration.
cuenv provides two core primitives for secure, validated development environments:
## Core Primitives
### `cuenv exec -- <command>`
Run any command with a validated environment and runtime-resolved secrets:
```bash
cuenv exec -- npm start
cuenv exec -e production -- ./deploy.sh
```
- Environment variables are validated against CUE constraints
- Secrets are resolved at runtime from providers (1Password, AWS, GCP, Vault)
- Secrets are never written to disk or exported to shell history
### `cuenv task <name>`
Execute orchestrated tasks with dependencies, parallelism, and caching:
```bash
cuenv task build
cuenv task -e staging test
```
- Tasks can run in parallel (object syntax) or sequentially (array syntax)
- Automatic dependency resolution via `dependsOn`
- Content-aware caching based on declared `inputs` and `outputs`
- Hermetic execution ensures reproducibility
## Configuration
cuenv uses CUE for type-safe configuration. Create an `env.cue` file:
```cue
package cuenv
import "github.com/cuenv/cuenv/schema"
schema.#Cuenv
env: {
NODE_ENV: "development" | "staging" | "production"
API_KEY: schema.#Secret & { command: "op", args: ["read", "op://vault/api/key"] }
}
tasks: {
build: {
command: "npm"
args: ["run", "build"]
inputs: ["src/**/*", "package.json"]
outputs: ["dist/**/*"]
}
test: {
unit: { command: "npm", args: ["test"] }
integration: { command: "npm", args: ["test:e2e"] }
}
}
```
## Key Concepts
- **Type Safety**: CUE constraints validate environment variables before execution
- **Secret Management**: Secrets resolved at runtime, redacted from logs, never persisted
- **Parallel Execution**: Object keys in task groups run concurrently
- **Sequential Execution**: Array elements in task groups run in order
- **Caching**: Tasks with declared inputs/outputs are cached by content hash
- **Hermetic Builds**: Tasks run in isolated directories with only declared inputs
## CLI Reference
```
cuenv exec -- <command> Execute command with validated environment
cuenv task <name> Run a named task
cuenv env print Show environment variables (secrets redacted)
cuenv env list List available environments
cuenv allow Approve configuration for hook execution
cuenv shell init <shell> Generate shell integration script
```
## Links
- Repository: https://github.com/cuenv/cuenv
- CUE Language: https://cuelang.org
## CUE Schema Reference
### ci.cue
```cue
package schema
#PipelineCondition: {
pullRequest?: bool
branch?: string | [...string]
tag?: string | [...string]
defaultBranch?: bool
scheduled?: bool
manual?: bool
}
#Pipeline: {
name: string
when?: #PipelineCondition
tasks: [...string]
}
#CI: {
pipelines: [...#Pipeline]
}
```
### config.cue
```cue
package schema
#Config: {
// Task output format
outputFormat?: "tui" | "spinner" | "simple" | "tree" | "json"
}
```
### cuenv.cue
```cue
package schema
#Cuenv: {
name?: string
config?: #Config
env?: #Env
hooks?: #Hooks
workspaces?: #Workspaces
ci?: #CI
release?: #Release
tasks: [string]: #Tasks | *{}
}
#Workspaces: [string]: #WorkspaceConfig
#WorkspaceConfig: {
enabled: bool | *true
package_manager?: "npm" | "pnpm" | "yarn" | "yarn-classic" | "bun" | "cargo"
root?: string
}
```
### devenv.cue
```cue
package schema
#Devenv: #ExecHook & {
order: 10
propagate: false
command: "devenv"
args: ["print-dev-env"]
source: true
inputs: ["devenv.nix", "devenv.lock", "devenv.yaml"]
}
```
### env.cue
```cue
package schema
// Environment variable value with optional policies
// Closed to avoid ambiguity with direct #Secret usage in #EnvironmentVariable
#EnvironmentVariableWithPolicies: close({
value: string | int | bool | #Secret
policies?: [...#Policy]
})
// Environment variable can be a simple value or a value with policies
#EnvironmentVariable: string | int | bool | #Secret | #EnvironmentVariableWithPolicies
// We support non-string types for constraints
// but when exported to the actual environment,
// these will always be strings.
#Environment: {
[=~"^[A-Z][A-Z0-9_]*$"]: #EnvironmentVariable
}
// #Env defines the structure for environment variable configuration
#Env: #Environment & {
// Environment-specific overrides
environment?: [string]: #Environment
}
```
### gcp.cue
```cue
package schema
#GcpSecret: close({
project: string
secret: string
version: string | *"latest"
ref: "gcp://\(project)/\(secret)/\(version)"
resolver: "exec"
command: "gcloud"
args: ["secrets", "versions", "access", version, "--secret", secret, "--project", project]
})
```
### hooks.cue
```cue
package schema
#Hooks: {
onEnter?: [string]: #Hook
onExit?: [string]: #Hook
}
#Hook: #ExecHook
#ExecHook: {
order?: int | *100
propagate?: bool | *false
command!: string
args?: [...string]
dir?: string | *"."
inputs?: [...string]
source?: bool
// To be extended
...
}
```
### nix.cue
```cue
package schema
#NixFlake: #ExecHook & {
order: 10
propagate: false
command: "nix"
args: ["print-dev-env"]
source: true
inputs: ["flake.nix", "flake.lock"]
}
```
### onepassword.cue
```cue
package schema
#OnePasswordRef: close({
resolver: "exec"
ref: string
command: "op"
args: ["read", ref]
})
```
### policy.cue
```cue
package schema
// #Policy defines access control for environment variables
#Policy: {
// Allowlist of task names that can access this variable
allowTasks?: [...string]
// Allowlist of exec commands that can access this variable
allowExec?: [...string]
}
```
### release.cue
```cue
package schema
// #Release defines the release management configuration for cuenv.
// This enables native release workflows including versioning, changelogs, and publishing.
#Release: {
// Git configuration for release management
git?: #ReleaseGit
// Package grouping configuration
packages?: #ReleasePackages
// CHANGELOG generation configuration
changelog?: #ChangelogConfig
}
// #ReleaseGit defines git-related release settings
#ReleaseGit: {
// Default branch for releases (e.g., "main", "master")
defaultBranch?: string | *"main"
// Tag format template. Supports ${package} and ${version} placeholders.
// Examples:
// - "v${version}" for single-package repos
// - "${package}-v${version}" for monorepos
tagFormat?: string | *"v${version}"
// Whether to create tags during release
createTags?: bool | *true
// Whether to push tags to remote
pushTags?: bool | *true
}
// #ReleasePackages defines package grouping for version management
#ReleasePackages: {
// Fixed groups: packages that share the same version (lockstep versioning)
// All packages in a group are bumped together with the highest bump level.
// Example: [["crates/cuenv-core", "crates/cuenv-cli"]]
fixed?: [...[...string]]
// Linked groups: packages that have their versions updated together when
// any one of them has a change. Unlike fixed, versions can differ.
// Example: [["crates/*"]]
linked?: [...[...string]]
// Independent packages: not part of any group, versioned independently
// This is implicit - packages not in fixed or linked are independent
}
// #ChangelogConfig defines CHANGELOG generation settings
#ChangelogConfig: {
// Path to the CHANGELOG file relative to project/package root
path?: string | *"CHANGELOG.md"
// Whether to generate changelogs for each package
perPackage?: bool | *true
// Whether to generate a root changelog for the entire workspace
workspace?: bool | *true
// Categories for organizing changelog entries
categories?: [...#ChangelogCategory]
}
// #ChangelogCategory defines a category for changelog entries
#ChangelogCategory: {
// Title for the category in the changelog
title: string
// Changeset types that belong to this category
types: [...#ChangesetType]
}
// #ChangesetType defines the type of change in a changeset
#ChangesetType: "major" | "minor" | "patch" | "none"
// #Changeset represents a single changeset entry
#Changeset: {
// Unique identifier for the changeset
id: string
// Summary of the change
summary: string
// Packages affected by this change
packages: [...#PackageChange]
// Optional longer description
description?: string
}
// #PackageChange represents a version bump for a specific package
#PackageChange: {
// Package name or path
name: string
// Type of version bump
bump: #ChangesetType
}
```
### rust.cue
```cue
package schema
// #Rust provides a collection of reusable tasks for Rust projects.
// It includes standard commands for building, testing, and linting.
//
// Usage:
//
// import "github.com/cuenv/cuenv/schema"
//
// tasks: {
// build: schema.#Rust.#Build & {
// inputs: ["Cargo.toml", "src"]
// }
// }
#Rust: {
// Common inputs used across most Rust tasks
// Users should override this to match their project structure
#BaseInputs: [...string] | *["Cargo.toml", "Cargo.lock", "src"]
// #Build runs 'cargo build'
#Build: #Task & {
command: "cargo"
args: ["build", ...string]
inputs: #BaseInputs
}
// #Test runs 'cargo test'
#Test: #Task & {
command: "cargo"
args: ["test", ...string]
inputs: #BaseInputs
}
// #Clippy runs 'cargo clippy'
#Clippy: #Task & {
command: "cargo"
args: ["clippy", ...string]
inputs: #BaseInputs
}
// #Fmt runs 'cargo fmt'
#Fmt: #Task & {
command: "cargo"
args: ["fmt", ...string]
inputs: #BaseInputs
}
// #Check runs 'cargo check' (faster than build)
#Check: #Task & {
command: "cargo"
args: ["check", ...string]
inputs: #BaseInputs
}
// #Doc runs 'cargo doc'
#Doc: #Task & {
command: "cargo"
args: ["doc", ...string]
inputs: #BaseInputs
}
// Default tasks exposed by this module
// Note: fmt and test are not exposed to avoid conflicts with common
// monorepo setups (treefmt, test groups).
build: #Build
check: #Check
clippy: #Clippy
doc: #Doc
...
}
```
### secrets.cue
```cue
package schema
// Base secret type with exec resolver
#Secret: {
resolver: "exec"
command: string
args?: [...string]
...
}
// For backward compatibility and structured types
#ExecResolver: {
command: string
args?: [...string]
}
```
### shell.cue
```cue
package schema
#Shell: {
command: string // Shell executable name (e.g., "bash", "fish", "zsh")
flag: string // Flag for command execution (e.g., "-c", "--command")
}
#Bash: #Shell & {
command: "bash"
flag: "-c"
}
#Fish: #Shell & {
command: "fish"
flag: "-c"
}
#Zsh: #Shell & {
command: "zsh"
flag: "-c"
}
#Sh: #Shell & {
command: "sh"
flag: "-c"
}
#Cmd: #Shell & {
command: "cmd"
flag: "/C"
}
#PowerShell: #Shell & {
command: "powershell"
flag: "-Command"
}
```
### tasks.cue
```cue
package schema
// #Tasks can represent either a single task or a group of tasks.
// Use a single #Task when you have an isolated command to run.
// Use a #TaskGroup when you need to define multiple tasks that should be executed
// either sequentially (as an array) or in parallel with dependencies (as an object).
// Choose the structure based on your workflow requirements:
// - Single #Task: Simple, standalone execution.
// - #TaskGroup: Complex workflows involving multiple tasks and dependencies.
#Tasks: #Task | #TaskGroup
#Task: {
shell?: #Shell
// Command to execute. Required unless 'script' is provided.
command?: string
// Inline script to execute (alternative to command).
// When script is provided, shell defaults to bash if not specified.
// Supports multiline strings and shebang lines for polyglot scripts.
// Example:
// script: """
// #!/bin/bash
// set -euo pipefail
// echo "Building..."
// cargo build --release
// """
script?: string
// Validation: exactly one of command or script must be provided
_hasCommand: command != _|_
_hasScript: script != _|_
_validTask: true & ((_hasCommand & !_hasScript) | (!_hasCommand & _hasScript))
args?: [...string]
env?: [string]: #EnvironmentVariable
// When true (default), task runs in an isolated hermetic directory with only
// declared inputs available. When false, task runs directly in the workspace
// root (if workspaces specified) or project root. Non-hermetic tasks are useful
// for install commands that need to write to the real filesystem.
hermetic?: bool | *true
dependsOn?: [...string]
// Inputs accepted:
// - File paths relative to the env.cue root, e.g. "src/index.ts"
// - Directories (recursively included), e.g. "src" or "src/lib"
// - Glob patterns (first-class), e.g. "src/**/*.ts", "assets/**/*.{png,jpg}"
// - Project references that pull outputs from another task in the repo
// All inputs are resolved relative to the project root and are the ONLY files
// made available inside the hermetic working directory when executing the task.
inputs?: [...#Input]
// Outputs accepted (same syntax as inputs): files, directories, and globs relative
// to the project root. Only declared outputs are indexed and persisted to the
// cache for later materialization. Writes to undeclared paths are allowed but
// will be warned about and are not indexed.
outputs?: [...string]
// Consume cached outputs from other tasks in the same project.
// The referenced task's outputs are materialized into this task's hermetic workspace.
inputsFrom?: [...#TaskOutput]
// Workspaces to mount/enable for this task
workspaces?: [...string]
description?: string
// Dagger-specific configuration for running this task in a container
dagger?: #DaggerConfig
// Task parameter definitions for CLI arguments
// Allows tasks to accept positional and named arguments:
// cuenv task import.youtube VIDEO_ID --quality 1080p
params?: #TaskParams
}
// Task parameter definitions
#TaskParams: {
// Positional arguments (order matters, consumed left-to-right)
// Referenced in args as {{0}}, {{1}}, etc.
positional?: [...#Param]
// Named arguments are declared as direct fields (--flag style)
// Referenced in args as {{name}} where name matches the field name
// Example: thumbnailUrl: { description: "URL", required: false }
[!~"^positional$"]: #Param
}
// Parameter definition for task arguments
#Param: {
// Human-readable description shown in --help
description?: string
// Whether the argument must be provided (default: false)
required?: bool | *false
// Default value if not provided
default?: string
// Type hint for validation (default: "string")
type?: "string" | "bool" | "int" | *"string"
// Short flag (single character, e.g., "t" for -t)
short?: =~"^[a-zA-Z]$"
}
// Accepted task inputs:
// - string: File path, directory, or glob pattern
// - #ProjectReference: Cross-project task outputs
// - #TaskOutput: Same-project task outputs
#Input: string | #ProjectReference | #TaskOutput
// Reference to another project's task within the same Git root
#ProjectReference: {
// Path to external project root. May be absolute-from-repo-root (prefix "/")
// or relative to the env.cue declaring this dependency.
project: string
// Name of the external task in that project
task: string
// Explicit selection and mapping of outputs to this task's hermetic workspace
map: [...#Mapping]
}
#Mapping: {
// Path of a declared output (file or directory) from the external task,
// relative to the external project's root. Directories map recursively.
from: string
// Destination path inside the dependent task's hermetic workspace where the
// selected file/dir will be materialized. Must be unique per mapping.
to: string
}
// Notes:
// - 'from' values must be among the external task's declared outputs
// - Directories in 'from' map recursively
// - Each 'to' destination must be unique; collisions are disallowed
// - External tasks run with their own environment; no env injection from dependents
// Reference to another task's outputs within the same project
#TaskOutput: {
// Name of the task whose cached outputs to consume (e.g. "docs.build")
task: string
// Optional explicit mapping of outputs. If omitted, all outputs are
// materialized at their original paths in the hermetic workspace.
map?: [...#Mapping]
}
// TaskGroup uses structure to determine execution mode:
// - Array of tasks: Sequential execution (order preserved)
// - Object of named tasks: Parallel execution with dependencies
#TaskGroup: [...#Tasks] | {[string]: #Tasks}
// Dagger-specific task configuration for containerized execution
#DaggerConfig: {
// Base container image (e.g., "node:20-alpine", "rust:1.75-slim")
// Required unless 'from' is specified
image?: string
// Use container from a previous task as base instead of an image.
// The referenced task must have run and produced a container.
// Example: from: "deps" continues from the "deps" task's container
from?: string
// Secrets to mount or expose as environment variables.
// Secrets are resolved using cuenv's secret resolvers (exec, 1Password, etc.)
// and securely passed to Dagger without exposing plaintext in logs.
secrets?: [...#DaggerSecret]
// Cache volumes to mount for persistent build caching.
// Cache volumes persist across task runs and speed up builds.
cache?: [...#DaggerCacheMount]
}
// Secret configuration for Dagger containers
#DaggerSecret: {
// Name identifier for the secret in Dagger
name: string
// Mount secret as a file at this path (e.g., "/root/.npmrc")
path?: string
// Expose secret as an environment variable with this name
envVar?: string
// Secret resolver - uses existing cuenv secret types (#Secret, #OnePasswordRef, etc.)
resolver: #Secret
}
// Cache volume mount configuration
#DaggerCacheMount: {
// Path inside the container to mount the cache (e.g., "/root/.npm", "/root/.cargo/registry")
path: string
// Unique name for the cache volume. Volumes with the same name share data.
name: string
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment