A CLI tool written in Rust for managing infrastructure deployments across multiple technologies (Terraform, Helm, Kustomize, and Ansible).
- 🔍 Auto-detection - Automatically detects technology type (terraform/helm/kustomize/ansible)
- ✅ Environment validation - Validates environment names before execution
- 🔒 Kubernetes context safety - Prevents deploying to wrong clusters (Helm/Kustomize)
- 🎨 Color-coded output - Clear, readable terminal output
- 🚀 Direct command execution - No intermediate make calls
- 🔧 Special commands - Support for
unlock, andduplicate - 🐚 Shell completions - Bash and Zsh support
Download pre-built binaries from the releases page:
# Download and install (example for Linux/macOS)
curl -L https://github.com/baprx/mk/releases/latest/download/mk-<platform> -o mk
chmod +x mk
mv mk ~/.local/bin/cargo build --release --locked
cp target/release/mk ~/.local/bin/Generate completions for your shell:
# Bash
mk completions bash > ~/.local/share/bash-completion/completions/mk
source ~/.local/share/bash-completion/completions/mk
# Zsh
source <(mk completions zsh)The completions include dynamic environment completion based on your project structure:
- For Terraform projects: Completes from
tfvars/*.tfvarsfiles - For Helm projects: Completes from
values/*/directories - For Kustomize projects: Completes from
overlays/*/directories - For Ansible projects: Completes from
inventories/*.ymlfiles
Example usage:
mk apply infrastructure/iam/terraform <TAB>
# Suggests: dev prod staging (based on actual tfvars files)# Apply infrastructure changes
mk apply <project-path> <environment> [options]
# Plan/check changes
mk check <project-path> <environment> [options]
mk plan <project-path> <environment> [options] # Alias for check
# Show diff
mk diff <project-path> <environment> [options]
# Destroy/delete infrastructure
mk delete <project-path> <environment> [options]
mk destroy <project-path> <environment> [options] # Alias
mk uninstall <project-path> <environment> [options] # Alias
# Update dependencies
mk deps <project-path> <environment> [options]
# Render templates
mk template <project-path> <environment> [options]
# Get terraform output
mk output <project-path> <environment> <key> # Autocompletion works for <key>, also a --all flag is available
# List ansible inventory
mk list <project-path> <environment> [options]
# Duplicate environment
mk duplicate <project-path> <source-env> <target-env>
# Check for dependency updates (Terraform & Helm)
mk bump <project-path> [--include-prereleases] [--recursive]# Force unlock terraform state
mk unlock <project-path> <environment> <lock-id>The bump command helps you keep Terraform modules and Helm charts up to date:
# Scan a single project for outdated dependencies
mk bump infrastructure/terraform/my-project
# Scan recursively across multiple projects (max depth: 5)
mk bump infrastructure --recursive
# Include pre-release versions (alpha, beta, rc)
mk bump infrastructure --include-prereleases --recursive
# Show verbose output during scanning
mk bump infrastructure --verbose --recursiveFeatures:
- Interactive selection of dependencies to update
- Support for Terraform registry modules and Helm chart repositories
- Caching of version lookups to avoid redundant API calls when scanning recursively
- Respects
.gitignorepatterns when scanning recursively - Configurable maximum scan depth via
~/.config/mk/config.toml
Configuration:
Create or update ~/.config/mk/config.toml:
[bump]
# Maximum directory depth for recursive scanning (default: 5)
max_depth = 5Example output:
$ mk bump infrastructure/pubsub --recursive
INFO: Scanning recursively (max depth: 5): infrastructure/pubsub
INFO: Found 3 Terraform project(s), 0 Helm project(s)
INFO: Found 2 dependencies with updates available
Select dependencies to update (Space to select, Enter to confirm):
> [x] terraform-google-modules/pubsub/google (pubsub.tf:3) 8.2.0 → 8.3.2
[ ] terraform-google-modules/iam/google//modules/pubsub_topics_iam (pubsub.tf:15) 8.0.0 → 8.1.0
INFO: Updating selected dependencies...
✓ Updated terraform-google-modules/pubsub/google in pubsub.tf
SUCCESS: 1 dependencies updated across 3 project(s)Scan infrastructure for configuration drift across multiple projects and environments:
# Scan a directory for drift (Terraform & Helm)
mk drift infrastructure
# Filter by technology
mk drift infrastructure --tech terraform
# Filter by environment(s)
mk drift infrastructure --env prod --env staging
# Capture detailed output to logs
mk drift infrastructure --capture --verbose
# Scan with custom depth and ignore .gitignore
mk drift infrastructure --max-depth 10 --no-ignoreExit codes:
0: No drift detected2: Drift detected1: Errors occurred
-v, --verbose Enable verbose output
-h, --help Show help information
-V, --version Show version informationThe tool automatically detects the technology based on project structure:
- Terraform: Directory named
terraformor containstfvars/directory - Helm: Contains
values.yamlfile - Kustomize: Contains
overlays/directory - Ansible: Directory named
ansibleor containsinventories/directory
Environments are detected from:
- Terraform: Files in
tfvars/directory (e.g.,tfvars/dev.tfvars→dev) - Helm: Directories in
values/(e.g.,values/dev/→dev) - Kustomize: Directories in
overlays/(e.g.,overlays/dev/→dev) - Ansible: Files in
inventories/(e.g.,inventories/dev.yml→dev)
# Plan infrastructure changes
mk plan infrastructure/iam/terraform demo-env
# Apply changes
mk apply infrastructure/iam/terraform demo-env
# Get output value
mk output infrastructure/iam/terraform demo-env vpc_id
# Duplicate environment
mk duplicate infrastructure/iam/terraform demo-env staging-env
# Unlock state
mk unlock infrastructure/iam/terraform demo-env 196787809097# Update dependencies
mk deps manifests/monitoring/prometheus demo-env
# Show diff
mk diff manifests/monitoring/prometheus demo-env
# Install/upgrade
mk apply manifests/monitoring/prometheus demo-env
# Uninstall
mk uninstall manifests/monitoring/prometheus demo-env
# Render templates
mk template manifests/monitoring/prometheus demo-env# Build manifests
mk template manifests/monitoring/stackdriver-exporter demo-env
# Show diff
mk diff manifests/monitoring/stackdriver-exporter demo-env
# Apply
mk apply manifests/monitoring/stackdriver-exporter demo-env
# Delete
mk delete manifests/monitoring/stackdriver-exporter demo-env# Install dependencies
mk deps infrastructure/sftp/instance/ansible demo-env
# Check playbook (dry-run)
mk check infrastructure/sftp/instance/ansible demo-env
# Run playbook
mk apply infrastructure/sftp/instance/ansible demo-env
# List inventory
mk list infrastructure/sftp/instance/ansible demo-envTerraform init is automatically run before
apply,plan,destroy, andoutputcommands.
| Action | Command |
|---|---|
apply |
terraform apply -var-file=tfvars/{env}.tfvars |
plan/check |
terraform plan -var-file=tfvars/{env}.tfvars |
destroy |
terraform destroy -var-file=tfvars/{env}.tfvars |
output |
terraform output {key} |
Helm dependencies are automatically updated before
apply,diff, andtemplateif needed (based onChart.lock&charts/*.tgz).
| Action | Command |
|---|---|
apply |
helmfile sync -e {env} --skip-deps |
diff |
helmfile diff -e {env} --skip-deps |
deps |
helmfile deps -e {env} |
template |
helmfile template -e {env} --skip-deps |
uninstall |
helmfile destroy -e {env} --skip-deps |
| Action | Command |
|---|---|
apply |
kustomize build overlays/{env} | kubectl apply -f - |
diff |
kustomize build overlays/{env} | kubectl diff -f - |
template |
kustomize build overlays/{env} |
delete |
kustomize build overlays/{env} | kubectl delete -f - |
| Action | Command |
|---|---|
apply |
ansible-playbook -i inventories/{env}.yml playbook.yml -D |
check/diff |
ansible-playbook -i inventories/{env}.yml playbook.yml -DC |
deps |
ansible-galaxy install -r roles/requirements.yml -f |
list |
ansible-inventory -i inventories/{env}.yml --list | jq . |
Initialize a configuration file with examples:
mk initThis creates ~/.config/mk/config.toml with the following options:
Set the priority order when multiple technologies are detected:
# Prioritize Terraform over other technologies
technology_priority = ["terraform", "kustomize", "helm", "ansible"]Configure the dependency bump command:
[bump]
# Maximum directory depth for recursive scanning (default: 5)
max_depth = 5Automatically validates that you're using the correct kubectl context before applying or diffing changes:
[context]
# Disable context validation checks (default: false)
disable_context_check = false
# Context mappings: repository -> environment -> kubectl context
# Example:
[context.mappings."github.com/user/infra"]
prod = "gke_project_cluster-prod"
staging = "gke_project_cluster-staging"How it works:
-
When you run
mk applyormk difffor Helm/Kustomize:- The tool checks if a context mapping exists for your git repository and environment
- If a mapping exists, it verifies your current kubectl context matches the expected one
- If no mapping exists, it prompts you to save the current context for future use
-
Example workflow:
# First time running for a new environment
$ mk apply ./my-helm-chart prod
WARNING: No Kubernetes context configured for:
Repository: github.com/user/infra
Environment: prod
Current kubectl context: gke_project_cluster-prod
Continue and save this context for future use? [Y/n]: y
SUCCESS: Context mapping saved to ~/.config/mk/config.toml
# Future runs validate automatically
$ mk apply ./my-helm-chart prod
✓ Context validated: gke_project_cluster-prod
# If you accidentally use wrong context
$ kubectl config use-context gke_project_cluster-staging
$ mk apply ./my-helm-chart prod
ERROR: Kubernetes context mismatch!
Repository: github.com/user/infra
Environment: prod
Expected context: gke_project_cluster-prod
Current context: gke_project_cluster-staging
Please switch to the correct context with:
kubectl config use-context gke_project_cluster-prod- Team sharing:
You can also create a .mk/contexts.toml file in your git repository to share context mappings with your team:
[mappings."github.com/user/infra"]
prod = "gke_project_cluster-prod"
staging = "gke_project_cluster-staging"
dev = "gke_project_cluster-dev"The tool prioritizes repo-level configs over user-level configs, allowing teams to establish consistent context mappings.
cargo build --release --locked
# or continuously with
watchexec -r -e rs --bell -- 'cargo build --release --locked'cargo testcargo clippyMIT License. See LICENSE for details.