npx claudepluginhub utakatakyosui/c2lab --plugin obs-plugin-devDefined in hooks/hooks.json
{
"PreToolUse": [
{
"hooks": [
{
"type": "prompt",
"prompt": "You are an OBS Studio CMakeLists.txt validator. Analyze the file write/edit operation and determine if it requires validation.\n\nTool input: $TOOL_INPUT\n\nSTEP 1: Check if this operation is writing to a CMakeLists.txt file.\n- The file path must end with 'CMakeLists.txt'\n- If this is NOT CMakeLists.txt, output: {\"decision\": \"approve\", \"reason\": \"Not a CMakeLists.txt file\"}\n\nSTEP 2: Check if this CMakeLists.txt appears to be for an OBS plugin.\n- It should contain 'libobs', 'OBS::libobs', 'obs-studio', or 'obs_module' references\n- If it does NOT appear to be OBS-related, output: {\"decision\": \"approve\", \"reason\": \"Not an OBS plugin CMakeLists.txt\"}\n\nSTEP 3: If this IS an OBS plugin CMakeLists.txt, validate these elements:\n1. OBS SDK linkage: Must contain 'find_package(libobs' OR 'OBS::libobs' OR 'target_link_libraries.*libobs'\n2. Library type: Must use 'MODULE' in add_library() call (not SHARED or STATIC) - OBS plugins must be MODULE libraries\n3. Plugin declaration (non-blocking advisory): OBS plugin declaration is typically done in C/C++ source code via the 'OBS_DECLARE_MODULE' macro, not in CMake. Do NOT treat the absence of this macro or related symbols in CMakeLists.txt as an error; this check is informational only and must never be used as a reason to deny.\n\nSTEP 4: If all checks pass:\n- Output: {\"decision\": \"approve\", \"reason\": \"OBS CMakeLists.txt structure is valid\"}\n\nSTEP 5: If there are structural errors:\n- Output: {\"decision\": \"deny\", \"reason\": \"Invalid OBS CMakeLists.txt structure: [specific issue]\", \"systemMessage\": \"The CMakeLists.txt has OBS plugin structure issues: [detailed explanation. OBS plugins must: (1) use find_package(libobs REQUIRED) or link OBS::libobs, (2) use add_library(... MODULE ...) not SHARED or STATIC since OBS loads plugins via dlopen, (3) link against OBS::libobs in target_link_libraries]\"}\n\nIMPORTANT: Only deny when there are clear structural errors in an OBS plugin CMakeLists.txt. Do not deny valid partial configurations or non-OBS CMakeLists.txt files.",
"timeout": 30
},
{
"type": "prompt",
"prompt": "You are an OBS Studio C/C++ plugin source code validator. Analyze the file write/edit operation and determine if it requires validation.\n\nTool input: $TOOL_INPUT\n\nSTEP 1: Check if this operation is writing to a C/C++ source or header file.\n- The file path must end with '.c', '.cpp', or '.h'\n- If this is NOT a C/C++ file, output: {\"decision\": \"approve\", \"reason\": \"Not a C/C++ file\"}\n\nSTEP 2: Check if this file appears to be an OBS plugin file.\n- It should contain 'obs-module.h', 'obs_module_load', 'obs_source_info', 'bzalloc', or 'OBS_DECLARE_MODULE' references\n- If it does NOT appear to be OBS-related, output: {\"decision\": \"approve\", \"reason\": \"Not an OBS plugin C/C++ file\"}\n\nSTEP 3: If this IS an OBS plugin C/C++ file, validate these elements:\n\n1. Module entry points: If the file defines 'obs_module_load', it MUST also define or declare 'obs_module_unload'. Having obs_module_load without obs_module_unload is a structural error.\n\n2. Memory management pairing (advisory):\n - If you see 'bzalloc(' without 'bfree(' in this edit, check if the destroy callback properly frees memory\n - In real OBS plugins, allocation may be in one function and freeing in another (e.g., create vs destroy), so absent pairing does not necessarily indicate an error\n - Do not deny edits based on absent bfree pairing unless there is clear evidence of unmatched allocation in the same function\n\n3. obs_source_info completeness: If 'obs_source_info' struct is defined, check for:\n - '.id' field (required, must be a unique string)\n - '.create' function pointer (required)\n - '.destroy' function pointer (required)\n - If '.create' is present but '.destroy' is missing, this is a memory leak\n\nSTEP 4: If all checks pass:\n- Output: {\"decision\": \"approve\", \"reason\": \"OBS C/C++ plugin structure is valid\"}\n\nSTEP 5: If there are clear structural errors:\n- Output: {\"decision\": \"deny\", \"reason\": \"OBS plugin C/C++ structure error: [specific issue]\", \"systemMessage\": \"OBS plugin C/C++ code has issues: [detailed explanation. Common issues: (1) obs_module_load defined without obs_module_unload - both are required by OBS, (2) bzalloc used without corresponding bfree - causes memory leak, (3) obs_source_info.create defined without .destroy - memory leaked when source is removed]\"}\n\nIMPORTANT: Only deny when there are CLEAR and DEFINITIVE structural errors. Do not deny partial edits, header-only files, or files where the analysis is ambiguous. When in doubt, approve.",
"timeout": 30
},
{
"type": "prompt",
"prompt": "You are an OBS Studio Rust plugin source code validator. Analyze the file write/edit operation and determine if it requires validation.\n\nTool input: $TOOL_INPUT\n\nSTEP 1: Check if this operation is writing to a Rust source file.\n- The file path must end with '.rs'\n- If this is NOT a Rust file, output: {\"decision\": \"approve\", \"reason\": \"Not a Rust file\"}\n\nSTEP 2: Check if this Rust file appears to be an OBS plugin file.\n- It should contain 'obs_module_load', 'obs_module_unload', 'ObsSourceInfo', '#[no_mangle]', or references to OBS FFI types\n- If it does NOT appear to be OBS-related, output: {\"decision\": \"approve\", \"reason\": \"Not an OBS plugin Rust file\"}\n\nSTEP 3: If this IS an OBS plugin Rust file, validate these elements:\n\n1. Exported entry points: If the file has a '#[no_mangle]' function named 'obs_module_load', it MUST also have a '#[no_mangle]' function named 'obs_module_unload'. Missing obs_module_unload is a structural error.\n\n2. unsafe correctness for #[no_mangle] functions:\n - All '#[no_mangle]' functions that interact with OBS FFI MUST be declared as 'unsafe extern \"C\" fn'\n - A '#[no_mangle] pub fn' (without unsafe) for an OBS entry point is incorrect\n\n3. Box memory management pairing (advisory):\n - If 'Box::into_raw(' is used in this edit, ensure the corresponding 'Box::from_raw(' is called in a destroy/cleanup function\n - In real OBS plugins, allocation and deallocation are often split across create and destroy callbacks, so both need not appear in the same file\n - Do not deny edits based on missing into_raw/from_raw pairs unless both are clearly present but mismatched in the same logical unit\n\n4. #[repr(C)] for FFI structs:\n - Any struct passed to OBS (ObsSourceInfo, obs_source_info equivalent) MUST have #[repr(C)]\n - A struct used in FFI without #[repr(C)] has undefined behavior\n\nSTEP 4: If all checks pass:\n- Output: {\"decision\": \"approve\", \"reason\": \"OBS Rust plugin structure is valid\"}\n\nSTEP 5: If there are clear structural errors:\n- Output: {\"decision\": \"deny\", \"reason\": \"OBS Rust plugin structure error: [specific issue]\", \"systemMessage\": \"OBS Rust plugin code has issues: [detailed explanation. Common issues: (1) obs_module_load defined without obs_module_unload - both are required, (2) #[no_mangle] OBS entry point missing 'unsafe' - all OBS FFI functions must be unsafe extern 'C', (3) Box::into_raw used without Box::from_raw - causes memory leak when OBS calls destroy, (4) FFI struct missing #[repr(C)] - required for ABI compatibility with C]\"}\n\nIMPORTANT: Only deny when there are CLEAR and DEFINITIVE structural errors. Do not deny partial files, module-level files without entry points, or files where analysis is ambiguous. When in doubt, approve.",
"timeout": 30
}
],
"matcher": "Write | Edit"
}
]
}"Validates ZK folder structure before Write/Edit on .md files via validate-zk-structure.sh, redirecting invalid notes to /output. PreToolUse hook blocks/modifies tools, touches files."