diff --git a/.claude/hooks/audit-log.sh b/.claude/hooks/audit-log.sh new file mode 100755 index 0000000..25cbae0 --- /dev/null +++ b/.claude/hooks/audit-log.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Log all Bash commands with timestamp for audit trail +# Event: PostToolUse | Matcher: Bash +# Logs to .claude/hooks/audit.log + +INPUT=$(cat) +COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') +TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // "unknown"') + +if [ -z "$COMMAND" ]; then + exit 0 +fi + +LOG_DIR="$(dirname "$0")" +LOG_FILE="$LOG_DIR/audit.log" + +TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + +echo "[$TIMESTAMP] [$TOOL_NAME] $COMMAND" >> "$LOG_FILE" + +exit 0 diff --git a/.claude/hooks/bash-firewall.sh b/.claude/hooks/bash-firewall.sh new file mode 100755 index 0000000..91bc89c --- /dev/null +++ b/.claude/hooks/bash-firewall.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# Block dangerous bash commands +# Event: PreToolUse | Matcher: Bash +# Exit 2 = block, Exit 0 = allow + +INPUT=$(cat) +COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty') + +if [ -z "$COMMAND" ]; then + exit 0 +fi + +BLOCKED_PATTERNS=( + 'rm\s+-rf\s+/' + 'rm\s+-rf\s+\*' + 'rm\s+-rf\s+~' + 'git\s+push\s+.*--force\s+.*main' + 'git\s+push\s+.*--force\s+.*master' + 'git\s+reset\s+--hard' + 'git\s+clean\s+-fd' + 'chmod\s+-R\s+777' + 'mkfs\.' + '>\s*/dev/sd' + 'dd\s+if=.*/dev/' + ':(){:|:&};:' +) + +for pattern in "${BLOCKED_PATTERNS[@]}"; do + if echo "$COMMAND" | grep -qE "$pattern"; then + echo "Blocked: dangerous command detected — matches pattern '$pattern'" >&2 + echo "Command was: $COMMAND" >&2 + exit 2 + fi +done + +exit 0 diff --git a/.claude/hooks/post-edit-format.sh b/.claude/hooks/post-edit-format.sh new file mode 100755 index 0000000..e748776 --- /dev/null +++ b/.claude/hooks/post-edit-format.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Auto-format files after Edit/Write using Prettier +# Event: PostToolUse | Matcher: Edit|Write +# Silently skips if Prettier is not installed or file doesn't exist + +INPUT=$(cat) +FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') + +if [ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ]; then + exit 0 +fi + +EXTENSIONS="ts tsx js jsx json css scss html md yaml yml" +FILE_EXT="${FILE_PATH##*.}" + +SHOULD_FORMAT=false +for ext in $EXTENSIONS; do + if [ "$FILE_EXT" = "$ext" ]; then + SHOULD_FORMAT=true + break + fi +done + +if [ "$SHOULD_FORMAT" = false ]; then + exit 0 +fi + +if command -v npx &>/dev/null && [ -f "node_modules/.bin/prettier" ]; then + npx prettier --write "$FILE_PATH" 2>/dev/null +elif command -v prettier &>/dev/null; then + prettier --write "$FILE_PATH" 2>/dev/null +fi + +exit 0 diff --git a/.claude/hooks/protect-files.sh b/.claude/hooks/protect-files.sh new file mode 100755 index 0000000..f74a248 --- /dev/null +++ b/.claude/hooks/protect-files.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# Protect sensitive files from accidental edits +# Event: PreToolUse | Matcher: Edit|Write +# Exit 2 = block, Exit 0 = allow + +INPUT=$(cat) +FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty') + +if [ -z "$FILE_PATH" ]; then + exit 0 +fi + +PROTECTED_PATTERNS=( + ".env" + ".env.local" + ".env.production" + "package-lock.json" + "pnpm-lock.yaml" + "yarn.lock" + ".git/" + ".git/config" + "id_rsa" + "id_ed25519" + ".pem" +) + +for pattern in "${PROTECTED_PATTERNS[@]}"; do + if [[ "$FILE_PATH" == *"$pattern"* ]]; then + echo "Blocked: editing '$FILE_PATH' — matches protected pattern '$pattern'" >&2 + exit 2 + fi +done + +exit 0 diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..41fe53a --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,66 @@ +{ + "hooks": { + "PreToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-files.sh" + } + ] + }, + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/bash-firewall.sh" + } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/post-edit-format.sh" + } + ] + }, + { + "matcher": "Bash", + "hooks": [ + { + "type": "command", + "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/audit-log.sh" + } + ] + } + ], + "Notification": [ + { + "matcher": "", + "hooks": [ + { + "type": "command", + "command": "osascript -e 'display notification \"Claude Code ждёт вашего ввода\" with title \"Claude Code\"'" + } + ] + } + ], + "SessionStart": [ + { + "matcher": "compact", + "hooks": [ + { + "type": "command", + "command": "echo \"Reminder: check RULES.md and RECOMMENDATIONS.md for project conventions. Current phase: $(grep -m1 'Current Phase' \"$CLAUDE_PROJECT_DIR/docs/phases-plan.md\" 2>/dev/null || echo 'unknown')\"" + } + ] + } + ] + } +} diff --git a/.gitignore b/.gitignore index 25b9b32..7021151 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ logs/ *.pid *.pid.lock +# Claude Code hooks audit log +.claude/hooks/audit.log + # Environment files .env .env.local diff --git a/DOCS.md b/DOCS.md index c05ac59..d8ec024 100644 --- a/DOCS.md +++ b/DOCS.md @@ -71,6 +71,31 @@ Technical index for developers and AI agents. Use this as the entry point to all - `agents/code-reviewer.md` — code quality and PR review. - `agents/prompt-engineer.md` — LLM prompt design and optimization. +## Claude Code Skills (`/.claude/skills`) + +- `.claude/skills/update-status/` — sync project status across docs after milestone. +- `.claude/skills/phase-transition/` — full phase transition with verification. +- `.claude/skills/init-project/` — interactive project initialization wizard. +- `.claude/skills/component/` — scaffold accessible React component (frontend-architect). +- `.claude/skills/a11y-audit/` — WCAG 2.2 AA accessibility audit (frontend-architect). +- `.claude/skills/api-endpoint/` — scaffold REST API endpoint (backend-architect). +- `.claude/skills/db-schema/` — design database schema with migration (backend-architect). +- `.claude/skills/security-audit/` — OWASP security audit of git diff (security-auditor). +- `.claude/skills/threat-model/` — threat modeling with risk tiers (security-auditor). +- `.claude/skills/write-tests/` — write tests with Vitest + Testing Library (test-engineer). +- `.claude/skills/test-plan/` — test strategy and coverage plan (test-engineer). +- `.claude/skills/review/` — code review of current git diff (code-reviewer). +- `.claude/skills/review-pr/` — GitHub PR review by number (code-reviewer). +- `.claude/skills/improve-prompt/` — diagnose and improve LLM prompt (prompt-engineer). + +## Claude Code Hooks (`/.claude/hooks`) + +- `.claude/hooks/protect-files.sh` — blocks edits to `.env`, lock files, `.git/`, keys. +- `.claude/hooks/bash-firewall.sh` — blocks destructive commands (`rm -rf /`, `git reset --hard`, etc.). +- `.claude/hooks/post-edit-format.sh` — auto-formats files with Prettier after edits. +- `.claude/hooks/audit-log.sh` — logs all Bash commands with timestamp to `audit.log`. +- `.claude/settings.json` — hooks configuration (also: Notification, SessionStart compact context). + ## GitHub Templates (`/.github`) - `.github/ISSUE_TEMPLATE/bug_report.md` — bug report template. diff --git a/README.md b/README.md index 17728cb..869b380 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,14 @@ your-project/ │ └── api/ # Backend API (Node.js) ├── packages/ # Shared packages (if monorepo) │ └── shared/ # Types, utils, API client +├── .claude/ # Claude Code configuration +│ ├── settings.json # Hooks configuration +│ ├── hooks/ # Hook scripts +│ │ ├── protect-files.sh # Block edits to sensitive files +│ │ ├── bash-firewall.sh # Block dangerous commands +│ │ ├── post-edit-format.sh # Auto-format after edits +│ │ └── audit-log.sh # Log all Bash commands +│ └── skills/ # Slash-command skills (14 total) ├── .editorconfig # Editor formatting standards ├── .env.example # Environment variables template ├── package.json # Project metadata & engines