#!/usr/bin/env node /** * Strategic Compact Suggester * * Cross-platform (Windows, macOS, Linux) * * Runs on PreToolUse or periodically to suggest manual compaction at logical intervals * * Why manual over auto-compact: * - Auto-compact happens at arbitrary points, often mid-task * - Strategic compacting preserves context through logical phases * - Compact after exploration, before execution * - Compact after completing a milestone, before starting next */ const fs = require('fs'); const path = require('path'); const { getTempDir, writeFile, log } = require('../lib/utils'); async function main() { // Track tool call count (increment in a temp file) // Use a session-specific counter file based on session ID from environment // or parent PID as fallback const sessionId = process.env.CLAUDE_SESSION_ID || String(process.ppid) || 'default'; const counterFile = path.join(getTempDir(), `claude-tool-count-${sessionId}`); const rawThreshold = parseInt(process.env.COMPACT_THRESHOLD || '50', 10); const threshold = Number.isFinite(rawThreshold) && rawThreshold > 0 && rawThreshold <= 10000 ? rawThreshold : 50; let count = 1; // Read existing count or start at 1 // Use fd-based read+write to reduce (but not eliminate) race window // between concurrent hook invocations try { const fd = fs.openSync(counterFile, 'a+'); try { const buf = Buffer.alloc(64); const bytesRead = fs.readSync(fd, buf, 0, 64, 0); if (bytesRead > 0) { const parsed = parseInt(buf.toString('utf8', 0, bytesRead).trim(), 10); count = Number.isFinite(parsed) ? parsed + 1 : 1; } // Truncate and write new value fs.ftruncateSync(fd, 0); fs.writeSync(fd, String(count), 0); } finally { fs.closeSync(fd); } } catch { // Fallback: just use writeFile if fd operations fail writeFile(counterFile, String(count)); } // Suggest compact after threshold tool calls if (count === threshold) { log(`[StrategicCompact] ${threshold} tool calls reached - consider /compact if transitioning phases`); } // Suggest at regular intervals after threshold if (count > threshold && count % 25 === 0) { log(`[StrategicCompact] ${count} tool calls - good checkpoint for /compact if context is stale`); } process.exit(0); } main().catch(err => { console.error('[StrategicCompact] Error:', err.message); process.exit(0); });