| Crates.io | cuenv |
| lib.rs | cuenv |
| version | 0.4.7 |
| created_at | 2025-07-24 12:37:47.006003+00 |
| updated_at | 2025-08-07 14:35:57.034899+00 |
| description | A direnv alternative that uses CUE files for environment configuration |
| homepage | https://github.com/rawkode/cuenv |
| repository | https://github.com/rawkode/cuenv |
| max_upload_size | |
| id | 1765989 |
| size | 2,889,589 |
A direnv alternative that uses CUE packages for environment configuration.
Development is only supported through the Nix flake:
# Enter the development shell
nix develop
# Build the project
cargo build
# Install directly from the GitHub repository
nix profile install github:rawkode/cuenv
# Or run without installing
nix run github:rawkode/cuenv -- --help
# Using a specific version/commit
nix profile install github:rawkode/cuenv/<commit-sha>
If you're using Home Manager, you can use the included module:
# In your flake.nix
{
inputs = {
cuenv.url = "github:rawkode/cuenv";
# ... other inputs
};
outputs = { self, nixpkgs, home-manager, cuenv, ... }: {
homeConfigurations.yourUsername = home-manager.lib.homeManagerConfiguration {
# ... your configuration
modules = [
cuenv.homeManagerModules.default
{
programs.cuenv = {
enable = true;
# Optional: specify package
# package = cuenv.packages.${pkgs.system}.default;
# Shell integrations (auto-detected based on enabled shells)
# enableBashIntegration = true;
# enableZshIntegration = true;
# enableFishIntegration = true;
# enableNushellIntegration = true; # Experimental
};
}
];
};
};
}
The module will automatically:
# Install from crates.io
cargo install cuenv
# Clone the repository
git clone https://github.com/rawkode/cuenv
cd cuenv
# Build with Nix
nix build
# The binary will be available in ./result/bin/cuenv
Add the following to your shell configuration:
eval "$(cuenv init bash)"
eval "$(cuenv init zsh)"
cuenv init fish | source
.cue files:package env
import "github.com/rawkode/cuenv"
env: cuenv.#Env & {
DATABASE_URL: "postgres://localhost/mydb"
API_KEY: "secret123"
DEBUG: "true"
PORT: "3000"
}
cuenv - Load CUE package from current directorycuenv load [directory] - Manually load environment from a directorycuenv unload - Unload the current environmentcuenv status - Show environment changescuenv hook <shell> - Generate shell-specific hook outputcuenv init <shell> - Generate shell initialization scriptcuenv run <command> [args...] - Run a command in a hermetic environment with only CUE-defined variablescuenv run)Your CUE package should use the cuenv package schema:
package env
import "github.com/rawkode/cuenv"
env: cuenv.#Env & {
// String values
DATABASE_URL: "postgres://user:pass@host/db"
// String representations of numbers
PORT: "3000"
TIMEOUT: "30"
// String representations of booleans
DEBUG: "true"
ENABLE_CACHE: "false"
// Shell expansion is supported
LOG_PATH: "$HOME/logs/myapp"
// CUE features are supported
BASE_URL: "https://api.example.com"
API_ENDPOINT: "\(BASE_URL)/v1" // String interpolation
HOST: "localhost"
DATABASE_DSN: "postgres://\(HOST):5432/myapp" // Computed values
}
.cue files)The run command executes programs with only the environment variables defined in your CUE files (plus PATH and HOME for basic functionality):
# Run a command with CUE-defined environment
cuenv run node server.js
# Pass arguments to the command
cuenv run npm -- install --save-dev
# Run shell commands
cuenv run bash -- -c "echo PORT=\$PORT"
# The environment is hermetic - parent environment variables are not passed through
export PARENT_VAR=123
cuenv run bash -- -c 'echo "PARENT_VAR=$PARENT_VAR"' # Will print: PARENT_VAR=
You can configure disk and network access restrictions for tasks using the security section in your CUE task definitions. This uses Landlock (Linux Security Module) for enforcement:
tasks: {
"secure-build": {
description: "Build the project with restricted filesystem access"
command: "echo 'Building project securely...' && sleep 1 && echo 'Build complete!'"
security: {
restrictDisk: true
readOnlyPaths: ["/usr", "/lib", "/bin"]
readWritePaths: ["/tmp", "./build"]
}
}
"network-task": {
description: "Task that needs network access but with restrictions"
command: "echo 'Downloading dependencies...' && curl --version"
security: {
restrictNetwork: true
allowedHosts: ["api.example.com", "registry.npmjs.org"]
}
}
"fully-restricted": {
description: "Task with both disk and network restrictions"
command: "echo 'Running in secure sandbox'"
security: {
restrictDisk: true
restrictNetwork: true
readOnlyPaths: ["/usr/bin", "/bin"]
readWritePaths: ["/tmp"]
allowedHosts: ["localhost"]
}
}
"unrestricted": {
description: "Task without security restrictions"
command: "echo 'Running without restrictions' && ls -la /"
}
}
Running tasks with security restrictions:
# Run a task with disk restrictions
cuenv run secure-build
# Run a task with network restrictions
cuenv run network-task
# Run a fully restricted task
cuenv run fully-restricted
Landlock Requirements:
Security Configuration Options:
restrictDisk: Enable filesystem access restrictionsrestrictNetwork: Enable network access restrictionsreadOnlyPaths: Array of paths allowed for readingreadWritePaths: Array of paths allowed for reading and writingdenyPaths: Array of paths explicitly denied (overrides allow lists)allowedHosts: Array of network hosts/CIDRs allowed for connectionsSecurity Model: When disk restrictions are enabled, you must explicitly allow all paths your task needs access to. This includes:
/bin, /usr/bin)/lib, /usr/lib, /lib64, /usr/lib64)/etc if needed)Note: Network restrictions are currently limited by Landlock V2 capabilities. The implementation will be enhanced in future versions to provide more granular network access control.
Note: Network and process restrictions are not yet fully implemented with Landlock. Use system-level controls or container runtimes for those restrictions.
When using cuenv run, secret references in your CUE files are automatically resolved:
package env
import "github.com/rawkode/cuenv"
env: cuenv.#Env & {
// Regular environment variables
DATABASE_HOST: "localhost"
DATABASE_USER: "myapp"
// Secret references - 1Password format
DATABASE_PASSWORD: cuenv.#OnePasswordRef & {ref: "op://Personal/database/password"}
API_KEY: cuenv.#OnePasswordRef & {ref: "op://Work/myapp-api-key/field"}
// Secret references - Various providers
GITHUB_TOKEN: "github://myorg/myrepo/GITHUB_TOKEN"
AWS_SECRET: "aws-secret://prod/api/secret"
GCP_SECRET: "gcp-secret://myproject/db-password"
AZURE_KEY: "azure-keyvault://myvault/keys/mykey"
VAULT_TOKEN: "vault://secret/data/myapp/token"
// You can compose URLs with resolved secrets
DB_HOST: "prod.example.com"
DATABASE_URL: "postgres://\(DATABASE_USER):\(DATABASE_PASSWORD)@\(DB_HOST):5432/myapp"
}
Requirements:
op signingcloud auth loginNote: Secret resolution only happens with cuenv run. Regular cuenv load will not resolve secrets for security reasons.
When using cuenv run, any resolved secret values are automatically obfuscated in the command's stdout and stderr output. This prevents accidental exposure of sensitive information in logs or terminal output.
# Example: If DATABASE_PASSWORD resolves to "secret123"
cuenv run sh -c 'echo "Password is: $DATABASE_PASSWORD"'
# Output: Password is: ***********
# Secrets are obfuscated even in error messages
cuenv run sh -c 'echo "Error: Failed to connect with $API_KEY" >&2'
# Stderr: Error: Failed to connect with ***********
This obfuscation applies to all resolved secrets from 1Password and GCP Secrets Manager, helping maintain security when running commands with sensitive data.
cuenv supports environment-specific configurations and capability-based filtering:
package env
import "github.com/rawkode/cuenv"
env: cuenv.#Env & {
// Base configuration
DATABASE_URL: "postgresql://localhost:5432/myapp"
LOG_LEVEL: "info"
PORT: "3000"
// AWS capabilities - tagged with @capability
AWS_REGION: "us-east-1" @capability("aws")
AWS_ACCESS_KEY: "aws-access-key" @capability("aws")
AWS_SECRET_KEY: "aws-secret-key" @capability("aws")
// Docker capabilities
DOCKER_REGISTRY: "docker.io" @capability("docker")
DOCKER_IMAGE: "myapp:latest" @capability("docker")
// Environment-specific overrides
environment: {
production: {
DATABASE_URL: "postgresql://prod-db:5432/myapp"
LOG_LEVEL: "warn"
PORT: "8080"
AWS_REGION: "us-west-2" @capability("aws")
}
staging: {
DATABASE_URL: "postgresql://staging-db:5432/myapp"
LOG_LEVEL: "debug"
}
}
// Capability mappings for automatic inference
capabilities: {
aws: {
commands: ["terraform", "aws", "deploy"]
}
cloudflare: {
commands: ["terraform"]
}
docker: {
commands: ["deploy"]
}
}
}
Usage:
# Use production environment
cuenv run -e production -- ./app
# Enable specific capabilities
cuenv run -c aws -- aws s3 ls
# Use environment variables
CUENV_ENV=production CUENV_CAPABILITIES=aws cuenv run -- terraform apply
# Automatic capability inference from command
cuenv run -e production -- aws s3 ls # Automatically enables 'aws' capability
direnv allow (can be added if needed)