holup is a small CLI tool that helps stop mistakes when running risky commands, especially in production.
It runs before your command.
If the command looks dangerous, it pauses and asks you to confirm.
- Watches commands like
kubectlandkafkactl - You define which commands are risky using patterns
- Shows a warning before running the command
You must tell holup which commands are dangerous.
This is done using a config file with patterns.
~/.holup/config.yaml
# regex named groups that can be used in the confirmation message
global_vars_named_groups:
- '((-n|--namespace)(=|\s+)(?P<NAMESPACE>[^\s]+))'
- '((-c|--context)(=|\s+)(?P<CONTEXT>[^\s]+))'
rules:
- pattern: 'kubectl\s+(delete|replace|edit|drain|patch|label|annotate|rollout\s+(restart|undo)|scale)'
message: >
[DANGER] Run "{{.INPUT_CMD}}" on cluster "{{default (exec "kubectl config current-context") .CONTEXT}}"
in namespace "{{default (exec "kubectl config view --minify --output 'jsonpath={..namespace}'") .NAMESPACE}}"
?- The pattern matches risky
kubectlcommands like:- delete
- scale
- rollout restart
- It reads:
- namespace from
-nor--namespace - cluster from
--contextor current kube config
- namespace from
- If the pattern matches, holup stops and shows a warning
k delete pod -n test abc --context prod-clusterYou must press y to continue.
If you press n, the command is stopped.
Sometimes you need to bypass checks (e.g., in automation scripts). You can control holup using the following environment variables:
Set HOLUP_CONFIG to specify a custom config file location. Defaults to ~/.holup/config.yaml.
export HOLUP_CONFIG=/path/to/config.yamlSet HOLUP_SKIP_USER_INPUT to true or 1. Holup will allow the command to proceed without asking for confirmation.
export HOLUP_SKIP_USER_INPUT=trueSet HOLUP_SKIP_USER_INPUT_UNTIL to a Unix Epoch Timestamp. Holup will skip confirmation checks until that time is reached.
To make this easier, you can add a helper function to your shell to skip checks for a specific number of seconds:
# Add to ~/.zshrc or ~/.bashrc
holup_skip() {
# Sets the variable to current time + N seconds
export HOLUP_SKIP_USER_INPUT_UNTIL=$(($(date +%s) + $1))
echo "holup: Skipping checks for the next $1 seconds"
}Usage:
# Skip checks for 5 minutes (300 seconds)
holup_skip 300- holup checks your command
- It compares the command with your defined patterns
- If a pattern matches:
- Shows a warning message
- Waits for confirmation
go build -o holup .
chmod +x holup
sudo mv holup /usr/local/bin/holupCreate the config directory and file:
mkdir -p ~/.holupCreate ~/.holup/config.yaml with the following content:
global_vars_named_groups:
- '((-n|--namespace)(=|\s+)(?P<NAMESPACE>[^\s]+))'
- '((--context)(=|\s+)(?P<CONTEXT>[^\s]+))'
rules:
- pattern: 'kubectl\s+(delete|create|apply|replace|edit|drain|patch|label|annotate|rollout\s+(restart|undo)|scale)'
message: >
{{color "hired" "[WARNING]"}} Run "{{color "hiyellow" .INPUT_CMD}}" on cluster {{color "hicyan" (default (exec "kubectl config current-context") .CONTEXT)}}
in namespace {{color "higreen" (default (exec "kubectl config view --minify --output 'jsonpath={..namespace}'") .NAMESPACE)}}?
- pattern: 'kafkactl\s+(delete|attach|create|reset|produce|alter)'
message: >
{{color "hired" "[WARNING]"}} Run "{{color "hiyellow" .INPUT_CMD}}" on cluster {{color "hicyan" (default (exec "kafkactl config current-context") .CONTEXT)}}?This config will:
- Catch risky
kubectlcommands (delete, apply, scale, etc.) - Catch risky
kafkactlcommands (delete, create, alter, etc.) - Show colorized warnings with cluster and namespace info
- Extract namespace and context from command flags
This makes sure kubectl and kafkactl go through holup.
cat <<EOF | tee ~/holup.sh
alias kubectl="holup kubectl"
alias k="holup kubectl"
alias kafkactl="holup kafkactl"
# Helper to snooze holup for N seconds
holup_skip() {
export HOLUP_SKIP_USER_INPUT_UNTIL=\$((\$(date +%s) + \$1))
echo "holup: Skipping checks for the next \$1 seconds"
}
EOFAdd it to your shell config:
echo "source ~/holup.sh" >> ~/.zshrc
# or
echo "source ~/holup.sh" >> ~/.bashrcReload your shell:
source ~/.zshrcThat’s it.
Now risky commands will stop and ask before doing damage.
