@smartsoft001/pro-claude-plugins 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +26 -0
- package/README.md +56 -0
- package/package.json +14 -0
- package/plugins/flow/.claude-plugin/README.md +91 -0
- package/plugins/flow/.claude-plugin/merge-permissions.js +115 -0
- package/plugins/flow/.claude-plugin/plugin.json +5 -0
- package/plugins/flow/.claude-plugin/settings.template.json +86 -0
- package/plugins/flow/agents/angular-component-scaffolder.md +176 -0
- package/plugins/flow/agents/angular-directive-builder.md +154 -0
- package/plugins/flow/agents/angular-guard-builder.md +244 -0
- package/plugins/flow/agents/angular-jest-test-writer.md +475 -0
- package/plugins/flow/agents/angular-pipe-builder.md +170 -0
- package/plugins/flow/agents/angular-resolver-builder.md +287 -0
- package/plugins/flow/agents/angular-service-builder.md +162 -0
- package/plugins/flow/agents/angular-signal-state-builder.md +340 -0
- package/plugins/flow/agents/angular-test-diagnostician.md +279 -0
- package/plugins/flow/agents/angular-testbed-configurator.md +315 -0
- package/plugins/flow/agents/arch-scaffolder.md +278 -0
- package/plugins/flow/agents/e2e-data-testid-injector.md +195 -0
- package/plugins/flow/agents/e2e-project-scaffolder.md +194 -0
- package/plugins/flow/agents/e2e-test-writer.md +357 -0
- package/plugins/flow/agents/shared-agent-evolver.md +294 -0
- package/plugins/flow/agents/shared-build-verifier.md +160 -0
- package/plugins/flow/agents/shared-config-updater.md +310 -0
- package/plugins/flow/agents/shared-coverage-enforcer.md +184 -0
- package/plugins/flow/agents/shared-error-handler.md +217 -0
- package/plugins/flow/agents/shared-file-creator.md +344 -0
- package/plugins/flow/agents/shared-impl-orchestrator.md +312 -0
- package/plugins/flow/agents/shared-impl-reporter.md +368 -0
- package/plugins/flow/agents/shared-impl-teammate.md +201 -0
- package/plugins/flow/agents/shared-linear-subtask-iterator.md +337 -0
- package/plugins/flow/agents/shared-logic-implementer.md +244 -0
- package/plugins/flow/agents/shared-maia-api.md +26 -0
- package/plugins/flow/agents/shared-parallelization-analyzer.md +343 -0
- package/plugins/flow/agents/shared-performance-validator.md +168 -0
- package/plugins/flow/agents/shared-plan-perspective.md +271 -0
- package/plugins/flow/agents/shared-project-standardizer.md +205 -0
- package/plugins/flow/agents/shared-report-synthesizer.md +188 -0
- package/plugins/flow/agents/shared-review-teammate.md +189 -0
- package/plugins/flow/agents/shared-security-scanner.md +186 -0
- package/plugins/flow/agents/shared-style-enforcer.md +230 -0
- package/plugins/flow/agents/shared-subtask-dependency-analyzer.md +189 -0
- package/plugins/flow/agents/shared-tdd-developer.md +350 -0
- package/plugins/flow/agents/shared-team-coordinator.md +192 -0
- package/plugins/flow/agents/shared-test-fixer.md +186 -0
- package/plugins/flow/agents/shared-test-runner.md +191 -0
- package/plugins/flow/agents/shared-ui-classifier.md +263 -0
- package/plugins/flow/agents/shared-verification-orchestrator.md +194 -0
- package/plugins/flow/agents/shared-verification-runner.md +140 -0
- package/plugins/flow/agents/ui-a11y-validator.md +305 -0
- package/plugins/flow/agents/ui-screenshot-reporter.md +329 -0
- package/plugins/flow/agents/ui-web-designer.md +214 -0
- package/plugins/flow/scripts/compute-session-tokens.sh +39 -0
- package/plugins/flow/skills/a11y-audit/SKILL.md +214 -0
- package/plugins/flow/skills/angular-patterns/SKILL.md +191 -0
- package/plugins/flow/skills/browser-capture/SKILL.md +238 -0
- package/plugins/flow/skills/commit/SKILL.md +259 -0
- package/plugins/flow/skills/debug-helper/SKILL.md +375 -0
- package/plugins/flow/skills/impl/SKILL.md +992 -0
- package/plugins/flow/skills/karpathy-guidelines/SKILL.md +72 -0
- package/plugins/flow/skills/linear-suggestion/SKILL.md +132 -0
- package/plugins/flow/skills/maia-files-delete/SKILL.md +59 -0
- package/plugins/flow/skills/maia-files-upload/SKILL.md +57 -0
- package/plugins/flow/skills/nx-conventions/SKILL.md +326 -0
- package/plugins/flow/skills/plan/SKILL.md +1033 -0
- package/plugins/flow/skills/push/SKILL.md +759 -0
- package/plugins/flow/skills/review/SKILL.md +443 -0
- package/plugins/flow/skills/test-e2e/SKILL.md +164 -0
- package/plugins/flow/skills/test-unit/SKILL.md +456 -0
- package/plugins/flow-external/.claude-plugin/README.md +146 -0
- package/plugins/flow-external/.claude-plugin/merge-permissions.js +94 -0
- package/plugins/flow-external/.claude-plugin/plugin.json +5 -0
- package/plugins/flow-external/.claude-plugin/settings.template.json +78 -0
- package/plugins/flow-external/agents/angular-component-scaffolder.md +271 -0
- package/plugins/flow-external/agents/angular-directive-builder.md +134 -0
- package/plugins/flow-external/agents/angular-guard-builder.md +73 -0
- package/plugins/flow-external/agents/angular-pipe-builder.md +90 -0
- package/plugins/flow-external/agents/angular-resolver-builder.md +79 -0
- package/plugins/flow-external/agents/angular-service-builder.md +168 -0
- package/plugins/flow-external/agents/angular-state-builder.md +263 -0
- package/plugins/flow-external/agents/shared-build-verifier.md +67 -0
- package/plugins/flow-external/agents/shared-impl-orchestrator.md +90 -0
- package/plugins/flow-external/agents/shared-impl-reporter.md +135 -0
- package/plugins/flow-external/agents/shared-linear-subtask-iterator.md +70 -0
- package/plugins/flow-external/agents/shared-ui-classifier.md +38 -0
- package/plugins/flow-external/agents/ui-web-designer.md +203 -0
- package/plugins/flow-external/scripts/compute-session-tokens.sh +39 -0
- package/plugins/flow-external/skills/a11y-audit/SKILL.md +97 -0
- package/plugins/flow-external/skills/angular-cli-conventions/SKILL.md +268 -0
- package/plugins/flow-external/skills/angular-patterns/SKILL.md +182 -0
- package/plugins/flow-external/skills/browser-capture/SKILL.md +74 -0
- package/plugins/flow-external/skills/commit/SKILL.md +114 -0
- package/plugins/flow-external/skills/debug-helper/SKILL.md +135 -0
- package/plugins/flow-external/skills/impl/SKILL.md +218 -0
- package/plugins/flow-external/skills/karpathy-guidelines/SKILL.md +72 -0
- package/plugins/flow-external/skills/linear-suggestion/SKILL.md +62 -0
- package/plugins/flow-external/skills/maia-files-delete/SKILL.md +34 -0
- package/plugins/flow-external/skills/maia-files-upload/SKILL.md +41 -0
- package/plugins/flow-external/skills/plan/SKILL.md +334 -0
- package/plugins/flow-external/skills/push/SKILL.md +232 -0
- package/plugins/flow-legacy/.claude-plugin/README.md +143 -0
- package/plugins/flow-legacy/.claude-plugin/merge-permissions.js +94 -0
- package/plugins/flow-legacy/.claude-plugin/plugin.json +5 -0
- package/plugins/flow-legacy/.claude-plugin/settings.template.json +79 -0
- package/plugins/flow-legacy/agents/angular-component-scaffolder.md +327 -0
- package/plugins/flow-legacy/agents/angular-directive-builder.md +253 -0
- package/plugins/flow-legacy/agents/angular-guard-builder.md +326 -0
- package/plugins/flow-legacy/agents/angular-pipe-builder.md +238 -0
- package/plugins/flow-legacy/agents/angular-resolver-builder.md +339 -0
- package/plugins/flow-legacy/agents/angular-service-builder.md +271 -0
- package/plugins/flow-legacy/agents/angular-state-builder.md +480 -0
- package/plugins/flow-legacy/agents/shared-impl-orchestrator.md +174 -0
- package/plugins/flow-legacy/agents/shared-impl-reporter.md +232 -0
- package/plugins/flow-legacy/agents/shared-linear-subtask-iterator.md +198 -0
- package/plugins/flow-legacy/agents/shared-tdd-developer.md +307 -0
- package/plugins/flow-legacy/agents/shared-test-runner.md +133 -0
- package/plugins/flow-legacy/agents/shared-ui-classifier.md +145 -0
- package/plugins/flow-legacy/scripts/compute-session-tokens.sh +39 -0
- package/plugins/flow-legacy/skills/a11y-audit/SKILL.md +214 -0
- package/plugins/flow-legacy/skills/angular-patterns/SKILL.md +346 -0
- package/plugins/flow-legacy/skills/browser-capture/SKILL.md +238 -0
- package/plugins/flow-legacy/skills/commit/SKILL.md +215 -0
- package/plugins/flow-legacy/skills/debug-helper/SKILL.md +395 -0
- package/plugins/flow-legacy/skills/impl/SKILL.md +710 -0
- package/plugins/flow-legacy/skills/karpathy-guidelines/SKILL.md +72 -0
- package/plugins/flow-legacy/skills/linear-suggestion/SKILL.md +132 -0
- package/plugins/flow-legacy/skills/maia-files-delete/SKILL.md +59 -0
- package/plugins/flow-legacy/skills/maia-files-upload/SKILL.md +57 -0
- package/plugins/flow-legacy/skills/nx-conventions/SKILL.md +368 -0
- package/plugins/flow-legacy/skills/plan/SKILL.md +742 -0
- package/plugins/flow-legacy/skills/push/SKILL.md +645 -0
- package/plugins/flow-legacy/skills/test-unit/SKILL.md +500 -0
- package/plugins/smart-pro/.claude-plugin/README.md +115 -0
- package/plugins/smart-pro/.claude-plugin/merge-permissions.js +129 -0
- package/plugins/smart-pro/.claude-plugin/plugin.json +5 -0
- package/plugins/smart-pro/.claude-plugin/settings.template.json +94 -0
- package/plugins/smart-pro/agents/angular-components/AGENT.md +214 -0
- package/plugins/smart-pro/hooks/CONFIG.md +198 -0
- package/plugins/smart-pro/hooks/README.md +139 -0
- package/plugins/smart-pro/hooks/audit_logger.py +107 -0
- package/plugins/smart-pro/hooks/auto_format.sh +11 -0
- package/plugins/smart-pro/hooks/hooks.json +79 -0
- package/plugins/smart-pro/hooks/safety_validator.py +129 -0
- package/plugins/smart-pro/hooks/sensitive_file_blocker.py +58 -0
- package/plugins/smart-pro/hooks/skill_validator.py +220 -0
- package/plugins/smart-pro/skills/angular-components-action-panel/SKILL.md +159 -0
- package/plugins/smart-pro/skills/angular-components-avatar/SKILL.md +142 -0
- package/plugins/smart-pro/skills/angular-components-badge/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-breadcrumbs/SKILL.md +91 -0
- package/plugins/smart-pro/skills/angular-components-button/SKILL.md +146 -0
- package/plugins/smart-pro/skills/angular-components-button-group/SKILL.md +121 -0
- package/plugins/smart-pro/skills/angular-components-calendar/SKILL.md +78 -0
- package/plugins/smart-pro/skills/angular-components-card/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-card-heading/SKILL.md +105 -0
- package/plugins/smart-pro/skills/angular-components-command-palette/SKILL.md +168 -0
- package/plugins/smart-pro/skills/angular-components-container/SKILL.md +93 -0
- package/plugins/smart-pro/skills/angular-components-description-list/SKILL.md +102 -0
- package/plugins/smart-pro/skills/angular-components-details/SKILL.md +70 -0
- package/plugins/smart-pro/skills/angular-components-divider/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-drawer/SKILL.md +136 -0
- package/plugins/smart-pro/skills/angular-components-dropdown/SKILL.md +131 -0
- package/plugins/smart-pro/skills/angular-components-empty-state/SKILL.md +103 -0
- package/plugins/smart-pro/skills/angular-components-feed/SKILL.md +110 -0
- package/plugins/smart-pro/skills/angular-components-form/SKILL.md +77 -0
- package/plugins/smart-pro/skills/angular-components-grid-list/SKILL.md +91 -0
- package/plugins/smart-pro/skills/angular-components-input/SKILL.md +118 -0
- package/plugins/smart-pro/skills/angular-components-list/SKILL.md +75 -0
- package/plugins/smart-pro/skills/angular-components-list-container/SKILL.md +106 -0
- package/plugins/smart-pro/skills/angular-components-media-object/SKILL.md +133 -0
- package/plugins/smart-pro/skills/angular-components-modal/SKILL.md +159 -0
- package/plugins/smart-pro/skills/angular-components-multi-column-layout/SKILL.md +84 -0
- package/plugins/smart-pro/skills/angular-components-navbar/SKILL.md +93 -0
- package/plugins/smart-pro/skills/angular-components-notification/SKILL.md +147 -0
- package/plugins/smart-pro/skills/angular-components-page/SKILL.md +162 -0
- package/plugins/smart-pro/skills/angular-components-page-heading/SKILL.md +96 -0
- package/plugins/smart-pro/skills/angular-components-paging/SKILL.md +86 -0
- package/plugins/smart-pro/skills/angular-components-progress-bars/SKILL.md +94 -0
- package/plugins/smart-pro/skills/angular-components-searchbar/SKILL.md +113 -0
- package/plugins/smart-pro/skills/angular-components-section-heading/SKILL.md +156 -0
- package/plugins/smart-pro/skills/angular-components-select-menu/SKILL.md +101 -0
- package/plugins/smart-pro/skills/angular-components-sidebar-layout/SKILL.md +121 -0
- package/plugins/smart-pro/skills/angular-components-sidebar-navigation/SKILL.md +80 -0
- package/plugins/smart-pro/skills/angular-components-sign-in-form/SKILL.md +91 -0
- package/plugins/smart-pro/skills/angular-components-stacked-layout/SKILL.md +114 -0
- package/plugins/smart-pro/skills/angular-components-stacked-list/SKILL.md +93 -0
- package/plugins/smart-pro/skills/angular-components-stats/SKILL.md +87 -0
- package/plugins/smart-pro/skills/angular-components-table/SKILL.md +98 -0
- package/plugins/smart-pro/skills/angular-components-tabs/SKILL.md +99 -0
- package/plugins/smart-pro/skills/angular-components-textarea/SKILL.md +111 -0
- package/plugins/smart-pro/skills/angular-components-toggle/SKILL.md +109 -0
- package/plugins/smart-pro/skills/angular-components-vertical-navigation/SKILL.md +139 -0
- package/plugins/smart-pro/skills/audit-log/SKILL.md +82 -0
- package/plugins/smart-pro/skills/format-code/SKILL.md +46 -0
- package/plugins/smart-pro/skills/project-conventions/SKILL.md +90 -0
- package/plugins/smart-pro/skills/safety-check/SKILL.md +0 -0
- package/src/index.d.ts +6 -0
- package/src/index.js +7 -0
- package/src/index.js.map +1 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Hooks Configuration Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to configure and customize the hooks system.
|
|
4
|
+
|
|
5
|
+
## Hook Configuration
|
|
6
|
+
|
|
7
|
+
All hooks are defined in `hooks.json` in this directory:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"hooks": {
|
|
12
|
+
"PreToolUse": [
|
|
13
|
+
{
|
|
14
|
+
"_description": "Safety gate: blocks destructive bash commands",
|
|
15
|
+
"matcher": "Bash|Write|Edit",
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "./safety_validator.py"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Hook commands use relative paths (e.g., `./safety_validator.py`) resolved from the `hooks/` directory.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Hook Customization
|
|
33
|
+
|
|
34
|
+
### safety_validator.py
|
|
35
|
+
|
|
36
|
+
**Add blocked patterns** by editing the script:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
DANGEROUS_PATTERNS = [
|
|
40
|
+
r"rm\s+-rf\s+/",
|
|
41
|
+
r"rm\s+-rf\s+~",
|
|
42
|
+
# Add your patterns here
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
SENSITIVE_FILES = [
|
|
46
|
+
".env",
|
|
47
|
+
"id_rsa",
|
|
48
|
+
# Add your patterns here
|
|
49
|
+
]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
### sensitive_file_blocker.py
|
|
55
|
+
|
|
56
|
+
**Add blocked file patterns** by editing:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
SENSITIVE_PATTERNS = [
|
|
60
|
+
r"\.env(?:\.|$)",
|
|
61
|
+
r"secrets",
|
|
62
|
+
r"credentials",
|
|
63
|
+
# Add your patterns here
|
|
64
|
+
]
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### audit_logger.py
|
|
70
|
+
|
|
71
|
+
**Change log location:**
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# Default: .claude/audit_logs/YYYYMMDD_audit.jsonl
|
|
75
|
+
LOG_DIR = Path(__file__).resolve().parent.parent / "audit_logs"
|
|
76
|
+
|
|
77
|
+
# Custom location:
|
|
78
|
+
LOG_DIR = Path("/var/log/claude-audit")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### auto_format.sh
|
|
84
|
+
|
|
85
|
+
**Change format command:**
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Default:
|
|
89
|
+
source ~/.nvm/nvm.sh && nvm use 24 && npm run format
|
|
90
|
+
|
|
91
|
+
# Custom (e.g., without nvm):
|
|
92
|
+
npm run format
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Environment Variables
|
|
98
|
+
|
|
99
|
+
| Variable | Purpose | Default |
|
|
100
|
+
| -------------------- | ---------------------- | ------------- |
|
|
101
|
+
| `CLAUDE_HOOK_EVENT` | Hook event type | Set by Claude |
|
|
102
|
+
| `CLAUDE_SESSION_ID` | Session identifier | Set by Claude |
|
|
103
|
+
| `CLAUDE_PROJECT_DIR` | Project root directory | Auto-detected |
|
|
104
|
+
| `SKIP_AUDIT_LOG` | Disable audit logging | Not set |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Hook Execution Order
|
|
109
|
+
|
|
110
|
+
Hooks run in the order specified in `hooks.json`:
|
|
111
|
+
|
|
112
|
+
**PreToolUse order:**
|
|
113
|
+
|
|
114
|
+
1. safety_validator.py (can block)
|
|
115
|
+
2. sensitive_file_blocker.py (can block)
|
|
116
|
+
3. audit_logger.py (logs)
|
|
117
|
+
4. skill_validator.py (warns)
|
|
118
|
+
|
|
119
|
+
**PostToolUse order:**
|
|
120
|
+
|
|
121
|
+
1. auto_format.sh (formats)
|
|
122
|
+
2. audit_logger.py (logs)
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Selective Hook Enabling
|
|
127
|
+
|
|
128
|
+
To use only specific hooks, edit `hooks.json` and remove unwanted entries.
|
|
129
|
+
|
|
130
|
+
### Safety Only (No Formatting)
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"hooks": {
|
|
135
|
+
"PreToolUse": [
|
|
136
|
+
{
|
|
137
|
+
"_description": "Safety gate",
|
|
138
|
+
"matcher": "Bash|Write|Edit",
|
|
139
|
+
"hooks": [
|
|
140
|
+
{
|
|
141
|
+
"type": "command",
|
|
142
|
+
"command": "./safety_validator.py"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Adding New Hooks
|
|
154
|
+
|
|
155
|
+
### Python Hook Template
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
#!/usr/bin/env python3
|
|
159
|
+
"""My custom hook."""
|
|
160
|
+
|
|
161
|
+
import json
|
|
162
|
+
import sys
|
|
163
|
+
|
|
164
|
+
def main() -> None:
|
|
165
|
+
try:
|
|
166
|
+
data = json.load(sys.stdin)
|
|
167
|
+
except json.JSONDecodeError:
|
|
168
|
+
sys.exit(0)
|
|
169
|
+
|
|
170
|
+
# Your logic here
|
|
171
|
+
tool_name = data.get("tool_name", "")
|
|
172
|
+
tool_input = data.get("tool_input", {})
|
|
173
|
+
|
|
174
|
+
# Exit 0 = allow, Exit 2 = block
|
|
175
|
+
sys.exit(0)
|
|
176
|
+
|
|
177
|
+
if __name__ == "__main__":
|
|
178
|
+
main()
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Shell Hook Template
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
#!/bin/bash
|
|
185
|
+
set -e
|
|
186
|
+
|
|
187
|
+
# Read JSON input
|
|
188
|
+
INPUT=$(cat)
|
|
189
|
+
|
|
190
|
+
# Parse with jq
|
|
191
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
192
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')
|
|
193
|
+
|
|
194
|
+
# Your logic here
|
|
195
|
+
|
|
196
|
+
# Exit 0 = allow, Exit 2 = block
|
|
197
|
+
exit 0
|
|
198
|
+
```
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Hooks
|
|
2
|
+
|
|
3
|
+
Claude Code hooks for safety validation, sensitive file protection, formatting, and audit logging.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## What Are Hooks?
|
|
8
|
+
|
|
9
|
+
Hooks are scripts that run at specific points in Claude's workflow:
|
|
10
|
+
- **UserPromptSubmit**: When user submits a prompt
|
|
11
|
+
- **PreToolUse**: Before a tool executes
|
|
12
|
+
- **PostToolUse**: After a tool completes
|
|
13
|
+
- **Stop**: When Claude stops responding
|
|
14
|
+
|
|
15
|
+
**Key insight:** Hooks can modify prompts, block actions, and track state.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Configuration
|
|
20
|
+
|
|
21
|
+
All hooks are configured in `hooks.json` in this directory. Claude Code reads this file automatically when the plugin is installed.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Current Hooks
|
|
26
|
+
|
|
27
|
+
| Hook | Event | Purpose |
|
|
28
|
+
|------|-------|---------|
|
|
29
|
+
| `safety_validator.py` | PreToolUse | Blocks destructive commands |
|
|
30
|
+
| `sensitive_file_blocker.py` | PreToolUse | Blocks access to sensitive files |
|
|
31
|
+
| `skill_validator.py` | PreToolUse | Validates skill file structure |
|
|
32
|
+
| `auto_format.sh` | PostToolUse | Auto-formats after file changes |
|
|
33
|
+
| `audit_logger.py` | All events | Logs all actions for audit trail |
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Hook Details
|
|
38
|
+
|
|
39
|
+
### safety_validator.py (PreToolUse)
|
|
40
|
+
|
|
41
|
+
**Purpose:** Blocks destructive bash commands and sensitive file modifications.
|
|
42
|
+
|
|
43
|
+
**Matcher:** `Bash|Write|Edit`
|
|
44
|
+
|
|
45
|
+
**Blocks:**
|
|
46
|
+
- `rm -rf /`, `rm -rf ~`, `rm -rf *`
|
|
47
|
+
- `dd` disk operations, `mkfs` formatting
|
|
48
|
+
- Fork bombs
|
|
49
|
+
- Bash access to `.env`, `id_rsa`, `credentials` files
|
|
50
|
+
|
|
51
|
+
**Exit codes:**
|
|
52
|
+
- `0` - Allow
|
|
53
|
+
- `2` - Block with message
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### sensitive_file_blocker.py (PreToolUse)
|
|
58
|
+
|
|
59
|
+
**Purpose:** Blocks Read/Edit/Write access to sensitive files.
|
|
60
|
+
|
|
61
|
+
**Matcher:** `Read|Edit|Write`
|
|
62
|
+
|
|
63
|
+
**Blocked patterns:**
|
|
64
|
+
- `.env` files (`.env`, `.env.local`, `.env.production`)
|
|
65
|
+
- `secrets` in path
|
|
66
|
+
- `credentials` in path
|
|
67
|
+
|
|
68
|
+
**Exception:** Files ending with `.example` are allowed.
|
|
69
|
+
|
|
70
|
+
**Exit codes:**
|
|
71
|
+
- `0` - Allow
|
|
72
|
+
- `2` - Block with message
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### skill_validator.py (PreToolUse)
|
|
77
|
+
|
|
78
|
+
**Purpose:** Validates skill files follow correct structure.
|
|
79
|
+
|
|
80
|
+
**Matcher:** `Write|Edit`
|
|
81
|
+
|
|
82
|
+
**Checks:**
|
|
83
|
+
- YAML frontmatter (name, description)
|
|
84
|
+
- Required sections (Purpose, When to Use)
|
|
85
|
+
- File length limits
|
|
86
|
+
- Resource file references
|
|
87
|
+
|
|
88
|
+
**Enforcement:** Soft (warns but doesn't block)
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
### auto_format.sh (PostToolUse)
|
|
93
|
+
|
|
94
|
+
**Purpose:** Auto-formats files after Write/Edit operations.
|
|
95
|
+
|
|
96
|
+
**Matcher:** `Write|Edit`
|
|
97
|
+
|
|
98
|
+
**Runs:** `source ~/.nvm/nvm.sh && nvm use 24 && npm run format`
|
|
99
|
+
|
|
100
|
+
**Requires:** Node.js 24 via nvm
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### audit_logger.py (All Events)
|
|
105
|
+
|
|
106
|
+
**Purpose:** Logs all Claude actions for audit trail.
|
|
107
|
+
|
|
108
|
+
**Log location:** `.claude/audit_logs/YYYYMMDD_audit.jsonl`
|
|
109
|
+
|
|
110
|
+
**Logged events:**
|
|
111
|
+
- PreToolUse (tool name, inputs)
|
|
112
|
+
- PostToolUse (tool name, success/failure)
|
|
113
|
+
- UserPromptSubmit (prompt text)
|
|
114
|
+
- Stop (session end)
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Adding New Hooks
|
|
119
|
+
|
|
120
|
+
1. Create script in this `hooks/` directory
|
|
121
|
+
2. Make executable: `chmod +x script.py`
|
|
122
|
+
3. Add to `hooks.json` under appropriate event
|
|
123
|
+
4. Include `_description` for documentation
|
|
124
|
+
|
|
125
|
+
Example entry in `hooks.json`:
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"_description": "My custom hook: does something useful",
|
|
129
|
+
"matcher": "Write|Edit",
|
|
130
|
+
"hooks": [
|
|
131
|
+
{
|
|
132
|
+
"type": "command",
|
|
133
|
+
"command": "./my-hook.py"
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
See [CONFIG.md](./CONFIG.md) for customization options.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Claude Code Audit Logger
|
|
4
|
+
|
|
5
|
+
Comprehensive audit trail for all Claude Code hook events.
|
|
6
|
+
Logs are stored in JSONL format with ISO timestamps for easy parsing and sorting.
|
|
7
|
+
|
|
8
|
+
Features:
|
|
9
|
+
- Daily log rotation with yyyymmdd_audit.jsonl naming format
|
|
10
|
+
- ISO 8601 timestamps (UTC) for consistent sorting
|
|
11
|
+
- Automatic cleanup of logs older than 90 days
|
|
12
|
+
- Captures all hook events: PreToolUse, PostToolUse, Stop, UserPromptSubmit
|
|
13
|
+
|
|
14
|
+
Log location: .claude/audit_logs/ (local to repository)
|
|
15
|
+
Log format: JSONL (one JSON object per line)
|
|
16
|
+
|
|
17
|
+
Each log entry contains:
|
|
18
|
+
- timestamp: ISO 8601 UTC timestamp
|
|
19
|
+
- event_type: The Claude hook event type
|
|
20
|
+
- session_id: Unique session identifier
|
|
21
|
+
- event_data: Full event payload from stdin
|
|
22
|
+
|
|
23
|
+
Usage:
|
|
24
|
+
Configure in .claude/settings.json hooks section
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import json
|
|
28
|
+
import os
|
|
29
|
+
import sys
|
|
30
|
+
import time
|
|
31
|
+
from datetime import datetime, timezone
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_log_directory() -> Path:
|
|
36
|
+
"""Get or create the audit logs directory in the local .claude folder."""
|
|
37
|
+
# Get the directory where this script is located (.claude/hooks/)
|
|
38
|
+
script_dir = Path(__file__).resolve().parent
|
|
39
|
+
# Go up to .claude/ and then into audit_logs/
|
|
40
|
+
log_dir = script_dir.parent / "audit_logs"
|
|
41
|
+
log_dir.mkdir(parents=True, exist_ok=True)
|
|
42
|
+
return log_dir
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def get_iso_timestamp() -> str:
|
|
46
|
+
"""Get current UTC timestamp in ISO 8601 format."""
|
|
47
|
+
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_log_filename() -> str:
|
|
51
|
+
"""Get log filename in yyyymmdd_audit.jsonl format."""
|
|
52
|
+
return datetime.now(timezone.utc).strftime("%Y%m%d") + "_audit.jsonl"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def parse_event_data() -> dict:
|
|
56
|
+
"""Parse event data from stdin."""
|
|
57
|
+
try:
|
|
58
|
+
return json.load(sys.stdin)
|
|
59
|
+
except json.JSONDecodeError as e:
|
|
60
|
+
return {"parse_error": str(e), "raw_input": "Could not read stdin"}
|
|
61
|
+
except Exception as e:
|
|
62
|
+
return {"error": str(e)}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def rotate_old_logs(log_dir: Path, retention_days: int = 90) -> None:
|
|
66
|
+
"""Remove log files older than retention period."""
|
|
67
|
+
cutoff_time = time.time() - (retention_days * 24 * 60 * 60)
|
|
68
|
+
|
|
69
|
+
for old_log in log_dir.glob("*_audit.jsonl"):
|
|
70
|
+
try:
|
|
71
|
+
if old_log.stat().st_mtime < cutoff_time:
|
|
72
|
+
old_log.unlink()
|
|
73
|
+
except OSError:
|
|
74
|
+
pass # Ignore errors during cleanup
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def write_audit_entry(log_dir: Path, entry: dict) -> None:
|
|
78
|
+
"""Write audit entry to daily log file."""
|
|
79
|
+
log_file = log_dir / get_log_filename()
|
|
80
|
+
|
|
81
|
+
with open(log_file, "a", encoding="utf-8") as f:
|
|
82
|
+
f.write(json.dumps(entry, ensure_ascii=False, separators=(",", ":")) + "\n")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def main() -> None:
|
|
86
|
+
"""Main entry point for audit logging."""
|
|
87
|
+
log_dir = get_log_directory()
|
|
88
|
+
|
|
89
|
+
# Build audit entry
|
|
90
|
+
audit_entry = {
|
|
91
|
+
"timestamp": get_iso_timestamp(),
|
|
92
|
+
"event_type": os.environ.get("CLAUDE_HOOK_EVENT", "unknown"),
|
|
93
|
+
"session_id": os.environ.get("CLAUDE_SESSION_ID", "unknown"),
|
|
94
|
+
"event_data": parse_event_data()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
# Write to log file
|
|
98
|
+
write_audit_entry(log_dir, audit_entry)
|
|
99
|
+
|
|
100
|
+
# Rotate old logs (runs on each call, but fast due to glob)
|
|
101
|
+
rotate_old_logs(log_dir)
|
|
102
|
+
|
|
103
|
+
sys.exit(0)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if __name__ == "__main__":
|
|
107
|
+
main()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Auto-format hook for Claude Code
|
|
3
|
+
#
|
|
4
|
+
# Runs the project's formatting pipeline (nx format + lint --fix)
|
|
5
|
+
# after Write/Edit operations.
|
|
6
|
+
#
|
|
7
|
+
# Requires Node.js 24 via nvm.
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
source ~/.nvm/nvm.sh && nvm use 24 && npm run format
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"PreToolUse": [
|
|
4
|
+
{
|
|
5
|
+
"_description": "Safety gate: blocks destructive bash commands",
|
|
6
|
+
"matcher": "Bash|Write|Edit",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "./safety_validator.py"
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"_description": "Block sensitive files with detailed error message",
|
|
16
|
+
"matcher": "Read|Edit|Write",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "./sensitive_file_blocker.py"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"_description": "Audit trail: logs all PreToolUse events",
|
|
26
|
+
"matcher": "",
|
|
27
|
+
"hooks": [
|
|
28
|
+
{
|
|
29
|
+
"type": "command",
|
|
30
|
+
"command": "./audit_logger.py"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"_description": "Skill validator: soft enforcement warnings for skill files",
|
|
36
|
+
"matcher": "Write|Edit",
|
|
37
|
+
"hooks": [
|
|
38
|
+
{
|
|
39
|
+
"type": "command",
|
|
40
|
+
"command": "./skill_validator.py"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"PostToolUse": [
|
|
46
|
+
{
|
|
47
|
+
"_description": "Auto-format files after Write/Edit",
|
|
48
|
+
"matcher": "Write|Edit",
|
|
49
|
+
"hooks": [
|
|
50
|
+
{
|
|
51
|
+
"type": "command",
|
|
52
|
+
"command": "./auto_format.sh"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"_description": "Audit trail: logs all PostToolUse events",
|
|
58
|
+
"matcher": "",
|
|
59
|
+
"hooks": [
|
|
60
|
+
{
|
|
61
|
+
"type": "command",
|
|
62
|
+
"command": "./audit_logger.py"
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"UserPromptSubmit": [
|
|
68
|
+
{
|
|
69
|
+
"_description": "Audit trail: logs all user prompt submissions",
|
|
70
|
+
"hooks": [
|
|
71
|
+
{
|
|
72
|
+
"type": "command",
|
|
73
|
+
"command": "./audit_logger.py"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Safety Validator Hook for Claude Code
|
|
4
|
+
======================================
|
|
5
|
+
|
|
6
|
+
Purpose:
|
|
7
|
+
Pre-tool-use validation layer that blocks potentially destructive operations
|
|
8
|
+
before they execute. Acts as a safety gate for Bash, Read, Write, and Edit tools.
|
|
9
|
+
|
|
10
|
+
Protected Against:
|
|
11
|
+
- Recursive deletion of root filesystem (rm -rf /)
|
|
12
|
+
- Recursive deletion of all files (rm -rf *)
|
|
13
|
+
- Recursive deletion of home directory (rm -rf ~)
|
|
14
|
+
- Disk wiping operations (dd if=/dev/zero)
|
|
15
|
+
- Access to environment files (.env, .env.local, .env.production, etc.)
|
|
16
|
+
- Access to secret files (.secret, .secret.local, etc.)
|
|
17
|
+
- Access to SSH private keys (id_rsa, id_ed25519, id_ecdsa)
|
|
18
|
+
- Access to credential files (.pem, credentials)
|
|
19
|
+
- Bash access to sensitive files (cat/head/tail/cp on .env, .secret, keys)
|
|
20
|
+
|
|
21
|
+
Exceptions:
|
|
22
|
+
- Files ending with .example are allowed (safe template files)
|
|
23
|
+
- e.g., .env.example, .secret.example can be read for structure reference
|
|
24
|
+
|
|
25
|
+
Exit Codes:
|
|
26
|
+
0 - Tool use permitted (validation passed)
|
|
27
|
+
2 - Tool use blocked (dangerous operation detected)
|
|
28
|
+
|
|
29
|
+
Integration:
|
|
30
|
+
Configured as PreToolUse hook in .claude/settings.json
|
|
31
|
+
Receives tool call JSON via stdin from Claude Code
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
import json
|
|
35
|
+
import sys
|
|
36
|
+
import re
|
|
37
|
+
|
|
38
|
+
data = json.load(sys.stdin)
|
|
39
|
+
tool_name = data.get("tool_name", "")
|
|
40
|
+
tool_input = data.get("tool_input", {})
|
|
41
|
+
|
|
42
|
+
# Block dangerous bash commands
|
|
43
|
+
if tool_name == "Bash":
|
|
44
|
+
command = tool_input.get("command", "")
|
|
45
|
+
|
|
46
|
+
dangerous_patterns = [
|
|
47
|
+
# rm -rf variations: handles -rf, -r -f, --recursive --force, etc.
|
|
48
|
+
r"rm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f[a-zA-Z]*|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r[a-zA-Z]*|-[a-zA-Z]*rf[a-zA-Z]*|-[a-zA-Z]*fr[a-zA-Z]*|--recursive\s+--force|--force\s+--recursive)\s+/\s*$",
|
|
49
|
+
# rm -rf /* or rm -rf *
|
|
50
|
+
r"rm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f[a-zA-Z]*|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r[a-zA-Z]*|-[a-zA-Z]*rf[a-zA-Z]*|-[a-zA-Z]*fr[a-zA-Z]*|--recursive\s+--force|--force\s+--recursive)\s+(/\*)?\*",
|
|
51
|
+
# rm -rf ~ (home directory)
|
|
52
|
+
r"rm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f[a-zA-Z]*|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r[a-zA-Z]*|-[a-zA-Z]*rf[a-zA-Z]*|-[a-zA-Z]*fr[a-zA-Z]*|--recursive\s+--force|--force\s+--recursive)\s+~",
|
|
53
|
+
# rm -rf $HOME
|
|
54
|
+
r"rm\s+(-[a-zA-Z]*r[a-zA-Z]*\s+-[a-zA-Z]*f[a-zA-Z]*|-[a-zA-Z]*f[a-zA-Z]*\s+-[a-zA-Z]*r[a-zA-Z]*|-[a-zA-Z]*rf[a-zA-Z]*|-[a-zA-Z]*fr[a-zA-Z]*|--recursive\s+--force|--force\s+--recursive)\s+\$HOME",
|
|
55
|
+
# dd disk operations
|
|
56
|
+
r"dd\s+.*if=/dev/(zero|random|urandom).*of=/dev/",
|
|
57
|
+
r"dd\s+.*of=/dev/[a-z]+\s",
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
for pattern in dangerous_patterns:
|
|
61
|
+
if re.search(pattern, command, re.IGNORECASE):
|
|
62
|
+
print("BLOCKED: Dangerous command pattern detected", file=sys.stderr)
|
|
63
|
+
sys.exit(2)
|
|
64
|
+
|
|
65
|
+
# Additional simple checks for common dangerous patterns
|
|
66
|
+
dangerous_simple = [
|
|
67
|
+
("rm -rf /", "recursive delete root"),
|
|
68
|
+
("rm -rf /*", "recursive delete root contents"),
|
|
69
|
+
("rm -rf ~", "recursive delete home"),
|
|
70
|
+
("rm -rf $HOME", "recursive delete home"),
|
|
71
|
+
("> /dev/sda", "overwrite disk"),
|
|
72
|
+
("mkfs.", "format filesystem"),
|
|
73
|
+
(":(){ :|:& };:", "fork bomb"),
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
for pattern, description in dangerous_simple:
|
|
77
|
+
if pattern in command:
|
|
78
|
+
print(f"BLOCKED: {description}", file=sys.stderr)
|
|
79
|
+
sys.exit(2)
|
|
80
|
+
|
|
81
|
+
# Block Bash access to sensitive files (but allow .example files)
|
|
82
|
+
# First check if it's an .example file - those are safe
|
|
83
|
+
if not re.search(r"\.example\b", command, re.IGNORECASE):
|
|
84
|
+
sensitive_file_patterns = [
|
|
85
|
+
r"\bcat\s+.*\.env\b",
|
|
86
|
+
r"\bhead\s+.*\.env\b",
|
|
87
|
+
r"\btail\s+.*\.env\b",
|
|
88
|
+
r"\bcp\s+.*\.env\b",
|
|
89
|
+
r"\bcat\s+.*\.secret",
|
|
90
|
+
r"\bhead\s+.*\.secret",
|
|
91
|
+
r"\btail\s+.*\.secret",
|
|
92
|
+
r"\bcp\s+.*\.secret",
|
|
93
|
+
r"\bcat\s+.*id_rsa",
|
|
94
|
+
r"\bcat\s+.*id_ed25519",
|
|
95
|
+
r"\bcat\s+.*\.pem",
|
|
96
|
+
r"\bcat\s+.*credentials",
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
for pattern in sensitive_file_patterns:
|
|
100
|
+
if re.search(pattern, command, re.IGNORECASE):
|
|
101
|
+
print("BLOCKED: Cannot access sensitive file via Bash", file=sys.stderr)
|
|
102
|
+
sys.exit(2)
|
|
103
|
+
|
|
104
|
+
# Block access to sensitive files
|
|
105
|
+
if tool_name in ["Read", "Write", "Edit"]:
|
|
106
|
+
file_path = tool_input.get("file_path", "")
|
|
107
|
+
|
|
108
|
+
# Allow .example files (they're safe templates without secrets)
|
|
109
|
+
if file_path.endswith(".example"):
|
|
110
|
+
sys.exit(0)
|
|
111
|
+
|
|
112
|
+
sensitive_patterns = [
|
|
113
|
+
".env",
|
|
114
|
+
".secret",
|
|
115
|
+
"id_rsa",
|
|
116
|
+
"id_ed25519",
|
|
117
|
+
"id_ecdsa",
|
|
118
|
+
".pem",
|
|
119
|
+
"credentials",
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
for blocked in sensitive_patterns:
|
|
123
|
+
if blocked in file_path:
|
|
124
|
+
print(
|
|
125
|
+
f"BLOCKED: Cannot modify sensitive file: {file_path}", file=sys.stderr
|
|
126
|
+
)
|
|
127
|
+
sys.exit(2)
|
|
128
|
+
|
|
129
|
+
sys.exit(0)
|