Claude
Skills
Sign in
Back

hook.simulate

Included with Lifetime
$97 forever

# hook.simulate

General

What this skill does

# hook.simulate

**Version:** 0.1.0
**Status:** Active
**Tags:** hook, simulation, testing, validation, development

## Overview

The `hook.simulate` skill allows developers to test a hook manifest before registering it in the Betty Framework. It validates the manifest structure, simulates hook triggers based on event types, and optionally executes the hook commands in a controlled environment.

This skill is essential for:
- **Testing hooks before deployment** - Catch errors early in development
- **Understanding hook behavior** - See which files match patterns and how commands execute
- **Debugging hook issues** - Validate patterns, commands, and execution flow
- **Safe experimentation** - Test hooks without affecting the live system

## Features

- ✅ **Manifest Validation** - Validates all required and optional fields
- ✅ **Pattern Matching** - Shows which files match the hook's pattern
- ✅ **Event Simulation** - Simulates different hook events (on_file_edit, on_commit, etc.)
- ✅ **Command Execution** - Runs hook commands with dry-run or actual execution
- ✅ **Timeout Testing** - Validates timeout behavior
- ✅ **Blocking Simulation** - Shows how blocking hooks would behave
- ✅ **JSON Output** - Structured results for automation and analysis

## Usage

### Command Line

```bash
# Basic validation and simulation
python skills/hook.simulate/hook_simulate.py examples/test-hook.yaml

# Simulate with dry-run command execution
python skills/hook.simulate/hook_simulate.py examples/test-hook.yaml --execute --dry-run

# Actually execute the command
python skills/hook.simulate/hook_simulate.py examples/test-hook.yaml --execute --no-dry-run

# Get JSON output for scripting
python skills/hook.simulate/hook_simulate.py examples/test-hook.yaml --output json
```

### As a Skill

```python
from skills.hook.simulate.hook_simulate import simulate_hook

# Simulate a hook
results = simulate_hook(
    manifest_path="examples/test-hook.yaml",
    dry_run=True,
    execute=True
)

# Check validation
if results["valid"]:
    print("✅ Hook is valid")
else:
    print("❌ Validation errors:", results["validation_errors"])

# Check if hook would trigger
if results["trigger_simulation"]["would_trigger"]:
    print("Hook would trigger!")
    print("Matching files:", results["trigger_simulation"]["matching_files"])
```

## Input Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `manifest_path` | string | Yes | - | Path to the hook.yaml manifest file |
| `execute` | boolean | No | false | Whether to execute the hook command |
| `dry_run` | boolean | No | true | If true, simulate without actually running commands |

## Output Schema

```json
{
  "manifest_path": "path/to/hook.yaml",
  "timestamp": "2025-10-23 12:34:56",
  "valid": true,
  "validation_errors": [],
  "manifest": {
    "name": "hook-name",
    "version": "0.1.0",
    "description": "Hook description",
    "event": "on_file_edit",
    "command": "python script.py {file_path}",
    "when": {
      "pattern": "*.yaml"
    },
    "blocking": true,
    "timeout": 30000
  },
  "trigger_simulation": {
    "would_trigger": true,
    "reason": "Found 5 file(s) matching pattern: *.yaml",
    "matching_files": ["file1.yaml", "file2.yaml"],
    "pattern": "*.yaml"
  },
  "command_executions": [
    {
      "command": "python script.py file1.yaml",
      "executed": true,
      "dry_run": false,
      "stdout": "Validation passed",
      "stderr": "",
      "return_code": 0,
      "execution_time_ms": 123.45,
      "success": true,
      "file": "file1.yaml"
    }
  ],
  "blocking": true,
  "timeout_ms": 30000
}
```

## Examples

### Example 1: Validate OpenAPI Hook

Create a hook manifest `openapi-validator.yaml`:

```yaml
name: validate-openapi
version: 0.1.0
description: "Validate OpenAPI specifications on edit"

event: on_file_edit

command: "python betty/skills/api.validate/api_validate.py {file_path} zalando"

when:
  pattern: "**/*.openapi.yaml"

blocking: true
timeout: 30000
on_failure: show_errors

status: draft
tags: [api, validation, openapi]
```

Simulate it:

```bash
python skills/hook.simulate/hook_simulate.py openapi-validator.yaml
```

Output:
```
=== Hook Simulation Results ===
Manifest: openapi-validator.yaml
Timestamp: 2025-10-23 12:34:56

✅ VALIDATION PASSED

Hook: validate-openapi v0.1.0
Event: on_file_edit
Command: python betty/skills/api.validate/api_validate.py {file_path} zalando
Blocking: True
Timeout: 30000ms

✅ WOULD TRIGGER
Reason: Found 3 file(s) matching pattern: **/*.openapi.yaml

Matching files (3):
  - specs/petstore.openapi.yaml
  - specs/users.openapi.yaml
  - api/products.openapi.yaml
```

### Example 2: Test Commit Hook

Create `pre-commit.yaml`:

```yaml
name: pre-commit-linter
version: 1.0.0
description: "Run linter before commits"

event: on_commit

command: "pylint src/"

blocking: true
timeout: 60000

status: active
tags: [lint, quality]
```

Simulate with execution:

```bash
python skills/hook.simulate/hook_simulate.py pre-commit.yaml --execute --dry-run
```

Output:
```
=== Hook Simulation Results ===
Manifest: pre-commit.yaml
Timestamp: 2025-10-23 12:35:00

✅ VALIDATION PASSED

Hook: pre-commit-linter v1.0.0
Event: on_commit
Command: pylint src/
Blocking: True
Timeout: 60000ms

✅ WOULD TRIGGER
Reason: on_commit hook would trigger with 5 changed file(s)

Changed files (5):
  - src/main.py
  - src/utils.py
  - tests/test_main.py
  - README.md
  - setup.py

=== Command Execution Results (1) ===

[1] N/A
Command: pylint src/
Mode: DRY RUN (not executed)
```

### Example 3: Test with Actual Execution

```bash
python skills/hook.simulate/hook_simulate.py openapi-validator.yaml --execute --no-dry-run
```

Output:
```
=== Hook Simulation Results ===
...

=== Command Execution Results (3) ===

[1] specs/petstore.openapi.yaml
Command: python betty/skills/api.validate/api_validate.py specs/petstore.openapi.yaml zalando
Executed: Yes
Return code: 0
Execution time: 234.56ms
Status: ✅ SUCCESS

Stdout:
✅ OpenAPI spec is valid

[2] specs/users.openapi.yaml
Command: python betty/skills/api.validate/api_validate.py specs/users.openapi.yaml zalando
Executed: Yes
Return code: 1
Execution time: 189.23ms
Status: ❌ FAILED

Stderr:
Error: Missing required field 'info.contact'

[3] api/products.openapi.yaml
Command: python betty/skills/api.validate/api_validate.py api/products.openapi.yaml zalando
Executed: Yes
Return code: 0
Execution time: 201.45ms
Status: ✅ SUCCESS
```

### Example 4: JSON Output for Automation

```bash
python skills/hook.simulate/hook_simulate.py my-hook.yaml --output json > results.json
```

Then process with scripts:

```python
import json

with open("results.json") as f:
    results = json.load(f)

if not results["valid"]:
    print("Validation failed:")
    for error in results["validation_errors"]:
        print(f"  - {error}")
    exit(1)

if results["trigger_simulation"]["would_trigger"]:
    files = results["trigger_simulation"]["matching_files"]
    print(f"Hook would run on {len(files)} files")

for execution in results["command_executions"]:
    if not execution["success"]:
        print(f"Failed on {execution['file']}")
        print(f"Error: {execution['stderr']}")
```

## Event Type Support

| Event | Simulation Support | Description |
|-------|-------------------|-------------|
| `on_file_edit` | ✅ Full | Matches files by pattern, simulates editing |
| `on_file_save` | ✅ Full | Similar to on_file_edit |
| `on_commit` | ✅ Full | Checks git status, shows changed files |
| `on_push` | ⚠️ Partial | Notes hook would trigger, no git simulation |
| `on_tool_use` | ⚠️ Partial | Notes hook would trigger, no tool simulation |
| `on_agent_start` | ⚠️ Partial | Notes hook would trigger, no agent simulation |
| `on_workflow_end` | ⚠️ Partial | Notes hook would trigger, no workflow simulation |

## Validation Rules

The skill validates all Betty Framework hook requirements:

1. **Required Fields**: name, version
Files: 4
Size: 34.7 KB
Complexity: 35/100
Category: General

Related in General