#!/usr/bin/env node /** * Token Checkpoint Monitor Hook * * Runs after tool execution to check if token usage has exceeded checkpoints. * Enforces inst_075: Token checkpoint monitoring is MANDATORY, not optional. * * This hook reads system context to extract current token count and compares * against checkpoints in .claude/token-checkpoints.json. */ const fs = require('fs'); const path = require('path'); const input = JSON.parse(process.argv[2] || '{}'); // Extract token usage from system warnings in context // Claude Code provides token counts in tags const contextText = JSON.stringify(input); const tokenMatch = contextText.match(/Token usage: (\d+)\/(\d+)/); if (!tokenMatch) { // No token info available - skip silently process.exit(0); } const currentTokens = parseInt(tokenMatch[1]); const budgetTokens = parseInt(tokenMatch[2]); // Read checkpoint configuration const checkpointPath = path.join(__dirname, '../token-checkpoints.json'); let checkpoints; try { checkpoints = JSON.parse(fs.readFileSync(checkpointPath, 'utf8')); } catch (err) { console.error('\x1b[31m❌ Failed to read token-checkpoints.json\x1b[0m'); process.exit(0); } const nextCheckpoint = checkpoints.next_checkpoint; // Check if we've passed a checkpoint if (currentTokens > nextCheckpoint) { console.log('\x1b[33m⚠️ TOKEN CHECKPOINT EXCEEDED\x1b[0m'); console.log(`\x1b[36mCurrent: ${currentTokens.toLocaleString()} / ${budgetTokens.toLocaleString()} tokens (${((currentTokens/budgetTokens)*100).toFixed(1)}%)\x1b[0m`); console.log(`\x1b[36mCheckpoint: ${nextCheckpoint.toLocaleString()} tokens\x1b[0m`); console.log('\x1b[31m📊 MANDATORY: Run checkpoint analysis NOW\x1b[0m'); console.log(`\x1b[36mnode scripts/check-token-checkpoint.js --tokens ${currentTokens}/${budgetTokens}\x1b[0m`); console.log('\x1b[36mSee inst_075 for checkpoint requirements\x1b[0m'); process.exit(0); } // Approaching checkpoint - warn at 90% const approachThreshold = nextCheckpoint * 0.9; if (currentTokens > approachThreshold) { const remaining = nextCheckpoint - currentTokens; console.log(`\x1b[33m⚠️ Approaching ${(nextCheckpoint/budgetTokens*100)}% checkpoint: ${remaining.toLocaleString()} tokens remaining\x1b[0m`); } process.exit(0);