claudectx 1.0.0 → 1.1.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.
- package/dist/index.js +1301 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1301 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +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"]}
|
|
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","../src/commands/budget.ts","../src/analyzer/budget-estimator.ts","../src/commands/warmup.ts","../src/commands/drift.ts","../src/analyzer/drift-detector.ts","../src/commands/hooks.ts","../src/hooks/registry.ts","../src/commands/convert.ts","../src/commands/teams.ts","../src/reporter/team-aggregator.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';\nimport { budgetCommand } from './commands/budget.js';\nimport { warmupCommand } from './commands/warmup.js';\nimport { driftCommand } from './commands/drift.js';\nimport { hooksCommand } from './commands/hooks.js';\nimport { convertCommand } from './commands/convert.js';\nimport { teamsCommand } from './commands/teams.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\n// ─── budget ───────────────────────────────────────────────────────────────────\nprogram\n .command('budget <globs...>')\n .description('Estimate token cost before running a task')\n .option('-m, --model <model>', 'Model for cost estimates (haiku|sonnet|opus)', 'sonnet')\n .option('--threshold <n>', 'Warn if total exceeds N tokens', '10000')\n .option('-p, --path <path>', 'Project directory')\n .option('--json', 'JSON output')\n .action(async (globs: string[], options) => {\n await budgetCommand(globs, options);\n });\n\n// ─── warmup ───────────────────────────────────────────────────────────────────\nprogram\n .command('warmup')\n .description('Pre-warm the Anthropic prompt cache with your CLAUDE.md')\n .option('-m, --model <model>', 'Model (haiku|sonnet|opus)', 'haiku')\n .option('--ttl <minutes>', 'Cache TTL: 5 or 60', '5')\n .option('--cron <expr>', 'Install as cron job (e.g. \"0 9 * * 1-5\")')\n .option('--api-key <key>', 'Anthropic API key')\n .option('-p, --path <path>', 'Project directory')\n .option('--json', 'JSON output')\n .action(async (options) => {\n await warmupCommand(options);\n });\n\n// ─── drift ────────────────────────────────────────────────────────────────────\nprogram\n .command('drift')\n .description('Detect stale references and dead sections in CLAUDE.md')\n .option('-p, --path <path>', 'Project directory')\n .option('--days <n>', 'Days window for section usage', '30')\n .option('--fix', 'Interactively remove flagged lines')\n .option('--json', 'JSON output')\n .action(async (options) => {\n await driftCommand(options);\n });\n\n// ─── hooks ────────────────────────────────────────────────────────────────────\nprogram\n .command('hooks [subcommand] [name]')\n .description('Hook marketplace: list | add <name> | remove <name> | status')\n .option('-p, --path <path>', 'Project directory')\n .option('--config <pair...>', 'key=value config pairs for add')\n .action(async (subcommand: string | undefined, name: string | undefined, options) => {\n await hooksCommand(subcommand, { ...options, name });\n });\n\n// ─── convert ──────────────────────────────────────────────────────────────────\nprogram\n .command('convert')\n .description('Convert CLAUDE.md to another AI assistant format')\n .option('--from <assistant>', 'Source format (default: claude)', 'claude')\n .requiredOption('--to <assistant>', 'Target format: cursor | copilot | windsurf')\n .option('--dry-run', 'Preview without writing')\n .option('-p, --path <path>', 'Project directory')\n .action(async (options) => {\n await convertCommand(options);\n });\n\n// ─── teams ────────────────────────────────────────────────────────────────────\nprogram\n .command('teams [subcommand]')\n .description('Multi-developer cost attribution (export | aggregate | share)')\n .option('--days <n>', 'Days to include', '30')\n .option('-m, --model <model>', 'Model', 'sonnet')\n .option('--anonymize', 'Replace identities with Dev 1, Dev 2...')\n .option('--dir <path>', 'Directory with team export JSON files')\n .option('--to <path>', 'Destination for share sub-command')\n .option('--json', 'JSON output')\n .action(async (subcommand: string | undefined, options) => {\n await teamsCommand(subcommand ?? 'export', 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 * Write arbitrary merged settings to .claude/settings.local.json.\n * Used by the hooks marketplace to add/remove named hooks.\n */\nexport function writeHooksSettings(\n projectRoot: string,\n mergedSettings: unknown,\n): void {\n const settingsPath = path.join(projectRoot, '.claude', 'settings.local.json');\n const dir = path.dirname(settingsPath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n fs.writeFileSync(settingsPath, JSON.stringify(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","import * as path from 'path';\nimport { findProjectRoot } from '../analyzer/context-parser.js';\nimport { estimateBudget, formatBudgetReport } from '../analyzer/budget-estimator.js';\nimport { resolveModel } from '../shared/models.js';\n\nexport interface BudgetOptions {\n path?: string;\n model?: string;\n threshold?: string;\n json?: boolean;\n}\n\nexport async function budgetCommand(globs: string[], options: BudgetOptions): Promise<void> {\n const projectPath = options.path ? path.resolve(options.path) : process.cwd();\n const projectRoot = findProjectRoot(projectPath) ?? projectPath;\n const model = resolveModel(options.model ?? 'sonnet');\n const thresholdTokens = parseInt(options.threshold ?? '10000', 10);\n\n if (globs.length === 0) {\n process.stderr.write('Error: at least one glob pattern is required.\\n');\n process.stderr.write('Example: claudectx budget \"src/**/*.ts\"\\n');\n process.exit(1);\n }\n\n const report = await estimateBudget(globs, projectRoot, model, thresholdTokens);\n\n if (options.json) {\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n return;\n }\n\n process.stdout.write(formatBudgetReport(report));\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { glob } from 'glob';\nimport { countTokens } from './tokenizer.js';\nimport { tokenCost, formatCost } from './cost-calculator.js';\nimport { readAllEvents } from '../watcher/session-store.js';\nimport type { ClaudeModel } from '../shared/types.js';\nimport { WASTE_THRESHOLDS } from '../shared/constants.js';\n\nexport interface FileTokenEntry {\n filePath: string;\n tokenCount: number;\n recentReadCount: number;\n cacheHitLikelihood: 'high' | 'medium' | 'low';\n estimatedCostUsd: number;\n}\n\nexport interface BudgetReport {\n globs: string[];\n model: ClaudeModel;\n files: FileTokenEntry[];\n totalTokens: number;\n totalEstimatedCostUsd: number;\n thresholdExceeded: boolean;\n thresholdTokens: number;\n cacheHitPotential: number; // 0-100, weighted % of tokens likely to cache-hit\n claudeignoreRecommendations: string[];\n}\n\n/**\n * Resolve glob patterns to matching file paths within projectRoot.\n */\nexport function resolveGlobs(globs: string[], projectRoot: string): string[] {\n const results: string[] = [];\n for (const pattern of globs) {\n try {\n const matches = glob.sync(pattern, {\n cwd: projectRoot,\n absolute: true,\n nodir: true,\n ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**', '**/*.min.js'],\n });\n results.push(...matches);\n } catch {\n // Skip invalid patterns\n }\n }\n // Deduplicate\n return [...new Set(results)];\n}\n\n/**\n * Classify cache hit likelihood based on how many times the file was read recently.\n */\nexport function classifyCacheHit(recentReadCount: number): 'high' | 'medium' | 'low' {\n if (recentReadCount >= 3) return 'high';\n if (recentReadCount >= 1) return 'medium';\n return 'low';\n}\n\n/**\n * Suggest files that should be added to .claudeignore (large files not already ignored).\n */\nexport function suggestClaudeignoreAdditions(\n files: FileTokenEntry[],\n projectRoot: string,\n): string[] {\n const ignorePath = path.join(projectRoot, '.claudeignore');\n let ignorePatterns: string[] = [];\n try {\n const content = fs.readFileSync(ignorePath, 'utf-8');\n ignorePatterns = content.split('\\n').filter(Boolean);\n } catch {\n // No .claudeignore — all large files are candidates\n }\n\n const recommendations: string[] = [];\n for (const file of files) {\n if (file.tokenCount <= WASTE_THRESHOLDS.MAX_REFERENCE_FILE_TOKENS) continue;\n\n const rel = path.relative(projectRoot, file.filePath);\n // Check if already covered by an existing ignore pattern\n const alreadyIgnored = ignorePatterns.some((pattern) => {\n const cleanPattern = pattern.replace(/^!/, '');\n return rel.startsWith(cleanPattern.replace(/\\*/g, '').replace(/\\//g, path.sep));\n });\n\n if (!alreadyIgnored) {\n recommendations.push(rel);\n }\n }\n return recommendations;\n}\n\n/**\n * Estimate token budget for the given file globs.\n */\nexport async function estimateBudget(\n globs: string[],\n projectRoot: string,\n model: ClaudeModel,\n thresholdTokens: number,\n): Promise<BudgetReport> {\n // Resolve globs to file paths\n const filePaths = resolveGlobs(globs, projectRoot);\n\n // Build recent read count map from reads.jsonl\n const events = readAllEvents();\n const readCounts = new Map<string, number>();\n for (const event of events) {\n const count = readCounts.get(event.filePath) ?? 0;\n readCounts.set(event.filePath, count + 1);\n }\n\n // Build per-file entries\n const files: FileTokenEntry[] = [];\n for (const filePath of filePaths) {\n let content = '';\n try {\n content = fs.readFileSync(filePath, 'utf-8');\n } catch {\n continue;\n }\n\n const tokenCount = countTokens(content);\n const recentReadCount = readCounts.get(filePath) ?? 0;\n const cacheHitLikelihood = classifyCacheHit(recentReadCount);\n const estimatedCostUsd = tokenCost(tokenCount, model);\n\n files.push({\n filePath,\n tokenCount,\n recentReadCount,\n cacheHitLikelihood,\n estimatedCostUsd,\n });\n }\n\n // Sort by token count descending\n files.sort((a, b) => b.tokenCount - a.tokenCount);\n\n const totalTokens = files.reduce((sum, f) => sum + f.tokenCount, 0);\n const totalEstimatedCostUsd = tokenCost(totalTokens, model);\n\n // Cache hit potential: weighted average\n // high = 0.85, medium = 0.50, low = 0.0\n const CACHE_WEIGHTS = { high: 0.85, medium: 0.5, low: 0 };\n let weightedSum = 0;\n for (const f of files) {\n weightedSum += f.tokenCount * CACHE_WEIGHTS[f.cacheHitLikelihood];\n }\n const cacheHitPotential = totalTokens > 0 ? Math.round((weightedSum / totalTokens) * 100) : 0;\n\n const claudeignoreRecommendations = suggestClaudeignoreAdditions(files, projectRoot);\n\n return {\n globs,\n model,\n files,\n totalTokens,\n totalEstimatedCostUsd,\n thresholdExceeded: totalTokens > thresholdTokens,\n thresholdTokens,\n cacheHitPotential,\n claudeignoreRecommendations,\n };\n}\n\n/** Format a budget report as a human-readable string */\nexport function formatBudgetReport(report: BudgetReport): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push('claudectx budget — context cost estimate');\n lines.push('═'.repeat(50));\n\n if (report.files.length === 0) {\n lines.push('No files matched the given glob patterns.');\n return lines.join('\\n');\n }\n\n // File table\n const LIKELIHOOD_ICON = { high: '🟢', medium: '🟡', low: '🔴' };\n const maxPathLen = Math.min(\n Math.max(...report.files.map((f) => path.basename(f.filePath).length)),\n 40,\n );\n\n lines.push(\n ` ${'File'.padEnd(maxPathLen)} ${'Tokens'.padStart(7)} Cache Cost`,\n );\n lines.push('─'.repeat(50));\n\n for (const file of report.files.slice(0, 20)) {\n const name = path.basename(file.filePath).slice(0, maxPathLen).padEnd(maxPathLen);\n const tokens = file.tokenCount.toLocaleString().padStart(7);\n const cache = `${LIKELIHOOD_ICON[file.cacheHitLikelihood]} ${file.cacheHitLikelihood.padEnd(6)}`;\n const cost = formatCost(file.estimatedCostUsd).padStart(7);\n lines.push(` ${name} ${tokens} ${cache} ${cost}`);\n }\n if (report.files.length > 20) {\n lines.push(` ... and ${report.files.length - 20} more files`);\n }\n\n lines.push('─'.repeat(50));\n\n const thresholdStatus = report.thresholdExceeded\n ? `⚠ EXCEEDS threshold (${report.thresholdTokens.toLocaleString()} tokens)`\n : `✓ Within threshold (${report.thresholdTokens.toLocaleString()} tokens)`;\n\n lines.push(` Total tokens: ${report.totalTokens.toLocaleString().padStart(10)}`);\n lines.push(` Estimated cost: ${formatCost(report.totalEstimatedCostUsd).padStart(10)}`);\n lines.push(` Cache potential: ${`${report.cacheHitPotential}%`.padStart(10)}`);\n lines.push(` ${thresholdStatus}`);\n\n if (report.claudeignoreRecommendations.length > 0) {\n lines.push('');\n lines.push(' 💡 Add to .claudeignore to exclude large files:');\n for (const rec of report.claudeignoreRecommendations.slice(0, 5)) {\n lines.push(` ${rec}`);\n }\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n","import * as path from 'path';\nimport Anthropic from '@anthropic-ai/sdk';\nimport { findProjectRoot } from '../analyzer/context-parser.js';\nimport { MODEL_PRICING, resolveModel } from '../shared/models.js';\nimport { formatCost } from '../analyzer/cost-calculator.js';\nimport type { ClaudeModel } from '../shared/types.js';\nimport fs from 'fs';\n\nexport interface WarmupOptions {\n path?: string;\n model?: string;\n ttl?: string;\n cron?: string;\n apiKey?: string;\n json?: boolean;\n}\n\nexport interface WarmupResult {\n model: string;\n tokensWarmed: number;\n cacheWriteCostUsd: number;\n estimatedSavingsPerHit: number;\n breakEvenRequests: number;\n ttlMinutes: number;\n timestamp: string;\n}\n\n/**\n * Build the messages array for the warmup request.\n * The CLAUDE.md content is placed in the system block with cache_control.\n */\nexport function buildWarmupMessages(\n claudeMdContent: string,\n): { system: Anthropic.TextBlockParam[]; messages: Anthropic.MessageParam[] } {\n const systemBlock: Anthropic.TextBlockParam = {\n type: 'text',\n text: claudeMdContent || '# Project\\nNo CLAUDE.md found.',\n // @ts-expect-error — cache_control is valid but not yet in the TS types for all SDKs\n cache_control: { type: 'ephemeral' },\n };\n\n return {\n system: [systemBlock],\n messages: [\n {\n role: 'user',\n content: 'ping',\n },\n ],\n };\n}\n\n/**\n * Calculate how many cache reads needed to break even on the write cost.\n */\nexport function calculateBreakEven(\n writeTokens: number,\n model: ClaudeModel,\n ttlMinutes: 5 | 60,\n): { breakEvenRequests: number; savingsPerHit: number; writeCostUsd: number } {\n const pricing = MODEL_PRICING[model];\n const writeMultiplier = ttlMinutes === 60 ? 2.0 : 1.25; // extended TTL costs 2x, standard is 1.25x\n const writeCostPerMillion = pricing.inputPerMillion * writeMultiplier;\n\n const writeCostUsd = (writeTokens / 1_000_000) * writeCostPerMillion;\n const readCostUsd = (writeTokens / 1_000_000) * pricing.cacheReadPerMillion;\n const inputCostUsd = (writeTokens / 1_000_000) * pricing.inputPerMillion;\n\n const savingsPerHit = inputCostUsd - readCostUsd;\n const breakEvenRequests = savingsPerHit > 0 ? Math.ceil(writeCostUsd / savingsPerHit) : 999;\n\n return { breakEvenRequests, savingsPerHit, writeCostUsd };\n}\n\n/**\n * Execute a warmup request. Accepts an injectable Anthropic client for testing.\n */\nexport async function executeWarmup(\n claudeMdContent: string,\n model: ClaudeModel,\n ttl: 5 | 60,\n client: Anthropic,\n): Promise<WarmupResult> {\n const { system, messages } = buildWarmupMessages(claudeMdContent);\n\n const betas: string[] = ['prompt-caching-2024-07-31'];\n if (ttl === 60) betas.push('extended-cache-ttl-2025-02-19');\n\n const response = await client.beta.messages.create({\n model,\n max_tokens: 8,\n system,\n messages,\n betas,\n });\n\n const usage = response.usage as Record<string, number>;\n const tokensWarmed = usage.cache_creation_input_tokens ?? 0;\n\n const { breakEvenRequests, savingsPerHit, writeCostUsd } = calculateBreakEven(\n tokensWarmed,\n model,\n ttl,\n );\n\n return {\n model,\n tokensWarmed,\n cacheWriteCostUsd: writeCostUsd,\n estimatedSavingsPerHit: savingsPerHit,\n breakEvenRequests,\n ttlMinutes: ttl,\n timestamp: new Date().toISOString(),\n };\n}\n\n/**\n * Install a cron job that runs `claudectx warmup` on a schedule.\n */\nasync function installCron(cronExpr: string, apiKey: string): Promise<void> {\n const { execSync } = await import('child_process');\n const command = `claudectx warmup --api-key ${apiKey}`;\n const cronLine = `${cronExpr} ${command}`;\n\n try {\n let existing = '';\n try {\n existing = execSync('crontab -l 2>/dev/null', { encoding: 'utf-8' });\n } catch {\n existing = '';\n }\n\n if (existing.includes('claudectx warmup')) {\n process.stdout.write('Cron job already installed for claudectx warmup.\\n');\n return;\n }\n\n const newCrontab = existing.trimEnd() + '\\n' + cronLine + '\\n';\n execSync(`echo ${JSON.stringify(newCrontab)} | crontab -`);\n process.stdout.write(`✓ Cron job installed: ${cronLine}\\n`);\n } catch {\n process.stdout.write(`Could not install cron automatically. Add manually:\\n ${cronLine}\\n`);\n }\n}\n\nexport async function warmupCommand(options: WarmupOptions): Promise<void> {\n const projectPath = options.path ? path.resolve(options.path) : process.cwd();\n const projectRoot = findProjectRoot(projectPath) ?? projectPath;\n const model = resolveModel(options.model ?? 'haiku');\n const ttl = (options.ttl === '60' ? 60 : 5) as 5 | 60;\n const apiKey = options.apiKey ?? process.env.ANTHROPIC_API_KEY;\n\n if (!apiKey) {\n process.stderr.write(\n 'Error: Anthropic API key required. Use --api-key or set ANTHROPIC_API_KEY.\\n',\n );\n process.exit(1);\n }\n\n // Read CLAUDE.md\n let claudeMdContent = '';\n const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');\n try {\n claudeMdContent = fs.readFileSync(claudeMdPath, 'utf-8');\n } catch {\n process.stderr.write(`Warning: No CLAUDE.md found at ${claudeMdPath}\\n`);\n }\n\n const client = new Anthropic({ apiKey });\n\n if (!options.json) {\n process.stdout.write(`Warming up prompt cache (model: ${model}, TTL: ${ttl}min)...\\n`);\n }\n\n let result: WarmupResult;\n try {\n result = await executeWarmup(claudeMdContent, model, ttl, client);\n } catch (err) {\n process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exit(1);\n }\n\n if (options.json) {\n process.stdout.write(JSON.stringify(result, null, 2) + '\\n');\n return;\n }\n\n process.stdout.write('\\n');\n process.stdout.write('claudectx warmup — prompt cache primed\\n');\n process.stdout.write('═'.repeat(45) + '\\n');\n process.stdout.write(` Model: ${result.model}\\n`);\n process.stdout.write(` Tokens warmed: ${result.tokensWarmed.toLocaleString()}\\n`);\n process.stdout.write(` Cache write cost: ${formatCost(result.cacheWriteCostUsd)}\\n`);\n process.stdout.write(` Savings per hit: ${formatCost(result.estimatedSavingsPerHit)}\\n`);\n process.stdout.write(` Break-even after: ${result.breakEvenRequests} requests\\n`);\n process.stdout.write(` TTL: ${result.ttlMinutes} minutes\\n`);\n process.stdout.write('\\n');\n\n if (result.tokensWarmed === 0) {\n process.stdout.write(\n ' ⚠ No tokens were cached. CLAUDE.md may be below the minimum token threshold\\n' +\n ` (${model === 'claude-haiku-4-5' ? '4,096' : '1,024'} tokens for ${model}).\\n`,\n );\n } else {\n process.stdout.write(\n ` ✓ First ${result.ttlMinutes === 60 ? '60-minute' : '5-minute'} window of requests will benefit from cache hits.\\n`,\n );\n }\n process.stdout.write('\\n');\n\n if (options.cron) {\n await installCron(options.cron, apiKey);\n }\n}\n","import * as path from 'path';\nimport * as fs from 'fs';\nimport { findProjectRoot } from '../analyzer/context-parser.js';\nimport { detectDrift } from '../analyzer/drift-detector.js';\nimport type { DriftIssue } from '../analyzer/drift-detector.js';\n\nexport interface DriftOptions {\n path?: string;\n days?: string;\n fix?: boolean;\n json?: boolean;\n}\n\nconst SEVERITY_ICON: Record<DriftIssue['severity'], string> = {\n error: '✖',\n warning: '⚠',\n info: '·',\n};\n\nconst TYPE_LABEL: Record<DriftIssue['type'], string> = {\n 'dead-ref': 'Dead @ref',\n 'git-deleted': 'Git deleted',\n 'stale-section': 'Stale section',\n 'dead-inline-path': 'Dead path',\n};\n\nexport async function driftCommand(options: DriftOptions): Promise<void> {\n const projectPath = options.path ? path.resolve(options.path) : process.cwd();\n const projectRoot = findProjectRoot(projectPath) ?? projectPath;\n const dayWindow = parseInt(options.days ?? '30', 10);\n\n const report = await detectDrift(projectRoot, dayWindow);\n\n if (options.json) {\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n return;\n }\n\n process.stdout.write('\\n');\n process.stdout.write('claudectx drift — CLAUDE.md staleness check\\n');\n process.stdout.write('═'.repeat(55) + '\\n');\n process.stdout.write(` File: ${report.claudeMdPath}\\n`);\n process.stdout.write(` Window: last ${report.dayWindow} days\\n`);\n process.stdout.write('\\n');\n\n if (report.issues.length === 0) {\n process.stdout.write(' ✓ No drift detected. CLAUDE.md looks clean.\\n\\n');\n return;\n }\n\n // Print issues table\n process.stdout.write(\n ` ${'Line'.padEnd(5)} ${'Type'.padEnd(14)} ${'Waste'.padStart(6)} Issue\\n`,\n );\n process.stdout.write('─'.repeat(55) + '\\n');\n\n for (const issue of report.issues) {\n const icon = SEVERITY_ICON[issue.severity];\n const typeLabel = TYPE_LABEL[issue.type].padEnd(14);\n const waste = `${issue.estimatedTokenWaste}t`.padStart(6);\n const lineNum = String(issue.line).padEnd(5);\n const text = issue.text.slice(0, 40);\n process.stdout.write(` ${lineNum} ${typeLabel} ${waste} ${icon} ${text}\\n`);\n }\n\n process.stdout.write('─'.repeat(55) + '\\n');\n process.stdout.write(\n ` ${report.issues.length} issue(s) found · ~${report.totalWastedTokens} tokens wasted\\n`,\n );\n process.stdout.write('\\n');\n\n // Print suggestions\n if (report.issues.length > 0) {\n process.stdout.write(' Suggestions:\\n');\n const shown = new Set<string>();\n for (const issue of report.issues.slice(0, 5)) {\n if (!shown.has(issue.suggestion)) {\n process.stdout.write(` Line ${issue.line}: ${issue.suggestion}\\n`);\n shown.add(issue.suggestion);\n }\n }\n process.stdout.write('\\n');\n }\n\n // Interactive fix mode\n if (options.fix && report.issues.length > 0) {\n await applyFix(report.claudeMdPath, report.issues);\n } else if (report.issues.length > 0 && !options.fix) {\n process.stdout.write(' Run with --fix to interactively remove flagged lines.\\n\\n');\n }\n}\n\nasync function applyFix(claudeMdPath: string, issues: DriftIssue[]): Promise<void> {\n // Dynamically import to keep startup fast\n const { checkbox } = await import('@inquirer/prompts').catch(() => {\n process.stderr.write('Error: @inquirer/prompts is required for --fix mode. Run: npm install -g @inquirer/prompts\\n');\n process.exit(1);\n });\n\n const choices = issues.map((issue) => ({\n name: `Line ${issue.line}: ${issue.text.slice(0, 60)} (${issue.estimatedTokenWaste}t)`,\n value: issue.line,\n checked: issue.severity === 'error',\n }));\n\n const selectedLines: number[] = await checkbox({\n message: 'Select lines to remove from CLAUDE.md:',\n choices,\n });\n\n if (selectedLines.length === 0) {\n process.stdout.write('No lines selected. Nothing changed.\\n');\n return;\n }\n\n const content = fs.readFileSync(claudeMdPath, 'utf-8');\n const lines = content.split('\\n');\n const lineSet = new Set(selectedLines.map((l) => l - 1)); // 0-indexed\n const newLines = lines.filter((_, i) => !lineSet.has(i));\n\n fs.writeFileSync(claudeMdPath, newLines.join('\\n'), 'utf-8');\n process.stdout.write(`\\n ✓ Removed ${selectedLines.length} line(s) from ${claudeMdPath}\\n\\n`);\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as childProcess from 'child_process';\nimport { countTokens } from './tokenizer.js';\nimport { readAllEvents } from '../watcher/session-store.js';\nimport type { FileReadEvent } from '../watcher/session-store.js';\n\nexport interface DriftIssue {\n type: 'dead-ref' | 'git-deleted' | 'stale-section' | 'dead-inline-path';\n line: number;\n text: string;\n severity: 'error' | 'warning' | 'info';\n estimatedTokenWaste: number;\n suggestion: string;\n}\n\nexport interface DriftReport {\n claudeMdPath: string;\n analyzedAt: string;\n dayWindow: number;\n issues: DriftIssue[];\n totalWastedTokens: number;\n}\n\n/** Regex for inline file paths in prose (e.g. src/old/file.py, ./lib/helper.ts) */\nconst INLINE_PATH_RE = /(?:^|\\s)((?:\\.{1,2}\\/|src\\/|lib\\/|docs\\/|app\\/|tests?\\/)\\S+\\.\\w{1,6})/gm;\n\n/** Regex for @file references */\nconst AT_REF_RE = /^@(.+)$/;\n\n/**\n * Find @file references in CLAUDE.md that don't exist on disk.\n */\nexport function findDeadAtReferences(content: string, projectRoot: string): DriftIssue[] {\n const issues: DriftIssue[] = [];\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const match = lines[i].match(AT_REF_RE);\n if (!match) continue;\n\n const ref = match[1].trim();\n const absPath = path.isAbsolute(ref) ? ref : path.join(projectRoot, ref);\n\n if (!fs.existsSync(absPath)) {\n const lineText = lines[i];\n issues.push({\n type: 'dead-ref',\n line: i + 1,\n text: lineText,\n severity: 'error',\n estimatedTokenWaste: countTokens(lineText),\n suggestion: `File \"${ref}\" does not exist. Remove this @reference or update the path.`,\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Find files mentioned in CLAUDE.md that git shows as deleted.\n * Degrades gracefully in non-git directories.\n */\nexport async function findGitDeletedMentions(\n content: string,\n projectRoot: string,\n): Promise<DriftIssue[]> {\n const issues: DriftIssue[] = [];\n\n // Get list of git-deleted files\n let deletedFiles: Set<string> = new Set();\n try {\n const output = childProcess.execSync(\n 'git log --diff-filter=D --name-only --pretty=format: --',\n { cwd: projectRoot, encoding: 'utf-8', timeout: 5000, stdio: ['pipe', 'pipe', 'pipe'] },\n );\n deletedFiles = new Set(\n output\n .split('\\n')\n .map((f) => f.trim())\n .filter(Boolean),\n );\n } catch {\n // Not a git repo or git not installed — skip silently\n return [];\n }\n\n if (deletedFiles.size === 0) return [];\n\n const lines = content.split('\\n');\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n for (const deleted of deletedFiles) {\n // Check if this deleted file name appears in the line\n const basename = path.basename(deleted);\n if (line.includes(basename) || line.includes(deleted)) {\n issues.push({\n type: 'git-deleted',\n line: i + 1,\n text: line.trim(),\n severity: 'warning',\n estimatedTokenWaste: countTokens(line),\n suggestion: `References \"${basename}\" which was deleted from git. Consider removing this mention.`,\n });\n break; // Only one issue per line\n }\n }\n }\n\n return issues;\n}\n\n/**\n * Find ## sections that have had zero file reads match their topic in the last N days.\n */\nexport function findStaleSections(\n content: string,\n events: FileReadEvent[],\n dayWindow: number,\n): DriftIssue[] {\n const issues: DriftIssue[] = [];\n\n // Filter events to the day window\n const cutoff = Date.now() - dayWindow * 24 * 60 * 60 * 1000;\n const recentEvents = events.filter((e) => new Date(e.timestamp).getTime() >= cutoff);\n\n // Build a set of all recently-read file paths (lowercased for fuzzy matching)\n const recentPaths = new Set(\n recentEvents.map((e) => e.filePath.toLowerCase()),\n );\n\n // Parse sections: ## Header lines\n const lines = content.split('\\n');\n const sections: Array<{ line: number; header: string; bodyLines: string[] }> = [];\n\n let currentSection: { line: number; header: string; bodyLines: string[] } | null = null;\n\n for (let i = 0; i < lines.length; i++) {\n const sectionMatch = lines[i].match(/^#{1,3}\\s+(.+)$/);\n if (sectionMatch) {\n if (currentSection) sections.push(currentSection);\n currentSection = { line: i + 1, header: sectionMatch[1], bodyLines: [] };\n } else if (currentSection) {\n currentSection.bodyLines.push(lines[i]);\n }\n }\n if (currentSection) sections.push(currentSection);\n\n for (const section of sections) {\n // Check if any recently-read file path contains a word from the section header\n const headerWords = section.header\n .toLowerCase()\n .split(/\\W+/)\n .filter((w) => w.length > 3);\n\n const matched = headerWords.some((word) =>\n [...recentPaths].some((p) => {\n if (p.includes(word)) return true;\n // Also check if any path segment starts with the header word or vice-versa\n // e.g. \"testing\" matches paths containing \"tests\"\n const segments = p.split(/[/\\\\.]/).filter((s) => s.length >= 4);\n return segments.some((seg) => word.startsWith(seg) || seg.startsWith(word));\n }),\n );\n\n if (!matched && recentEvents.length > 0) {\n const sectionContent = section.bodyLines.join('\\n');\n issues.push({\n type: 'stale-section',\n line: section.line,\n text: `## ${section.header}`,\n severity: 'info',\n estimatedTokenWaste: countTokens(`## ${section.header}\\n${sectionContent}`),\n suggestion: `Section \"## ${section.header}\" had no matching file reads in the last ${dayWindow} days. Consider removing or archiving it.`,\n });\n }\n }\n\n return issues;\n}\n\n/**\n * Find inline file paths in prose that no longer exist on disk.\n */\nexport function findDeadInlinePaths(content: string, projectRoot: string): DriftIssue[] {\n const issues: DriftIssue[] = [];\n const lines = content.split('\\n');\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n // Skip @reference lines (handled by findDeadAtReferences)\n if (AT_REF_RE.test(line)) continue;\n\n let match: RegExpExecArray | null;\n INLINE_PATH_RE.lastIndex = 0;\n const seen = new Set<string>();\n\n while ((match = INLINE_PATH_RE.exec(line)) !== null) {\n const rawPath = match[1].trim();\n if (seen.has(rawPath)) continue;\n seen.add(rawPath);\n\n const absPath = path.isAbsolute(rawPath) ? rawPath : path.join(projectRoot, rawPath);\n if (!fs.existsSync(absPath)) {\n issues.push({\n type: 'dead-inline-path',\n line: i + 1,\n text: line.trim(),\n severity: 'warning',\n estimatedTokenWaste: countTokens(rawPath),\n suggestion: `Path \"${rawPath}\" no longer exists. Update or remove this reference.`,\n });\n break; // One issue per line to avoid noise\n }\n }\n }\n\n return issues;\n}\n\n/**\n * Run all drift checks and produce a consolidated report.\n */\nexport async function detectDrift(projectRoot: string, dayWindow: number): Promise<DriftReport> {\n const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');\n let content = '';\n try {\n content = fs.readFileSync(claudeMdPath, 'utf-8');\n } catch {\n // No CLAUDE.md — return empty report\n return {\n claudeMdPath,\n analyzedAt: new Date().toISOString(),\n dayWindow,\n issues: [],\n totalWastedTokens: 0,\n };\n }\n\n const events = readAllEvents();\n\n const [deadRefs, gitDeleted, staleSections, deadInlinePaths] = await Promise.all([\n Promise.resolve(findDeadAtReferences(content, projectRoot)),\n findGitDeletedMentions(content, projectRoot),\n Promise.resolve(findStaleSections(content, events, dayWindow)),\n Promise.resolve(findDeadInlinePaths(content, projectRoot)),\n ]);\n\n const allIssues = [...deadRefs, ...gitDeleted, ...staleSections, ...deadInlinePaths];\n // Sort by line number\n allIssues.sort((a, b) => a.line - b.line);\n\n const totalWastedTokens = allIssues.reduce((sum, i) => sum + i.estimatedTokenWaste, 0);\n\n return {\n claudeMdPath,\n analyzedAt: new Date().toISOString(),\n dayWindow,\n issues: allIssues,\n totalWastedTokens,\n };\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { findProjectRoot } from '../analyzer/context-parser.js';\nimport { HOOK_REGISTRY, getHook, buildHookEntry, interpolateCommand } from '../hooks/registry.js';\nimport { writeHooksSettings } from '../optimizer/hooks-installer.js';\n\nexport interface HooksOptions {\n path?: string;\n config?: string[];\n name?: string;\n}\n\ntype SettingsJson = {\n hooks?: {\n [event: string]: Array<Record<string, unknown>>;\n };\n [key: string]: unknown;\n};\n\n/** Read current settings.local.json, returning {} if missing/invalid */\nexport function readInstalledHooks(projectRoot: string): SettingsJson {\n const settingsPath = path.join(projectRoot, '.claude', 'settings.local.json');\n try {\n return JSON.parse(fs.readFileSync(settingsPath, 'utf-8')) as SettingsJson;\n } catch {\n return {};\n }\n}\n\n/** Remove all hook entries whose command contains the hook name */\nexport function removeHookByName(settings: SettingsJson, name: string): SettingsJson {\n const hooks = settings.hooks ?? {};\n const updated: SettingsJson['hooks'] = {};\n\n for (const [event, entries] of Object.entries(hooks)) {\n updated[event] = (entries as Array<Record<string, unknown>>).filter((entry) => {\n const hookItems = (entry.hooks as Array<{ command?: string }>) ?? [];\n return !hookItems.some((h) => h.command?.includes(`claudectx`) && entry.name === name);\n });\n }\n\n return { ...settings, hooks: updated };\n}\n\n/** Parse key=value pairs from --config option */\nexport function parseConfigPairs(pairs: string[]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const pair of pairs) {\n const idx = pair.indexOf('=');\n if (idx === -1) continue;\n const key = pair.slice(0, idx).trim();\n const value = pair.slice(idx + 1).trim();\n if (key) result[key] = value;\n }\n return result;\n}\n\nexport async function hooksList(projectRoot: string): Promise<void> {\n const settings = readInstalledHooks(projectRoot);\n const installedCommands = JSON.stringify(settings.hooks ?? {});\n\n process.stdout.write('\\n');\n process.stdout.write('claudectx hooks — available hooks\\n');\n process.stdout.write('═'.repeat(55) + '\\n');\n process.stdout.write(\n ` ${'Name'.padEnd(16)} ${'Category'.padEnd(12)} ${'Trigger'.padEnd(12)} Status\\n`,\n );\n process.stdout.write('─'.repeat(55) + '\\n');\n\n for (const hook of HOOK_REGISTRY) {\n const installed = installedCommands.includes(hook.name) ? '✓ installed' : ' available';\n process.stdout.write(\n ` ${hook.name.padEnd(16)} ${hook.category.padEnd(12)} ${hook.triggerEvent.padEnd(12)} ${installed}\\n`,\n );\n }\n\n process.stdout.write('\\n');\n process.stdout.write(' Use: claudectx hooks add <name> [--config key=value]\\n\\n');\n}\n\nexport async function hooksAdd(\n name: string,\n projectRoot: string,\n configPairs: string[],\n): Promise<void> {\n const def = getHook(name);\n if (!def) {\n process.stderr.write(\n `Error: unknown hook \"${name}\". Run \"claudectx hooks list\" to see available hooks.\\n`,\n );\n process.exit(1);\n }\n\n const config = parseConfigPairs(configPairs);\n\n // Prompt for required fields not provided via --config\n const requiredMissing = Object.entries(def.configSchema).filter(\n ([key, field]) => field.required && config[key] === undefined,\n );\n\n if (requiredMissing.length > 0) {\n try {\n const { input } = await import('@inquirer/prompts');\n for (const [key, field] of requiredMissing) {\n const value = await input({ message: `${field.description} (${key}):` });\n config[key] = value;\n }\n } catch {\n // @inquirer/prompts not available — list what's missing\n process.stderr.write(\n `Error: required config fields missing: ${requiredMissing.map(([k]) => k).join(', ')}\\n` +\n ` Use: claudectx hooks add ${name} --config ${requiredMissing.map(([k]) => `${k}=<value>`).join(' --config ')}\\n`,\n );\n process.exit(1);\n }\n }\n\n // Apply defaults for optional missing fields\n for (const [key, field] of Object.entries(def.configSchema)) {\n if (config[key] === undefined && field.default !== undefined) {\n config[key] = String(field.default);\n }\n }\n\n // Verify the interpolated command has no unresolved placeholders\n const command = interpolateCommand(def.commandTemplate, config);\n if (command.includes('{{config.')) {\n process.stderr.write(`Error: unresolved config placeholders in command: ${command}\\n`);\n process.exit(1);\n }\n\n // Build entry and merge into settings\n const entry = { ...buildHookEntry(def, config), name };\n const settings = readInstalledHooks(projectRoot);\n const hooksObj = settings.hooks ?? {};\n const eventList = (hooksObj[def.triggerEvent] as Array<Record<string, unknown>>) ?? [];\n\n // Avoid duplicate installation\n if (eventList.some((e) => e.name === name)) {\n process.stdout.write(`Hook \"${name}\" is already installed.\\n`);\n return;\n }\n\n const updatedSettings: SettingsJson = {\n ...settings,\n hooks: { ...hooksObj, [def.triggerEvent]: [...eventList, entry] },\n };\n\n writeHooksSettings(projectRoot, updatedSettings);\n process.stdout.write(`\\n ✓ Hook \"${name}\" installed (${def.triggerEvent}${def.matcher ? ` / ${def.matcher}` : ''}).\\n\\n`);\n}\n\nexport async function hooksRemove(name: string, projectRoot: string): Promise<void> {\n const settings = readInstalledHooks(projectRoot);\n const updated = removeHookByName(settings, name);\n writeHooksSettings(projectRoot, updated);\n process.stdout.write(` ✓ Hook \"${name}\" removed.\\n\\n`);\n}\n\nexport async function hooksStatus(projectRoot: string): Promise<void> {\n const settings = readInstalledHooks(projectRoot);\n const hooks = settings.hooks ?? {};\n const entries = Object.entries(hooks).flatMap(([event, arr]) =>\n (arr as Array<Record<string, unknown>>).map((e) => ({ event, ...e })),\n );\n\n if (entries.length === 0) {\n process.stdout.write('\\n No hooks installed. Run \"claudectx hooks add <name>\" to add one.\\n\\n');\n return;\n }\n\n process.stdout.write('\\n Installed hooks:\\n');\n for (const entry of entries) {\n const name = (entry.name as string) ?? 'unnamed';\n const event = entry.event;\n const matcher = entry.matcher ? ` / ${entry.matcher}` : '';\n process.stdout.write(` ${name.padEnd(18)} ${event}${matcher}\\n`);\n }\n process.stdout.write('\\n');\n}\n\nexport async function hooksCommand(\n subcommand: string | undefined,\n options: HooksOptions & { name?: string },\n): Promise<void> {\n const projectPath = options.path ? path.resolve(options.path) : process.cwd();\n const projectRoot = findProjectRoot(projectPath) ?? projectPath;\n\n const sub = subcommand ?? 'list';\n\n switch (sub) {\n case 'list':\n await hooksList(projectRoot);\n break;\n case 'add': {\n const name = options.name;\n if (!name) {\n process.stderr.write('Usage: claudectx hooks add <name> [--config key=value]\\n');\n process.exit(1);\n }\n await hooksAdd(name, projectRoot, options.config ?? []);\n break;\n }\n case 'remove': {\n const name = options.name;\n if (!name) {\n process.stderr.write('Usage: claudectx hooks remove <name>\\n');\n process.exit(1);\n }\n await hooksRemove(name, projectRoot);\n break;\n }\n case 'status':\n await hooksStatus(projectRoot);\n break;\n default:\n process.stderr.write(\n `Unknown sub-command \"${sub}\". Use: list | add <name> | remove <name> | status\\n`,\n );\n process.exit(1);\n }\n}\n","export type TriggerEvent = 'PreToolUse' | 'PostToolUse' | 'Stop' | 'Notification';\n\nexport interface HookConfigField {\n type: 'string' | 'number' | 'boolean';\n default?: string | number | boolean;\n description: string;\n required?: boolean;\n}\n\nexport interface HookDefinition {\n name: string;\n description: string;\n triggerEvent: TriggerEvent;\n matcher?: string;\n commandTemplate: string;\n configSchema: Record<string, HookConfigField>;\n category: 'compression' | 'budget' | 'notification' | 'warmup';\n}\n\nexport const HOOK_REGISTRY: HookDefinition[] = [\n {\n name: 'auto-compress',\n description: 'Compress session when token count exceeds threshold',\n triggerEvent: 'PostToolUse',\n matcher: 'Read',\n commandTemplate: 'claudectx compress --auto --api-key {{config.apiKey}}',\n configSchema: {\n threshold: { type: 'number', default: 50000, description: 'Token threshold to trigger compression' },\n apiKey: { type: 'string', description: 'Anthropic API key for AI summarization', required: true },\n },\n category: 'compression',\n },\n {\n name: 'daily-budget',\n description: 'Warn when daily spend exceeds a dollar limit',\n triggerEvent: 'PreToolUse',\n commandTemplate: 'claudectx report --days 1 --json',\n configSchema: {\n dailyLimit: { type: 'number', default: 5, description: 'Daily spend limit in USD' },\n },\n category: 'budget',\n },\n {\n name: 'slack-digest',\n description: 'POST daily usage summary to a Slack incoming webhook',\n triggerEvent: 'Stop',\n commandTemplate:\n 'claudectx report --json | curl -s -X POST -H \"Content-Type: application/json\" --data-binary @- {{config.webhookUrl}}',\n configSchema: {\n webhookUrl: {\n type: 'string',\n description: 'Slack Incoming Webhook URL',\n required: true,\n },\n },\n category: 'notification',\n },\n {\n name: 'session-warmup',\n description: 'Pre-warm the Anthropic prompt cache on each session start',\n triggerEvent: 'PostToolUse',\n matcher: 'Read',\n commandTemplate: 'claudectx warmup --api-key {{config.apiKey}}',\n configSchema: {\n apiKey: { type: 'string', description: 'Anthropic API key', required: true },\n },\n category: 'warmup',\n },\n];\n\n/**\n * Look up a hook by name. Returns undefined if not found.\n */\nexport function getHook(name: string): HookDefinition | undefined {\n return HOOK_REGISTRY.find((h) => h.name === name);\n}\n\n/**\n * Interpolate {{config.key}} placeholders in a command template.\n */\nexport function interpolateCommand(\n template: string,\n config: Record<string, string | number | boolean>,\n): string {\n return template.replace(/\\{\\{config\\.(\\w+)\\}\\}/g, (_, key) => {\n const val = config[key];\n return val !== undefined ? String(val) : `{{config.${key}}}`;\n });\n}\n\n/**\n * Build the hook entry object that goes inside .claude/settings.local.json hooks array.\n */\nexport function buildHookEntry(\n def: HookDefinition,\n config: Record<string, string | number | boolean>,\n): Record<string, unknown> {\n const command = interpolateCommand(def.commandTemplate, config);\n const hookItem: Record<string, unknown> = {\n type: 'command',\n command,\n };\n\n const entry: Record<string, unknown> = { hooks: [hookItem] };\n if (def.matcher) {\n entry.matcher = def.matcher;\n }\n\n return entry;\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { findProjectRoot } from '../analyzer/context-parser.js';\n\nexport interface ConvertOptions {\n path?: string;\n from?: string;\n to: string;\n dryRun?: boolean;\n}\n\nexport interface ConvertedFile {\n filename: string;\n content: string;\n}\n\n/** Slugify a section header for use as a filename */\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\n/**\n * Split CLAUDE.md into Cursor .mdc rule files.\n * Each ## Section becomes a separate .cursor/rules/<slug>.mdc file.\n */\nexport function claudeMdToCursorRules(content: string): ConvertedFile[] {\n const files: ConvertedFile[] = [];\n const lines = content.split('\\n');\n\n let currentHeader = '';\n let currentBody: string[] = [];\n\n function flushSection() {\n if (!currentHeader) return;\n const slug = slugify(currentHeader);\n if (!slug) return;\n const mdc = [\n '---',\n `description: ${currentHeader}`,\n 'alwaysApply: true',\n '---',\n '',\n ...currentBody,\n ].join('\\n');\n files.push({ filename: `${slug}.mdc`, content: mdc });\n }\n\n for (const line of lines) {\n const match = line.match(/^##\\s+(.+)$/);\n if (match) {\n flushSection();\n currentHeader = match[1];\n currentBody = [];\n } else if (currentHeader) {\n currentBody.push(line);\n }\n // Lines before the first ## header are ignored (top-level intro content)\n }\n flushSection();\n\n // If no ## sections found, output everything as a single file\n if (files.length === 0 && content.trim()) {\n files.push({\n filename: 'project-instructions.mdc',\n content: ['---', 'description: Project Instructions', 'alwaysApply: true', '---', '', content].join('\\n'),\n });\n }\n\n return files;\n}\n\n/**\n * Convert CLAUDE.md to a GitHub Copilot instructions file.\n * Strips ## headers and joins bodies into plain Markdown.\n */\nexport function claudeMdToCopilot(content: string): string {\n // For Copilot, just clean up @references and emit as-is (it reads plain markdown)\n return content\n .split('\\n')\n .filter((line) => !line.match(/^@.+$/)) // strip @file references (Copilot doesn't support them)\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n') // normalize extra blank lines\n .trim();\n}\n\n/**\n * Convert CLAUDE.md to a Windsurf rules file.\n * Strips @references; Windsurf reads plain text.\n */\nexport function claudeMdToWindsurf(content: string): string {\n return content\n .split('\\n')\n .filter((line) => !line.match(/^@.+$/))\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n}\n\nexport async function convertCommand(options: ConvertOptions): Promise<void> {\n const projectPath = options.path ? path.resolve(options.path) : process.cwd();\n const projectRoot = findProjectRoot(projectPath) ?? projectPath;\n const from = options.from ?? 'claude';\n const to = options.to;\n\n if (from !== 'claude') {\n process.stderr.write(`Error: --from \"${from}\" is not yet supported. Only --from claude is available.\\n`);\n process.exit(1);\n }\n\n const claudeMdPath = path.join(projectRoot, 'CLAUDE.md');\n let content = '';\n try {\n content = fs.readFileSync(claudeMdPath, 'utf-8');\n } catch {\n process.stderr.write(`Error: CLAUDE.md not found at ${claudeMdPath}\\n`);\n process.exit(1);\n }\n\n if (to === 'cursor') {\n const files = claudeMdToCursorRules(content);\n const targetDir = path.join(projectRoot, '.cursor', 'rules');\n\n process.stdout.write(`\\nConverting CLAUDE.md → ${files.length} Cursor rule file(s)\\n\\n`);\n\n for (const file of files) {\n const filePath = path.join(targetDir, file.filename);\n process.stdout.write(` ${options.dryRun ? '[dry-run] ' : ''}→ .cursor/rules/${file.filename}\\n`);\n if (!options.dryRun) {\n fs.mkdirSync(targetDir, { recursive: true });\n fs.writeFileSync(filePath, file.content, 'utf-8');\n }\n }\n process.stdout.write('\\n');\n\n } else if (to === 'copilot') {\n const converted = claudeMdToCopilot(content);\n const targetPath = path.join(projectRoot, '.github', 'copilot-instructions.md');\n process.stdout.write(`\\nConverting CLAUDE.md → .github/copilot-instructions.md\\n`);\n if (!options.dryRun) {\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n fs.writeFileSync(targetPath, converted, 'utf-8');\n process.stdout.write(` ✓ Written to ${targetPath}\\n\\n`);\n } else {\n process.stdout.write(` [dry-run] Would write ${converted.length} chars to ${targetPath}\\n\\n`);\n }\n\n } else if (to === 'windsurf') {\n const converted = claudeMdToWindsurf(content);\n const targetPath = path.join(projectRoot, '.windsurfrules');\n process.stdout.write(`\\nConverting CLAUDE.md → .windsurfrules\\n`);\n if (!options.dryRun) {\n fs.writeFileSync(targetPath, converted, 'utf-8');\n process.stdout.write(` ✓ Written to ${targetPath}\\n\\n`);\n } else {\n process.stdout.write(` [dry-run] Would write ${converted.length} chars to ${targetPath}\\n\\n`);\n }\n\n } else {\n process.stderr.write(`Error: unknown target \"${to}\". Use: cursor | copilot | windsurf\\n`);\n process.exit(1);\n }\n}\n","import * as path from 'path';\nimport * as fs from 'fs';\nimport { resolveModel } from '../shared/models.js';\nimport { formatCost } from '../analyzer/cost-calculator.js';\nimport {\n buildTeamExport,\n aggregateTeamReports,\n writeTeamExport,\n readTeamExports,\n anonymizeExport,\n} from '../reporter/team-aggregator.js';\nimport { getStoreDir } from '../watcher/session-store.js';\n\nexport interface TeamsOptions {\n days?: string;\n model?: string;\n anonymize?: boolean;\n dir?: string;\n to?: string;\n json?: boolean;\n name?: string;\n}\n\nexport async function teamsExport(options: TeamsOptions): Promise<void> {\n const model = resolveModel(options.model ?? 'sonnet');\n const days = parseInt(options.days ?? '30', 10);\n const anonymize = options.anonymize ?? false;\n\n const exportData = await buildTeamExport(days, model, anonymize);\n\n if (options.json) {\n process.stdout.write(JSON.stringify(exportData, null, 2) + '\\n');\n return;\n }\n\n const filePath = writeTeamExport(exportData);\n process.stdout.write('\\n');\n process.stdout.write(`claudectx teams export\\n`);\n process.stdout.write('═'.repeat(45) + '\\n');\n process.stdout.write(` Developer: ${exportData.developer.identity}\\n`);\n process.stdout.write(` Period: Last ${days} days\\n`);\n process.stdout.write(` Sessions: ${exportData.developer.sessionCount}\\n`);\n process.stdout.write(` Total cost: ${formatCost(exportData.developer.totalCostUsd)}\\n`);\n process.stdout.write(` Cache rate: ${exportData.developer.cacheHitRate}%\\n`);\n process.stdout.write(`\\n ✓ Saved to: ${filePath}\\n`);\n process.stdout.write(' Share this file with your team lead for aggregation.\\n\\n');\n}\n\nexport async function teamsAggregate(options: TeamsOptions): Promise<void> {\n const dir = options.dir ?? getStoreDir();\n const anonymize = options.anonymize ?? false;\n\n const exports = readTeamExports(dir);\n if (exports.length === 0) {\n process.stderr.write(\n `No team export files found in ${dir}.\\n` +\n `Run \"claudectx teams export\" on each developer machine first.\\n`,\n );\n process.exit(1);\n }\n\n const anonymized = anonymize\n ? exports.map((e, i) => anonymizeExport(e, i))\n : exports;\n\n const report = aggregateTeamReports(anonymized);\n\n if (options.json) {\n process.stdout.write(JSON.stringify(report, null, 2) + '\\n');\n return;\n }\n\n process.stdout.write('\\n');\n process.stdout.write('claudectx teams aggregate — team cost report\\n');\n process.stdout.write('═'.repeat(55) + '\\n');\n process.stdout.write(` Developers: ${report.totalDevelopers}\\n`);\n process.stdout.write(` Period: Last ${report.periodDays} days\\n`);\n process.stdout.write(` Team total cost: ${formatCost(report.teamTotalCostUsd)}\\n`);\n process.stdout.write(` Team cache rate: ${report.teamCacheHitRate}%\\n`);\n process.stdout.write('\\n');\n\n process.stdout.write(\n ` ${'Developer'.padEnd(30)} ${'Cost'.padStart(8)} ${'Cache'.padStart(6)} Sessions\\n`,\n );\n process.stdout.write('─'.repeat(55) + '\\n');\n for (const dev of report.developers) {\n const identity = dev.identity.slice(0, 30).padEnd(30);\n const cost = formatCost(dev.totalCostUsd).padStart(8);\n const cache = `${dev.cacheHitRate}%`.padStart(6);\n const sessions = String(dev.sessionCount).padStart(8);\n process.stdout.write(` ${identity} ${cost} ${cache} ${sessions}\\n`);\n }\n process.stdout.write('\\n');\n\n if (report.topWasteFiles.length > 0) {\n process.stdout.write(' Top shared files (by read count across team):\\n');\n for (const f of report.topWasteFiles.slice(0, 5)) {\n const devList = f.developers.slice(0, 3).join(', ');\n process.stdout.write(` ${f.readCount}x ${path.basename(f.filePath)} (${devList})\\n`);\n }\n process.stdout.write('\\n');\n }\n}\n\nexport async function teamsShare(options: TeamsOptions): Promise<void> {\n const dest = options.to;\n if (!dest) {\n process.stderr.write('Usage: claudectx teams share --to <path>\\n');\n process.exit(1);\n }\n\n const storeDir = getStoreDir();\n const exportFiles = fs\n .readdirSync(storeDir)\n .filter((f) => f.match(/^team-export-.*\\.json$/))\n .sort()\n .reverse();\n\n if (exportFiles.length === 0) {\n process.stderr.write('No team export files found. Run \"claudectx teams export\" first.\\n');\n process.exit(1);\n }\n\n const latest = exportFiles[0];\n const src = path.join(storeDir, latest);\n const destPath = fs.statSync(dest).isDirectory() ? path.join(dest, latest) : dest;\n\n fs.copyFileSync(src, destPath);\n process.stdout.write(` ✓ Copied ${latest} → ${destPath}\\n\\n`);\n}\n\nexport async function teamsCommand(\n subcommand: string,\n options: TeamsOptions,\n): Promise<void> {\n switch (subcommand) {\n case 'export':\n await teamsExport(options);\n break;\n case 'aggregate':\n await teamsAggregate(options);\n break;\n case 'share':\n await teamsShare(options);\n break;\n default:\n process.stderr.write(\n `Unknown sub-command \"${subcommand}\". Use: export | aggregate | share\\n`,\n );\n process.exit(1);\n }\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport * as childProcess from 'child_process';\nimport { listSessionFiles, readSessionUsage } from '../watcher/session-reader.js';\nimport { readAllEvents, aggregateStats, getStoreDir } from '../watcher/session-store.js';\nimport { MODEL_PRICING } from '../shared/models.js';\nimport type { ClaudeModel } from '../shared/types.js';\nimport type { DayBucket } from './usage-aggregator.js';\n\nexport interface DeveloperRecord {\n identity: string;\n exportedAt: string;\n periodDays: number;\n totalCostUsd: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n cacheHitRate: number;\n avgRequestSize: number;\n topWasteFiles: Array<{ filePath: string; readCount: number }>;\n sessionCount: number;\n}\n\nexport interface TeamExport {\n version: '1';\n developer: DeveloperRecord;\n byDay: DayBucket[];\n}\n\nexport interface TeamReport {\n generatedAt: string;\n totalDevelopers: number;\n periodDays: number;\n developers: DeveloperRecord[];\n teamTotalCostUsd: number;\n teamCacheHitRate: number;\n topWasteFiles: Array<{ filePath: string; readCount: number; developers: string[] }>;\n}\n\n/**\n * Get a stable developer identity: git email, falling back to hostname.\n */\nexport function getDeveloperIdentity(): string {\n try {\n const email = childProcess\n .execSync('git config user.email', { encoding: 'utf-8', timeout: 2000, stdio: ['pipe', 'pipe', 'pipe'] })\n .trim();\n if (email) return email;\n } catch {\n // Not a git repo or git not installed\n }\n return os.hostname();\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\nfunction isoDate(d: Date): string {\n return d.toISOString().slice(0, 10);\n}\n\n/**\n * Anonymize a developer export by replacing identity with \"Dev N\".\n */\nexport function anonymizeExport(report: TeamExport, index: number): TeamExport {\n return {\n ...report,\n developer: {\n ...report.developer,\n identity: `Dev ${index + 1}`,\n },\n };\n}\n\n/**\n * Build a team export from the current developer's local session data.\n */\nexport async function buildTeamExport(\n days: number,\n model: ClaudeModel,\n anonymize: boolean,\n): Promise<TeamExport> {\n const now = new Date();\n const cutoff = new Date(now);\n cutoff.setDate(cutoff.getDate() - days);\n const cutoffMs = cutoff.getTime();\n\n const sessionFiles = listSessionFiles().filter((f) => f.mtimeMs >= cutoffMs);\n\n // Per-day buckets\n const bucketMap = new Map<string, DayBucket>();\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, sessions: 0, inputTokens: 0, outputTokens: 0,\n cacheReadTokens: 0, requests: 0, costUsd: 0,\n });\n }\n\n let totalInput = 0;\n let totalOutput = 0;\n let totalCacheRead = 0;\n let totalRequests = 0;\n\n for (const sf of sessionFiles) {\n const dateStr = isoDate(new Date(sf.mtimeMs));\n const bucket = bucketMap.get(dateStr);\n const usage = readSessionUsage(sf.filePath);\n\n if (bucket) {\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\n totalInput += usage.inputTokens;\n totalOutput += usage.outputTokens;\n totalCacheRead += usage.cacheReadTokens;\n totalRequests += usage.requestCount;\n }\n\n const fileEvents = readAllEvents().filter(\n (e) => new Date(e.timestamp).getTime() >= cutoffMs,\n );\n const topWasteFiles = aggregateStats(fileEvents)\n .slice(0, 10)\n .map((s) => ({ filePath: s.filePath, readCount: s.readCount }));\n\n const totalCostUsd = calcCost(totalInput, totalOutput, model);\n const cacheHitRate = totalInput > 0 ? Math.round((totalCacheRead / totalInput) * 100) : 0;\n const uniqueSessions = new Set(sessionFiles.map((f) => f.sessionId)).size;\n\n const developer: DeveloperRecord = {\n identity: getDeveloperIdentity(),\n exportedAt: now.toISOString(),\n periodDays: days,\n totalCostUsd,\n totalInputTokens: totalInput,\n totalOutputTokens: totalOutput,\n cacheHitRate,\n avgRequestSize: totalRequests > 0 ? Math.round(totalInput / totalRequests) : 0,\n topWasteFiles,\n sessionCount: uniqueSessions,\n };\n\n const byDay = [...bucketMap.values()].sort((a, b) => a.date.localeCompare(b.date));\n\n const exportData: TeamExport = { version: '1', developer, byDay };\n\n if (anonymize) return anonymizeExport(exportData, 0);\n return exportData;\n}\n\n/**\n * Merge multiple developer exports into a consolidated team report.\n */\nexport function aggregateTeamReports(exports: TeamExport[]): TeamReport {\n const developers = exports.map((e) => e.developer);\n // Sort by cost descending\n developers.sort((a, b) => b.totalCostUsd - a.totalCostUsd);\n\n const teamTotalCostUsd = developers.reduce((sum, d) => sum + d.totalCostUsd, 0);\n const teamCacheHitRate =\n developers.length > 0\n ? Math.round(developers.reduce((sum, d) => sum + d.cacheHitRate, 0) / developers.length)\n : 0;\n\n // Merge top waste files across developers\n const fileMap = new Map<string, { readCount: number; developers: string[] }>();\n for (const dev of developers) {\n for (const wf of dev.topWasteFiles) {\n const existing = fileMap.get(wf.filePath);\n if (existing) {\n existing.readCount += wf.readCount;\n existing.developers.push(dev.identity);\n } else {\n fileMap.set(wf.filePath, { readCount: wf.readCount, developers: [dev.identity] });\n }\n }\n }\n\n const topWasteFiles = [...fileMap.entries()]\n .map(([filePath, data]) => ({ filePath, ...data }))\n .sort((a, b) => b.readCount - a.readCount)\n .slice(0, 10);\n\n const periodDays = exports[0]?.developer.periodDays ?? 30;\n\n return {\n generatedAt: new Date().toISOString(),\n totalDevelopers: exports.length,\n periodDays,\n developers,\n teamTotalCostUsd,\n teamCacheHitRate,\n topWasteFiles,\n };\n}\n\n/** Write a team export to ~/.claudectx/team-export-{date}.json */\nexport function writeTeamExport(exportData: TeamExport): string {\n const storeDir = getStoreDir();\n if (!fs.existsSync(storeDir)) fs.mkdirSync(storeDir, { recursive: true });\n const date = isoDate(new Date());\n const filePath = path.join(storeDir, `team-export-${date}.json`);\n fs.writeFileSync(filePath, JSON.stringify(exportData, null, 2), 'utf-8');\n return filePath;\n}\n\n/** Read all team-export-*.json files from a directory */\nexport function readTeamExports(dir: string): TeamExport[] {\n const exports: TeamExport[] = [];\n if (!fs.existsSync(dir)) return exports;\n const files = fs.readdirSync(dir).filter((f) => f.match(/^team-export-.*\\.json$/));\n for (const file of files) {\n try {\n const raw = fs.readFileSync(path.join(dir, file), 'utf-8');\n exports.push(JSON.parse(raw) as TeamExport);\n } catch {\n // Skip malformed files\n }\n }\n return exports;\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","Anthropic","shortPath","fs","path","chalk","calcCost","fmtNum","fmtCost","shortPath","MODEL_ALIASES","path","fs","path","import_glob","path","import_fs","execSync","fs","Anthropic","path","fs","fs","path","basename","checkbox","fs","path","fs","path","slugify","path","fs","fs","path","os","childProcess","calcCost","isoDate","exports","exports"]}
|