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
# Zshsource<(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 technologiestechnology_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.