claudectx 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../node_modules/tsup/assets/cjs_shims.js","../src/analyzer/tokenizer.ts","../src/shared/models.ts","../src/watcher/session-store.ts","../src/watcher/session-reader.ts","../src/components/Dashboard.tsx","../src/mcp/smart-reader.ts","../src/mcp/symbol-index.ts","../src/mcp/server.ts","../src/index.ts","../src/commands/analyze.ts","../src/analyzer/index.ts","../src/analyzer/context-parser.ts","../src/analyzer/waste-detector.ts","../src/shared/constants.ts","../src/analyzer/cost-calculator.ts","../src/commands/optimize.ts","../src/shared/logger.ts","../src/optimizer/ignorefile-generator.ts","../src/optimizer/claudemd-splitter.ts","../src/optimizer/cache-applier.ts","../src/optimizer/hooks-installer.ts","../src/commands/watch.ts","../src/commands/mcp.ts","../src/mcp/installer.ts","../src/commands/compress.ts","../src/compressor/session-parser.ts","../src/compressor/summarizer.ts","../src/shared/config.ts","../src/compressor/memory-writer.ts","../src/commands/report.ts","../src/reporter/usage-aggregator.ts","../src/reporter/formatter.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import { get_encoding } from 'js-tiktoken';\n\n// cl100k_base is the closest available encoding to Claude's tokenizer\n// Accuracy: within 2-5% of actual Claude token counts\nlet encoder: ReturnType<typeof get_encoding> | null = null;\n\nfunction getEncoder() {\n if (!encoder) {\n encoder = get_encoding('cl100k_base');\n }\n return encoder;\n}\n\n/**\n * Count tokens in a string using cl100k_base encoding.\n * Accurate to within 2-5% of Claude's actual tokenizer.\n */\nexport function countTokens(text: string): number {\n if (!text || text.length === 0) return 0;\n try {\n return getEncoder().encode(text).length;\n } catch {\n // Fallback: rough approximation (1 token ≈ 4 chars)\n return Math.ceil(text.length / 4);\n }\n}\n\n/**\n * Estimate token count without loading the encoder (for quick estimates).\n * Less accurate but faster. 1 token ≈ 4 characters on average.\n */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n","import type { ClaudeModel, ModelPricing } from './types.js';\n\n/** Per-million token pricing for all Claude models (USD) */\nexport const MODEL_PRICING: Record<ClaudeModel, ModelPricing> = {\n 'claude-haiku-4-5': {\n inputPerMillion: 1.0,\n outputPerMillion: 5.0,\n cacheReadPerMillion: 0.1,\n cacheWritePerMillion: 1.25,\n contextWindow: 200_000,\n },\n 'claude-sonnet-4-6': {\n inputPerMillion: 3.0,\n outputPerMillion: 15.0,\n cacheReadPerMillion: 0.3,\n cacheWritePerMillion: 3.75,\n contextWindow: 1_000_000,\n },\n 'claude-opus-4-6': {\n inputPerMillion: 5.0,\n outputPerMillion: 25.0,\n cacheReadPerMillion: 0.5,\n cacheWritePerMillion: 6.25,\n contextWindow: 1_000_000,\n },\n};\n\nexport const DEFAULT_MODEL: ClaudeModel = 'claude-sonnet-4-6';\n\nexport const MODEL_ALIASES: Record<string, ClaudeModel> = {\n haiku: 'claude-haiku-4-5',\n sonnet: 'claude-sonnet-4-6',\n opus: 'claude-opus-4-6',\n 'claude-haiku': 'claude-haiku-4-5',\n 'claude-sonnet': 'claude-sonnet-4-6',\n 'claude-opus': 'claude-opus-4-6',\n};\n\n/** Resolve a model alias or full name to a ClaudeModel key */\nexport function resolveModel(input: string): ClaudeModel {\n const lower = input.toLowerCase();\n if (lower in MODEL_ALIASES) return MODEL_ALIASES[lower];\n if (lower in MODEL_PRICING) return lower as ClaudeModel;\n return DEFAULT_MODEL;\n}\n\n/** Calculate cost for a given token count and model */\nexport function calculateCost(tokens: number, model: ClaudeModel): number {\n if (tokens === 0) return 0;\n return (tokens / 1_000_000) * MODEL_PRICING[model].inputPerMillion;\n}\n","/**\n * Cross-process session store.\n *\n * The Claude Code PostToolUse hook writes a file-read event here each time\n * Claude reads a file. The watch dashboard polls this file for live updates.\n */\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nexport interface FileReadEvent {\n timestamp: string;\n filePath: string;\n sessionId?: string;\n}\n\nexport interface FileStats {\n filePath: string;\n readCount: number;\n firstSeen: string;\n lastSeen: string;\n}\n\n// Computed lazily so os.homedir() can be mocked in tests\nfunction getStoreDirPath(): string {\n return path.join(os.homedir(), '.claudectx');\n}\n\nfunction getReadsFilePath_(): string {\n return path.join(getStoreDirPath(), 'reads.jsonl');\n}\n\nfunction ensureStoreDir(): void {\n const dir = getStoreDirPath();\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n}\n\n/**\n * Append a file-read event. Called by the hook (runs in a separate process).\n */\nexport function appendFileRead(filePath: string, sessionId?: string): void {\n ensureStoreDir();\n const event: FileReadEvent = {\n timestamp: new Date().toISOString(),\n filePath,\n sessionId,\n };\n fs.appendFileSync(getReadsFilePath_(), JSON.stringify(event) + '\\n', 'utf-8');\n}\n\n/**\n * Read all logged file-read events from disk.\n */\nexport function readAllEvents(): FileReadEvent[] {\n const readsFile = getReadsFilePath_();\n if (!fs.existsSync(readsFile)) return [];\n const lines = fs.readFileSync(readsFile, 'utf-8').trim().split('\\n').filter(Boolean);\n return lines\n .map((line) => {\n try {\n return JSON.parse(line) as FileReadEvent;\n } catch {\n return null;\n }\n })\n .filter((e): e is FileReadEvent => e !== null);\n}\n\n/**\n * Aggregate raw events into per-file stats, sorted by read count descending.\n */\nexport function aggregateStats(events: FileReadEvent[]): FileStats[] {\n const map = new Map<string, FileStats>();\n for (const e of events) {\n const existing = map.get(e.filePath);\n if (existing) {\n existing.readCount++;\n existing.lastSeen = e.timestamp;\n } else {\n map.set(e.filePath, {\n filePath: e.filePath,\n readCount: 1,\n firstSeen: e.timestamp,\n lastSeen: e.timestamp,\n });\n }\n }\n return [...map.values()].sort((a, b) => b.readCount - a.readCount);\n}\n\n/**\n * Clear the log (e.g. at session start).\n */\nexport function clearStore(): void {\n const readsFile = getReadsFilePath_();\n if (fs.existsSync(readsFile)) {\n fs.writeFileSync(readsFile, '', 'utf-8');\n }\n}\n\nexport function getReadsFilePath(): string {\n return getReadsFilePath_();\n}\n\nexport function getStoreDir(): string {\n return getStoreDirPath();\n}\n","/**\n * Reads Claude Code session JSONL files to extract token usage.\n *\n * Session files live at:\n * ~/.claude/projects/<path-with-slashes-as-dashes>/<session-uuid>.jsonl\n *\n * Each line is one of:\n * {\"type\":\"user\", \"message\": {...}}\n * {\"type\":\"assistant\", \"message\": {\"role\":\"assistant\",\"content\":[...],\"usage\":{...}}}\n * {\"type\":\"summary\", ...}\n *\n * The `usage` object on assistant messages mirrors the Anthropic API:\n * input_tokens, output_tokens,\n * cache_creation_input_tokens, cache_read_input_tokens\n */\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nexport interface SessionTokenUsage {\n inputTokens: number;\n outputTokens: number;\n cacheCreationTokens: number;\n cacheReadTokens: number;\n requestCount: number;\n}\n\nexport interface SessionFileMeta {\n filePath: string;\n mtimeMs: number;\n sessionId: string;\n projectDir: string;\n}\n\nconst CLAUDE_PROJECTS_DIR = path.join(os.homedir(), '.claude', 'projects');\n\n/**\n * List all session JSONL files across all projects, sorted newest-first.\n */\nexport function listSessionFiles(): SessionFileMeta[] {\n if (!fs.existsSync(CLAUDE_PROJECTS_DIR)) return [];\n\n const results: SessionFileMeta[] = [];\n\n try {\n const projectDirs = fs.readdirSync(CLAUDE_PROJECTS_DIR);\n for (const projectDir of projectDirs) {\n const projectPath = path.join(CLAUDE_PROJECTS_DIR, projectDir);\n try {\n const stat = fs.statSync(projectPath);\n if (!stat.isDirectory()) continue;\n\n const files = fs.readdirSync(projectPath).filter((f) => f.endsWith('.jsonl'));\n for (const file of files) {\n const filePath = path.join(projectPath, file);\n try {\n const fstat = fs.statSync(filePath);\n results.push({\n filePath,\n mtimeMs: fstat.mtimeMs,\n sessionId: path.basename(file, '.jsonl'),\n projectDir,\n });\n } catch {\n // skip unreadable files\n }\n }\n } catch {\n // skip unreadable dirs\n }\n }\n } catch {\n return [];\n }\n\n return results.sort((a, b) => b.mtimeMs - a.mtimeMs);\n}\n\n/**\n * Return the path to the most recently modified session JSONL file,\n * optionally filtered to the given session ID.\n */\nexport function findSessionFile(sessionId?: string): string | null {\n const files = listSessionFiles();\n if (files.length === 0) return null;\n\n if (sessionId) {\n const match = files.find((f) => f.sessionId === sessionId);\n return match?.filePath ?? null;\n }\n\n return files[0]?.filePath ?? null;\n}\n\n/**\n * Parse a session JSONL file and aggregate token usage across all requests.\n * Gracefully skips malformed lines.\n */\nexport function readSessionUsage(sessionFilePath: string): SessionTokenUsage {\n const result: SessionTokenUsage = {\n inputTokens: 0,\n outputTokens: 0,\n cacheCreationTokens: 0,\n cacheReadTokens: 0,\n requestCount: 0,\n };\n\n if (!fs.existsSync(sessionFilePath)) return result;\n\n let content: string;\n try {\n content = fs.readFileSync(sessionFilePath, 'utf-8');\n } catch {\n return result;\n }\n\n const lines = content.trim().split('\\n').filter(Boolean);\n\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as Record<string, unknown>;\n\n // Support both top-level usage and nested message.usage\n const usage =\n (entry.usage as Record<string, number> | undefined) ??\n ((entry.message as Record<string, unknown> | undefined)?.usage as\n | Record<string, number>\n | undefined);\n\n if (!usage) continue;\n\n const isAssistant =\n entry.type === 'assistant' ||\n (entry.message as Record<string, unknown> | undefined)?.role === 'assistant';\n\n if (isAssistant) {\n result.inputTokens += usage.input_tokens ?? 0;\n result.outputTokens += usage.output_tokens ?? 0;\n result.cacheCreationTokens += usage.cache_creation_input_tokens ?? 0;\n result.cacheReadTokens += usage.cache_read_input_tokens ?? 0;\n result.requestCount++;\n }\n } catch {\n // skip malformed lines\n }\n }\n\n return result;\n}\n\n/**\n * Derive a human-readable project name from the project directory name\n * (e.g. \"-Users-alice-code-myapp\" → \"myapp\").\n */\nexport function projectNameFromDir(projectDir: string): string {\n const parts = projectDir.split('-').filter(Boolean);\n return parts[parts.length - 1] ?? projectDir;\n}\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport {\n readAllEvents,\n aggregateStats,\n getReadsFilePath,\n type FileStats,\n} from '../watcher/session-store.js';\nimport {\n findSessionFile,\n readSessionUsage,\n type SessionTokenUsage,\n} from '../watcher/session-reader.js';\nimport { MODEL_PRICING } from '../shared/models.js';\nimport type { ClaudeModel } from '../shared/types.js';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction fmtNum(n: number): string {\n return n.toLocaleString();\n}\n\nfunction fmtCost(tokens: number, model: ClaudeModel): string {\n const p = MODEL_PRICING[model];\n const cost = (tokens / 1_000_000) * p.inputPerMillion;\n return `$${cost.toFixed(4)}`;\n}\n\nfunction shortPath(filePath: string): string {\n const parts = filePath.split(path.sep);\n if (parts.length <= 3) return filePath;\n return '…/' + parts.slice(-3).join('/');\n}\n\nfunction padEnd(str: string, len: number): string {\n return str.length >= len ? str.slice(0, len) : str + ' '.repeat(len - str.length);\n}\n\nfunction padStart(str: string, len: number): string {\n return str.length >= len ? str.slice(0, len) : ' '.repeat(len - str.length) + str;\n}\n\n// ─── Dashboard state ──────────────────────────────────────────────────────────\n\ninterface DashboardState {\n fileStats: FileStats[];\n usage: SessionTokenUsage;\n sessionFile: string | null;\n lastUpdated: Date;\n tickCount: number;\n}\n\n// ─── Sub-components ───────────────────────────────────────────────────────────\n\nfunction Spinner({ tick }: { tick: number }): React.ReactElement {\n const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n return <Text color=\"cyan\">{frames[tick % frames.length]}</Text>;\n}\n\nfunction SectionTitle({ children }: { children: string }): React.ReactElement {\n return (\n <Box marginBottom={0}>\n <Text bold underline color=\"white\">\n {children}\n </Text>\n </Box>\n );\n}\n\nfunction UsagePanel({\n usage,\n model,\n}: {\n usage: SessionTokenUsage;\n model: ClaudeModel;\n}): React.ReactElement {\n const totalBillable = usage.inputTokens + usage.outputTokens;\n const cacheHitPct =\n usage.inputTokens > 0\n ? ((usage.cacheReadTokens / usage.inputTokens) * 100).toFixed(1)\n : '0.0';\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <SectionTitle>Token Usage</SectionTitle>\n <Box>\n <Text dimColor>{' Input: '}</Text>\n <Text color=\"yellow\">{fmtNum(usage.inputTokens)}</Text>\n {usage.cacheReadTokens > 0 && (\n <Text dimColor>{` (${fmtNum(usage.cacheReadTokens)} from cache, ${cacheHitPct}% hit)`}</Text>\n )}\n </Box>\n <Box>\n <Text dimColor>{' Output: '}</Text>\n <Text color=\"green\">{fmtNum(usage.outputTokens)}</Text>\n </Box>\n <Box>\n <Text dimColor>{' Cache writes: '}</Text>\n <Text color=\"cyan\">{fmtNum(usage.cacheCreationTokens)}</Text>\n </Box>\n <Box>\n <Text dimColor>{' Requests: '}</Text>\n <Text>{usage.requestCount}</Text>\n </Box>\n <Box>\n <Text dimColor>{' Estimated cost: '}</Text>\n <Text color=\"magenta\">{fmtCost(totalBillable, model)}</Text>\n </Box>\n </Box>\n );\n}\n\nfunction FileTable({ stats }: { stats: FileStats[] }): React.ReactElement {\n const COL_NUM = 4;\n const COL_READS = 6;\n const COL_FILE = 55;\n\n if (stats.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <SectionTitle>Files Read</SectionTitle>\n <Text dimColor>\n {' No file reads tracked yet.\\n Install hooks first: '}\n <Text color=\"cyan\">claudectx optimize --hooks</Text>\n </Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <SectionTitle>{`Files Read (${stats.length} unique)`}</SectionTitle>\n <Box>\n <Text dimColor>{padStart('#', COL_NUM) + ' '}</Text>\n <Text dimColor>{padEnd('File', COL_FILE) + ' '}</Text>\n <Text dimColor>{padStart('Reads', COL_READS)}</Text>\n </Box>\n {stats.slice(0, 18).map((s, i) => (\n <Box key={s.filePath}>\n <Text dimColor>{padStart(String(i + 1), COL_NUM) + ' '}</Text>\n <Text>{padEnd(shortPath(s.filePath), COL_FILE) + ' '}</Text>\n <Text color={s.readCount >= 3 ? 'yellow' : 'white'}>\n {padStart(String(s.readCount), COL_READS)}\n </Text>\n </Box>\n ))}\n {stats.length > 18 && (\n <Text dimColor>{` … and ${stats.length - 18} more`}</Text>\n )}\n </Box>\n );\n}\n\n// ─── Main Dashboard ───────────────────────────────────────────────────────────\n\ninterface DashboardProps {\n model?: ClaudeModel;\n sessionId?: string;\n}\n\nexport function Dashboard({\n model = 'claude-sonnet-4-6',\n sessionId,\n}: DashboardProps): React.ReactElement {\n const { exit } = useApp();\n\n const [state, setState] = useState<DashboardState>({\n fileStats: [],\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n cacheCreationTokens: 0,\n cacheReadTokens: 0,\n requestCount: 0,\n },\n sessionFile: null,\n lastUpdated: new Date(),\n tickCount: 0,\n });\n\n const refresh = useCallback(() => {\n const events = readAllEvents();\n const fileStats = aggregateStats(events);\n\n const sessionFile = sessionId\n ? findSessionFile(sessionId)\n : findSessionFile();\n\n const usage = sessionFile\n ? readSessionUsage(sessionFile)\n : {\n inputTokens: 0,\n outputTokens: 0,\n cacheCreationTokens: 0,\n cacheReadTokens: 0,\n requestCount: 0,\n };\n\n setState((prev) => ({\n fileStats,\n usage,\n sessionFile,\n lastUpdated: new Date(),\n tickCount: prev.tickCount + 1,\n }));\n }, [sessionId]);\n\n useEffect(() => {\n refresh();\n\n // Poll every 2s\n const interval = setInterval(refresh, 2000);\n\n // Also react instantly when the reads file changes\n const readsFile = getReadsFilePath();\n let watcher: fs.FSWatcher | null = null;\n const tryWatch = () => {\n if (fs.existsSync(readsFile)) {\n try {\n watcher = fs.watch(readsFile, () => refresh());\n } catch {\n /* ignore */\n }\n }\n };\n tryWatch();\n // Retry watcher setup after 3s in case file doesn't exist yet\n const watchRetry = setTimeout(tryWatch, 3000);\n\n return () => {\n clearInterval(interval);\n clearTimeout(watchRetry);\n watcher?.close();\n };\n }, [refresh]);\n\n // Spinner tick\n useEffect(() => {\n const ticker = setInterval(() => {\n setState((prev) => ({ ...prev, tickCount: prev.tickCount + 1 }));\n }, 100);\n return () => clearInterval(ticker);\n }, []);\n\n useInput((input, key) => {\n if (input === 'q' || input === 'Q' || key.escape) {\n exit();\n }\n if (input === 'r' || input === 'R') {\n refresh();\n }\n });\n\n const { fileStats, usage, sessionFile, lastUpdated, tickCount } = state;\n\n return (\n <Box flexDirection=\"column\" paddingX={1} paddingY={0}>\n {/* ── Header ── */}\n <Box marginBottom={1}>\n <Spinner tick={tickCount} />\n <Text bold color=\"cyan\">\n {' claudectx watch'}\n </Text>\n <Text dimColor>\n {' — Live Session Monitor — '}\n {lastUpdated.toLocaleTimeString()}\n </Text>\n {sessionFile && (\n <Text dimColor>\n {' — '}\n {path.basename(sessionFile, '.jsonl').slice(0, 8)}\n {'…'}\n </Text>\n )}\n {!sessionFile && (\n <Text dimColor>{' — no session file found'}</Text>\n )}\n </Box>\n\n {/* ── Token usage ── */}\n <UsagePanel usage={usage} model={model} />\n\n {/* ── File table ── */}\n <FileTable stats={fileStats} />\n\n {/* ── Footer ── */}\n <Box marginTop={1}>\n <Text dimColor>\n {'Press '}\n </Text>\n <Text bold>q</Text>\n <Text dimColor>{' to quit • '}</Text>\n <Text bold>r</Text>\n <Text dimColor>{' to refresh • Polls every 2s'}</Text>\n </Box>\n </Box>\n );\n}\n","/**\n * Smart symbol extractor — finds and returns just the code block for a named\n * symbol (function / class / interface / type) instead of the whole file.\n *\n * Uses regex-based extraction (no native tree-sitter required).\n * Supports TypeScript, JavaScript, and Python out of the box; falls back to\n * line-range extraction for other languages.\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { countTokens } from '../analyzer/tokenizer.js';\n\nexport type SymbolType = 'function' | 'class' | 'interface' | 'type' | 'variable' | 'unknown';\n\nexport interface ExtractedSymbol {\n name: string;\n type: SymbolType;\n filePath: string;\n startLine: number; // 1-based\n endLine: number; // 1-based\n content: string;\n tokenCount: number;\n language: Language;\n}\n\nexport interface LineRangeResult {\n filePath: string;\n startLine: number;\n endLine: number;\n content: string;\n tokenCount: number;\n totalLines: number;\n}\n\nexport type Language = 'typescript' | 'javascript' | 'python' | 'other';\n\n// ─── Language detection ────────────────────────────────────────────────────────\n\nexport function detectLanguage(filePath: string): Language {\n const ext = path.extname(filePath).toLowerCase();\n switch (ext) {\n case '.ts':\n case '.tsx':\n return 'typescript';\n case '.js':\n case '.jsx':\n case '.mjs':\n case '.cjs':\n return 'javascript';\n case '.py':\n return 'python';\n default:\n return 'other';\n }\n}\n\n// ─── Symbol patterns ──────────────────────────────────────────────────────────\n\ninterface SymbolPattern {\n pattern: RegExp;\n type: SymbolType;\n}\n\nconst TS_JS_PATTERNS: SymbolPattern[] = [\n // export async function name / export function name / function name\n { pattern: /^(?:export\\s+)?(?:async\\s+)?function\\s+(\\w+)/, type: 'function' },\n // export default function name\n { pattern: /^export\\s+default\\s+(?:async\\s+)?function\\s+(\\w+)?/, type: 'function' },\n // const/let/var name = (params) => / async (params) =>\n { pattern: /^(?:export\\s+)?(?:const|let|var)\\s+(\\w+)\\s*=\\s*(?:async\\s+)?(?:[(][^)]*[)]|\\w+)\\s*=>/, type: 'function' },\n // const/let name = function\n { pattern: /^(?:export\\s+)?(?:const|let|var)\\s+(\\w+)\\s*=\\s*(?:async\\s+)?function/, type: 'function' },\n // export abstract class / export class / class\n { pattern: /^(?:export\\s+)?(?:abstract\\s+)?class\\s+(\\w+)/, type: 'class' },\n // export interface / interface\n { pattern: /^(?:export\\s+)?interface\\s+(\\w+)/, type: 'interface' },\n // export type Name = / type Name =\n { pattern: /^(?:export\\s+)?type\\s+(\\w+)\\s*(?:<[^>]*>)?\\s*=/, type: 'type' },\n // export enum / enum\n { pattern: /^(?:export\\s+)?(?:const\\s+)?enum\\s+(\\w+)/, type: 'type' },\n // export const NAME (capital-snake — treat as variable)\n { pattern: /^(?:export\\s+)?const\\s+([A-Z_][A-Z0-9_]+)\\s*=/, type: 'variable' },\n // export const name (lowercase)\n { pattern: /^(?:export\\s+)?(?:const|let|var)\\s+(\\w+)\\s*(?::\\s*\\S+)?\\s*=/, type: 'variable' },\n];\n\nconst PYTHON_PATTERNS: SymbolPattern[] = [\n { pattern: /^(?:async\\s+)?def\\s+(\\w+)\\s*\\(/, type: 'function' },\n { pattern: /^class\\s+(\\w+)(?:\\s*[(:]|$)/, type: 'class' },\n { pattern: /^([A-Z_][A-Z0-9_]+)\\s*=/, type: 'variable' },\n];\n\n// ─── Find a symbol in a file ──────────────────────────────────────────────────\n\n/**\n * Locate a named symbol in a file and return its start/end lines.\n * Returns null if the symbol cannot be found.\n */\nexport function findSymbol(filePath: string, symbolName: string): ExtractedSymbol | null {\n if (!fs.existsSync(filePath)) return null;\n\n const content = fs.readFileSync(filePath, 'utf-8');\n const lines = content.split('\\n');\n const lang = detectLanguage(filePath);\n const patterns = lang === 'python' ? PYTHON_PATTERNS : TS_JS_PATTERNS;\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n\n for (const { pattern, type } of patterns) {\n const match = line.match(pattern);\n if (!match) continue;\n\n const capturedName = match[1];\n if (!capturedName || capturedName !== symbolName) continue;\n\n // Found the start — now find the end\n const startLine = i + 1; // convert to 1-based\n const endLine =\n lang === 'python'\n ? findPythonBlockEnd(lines, i)\n : findBraceBlockEnd(lines, i);\n\n const extracted = lines.slice(i, endLine).join('\\n');\n\n return {\n name: capturedName,\n type,\n filePath,\n startLine,\n endLine,\n content: extracted,\n tokenCount: countTokens(extracted),\n language: lang,\n };\n }\n }\n\n return null;\n}\n\n// ─── Block end detection ──────────────────────────────────────────────────────\n\n/**\n * Find the end of a JS/TS block by counting balanced `{}`.\n * Returns the end line index (exclusive, 0-based) — use `.slice(start, end)`.\n */\nfunction findBraceBlockEnd(lines: string[], startIdx: number): number {\n let depth = 0;\n let foundOpenBrace = false;\n\n for (let i = startIdx; i < lines.length; i++) {\n const line = lines[i];\n for (const ch of line) {\n if (ch === '{') {\n depth++;\n foundOpenBrace = true;\n } else if (ch === '}') {\n depth--;\n if (foundOpenBrace && depth === 0) {\n return i + 1; // end (exclusive)\n }\n }\n }\n }\n\n // No matching brace found — return up to 60 lines as fallback\n return Math.min(startIdx + 60, lines.length);\n}\n\n/**\n * Find the end of a Python block by tracking indentation level.\n */\nfunction findPythonBlockEnd(lines: string[], startIdx: number): number {\n const baseLine = lines[startIdx];\n const baseIndent = baseLine.length - baseLine.trimStart().length;\n\n for (let i = startIdx + 1; i < lines.length; i++) {\n const line = lines[i];\n if (line.trim() === '' || line.trim().startsWith('#')) continue; // skip blanks/comments\n\n const indent = line.length - line.trimStart().length;\n if (indent <= baseIndent) {\n return i; // end (exclusive)\n }\n }\n\n return lines.length; // end of file\n}\n\n// ─── Line-range extraction ────────────────────────────────────────────────────\n\n/**\n * Extract a specific line range from a file (1-based, inclusive).\n * Adds a small context buffer above and below when requested.\n */\nexport function extractLineRange(\n filePath: string,\n startLine: number,\n endLine: number,\n contextLines = 0\n): LineRangeResult | null {\n if (!fs.existsSync(filePath)) return null;\n\n const allLines = fs.readFileSync(filePath, 'utf-8').split('\\n');\n const totalLines = allLines.length;\n\n const from = Math.max(0, startLine - 1 - contextLines); // to 0-based\n const to = Math.min(totalLines, endLine + contextLines); // exclusive\n\n const extracted = allLines.slice(from, to).join('\\n');\n\n return {\n filePath,\n startLine: from + 1,\n endLine: to,\n content: extracted,\n tokenCount: countTokens(extracted),\n totalLines,\n };\n}\n\n// ─── Token-aware full-file read ───────────────────────────────────────────────\n\nexport interface SmartReadResult {\n content: string;\n tokenCount: number;\n filePath: string;\n startLine: number;\n endLine: number;\n totalLines: number;\n truncated: boolean;\n symbolName?: string;\n}\n\nconst MAX_FULL_FILE_TOKENS = 8_000;\n\n/**\n * High-level smart read:\n * 1. If `symbol` given → extract just that symbol\n * 2. If `startLine`/`endLine` given → extract that range\n * 3. Otherwise → return full file (truncated at 8K tokens if huge)\n */\nexport function smartRead(\n filePath: string,\n symbol?: string,\n startLine?: number,\n endLine?: number,\n contextLines = 3\n): SmartReadResult {\n if (!fs.existsSync(filePath)) {\n throw new Error(`File not found: ${filePath}`);\n }\n\n if (symbol) {\n const extracted = findSymbol(filePath, symbol);\n if (extracted) {\n return {\n content: extracted.content,\n tokenCount: extracted.tokenCount,\n filePath,\n startLine: extracted.startLine,\n endLine: extracted.endLine,\n totalLines: fs.readFileSync(filePath, 'utf-8').split('\\n').length,\n truncated: false,\n symbolName: symbol,\n };\n }\n // Symbol not found — fall through to line range or full read\n }\n\n if (startLine !== undefined && endLine !== undefined) {\n const result = extractLineRange(filePath, startLine, endLine, contextLines);\n if (result) {\n return { ...result, truncated: false };\n }\n }\n\n // Full file read with token cap\n const fullContent = fs.readFileSync(filePath, 'utf-8');\n const allLines = fullContent.split('\\n');\n const totalLines = allLines.length;\n const fullTokens = countTokens(fullContent);\n\n if (fullTokens <= MAX_FULL_FILE_TOKENS) {\n return {\n content: fullContent,\n tokenCount: fullTokens,\n filePath,\n startLine: 1,\n endLine: totalLines,\n totalLines,\n truncated: false,\n };\n }\n\n // Truncate to first N lines that fit within the token budget\n let accumulated = '';\n let lastLine = 0;\n for (let i = 0; i < allLines.length; i++) {\n const next = accumulated + allLines[i] + '\\n';\n if (countTokens(next) > MAX_FULL_FILE_TOKENS) break;\n accumulated = next;\n lastLine = i + 1;\n }\n\n return {\n content:\n accumulated +\n `\\n\\n// ... file truncated at ${lastLine}/${totalLines} lines (token budget).` +\n `\\n// Use smart_read with a symbol name or line range to read more.`,\n tokenCount: countTokens(accumulated),\n filePath,\n startLine: 1,\n endLine: lastLine,\n totalLines,\n truncated: true,\n };\n}\n","/**\n * In-memory symbol index built by scanning source files in a project.\n * Powers the `search_symbols` MCP tool.\n *\n * Supports TypeScript, JavaScript, and Python. Built lazily on first query.\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { glob } from 'glob';\nimport { detectLanguage, type SymbolType } from './smart-reader.js';\n\nexport interface SymbolEntry {\n name: string;\n type: SymbolType;\n filePath: string;\n lineStart: number; // 1-based\n signature: string; // first line of the declaration\n}\n\n// ─── Index builder ────────────────────────────────────────────────────────────\n\nconst TS_JS_EXTRACTORS: Array<{ pattern: RegExp; type: SymbolType }> = [\n { pattern: /^(?:export\\s+)?(?:async\\s+)?function\\s+(\\w+)/, type: 'function' },\n { pattern: /^export\\s+default\\s+(?:async\\s+)?function\\s+(\\w+)/, type: 'function' },\n { pattern: /^(?:export\\s+)?(?:const|let|var)\\s+(\\w+)\\s*=\\s*(?:async\\s+)?(?:[(][^)]*[)]|\\w+)\\s*=>/, type: 'function' },\n { pattern: /^(?:export\\s+)?(?:const|let|var)\\s+(\\w+)\\s*=\\s*(?:async\\s+)?function/, type: 'function' },\n { pattern: /^(?:export\\s+)?(?:abstract\\s+)?class\\s+(\\w+)/, type: 'class' },\n { pattern: /^(?:export\\s+)?interface\\s+(\\w+)/, type: 'interface' },\n { pattern: /^(?:export\\s+)?type\\s+(\\w+)\\s*(?:<[^>]*>)?\\s*=/, type: 'type' },\n { pattern: /^(?:export\\s+)?(?:const\\s+)?enum\\s+(\\w+)/, type: 'type' },\n { pattern: /^(?:export\\s+)?(?:const|let|var)\\s+(\\w+)\\s*(?::\\s*\\S+)?\\s*=/, type: 'variable' },\n];\n\nconst PYTHON_EXTRACTORS: Array<{ pattern: RegExp; type: SymbolType }> = [\n { pattern: /^(?:async\\s+)?def\\s+(\\w+)\\s*\\(/, type: 'function' },\n { pattern: /^class\\s+(\\w+)(?:\\s*[(:]|$)/, type: 'class' },\n { pattern: /^([A-Z_][A-Z0-9_]+)\\s*=/, type: 'variable' },\n];\n\nfunction extractSymbolsFromFile(filePath: string): SymbolEntry[] {\n const lang = detectLanguage(filePath);\n if (lang === 'other') return [];\n\n let content: string;\n try {\n content = fs.readFileSync(filePath, 'utf-8');\n } catch {\n return [];\n }\n\n const lines = content.split('\\n');\n const extractors = lang === 'python' ? PYTHON_EXTRACTORS : TS_JS_EXTRACTORS;\n const results: SymbolEntry[] = [];\n const seenNames = new Set<string>();\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('#')) continue;\n\n for (const { pattern, type } of extractors) {\n const match = trimmed.match(pattern);\n if (!match?.[1]) continue;\n const name = match[1];\n if (seenNames.has(name)) continue; // deduplicate within file\n seenNames.add(name);\n\n results.push({\n name,\n type,\n filePath,\n lineStart: i + 1,\n signature: lines[i].trimEnd(),\n });\n break; // only one pattern per line\n }\n }\n\n return results;\n}\n\n// ─── SymbolIndex class ────────────────────────────────────────────────────────\n\nconst SOURCE_GLOBS = [\n '**/*.ts',\n '**/*.tsx',\n '**/*.js',\n '**/*.jsx',\n '**/*.mjs',\n '**/*.py',\n];\n\nconst IGNORE_DIRS = [\n 'node_modules/**',\n 'dist/**',\n 'build/**',\n '.git/**',\n '__pycache__/**',\n '*.min.js',\n '**/*.d.ts',\n];\n\nexport class SymbolIndex {\n private entries: SymbolEntry[] = [];\n private builtFor: string | null = null;\n private buildInProgress = false;\n\n /** Build the index for a project root. Subsequent calls are no-ops if root matches. */\n async build(projectRoot: string): Promise<{ fileCount: number; symbolCount: number }> {\n if (this.builtFor === projectRoot) {\n return { fileCount: 0, symbolCount: this.entries.length };\n }\n if (this.buildInProgress) {\n // Wait briefly and return current state\n await new Promise((r) => setTimeout(r, 200));\n return { fileCount: 0, symbolCount: this.entries.length };\n }\n\n this.buildInProgress = true;\n this.entries = [];\n\n let files: string[] = [];\n try {\n files = await glob(SOURCE_GLOBS.map((g) => path.join(projectRoot, g)), {\n ignore: IGNORE_DIRS.map((g) => path.join(projectRoot, g)),\n absolute: true,\n });\n } catch {\n /* glob failure — proceed with empty */\n }\n\n for (const file of files) {\n const symbols = extractSymbolsFromFile(file);\n this.entries.push(...symbols);\n }\n\n this.builtFor = projectRoot;\n this.buildInProgress = false;\n\n return { fileCount: files.length, symbolCount: this.entries.length };\n }\n\n /** Rebuild the index (e.g. after file changes). */\n async rebuild(projectRoot: string): Promise<{ fileCount: number; symbolCount: number }> {\n this.builtFor = null;\n return this.build(projectRoot);\n }\n\n /**\n * Search for symbols matching the query.\n *\n * @param query - Partial or full symbol name (case-insensitive substring match)\n * @param type - Optional filter by symbol type\n * @param pathFilter - Optional substring filter on the file path\n * @param limit - Max results to return (default 20)\n */\n search(\n query: string,\n type?: SymbolType | 'all',\n pathFilter?: string,\n limit = 20\n ): SymbolEntry[] {\n const q = query.toLowerCase();\n return this.entries\n .filter((e) => {\n if (!e.name.toLowerCase().includes(q)) return false;\n if (type && type !== 'all' && e.type !== type) return false;\n if (pathFilter && !e.filePath.includes(pathFilter)) return false;\n return true;\n })\n .slice(0, limit);\n }\n\n /** Total symbol count. */\n get size(): number {\n return this.entries.length;\n }\n\n /** Whether the index has been built. */\n get isReady(): boolean {\n return this.builtFor !== null;\n }\n}\n\n// Shared singleton used by the MCP server\nexport const globalIndex = new SymbolIndex();\n","/**\n * claudectx MCP server — provides symbol-level file reading to Claude Code.\n *\n * Tools:\n * smart_read — read a named symbol (function/class) or line range from a file\n * search_symbols — full-text search for symbols across the indexed codebase\n * index_project — (re)build the symbol index for a given project root\n */\nimport * as path from 'path';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { smartRead } from './smart-reader.js';\nimport { globalIndex } from './symbol-index.js';\n\n// ─── Tool definitions ─────────────────────────────────────────────────────────\n\nconst TOOLS = [\n {\n name: 'smart_read',\n description:\n 'Read a specific symbol (function, class, interface) or line range from a file ' +\n 'instead of the whole file. Saves 60-90% of tokens on large files. ' +\n 'Falls back to full file if symbol is not found (capped at 8K tokens).',\n inputSchema: {\n type: 'object',\n properties: {\n file: {\n type: 'string',\n description: 'Absolute or relative path to the file to read.',\n },\n symbol: {\n type: 'string',\n description:\n 'Name of the function, class, interface, or type to extract. ' +\n 'If provided, only that symbol block is returned.',\n },\n start_line: {\n type: 'number',\n description: 'Start line (1-based, inclusive). Use with end_line.',\n },\n end_line: {\n type: 'number',\n description: 'End line (1-based, inclusive). Use with start_line.',\n },\n context_lines: {\n type: 'number',\n description: 'Extra lines of context above/below line range (default 3).',\n },\n },\n required: ['file'],\n },\n },\n {\n name: 'search_symbols',\n description:\n 'Search for functions, classes, variables, and interfaces by name across the ' +\n 'indexed codebase. Returns file paths and line numbers. ' +\n 'Run index_project first to populate the index.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Symbol name to search for (substring match, case-insensitive).',\n },\n type: {\n type: 'string',\n enum: ['function', 'class', 'interface', 'type', 'variable', 'all'],\n description: 'Filter by symbol type (default: all).',\n },\n path_filter: {\n type: 'string',\n description: 'Only include results from files whose path contains this string.',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default 20).',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'index_project',\n description:\n 'Build or rebuild the symbol index for a project directory. ' +\n 'Required before using search_symbols. Takes a few seconds for large projects.',\n inputSchema: {\n type: 'object',\n properties: {\n project_root: {\n type: 'string',\n description: 'Absolute path to the project root (default: cwd).',\n },\n rebuild: {\n type: 'boolean',\n description: 'Force a full rebuild even if the index is already built.',\n },\n },\n required: [],\n },\n },\n];\n\n// ─── Tool handlers ────────────────────────────────────────────────────────────\n\ninterface SmartReadArgs {\n file: string;\n symbol?: string;\n start_line?: number;\n end_line?: number;\n context_lines?: number;\n}\n\ninterface SearchSymbolsArgs {\n query: string;\n type?: 'function' | 'class' | 'interface' | 'type' | 'variable' | 'all';\n path_filter?: string;\n limit?: number;\n}\n\ninterface IndexProjectArgs {\n project_root?: string;\n rebuild?: boolean;\n}\n\nfunction handleSmartRead(args: SmartReadArgs): string {\n const filePath = path.resolve(args.file);\n const result = smartRead(\n filePath,\n args.symbol,\n args.start_line,\n args.end_line,\n args.context_lines ?? 3\n );\n\n const header = [\n `// File: ${result.filePath}`,\n result.symbolName ? `// Symbol: ${result.symbolName} (lines ${result.startLine}–${result.endLine})` : `// Lines: ${result.startLine}–${result.endLine} of ${result.totalLines}`,\n `// Tokens: ${result.tokenCount}${result.truncated ? ' (truncated — file is large)' : ''}`,\n '',\n ].join('\\n');\n\n return header + result.content;\n}\n\nasync function handleSearchSymbols(args: SearchSymbolsArgs): Promise<string> {\n if (!globalIndex.isReady) {\n return (\n 'Index not built yet. Call index_project first.\\n' +\n `Example: index_project({ \"project_root\": \"${process.cwd()}\" })`\n );\n }\n\n const results = globalIndex.search(\n args.query,\n args.type ?? 'all',\n args.path_filter,\n args.limit ?? 20\n );\n\n if (results.length === 0) {\n return `No symbols found matching \"${args.query}\".`;\n }\n\n const lines = [\n `Found ${results.length} symbol(s) matching \"${args.query}\":`,\n '',\n ];\n\n for (let i = 0; i < results.length; i++) {\n const r = results[i];\n const rel = path.relative(process.cwd(), r.filePath);\n lines.push(`${i + 1}. [${r.type}] ${r.name}`);\n lines.push(` ${rel}:${r.lineStart}`);\n lines.push(` ${r.signature.trim()}`);\n lines.push('');\n }\n\n lines.push(\n `Tip: Use smart_read({ \"file\": \"<path>\", \"symbol\": \"<name>\" }) to read a specific symbol.`\n );\n\n return lines.join('\\n');\n}\n\nasync function handleIndexProject(args: IndexProjectArgs): Promise<string> {\n const projectRoot = args.project_root ? path.resolve(args.project_root) : process.cwd();\n\n const fn = args.rebuild\n ? () => globalIndex.rebuild(projectRoot)\n : () => globalIndex.build(projectRoot);\n\n const { fileCount, symbolCount } = await fn();\n\n if (fileCount === 0 && globalIndex.isReady) {\n return `Index already built: ${globalIndex.size} symbols. Pass rebuild: true to force re-index.`;\n }\n\n return (\n `Index built for: ${projectRoot}\\n` +\n `Files scanned: ${fileCount}\\n` +\n `Symbols indexed: ${symbolCount}\\n\\n` +\n `Use search_symbols({ \"query\": \"<name>\" }) to find symbols.`\n );\n}\n\n// ─── Server bootstrap ─────────────────────────────────────────────────────────\n\nexport async function startMcpServer(): Promise<void> {\n const server = new Server(\n { name: 'claudectx', version: '0.1.0' },\n { capabilities: { tools: {} } }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n let text: string;\n\n switch (name) {\n case 'smart_read':\n text = handleSmartRead(args as SmartReadArgs);\n break;\n case 'search_symbols':\n text = await handleSearchSymbols(args as SearchSymbolsArgs);\n break;\n case 'index_project':\n text = await handleIndexProject(args as IndexProjectArgs);\n break;\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n\n return { content: [{ type: 'text', text }] };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n content: [{ type: 'text', text: `Error: ${message}` }],\n isError: true,\n };\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n // Log to stderr so it doesn't pollute the MCP stdio protocol\n process.stderr.write('[claudectx mcp] Server started (stdio)\\n');\n}\n","import { Command } from 'commander';\nimport { analyzeCommand } from './commands/analyze.js';\nimport { optimizeCommand } from './commands/optimize.js';\nimport { watchCommand } from './commands/watch.js';\nimport { mcpCommand } from './commands/mcp.js';\nimport { compressCommand } from './commands/compress.js';\nimport { reportCommand } from './commands/report.js';\n\n// Version injected at build time by tsup via package.json\nconst VERSION = '1.0.0';\nconst DESCRIPTION = 'Reduce Claude Code token usage by up to 80%. Context analyzer, auto-optimizer, live dashboard, and smart MCP tools.';\n\nconst program = new Command();\n\nprogram\n .name('claudectx')\n .description(DESCRIPTION)\n .version(VERSION);\n\n// ─── analyze ──────────────────────────────────────────────────────────────────\nprogram\n .command('analyze')\n .alias('a')\n .description('Analyze token usage in the current Claude Code project')\n .option('-p, --path <path>', 'Path to project directory (default: cwd)')\n .option('-j, --json', 'Output raw JSON (for scripting)')\n .option('-m, --model <model>', 'Claude model to estimate costs for (haiku|sonnet|opus)', 'sonnet')\n .option('-w, --watch', 'Re-run analysis on CLAUDE.md / MEMORY.md changes')\n .action(async (options) => {\n await analyzeCommand(options);\n });\n\n// ─── optimize ─────────────────────────────────────────────────────────────────\nprogram\n .command('optimize')\n .alias('o')\n .description('Auto-fix token waste issues in CLAUDE.md, .claudeignore, and hooks')\n .option('-p, --path <path>', 'Path to project directory (default: cwd)')\n .option('--apply', 'Apply all fixes without prompting')\n .option('--dry-run', 'Preview changes without applying')\n .option('--claudemd', 'Only optimize CLAUDE.md (split into @files)')\n .option('--ignorefile', 'Only generate .claudeignore')\n .option('--cache', 'Only fix cache-busting content')\n .option('--hooks', 'Only install session hooks')\n .option('--api-key <key>', 'Anthropic API key (for AI-powered CLAUDE.md rewriting)')\n .action(async (options) => {\n await optimizeCommand(options);\n });\n\n// ─── watch ────────────────────────────────────────────────────────────────────\nprogram\n .command('watch')\n .alias('w')\n .description('Live token-usage dashboard — tracks files read and session cost in real time')\n .option('--session <id>', 'Watch a specific session ID (default: most recent)')\n .option('-m, --model <model>', 'Model for cost estimates (haiku|sonnet|opus)', 'sonnet')\n .option('--log-stdin', 'Read hook JSON from stdin and log the file path (called by Claude Code hook)')\n .option('--clear', 'Clear the session file-read log and exit')\n .action(async (options) => {\n await watchCommand(options);\n });\n\n// ─── mcp ──────────────────────────────────────────────────────────────────────\nprogram\n .command('mcp')\n .description('Start the smart MCP server — symbol-level file reading for Claude Code')\n .option('-p, --path <path>', 'Project root (default: cwd)')\n .option('--port <port>', 'HTTP transport port (stdio is default; HTTP coming soon)')\n .option('--install', 'Add server to .claude/settings.json and exit')\n .action(async (options) => {\n await mcpCommand(options);\n });\n\n// ─── compress ─────────────────────────────────────────────────────────────────\nprogram\n .command('compress')\n .alias('c')\n .description('Compress a Claude Code session into a compact MEMORY.md entry')\n .option('-p, --path <path>', 'Project directory (default: cwd)')\n .option('--session <id>', 'Compress specific session ID (default: most recent)')\n .option('--auto', 'Non-interactive mode (for hooks)')\n .option('--prune', 'Also prune old MEMORY.md entries')\n .option('--days <n>', 'Days threshold for pruning (with --prune)', '30')\n .option('--api-key <key>', 'Anthropic API key for AI-powered summarization')\n .action(async (options) => {\n await compressCommand(options);\n });\n\n// ─── report ───────────────────────────────────────────────────────────────────\nprogram\n .command('report')\n .alias('r')\n .description('Show token usage analytics for the last N days')\n .option('-p, --path <path>', 'Project directory (default: cwd)')\n .option('--days <n>', 'Number of days to include', '7')\n .option('--json', 'Machine-readable JSON output')\n .option('--markdown', 'GitHub-flavoured Markdown output')\n .option('-m, --model <model>', 'Claude model for cost estimates (haiku|sonnet|opus)', 'sonnet')\n .action(async (options) => {\n await reportCommand(options);\n });\n\nprogram.parse();\n","import path from 'path';\nimport chalk from 'chalk';\nimport boxen from 'boxen';\nimport Table from 'cli-table3';\nimport { ContextAnalyzer } from '../analyzer/index.js';\nimport { resolveModel } from '../shared/models.js';\nimport { formatCost } from '../analyzer/cost-calculator.js';\nimport type { AnalysisReport, ContextComponent } from '../shared/types.js';\n\ninterface AnalyzeOptions {\n path?: string;\n json?: boolean;\n model?: string;\n watch?: boolean;\n}\n\nfunction statusIcon(component: ContextComponent): string {\n if (component.warnings.length === 0) return chalk.green('✓');\n const hasError = component.warnings.some((w) => w.severity === 'error');\n if (hasError) return chalk.red('✖');\n return chalk.yellow('⚠');\n}\n\nfunction renderReport(report: AnalysisReport): void {\n const contextPct = ((report.totalTokensPerRequest / 200_000) * 100).toFixed(1);\n\n // Header box\n const header = [\n chalk.bold('claudectx — Context Analysis'),\n chalk.dim(`Project: ${report.projectPath}`),\n '',\n `${chalk.bold('Tokens/request:')} ${chalk.cyan(report.totalTokensPerRequest.toLocaleString())} ${chalk.bold('Session cost:')} ${chalk.yellow(formatCost(report.estimatedCostPerSession))}`,\n `${chalk.bold('Model:')} ${report.model} ${chalk.bold('Context used:')} ${contextPct}% of 200K window`,\n ].join('\\n');\n\n process.stdout.write(\n boxen(header, {\n padding: 1,\n borderStyle: 'double',\n borderColor: 'cyan',\n }) + '\\n\\n',\n );\n\n // Component table\n const table = new Table({\n head: [\n chalk.bold('Component'),\n chalk.bold('Tokens'),\n chalk.bold('Cost/req'),\n chalk.bold('Status'),\n ],\n colWidths: [38, 12, 12, 10],\n style: { head: [], border: [] },\n });\n\n for (const c of report.components) {\n table.push([\n c.name,\n c.tokenCount.toLocaleString(),\n formatCost(c.estimatedCostPerRequest),\n statusIcon(c),\n ]);\n }\n\n // Total row\n table.push([\n chalk.bold('TOTAL (per request)'),\n chalk.bold(report.totalTokensPerRequest.toLocaleString()),\n chalk.bold(formatCost(report.components.reduce((s, c) => s + c.estimatedCostPerRequest, 0))),\n '',\n ]);\n\n process.stdout.write(table.toString() + '\\n');\n\n // Warnings\n if (report.warnings.length === 0) {\n process.stdout.write('\\n' + chalk.green('✔ No optimization opportunities found. Looking good!\\n'));\n } else {\n process.stdout.write(\n '\\n' + chalk.yellow(`⚠ ${report.warnings.length} optimization ${report.warnings.length === 1 ? 'opportunity' : 'opportunities'} found:\\n\\n`),\n );\n\n report.warnings.forEach((w, i) => {\n const icon =\n w.severity === 'error' ? chalk.red('✖') : w.severity === 'warning' ? chalk.yellow('⚠') : chalk.blue('ℹ');\n const lineInfo = w.lineNumber ? ` (line ${w.lineNumber})` : '';\n process.stdout.write(` ${chalk.bold(`[${i + 1}]`)} ${icon} ${w.message}${lineInfo}\\n`);\n process.stdout.write(` ${chalk.dim('→')} ${w.suggestion}\\n`);\n if (w.estimatedSavings > 0) {\n process.stdout.write(\n ` ${chalk.dim('→')} Potential savings: ~${w.estimatedSavings.toLocaleString()} tokens/request\\n`,\n );\n }\n process.stdout.write('\\n');\n });\n\n process.stdout.write(\n chalk.dim(\n ` 💡 Run ${chalk.cyan('claudectx optimize')} to fix all issues automatically.\\n` +\n ` 💡 Run ${chalk.cyan('claudectx optimize --dry-run')} to preview changes first.\\n`,\n ) + '\\n',\n );\n }\n\n if (report.potentialSavingsPercent > 0) {\n process.stdout.write(\n chalk.dim(\n ` Potential savings: ${report.potentialSavingsPercent}% (${(report.totalTokensPerRequest - report.optimizedTokensPerRequest).toLocaleString()} tokens)\\n\\n`,\n ),\n );\n }\n\n process.stdout.write(\n chalk.dim(' ⭐ If claudectx saved you money, star the repo: https://github.com/Horilla/claudectx\\n\\n'),\n );\n}\n\nexport async function analyzeCommand(options: AnalyzeOptions): Promise<void> {\n const targetPath = path.resolve(options.path ?? process.cwd());\n const model = resolveModel(options.model ?? 'sonnet');\n const analyzer = new ContextAnalyzer(model);\n\n async function run() {\n try {\n const report = await analyzer.analyze(targetPath);\n\n if (options.json) {\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n return;\n }\n\n renderReport(report);\n } catch (err) {\n process.stderr.write(chalk.red(`Error: ${err instanceof Error ? err.message : String(err)}\\n`));\n process.exit(1);\n }\n }\n\n await run();\n\n if (options.watch) {\n const { watch } = await import('fs');\n process.stderr.write(chalk.dim('Watching for changes (Ctrl+C to stop)...\\n'));\n\n let debounce: ReturnType<typeof setTimeout> | null = null;\n watch(targetPath, { recursive: true }, (_event, filename) => {\n if (!filename?.includes('CLAUDE') && !filename?.includes('MEMORY')) return;\n if (debounce) clearTimeout(debounce);\n debounce = setTimeout(async () => {\n process.stdout.write('\\x1Bc'); // clear terminal\n process.stderr.write(chalk.dim(`Re-analyzing after change to ${filename}...\\n\\n`));\n await run();\n }, 300);\n });\n\n // Keep process alive\n await new Promise(() => {});\n }\n}\n","import { parseContext } from './context-parser.js';\nimport { countTokens } from './tokenizer.js';\nimport {\n detectClaudeMdWarnings,\n detectMemoryWarnings,\n detectReferenceFileWarnings,\n detectMissingIgnoreFile,\n detectNoCachingConfigured,\n detectRedundantContent,\n} from './waste-detector.js';\nimport { sessionCost, calculatePotentialSavings } from './cost-calculator.js';\nimport { calculateCost } from '../shared/models.js';\nimport { BUILTIN_OVERHEAD } from '../shared/constants.js';\nimport type { AnalysisReport, ContextComponent, ClaudeModel, WasteWarning } from '../shared/types.js';\n\nexport class ContextAnalyzer {\n constructor(private readonly model: ClaudeModel) {}\n\n async analyze(projectPath: string): Promise<AnalysisReport> {\n const ctx = parseContext(projectPath);\n const components: ContextComponent[] = [];\n const allWarnings: WasteWarning[] = [];\n\n // Built-in overhead (cannot be reduced)\n components.push({\n name: 'System prompt (built-in)',\n type: 'system-prompt',\n tokenCount: BUILTIN_OVERHEAD.SYSTEM_PROMPT,\n estimatedCostPerRequest: calculateCost(BUILTIN_OVERHEAD.SYSTEM_PROMPT, this.model),\n warnings: [],\n });\n\n components.push({\n name: 'Tool definitions (built-in)',\n type: 'tool-definitions',\n tokenCount: BUILTIN_OVERHEAD.TOOL_DEFINITIONS,\n estimatedCostPerRequest: calculateCost(BUILTIN_OVERHEAD.TOOL_DEFINITIONS, this.model),\n warnings: [],\n });\n\n // MCP schemas\n if (ctx.mcpToolCount > 0) {\n const mcpTokens = ctx.mcpToolCount * BUILTIN_OVERHEAD.MCP_PER_TOOL;\n components.push({\n name: `MCP schemas (${ctx.mcpToolCount} tools)`,\n type: 'mcp-schemas',\n tokenCount: mcpTokens,\n estimatedCostPerRequest: calculateCost(mcpTokens, this.model),\n warnings: [],\n });\n }\n\n // Project CLAUDE.md\n if (ctx.projectClaudeMd) {\n const tokenCount = countTokens(ctx.projectClaudeMd.content);\n const refCount = ctx.referencedFiles.length;\n const warnings = detectClaudeMdWarnings(ctx.projectClaudeMd.content, tokenCount, refCount);\n allWarnings.push(...warnings);\n components.push({\n name: 'CLAUDE.md (project)',\n type: 'claude-md',\n filePath: ctx.projectClaudeMd.filePath,\n tokenCount,\n estimatedCostPerRequest: calculateCost(tokenCount, this.model),\n warnings,\n });\n }\n\n // User CLAUDE.md\n if (ctx.userClaudeMd) {\n const tokenCount = countTokens(ctx.userClaudeMd.content);\n const warnings = detectClaudeMdWarnings(ctx.userClaudeMd.content, tokenCount, 0);\n allWarnings.push(...warnings);\n components.push({\n name: 'CLAUDE.md (user ~/.claude/)',\n type: 'claude-md',\n filePath: ctx.userClaudeMd.filePath,\n tokenCount,\n estimatedCostPerRequest: calculateCost(tokenCount, this.model),\n warnings,\n });\n }\n\n // MEMORY.md\n if (ctx.memoryMd) {\n const tokenCount = countTokens(ctx.memoryMd.content);\n const warnings = detectMemoryWarnings(ctx.memoryMd.content, tokenCount);\n allWarnings.push(...warnings);\n components.push({\n name: 'MEMORY.md',\n type: 'memory',\n filePath: ctx.memoryMd.filePath,\n tokenCount,\n estimatedCostPerRequest: calculateCost(tokenCount, this.model),\n warnings,\n });\n }\n\n // Referenced files\n for (const ref of ctx.referencedFiles) {\n const tokenCount = countTokens(ref.content);\n const warnings = detectReferenceFileWarnings(ref.filePath, ref.content, tokenCount);\n allWarnings.push(...warnings);\n components.push({\n name: `@${ref.referencedAs}`,\n type: 'reference-file',\n filePath: ref.filePath,\n tokenCount,\n estimatedCostPerRequest: calculateCost(tokenCount, this.model),\n warnings,\n });\n }\n\n // Project-level warnings\n const projectRoot = ctx.projectRoot ?? projectPath;\n const missingIgnore = detectMissingIgnoreFile(projectRoot);\n if (missingIgnore) allWarnings.push(missingIgnore);\n\n const noCache = detectNoCachingConfigured(\n projectRoot,\n ctx.projectClaudeMd?.content,\n );\n if (noCache) allWarnings.push(noCache);\n\n const redundant = detectRedundantContent(\n ctx.projectClaudeMd?.content ?? '',\n ctx.memoryMd?.content,\n );\n if (redundant) allWarnings.push(redundant);\n\n // Totals\n const totalTokensPerRequest = components.reduce((s, c) => s + c.tokenCount, 0);\n const totalSavableTokens = allWarnings.reduce((s, w) => s + w.estimatedSavings, 0);\n const costs = sessionCost(totalTokensPerRequest, this.model);\n const savings = calculatePotentialSavings(\n totalTokensPerRequest,\n totalSavableTokens,\n this.model,\n );\n\n return {\n projectPath,\n timestamp: new Date().toISOString(),\n model: this.model,\n components,\n totalTokensPerRequest,\n estimatedCostPerSession: costs.perSession,\n warnings: allWarnings,\n optimizedTokensPerRequest: totalTokensPerRequest - savings.savedTokens,\n potentialSavingsPercent: savings.savedPercent,\n };\n }\n}\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\n\nexport interface ParsedContext {\n projectClaudeMd?: { filePath: string; content: string };\n userClaudeMd?: { filePath: string; content: string };\n memoryMd?: { filePath: string; content: string };\n referencedFiles: Array<{ filePath: string; content: string; referencedAs: string }>;\n mcpToolCount: number;\n projectRoot: string | null;\n}\n\n/** Walk up from cwd looking for CLAUDE.md or .claude/ directory */\nexport function findProjectRoot(startDir: string = process.cwd()): string | null {\n let current = startDir;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n if (\n fs.existsSync(path.join(current, 'CLAUDE.md')) ||\n fs.existsSync(path.join(current, '.claude'))\n ) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) return null; // reached filesystem root\n current = parent;\n }\n}\n\n/** Parse @filename references from CLAUDE.md content */\nfunction extractReferences(content: string): string[] {\n const refs: string[] = [];\n const lines = content.split('\\n');\n for (const line of lines) {\n const match = line.match(/^@(.+)$/);\n if (match) refs.push(match[1].trim());\n }\n return refs;\n}\n\n/** Count MCP tools from .claude/settings.json */\nfunction countMcpTools(settingsPath: string): number {\n try {\n const raw = fs.readFileSync(settingsPath, 'utf-8');\n const settings = JSON.parse(raw);\n const servers = settings?.mcpServers ?? {};\n // Each server contributes ~3-6 tools on average — we can't know exactly without\n // querying the server, so we count registered servers and estimate 3 tools each\n return Object.keys(servers).length * 3;\n } catch {\n return 0;\n }\n}\n\n/** Read a file safely, returning null if not found */\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Parse all Claude Code context files for a project.\n */\nexport function parseContext(projectPath: string): ParsedContext {\n const result: ParsedContext = {\n referencedFiles: [],\n mcpToolCount: 0,\n projectRoot: findProjectRoot(projectPath),\n };\n\n const root = result.projectRoot ?? projectPath;\n\n // Project CLAUDE.md\n const projectClaudeMdPath = path.join(root, 'CLAUDE.md');\n const projectClaudeMdContent = readFileSafe(projectClaudeMdPath);\n if (projectClaudeMdContent !== null) {\n result.projectClaudeMd = { filePath: projectClaudeMdPath, content: projectClaudeMdContent };\n }\n\n // User-level CLAUDE.md (~/.claude/CLAUDE.md)\n const userClaudeMdPath = path.join(os.homedir(), '.claude', 'CLAUDE.md');\n const userClaudeMdContent = readFileSafe(userClaudeMdPath);\n if (userClaudeMdContent !== null) {\n result.userClaudeMd = { filePath: userClaudeMdPath, content: userClaudeMdContent };\n }\n\n // MEMORY.md (.claude/MEMORY.md)\n const memoryPath = path.join(root, '.claude', 'MEMORY.md');\n const memoryContent = readFileSafe(memoryPath);\n if (memoryContent !== null) {\n result.memoryMd = { filePath: memoryPath, content: memoryContent };\n }\n\n // MCP tool count from settings\n const settingsPath = path.join(root, '.claude', 'settings.json');\n result.mcpToolCount = countMcpTools(settingsPath);\n\n // @referenced files from all CLAUDE.md files\n const allClaudeMdContent = [\n projectClaudeMdContent,\n userClaudeMdContent,\n ].filter(Boolean).join('\\n');\n\n const refs = extractReferences(allClaudeMdContent);\n for (const ref of refs) {\n const refPath = path.isAbsolute(ref) ? ref : path.join(root, ref);\n const refContent = readFileSafe(refPath);\n if (refContent !== null) {\n result.referencedFiles.push({\n filePath: refPath,\n content: refContent,\n referencedAs: ref,\n });\n }\n }\n\n return result;\n}\n","import fs from 'fs';\nimport path from 'path';\nimport { countTokens } from './tokenizer.js';\nimport { WASTE_THRESHOLDS, CACHE_BUSTERS } from '../shared/constants.js';\nimport type { WasteWarning, WasteCode } from '../shared/types.js';\n\nfunction warn(\n code: WasteCode,\n severity: WasteWarning['severity'],\n message: string,\n suggestion: string,\n estimatedSavings: number,\n lineNumber?: number,\n): WasteWarning {\n return { code, severity, message, suggestion, estimatedSavings, lineNumber };\n}\n\n/** Detect waste patterns in CLAUDE.md content */\nexport function detectClaudeMdWarnings(\n content: string,\n tokenCount: number,\n referenceCount: number,\n): WasteWarning[] {\n const warnings: WasteWarning[] = [];\n\n // OVERSIZED_CLAUDEMD\n if (tokenCount > WASTE_THRESHOLDS.MAX_CLAUDEMD_TOKENS) {\n const excess = tokenCount - WASTE_THRESHOLDS.MAX_CLAUDEMD_TOKENS;\n const pct = Math.round((tokenCount / WASTE_THRESHOLDS.MAX_CLAUDEMD_TOKENS - 1) * 100);\n warnings.push(\n warn(\n 'OVERSIZED_CLAUDEMD',\n 'error',\n `CLAUDE.md is ${tokenCount.toLocaleString()} tokens — ${pct}% over the ${WASTE_THRESHOLDS.MAX_CLAUDEMD_TOKENS.toLocaleString()} token recommendation`,\n 'Run `claudectx optimize --claudemd` to split into demand-loaded files',\n excess,\n ),\n );\n }\n\n // CACHE_BUSTING_CONTENT\n const lines = content.split('\\n');\n for (const { pattern, label } of CACHE_BUSTERS) {\n pattern.lastIndex = 0; // reset regex state\n for (let i = 0; i < lines.length; i++) {\n if (pattern.test(lines[i])) {\n warnings.push(\n warn(\n 'CACHE_BUSTING_CONTENT',\n 'warning',\n `${label} on line ${i + 1} breaks prompt caching`,\n 'Remove or externalize dynamic content — static CLAUDE.md saves ~88% on repeated requests',\n 0,\n i + 1,\n ),\n );\n break; // one warning per pattern type is enough\n }\n pattern.lastIndex = 0;\n }\n }\n\n // TOO_MANY_REFERENCES\n if (referenceCount > WASTE_THRESHOLDS.MAX_REFERENCE_COUNT) {\n warnings.push(\n warn(\n 'TOO_MANY_REFERENCES',\n 'warning',\n `CLAUDE.md has ${referenceCount} @referenced files — consider consolidating`,\n 'Group related references into fewer files to reduce overhead',\n 0,\n ),\n );\n }\n\n return warnings;\n}\n\n/** Detect waste patterns in MEMORY.md */\nexport function detectMemoryWarnings(content: string, tokenCount: number): WasteWarning[] {\n const warnings: WasteWarning[] = [];\n\n if (tokenCount > WASTE_THRESHOLDS.MAX_MEMORY_TOKENS) {\n const excess = tokenCount - WASTE_THRESHOLDS.MAX_MEMORY_TOKENS;\n warnings.push(\n warn(\n 'OVERSIZED_MEMORY',\n 'warning',\n `MEMORY.md is ${tokenCount.toLocaleString()} tokens — over the ${WASTE_THRESHOLDS.MAX_MEMORY_TOKENS.toLocaleString()} token recommendation`,\n 'Run `claudectx compress --prune --days 30` to prune old entries',\n excess,\n ),\n );\n }\n\n return warnings;\n}\n\n/** Detect warnings for a referenced file */\nexport function detectReferenceFileWarnings(\n filePath: string,\n content: string,\n tokenCount: number,\n): WasteWarning[] {\n const warnings: WasteWarning[] = [];\n\n if (tokenCount > WASTE_THRESHOLDS.MAX_REFERENCE_FILE_TOKENS) {\n warnings.push(\n warn(\n 'LARGE_REFERENCE_FILE',\n 'warning',\n `Referenced file ${path.basename(filePath)} is ${tokenCount.toLocaleString()} tokens`,\n 'Split large reference files or move rarely-needed sections to separate files',\n tokenCount - WASTE_THRESHOLDS.MAX_REFERENCE_FILE_TOKENS,\n ),\n );\n }\n\n return warnings;\n}\n\n/** Check if a .claudeignore file is missing */\nexport function detectMissingIgnoreFile(projectRoot: string): WasteWarning | null {\n const ignorePath = path.join(projectRoot, '.claudeignore');\n if (!fs.existsSync(ignorePath)) {\n return warn(\n 'MISSING_IGNOREFILE',\n 'warning',\n 'No .claudeignore file found — Claude may read node_modules, .git, dist/ etc.',\n 'Run `claudectx optimize --ignorefile` to generate one',\n 0,\n );\n }\n return null;\n}\n\n/** Check if prompt caching is not configured */\nexport function detectNoCachingConfigured(\n projectRoot: string,\n claudeMdContent?: string,\n): WasteWarning | null {\n // Simple heuristic: if CLAUDE.md has cache-busting content, flag it\n // A proper check would inspect API call headers, which we can't do statically\n const settingsPath = path.join(projectRoot, '.claude', 'settings.json');\n if (!fs.existsSync(settingsPath) && claudeMdContent) {\n // No settings file at all — caching is likely not configured\n return warn(\n 'NO_CACHING_CONFIGURED',\n 'info',\n 'Prompt caching may not be configured — static context is re-billed on every request',\n 'Run `claudectx optimize --cache` for caching recommendations',\n 0,\n );\n }\n return null;\n}\n\n/** Estimate redundant content between CLAUDE.md and MEMORY.md */\nexport function detectRedundantContent(\n claudeMdContent: string,\n memoryContent?: string,\n): WasteWarning | null {\n if (!memoryContent) return null;\n\n // Find lines that appear in both (exact duplicates)\n const claudeLines = new Set(\n claudeMdContent\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => l.length > 20),\n );\n const memoryLines = memoryContent\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => l.length > 20);\n\n const duplicates = memoryLines.filter((l) => claudeLines.has(l));\n\n if (duplicates.length > 3) {\n return warn(\n 'REDUNDANT_CONTENT',\n 'info',\n `${duplicates.length} lines appear in both CLAUDE.md and MEMORY.md`,\n 'Remove duplicated content from MEMORY.md — CLAUDE.md is already injected every request',\n countTokens(duplicates.join('\\n')),\n );\n }\n\n return null;\n}\n","/** Claude Code built-in token overhead (sent on every request, cannot be reduced) */\nexport const BUILTIN_OVERHEAD = {\n /** Claude Code's own system prompt */\n SYSTEM_PROMPT: 4200,\n /** Built-in tool schemas (Read, Edit, Bash, Glob, Grep, etc.) */\n TOOL_DEFINITIONS: 2100,\n /** Approximate tokens per registered MCP tool schema */\n MCP_PER_TOOL: 180,\n} as const;\n\n/** Waste detection thresholds */\nexport const WASTE_THRESHOLDS = {\n /** CLAUDE.md token count above this triggers OVERSIZED_CLAUDEMD */\n MAX_CLAUDEMD_TOKENS: 2000,\n /** MEMORY.md token count above this triggers OVERSIZED_MEMORY */\n MAX_MEMORY_TOKENS: 3000,\n /** Referenced file token count above this triggers LARGE_REFERENCE_FILE */\n MAX_REFERENCE_FILE_TOKENS: 5000,\n /** Number of @referenced files above this triggers TOO_MANY_REFERENCES */\n MAX_REFERENCE_COUNT: 5,\n} as const;\n\n/** Default session assumptions for cost estimates */\nexport const SESSION_DEFAULTS = {\n /** Assumed number of requests in a typical 2-hour session */\n REQUESTS_PER_SESSION: 60,\n} as const;\n\n/** Regex patterns that break prompt caching */\nexport const CACHE_BUSTERS = [\n { pattern: /\\d{4}-\\d{2}-\\d{2}/g, label: 'Date string' },\n { pattern: /\\d{2}:\\d{2}:\\d{2}/g, label: 'Time string' },\n { pattern: /process\\.env\\.\\w+/g, label: 'Environment variable reference' },\n { pattern: /\\$\\{.*?\\}/g, label: 'Template literal with variable' },\n { pattern: /Last updated:.*/gi, label: '\"Last updated\" timestamp' },\n { pattern: /Version:.*\\d+\\.\\d+/gi, label: 'Version string' },\n { pattern: /Generated by.*/gi, label: 'Generator comment' },\n] as const;\n","import { MODEL_PRICING, calculateCost } from '../shared/models.js';\nimport { SESSION_DEFAULTS } from '../shared/constants.js';\nimport type { ClaudeModel } from '../shared/types.js';\n\nexport interface CostBreakdown {\n perRequest: number;\n perSession: number; // SESSION_DEFAULTS.REQUESTS_PER_SESSION requests\n perHour: number; // 60 requests/hour estimate\n}\n\n/** Calculate cost for a given token count and model */\nexport function tokenCost(tokens: number, model: ClaudeModel): number {\n return calculateCost(tokens, model);\n}\n\n/** Calculate full session cost breakdown */\nexport function sessionCost(tokensPerRequest: number, model: ClaudeModel): CostBreakdown {\n const perRequest = calculateCost(tokensPerRequest, model);\n return {\n perRequest,\n perSession: perRequest * SESSION_DEFAULTS.REQUESTS_PER_SESSION,\n perHour: perRequest * 60,\n };\n}\n\n/** Calculate potential savings if all warnings are fixed */\nexport function calculatePotentialSavings(\n currentTokens: number,\n savableTokens: number,\n model: ClaudeModel,\n): {\n savedTokens: number;\n savedPercent: number;\n savedCostPerSession: number;\n} {\n const savedTokens = Math.min(savableTokens, currentTokens);\n const savedPercent = currentTokens > 0 ? Math.round((savedTokens / currentTokens) * 100) : 0;\n const savedCostPerSession =\n calculateCost(savedTokens, model) * SESSION_DEFAULTS.REQUESTS_PER_SESSION;\n\n return { savedTokens, savedPercent, savedCostPerSession };\n}\n\n/** Format cost as a dollar string */\nexport function formatCost(usd: number): string {\n if (usd < 0.01) return '$0.00';\n return `$${usd.toFixed(2)}`;\n}\n\n/** Format cost per model for comparison table */\nexport function allModelCosts(tokens: number): Record<ClaudeModel, number> {\n return Object.fromEntries(\n Object.keys(MODEL_PRICING).map((model) => [model, calculateCost(tokens, model as ClaudeModel)]),\n ) as Record<ClaudeModel, number>;\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport chalk from 'chalk';\nimport boxen from 'boxen';\nimport { checkbox, confirm } from '@inquirer/prompts';\nimport { ContextAnalyzer } from '../analyzer/index.js';\nimport { findProjectRoot } from '../analyzer/context-parser.js';\nimport { logger } from '../shared/logger.js';\nimport type { AnalysisReport, WasteCode } from '../shared/types.js';\nimport { generateIgnorefile, writeIgnorefile } from '../optimizer/ignorefile-generator.js';\nimport {\n parseSections,\n planSplit,\n applySplit,\n SPLIT_MIN_TOKENS,\n} from '../optimizer/claudemd-splitter.js';\nimport {\n planCacheFixes,\n applyAndWriteCacheFixes,\n} from '../optimizer/cache-applier.js';\nimport {\n planHooksInstall,\n applyHooksInstall,\n isAlreadyInstalled,\n} from '../optimizer/hooks-installer.js';\n\ninterface OptimizeOptions {\n path?: string;\n apply?: boolean;\n dryRun?: boolean;\n claudemd?: boolean;\n ignorefile?: boolean;\n cache?: boolean;\n hooks?: boolean;\n apiKey?: string;\n}\n\n// ─── Entry point ──────────────────────────────────────────────────────────────\n\nexport async function optimizeCommand(options: OptimizeOptions): Promise<void> {\n const projectPath = options.path\n ? path.resolve(options.path)\n : (findProjectRoot() ?? process.cwd());\n\n const dryRun = options.dryRun ?? false;\n const autoApply = options.apply ?? false;\n\n // Check if a specific sub-optimizer was requested directly\n const specificMode =\n options.claudemd || options.ignorefile || options.cache || options.hooks;\n\n // Print header\n console.log(\n boxen(\n chalk.bold('claudectx — Optimize') +\n '\\n' +\n chalk.dim(`Project: ${projectPath}`) +\n (dryRun ? '\\n' + chalk.yellow('Dry run — no files will be changed') : ''),\n { padding: 1, borderStyle: 'round', borderColor: dryRun ? 'yellow' : 'cyan' }\n )\n );\n\n // Always run analysis first so we know what needs fixing\n logger.info('Analyzing context...');\n const analyzer = new ContextAnalyzer('claude-sonnet-4-6');\n const report = await analyzer.analyze(projectPath);\n\n const hasWarning = (code: WasteCode) => report.warnings.some((w) => w.code === code);\n\n // ── Build the menu of available fixes ──────────────────────────────────────\n\n type FixId = 'ignorefile' | 'claudemd' | 'cache' | 'hooks';\n\n interface FixOption {\n id: FixId;\n label: string;\n detail: string;\n available: boolean;\n }\n\n const fixes: FixOption[] = [\n {\n id: 'ignorefile',\n label: 'Generate .claudeignore',\n detail: 'Prevents Claude from reading node_modules/, dist/, .git/, etc.',\n available: hasWarning('MISSING_IGNOREFILE') || !!options.ignorefile,\n },\n {\n id: 'claudemd',\n label: `Split CLAUDE.md into @files`,\n detail: `Extract large sections to demand-loaded files (saves tokens per request)`,\n available: hasWarning('OVERSIZED_CLAUDEMD') || !!options.claudemd,\n },\n {\n id: 'cache',\n label: 'Remove cache-busting content',\n detail: 'Comment-out dynamic dates/timestamps that bust the prompt cache every request',\n available: hasWarning('CACHE_BUSTING_CONTENT') || !!options.cache,\n },\n {\n id: 'hooks',\n label: 'Install session hooks',\n detail: 'Track per-file token spend via PostToolUse hook in .claude/settings.local.json',\n available: !isAlreadyInstalled(projectPath) || !!options.hooks,\n },\n ];\n\n const eligible = fixes.filter((f) => f.available);\n\n if (eligible.length === 0 && !specificMode) {\n logger.success(\n 'Nothing to optimize! Run `claudectx analyze` to see the current token breakdown.'\n );\n return;\n }\n\n // ── Select which fixes to run ───────────────────────────────────────────────\n\n let selected: FixId[];\n\n if (specificMode) {\n // Honour explicit flags\n selected = (\n [\n options.ignorefile && 'ignorefile',\n options.claudemd && 'claudemd',\n options.cache && 'cache',\n options.hooks && 'hooks',\n ] as (FixId | false)[]\n ).filter((x): x is FixId => !!x);\n } else if (autoApply || dryRun) {\n selected = eligible.map((f) => f.id);\n } else {\n selected = await checkbox<FixId>({\n message: 'Which optimizations would you like to apply?',\n choices: eligible.map((f) => ({\n name: `${chalk.white(f.label)} ${chalk.dim('—')} ${chalk.dim(f.detail)}`,\n value: f.id,\n checked: true,\n })),\n });\n }\n\n if (selected.length === 0) {\n logger.info('Nothing selected — no changes made.');\n return;\n }\n\n // ── Run each selected fix ───────────────────────────────────────────────────\n\n for (const id of selected) {\n switch (id) {\n case 'ignorefile':\n await runIgnorefile(projectPath, dryRun, autoApply);\n break;\n case 'claudemd':\n await runClaudeMdSplit(projectPath, report, dryRun, autoApply);\n break;\n case 'cache':\n await runCacheOptimization(projectPath, dryRun, autoApply);\n break;\n case 'hooks':\n await runHooks(projectPath, dryRun, autoApply);\n break;\n }\n }\n\n // ── Footer ─────────────────────────────────────────────────────────────────\n\n console.log('');\n if (dryRun) {\n logger.warn('Dry run complete. Re-run without --dry-run to apply changes.');\n } else {\n logger.success('Optimization complete! Run `claudectx analyze` to verify your savings.');\n }\n}\n\n// ─── .claudeignore ────────────────────────────────────────────────────────────\n\nasync function runIgnorefile(\n projectRoot: string,\n dryRun: boolean,\n autoApply: boolean\n): Promise<void> {\n printSectionHeader('.claudeignore');\n\n const result = generateIgnorefile(projectRoot);\n\n if (result.existed) {\n logger.warn('.claudeignore already exists — new patterns will be appended.');\n } else {\n logger.info(`Will create: ${chalk.cyan(result.filePath)}`);\n }\n\n logger.info(\n `Detected project types: ${result.projectTypes.length ? result.projectTypes.join(', ') : 'generic'}`\n );\n\n if (dryRun) {\n console.log(chalk.dim('\\nPreview (first 20 lines):'));\n console.log(\n chalk.dim(result.content.split('\\n').slice(0, 20).join('\\n') + '\\n ...')\n );\n return;\n }\n\n const ok =\n autoApply ||\n (await confirm({\n message: result.existed\n ? 'Append patterns to existing .claudeignore?'\n : 'Create .claudeignore?',\n default: true,\n }));\n\n if (!ok) {\n logger.info('Skipped.');\n return;\n }\n\n writeIgnorefile(result);\n logger.success(`${result.existed ? 'Updated' : 'Created'} ${chalk.cyan(result.filePath)}`);\n}\n\n// ─── CLAUDE.md splitter ───────────────────────────────────────────────────────\n\nasync function runClaudeMdSplit(\n projectRoot: string,\n report: AnalysisReport,\n dryRun: boolean,\n autoApply: boolean\n): Promise<void> {\n printSectionHeader('CLAUDE.md → @files');\n\n const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');\n if (!fs.existsSync(claudeMdPath)) {\n logger.warn('No CLAUDE.md found — skipping.');\n return;\n }\n\n const content = fs.readFileSync(claudeMdPath, 'utf-8');\n const sections = parseSections(content);\n const largeSections = sections.filter(\n (s) => !s.isPreamble && s.tokens >= SPLIT_MIN_TOKENS\n );\n\n if (largeSections.length === 0) {\n logger.info(`No sections exceed ${SPLIT_MIN_TOKENS} tokens — nothing to extract.`);\n return;\n }\n\n // Show current usage from the report\n const claudeMdWarning = report.warnings.find((w) => w.code === 'OVERSIZED_CLAUDEMD');\n if (claudeMdWarning) {\n logger.warn(claudeMdWarning.message);\n }\n\n console.log('\\n Large sections found:');\n for (const s of largeSections) {\n console.log(` ${chalk.yellow('•')} ${s.title} ${chalk.dim(`(${s.tokens} tokens)`)}`);\n }\n\n let sectionsToExtract: string[];\n\n if (autoApply || dryRun) {\n sectionsToExtract = largeSections.map((s) => s.title);\n } else {\n sectionsToExtract = await checkbox<string>({\n message: 'Select sections to extract into .claude/ @files:',\n choices: largeSections.map((s) => ({\n name: `${s.title} ${chalk.dim(`— ${s.tokens} tokens`)}`,\n value: s.title,\n checked: true,\n })),\n });\n }\n\n if (sectionsToExtract.length === 0) {\n logger.info('Skipped.');\n return;\n }\n\n const splitResult = planSplit(claudeMdPath, sectionsToExtract);\n\n if (dryRun) {\n console.log(\n chalk.dim(\n `\\nWould extract ${splitResult.extractedFiles.length} section(s) to .claude/`\n )\n );\n for (const f of splitResult.extractedFiles) {\n console.log(chalk.dim(` → ${f.refPath} (${f.sectionTitle})`));\n }\n console.log(chalk.dim(` Estimated savings: ~${splitResult.tokensSaved} tokens/request`));\n return;\n }\n\n const ok =\n autoApply ||\n (await confirm({\n message: `Extract ${sectionsToExtract.length} section(s) and update CLAUDE.md?`,\n default: true,\n }));\n\n if (!ok) {\n logger.info('Skipped.');\n return;\n }\n\n applySplit(splitResult);\n logger.success(\n `Extracted ${splitResult.extractedFiles.length} section(s). Saved ~${splitResult.tokensSaved} tokens/request.`\n );\n for (const f of splitResult.extractedFiles) {\n logger.info(` Created: ${chalk.cyan(path.relative(projectRoot, f.filePath))}`);\n }\n}\n\n// ─── Cache optimisation ───────────────────────────────────────────────────────\n\nasync function runCacheOptimization(\n projectRoot: string,\n dryRun: boolean,\n autoApply: boolean\n): Promise<void> {\n printSectionHeader('Prompt cache optimisation');\n\n const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');\n if (!fs.existsSync(claudeMdPath)) {\n logger.warn('No CLAUDE.md found — skipping.');\n return;\n }\n\n const result = planCacheFixes(claudeMdPath);\n\n if (result.fixes.length === 0) {\n logger.success('No cache-busting patterns found in CLAUDE.md.');\n return;\n }\n\n console.log(`\\n ${result.fixes.length} cache-busting line(s) detected:\\n`);\n for (const fix of result.fixes) {\n console.log(\n ` ${chalk.dim(`line ${fix.lineNumber}:`)} ${chalk.red(fix.originalLine.trim())}`\n );\n console.log(` ${chalk.dim('→')} ${chalk.green(fix.fixedLine)}`);\n console.log('');\n }\n\n if (dryRun) return;\n\n const ok =\n autoApply ||\n (await confirm({\n message: `Comment-out ${result.fixes.length} cache-busting line(s)?`,\n default: true,\n }));\n\n if (!ok) {\n logger.info('Skipped.');\n return;\n }\n\n applyAndWriteCacheFixes(claudeMdPath, result);\n logger.success(`Fixed ${result.fixes.length} cache-busting pattern(s) in CLAUDE.md.`);\n}\n\n// ─── Hooks installer ──────────────────────────────────────────────────────────\n\nasync function runHooks(\n projectRoot: string,\n dryRun: boolean,\n autoApply: boolean\n): Promise<void> {\n printSectionHeader('Session hooks');\n\n const result = planHooksInstall(projectRoot);\n\n logger.info(\n `Settings file: ${chalk.cyan(path.relative(projectRoot, result.settingsPath))}`\n );\n logger.info(result.existed ? 'Will merge with existing settings.' : 'Will create new file.');\n console.log(chalk.dim('\\n Hooks to install:'));\n console.log(\n chalk.dim(' • PostToolUse → Read: track per-file token spend for `claudectx watch`')\n );\n\n if (dryRun) return;\n\n const ok =\n autoApply ||\n (await confirm({ message: 'Install claudectx session hooks?', default: true }));\n\n if (!ok) {\n logger.info('Skipped.');\n return;\n }\n\n applyHooksInstall(result);\n logger.success(\n `Hooks installed → ${chalk.cyan(path.relative(projectRoot, result.settingsPath))}`\n );\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction printSectionHeader(title: string): void {\n console.log('');\n console.log(chalk.bold.cyan(`── ${title} ${'─'.repeat(Math.max(0, 50 - title.length))}`));\n}\n","import chalk from 'chalk';\n\nexport const logger = {\n info: (msg: string) => process.stderr.write(chalk.blue('ℹ ') + msg + '\\n'),\n warn: (msg: string) => process.stderr.write(chalk.yellow('⚠ ') + msg + '\\n'),\n error: (msg: string) => process.stderr.write(chalk.red('✖ ') + msg + '\\n'),\n success: (msg: string) => process.stderr.write(chalk.green('✔ ') + msg + '\\n'),\n dim: (msg: string) => process.stderr.write(chalk.dim(msg) + '\\n'),\n};\n","import * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface IgnorefileResult {\n filePath: string;\n content: string;\n existed: boolean;\n projectTypes: string[];\n}\n\nconst ALWAYS_IGNORE = `# .claudeignore — generated by claudectx\n# Prevents Claude Code from accidentally reading large binary/generated files.\n# Syntax is identical to .gitignore.\n\n# Version control internals\n.git/\n\n# Dependencies\nnode_modules/\nvendor/\n.venv/\nvenv/\nenv/\n.env/\n\n# Build output\ndist/\nbuild/\nout/\n.next/\n.nuxt/\n.output/\ntarget/\n\n# Bytecode & compiled files\n*.pyc\n*.pyo\n__pycache__/\n*.class\n*.o\n*.a\n*.so\n*.dylib\n\n# Logs & databases\n*.log\nlogs/\n*.sqlite3\n*.sqlite\n*.db\n\n# OS artefacts\n.DS_Store\nThumbs.db\ndesktop.ini\n\n# Environment & secrets (never let Claude read these)\n.env\n.env.local\n.env.*.local\n*.pem\n*.key\n*.cert\nsecrets.json\n\n# Coverage & test caches\ncoverage/\n.coverage\nhtmlcov/\n.cache/\n.pytest_cache/\n.mypy_cache/\n.ruff_cache/\n.tox/\n\n# IDE files\n.idea/\n.vscode/\n*.swp\n*.swo\n*~\n\n# Large media / binary assets\n*.jpg\n*.jpeg\n*.png\n*.gif\n*.ico\n*.mp4\n*.mp3\n*.pdf\n*.zip\n*.tar.gz\n*.woff\n*.woff2\n*.ttf\n*.eot\n`;\n\nconst PYTHON_EXTRA = `\n# Python / Django extras\nmigrations/\nstaticfiles/\nmedia/\n.eggs/\n*.egg-info/\npip-wheel-metadata/\n`;\n\nconst NODE_EXTRA = `\n# Node.js lock files (large, rarely useful to Claude)\npackage-lock.json\nyarn.lock\npnpm-lock.yaml\n.yarn/\n`;\n\nconst RUST_EXTRA = `\n# Rust\nCargo.lock\n`;\n\nconst GO_EXTRA = `\n# Go\ngo.sum\n`;\n\nfunction detectProjectTypes(projectRoot: string): string[] {\n const types: string[] = [];\n if (fs.existsSync(path.join(projectRoot, 'package.json'))) types.push('node');\n if (\n fs.existsSync(path.join(projectRoot, 'manage.py')) ||\n fs.existsSync(path.join(projectRoot, 'requirements.txt')) ||\n fs.existsSync(path.join(projectRoot, 'pyproject.toml'))\n )\n types.push('python');\n if (fs.existsSync(path.join(projectRoot, 'Cargo.toml'))) types.push('rust');\n if (fs.existsSync(path.join(projectRoot, 'go.mod'))) types.push('go');\n return types;\n}\n\nexport function generateIgnorefile(projectRoot: string): IgnorefileResult {\n const filePath = path.join(projectRoot, '.claudeignore');\n const existed = fs.existsSync(filePath);\n const projectTypes = detectProjectTypes(projectRoot);\n\n let content = ALWAYS_IGNORE;\n if (projectTypes.includes('python')) content += PYTHON_EXTRA;\n if (projectTypes.includes('node')) content += NODE_EXTRA;\n if (projectTypes.includes('rust')) content += RUST_EXTRA;\n if (projectTypes.includes('go')) content += GO_EXTRA;\n\n return { filePath, content, existed, projectTypes };\n}\n\nexport function writeIgnorefile(result: IgnorefileResult): void {\n if (result.existed) {\n const existing = fs.readFileSync(result.filePath, 'utf-8');\n fs.writeFileSync(result.filePath, existing.trimEnd() + '\\n\\n' + result.content, 'utf-8');\n } else {\n fs.writeFileSync(result.filePath, result.content, 'utf-8');\n }\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { countTokens } from '../analyzer/tokenizer.js';\n\nexport interface ParsedSection {\n title: string; // empty string = preamble (content before first ## heading)\n content: string; // full raw text of this section including the ## header line\n tokens: number;\n isPreamble: boolean;\n}\n\nexport interface ExtractedFile {\n filePath: string;\n content: string;\n sectionTitle: string;\n refPath: string; // relative path used in @reference (e.g. \".claude/commands.md\")\n}\n\nexport interface SplitResult {\n claudeMdPath: string;\n newClaudeMd: string;\n extractedFiles: ExtractedFile[];\n tokensSaved: number;\n}\n\n/** Minimum token count for a section to be worth extracting */\nexport const SPLIT_MIN_TOKENS = 300;\n\nfunction slugify(title: string): string {\n return title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n/**\n * Parse a CLAUDE.md file into preamble + `##`-level sections.\n * `#` top-level headings are included in the preamble or kept with their section.\n */\nexport function parseSections(content: string): ParsedSection[] {\n const lines = content.split('\\n');\n const sections: ParsedSection[] = [];\n\n let currentLines: string[] = [];\n let currentTitle = '';\n let isPreamble = true;\n\n const flush = () => {\n if (currentLines.length === 0 && !isPreamble) return;\n const text = currentLines.join('\\n');\n sections.push({\n title: currentTitle,\n content: text,\n tokens: countTokens(text),\n isPreamble,\n });\n };\n\n for (const line of lines) {\n if (line.startsWith('## ')) {\n flush();\n currentTitle = line.slice(3).trim();\n currentLines = [line];\n isPreamble = false;\n } else {\n currentLines.push(line);\n }\n }\n flush();\n\n return sections;\n}\n\n/**\n * Plan the split: choose which sections to extract, build the new CLAUDE.md text\n * and the list of files to create. Does NOT write anything to disk.\n */\nexport function planSplit(claudeMdPath: string, sectionsToExtract: string[]): SplitResult {\n const content = fs.readFileSync(claudeMdPath, 'utf-8');\n const sections = parseSections(content);\n const claudeDir = path.join(path.dirname(claudeMdPath), '.claude');\n\n const extractedFiles: ExtractedFile[] = [];\n let newContent = '';\n let tokensSaved = 0;\n\n // Track slugs to avoid duplicate filenames\n const usedSlugs = new Map<string, number>();\n\n for (const section of sections) {\n if (!section.isPreamble && sectionsToExtract.includes(section.title)) {\n let slug = slugify(section.title);\n const count = usedSlugs.get(slug) ?? 0;\n if (count > 0) slug = `${slug}-${count}`;\n usedSlugs.set(slug, count + 1);\n\n const filename = `${slug}.md`;\n const relRefPath = `.claude/${filename}`;\n const filePath = path.join(claudeDir, filename);\n\n const refBlock = `## ${section.title}\\n\\n@${relRefPath}\\n`;\n newContent += refBlock + '\\n';\n\n extractedFiles.push({\n filePath,\n content: section.content,\n sectionTitle: section.title,\n refPath: relRefPath,\n });\n\n tokensSaved += section.tokens - countTokens(refBlock);\n } else {\n // Keep section as-is, normalise trailing newline\n newContent += section.content.trimEnd() + '\\n\\n';\n }\n }\n\n return {\n claudeMdPath,\n newClaudeMd: newContent.trimEnd() + '\\n',\n extractedFiles,\n tokensSaved: Math.max(0, tokensSaved),\n };\n}\n\n/**\n * Apply the planned split: write extracted files and overwrite CLAUDE.md.\n */\nexport function applySplit(result: SplitResult): void {\n if (result.extractedFiles.length === 0) return;\n\n const claudeDir = path.dirname(result.extractedFiles[0].filePath);\n if (!fs.existsSync(claudeDir)) {\n fs.mkdirSync(claudeDir, { recursive: true });\n }\n\n for (const file of result.extractedFiles) {\n fs.writeFileSync(file.filePath, file.content, 'utf-8');\n }\n\n fs.writeFileSync(result.claudeMdPath, result.newClaudeMd, 'utf-8');\n}\n","import * as fs from 'fs';\nimport { CACHE_BUSTERS } from '../shared/constants.js';\n\nexport interface CacheFix {\n label: string;\n lineNumber: number; // 1-based\n originalLine: string;\n fixedLine: string;\n}\n\nexport interface CacheApplierResult {\n fixes: CacheFix[];\n newContent: string;\n}\n\n/**\n * Scan CLAUDE.md content for lines that contain cache-busting patterns.\n * Returns a list of proposed fixes (does NOT modify the file).\n */\nexport function findCacheBusters(content: string): CacheFix[] {\n const fixes: CacheFix[] = [];\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n for (const buster of CACHE_BUSTERS) {\n // Recreate without the global flag to avoid stateful lastIndex issues\n const re = new RegExp(buster.pattern.source, 'i');\n if (re.test(line)) {\n fixes.push({\n label: buster.label,\n lineNumber: i + 1,\n originalLine: line,\n // Comment-out the line so content is still vaguely visible in the file\n fixedLine: `<!-- claudectx removed cache-busting content (${buster.label}): ${line.trim()} -->`,\n });\n break; // only flag each line once\n }\n }\n }\n\n return fixes;\n}\n\n/**\n * Apply the list of fixes to the content string and return the modified text.\n */\nexport function applyCacheFixes(content: string, fixes: CacheFix[]): string {\n const lines = content.split('\\n');\n for (const fix of fixes) {\n lines[fix.lineNumber - 1] = fix.fixedLine;\n }\n return lines.join('\\n');\n}\n\n/**\n * High-level: read a file, find cache busters, apply fixes, return result.\n * Does NOT write anything to disk.\n */\nexport function planCacheFixes(claudeMdPath: string): CacheApplierResult {\n const content = fs.readFileSync(claudeMdPath, 'utf-8');\n const fixes = findCacheBusters(content);\n return { fixes, newContent: applyCacheFixes(content, fixes) };\n}\n\n/**\n * Write the fixed content back to disk.\n */\nexport function applyAndWriteCacheFixes(claudeMdPath: string, result: CacheApplierResult): void {\n fs.writeFileSync(claudeMdPath, result.newContent, 'utf-8');\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface HooksResult {\n settingsPath: string;\n existed: boolean;\n mergedSettings: Record<string, unknown>;\n}\n\n/**\n * claudectx hooks to inject into .claude/settings.local.json\n *\n * PostToolUse / Read → log the file path + line count so `claudectx watch`\n * can track token spend per file across the session.\n */\nconst CLAUDECTX_HOOKS = {\n PostToolUse: [\n {\n // Pipe the hook JSON payload to `claudectx watch --log-stdin`.\n // Claude Code passes { tool_name, tool_input, tool_response, session_id }\n // via stdin when the PostToolUse hook fires.\n matcher: 'Read',\n hooks: [\n {\n type: 'command',\n command: 'claudectx watch --log-stdin',\n },\n ],\n },\n ],\n};\n\n/**\n * Build the merged settings object without touching the filesystem.\n * We write to settings.local.json (not settings.json) so the changes\n * aren't accidentally committed.\n */\nexport function planHooksInstall(projectRoot: string): HooksResult {\n const claudeDir = path.join(projectRoot, '.claude');\n const settingsPath = path.join(claudeDir, 'settings.local.json');\n const existed = fs.existsSync(settingsPath);\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));\n } catch {\n // malformed JSON — start fresh\n existing = {};\n }\n }\n\n // Merge: preserve any existing hooks, append ours under PostToolUse\n const existingHooks = (existing.hooks as Record<string, unknown>) ?? {};\n const existingPostToolUse = (existingHooks.PostToolUse as unknown[]) ?? [];\n\n // Avoid duplicating our own hook if already installed\n const alreadyInstalled = existingPostToolUse.some(\n (h) =>\n typeof h === 'object' &&\n h !== null &&\n (h as Record<string, unknown>).matcher === 'Read' &&\n JSON.stringify(h).includes('claudectx')\n );\n\n const mergedPostToolUse = alreadyInstalled\n ? existingPostToolUse\n : [...existingPostToolUse, ...CLAUDECTX_HOOKS.PostToolUse];\n\n const mergedSettings: Record<string, unknown> = {\n ...existing,\n hooks: {\n ...existingHooks,\n PostToolUse: mergedPostToolUse,\n },\n };\n\n return { settingsPath, existed, mergedSettings };\n}\n\n/**\n * Write the merged settings to disk.\n */\nexport function applyHooksInstall(result: HooksResult): void {\n const dir = path.dirname(result.settingsPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(result.settingsPath, JSON.stringify(result.mergedSettings, null, 2) + '\\n', 'utf-8');\n}\n\n/**\n * Check whether claudectx hooks are already installed in a project.\n */\nexport function isAlreadyInstalled(projectRoot: string): boolean {\n const settingsPath = path.join(projectRoot, '.claude', 'settings.local.json');\n if (!fs.existsSync(settingsPath)) return false;\n try {\n const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));\n const postToolUse = settings?.hooks?.PostToolUse ?? [];\n return postToolUse.some((h: Record<string, unknown>) => h.matcher === 'Read');\n } catch {\n return false;\n }\n}\n","import * as path from 'path';\nimport { appendFileRead } from '../watcher/session-store.js';\nimport { resolveModel } from '../shared/models.js';\nimport type { ClaudeModel } from '../shared/types.js';\n\ninterface WatchOptions {\n session?: string;\n logStdin?: boolean;\n model?: string;\n clear?: boolean;\n}\n\n/**\n * Hook payload sent via stdin when PostToolUse fires.\n * Claude Code passes: { tool_name, tool_input, tool_response, session_id }\n */\ninterface HookPayload {\n tool_name?: string;\n tool_input?: { file_path?: string };\n session_id?: string;\n}\n\nexport async function watchCommand(options: WatchOptions): Promise<void> {\n // ── Hook mode ────────────────────────────────────────────────────────────\n // Called by the Claude Code PostToolUse hook via:\n // echo \"$HOOK_JSON\" | claudectx watch --log-stdin\n if (options.logStdin) {\n await handleLogStdin();\n return;\n }\n\n // ── Clear mode ───────────────────────────────────────────────────────────\n if (options.clear) {\n const { clearStore } = await import('../watcher/session-store.js');\n clearStore();\n process.stdout.write('claudectx: session store cleared.\\n');\n return;\n }\n\n // ── Dashboard mode ───────────────────────────────────────────────────────\n // Check that we're in an interactive terminal\n if (!process.stdout.isTTY) {\n process.stderr.write(\n 'claudectx watch: stdout is not a TTY — dashboard requires an interactive terminal.\\n'\n );\n process.exit(1);\n }\n\n const model = (options.model ? resolveModel(options.model) : 'claude-sonnet-4-6') as ClaudeModel;\n\n const { render } = await import('ink');\n const React = (await import('react')).default;\n const { Dashboard } = await import('../components/Dashboard.js');\n\n render(\n React.createElement(Dashboard, {\n model,\n sessionId: options.session,\n })\n );\n}\n\n/** Read stdin, parse JSON hook payload, log the file path. */\nasync function handleLogStdin(): Promise<void> {\n const raw = await readStdin();\n if (!raw.trim()) return;\n\n try {\n const payload = JSON.parse(raw) as HookPayload;\n const filePath = payload.tool_input?.file_path;\n if (filePath) {\n appendFileRead(path.resolve(filePath), payload.session_id);\n }\n } catch {\n // Malformed JSON — ignore, don't crash the hook\n }\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = '';\n process.stdin.setEncoding('utf-8');\n process.stdin.on('data', (chunk) => (data += chunk));\n process.stdin.on('end', () => resolve(data));\n // Safety timeout — if stdin never closes (not piped), resolve empty\n setTimeout(() => resolve(data), 500);\n });\n}\n","import * as path from 'path';\nimport chalk from 'chalk';\nimport { logger } from '../shared/logger.js';\nimport { planInstall, applyInstall, isInstalled } from '../mcp/installer.js';\n\ninterface McpOptions {\n port?: string;\n install?: boolean;\n path?: string;\n}\n\nexport async function mcpCommand(options: McpOptions): Promise<void> {\n const projectRoot = options.path ? path.resolve(options.path) : process.cwd();\n\n // ── Install mode ─────────────────────────────────────────────────────────\n if (options.install) {\n await runInstall(projectRoot);\n return;\n }\n\n // ── Server mode ───────────────────────────────────────────────────────────\n // HTTP transport (--port) is planned for a future release.\n if (options.port) {\n process.stderr.write(\n chalk.yellow(\n `HTTP transport (--port) is coming in a future release.\\n` +\n `Starting stdio server instead.\\n`\n )\n );\n }\n\n // Auto-suggest install if not yet done\n if (!isInstalled(projectRoot)) {\n process.stderr.write(\n chalk.dim(\n `Tip: run \"claudectx mcp --install\" to add this server to .claude/settings.json\\n`\n )\n );\n }\n\n const { startMcpServer } = await import('../mcp/server.js');\n await startMcpServer();\n}\n\nasync function runInstall(projectRoot: string): Promise<void> {\n const result = planInstall(projectRoot);\n\n if (result.alreadyInstalled) {\n logger.success(\n `claudectx MCP server is already registered in ${chalk.cyan(result.settingsPath)}`\n );\n return;\n }\n\n logger.info(`Adding claudectx MCP server to ${chalk.cyan(result.settingsPath)} ...`);\n applyInstall(result);\n\n logger.success('MCP server installed!');\n console.log('');\n console.log(chalk.dim(' Claude Code will pick it up on next restart.'));\n console.log(chalk.dim(' Tools available to Claude:'));\n console.log(chalk.dim(' • smart_read — read a symbol instead of a whole file'));\n console.log(chalk.dim(' • search_symbols — search for symbols by name'));\n console.log(chalk.dim(' • index_project — build the symbol index'));\n console.log('');\n console.log(chalk.dim(` Settings file: ${result.settingsPath}`));\n}\n","/**\n * Auto-install the claudectx MCP server into .claude/settings.json\n * so Claude Code can discover it automatically.\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nexport interface InstallResult {\n settingsPath: string;\n existed: boolean;\n alreadyInstalled: boolean;\n mergedSettings: Record<string, unknown>;\n}\n\nconst SERVER_NAME = 'claudectx';\n\nconst SERVER_ENTRY = {\n command: 'claudectx',\n args: ['mcp'],\n type: 'stdio',\n};\n\n/**\n * Build the merged settings object.\n * Writes to `settings.json` (not settings.local.json) because MCP servers\n * are typically project-level config meant to be shared.\n */\nexport function planInstall(projectRoot: string): InstallResult {\n const claudeDir = path.join(projectRoot, '.claude');\n const settingsPath = path.join(claudeDir, 'settings.json');\n const existed = fs.existsSync(settingsPath);\n\n let existing: Record<string, unknown> = {};\n if (existed) {\n try {\n existing = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));\n } catch {\n existing = {};\n }\n }\n\n const mcpServers = (existing.mcpServers as Record<string, unknown>) ?? {};\n const alreadyInstalled = SERVER_NAME in mcpServers;\n\n const mergedSettings: Record<string, unknown> = {\n ...existing,\n mcpServers: {\n ...mcpServers,\n [SERVER_NAME]: SERVER_ENTRY,\n },\n };\n\n return { settingsPath, existed, alreadyInstalled, mergedSettings };\n}\n\nexport function applyInstall(result: InstallResult): void {\n const dir = path.dirname(result.settingsPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(\n result.settingsPath,\n JSON.stringify(result.mergedSettings, null, 2) + '\\n',\n 'utf-8'\n );\n}\n\n/**\n * Check whether the claudectx MCP server is already registered.\n */\nexport function isInstalled(projectRoot: string): boolean {\n const settingsPath = path.join(projectRoot, '.claude', 'settings.json');\n if (!fs.existsSync(settingsPath)) return false;\n try {\n const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));\n return SERVER_NAME in (settings.mcpServers ?? {});\n } catch {\n return false;\n }\n}\n","/**\n * claudectx compress — compress the most recent (or specified) Claude Code\n * session into a compact MEMORY.md entry.\n *\n * Usage:\n * claudectx compress # compress most recent session\n * claudectx compress --session <id> # compress specific session\n * claudectx compress --auto # non-interactive (for hooks)\n * claudectx compress --prune --days 30 # also prune old entries\n * claudectx compress --path ./proj # project directory\n * claudectx compress --api-key <key> # use AI summarization\n */\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport { listSessionFiles } from '../watcher/session-reader.js';\nimport { parseSessionFile, buildConversationText } from '../compressor/session-parser.js';\nimport { summariseSession } from '../compressor/summarizer.js';\nimport {\n appendEntry,\n pruneOldEntries,\n isAlreadyCompressed,\n} from '../compressor/memory-writer.js';\nimport { getApiKey } from '../shared/config.js';\n\nexport interface CompressOptions {\n session?: string;\n auto?: boolean;\n path?: string;\n prune?: boolean;\n days?: string;\n apiKey?: string;\n}\n\nexport async function compressCommand(options: CompressOptions): Promise<void> {\n const chalk = (await import('chalk')).default;\n const projectRoot = options.path ? path.resolve(options.path) : process.cwd();\n const memoryFilePath = path.join(projectRoot, 'MEMORY.md');\n\n // ── 1. Resolve session file ──────────────────────────────────────────────────\n\n const sessionFiles = listSessionFiles();\n if (sessionFiles.length === 0) {\n process.stdout.write(chalk.red('No Claude Code sessions found.\\n'));\n process.stdout.write(chalk.dim('Sessions are stored in ~/.claude/projects/\\n'));\n process.exitCode = 1;\n return;\n }\n\n let targetFile: string;\n\n if (options.session) {\n const match = sessionFiles.find(\n (f) => f.sessionId === options.session || f.sessionId.startsWith(options.session!)\n );\n if (!match) {\n process.stdout.write(chalk.red(`Session not found: ${options.session}\\n`));\n process.stdout.write(chalk.dim(`Available: ${sessionFiles.slice(0, 5).map((f) => f.sessionId).join(', ')}\\n`));\n process.exitCode = 1;\n return;\n }\n targetFile = match.filePath;\n } else {\n // Most recent session (already sorted by mtime desc)\n targetFile = sessionFiles[0].filePath;\n }\n\n const sessionId = path.basename(targetFile, '.jsonl');\n\n // ── 2. Deduplication check ───────────────────────────────────────────────────\n\n if (isAlreadyCompressed(memoryFilePath, sessionId)) {\n if (!options.auto) {\n process.stdout.write(chalk.yellow(`Session ${sessionId.slice(0, 8)}… is already in MEMORY.md — skipping.\\n`));\n }\n return;\n }\n\n // ── 3. Parse session ─────────────────────────────────────────────────────────\n\n const parsed = parseSessionFile(targetFile);\n if (!parsed) {\n process.stdout.write(chalk.red(`Failed to parse session file: ${targetFile}\\n`));\n process.exitCode = 1;\n return;\n }\n\n if (!options.auto) {\n process.stdout.write(\n chalk.cyan(`Compressing session ${chalk.bold(sessionId.slice(0, 8))}… `) +\n chalk.dim(`(${parsed.turnCount} turns, ${parsed.filesEdited.length} files edited)\\n`)\n );\n }\n\n // ── 4. Summarize ─────────────────────────────────────────────────────────────\n\n const conversationText = buildConversationText(parsed);\n const apiKey = options.apiKey ?? getApiKey();\n\n let spinner: ReturnType<typeof setInterval> | null = null;\n const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n let frameIdx = 0;\n\n if (!options.auto && apiKey) {\n process.stdout.write(chalk.dim('Summarizing with AI… '));\n spinner = setInterval(() => {\n process.stdout.write(`\\r${chalk.dim('Summarizing with AI… ')}${frames[frameIdx++ % frames.length]}`);\n }, 80);\n }\n\n const result = await summariseSession(parsed, conversationText, apiKey ?? undefined);\n\n if (spinner) {\n clearInterval(spinner);\n process.stdout.write('\\r' + ' '.repeat(40) + '\\r');\n }\n\n // ── 5. Append to MEMORY.md ───────────────────────────────────────────────────\n\n appendEntry(memoryFilePath, sessionId, result.text);\n\n if (!options.auto) {\n const methodLabel =\n result.method === 'ai'\n ? chalk.green(`AI (${result.model}, ${result.inputTokens} tokens)`)\n : chalk.yellow('heuristic (no API key)');\n\n process.stdout.write(chalk.green('✓') + ` Appended to ${chalk.bold(memoryFilePath)} via ${methodLabel}\\n`);\n process.stdout.write('\\n' + chalk.dim('─'.repeat(60)) + '\\n');\n process.stdout.write(result.text + '\\n');\n process.stdout.write(chalk.dim('─'.repeat(60)) + '\\n');\n }\n\n // ── 6. Optional prune ────────────────────────────────────────────────────────\n\n if (options.prune) {\n const days = parseInt(options.days ?? '30', 10);\n if (!fs.existsSync(memoryFilePath)) return;\n\n const pruned = pruneOldEntries(memoryFilePath, days);\n if (pruned.removed > 0 && !options.auto) {\n process.stdout.write(\n chalk.dim(`Pruned ${pruned.removed} entr${pruned.removed === 1 ? 'y' : 'ies'} older than ${days} days.\\n`)\n );\n }\n }\n}\n","/**\n * Parses a Claude Code session JSONL file into structured, human-readable\n * content suitable for summarisation.\n */\nimport * as fs from 'fs';\n\nexport interface SessionTurn {\n role: 'user' | 'assistant';\n text: string; // extracted plain text\n toolCalls: ToolCall[];\n usage?: { inputTokens: number; outputTokens: number };\n}\n\nexport interface ToolCall {\n tool: string;\n input: Record<string, unknown>;\n}\n\nexport interface ParsedSession {\n sessionId: string;\n filePath: string;\n turns: SessionTurn[];\n totalUsage: { inputTokens: number; outputTokens: number; cacheReadTokens: number };\n filesRead: string[];\n filesEdited: string[];\n filesCreated: string[];\n commandsRun: string[];\n turnCount: number;\n}\n\n// ─── Raw JSONL types ──────────────────────────────────────────────────────────\n\ninterface RawUsage {\n input_tokens?: number;\n output_tokens?: number;\n cache_read_input_tokens?: number;\n}\n\ninterface RawContentBlock {\n type: string;\n text?: string;\n name?: string;\n input?: Record<string, unknown>;\n content?: string | RawContentBlock[];\n}\n\ninterface RawMessage {\n role?: string;\n content?: string | RawContentBlock[];\n usage?: RawUsage;\n}\n\ninterface RawEntry {\n type?: string;\n message?: RawMessage;\n usage?: RawUsage;\n}\n\n// ─── Parsing ──────────────────────────────────────────────────────────────────\n\nfunction extractText(content: string | RawContentBlock[] | undefined): string {\n if (!content) return '';\n if (typeof content === 'string') return content;\n return content\n .filter((b) => b.type === 'text' && b.text)\n .map((b) => b.text!)\n .join('\\n')\n .trim();\n}\n\nfunction extractToolCalls(content: string | RawContentBlock[] | undefined): ToolCall[] {\n if (!content || typeof content === 'string') return [];\n return content\n .filter((b) => b.type === 'tool_use' && b.name)\n .map((b) => ({ tool: b.name!, input: b.input ?? {} }));\n}\n\nexport function parseSessionFile(sessionFilePath: string): ParsedSession | null {\n if (!fs.existsSync(sessionFilePath)) return null;\n\n let content: string;\n try {\n content = fs.readFileSync(sessionFilePath, 'utf-8');\n } catch {\n return null;\n }\n\n const lines = content.trim().split('\\n').filter(Boolean);\n const turns: SessionTurn[] = [];\n const totalUsage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0 };\n\n for (const line of lines) {\n try {\n const entry = JSON.parse(line) as RawEntry;\n const msg = entry.message;\n if (!msg) continue;\n\n const role = msg.role === 'user' ? 'user' : msg.role === 'assistant' ? 'assistant' : null;\n if (!role) continue;\n\n const usage = msg.usage ?? entry.usage;\n if (usage) {\n totalUsage.inputTokens += usage.input_tokens ?? 0;\n totalUsage.outputTokens += usage.output_tokens ?? 0;\n totalUsage.cacheReadTokens += usage.cache_read_input_tokens ?? 0;\n }\n\n turns.push({\n role,\n text: extractText(msg.content),\n toolCalls: extractToolCalls(msg.content),\n usage: usage\n ? { inputTokens: usage.input_tokens ?? 0, outputTokens: usage.output_tokens ?? 0 }\n : undefined,\n });\n } catch {\n // skip malformed lines\n }\n }\n\n // Derive file lists from tool calls\n const filesRead = new Set<string>();\n const filesEdited = new Set<string>();\n const filesCreated = new Set<string>();\n const commandsRun: string[] = [];\n\n for (const turn of turns) {\n for (const tc of turn.toolCalls) {\n const fp = (tc.input.file_path ?? tc.input.path ?? tc.input.file) as string | undefined;\n switch (tc.tool) {\n case 'Read':\n if (fp) filesRead.add(fp);\n break;\n case 'Edit':\n case 'MultiEdit':\n if (fp) filesEdited.add(fp);\n break;\n case 'Write':\n if (fp) filesCreated.add(fp);\n break;\n case 'Bash': {\n const cmd = tc.input.command as string | undefined;\n if (cmd) commandsRun.push(cmd.slice(0, 120));\n break;\n }\n }\n }\n }\n\n const sessionId = sessionFilePath.replace(/^.*[\\\\/]/, '').replace('.jsonl', '');\n\n return {\n sessionId,\n filePath: sessionFilePath,\n turns,\n totalUsage,\n filesRead: [...filesRead],\n filesEdited: [...filesEdited],\n filesCreated: [...filesCreated],\n commandsRun,\n turnCount: turns.filter((t) => t.role === 'user').length,\n };\n}\n\n/**\n * Build a condensed text representation of the session suitable for the\n * Claude summarisation prompt. Keeps the most important context.\n */\nexport function buildConversationText(session: ParsedSession, maxChars = 20_000): string {\n const parts: string[] = [];\n\n // Include up to the last 10 user/assistant exchanges\n const relevantTurns = session.turns.slice(-20);\n for (const turn of relevantTurns) {\n if (!turn.text && turn.toolCalls.length === 0) continue;\n\n const label = turn.role === 'user' ? 'USER' : 'ASSISTANT';\n const text = turn.text ? turn.text.slice(0, 800) : '';\n const tools =\n turn.toolCalls.length > 0\n ? `[tools: ${turn.toolCalls.map((t) => t.tool).join(', ')}]`\n : '';\n\n parts.push(`${label}: ${text} ${tools}`.trim());\n }\n\n const body = parts.join('\\n\\n');\n return body.length > maxChars ? body.slice(0, maxChars) + '\\n…(truncated)' : body;\n}\n","/**\n * Summarises a parsed session into a compact MEMORY.md entry.\n *\n * Strategy:\n * 1. If ANTHROPIC_API_KEY is available → call claude-haiku-4-5 for a tight summary\n * 2. Otherwise → build a structured summary from the parsed session metadata\n */\nimport type { ParsedSession } from './session-parser.js';\nimport { getApiKey } from '../shared/config.js';\nimport { MODEL_PRICING } from '../shared/models.js';\n\nexport interface SummaryResult {\n text: string;\n method: 'ai' | 'heuristic';\n model?: string;\n inputTokens?: number;\n}\n\nconst SUMMARY_MODEL = 'claude-haiku-4-5-20251001';\nconst SUMMARY_MAX_TOKENS = 300;\n\nconst SYSTEM_PROMPT = `You are a session-compressor for Claude Code.\nYour job is to produce a concise MEMORY.md entry (max 200 words) for a coding session.\n\nFocus on:\n- What was built or fixed (specific function/file names)\n- Key decisions or patterns established\n- Any gotchas or critical context for future sessions\n\nOutput ONLY the entry body — no frontmatter, no headings, no preamble.\nUse bullet points. Be terse. Prioritise facts over narrative.`;\n\n// ─── AI summarisation ─────────────────────────────────────────────────────────\n\nexport async function summariseWithAI(\n conversationText: string,\n apiKey?: string\n): Promise<SummaryResult> {\n const key = apiKey ?? getApiKey();\n if (!key) {\n throw new Error('No API key available');\n }\n\n // Lazy import so the SDK is only loaded when actually needed\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n const client = new Anthropic({ apiKey: key });\n\n const response = await client.messages.create({\n model: SUMMARY_MODEL,\n max_tokens: SUMMARY_MAX_TOKENS,\n system: SYSTEM_PROMPT,\n messages: [\n {\n role: 'user',\n content: `Summarise this Claude Code session:\\n\\n${conversationText}`,\n },\n ],\n });\n\n const text =\n response.content\n .filter((b) => b.type === 'text')\n .map((b) => (b as { type: 'text'; text: string }).text)\n .join('\\n')\n .trim() || '(no summary generated)';\n\n return {\n text,\n method: 'ai',\n model: SUMMARY_MODEL,\n inputTokens: response.usage.input_tokens,\n };\n}\n\n// ─── Heuristic fallback ───────────────────────────────────────────────────────\n\nexport function summariseHeuristically(session: ParsedSession): SummaryResult {\n const lines: string[] = [];\n\n // First user message = the task description\n const firstUser = session.turns.find((t) => t.role === 'user' && t.text);\n if (firstUser?.text) {\n const brief = firstUser.text.split('\\n')[0].slice(0, 200);\n lines.push(`- **Task:** ${brief}`);\n }\n\n // Files touched\n if (session.filesCreated.length > 0) {\n lines.push(`- **Created:** ${session.filesCreated.map(shortPath).join(', ')}`);\n }\n if (session.filesEdited.length > 0) {\n const edited = session.filesEdited.slice(0, 8).map(shortPath).join(', ');\n lines.push(`- **Edited:** ${edited}${session.filesEdited.length > 8 ? ' …' : ''}`);\n }\n if (session.filesRead.length > 0) {\n lines.push(`- **Read ${session.filesRead.length} file(s)**`);\n }\n\n // Key commands\n const notable = session.commandsRun\n .filter((c) => !c.startsWith('echo') && !c.startsWith('cat'))\n .slice(0, 3);\n if (notable.length > 0) {\n lines.push(`- **Commands:** ${notable.map((c) => `\\`${c.slice(0, 60)}\\``).join(', ')}`);\n }\n\n // Token stats\n const totalIn = session.totalUsage.inputTokens;\n const totalOut = session.totalUsage.outputTokens;\n const cost = calcCost(totalIn, totalOut);\n lines.push(\n `- **Stats:** ${session.turnCount} requests, ${fmt(totalIn)}↓ / ${fmt(totalOut)}↑ tokens, ~$${cost}`\n );\n\n return {\n text: lines.join('\\n') || '- (No session content extracted)',\n method: 'heuristic',\n };\n}\n\n// ─── High-level entry point ───────────────────────────────────────────────────\n\nexport async function summariseSession(\n session: ParsedSession,\n conversationText: string,\n apiKey?: string\n): Promise<SummaryResult> {\n const key = apiKey ?? getApiKey();\n if (key) {\n try {\n return await summariseWithAI(conversationText, key);\n } catch {\n // Fall through to heuristic\n }\n }\n return summariseHeuristically(session);\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction shortPath(p: string): string {\n const parts = p.split('/');\n return parts.slice(-2).join('/');\n}\n\nfunction fmt(n: number): string {\n return n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n);\n}\n\nfunction calcCost(inputTokens: number, outputTokens: number): string {\n const p = MODEL_PRICING['claude-sonnet-4-6'];\n const cost = (inputTokens / 1e6) * p.inputPerMillion + (outputTokens / 1e6) * p.outputPerMillion;\n return cost.toFixed(3);\n}\n","import Conf from 'conf';\nimport type { ClaudeCtxConfig } from './types.js';\n\nconst conf = new Conf<ClaudeCtxConfig>({\n projectName: 'claudectx',\n defaults: {\n defaultModel: 'claude-sonnet-4-6',\n maxMemoryTokens: 3000,\n maxClaudeMdTokens: 2000,\n watchPollIntervalMs: 2000,\n },\n});\n\nexport function getConfig(): ClaudeCtxConfig {\n return conf.store as ClaudeCtxConfig;\n}\n\nexport function setConfig(key: keyof ClaudeCtxConfig, value: unknown): void {\n conf.set(key, value);\n}\n\nexport function getApiKey(): string | undefined {\n return process.env.ANTHROPIC_API_KEY || conf.get('anthropicApiKey');\n}\n","/**\n * Reads, writes, and prunes MEMORY.md entries.\n *\n * Entry format — each entry is wrapped in HTML comments so the writer\n * can identify and remove old ones during pruning:\n *\n * <!-- claudectx-entry: 2026-04-11 | session: abc12345 -->\n * ### [2026-04-11] Session abc12345…\n *\n * <summary body>\n *\n * ---\n */\nimport * as fs from 'fs';\nimport * as path from 'path';\n\n\n\nexport interface MemoryEntry {\n date: string; // ISO date string YYYY-MM-DD\n sessionId: string;\n raw: string; // full block including markers\n}\n\n// ─── Parsing ──────────────────────────────────────────────────────────────────\n\n/**\n * Parse all claudectx-managed entries from a MEMORY.md file.\n * Unmanaged content (before the first marker) is preserved as-is.\n */\nexport function parseMemoryFile(filePath: string): {\n preamble: string;\n entries: MemoryEntry[];\n} {\n if (!fs.existsSync(filePath)) {\n return { preamble: '', entries: [] };\n }\n\n const content = fs.readFileSync(filePath, 'utf-8');\n const markerRegex = /<!-- claudectx-entry: (\\d{4}-\\d{2}-\\d{2}) \\| session: ([a-z0-9-]+) -->/g;\n\n // Split into blocks at each marker\n const indices: number[] = [];\n let match: RegExpExecArray | null;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n match = markerRegex.exec(content);\n if (!match) break;\n indices.push(match.index);\n }\n\n if (indices.length === 0) {\n return { preamble: content, entries: [] };\n }\n\n const preamble = content.slice(0, indices[0]);\n const entries: MemoryEntry[] = [];\n\n for (let i = 0; i < indices.length; i++) {\n const start = indices[i];\n const end = i + 1 < indices.length ? indices[i + 1] : content.length;\n const block = content.slice(start, end).trim();\n\n // Re-parse the marker from the block to get date + sessionId\n const headerMatch = block.match(\n /<!-- claudectx-entry: (\\d{4}-\\d{2}-\\d{2}) \\| session: ([a-z0-9-]+) -->/\n );\n if (!headerMatch) continue;\n\n entries.push({\n date: headerMatch[1],\n sessionId: headerMatch[2],\n raw: block,\n });\n }\n\n return { preamble, entries };\n}\n\n// ─── Writing ──────────────────────────────────────────────────────────────────\n\n/**\n * Build a MEMORY.md entry block for a session summary.\n */\nexport function buildEntryBlock(\n sessionId: string,\n summaryText: string,\n date = new Date()\n): string {\n const dateStr = date.toISOString().slice(0, 10);\n const shortId = sessionId.slice(0, 8);\n const heading = `### [${dateStr}] Session ${shortId}…`;\n\n return [\n `<!-- claudectx-entry: ${dateStr} | session: ${sessionId} -->`,\n heading,\n '',\n summaryText.trim(),\n '',\n '---',\n ].join('\\n');\n}\n\n/**\n * Append a new entry to MEMORY.md, creating the file if it doesn't exist.\n * Returns the final file content.\n */\nexport function appendEntry(\n memoryFilePath: string,\n sessionId: string,\n summaryText: string,\n date = new Date()\n): string {\n const { preamble, entries } = parseMemoryFile(memoryFilePath);\n\n // Check for duplicate (same session already compressed)\n if (entries.some((e) => e.sessionId === sessionId)) {\n throw new Error(`Session ${sessionId.slice(0, 8)} is already in MEMORY.md`);\n }\n\n const newBlock = buildEntryBlock(sessionId, summaryText, date);\n const allBlocks = [...entries.map((e) => e.raw), newBlock];\n\n const newContent =\n (preamble.trimEnd() ? preamble.trimEnd() + '\\n\\n' : '') +\n allBlocks.join('\\n\\n') +\n '\\n';\n\n const dir = path.dirname(memoryFilePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(memoryFilePath, newContent, 'utf-8');\n\n return newContent;\n}\n\n// ─── Pruning ──────────────────────────────────────────────────────────────────\n\nexport interface PruneResult {\n removed: number;\n kept: number;\n removedEntries: MemoryEntry[];\n}\n\n/**\n * Remove entries older than `days` days from MEMORY.md.\n * Returns what was removed and what was kept.\n */\nexport function pruneOldEntries(memoryFilePath: string, days: number): PruneResult {\n if (!fs.existsSync(memoryFilePath)) {\n return { removed: 0, kept: 0, removedEntries: [] };\n }\n\n const { preamble, entries } = parseMemoryFile(memoryFilePath);\n const cutoff = new Date();\n cutoff.setDate(cutoff.getDate() - days);\n const cutoffStr = cutoff.toISOString().slice(0, 10);\n\n const kept = entries.filter((e) => e.date >= cutoffStr);\n const removed = entries.filter((e) => e.date < cutoffStr);\n\n if (removed.length === 0) {\n return { removed: 0, kept: kept.length, removedEntries: [] };\n }\n\n const newContent =\n (preamble.trimEnd() ? preamble.trimEnd() + '\\n\\n' : '') +\n kept.map((e) => e.raw).join('\\n\\n') +\n (kept.length > 0 ? '\\n' : '');\n\n fs.writeFileSync(memoryFilePath, newContent, 'utf-8');\n\n return { removed: removed.length, kept: kept.length, removedEntries: removed };\n}\n\n/**\n * Check if a session has already been compressed into MEMORY.md.\n */\nexport function isAlreadyCompressed(memoryFilePath: string, sessionId: string): boolean {\n const { entries } = parseMemoryFile(memoryFilePath);\n return entries.some((e) => e.sessionId === sessionId);\n}\n","/**\n * claudectx report — print a usage analytics report for the last N days.\n *\n * Usage:\n * claudectx report # 7-day text report\n * claudectx report --days 30 # 30-day window\n * claudectx report --json # machine-readable JSON\n * claudectx report --markdown # GitHub-flavoured Markdown\n * claudectx report --model opus\n */\nimport type { ClaudeModel } from '../shared/types.js';\nimport { aggregateUsage } from '../reporter/usage-aggregator.js';\nimport { format } from '../reporter/formatter.js';\n\nexport interface ReportOptions {\n days?: string;\n json?: boolean;\n markdown?: boolean;\n model?: string;\n path?: string;\n}\n\nconst MODEL_ALIASES: Record<string, ClaudeModel> = {\n haiku: 'claude-haiku-4-5-20251001',\n sonnet: 'claude-sonnet-4-6',\n opus: 'claude-opus-4-6',\n 'claude-haiku-4-5-20251001': 'claude-haiku-4-5-20251001',\n 'claude-sonnet-4-6': 'claude-sonnet-4-6',\n 'claude-opus-4-6': 'claude-opus-4-6',\n};\n\nexport async function reportCommand(options: ReportOptions): Promise<void> {\n const days = Math.max(1, parseInt(options.days ?? '7', 10));\n\n const modelAlias = options.model ?? 'sonnet';\n const model: ClaudeModel = MODEL_ALIASES[modelAlias] ?? 'claude-sonnet-4-6';\n\n const mode = options.json ? 'json' : options.markdown ? 'markdown' : 'text';\n\n const data = await aggregateUsage(days, model);\n const output = format(data, mode);\n\n process.stdout.write(output + '\\n');\n}\n","/**\n * Aggregates token usage and file-read data across multiple sessions\n * for the `claudectx report` command.\n */\nimport { listSessionFiles, readSessionUsage } from '../watcher/session-reader.js';\nimport { readAllEvents, aggregateStats } from '../watcher/session-store.js';\nimport { MODEL_PRICING } from '../shared/models.js';\nimport type { ClaudeModel } from '../shared/types.js';\n\nexport interface DayBucket {\n date: string; // YYYY-MM-DD\n sessions: number;\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n requests: number;\n costUsd: number;\n}\n\nexport interface ReportData {\n periodDays: number;\n startDate: string;\n endDate: string;\n totalSessions: number;\n totalRequests: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n totalCacheReadTokens: number;\n cacheHitRate: number; // 0-100\n totalCostUsd: number;\n avgCostPerSession: number;\n avgTokensPerRequest: number;\n byDay: DayBucket[];\n topFiles: Array<{ filePath: string; readCount: number }>;\n model: ClaudeModel;\n generatedAt: string;\n}\n\nfunction isoDate(d: Date): string {\n return d.toISOString().slice(0, 10);\n}\n\nfunction calcCost(inputTokens: number, outputTokens: number, model: ClaudeModel): number {\n const p = MODEL_PRICING[model];\n return (inputTokens / 1e6) * p.inputPerMillion + (outputTokens / 1e6) * p.outputPerMillion;\n}\n\n/**\n * Aggregate session data for the last `days` days.\n */\nexport async function aggregateUsage(\n days: number,\n model: ClaudeModel = 'claude-sonnet-4-6'\n): Promise<ReportData> {\n const now = new Date();\n const cutoff = new Date(now);\n cutoff.setDate(cutoff.getDate() - days);\n const cutoffMs = cutoff.getTime();\n\n // ── Session JSONL data ──────────────────────────────────────────────────────\n\n const sessionFiles = listSessionFiles().filter((f) => f.mtimeMs >= cutoffMs);\n\n const bucketMap = new Map<string, DayBucket>();\n\n // Initialise one bucket per day in the range\n for (let i = 0; i < days; i++) {\n const d = new Date(now);\n d.setDate(d.getDate() - i);\n const dateStr = isoDate(d);\n bucketMap.set(dateStr, {\n date: dateStr,\n sessions: 0,\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n requests: 0,\n costUsd: 0,\n });\n }\n\n let totalRequests = 0;\n let totalInput = 0;\n let totalOutput = 0;\n let totalCacheRead = 0;\n\n for (const sf of sessionFiles) {\n const dateStr = isoDate(new Date(sf.mtimeMs));\n const bucket = bucketMap.get(dateStr);\n if (!bucket) continue;\n\n const usage = readSessionUsage(sf.filePath);\n bucket.sessions++;\n bucket.inputTokens += usage.inputTokens;\n bucket.outputTokens += usage.outputTokens;\n bucket.cacheReadTokens += usage.cacheReadTokens;\n bucket.requests += usage.requestCount;\n bucket.costUsd += calcCost(usage.inputTokens, usage.outputTokens, model);\n\n totalInput += usage.inputTokens;\n totalOutput += usage.outputTokens;\n totalCacheRead += usage.cacheReadTokens;\n totalRequests += usage.requestCount;\n }\n\n // ── File-read stats ─────────────────────────────────────────────────────────\n\n const fileEvents = readAllEvents().filter(\n (e) => new Date(e.timestamp).getTime() >= cutoffMs\n );\n const fileStats = aggregateStats(fileEvents);\n const topFiles = fileStats.slice(0, 10).map((s) => ({\n filePath: s.filePath,\n readCount: s.readCount,\n }));\n\n // ── Totals ──────────────────────────────────────────────────────────────────\n\n const totalCost = calcCost(totalInput, totalOutput, model);\n const cacheHitRate =\n totalInput > 0 ? Math.round((totalCacheRead / totalInput) * 100) : 0;\n\n const byDay = [...bucketMap.values()].sort((a, b) => a.date.localeCompare(b.date));\n\n // Scan actual unique sessions count from file list\n const uniqueSessions = new Set(sessionFiles.map((f) => f.sessionId)).size;\n\n return {\n periodDays: days,\n startDate: isoDate(cutoff),\n endDate: isoDate(now),\n totalSessions: uniqueSessions,\n totalRequests,\n totalInputTokens: totalInput,\n totalOutputTokens: totalOutput,\n totalCacheReadTokens: totalCacheRead,\n cacheHitRate,\n totalCostUsd: totalCost,\n avgCostPerSession: uniqueSessions > 0 ? totalCost / uniqueSessions : 0,\n avgTokensPerRequest: totalRequests > 0 ? Math.round(totalInput / totalRequests) : 0,\n byDay,\n topFiles,\n model,\n generatedAt: now.toISOString(),\n };\n}\n","/**\n * Formats a ReportData object as plain text, JSON, or Markdown.\n */\nimport type { ReportData } from './usage-aggregator.js';\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction fmtNum(n: number): string {\n return n.toLocaleString();\n}\n\nfunction fmtCost(usd: number): string {\n if (usd < 0.01) return `$${usd.toFixed(4)}`;\n return `$${usd.toFixed(2)}`;\n}\n\nfunction fmtK(n: number): string {\n return n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n);\n}\n\nfunction bar(value: number, max: number, width = 20): string {\n if (max === 0) return ' '.repeat(width);\n const filled = Math.round((value / max) * width);\n return '█'.repeat(filled) + '░'.repeat(width - filled);\n}\n\nfunction shortPath(p: string): string {\n const parts = p.split('/');\n return parts.length > 3 ? '…/' + parts.slice(-3).join('/') : p;\n}\n\n// ─── Plain text ───────────────────────────────────────────────────────────────\n\nexport function formatText(data: ReportData): string {\n const lines: string[] = [];\n\n lines.push(\n `claudectx report — ${data.periodDays}-day summary (${data.startDate} → ${data.endDate})`\n );\n lines.push('═'.repeat(70));\n lines.push('');\n\n // Summary table\n lines.push('TOTALS');\n lines.push('─'.repeat(40));\n lines.push(` Sessions: ${fmtNum(data.totalSessions)}`);\n lines.push(` Requests: ${fmtNum(data.totalRequests)}`);\n lines.push(` Input tokens: ${fmtNum(data.totalInputTokens)}`);\n lines.push(` Output tokens: ${fmtNum(data.totalOutputTokens)}`);\n lines.push(` Cache reads: ${fmtNum(data.totalCacheReadTokens)} (${data.cacheHitRate}% hit rate)`);\n lines.push(` Total cost (est.): ${fmtCost(data.totalCostUsd)}`);\n lines.push(` Avg cost/session: ${fmtCost(data.avgCostPerSession)}`);\n lines.push(` Avg tokens/request: ${fmtNum(data.avgTokensPerRequest)}`);\n lines.push(` Model: ${data.model}`);\n lines.push('');\n\n // Daily breakdown (spark-bar chart)\n const activeDays = data.byDay.filter((d) => d.sessions > 0);\n if (activeDays.length > 0) {\n lines.push('DAILY USAGE');\n lines.push('─'.repeat(40));\n const maxTokens = Math.max(...activeDays.map((d) => d.inputTokens), 1);\n for (const day of data.byDay) {\n if (day.sessions === 0) continue;\n const b = bar(day.inputTokens, maxTokens, 18);\n lines.push(\n ` ${day.date} ${b} ${fmtK(day.inputTokens)} in ${fmtCost(day.costUsd)} (${day.sessions} sess)`\n );\n }\n lines.push('');\n }\n\n // Top files\n if (data.topFiles.length > 0) {\n lines.push('TOP FILES READ');\n lines.push('─'.repeat(40));\n const maxReads = Math.max(...data.topFiles.map((f) => f.readCount), 1);\n for (let i = 0; i < data.topFiles.length; i++) {\n const f = data.topFiles[i];\n const b = bar(f.readCount, maxReads, 12);\n lines.push(` ${String(i + 1).padStart(2)}. ${b} ×${f.readCount} ${shortPath(f.filePath)}`);\n }\n lines.push('');\n } else {\n lines.push(' No file-read data. Install hooks: claudectx optimize --hooks');\n lines.push('');\n }\n\n // Optimisation tips\n const tips: string[] = [];\n if (data.cacheHitRate < 30 && data.totalRequests > 5) {\n tips.push('Cache hit rate is low — run `claudectx optimize --cache` to fix dynamic content.');\n }\n if (data.avgTokensPerRequest > 10_000) {\n tips.push('High tokens/request — run `claudectx optimize --claudemd` to split your CLAUDE.md.');\n }\n if (data.topFiles.length === 0) {\n tips.push('Install hooks to track file reads: `claudectx optimize --hooks`.');\n }\n\n if (tips.length > 0) {\n lines.push('OPTIMISATION TIPS');\n lines.push('─'.repeat(40));\n tips.forEach((t) => lines.push(` ⚡ ${t}`));\n lines.push('');\n }\n\n lines.push(`Generated at: ${data.generatedAt}`);\n\n return lines.join('\\n');\n}\n\n// ─── JSON ─────────────────────────────────────────────────────────────────────\n\nexport function formatJSON(data: ReportData): string {\n return JSON.stringify(data, null, 2);\n}\n\n// ─── Markdown ─────────────────────────────────────────────────────────────────\n\nexport function formatMarkdown(data: ReportData): string {\n const lines: string[] = [];\n\n lines.push(`# claudectx Report`);\n lines.push('');\n lines.push(`**Period:** ${data.startDate} → ${data.endDate} (${data.periodDays} days)`);\n lines.push(`**Generated:** ${new Date(data.generatedAt).toLocaleString()}`);\n lines.push('');\n\n lines.push('## Summary');\n lines.push('');\n lines.push('| Metric | Value |');\n lines.push('|--------|-------|');\n lines.push(`| Sessions | ${fmtNum(data.totalSessions)} |`);\n lines.push(`| Requests | ${fmtNum(data.totalRequests)} |`);\n lines.push(`| Input tokens | ${fmtNum(data.totalInputTokens)} |`);\n lines.push(`| Output tokens | ${fmtNum(data.totalOutputTokens)} |`);\n lines.push(`| Cache hit rate | ${data.cacheHitRate}% |`);\n lines.push(`| Total cost (est.) | ${fmtCost(data.totalCostUsd)} |`);\n lines.push(`| Avg cost/session | ${fmtCost(data.avgCostPerSession)} |`);\n lines.push(`| Avg tokens/request | ${fmtNum(data.avgTokensPerRequest)} |`);\n lines.push(`| Model | \\`${data.model}\\` |`);\n lines.push('');\n\n const activeDays = data.byDay.filter((d) => d.sessions > 0);\n if (activeDays.length > 0) {\n lines.push('## Daily Breakdown');\n lines.push('');\n lines.push('| Date | Sessions | Input tokens | Cost |');\n lines.push('|------|----------|-------------|------|');\n for (const day of activeDays) {\n lines.push(\n `| ${day.date} | ${day.sessions} | ${fmtK(day.inputTokens)} | ${fmtCost(day.costUsd)} |`\n );\n }\n lines.push('');\n }\n\n if (data.topFiles.length > 0) {\n lines.push('## Top Files Read');\n lines.push('');\n lines.push('| # | File | Reads |');\n lines.push('|---|------|-------|');\n data.topFiles.forEach((f, i) => {\n lines.push(`| ${i + 1} | \\`${shortPath(f.filePath)}\\` | ${f.readCount} |`);\n });\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n// ─── Dispatcher ───────────────────────────────────────────────────────────────\n\nexport function format(\n data: ReportData,\n mode: 'text' | 'json' | 'markdown'\n): string {\n switch (mode) {\n case 'json':\n return formatJSON(data);\n case 'markdown':\n return formatMarkdown(data);\n default:\n return formatText(data);\n }\n}\n"],"mappings":"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","names":["fs","os","path","fs","os","path","fileStats","sessionFile","usage","fs","path","fs","path","fs","path","path","import_path","fs","path","os","import_fs","import_path","path","fs","chalk","boxen","Table","path","watch","fs","path","import_chalk","import_boxen","import_chalk","chalk","fs","path","fs","path","fs","fs","path","boxen","chalk","path","clearStore","React","Dashboard","resolve","path","import_chalk","fs","path","chalk","startMcpServer","path","fs","fs","Conf","shortPath","fs","path","chalk","calcCost","fmtNum","fmtCost","shortPath","MODEL_ALIASES"]}