Development
Hook
Hooks
What aurakit runs automatically, and when. A hook is a command Claude Code fires at a fixed moment, without you asking for it.
Install
$ npx -y skills add smorky850612/Aurakit --agent claude-codeShips with aurakit. Installing the plugin gets these hooks.
Where it lives
- hooks/auto-format.jsGitHub
Read the script
#!/usr/bin/env node /** * AuraKit — PostToolUse Auto Formatter * Write/Edit 완료 후 자동 코드 포맷 * Prettier(JS/TS/CSS/JSON/MD) · gofmt(Go) · black(Python) · rustfmt(Rust) * Hook: PostToolUse (matcher: Write|Edit) */ 'use strict'; const { readInput, fileExists } = require('./lib/common.js'); const { execSync } = require('child_process'); const path = require('path'); const input = readInput(); const toolName = input.tool_name || ''; const toolInput = input.tool_input || {}; // Write/Edit 툴만 처리 if (!['Write', 'Edit'].includes(toolName)) process.exit(0); const filePath = toolInput.file_path || ''; if (!filePath) process.exit(0); const ext = path.extname(filePath).toLowerCase(); // ── 도구 실행 헬퍼 ──────────────────────────────────────────────────── function tryExec(cmd) { try { execSync(cmd, { timeout: 15000, stdio: 'ignore' }); return true; } catch { return false; } } // ── Prettier 적용 대상 확장자 ───────────────────────────────────────── const PRETTIER_EXTS = new Set(['.js', '.jsx', '.ts', '.tsx', '.css', '.scss', '.json', '.md', '.yaml', '.yml', '.html']); if (PRETTIER_EXTS.has(ext)) { // Prettier 설정 파일 존재 확인 (프로젝트에 설정 없으면 포맷하지 않음) const hasPrettier = fileExists('.prettierrc') || fileExists('.prettierrc.json') || fileExists('.prettierrc.js') || fileExists('.prettierrc.cjs') || fileExists('.prettierrc.yaml') || fileExists('.prettierrc.yml') || fileExists('prettier.config.js') || fileExists('prettier.config.cjs'); if (hasPrettier) { // 로컬 설치 우선, 없으면 npx const localPrettier = path.join('node_modules', '.bin', 'prettier'); if (fileExists(localPrettier)) { tryExec(`"${localPrettier}" --write "${filePath}" 2>/dev/null`); } else { tryExec(`npx --yes --quiet prettier --write "${filePath}" 2>/dev/null`); } } process.exit(0); } // ── Go ──────────────────────────────────────────────────────────────── if (ext === '.go') { tryExec(`gofmt -w "${filePath}"`); process.exit(0); } // ── Python ──────────────────────────────────────────────────────────── if (ext === '.py') { // black 우선, 없으면 autopep8 if (!tryExec(`black "${filePath}" --quiet 2>/dev/null`)) { tryExec(`python -m black "${filePath}" --quiet 2>/dev/null`); } process.exit(0); } // ── Rust ────────────────────────────────────────────────────────────── if (ext === '.rs') { tryExec(`rustfmt "${filePath}" 2>/dev/null`); process.exit(0); } // ── Java / Kotlin ───────────────────────────────────────────────────── if (ext === '.java') { // google-java-format (있을 때만) tryExec(`google-java-format -i "${filePath}" 2>/dev/null`); process.exit(0); } if (ext === '.kt' || ext === '.kts') { tryExec(`ktlint -F "${filePath}" 2>/dev/null`); process.exit(0); } // ── PHP ─────────────────────────────────────────────────────────────── if (ext === '.php') { tryExec(`php-cs-fixer fix "${filePath}" --quiet 2>/dev/null`); process.exit(0); } process.exit(0); - hooks/bash-guard.jsGitHub
Read the script
#!/usr/bin/env node /** * AuraKit — PreToolUse Bash Guard (Node.js 크로스 플랫폼 버전) * 위험한 Bash 명령 감지. matcher: Bash */ 'use strict'; const { readInput, allow, block } = require('./lib/common.js'); const input = readInput(); const cmd = (input.tool_input || {}).command || ''; if (!cmd) allow(); // ── 파괴적 명령 패턴 ───────────────────────────────────────────────── const DANGEROUS = [ { re: /rm\s+-rf?\s+\/(?:\s|$)/, desc: 'rm -rf /' }, { re: /git\s+push\s+.*--force\s+(?:origin\s+)?main/, desc: 'force push to main' }, { re: /git\s+reset\s+--hard\s+HEAD~(?:[2-9]|\d{2,})/, desc: 'git reset --hard HEAD~N (N≥2)' }, { re: /git\s+clean\s+.*-[a-z]*f[a-z]*/, desc: 'git clean -f (미추적 파일 삭제)' }, { re: /DROP\s+DATABASE/i, desc: 'DROP DATABASE' }, { re: /chmod\s+-R\s+777/, desc: 'chmod -R 777' }, { re: />\s*\/etc\/(passwd|shadow|sudoers)/, desc: '/etc/passwd|shadow 쓰기' }, { re: /curl.*\|\s*(?:bash|sh)/, desc: 'curl | bash (원격 실행)' }, { re: /wget.*\|\s*(?:bash|sh)/, desc: 'wget | bash (원격 실행)' }, ]; const found = DANGEROUS.filter(p => p.re.test(cmd)); if (found.length > 0) { block( '🔴 AuraKit Bash Guard 차단\n' + ' 위험한 명령이 감지되었습니다:\n' + found.map(f => ' - ' + f.desc).join('\n') + '\n' + ' 의도한 명령이라면 직접 터미널에서 실행하세요.' ); } allow(); - hooks/bloat-check.jsGitHub
Read the script
#!/usr/bin/env node /** * AuraKit — PostToolUse Bloat Check (Node.js 크로스 플랫폼 버전) * 파일 크기 감시 (250줄 초과 경고). matcher: Write|Edit */ 'use strict'; const fs = require('fs'); const { readInput, allow } = require('./lib/common.js'); const input = readInput(); const filePath = (input.tool_input || {}).file_path || ''; if (!filePath) allow(); try { const content = fs.readFileSync(filePath, 'utf8'); const lines = content.split('\n').length; if (lines > 250) { process.stderr.write( `⚠️ AuraKit Bloat: ${filePath} (${lines}줄 > 250줄)\n` + ' 컴포넌트 분할을 권장합니다. /aura clean: 으로 정리 가능.\n' ); } } catch {} allow(); - hooks/bloat-check.shGitHub
Read the script
#!/bin/bash # AuraKit - 파일 크기(줄 수) 모니터링 및 블로트 경고 # Hook: PostToolUse (matcher: Write|Edit) # stdin: JSON (tool_result + tool_input) # exit 0 (경고만, 블로킹 아님) set -euo pipefail # ── 설정 ─────────────────────────────────────────────────────────────── WARN_LINES=250 # 경고 임계값 CRITICAL_LINES=400 # 심각 경고 임계값 # ── JSON 입력 읽기 ───────────────────────────────────────────────────── INPUT=$(cat) # file_path 추출 if command -v jq &>/dev/null; then FILE_PATH=$(echo "${INPUT}" | jq -r '.tool_input.file_path // ""' 2>/dev/null || echo "") else FILE_PATH=$(echo "${INPUT}" | grep -o '"file_path":"[^"]*"' | sed 's/"file_path":"//;s/"$//' || echo "") fi # 파일 경로가 없거나 존재하지 않으면 스킵 if [ -z "${FILE_PATH}" ] || [ ! -f "${FILE_PATH}" ]; then exit 0 fi # ── 검사 대상 파일 필터링 ───────────────────────────────────────────── EXTENSION="${FILE_PATH##*.}" # 소스 코드 파일만 검사 case "${EXTENSION}" in ts|tsx|js|jsx|py|go|rs|java|kt|swift|rb|php|vue|svelte|astro) # 검사 대상 ;; *) # 설정 파일, 마크다운, JSON 등은 스킵 exit 0 ;; esac # 생성된 파일 / 노드 모듈 제외 if echo "${FILE_PATH}" | grep -qE "node_modules|\.next|dist|build|__pycache__|\.pyc$|vendor"; then exit 0 fi # ── 줄 수 카운트 ────────────────────────────────────────────────────── if command -v wc &>/dev/null; then LINE_COUNT=$(wc -l < "${FILE_PATH}" 2>/dev/null || echo "0") else LINE_COUNT=$(grep -c "" "${FILE_PATH}" 2>/dev/null || echo "0") fi # ── 결과 출력 ───────────────────────────────────────────────────────── FILE_BASENAME=$(basename "${FILE_PATH}") if [ "${LINE_COUNT}" -ge "${CRITICAL_LINES}" ] 2>/dev/null; then echo "" echo "🚨 AuraKit Bloat Warning [CRITICAL]: ${FILE_PATH}" echo " 현재 줄 수: ${LINE_COUNT}줄 (임계값: ${WARN_LINES}줄)" echo "" echo " 분할 권장:" case "${EXTENSION}" in tsx|jsx) echo " → 서브 컴포넌트로 분리 ([Name]Item.tsx, [Name]List.tsx)" echo " → 커스텀 훅 추출 (use[Name].ts)" echo " → 타입 분리 ([name].types.ts)" ;; ts|js) if echo "${FILE_PATH}" | grep -qi "route\|controller\|handler"; then echo " → 서비스 레이어 추출 ([name].service.ts)" echo " → 리포지토리 레이어 추출 ([name].repository.ts)" echo " → 스키마 분리 ([name].schema.ts)" else echo " → 도메인별 유틸리티 분리 ([domain].utils.ts)" echo " → 상수 분리 ([name].constants.ts)" fi ;; py) echo " → 모듈로 분리 (services/, repositories/, schemas/)" echo " → 믹스인 추출" ;; esac echo "" echo " /aura 분할 리팩토링 해줘 — 로 자동 분할 요청 가능" elif [ "${LINE_COUNT}" -ge "${WARN_LINES}" ] 2>/dev/null; then echo "" echo "⚠️ AuraKit Bloat Warning: ${FILE_PATH}" echo " 현재 줄 수: ${LINE_COUNT}줄 (권장 최대: ${WARN_LINES}줄)" echo " 250줄 이내로 분할을 권장합니다." echo " /aura ${FILE_BASENAME} 분할해줘 — 로 자동 분할 가능" fi # 경고는 출력하되 항상 exit 0 (블로킹 없음) exit 0 - hooks/build-progress.jsGitHub
Read the script
#!/usr/bin/env node /** * AuraKit — PostToolUse Build Progress (Node.js 크로스 플랫폼 버전) * 파일 완료 시 스냅샷 업데이트 + 진행률 표시. matcher: Write|Edit */ 'use strict'; const fs = require('fs'); const path = require('path'); const { readInput, allow, AURA_DIR, SNAPSHOTS_DIR } = require('./lib/common.js'); const input = readInput(); const filePath = (input.tool_input || {}).file_path || ''; if (!filePath) allow(); const snapshotFile = path.join(SNAPSHOTS_DIR, 'current.md'); try { if (fs.existsSync(snapshotFile)) { let snap = fs.readFileSync(snapshotFile, 'utf8'); // Remaining 섹션에서 완료된 파일 체크 const baseName = path.basename(filePath); const escapedBase = baseName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); snap = snap.replace(new RegExp(`^- \\[ \\] .*${escapedBase}.*$`, 'm'), m => m.replace('[ ]', '[x]')); fs.writeFileSync(snapshotFile, snap, 'utf8'); } } catch {} allow(); - hooks/build-verify.jsGitHub
Read the script
#!/usr/bin/env node /** * AuraKit — PostToolUse Build Verify (Node.js 크로스 플랫폼 버전) * TypeScript/Python 문법 검사 + Convention Check (V1). matcher: Write|Edit */ 'use strict'; const path = require('path'); const fs = require('fs'); const { execSync } = require('child_process'); const { readInput, allow } = require('./lib/common.js'); const input = readInput(); const filePath = (input.tool_input || {}).file_path || ''; if (!filePath) allow(); // TypeScript 파일 검사 — tsconfig.json 없으면 스킵 (npx 기동비용 방지) if (/\.(ts|tsx)$/.test(filePath) && fs.existsSync('tsconfig.json')) { try { // 로컬 tsc 우선 사용 (npx 오버헤드 ~1s 제거) const localTsc = path.join('node_modules', '.bin', 'tsc'); const tscCmd = fs.existsSync(localTsc) ? `"${localTsc}"` : 'npx tsc'; execSync(`${tscCmd} --noEmit --skipLibCheck 2>&1`, { timeout: 15000, stdio: 'pipe' }); } catch (e) { const out = e.stdout ? e.stdout.toString() : ''; if (out && out.includes('error TS')) { process.stderr.write('⚠️ AuraKit V1: TypeScript 오류\n' + out.substring(0, 500) + '\n'); } } } // Python 파일 검사 if (/\.py$/.test(filePath)) { try { const py = process.platform === 'win32' ? 'python' : 'python3'; execSync(`${py} -m py_compile "${filePath}" 2>&1`, { timeout: 10000, stdio: 'pipe' }); } catch (e) { const out = e.stdout ? e.stdout.toString() : (e.stderr ? e.stderr.toString() : ''); if (out) process.stderr.write('⚠️ AuraKit V1: Python 오류\n' + out.substring(0, 300) + '\n'); } } // Convention Check (CONV-001~005) — 경고만, 차단 아님 (pre-commit에서 차단) if (/\.(ts|tsx|js|jsx|py|go)$/.test(filePath)) { try { const convScript = path.join(__dirname, '..', 'scripts', 'convention-check.sh'); if (fs.existsSync(convScript)) { execSync(`bash "${convScript}" "${filePath}" 2>&1`, { timeout: 10000, stdio: 'pipe' }); } } catch (e) { const out = e.stdout ? e.stdout.toString() : ''; if (out && out.includes('CONV')) { process.stderr.write('⚠️ AuraKit V1 Convention:\n' + out.substring(0, 400) + '\n'); } } } allow(); - hooks/build-verify.shGitHub
- hooks/cache-guard.jsGitHub
- hooks/governance-capture.jsGitHub
- hooks/injection-guard.jsGitHub
- hooks/instinct-auto-save.jsGitHub
- hooks/korean-command.jsGitHub
- hooks/migration-guard.jsGitHub
- hooks/output-filter.jsGitHub
- hooks/post-compact-restore.jsGitHub
- hooks/post-compact-restore.shGitHub
- hooks/post-tool-failure.jsGitHub
- hooks/pre-compact-snapshot.jsGitHub
- hooks/pre-compact-snapshot.shGitHub
- hooks/pre-session.jsGitHub
- hooks/pre-session.shGitHub
- hooks/security-scan.jsGitHub
- hooks/security-scan.shGitHub
- hooks/session-stop.jsGitHub
- hooks/subagent-start.jsGitHub
- hooks/subagent-stop.jsGitHub
- hooks/task-completed.jsGitHub
- hooks/teammate-idle.jsGitHub
- hooks/token-stats-inject.jsGitHub
- hooks/token-stats-inject.pyGitHub
- hooks/token-tracker.jsGitHub
- hooks/token-tracker.pyGitHub
- hooks/uninstall.jsGitHub
All 33 scripts are listed above. The source is inlined for 6 of them, starting with whatever hooks.json actually runs. See all of them in the repo.
Read the script before you install anything that runs on your machine. This is the one part of a plugin that acts without being asked.
Ships withaurakit
One command. Full stack. Zero compromise. — All-in-one Claude Code skill with 33 modes, 6-layer security, 23 hooks, and 75% token savings. Works on Codex, Cursor, Manus, Windsurf.
Get the whole plugin
Stats
41
Stars
7
Forks
Maintained
Maintenance
JavaScript
Language
MIT
License
5mo ago
Last commit
6mo ago
Created
Repo: smorky850612/Aurakit

