#!/usr/bin/env node /** * Stop Hook: Display basic status + AI summary prompt (Cross-platform) * * Event: Stop * Purpose: Display Git status, change statistics and temp files when session stops */ const common = require('./hook-common'); // Read stdin input let input = {}; try { const stdinData = require('fs').readFileSync(0, 'utf8'); if (stdinData.trim()) { input = JSON.parse(stdinData); } } catch { // Use default empty object } const cwd = input.cwd || process.cwd(); const reason = input.reason || 'task_complete'; const binding = common.getProjectMemoryBinding(cwd); const path = require('path'); function getTempBucket(file) { const normalized = file.replace(/\\/g, '/'); const knownRoots = ['plan', 'docs/plans', '.claude/temp', 'tmp', 'temp']; for (const root of knownRoots) { if (normalized === root || normalized.startsWith(`${root}/`)) { return root; } } const dirname = path.dirname(normalized); if (dirname === '.' || dirname === '') { return '.'; } return normalized.split('/')[0]; } // Build message function buildMessage() { let msg = '\n---\n'; msg += 'โœ… Session ended\n\n'; // Git info const gitInfo = common.getGitInfo(cwd); if (gitInfo.is_repo) { msg += '๐Ÿ“ Git repository\n'; msg += ` Branch: ${gitInfo.branch}\n`; if (gitInfo.has_changes) { const changesDetails = common.getChangesDetails(cwd); msg += ' Changes:\n'; if (changesDetails.added > 0) msg += ` ๅขžๅŠ : ${changesDetails.added} files\n`; if (changesDetails.modified > 0) msg += ` ไฟฎๆ”น: ${changesDetails.modified} files\n`; if (changesDetails.deleted > 0) msg += ` ๅˆ ้™ค: ${changesDetails.deleted} files\n`; } else { msg += ' Status: clean\n'; } } else { msg += '๐Ÿ“ Not a Git repository\n'; } msg += '\n'; // Temp file detection const tempInfo = common.detectTempFiles(cwd); if (tempInfo.count > 0) { msg += `๐Ÿงน Temp files: ${tempInfo.count}\n`; const grouped = {}; for (const file of tempInfo.files) { const dir = getTempBucket(file); if (!grouped[dir]) grouped[dir] = []; grouped[dir].push(file); } const orderedGroups = Object.entries(grouped).sort(([a], [b]) => { if (a === '.' && b !== '.') return -1; if (a !== '.' && b === '.') return 1; return a.localeCompare(b); }); for (const [dir, files] of orderedGroups) { const label = dir === '.' ? './' : `${dir}/`; msg += ` ๐Ÿ“‚ ${label} (${files.length})\n`; } } else { msg += 'โœ… No temp files\n'; } if (binding.bound) { msg += '\n๐Ÿง  Bound Obsidian KB\n'; msg += ` Project: ${binding.projectId || 'unknown'}\n`; msg += ' Minimum maintenance after research-state turns:\n'; msg += ' โ€ข Daily/YYYY-MM-DD.md\n'; msg += ` โ€ข ${binding.memoryPath || '.claude/project-memory/.md'}\n`; msg += ' โ€ข 00-Hub.md (only when top-level project status changes)\n'; } msg += '---'; return msg; } // Build and return const systemMessage = buildMessage(); const result = { continue: true, systemMessage: systemMessage }; console.log(JSON.stringify(result)); process.exit(0);