Plugins examples

Exec plugin reference implementation

File validator

A working exec plugin in Bash that validates file operations. Blocks binary files, warns on executable scripts, and enforces a configurable size limit.

Requires bash and jq. Install jq with your package manager (brew install jq, apt-get install jq).

Install

chmod +x file_validator.sh
mkdir -p ~/.klaudiush/plugins
cp file_validator.sh ~/.klaudiush/plugins/

Configure

Add to ~/.klaudiush/config.toml:

[[plugins.plugins]]
name = "file-validator"
type = "exec"
enabled = true
path = "~/.klaudiush/plugins/file_validator.sh"
timeout = "5s"

[plugins.plugins.predicate]
event_types = ["PreToolUse"]
tool_types = ["Write", "Edit"]

[plugins.plugins.config]
warn_on_exe = "true"
block_on_bin = "true"
max_file_size = "1048576"  # 1MB

Test

Run --info to check the plugin loads:

./file_validator.sh --info

Test a binary file (should block):

echo '{"tool_name":"Write","file_path":"malware.exe","content":"binary"}' | ./file_validator.sh

Test an executable script (should warn):

echo '{"tool_name":"Write","file_path":"script.sh","content":"#!/bin/bash\necho hello"}' | ./file_validator.sh

Test a normal file (should pass):

echo '{"tool_name":"Write","file_path":"README.md","content":"# Docs"}' | ./file_validator.sh

Protocol

Plugins receive a JSON request on stdin and return a JSON response on stdout.

Request fields: event_type, tool_name, file_path, content, config.

Pass response:

{"passed": true, "should_block": false}

Fail response:

{
  "passed": false,
  "should_block": true,
  "message": "Error description",
  "error_code": "CODE",
  "fix_hint": "How to fix it"
}

See the plugins guide for the full protocol spec and other plugin types.

File validator

Blocks binary files, warns on executable scripts, enforces size limits.

exec-shell/file_validator.sh 111 lines
#!/usr/bin/env bash

# File validator
# Blocks binary files, warns on executable scripts, enforces size limits.

set -euo pipefail

# Handle --info flag
if [[ "${1:-}" == "--info" ]]; then
  cat <<EOF
{
  "name": "file-validator",
  "version": "1.0.0",
  "description": "Validates file operations (blocks binaries, warns on executables)",
  "author": "klaudiush"
}
EOF
  exit 0
fi

# Read request from stdin
read -r request

# Parse JSON fields using jq
tool_name=$(echo "$request" | jq -r '.tool_name // empty')
file_path=$(echo "$request" | jq -r '.file_path // empty')
content=$(echo "$request" | jq -r '.content // empty')

# Read configuration
warn_on_exe=$(echo "$request" | jq -r '.config.warn_on_exe // "true"')
block_on_bin=$(echo "$request" | jq -r '.config.block_on_bin // "true"')
max_file_size=$(echo "$request" | jq -r '.config.max_file_size // "1048576"')

# Only validate file operations
if [[ "$tool_name" != "Write" && "$tool_name" != "Edit" ]]; then
  echo '{"passed":true,"should_block":false}'
  exit 0
fi

# Check if file path is empty
if [[ -z "$file_path" ]]; then
  echo '{"passed":true,"should_block":false}'
  exit 0
fi

# Check for binary files (block if configured)
if [[ "$block_on_bin" == "true" ]]; then
  case "$file_path" in
    *.exe|*.dll|*.so|*.dylib|*.bin)
      cat <<EOF
{
  "passed": false,
  "should_block": true,
  "message": "Binary files are not allowed: $file_path",
  "error_code": "BIN_FILE",
  "fix_hint": "Use source code or text files instead",
  "doc_link": "https://klaudiu.sh/docs/plugins"
}
EOF
      exit 0
      ;;
  esac
fi

# Warn on executable scripts (unless disabled)
if [[ "$warn_on_exe" == "true" ]]; then
  case "$file_path" in
    *.sh|*.bash|*.py|*.rb|*.pl)
      # Check if content starts with shebang
      if echo "$content" | head -n1 | grep -q "^#!"; then
        cat <<EOF
{
  "passed": false,
  "should_block": false,
  "message": "Executable script detected: $file_path",
  "error_code": "EXEC_SCRIPT",
  "fix_hint": "Ensure script has proper validation and error handling",
  "details": {
    "shebang": "$(echo "$content" | head -n1)"
  }
}
EOF
        exit 0
      fi
      ;;
  esac
fi

# Check content size if available
if [[ -n "$content" ]]; then
  content_size=$(echo -n "$content" | wc -c | tr -d ' ')
  if [[ "$content_size" -gt "$max_file_size" ]]; then
    cat <<EOF
{
  "passed": false,
  "should_block": true,
  "message": "File content exceeds maximum size: $content_size bytes > $max_file_size bytes",
  "error_code": "FILE_TOO_LARGE",
  "fix_hint": "Reduce file size or increase max_file_size in config",
  "details": {
    "size": "$content_size",
    "max_size": "$max_file_size"
  }
}
EOF
    exit 0
  fi
fi

# Pass validation
echo '{"passed":true,"should_block":false}'

© 2026 Smykla Skalski Labs