ci/hooks/README.md
This directory contains pre-command hooks that prevent Claude AI agents from running dangerous or forbidden build commands that could bypass FastLED's build system safety checks.
Purpose: Blocks direct invocation of build system commands that should go through FastLED's bash wrapper scripts.
Location: ci/hooks/check_forbidden_commands.py
Hook Type: PreToolUse (runs before any Bash command)
Configuration: .claude/settings.json
The hook blocks these commands to prevent bypassing the build system. Use the recommended alternatives instead:
| Forbidden Command | Category | Recommended Alternative | Notes |
|---|---|---|---|
ninja | Build Tool | bash test | FastLED build system handles ninja invocation |
meson | Build Tool | bash test | FastLED build system handles meson configuration |
clang | Compiler | bash test | Build system uses clang-tool-chain internally |
clang++ | Compiler | bash test | Build system uses clang-tool-chain internally |
gcc | Compiler | ❌ Not supported | FastLED requires Clang 21.1.5 - GCC is not supported |
g++ | Compiler | ❌ Not supported | FastLED requires Clang 21.1.5 - GCC is not supported |
gdb | Debugger | clang-tool-chain-lldb | Use FastLED's LLDB wrapper for debugging |
lldb | Debugger | clang-tool-chain-lldb | Use FastLED's LLDB wrapper for debugging |
pio | PlatformIO | bash compile, bash debug, bash validate | Use FastLED's platform compilation wrappers |
platformio | PlatformIO | bash compile, bash debug, bash validate | Use FastLED's platform compilation wrappers |
Key Points:
bash test - the build system manages these internallybash test - the build system uses clang-tool-chain wrappersclang-tool-chain-lldb for consistent debugging experiencebash compile (build), bash debug (interactive debugging), or bash validate (hardware testing)The hook also blocks dangerous patterns:
rm -rf .build - Use bash test --clean insteadrm -rf .fbuild - Use bash compile --clean insteadRationale: Build system is self-healing and has special cache invalidation code. Manual deletion can corrupt build state.
--no-fingerprint - Use bash test --clean insteadRationale: Makes builds 10-100x slower. Fingerprint cache is reliable and tracks changes correctly.
meson anywhere in command - Use bash test insteadninja anywhere in command - Use bash test insteadRationale: Catches build commands in the middle of command chains (e.g., cd .build/meson-quick && meson test). Uses literal space matching to detect commands with spaces around them.
ZCCACHE_DISABLE=1 - Never disable zccacheRationale: zccache provides critical compilation performance optimization.
To bypass the hook for legitimate reasons, set the environment variable FL_AGENT_ALLOW_ALL_CMDS=1:
Option 1: Set in command (recommended for one-off commands):
FL_AGENT_ALLOW_ALL_CMDS=1 ninja --version
FL_AGENT_ALLOW_ALL_CMDS=1 rm -rf .build/meson-quick
FL_AGENT_ALLOW_ALL_CMDS=1 clang++ test.cpp -o test.exe
Option 2: Set in shell environment (for multiple commands):
export FL_AGENT_ALLOW_ALL_CMDS=1
ninja --version
clang++ test.cpp -o test.exe
How it works:
FL_AGENT_ALLOW_ALL_CMDS=1 is set in the command stringWarning: Only use the override when you have a specific, documented reason to run these commands directly.
The hook has been tested with:
✅ All forbidden commands (ninja, meson, clang, clang++, gcc, g++, gdb, lldb, pio, platformio) ✅ All forbidden patterns (cache deletion, --no-fingerprint, ZCCACHE_DISABLE) ✅ Environment variable override works ✅ Normal commands pass through
When blocked, you'll see clear error messages:
ninja is forbidden. If you really want to run this manually, set environment variable "FL_AGENT_ALLOW_ALL_CMDS"
rm -rf .build is forbidden - use 'bash test --clean' instead
--no-fingerprint is forbidden - makes builds 10-100x slower, use 'bash test --clean' instead
Setting ZCCACHE_DISABLE is forbidden. If you really want to set this, use environment variable "FL_AGENT_ALLOW_ALL_CMDS"
Hook Flow:
FL_AGENT_ALLOW_ALL_CMDS overrideKey Functions:
is_forbidden_command() - Checks command starts with forbidden binarycheck_forbidden_pattern() - Checks command matches forbidden regexcheck_forbidden_env_vars() - Checks command sets forbidden env varsTo add more forbidden commands, edit ci/hooks/check_forbidden_commands.py:
FORBIDDEN_COMMANDS = [
# Add new command here
"new_forbidden_cmd",
]
FORBIDDEN_PATTERNS = [
# Add new pattern here
(r"pattern_regex", "Error message to show"),
]
FORBIDDEN_ENV_VARS = [
# Add new env var here
"NEW_FORBIDDEN_VAR",
]
To see hook execution in detail:
--debug flagCtrl+O during session.claude/settings.json for hook configurationdocs/agents/build-system.md - Build system standardsCLAUDE.md - Core agent rulesdocs/agents/testing-commands.md - Testing commands