Two commands. Type-safe environments. Secrets that never leak. Tasks that run in parallel.
Warning
Rapid iteration in progress. I'm actively exploring the right APIs and schema to handle everything cuenv needs to do. Expect breaking changes between releases during this period. If you're using cuenv, be prepared for things to break.
You've been here before:
- Secrets in
.envfiles that accidentally get committed, logged, or shared - "Works on my machine" because environment variables differ between developers
- Build scripts that can't run in parallel so your CI takes forever
- Copy-paste task definitions across projects with no validation
cuenv fixes this with two powerful primitives.
cuenv exec -- npm start
cuenv exec -e production -- ./deploy.sh
cuenv exec -- cargo build --releaseEvery command runs with:
- Validated environment - CUE constraints ensure
NODE_ENVis actually"development" | "staging" | "production", not a typo - Secrets resolved at runtime - Pulled from 1Password, AWS, GCP, Vault—never stored in files, never in git history
- Environment-specific overrides - Switch from dev to production with
-e production
env: {
NODE_ENV: "development" | "staging" | "production"
PORT: >0 & <65536 & *3000
// Secrets are resolved at runtime, redacted from logs
DB_PASSWORD: schema.#OnePasswordRef & {
ref: "op://vault/database/password"
}
}Why this matters: Your production credentials are never on disk. They're fetched when needed, used, and forgotten. cuenv env print shows [SECRET] instead of values. Shell exports exclude secrets entirely.
cuenv task build
cuenv task test
cuenv task -e production deployEvery task runs with:
- Automatic dependency resolution -
buildwaits forlintandtestif configured - Parallel execution - Independent subtasks run simultaneously
- Content-aware caching - Skip tasks when inputs haven't changed
- Same secret + environment benefits as
exec
tasks: {
// Parallel: unit, integration, and lint run at the same time
test: {
unit: { command: "npm", args: ["run", "test:unit"] }
integration: { command: "npm", args: ["run", "test:e2e"] }
lint: { command: "npm", args: ["run", "lint"] }
}
// Sequential: each step waits for the previous
deploy: [
{ command: "docker", args: ["build", "-t", "myapp", "."] }
{ command: "docker", args: ["push", "myapp"] }
{ command: "kubectl", args: ["apply", "-f", "k8s/"] }
]
// Dependencies: build won't start until test completes
build: {
command: "npm"
args: ["run", "build"]
dependsOn: ["test"]
inputs: ["src/**/*", "package.json"]
outputs: ["dist/**/*"]
}
}Why this matters: Your test suite runs in parallel. Your CI is faster. If nothing changed, cached results are used. And every task inherits your validated environment and resolved secrets.
# Install cuenv
nix profile install github:cuenv/cuenv
# or: cargo install cuenv
# Create configuration
cat > env.cue << 'EOF'
package cuenv
import "github.com/cuenv/cuenv/schema"
schema.#Project & {
name: "my-project"
}
env: {
NODE_ENV: "development" | "production"
API_KEY: schema.#OnePasswordRef & { ref: "op://dev/api/key" }
}
tasks: {
dev: { command: "npm", args: ["run", "dev"] }
build: { command: "npm", args: ["run", "build"] }
test: { command: "npm", args: ["test"] }
}
EOF
# Run commands with your secure environment
cuenv exec -- npm install
cuenv task dev
# List available tasks
cuenv task
# Generate CI workflow (optional)
cuenv ci --generate githubStop committing .env files. Define secrets with any provider—they're resolved only when needed:
env: {
// 1Password
DB_PASSWORD: schema.#OnePasswordRef & { ref: "op://vault/db/password" }
// AWS Secrets Manager
API_KEY: schema.#AWSSecretRef & { region: "us-west-2", name: "api-key" }
// HashiCorp Vault
STRIPE_KEY: schema.#VaultRef & { path: "secret/stripe", field: "key" }
// Or define your own resolver for any CLI
CUSTOM_SECRET: schema.#ExecResolver & {
command: "my-secret-tool"
args: ["fetch", "my-secret"]
}
}Secrets are never written to disk, never exported to your shell, and redacted from logs.
Catch configuration errors before they become runtime failures:
env: {
// Constrained to valid values only
NODE_ENV: "development" | "staging" | "production"
LOG_LEVEL: "debug" | "info" | "warn" | "error"
// Must match patterns
DATABASE_URL: string & =~"^postgresql://"
API_ENDPOINT: string & =~"^https://"
// Numeric bounds
PORT: >0 & <65536
// Defaults that can be overridden
TIMEOUT: string | *"30s"
}If someone sets NODE_ENV: "prod" instead of "production", cuenv tells them immediately.
Object keys run in parallel. Arrays run sequentially. Dependencies are respected automatically:
tasks: {
// These three run at the same time
lint: {
check: { command: "eslint", args: ["src/"] }
types: { command: "tsc", args: ["--noEmit"] }
format: { command: "prettier", args: ["--check", "."] }
}
// These run one after another
deploy: [
{ command: "npm", args: ["run", "build"] }
{ command: "docker", args: ["build", "-t", "app", "."] }
{ command: "docker", args: ["push", "app"] }
{ command: "kubectl", args: ["rollout", "restart", "deployment/app"] }
]
// This waits for lint to complete first
build: {
command: "npm"
args: ["run", "build"]
dependsOn: ["lint"]
}
}CUE configurations compose naturally. Define once, use everywhere:
myproject/
├── env.cue # Global settings
├── shared/
│ └── database.cue # Shared DB config
├── services/
│ ├── api/
│ │ └── env.cue # Inherits global + adds API-specific
│ └── web/
│ └── env.cue # Inherits global + adds web-specific
// services/api/env.cue
import "github.com/myorg/shared/database"
env: database.#Config & {
SERVICE_NAME: "api"
PORT: 8080
}When you cd into a cuenv project, your shell is configured automatically:
# Add to .zshrc / .bashrc
eval "$(cuenv shell init zsh)"
# Now just cd into your project
cd ~/projects/myapp
# → Environment loaded automatically
# → Nix packages available (if configured)
# → Ready to workGenerate CI workflows from your CUE configuration. cuenv detects affected projects and runs only what's needed:
# Generate GitHub Actions workflow
cuenv ci --generate github
# Run CI locally
cuenv ci
# Preview what would run
cuenv ci --dry-runcuenv automatically detects your CI provider (GitHub Actions, GitLab CI, etc.) and optimizes pipelines based on which files changed.
Manage releases with changesets and automated publishing:
# Add a changeset describing your changes
cuenv changeset add -s "Added dark mode" -P my-package:minor
# Or generate from conventional commits
cuenv changeset from-commits
# Preview version bumps
cuenv release version --dry-run
# Publish packages in dependency order
cuenv release publishChangesets integrate with conventional commits and automatically calculate semantic version bumps.
Generate and sync files from CUE templates—configuration files, boilerplate, and more:
# Sync all generated files
cuenv sync cubes
# Check if files are in sync (useful in CI)
cuenv sync cubes --check
# Preview changes
cuenv sync cubes --diff --dry-runDefine cubes in your CUE configuration to generate TypeScript configs, Dockerfiles, or any templated content.
cuenv supports GitHub, GitLab, and Bitbucket for CODEOWNERS and CI integration:
# Sync CODEOWNERS for your platform
cuenv sync codeowners
# Works with GitHub, GitLab, or Bitbucket
# Platform is auto-detected from your repository# Execute commands with validated environment + resolved secrets
cuenv exec -- npm start # or: cuenv x -- npm start
cuenv exec -e production -- ./deploy.sh
# Run named tasks with dependencies, parallelism, caching
cuenv task build # or: cuenv t build
cuenv task -e staging test
cuenv task --tui build # Rich TUI output
cuenv task -l ci # Run all tasks with label "ci"# View environment (secrets are redacted)
cuenv env print
cuenv env print --output-format json
cuenv env list # List available environments
# Shell integration
cuenv shell init zsh >> ~/.zshrc
cuenv env load # Load environment in background
cuenv env status # Check hook execution status# Sync generated files from CUE configuration
cuenv sync # Sync all
cuenv sync ignore # Generate .gitignore/.dockerignore
cuenv sync codeowners # Sync CODEOWNERS file
cuenv sync cubes # Sync code from CUE cubes
cuenv sync --check # Check if files are in sync# CI integration
cuenv ci # Run CI pipeline
cuenv ci --generate github # Generate GitHub Actions workflow
cuenv ci --dry-run # Preview what would run
# Release management
cuenv changeset add # Add a changeset entry
cuenv changeset status # Show pending changesets
cuenv changeset from-commits # Generate from conventional commits
cuenv release version # Calculate and apply version bumps
cuenv release publish # Publish to crates.io# Security approval for configurations
cuenv allow # Approve configuration for hooks
cuenv deny # Revoke approval
# Utilities
cuenv version # Show version info
cuenv completions zsh # Generate shell completions
cuenv tui # Interactive TUI dashboard| Option | Description |
|---|---|
--env, -e |
Environment to use (dev, staging, production) |
-p, --path |
Directory with CUE files (default: ".") |
--package |
CUE package name (default: "cuenv") |
--output-format |
Output format (json, env, simple) |
-L, --level |
Log level (trace, debug, info, warn, error) |
| Feature | cuenv | Make | Bazel | Taskfile | direnv |
|---|---|---|---|---|---|
| Type Safety | ✅ CUE constraints | ❌ | ✅ BUILD files | ❌ | ❌ |
| Monorepo Support | ✅ Native | ✅ Excellent | |||
| Environment Management | ✅ Typed + Secrets | ❌ | ❌ | ❌ | ✅ Basic |
| Task Dependencies | ✅ Smart | ✅ | ✅ Advanced | ✅ Basic | ❌ |
| Parallel Execution | ✅ | ✅ | ❌ | ||
| Caching | ✅ Content-aware | ❌ | ✅ Advanced | ❌ | ❌ |
| CI Integration | ✅ Native | ❌ | ❌ | ❌ | |
| Security Isolation | ✅ Via Dagger | ❌ | ✅ Sandboxing | ❌ | ❌ |
| Shell Integration | ✅ | ❌ | ❌ | ❌ | ✅ |
| Component | Status |
|---|---|
| CUE Evaluation Engine | ✅ Complete |
| CLI + Task Runner | ✅ Complete |
| Secret Management | ✅ Complete |
| Shell Integration | ✅ Complete |
| CI Integration | 🚧 Development |
| Release Management | 🚧 Development |
| Code Generation | 🚧 Development |
| Security Isolation | ✅ Complete |
We welcome contributions! cuenv is licensed under AGPL-3.0, ensuring it remains open source.
# Clone the repository
jj git clone https://github.com/cuenv/cuenv
cd cuenv
# Enter development environment
nix develop
# or with direnv: direnv allow
# Project automation (this repo)
cuenv task fmt.check
cuenv task lint
cuenv task test.unit
cuenv task buildcuenv/
├── crates/
│ ├── cuengine/ # CUE evaluation engine (Go FFI bridge)
│ ├── core/ # Shared types, task execution, caching
│ ├── cuenv/ # CLI and TUI
│ ├── events/ # Event system for UI frontends
│ ├── workspaces/ # Monorepo and package manager detection
│ ├── ci/ # CI pipeline integration
│ ├── release/ # Version management and publishing
│ ├── cubes/ # CUE-based code generation
│ ├── ignore/ # Ignore file generation
│ ├── codeowners/ # CODEOWNERS generation
│ ├── github/ # GitHub provider
│ ├── gitlab/ # GitLab provider
│ ├── bitbucket/ # Bitbucket provider
│ └── dagger/ # Dagger task execution backend
├── schema/ # CUE schema definitions
├── examples/ # CUE configuration examples
└── docs/ # Documentation
- Unit tests:
cuenv task test.unit - BDD tests:
cuenv task test.bdd - Coverage:
cuenv task coverage
Licensed under the GNU Affero General Public License v3.0.
Why AGPL? We believe in keeping cuenv open source while building a sustainable business. The AGPL ensures that any modifications or hosted services using cuenv remain open source, benefiting the entire community.
- Documentation: cuenv.dev 🚧
- CUE Language: cuelang.org
- Discussion: GitHub Discussions
Built in 🏴 w for the open source community