#!/usr/bin/env node /** * token-hotspots CLI — emit ranked token hotspots and Opus 4.7 pattern findings * for a target repo path. * * Usage: * node token-hotspots-cli.mjs [path] [--json] [--output-file ] [--global] * * Exit codes: 0=ok, 3=unrecoverable error. * Zero external dependencies. */ import { resolve } from 'node:path'; import { writeFile, stat } from 'node:fs/promises'; import { discoverConfigFiles } from './lib/file-discovery.mjs'; import { resetCounter } from './lib/output.mjs'; import { scan } from './token-hotspots.mjs'; async function main() { const args = process.argv.slice(2); let targetPath = '.'; let outputFile = null; let jsonMode = false; let includeGlobal = false; for (let i = 0; i < args.length; i++) { if (args[i] === '--json') jsonMode = true; else if (args[i] === '--global') includeGlobal = true; else if (args[i] === '--output-file' && args[i + 1]) outputFile = args[++i]; else if (!args[i].startsWith('-')) targetPath = args[i]; } const absPath = resolve(targetPath); try { const s = await stat(absPath); if (!s.isDirectory()) { process.stderr.write(`Error: ${absPath} is not a directory\n`); process.exit(3); } } catch { process.stderr.write(`Error: path does not exist: ${absPath}\n`); process.exit(3); } resetCounter(); const discovery = await discoverConfigFiles(absPath, { includeGlobal }); const result = await scan(absPath, discovery); const payload = { scanner: result.scanner, status: result.status, files_scanned: result.files_scanned, duration_ms: result.duration_ms, total_estimated_tokens: result.total_estimated_tokens, hotspots: result.hotspots, findings: result.findings, counts: result.counts, }; const json = JSON.stringify(payload, null, 2); if (outputFile) { await writeFile(outputFile, json, 'utf-8'); } if (jsonMode || !outputFile) { process.stdout.write(json + '\n'); } } const isDirectRun = process.argv[1] && resolve(process.argv[1]) === resolve(new URL(import.meta.url).pathname); if (isDirectRun) { main().catch(err => { process.stderr.write(`Fatal: ${err.message}\n`); process.exit(3); }); }