@colbymchenry/cmem 0.2.23 → 0.2.29
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.
Potentially problematic release.
This version of @colbymchenry/cmem might be problematic. Click here for more details.
- package/dist/cli.js +530 -70
- package/dist/cli.js.map +1 -1
- package/package.json +12 -5
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/install.ts","../src/cli.ts","../src/ui/App.tsx","../src/ui/components/Header.tsx","../src/ui/components/SearchInput.tsx","../src/ui/components/SessionList.tsx","../src/utils/format.ts","../src/ui/components/Preview.tsx","../src/ui/hooks/useSessions.ts","../src/db/index.ts","../src/utils/config.ts","../src/parser/index.ts","../src/db/sessions.ts","../src/db/vectors.ts","../src/embeddings/index.ts","../src/commands/save.ts","../src/commands/list.ts","../src/commands/search.ts","../src/commands/restore.ts","../src/utils/clipboard.ts","../src/commands/delete.ts","../src/commands/stats.ts","../src/commands/watch.ts","../src/commands/mcp.ts","../src/mcp/server.ts","../src/utils/claude-cli.ts","../src/commands/setup.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { writeFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';\nimport { homedir } from 'os';\nimport { join, dirname } from 'path';\nimport { execSync } from 'child_process';\n\nconst LAUNCH_AGENTS_DIR = join(homedir(), 'Library', 'LaunchAgents');\nconst PLIST_NAME = 'com.cmem.watch.plist';\nconst PLIST_PATH = join(LAUNCH_AGENTS_DIR, PLIST_NAME);\n\nfunction getCmemPath(): string {\n try {\n // Find the actual cmem binary path\n const result = execSync('which cmem', { encoding: 'utf-8' }).trim();\n return result;\n } catch {\n // Fallback to npx\n return '/usr/local/bin/cmem';\n }\n}\n\nfunction getNodeBinDir(): string {\n try {\n // Get the directory containing node (for nvm, homebrew, etc.)\n const nodePath = execSync('which node', { encoding: 'utf-8' }).trim();\n return dirname(nodePath); // Return the bin directory\n } catch {\n return '/usr/local/bin';\n }\n}\n\nfunction generatePlist(cmemPath: string): string {\n const nodeBinDir = getNodeBinDir();\n // Build PATH with node's bin directory first, then standard paths\n const pathValue = `${nodeBinDir}:/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin`;\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.cmem.watch</string>\n\n <key>ProgramArguments</key>\n <array>\n <string>${cmemPath}</string>\n <string>watch</string>\n </array>\n\n <key>RunAtLoad</key>\n <true/>\n\n <key>KeepAlive</key>\n <true/>\n\n <key>StandardOutPath</key>\n <string>${homedir()}/.cmem/watch.log</string>\n\n <key>StandardErrorPath</key>\n <string>${homedir()}/.cmem/watch.error.log</string>\n\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>${pathValue}</string>\n </dict>\n</dict>\n</plist>`;\n}\n\nexport async function installCommand(): Promise<void> {\n const platform = process.platform;\n\n if (platform !== 'darwin') {\n console.log(chalk.yellow('Auto-install is currently only supported on macOS.'));\n console.log(chalk.dim('\\nFor Linux, create a systemd service:'));\n console.log(chalk.dim(' ~/.config/systemd/user/cmem-watch.service'));\n console.log(chalk.dim('\\nFor manual background run:'));\n console.log(chalk.dim(' nohup cmem watch > ~/.cmem/watch.log 2>&1 &'));\n return;\n }\n\n console.log(chalk.cyan('Installing cmem watch daemon...\\n'));\n\n // Ensure LaunchAgents directory exists\n if (!existsSync(LAUNCH_AGENTS_DIR)) {\n mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });\n }\n\n // Ensure .cmem directory exists for logs\n const cmemDir = join(homedir(), '.cmem');\n if (!existsSync(cmemDir)) {\n mkdirSync(cmemDir, { recursive: true });\n }\n\n // Get cmem path\n const cmemPath = getCmemPath();\n console.log(chalk.dim(`Using cmem at: ${cmemPath}`));\n\n // Check if already installed\n if (existsSync(PLIST_PATH)) {\n console.log(chalk.yellow('LaunchAgent already exists. Unloading first...'));\n try {\n execSync(`launchctl unload \"${PLIST_PATH}\"`, { stdio: 'ignore' });\n } catch {\n // May not be loaded\n }\n }\n\n // Write plist\n const plistContent = generatePlist(cmemPath);\n writeFileSync(PLIST_PATH, plistContent);\n console.log(chalk.green(`✓ Created ${PLIST_PATH}`));\n\n // Load the LaunchAgent\n try {\n execSync(`launchctl load \"${PLIST_PATH}\"`);\n console.log(chalk.green('✓ LaunchAgent loaded'));\n } catch (err) {\n console.log(chalk.red('Failed to load LaunchAgent:'), err);\n return;\n }\n\n console.log(chalk.green('\\n✓ cmem watch daemon installed and running!'));\n console.log(chalk.dim('\\nThe daemon will:'));\n console.log(chalk.dim(' • Start automatically on login'));\n console.log(chalk.dim(' • Restart if it crashes'));\n console.log(chalk.dim(` • Log to ~/.cmem/watch.log`));\n console.log(chalk.dim('\\nCommands:'));\n console.log(chalk.dim(' cmem uninstall Stop and remove the daemon'));\n console.log(chalk.dim(' cmem status Check daemon status'));\n}\n\nexport async function uninstallCommand(): Promise<void> {\n const platform = process.platform;\n\n if (platform !== 'darwin') {\n console.log(chalk.yellow('Auto-uninstall is currently only supported on macOS.'));\n return;\n }\n\n console.log(chalk.cyan('Uninstalling cmem watch daemon...\\n'));\n\n if (!existsSync(PLIST_PATH)) {\n console.log(chalk.yellow('LaunchAgent not found. Nothing to uninstall.'));\n return;\n }\n\n // Unload the LaunchAgent\n try {\n execSync(`launchctl unload \"${PLIST_PATH}\"`);\n console.log(chalk.green('✓ LaunchAgent unloaded'));\n } catch {\n console.log(chalk.yellow('LaunchAgent was not loaded'));\n }\n\n // Remove plist file\n try {\n unlinkSync(PLIST_PATH);\n console.log(chalk.green(`✓ Removed ${PLIST_PATH}`));\n } catch (err) {\n console.log(chalk.red('Failed to remove plist:'), err);\n return;\n }\n\n console.log(chalk.green('\\n✓ cmem watch daemon uninstalled'));\n}\n\nexport async function statusCommand(): Promise<void> {\n const platform = process.platform;\n\n if (platform !== 'darwin') {\n console.log(chalk.yellow('Status check is currently only supported on macOS.'));\n return;\n }\n\n console.log(chalk.cyan('cmem watch daemon status\\n'));\n\n if (!existsSync(PLIST_PATH)) {\n console.log(chalk.yellow('Status: Not installed'));\n console.log(chalk.dim('Run: cmem install'));\n return;\n }\n\n try {\n const result = execSync(`launchctl list | grep com.cmem.watch`, {\n encoding: 'utf-8',\n });\n\n const parts = result.trim().split(/\\s+/);\n const pid = parts[0];\n const exitCode = parts[1];\n\n if (pid && pid !== '-') {\n console.log(chalk.green(`Status: Running (PID ${pid})`));\n } else if (exitCode === '0') {\n console.log(chalk.yellow('Status: Stopped (exit code 0)'));\n } else {\n console.log(chalk.red(`Status: Crashed (exit code ${exitCode})`));\n console.log(chalk.dim('Check ~/.cmem/watch.error.log for details'));\n }\n } catch {\n console.log(chalk.yellow('Status: Not running'));\n console.log(chalk.dim('The daemon is installed but not currently running.'));\n console.log(chalk.dim('It will start on next login, or run: launchctl load ~/Library/LaunchAgents/com.cmem.watch.plist'));\n }\n\n console.log(chalk.dim(`\\nPlist: ${PLIST_PATH}`));\n console.log(chalk.dim('Logs: ~/.cmem/watch.log'));\n}\n","import { program } from 'commander';\nimport { render } from 'ink';\nimport React from 'react';\nimport { existsSync, readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { spawn } from 'child_process';\nimport { App } from './ui/App.js';\nimport { saveCommand } from './commands/save.js';\nimport { listCommand } from './commands/list.js';\nimport { searchCommand } from './commands/search.js';\nimport { restoreCommand } from './commands/restore.js';\nimport { deleteCommand } from './commands/delete.js';\nimport { statsCommand } from './commands/stats.js';\nimport { watchCommand } from './commands/watch.js';\nimport { mcpCommand } from './commands/mcp.js';\nimport { installCommand, uninstallCommand, statusCommand } from './commands/install.js';\nimport { setupCommand, shouldRunSetup } from './commands/setup.js';\n\n// Store session to resume after TUI exits\nlet sessionToResume: { sessionId: string; projectPath: string | null } | null = null;\n\n// Get version from package.json\nfunction getVersion(): string {\n try {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const packagePath = join(__dirname, '..', 'package.json');\n if (existsSync(packagePath)) {\n const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));\n return pkg.version || '0.1.0';\n }\n } catch {\n // Ignore\n }\n return '0.1.0';\n}\n\nprogram\n .name('cmem')\n .description('Persistent session storage for Claude Code CLI')\n .version(getVersion())\n .option('-l, --local', 'Filter to sessions from current directory')\n .action(async (options) => {\n // Check if we should run setup (first run via npx)\n if (shouldRunSetup()) {\n await setupCommand();\n return;\n }\n\n // Handle resume callback from TUI\n const handleResume = (sessionId: string, projectPath: string | null) => {\n sessionToResume = { sessionId, projectPath };\n };\n\n // Determine project filter\n const projectFilter = options.local ? process.cwd() : null;\n\n // Default action: launch TUI\n const { waitUntilExit } = render(React.createElement(App, { onResume: handleResume, projectFilter }));\n await waitUntilExit();\n\n // If user selected a session to resume, spawn Claude\n if (sessionToResume) {\n const args = ['--resume', sessionToResume.sessionId];\n\n // Use project path if available, otherwise current directory\n const cwd = sessionToResume.projectPath || process.cwd();\n\n console.log(`\\nResuming session in: ${cwd}\\n`);\n\n // Spawn Claude with inherited stdio so it takes over the terminal\n const child = spawn('claude', args, {\n cwd,\n stdio: 'inherit',\n shell: true,\n });\n\n child.on('error', (err) => {\n console.error('Failed to start Claude:', err.message);\n process.exit(1);\n });\n\n child.on('exit', (code) => {\n process.exit(code || 0);\n });\n }\n });\n\nprogram\n .command('setup')\n .description('Run interactive setup wizard')\n .action(async () => {\n await setupCommand();\n });\n\nprogram\n .command('save')\n .description('Save a Claude Code session')\n .option('-t, --title <title>', 'Custom title')\n .option('--latest', 'Auto-save most recent session')\n .action(async (options) => {\n await saveCommand(options);\n });\n\nprogram\n .command('list')\n .description('List saved sessions (human sessions only by default)')\n .option('-a, --all', 'Show all sessions including automated ones')\n .action(async (options) => {\n await listCommand(options);\n });\n\nprogram\n .command('search <query>')\n .description('Semantic search across sessions')\n .action(async (query) => {\n await searchCommand(query);\n });\n\nprogram\n .command('restore <id>')\n .description('Restore a session')\n .option('--copy', 'Copy to clipboard')\n .option('--format <format>', 'Output format: context|json|markdown', 'context')\n .action(async (id, options) => {\n await restoreCommand(id, options);\n });\n\nprogram\n .command('delete <id>')\n .description('Delete a session')\n .action(async (id) => {\n await deleteCommand(id);\n });\n\nprogram\n .command('stats')\n .description('Show storage statistics')\n .action(async () => {\n await statsCommand();\n });\n\nprogram\n .command('watch')\n .description('Watch for Claude Code session changes and auto-sync')\n .option('-v, --verbose', 'Show detailed output')\n .option('--embed-threshold <chars>', 'Re-embed after this many new chars', '500')\n .action(async (options) => {\n await watchCommand({\n verbose: options.verbose,\n embedThreshold: parseInt(options.embedThreshold, 10),\n });\n });\n\nprogram\n .command('mcp')\n .description('Start MCP server for Claude Code integration')\n .action(async () => {\n await mcpCommand();\n });\n\nprogram\n .command('install')\n .description('Install watch daemon to run at system startup (macOS)')\n .action(async () => {\n await installCommand();\n });\n\nprogram\n .command('uninstall')\n .description('Remove watch daemon from system startup')\n .action(async () => {\n await uninstallCommand();\n });\n\nprogram\n .command('status')\n .description('Check watch daemon status')\n .action(async () => {\n await statusCommand();\n });\n\nprogram.parse();\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\nimport TextInput from 'ink-text-input';\nimport Spinner from 'ink-spinner';\nimport { basename, dirname } from 'path';\nimport { existsSync } from 'fs';\nimport { Header } from './components/Header.js';\nimport { SearchInput } from './components/SearchInput.js';\nimport { SessionList } from './components/SessionList.js';\nimport { Preview } from './components/Preview.js';\nimport { useSessions } from './hooks/useSessions.js';\nimport { renameSession } from '../db/sessions.js';\n\ntype Mode = 'list' | 'search' | 'confirm-delete' | 'rename';\n\nexport interface AppProps {\n onResume?: (sessionId: string, projectPath: string | null) => void;\n projectFilter?: string | null;\n}\n\nexport const App: React.FC<AppProps> = ({ onResume, projectFilter: initialProjectFilter }) => {\n const { exit } = useApp();\n const {\n sessions,\n loading,\n embeddingsReady,\n projectFilter,\n setProjectFilter,\n search,\n clearSearch,\n deleteSession,\n refresh,\n } = useSessions({ projectFilter: initialProjectFilter });\n\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [searchQuery, setSearchQuery] = useState('');\n const [mode, setMode] = useState<Mode>('list');\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState('');\n\n // Reset selection when sessions change\n useEffect(() => {\n if (selectedIndex >= sessions.length) {\n setSelectedIndex(Math.max(0, sessions.length - 1));\n }\n }, [sessions, selectedIndex]);\n\n // Debounced search\n useEffect(() => {\n if (mode === 'search' && searchQuery.length > 2) {\n const timer = setTimeout(() => {\n search(searchQuery);\n }, 300);\n return () => clearTimeout(timer);\n } else if (mode === 'search' && searchQuery.length === 0) {\n clearSearch();\n }\n }, [searchQuery, mode, search, clearSearch]);\n\n // Clear status message after 3 seconds\n useEffect(() => {\n if (statusMessage) {\n const timer = setTimeout(() => setStatusMessage(null), 3000);\n return () => clearTimeout(timer);\n }\n }, [statusMessage]);\n\n const handleRestore = useCallback(() => {\n const session = sessions[selectedIndex];\n if (!session) return;\n\n // Extract the Claude session ID from the source file path\n // The sourceFile looks like: /Users/colby/.claude/projects/-Users-colby-Desktop-cmem/uuid.jsonl\n if (session.sourceFile) {\n const filename = basename(session.sourceFile);\n const claudeSessionId = filename.replace('.jsonl', '');\n\n // Reconstruct project path from the sourceFile's directory name\n // This is more reliable than sessions-index.json because it matches where Claude stored the session\n const projectDirName = basename(dirname(session.sourceFile));\n let projectPath: string | null = null;\n\n if (projectDirName.startsWith('-')) {\n // Reconstruct path by finding valid directory boundaries\n const segments = projectDirName.substring(1).split('-');\n let currentPath = '';\n let remainingSegments = [...segments];\n\n while (remainingSegments.length > 0) {\n let found = false;\n for (let i = remainingSegments.length; i > 0; i--) {\n const testSegment = remainingSegments.slice(0, i).join('-');\n const testPath = currentPath + '/' + testSegment;\n\n if (existsSync(testPath)) {\n currentPath = testPath;\n remainingSegments = remainingSegments.slice(i);\n found = true;\n break;\n }\n }\n\n if (!found) {\n currentPath = currentPath + '/' + remainingSegments.join('-');\n break;\n }\n }\n\n if (currentPath && existsSync(currentPath)) {\n projectPath = currentPath;\n }\n }\n\n if (onResume) {\n onResume(claudeSessionId, projectPath);\n exit();\n }\n } else {\n setStatusMessage('No source file - cannot resume this session');\n }\n }, [sessions, selectedIndex, onResume, exit]);\n\n const handleDelete = useCallback(() => {\n const session = sessions[selectedIndex];\n if (session) {\n deleteSession(session.id);\n setStatusMessage(`Deleted: ${session.customTitle || session.title}`);\n setMode('list');\n }\n }, [sessions, selectedIndex, deleteSession]);\n\n const handleRename = useCallback(() => {\n const session = sessions[selectedIndex];\n if (session && renameValue.trim()) {\n renameSession(session.id, renameValue.trim());\n setStatusMessage(`Renamed to: ${renameValue.trim()}`);\n refresh();\n }\n setMode('list');\n setRenameValue('');\n }, [sessions, selectedIndex, renameValue, refresh]);\n\n const handleClearRename = useCallback(() => {\n const session = sessions[selectedIndex];\n if (session && session.customTitle) {\n renameSession(session.id, null);\n setStatusMessage(`Cleared custom name`);\n refresh();\n }\n setMode('list');\n }, [sessions, selectedIndex, refresh]);\n\n // Handle keyboard input\n useInput((input, key) => {\n // Global quit\n if (input === 'q' && mode !== 'search' && mode !== 'rename') {\n exit();\n return;\n }\n\n // Mode-specific handling\n if (mode === 'confirm-delete') {\n if (input === 'y' || input === 'Y') {\n handleDelete();\n } else {\n setMode('list');\n }\n return;\n }\n\n if (mode === 'rename') {\n if (key.escape) {\n setMode('list');\n setRenameValue('');\n return;\n }\n if (key.return) {\n handleRename();\n return;\n }\n // Let TextInput handle other keys\n return;\n }\n\n if (mode === 'search') {\n if (key.escape) {\n setMode('list');\n setSearchQuery('');\n clearSearch();\n return;\n }\n if (key.return) {\n setMode('list');\n return;\n }\n // Let TextInput handle other keys\n return;\n }\n\n // List mode\n if (input === '/') {\n setMode('search');\n return;\n }\n\n if (input === 'r') {\n if (sessions.length > 0) {\n const session = sessions[selectedIndex];\n // Pre-fill with existing custom title or empty\n setRenameValue(session?.customTitle || '');\n setMode('rename');\n }\n return;\n }\n\n if (input === 'R') {\n // Shift+R to clear custom name\n handleClearRename();\n return;\n }\n\n if (key.upArrow || input === 'k') {\n setSelectedIndex(prev => Math.max(0, prev - 1));\n return;\n }\n\n if (key.downArrow || input === 'j') {\n setSelectedIndex(prev => Math.min(sessions.length - 1, prev + 1));\n return;\n }\n\n if (key.return) {\n handleRestore();\n return;\n }\n\n if (input === 'd') {\n if (sessions.length > 0) {\n setMode('confirm-delete');\n }\n return;\n }\n\n if (input === 'f') {\n // Toggle folder filter based on selected session's folder\n if (projectFilter) {\n setProjectFilter(null);\n setStatusMessage('Filter cleared - showing all sessions');\n } else {\n const session = sessions[selectedIndex];\n if (session?.projectPath) {\n setProjectFilter(session.projectPath);\n setStatusMessage(`Filtering to: ${basename(session.projectPath)}`);\n } else {\n setStatusMessage('No folder for this session');\n }\n }\n setSelectedIndex(0);\n return;\n }\n });\n\n const handleSearchChange = useCallback((value: string) => {\n setSearchQuery(value);\n setSelectedIndex(0);\n }, []);\n\n if (loading && sessions.length === 0) {\n return (\n <Box padding={1}>\n <Spinner type=\"dots\" />\n <Text> Loading sessions...</Text>\n </Box>\n );\n }\n\n const selectedSession = sessions[selectedIndex] || null;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header embeddingsReady={embeddingsReady} projectFilter={projectFilter} />\n\n <SearchInput\n value={searchQuery}\n onChange={handleSearchChange}\n isFocused={mode === 'search'}\n />\n\n <SessionList\n sessions={sessions}\n selectedIndex={selectedIndex}\n onSelect={setSelectedIndex}\n />\n\n <Preview session={selectedSession} />\n\n {/* Footer */}\n <Box marginTop={1}>\n {mode === 'confirm-delete' ? (\n <Text color=\"yellow\">\n Delete \"{selectedSession?.customTitle || selectedSession?.title}\"? [y/n]\n </Text>\n ) : mode === 'rename' ? (\n <Box>\n <Text color=\"magenta\">Rename: </Text>\n <TextInput\n value={renameValue}\n onChange={setRenameValue}\n placeholder=\"Enter new name...\"\n />\n <Text dimColor> [Enter] Save [Esc] Cancel</Text>\n </Box>\n ) : statusMessage ? (\n <Text color=\"green\">{statusMessage}</Text>\n ) : (\n <Text dimColor>\n [↑↓/jk] Navigate [Enter] Resume [f] Filter folder [r] Rename [d] Delete [/] Search [q] Quit\n </Text>\n )}\n </Box>\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport { basename } from 'path';\n\ninterface HeaderProps {\n embeddingsReady: boolean;\n projectFilter?: string | null;\n}\n\nexport const Header: React.FC<HeaderProps> = ({ embeddingsReady, projectFilter }) => {\n return (\n <Box marginBottom={1} justifyContent=\"space-between\">\n <Box>\n <Text bold color=\"cyan\">cmem</Text>\n {projectFilter && (\n <Text color=\"yellow\"> 📁 {basename(projectFilter)}</Text>\n )}\n {!embeddingsReady && (\n <Text color=\"yellow\" dimColor> (loading model...)</Text>\n )}\n </Box>\n <Text dimColor>[q] quit</Text>\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport TextInput from 'ink-text-input';\n\ninterface SearchInputProps {\n value: string;\n onChange: (value: string) => void;\n isFocused: boolean;\n}\n\nexport const SearchInput: React.FC<SearchInputProps> = ({\n value,\n onChange,\n isFocused,\n}) => {\n return (\n <Box marginBottom={1}>\n <Text>Search: </Text>\n {isFocused ? (\n <TextInput\n value={value}\n onChange={onChange}\n placeholder=\"type to search...\"\n focus={true}\n />\n ) : (\n <Text dimColor>{value || 'press / to search'}</Text>\n )}\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport { basename } from 'path';\nimport type { Session } from '../../db/sessions.js';\nimport { formatTimeAgo, truncate } from '../../utils/format.js';\n\ninterface SessionListProps {\n sessions: Session[];\n selectedIndex: number;\n onSelect: (index: number) => void;\n}\n\nexport const SessionList: React.FC<SessionListProps> = ({\n sessions,\n selectedIndex,\n}) => {\n if (sessions.length === 0) {\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n >\n <Text bold>Sessions</Text>\n <Text dimColor>No sessions found</Text>\n <Text dimColor>Run: cmem save --latest</Text>\n </Box>\n );\n }\n\n // Show max 8 sessions, centered around selected\n const visibleCount = 8;\n let startIndex = Math.max(0, selectedIndex - Math.floor(visibleCount / 2));\n const endIndex = Math.min(sessions.length, startIndex + visibleCount);\n if (endIndex - startIndex < visibleCount) {\n startIndex = Math.max(0, endIndex - visibleCount);\n }\n\n const visibleSessions = sessions.slice(startIndex, endIndex);\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n >\n <Text bold>Sessions ({sessions.length})</Text>\n {visibleSessions.map((session, i) => {\n const actualIndex = startIndex + i;\n const isSelected = actualIndex === selectedIndex;\n\n return (\n <SessionItem\n key={session.id}\n session={session}\n isSelected={isSelected}\n />\n );\n })}\n {sessions.length > visibleCount && (\n <Text dimColor>\n {startIndex > 0 ? '↑ more above' : ''}\n {startIndex > 0 && endIndex < sessions.length ? ' | ' : ''}\n {endIndex < sessions.length ? '↓ more below' : ''}\n </Text>\n )}\n </Box>\n );\n};\n\ninterface SessionItemProps {\n session: Session;\n isSelected: boolean;\n}\n\nconst SessionItem: React.FC<SessionItemProps> = ({ session, isSelected }) => {\n const hasCustomTitle = !!session.customTitle;\n const displayTitle = truncate(session.customTitle || session.title, 40);\n const folderName = session.projectPath ? truncate(basename(session.projectPath), 40) : '';\n const msgs = String(session.messageCount).padStart(3);\n const updated = formatTimeAgo(session.updatedAt);\n\n // Determine title color: cyan if selected, magenta if renamed, undefined otherwise\n const getTitleColor = () => {\n if (isSelected) return 'cyan';\n if (hasCustomTitle) return 'magenta';\n return undefined;\n };\n\n return (\n <Box>\n <Text color={isSelected ? 'cyan' : undefined}>\n {isSelected ? '▸ ' : ' '}\n </Text>\n <Text bold={isSelected} color={getTitleColor()} wrap=\"truncate\">\n {displayTitle.padEnd(40)}\n </Text>\n <Text color=\"blue\"> {folderName.padEnd(40)}</Text>\n <Text dimColor> {msgs} </Text>\n <Text dimColor>{updated.padStart(8)}</Text>\n </Box>\n );\n};\n","/**\n * Format a timestamp into a human-readable relative time\n */\nexport function formatTimeAgo(timestamp: string): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffSecs = Math.floor(diffMs / 1000);\n const diffMins = Math.floor(diffSecs / 60);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n const diffWeeks = Math.floor(diffDays / 7);\n const diffMonths = Math.floor(diffDays / 30);\n\n if (diffSecs < 60) return 'just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n if (diffWeeks < 4) return `${diffWeeks}w ago`;\n return `${diffMonths}mo ago`;\n}\n\n/**\n * Truncate text to a maximum length with ellipsis\n */\nexport function truncate(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return text.slice(0, maxLength - 3) + '...';\n}\n\n/**\n * Generate a short ID from a longer string\n */\nexport function shortId(id: string): string {\n return id.slice(0, 8);\n}\n\n/**\n * Format a number with thousands separator\n */\nexport function formatNumber(num: number): string {\n return num.toLocaleString();\n}\n\n/**\n * Format bytes into human-readable size\n */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n}\n\n/**\n * Generate a title from message content\n */\nexport function generateTitle(content: string): string {\n // Take first line or first 50 chars\n const firstLine = content.split('\\n')[0].trim();\n const title = truncate(firstLine, 50);\n return title || 'Untitled Session';\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { Session } from '../../db/sessions.js';\nimport { truncate } from '../../utils/format.js';\n\ninterface PreviewProps {\n session: Session | null;\n}\n\nexport const Preview: React.FC<PreviewProps> = ({ session }) => {\n if (!session) {\n return null;\n }\n\n const summary = session.summary\n ? truncate(session.summary, 200)\n : 'No summary available';\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n marginTop={1}\n >\n <Box>\n <Text bold>Preview</Text>\n {session.projectPath && (\n <Text bold color=\"blue\"> 📁 {session.projectPath}</Text>\n )}\n </Box>\n <Text wrap=\"wrap\">{summary}</Text>\n <Text dimColor>Messages: {session.messageCount}</Text>\n </Box>\n );\n};\n","import { useState, useEffect, useCallback } from 'react';\nimport { listHumanSessions, listHumanSessionsByProject, deleteSession as dbDeleteSession, getSession } from '../../db/sessions.js';\nimport { searchSessions } from '../../db/vectors.js';\nimport { getEmbedding, initializeEmbeddings, isReady } from '../../embeddings/index.js';\nimport type { Session } from '../../db/sessions.js';\n\nexport interface UseSessionsOptions {\n projectFilter?: string | null;\n}\n\nexport interface UseSessionsResult {\n sessions: Session[];\n loading: boolean;\n error: string | null;\n embeddingsReady: boolean;\n projectFilter: string | null;\n setProjectFilter: (filter: string | null) => void;\n refresh: () => void;\n search: (query: string) => Promise<void>;\n clearSearch: () => void;\n deleteSession: (id: string) => void;\n getSessionById: (id: string) => Session | null;\n}\n\nexport function useSessions(options: UseSessionsOptions = {}): UseSessionsResult {\n const [sessions, setSessions] = useState<Session[]>([]);\n const [allSessions, setAllSessions] = useState<Session[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [embeddingsReady, setEmbeddingsReady] = useState(false);\n const [isSearching, setIsSearching] = useState(false);\n const [projectFilter, setProjectFilter] = useState<string | null>(options.projectFilter ?? null);\n\n const loadSessions = useCallback(() => {\n try {\n const loaded = projectFilter\n ? listHumanSessionsByProject(projectFilter)\n : listHumanSessions();\n setAllSessions(loaded);\n setSessions(loaded);\n setError(null);\n } catch (err) {\n setError(String(err));\n } finally {\n setLoading(false);\n }\n }, [projectFilter]);\n\n const initEmbeddings = useCallback(async () => {\n if (isReady()) {\n setEmbeddingsReady(true);\n return;\n }\n try {\n await initializeEmbeddings();\n setEmbeddingsReady(true);\n } catch {\n setEmbeddingsReady(false);\n }\n }, []);\n\n useEffect(() => {\n loadSessions();\n initEmbeddings();\n }, [loadSessions, initEmbeddings]);\n\n // Reload when project filter changes\n useEffect(() => {\n loadSessions();\n }, [projectFilter, loadSessions]);\n\n const search = useCallback(async (query: string) => {\n if (!query.trim()) {\n setSessions(allSessions);\n setIsSearching(false);\n return;\n }\n\n if (!embeddingsReady) {\n // Fall back to simple text search\n const filtered = allSessions.filter(s =>\n s.title.toLowerCase().includes(query.toLowerCase()) ||\n (s.summary && s.summary.toLowerCase().includes(query.toLowerCase()))\n );\n setSessions(filtered);\n setIsSearching(true);\n return;\n }\n\n try {\n setLoading(true);\n const queryEmbedding = await getEmbedding(query);\n const results = searchSessions(queryEmbedding, 20);\n setSessions(results);\n setIsSearching(true);\n } catch (err) {\n setError(String(err));\n // Fall back to text search on error\n const filtered = allSessions.filter(s =>\n s.title.toLowerCase().includes(query.toLowerCase()) ||\n (s.summary && s.summary.toLowerCase().includes(query.toLowerCase()))\n );\n setSessions(filtered);\n } finally {\n setLoading(false);\n }\n }, [allSessions, embeddingsReady]);\n\n const clearSearch = useCallback(() => {\n setSessions(allSessions);\n setIsSearching(false);\n }, [allSessions]);\n\n const deleteSessionHandler = useCallback((id: string) => {\n const deleted = dbDeleteSession(id);\n if (deleted) {\n setAllSessions(prev => prev.filter(s => s.id !== id));\n setSessions(prev => prev.filter(s => s.id !== id));\n }\n }, []);\n\n const getSessionById = useCallback((id: string) => {\n return getSession(id);\n }, []);\n\n return {\n sessions,\n loading,\n error,\n embeddingsReady,\n projectFilter,\n setProjectFilter,\n refresh: loadSessions,\n search,\n clearSearch,\n deleteSession: deleteSessionHandler,\n getSessionById,\n };\n}\n","import Database from 'better-sqlite3';\nimport * as sqliteVec from 'sqlite-vec';\nimport { existsSync } from 'fs';\nimport { DB_PATH, ensureCmemDir, EMBEDDING_DIMENSIONS } from '../utils/config.js';\nimport { extractSessionMetadata } from '../parser/index.js';\n\nlet db: Database.Database | null = null;\n\n/**\n * Get or create the database connection\n */\nexport function getDatabase(): Database.Database {\n if (db) return db;\n\n ensureCmemDir();\n\n db = new Database(DB_PATH);\n db.pragma('journal_mode = WAL');\n\n // Load sqlite-vec extension\n sqliteVec.load(db);\n\n // Initialize schema\n initSchema(db);\n\n return db;\n}\n\n/**\n * Initialize database schema\n */\nfunction initSchema(database: Database.Database): void {\n // Migrations tracking table\n database.exec(`\n CREATE TABLE IF NOT EXISTS migrations (\n name TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL\n );\n `);\n\n // Sessions table\n database.exec(`\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n summary TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n message_count INTEGER DEFAULT 0,\n project_path TEXT,\n source_file TEXT,\n raw_data TEXT NOT NULL\n );\n `);\n\n // Add source_file column if it doesn't exist (migration)\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN source_file TEXT`);\n } catch {\n // Column already exists\n }\n\n // Add is_sidechain column if it doesn't exist (migration)\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN is_sidechain INTEGER DEFAULT 0`);\n } catch {\n // Column already exists\n }\n\n // Add is_automated column if it doesn't exist (migration)\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN is_automated INTEGER DEFAULT 0`);\n } catch {\n // Column already exists\n }\n\n // Add custom_title column if it doesn't exist (migration)\n // Used for user-renamed sessions\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN custom_title TEXT`);\n } catch {\n // Column already exists\n }\n\n // Messages table\n database.exec(`\n CREATE TABLE IF NOT EXISTS messages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),\n content TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n `);\n\n // Embedding state tracking for incremental updates\n database.exec(`\n CREATE TABLE IF NOT EXISTS embedding_state (\n session_id TEXT PRIMARY KEY,\n content_length INTEGER NOT NULL,\n file_mtime TEXT,\n last_embedded_at TEXT NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n `);\n\n // Vector embeddings table (768 dimensions for nomic-embed-text)\n database.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS session_embeddings USING vec0(\n session_id TEXT PRIMARY KEY,\n embedding FLOAT[${EMBEDDING_DIMENSIONS}]\n );\n `);\n\n // Indexes\n database.exec(`\n CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);\n `);\n database.exec(`\n CREATE INDEX IF NOT EXISTS idx_sessions_updated ON sessions(updated_at DESC);\n `);\n database.exec(`\n CREATE INDEX IF NOT EXISTS idx_sessions_source ON sessions(source_file);\n `);\n\n // Run data migrations\n runMigrations(database);\n}\n\n/**\n * Run data migrations (separate from schema migrations)\n */\nfunction runMigrations(database: Database.Database): void {\n // Migration: Populate is_sidechain and is_automated from JSONL metadata\n const migrationName = 'populate_session_metadata_v1';\n\n const existing = database.prepare(\n 'SELECT 1 FROM migrations WHERE name = ?'\n ).get(migrationName);\n\n if (existing) return; // Already applied\n\n // Get all sessions with source files\n const sessions = database.prepare(`\n SELECT id, source_file FROM sessions WHERE source_file IS NOT NULL\n `).all() as { id: string; source_file: string }[];\n\n const updateStmt = database.prepare(`\n UPDATE sessions SET is_sidechain = ?, is_automated = ? WHERE id = ?\n `);\n\n const transaction = database.transaction(() => {\n for (const session of sessions) {\n if (!existsSync(session.source_file)) continue;\n\n try {\n const metadata = extractSessionMetadata(session.source_file);\n const isAutomated = metadata.isSidechain || metadata.isMeta;\n updateStmt.run(\n metadata.isSidechain ? 1 : 0,\n isAutomated ? 1 : 0,\n session.id\n );\n } catch {\n // Skip files that can't be parsed\n }\n }\n\n // Mark migration as complete\n database.prepare(\n 'INSERT INTO migrations (name, applied_at) VALUES (?, ?)'\n ).run(migrationName, new Date().toISOString());\n });\n\n transaction();\n}\n\n/**\n * Close the database connection\n */\nexport function closeDatabase(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n","import { homedir } from 'os';\nimport { join } from 'path';\nimport { mkdirSync, existsSync } from 'fs';\n\n// Data storage paths\nexport const CMEM_DIR = join(homedir(), '.cmem');\nexport const DB_PATH = join(CMEM_DIR, 'sessions.db');\nexport const MODELS_DIR = join(CMEM_DIR, 'models');\n\n// Claude Code paths\nexport const CLAUDE_DIR = join(homedir(), '.claude');\nexport const CLAUDE_PROJECTS_DIR = join(CLAUDE_DIR, 'projects');\nexport const CLAUDE_SESSIONS_DIR = join(CLAUDE_DIR, 'sessions');\n\n// Embedding model settings (transformers.js)\nexport const EMBEDDING_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\nexport const EMBEDDING_DIMENSIONS = 768;\n\n// Text limits\nexport const MAX_EMBEDDING_CHARS = 8000;\nexport const MAX_MESSAGE_PREVIEW_CHARS = 500;\nexport const MAX_MESSAGES_FOR_CONTEXT = 20;\n\n// Ensure cmem directory exists\nexport function ensureCmemDir(): void {\n if (!existsSync(CMEM_DIR)) {\n mkdirSync(CMEM_DIR, { recursive: true });\n }\n}\n\n// Ensure models directory exists\nexport function ensureModelsDir(): void {\n ensureCmemDir();\n if (!existsSync(MODELS_DIR)) {\n mkdirSync(MODELS_DIR, { recursive: true });\n }\n}\n","import { readFileSync, readdirSync, existsSync, statSync } from 'fs';\nimport { join, basename, dirname } from 'path';\nimport { CLAUDE_PROJECTS_DIR, CLAUDE_SESSIONS_DIR } from '../utils/config.js';\n\nexport interface ParsedMessage {\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n}\n\nexport interface SessionMetadata {\n isSidechain: boolean;\n isMeta: boolean;\n}\n\n// Patterns that indicate automated/system sessions based on title\nconst AUTOMATED_TITLE_PATTERNS = [\n /^<[a-z-]+>/i, // XML-like tags: <project-instructions>, <command-message>, etc.\n /^<[A-Z_]+>/, // Uppercase tags: <SYSTEM>, <TOOL_USE>, etc.\n /^\\[system\\]/i, // [system] prefix\n /^\\/[a-z]+$/i, // Slash commands: /init, /help, etc.\n];\n\n/**\n * Check if a title/first message indicates an automated session\n */\nexport function isAutomatedByContent(title: string): boolean {\n for (const pattern of AUTOMATED_TITLE_PATTERNS) {\n if (pattern.test(title.trim())) {\n return true;\n }\n }\n return false;\n}\n\nexport interface ParsedSession {\n filePath: string;\n projectPath: string | null;\n messages: ParsedMessage[];\n rawData: string;\n modifiedAt: Date;\n agentMessages?: ParsedMessage[]; // Messages from subagents linked to this session\n}\n\ninterface SessionIndexEntry {\n sessionId: string;\n fullPath: string;\n fileMtime: number;\n firstPrompt: string;\n messageCount: number;\n created: string;\n modified: string;\n gitBranch?: string;\n projectPath: string;\n isSidechain: boolean;\n}\n\ninterface SessionsIndex {\n version: number;\n entries: SessionIndexEntry[];\n}\n\n/**\n * Extract session metadata from JSONL file (isSidechain, agentId, isMeta, etc.)\n * Only uses reliable JSONL metadata fields, not content-based heuristics\n */\nexport function extractSessionMetadata(filepath: string): SessionMetadata {\n const content = readFileSync(filepath, 'utf-8');\n\n const metadata: SessionMetadata = {\n isSidechain: false,\n isMeta: false,\n };\n\n // Find the first user message to check metadata\n for (const line of content.split('\\n')) {\n if (!line.trim()) continue;\n\n try {\n const parsed = JSON.parse(line);\n\n // Look for the first user message\n if (parsed.type === 'user' && parsed.message) {\n // Check isSidechain field (present in all Claude Code JSONL entries)\n // This is true for subagent/automated sessions\n if (parsed.isSidechain === true) {\n metadata.isSidechain = true;\n }\n\n // Check if this has an agentId (subagent session)\n if (parsed.agentId) {\n metadata.isSidechain = true;\n }\n\n // Check isMeta field - true for local command sessions\n if (parsed.isMeta === true) {\n metadata.isMeta = true;\n }\n\n break; // Only need first user message\n }\n } catch {\n // Skip malformed lines\n }\n }\n\n return metadata;\n}\n\n/**\n * Parse a Claude Code session JSONL file\n */\nexport function parseSessionFile(filepath: string): ParsedMessage[] {\n const content = readFileSync(filepath, 'utf-8');\n const messages: ParsedMessage[] = [];\n\n for (const line of content.split('\\n')) {\n if (!line.trim()) continue;\n\n try {\n const parsed = JSON.parse(line);\n\n // Handle different Claude Code JSONL formats\n if ((parsed.type === 'user' || parsed.type === 'assistant') && parsed.message) {\n // Claude Code format: type is 'user'/'assistant', message contains the actual content\n const msg = parsed.message;\n if (msg.role && msg.content) {\n const content = Array.isArray(msg.content)\n ? msg.content\n .filter((c: { type: string }) => c.type === 'text')\n .map((c: { text: string }) => c.text)\n .join('\\n')\n : typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content);\n\n if (content) {\n messages.push({\n role: msg.role as 'user' | 'assistant',\n content,\n timestamp: parsed.timestamp || new Date().toISOString(),\n });\n }\n }\n } else if (parsed.type === 'message' && parsed.role && parsed.content) {\n // Standard message format\n messages.push({\n role: parsed.role as 'user' | 'assistant',\n content: typeof parsed.content === 'string'\n ? parsed.content\n : JSON.stringify(parsed.content),\n timestamp: parsed.timestamp || new Date().toISOString(),\n });\n } else if (parsed.role && parsed.content && !parsed.type) {\n // Simplified format without type field\n messages.push({\n role: parsed.role as 'user' | 'assistant',\n content: typeof parsed.content === 'string'\n ? parsed.content\n : JSON.stringify(parsed.content),\n timestamp: parsed.timestamp || new Date().toISOString(),\n });\n }\n // Skip tool_use, tool_result, and other non-message entries\n } catch {\n // Skip malformed lines\n }\n }\n\n return messages;\n}\n\n/**\n * Find all Claude Code session files (excluding subagent sessions)\n */\nexport function findSessionFiles(): ParsedSession[] {\n const sessions: ParsedSession[] = [];\n\n // Search in ~/.claude/projects/<hash>/\n if (existsSync(CLAUDE_PROJECTS_DIR)) {\n const projectDirs = readdirSync(CLAUDE_PROJECTS_DIR);\n for (const projectDir of projectDirs) {\n const projectDirPath = join(CLAUDE_PROJECTS_DIR, projectDir);\n const stat = statSync(projectDirPath);\n if (!stat.isDirectory()) continue;\n\n // Try to read sessions-index.json for metadata\n const indexPath = join(projectDirPath, 'sessions-index.json');\n const sessionIndex = loadSessionIndex(indexPath);\n\n // Build a map of session IDs to their metadata\n const indexedSessions = new Map<string, SessionIndexEntry>();\n if (sessionIndex) {\n for (const entry of sessionIndex.entries) {\n indexedSessions.set(entry.sessionId, entry);\n }\n }\n\n // Only load .jsonl files directly in the project directory (not in subfolders)\n const entries = readdirSync(projectDirPath, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.jsonl')) continue;\n\n const filePath = join(projectDirPath, entry.name);\n const sessionId = entry.name.replace('.jsonl', '');\n\n try {\n const session = loadSession(filePath);\n if (session) {\n // Use metadata from sessions-index.json if available\n const indexEntry = indexedSessions.get(sessionId);\n if (indexEntry) {\n session.projectPath = indexEntry.projectPath;\n }\n\n // Load any subagent messages for this session\n const agentMessages = loadSubagentMessages(projectDirPath, sessionId);\n if (agentMessages.length > 0) {\n session.agentMessages = agentMessages;\n }\n\n sessions.push(session);\n }\n } catch {\n // Skip unreadable files\n }\n }\n }\n }\n\n // Search in ~/.claude/sessions/ (no subagents here)\n if (existsSync(CLAUDE_SESSIONS_DIR)) {\n const sessionFiles = readdirSync(CLAUDE_SESSIONS_DIR).filter(f => f.endsWith('.jsonl'));\n for (const sessionFile of sessionFiles) {\n const filePath = join(CLAUDE_SESSIONS_DIR, sessionFile);\n try {\n const session = loadSession(filePath);\n if (session) {\n sessions.push(session);\n }\n } catch {\n // Skip unreadable files\n }\n }\n }\n\n // Sort by modification time (newest first)\n sessions.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());\n\n return sessions;\n}\n\n/**\n * Load sessions-index.json if it exists\n */\nfunction loadSessionIndex(indexPath: string): SessionsIndex | null {\n if (!existsSync(indexPath)) return null;\n\n try {\n const content = readFileSync(indexPath, 'utf-8');\n return JSON.parse(content) as SessionsIndex;\n } catch {\n return null;\n }\n}\n\n/**\n * Load messages from all subagent sessions for a parent session\n */\nfunction loadSubagentMessages(projectDirPath: string, parentSessionId: string): ParsedMessage[] {\n const subagentsDir = join(projectDirPath, parentSessionId, 'subagents');\n if (!existsSync(subagentsDir)) return [];\n\n const messages: ParsedMessage[] = [];\n\n try {\n const agentFiles = readdirSync(subagentsDir).filter(f => f.endsWith('.jsonl'));\n for (const agentFile of agentFiles) {\n const agentPath = join(subagentsDir, agentFile);\n const agentMessages = parseSessionFile(agentPath);\n messages.push(...agentMessages);\n }\n } catch {\n // Ignore errors reading subagent files\n }\n\n return messages;\n}\n\n/**\n * Load a session from a file path\n */\nfunction loadSession(filePath: string): ParsedSession | null {\n const rawData = readFileSync(filePath, 'utf-8');\n const messages = parseSessionFile(filePath);\n\n // Skip empty sessions\n if (messages.length === 0) {\n return null;\n }\n\n const stats = statSync(filePath);\n\n return {\n filePath,\n projectPath: null,\n messages,\n rawData,\n modifiedAt: stats.mtime,\n };\n}\n\n\n/**\n * Get the most recent session file\n */\nexport function getMostRecentSession(): ParsedSession | null {\n const sessions = findSessionFiles();\n return sessions.length > 0 ? sessions[0] : null;\n}\n\n/**\n * Generate a summary from session messages\n */\nexport function generateSummary(messages: ParsedMessage[]): string {\n // Take first user message as the main topic\n const firstUserMessage = messages.find(m => m.role === 'user');\n if (!firstUserMessage) {\n return 'No user messages found';\n }\n\n // Truncate to reasonable summary length\n const summary = firstUserMessage.content.slice(0, 300);\n return summary.length < firstUserMessage.content.length ? summary + '...' : summary;\n}\n","import { getDatabase } from './index.js';\nimport { randomUUID } from 'crypto';\n\nexport interface Session {\n id: string;\n title: string;\n customTitle: string | null;\n summary: string | null;\n createdAt: string;\n updatedAt: string;\n messageCount: number;\n projectPath: string | null;\n sourceFile: string | null;\n rawData: string;\n isSidechain: boolean;\n isAutomated: boolean;\n}\n\nexport interface Message {\n id: number;\n sessionId: string;\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n}\n\nexport interface SessionInput {\n title: string;\n summary?: string;\n projectPath?: string;\n sourceFile?: string;\n rawData: string;\n messages: Omit<Message, 'id' | 'sessionId'>[];\n isSidechain?: boolean;\n isAutomated?: boolean;\n}\n\nexport interface EmbeddingState {\n sessionId: string;\n contentLength: number;\n fileMtime: string | null;\n lastEmbeddedAt: string;\n}\n\n/**\n * Create a new session\n */\nexport function createSession(input: SessionInput): string {\n const db = getDatabase();\n const id = randomUUID();\n const now = new Date().toISOString();\n\n const insertSession = db.prepare(`\n INSERT INTO sessions (id, title, summary, created_at, updated_at, message_count, project_path, source_file, raw_data, is_sidechain, is_automated)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertMessage = db.prepare(`\n INSERT INTO messages (session_id, role, content, timestamp)\n VALUES (?, ?, ?, ?)\n `);\n\n const transaction = db.transaction(() => {\n insertSession.run(\n id,\n input.title,\n input.summary || null,\n now,\n now,\n input.messages.length,\n input.projectPath || null,\n input.sourceFile || null,\n input.rawData,\n input.isSidechain ? 1 : 0,\n input.isAutomated ? 1 : 0\n );\n\n for (const msg of input.messages) {\n insertMessage.run(id, msg.role, msg.content, msg.timestamp);\n }\n });\n\n transaction();\n return id;\n}\n\n/**\n * Update an existing session with new data\n */\nexport function updateSession(id: string, input: Partial<SessionInput>): void {\n const db = getDatabase();\n const now = new Date().toISOString();\n\n const updates: string[] = ['updated_at = ?'];\n const values: unknown[] = [now];\n\n if (input.title !== undefined) {\n updates.push('title = ?');\n values.push(input.title);\n }\n if (input.summary !== undefined) {\n updates.push('summary = ?');\n values.push(input.summary);\n }\n if (input.rawData !== undefined) {\n updates.push('raw_data = ?');\n values.push(input.rawData);\n }\n if (input.messages !== undefined) {\n updates.push('message_count = ?');\n values.push(input.messages.length);\n }\n if (input.isSidechain !== undefined) {\n updates.push('is_sidechain = ?');\n values.push(input.isSidechain ? 1 : 0);\n }\n if (input.isAutomated !== undefined) {\n updates.push('is_automated = ?');\n values.push(input.isAutomated ? 1 : 0);\n }\n if (input.projectPath !== undefined) {\n updates.push('project_path = ?');\n values.push(input.projectPath);\n }\n\n values.push(id);\n\n const transaction = db.transaction(() => {\n db.prepare(`UPDATE sessions SET ${updates.join(', ')} WHERE id = ?`).run(...values);\n\n // If messages provided, replace them\n if (input.messages !== undefined) {\n db.prepare('DELETE FROM messages WHERE session_id = ?').run(id);\n const insertMessage = db.prepare(`\n INSERT INTO messages (session_id, role, content, timestamp)\n VALUES (?, ?, ?, ?)\n `);\n for (const msg of input.messages) {\n insertMessage.run(id, msg.role, msg.content, msg.timestamp);\n }\n }\n });\n\n transaction();\n}\n\n/**\n * Get a session by ID\n */\nexport function getSession(id: string): Session | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions WHERE id = ?\n `).get(id) as SessionRow | undefined;\n\n if (!row) return null;\n return mapSessionRow(row);\n}\n\n/**\n * Get a session by ID prefix (for partial ID matching)\n */\nexport function getSessionByIdPrefix(idPrefix: string): Session | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions WHERE id LIKE ? || '%'\n LIMIT 1\n `).get(idPrefix) as SessionRow | undefined;\n\n if (!row) return null;\n return mapSessionRow(row);\n}\n\n/**\n * Get a session by source file path\n */\nexport function getSessionBySourceFile(sourceFile: string): Session | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions WHERE source_file = ?\n `).get(sourceFile) as SessionRow | undefined;\n\n if (!row) return null;\n return mapSessionRow(row);\n}\n\n/**\n * Get messages for a session\n */\nexport function getSessionMessages(sessionId: string): Message[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT id, session_id as sessionId, role, content, timestamp\n FROM messages WHERE session_id = ?\n ORDER BY timestamp ASC\n `).all(sessionId) as Message[];\n\n return rows;\n}\n\ntype SessionRow = {\n isSidechain: number;\n isAutomated: number;\n customTitle: string | null;\n} & Omit<Session, 'isSidechain' | 'isAutomated' | 'customTitle'>;\n\nfunction mapSessionRow(row: SessionRow): Session {\n return {\n ...row,\n customTitle: row.customTitle,\n isSidechain: row.isSidechain === 1,\n isAutomated: row.isAutomated === 1,\n };\n}\n\n/**\n * List all sessions ordered by updated_at desc\n */\nexport function listSessions(limit = 100): Session[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions\n ORDER BY updated_at DESC\n LIMIT ?\n `).all(limit) as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n\n/**\n * Check if a session appears to be an automated/system session rather than a real human conversation\n * Uses metadata stored in the database (isSidechain, isAutomated) which was extracted from the JSONL\n */\nexport function isAutomatedSession(session: Session): boolean {\n // Use the metadata fields from the database\n if (session.isSidechain || session.isAutomated) {\n return true;\n }\n\n return false;\n}\n\n/**\n * List human sessions (filters out automated/system sessions)\n * Filters directly in SQL for better performance\n */\nexport function listHumanSessions(limit = 100): Session[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions\n WHERE is_sidechain = 0 AND is_automated = 0\n ORDER BY updated_at DESC\n LIMIT ?\n `).all(limit) as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n\n/**\n * List human sessions filtered by project path\n * Uses LIKE to match sessions where the project_path starts with the given path\n */\nexport function listHumanSessionsByProject(projectPath: string, limit = 100): Session[] {\n const db = getDatabase();\n // Use LIKE to match sessions in this folder or subfolders\n const rows = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions\n WHERE is_sidechain = 0 AND is_automated = 0\n AND project_path LIKE ? || '%'\n ORDER BY updated_at DESC\n LIMIT ?\n `).all(projectPath, limit) as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n\n/**\n * Delete a session\n */\nexport function deleteSession(id: string): boolean {\n const db = getDatabase();\n\n const transaction = db.transaction(() => {\n // Delete from vector table first\n db.prepare('DELETE FROM session_embeddings WHERE session_id = ?').run(id);\n // Delete embedding state\n db.prepare('DELETE FROM embedding_state WHERE session_id = ?').run(id);\n // Delete messages (cascade should handle this, but explicit is safer)\n db.prepare('DELETE FROM messages WHERE session_id = ?').run(id);\n // Delete session\n const result = db.prepare('DELETE FROM sessions WHERE id = ?').run(id);\n return result.changes > 0;\n });\n\n return transaction();\n}\n\n/**\n * Update session summary\n */\nexport function updateSessionSummary(id: string, summary: string): void {\n const db = getDatabase();\n db.prepare(`\n UPDATE sessions SET summary = ?, updated_at = ? WHERE id = ?\n `).run(summary, new Date().toISOString(), id);\n}\n\n/**\n * Rename a session (set custom title)\n */\nexport function renameSession(id: string, customTitle: string | null): void {\n const db = getDatabase();\n db.prepare(`\n UPDATE sessions SET custom_title = ?, updated_at = ? WHERE id = ?\n `).run(customTitle, new Date().toISOString(), id);\n}\n\n/**\n * Get storage statistics\n */\nexport function getStats(): {\n sessionCount: number;\n messageCount: number;\n embeddingCount: number;\n} {\n const db = getDatabase();\n\n const sessionCount = (db.prepare('SELECT COUNT(*) as count FROM sessions').get() as { count: number }).count;\n const messageCount = (db.prepare('SELECT COUNT(*) as count FROM messages').get() as { count: number }).count;\n const embeddingCount = (db.prepare('SELECT COUNT(*) as count FROM session_embeddings').get() as { count: number }).count;\n\n return { sessionCount, messageCount, embeddingCount };\n}\n\n/**\n * Check if a session exists by its raw data hash (to avoid duplicates)\n */\nexport function sessionExists(rawData: string): boolean {\n const db = getDatabase();\n const row = db.prepare('SELECT 1 FROM sessions WHERE raw_data = ? LIMIT 1').get(rawData);\n return !!row;\n}\n\n/**\n * Get embedding state for a session\n */\nexport function getEmbeddingState(sessionId: string): EmbeddingState | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT session_id as sessionId, content_length as contentLength,\n file_mtime as fileMtime, last_embedded_at as lastEmbeddedAt\n FROM embedding_state WHERE session_id = ?\n `).get(sessionId) as EmbeddingState | undefined;\n\n return row || null;\n}\n\n/**\n * Update embedding state for a session\n */\nexport function updateEmbeddingState(\n sessionId: string,\n contentLength: number,\n fileMtime?: string\n): void {\n const db = getDatabase();\n const now = new Date().toISOString();\n\n db.prepare(`\n INSERT OR REPLACE INTO embedding_state (session_id, content_length, file_mtime, last_embedded_at)\n VALUES (?, ?, ?, ?)\n `).run(sessionId, contentLength, fileMtime || null, now);\n}\n\n/**\n * Check if session needs re-embedding based on content growth\n * Returns true if content has grown by more than threshold chars\n */\nexport function needsReembedding(sessionId: string, currentContentLength: number, threshold = 500): boolean {\n const state = getEmbeddingState(sessionId);\n if (!state) return true; // Never embedded\n return currentContentLength - state.contentLength >= threshold;\n}\n\n/**\n * Get all sessions that need embedding\n */\nexport function getSessionsNeedingEmbedding(): Session[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT s.id, s.title, s.custom_title as customTitle, s.summary,\n s.created_at as createdAt, s.updated_at as updatedAt,\n s.message_count as messageCount, s.project_path as projectPath,\n s.source_file as sourceFile, s.raw_data as rawData,\n s.is_sidechain as isSidechain, s.is_automated as isAutomated\n FROM sessions s\n LEFT JOIN embedding_state e ON s.id = e.session_id\n WHERE e.session_id IS NULL\n ORDER BY s.updated_at DESC\n `).all() as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n","import { getDatabase } from './index.js';\nimport type { Session } from './sessions.js';\n\n/**\n * Store an embedding for a session\n */\nexport function storeEmbedding(sessionId: string, embedding: number[]): void {\n const db = getDatabase();\n\n // sqlite-vec expects JSON array format\n const embeddingJson = JSON.stringify(embedding);\n\n db.prepare(`\n INSERT OR REPLACE INTO session_embeddings (session_id, embedding)\n VALUES (?, ?)\n `).run(sessionId, embeddingJson);\n}\n\n/**\n * Search for similar sessions using vector similarity\n */\nexport function searchSimilar(queryEmbedding: number[], limit = 10): Array<{ sessionId: string; distance: number }> {\n const db = getDatabase();\n\n const embeddingJson = JSON.stringify(queryEmbedding);\n\n // Use vec_distance_L2 for Euclidean distance (lower = more similar)\n const rows = db.prepare(`\n SELECT session_id as sessionId, vec_distance_L2(embedding, ?) as distance\n FROM session_embeddings\n ORDER BY distance ASC\n LIMIT ?\n `).all(embeddingJson, limit) as Array<{ sessionId: string; distance: number }>;\n\n return rows;\n}\n\n/**\n * Search sessions and return full session objects\n */\nexport function searchSessions(queryEmbedding: number[], limit = 10): Session[] {\n const db = getDatabase();\n\n const embeddingJson = JSON.stringify(queryEmbedding);\n\n const rows = db.prepare(`\n SELECT s.id, s.title, s.summary, s.created_at as createdAt, s.updated_at as updatedAt,\n s.message_count as messageCount, s.project_path as projectPath, s.raw_data as rawData,\n vec_distance_L2(e.embedding, ?) as distance\n FROM session_embeddings e\n JOIN sessions s ON e.session_id = s.id\n ORDER BY distance ASC\n LIMIT ?\n `).all(embeddingJson, limit) as Session[];\n\n return rows;\n}\n\n/**\n * Delete embedding for a session\n */\nexport function deleteEmbedding(sessionId: string): void {\n const db = getDatabase();\n db.prepare('DELETE FROM session_embeddings WHERE session_id = ?').run(sessionId);\n}\n\n/**\n * Check if session has an embedding\n */\nexport function hasEmbedding(sessionId: string): boolean {\n const db = getDatabase();\n const row = db.prepare('SELECT 1 FROM session_embeddings WHERE session_id = ? LIMIT 1').get(sessionId);\n return !!row;\n}\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport {\n EMBEDDING_MODEL,\n MODELS_DIR,\n MAX_EMBEDDING_CHARS,\n MAX_MESSAGE_PREVIEW_CHARS,\n ensureModelsDir,\n} from '../utils/config.js';\n\n// Lazy load transformers.js\nlet transformersModule: typeof import('@xenova/transformers') | null = null;\nlet pipeline: any = null;\nlet initialized = false;\n\nasync function getTransformers() {\n if (!transformersModule) {\n transformersModule = await import('@xenova/transformers');\n }\n return transformersModule;\n}\n\nexport interface InitProgress {\n status: 'checking' | 'downloading' | 'loading' | 'ready';\n file?: string;\n progress?: number;\n}\n\n/**\n * Check if the model is already cached locally\n */\nexport function isModelCached(): boolean {\n // Transformers.js stores models at models/org/model-name/\n const modelCachePath = join(MODELS_DIR, EMBEDDING_MODEL);\n return existsSync(modelCachePath);\n}\n\n/**\n * Initialize the embedding pipeline\n * Downloads the model on first use with progress callback\n */\nexport async function initializeEmbeddings(\n onProgress?: (progress: InitProgress) => void\n): Promise<void> {\n if (initialized && pipeline) {\n return;\n }\n\n ensureModelsDir();\n\n const { pipeline: createPipeline, env } = await getTransformers();\n\n // Configure cache directory\n env.cacheDir = MODELS_DIR;\n\n // Check if model is cached\n const cached = isModelCached();\n if (cached) {\n env.allowRemoteModels = false; // Use local cache only\n onProgress?.({ status: 'loading' });\n } else {\n onProgress?.({ status: 'downloading' });\n }\n\n // Create the pipeline with progress callback\n pipeline = await createPipeline('feature-extraction', EMBEDDING_MODEL, {\n progress_callback: onProgress\n ? (progress: { status: string; file?: string; progress?: number }) => {\n if (progress.status === 'progress' && progress.file && progress.progress !== undefined) {\n onProgress({\n status: 'downloading',\n file: progress.file,\n progress: progress.progress,\n });\n }\n }\n : undefined,\n });\n\n initialized = true;\n onProgress?.({ status: 'ready' });\n}\n\n/**\n * Check if embeddings are ready to use\n */\nexport function isReady(): boolean {\n return initialized && pipeline !== null;\n}\n\n/**\n * Generate an embedding vector for text\n */\nexport async function getEmbedding(text: string): Promise<number[]> {\n // Initialize if needed (will use cached model if available)\n if (!initialized) {\n await initializeEmbeddings();\n }\n\n // Truncate to max chars\n const truncated = text.slice(0, MAX_EMBEDDING_CHARS);\n\n // Generate embedding\n const output = await pipeline(truncated, {\n pooling: 'mean',\n normalize: true,\n });\n\n // Convert to regular array\n return Array.from(output.data);\n}\n\n/**\n * Create embedding text from session data\n * Combines title, summary, and key messages for semantic search\n */\nexport function createEmbeddingText(\n title: string,\n summary: string | undefined,\n messages: Array<{ role: string; content: string }>\n): string {\n const parts: string[] = [];\n\n // Add title\n parts.push(`Title: ${title}`);\n\n // Add summary if available\n if (summary) {\n parts.push(`Summary: ${summary}`);\n }\n\n // Add first 5 user messages (truncated)\n const userMessages = messages\n .filter((m) => m.role === 'user')\n .slice(0, 5)\n .map((m) => m.content.slice(0, MAX_MESSAGE_PREVIEW_CHARS));\n\n if (userMessages.length > 0) {\n parts.push('User messages:');\n parts.push(...userMessages);\n }\n\n // Add first 3 assistant responses (truncated) for context\n const assistantMessages = messages\n .filter((m) => m.role === 'assistant')\n .slice(0, 3)\n .map((m) => m.content.slice(0, MAX_MESSAGE_PREVIEW_CHARS));\n\n if (assistantMessages.length > 0) {\n parts.push('Assistant responses:');\n parts.push(...assistantMessages);\n }\n\n return parts.join('\\n\\n');\n}\n","import chalk from 'chalk';\nimport { findSessionFiles, getMostRecentSession, generateSummary } from '../parser/index.js';\nimport { createSession, sessionExists } from '../db/sessions.js';\nimport { storeEmbedding } from '../db/vectors.js';\nimport { getEmbedding, createEmbeddingText, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { generateTitle } from '../utils/format.js';\n\ninterface SaveOptions {\n title?: string;\n latest?: boolean;\n}\n\nexport async function saveCommand(options: SaveOptions): Promise<void> {\n console.log(chalk.cyan('Scanning for Claude Code sessions...'));\n\n // Initialize embeddings (downloads model if needed)\n let embeddingsReady = isReady();\n if (!embeddingsReady) {\n console.log(chalk.dim('Initializing embedding model...'));\n try {\n await initializeEmbeddings();\n embeddingsReady = true;\n } catch (err) {\n console.log(chalk.yellow('Warning: Could not initialize embeddings.'));\n console.log(chalk.yellow('Semantic search will not be available.'));\n }\n }\n\n // Find sessions\n const sessions = findSessionFiles();\n\n if (sessions.length === 0) {\n console.log(chalk.red('No Claude Code sessions found.'));\n console.log(chalk.dim('Looking in:'));\n console.log(chalk.dim(' ~/.claude/projects/'));\n console.log(chalk.dim(' ~/.claude/sessions/'));\n console.log(chalk.dim('\\nUse Claude Code first, then run: cmem save --latest'));\n return;\n }\n\n console.log(chalk.green(`Found ${sessions.length} session(s)`));\n\n // Select session to save\n let sessionToSave = options.latest ? getMostRecentSession() : sessions[0];\n\n if (!sessionToSave) {\n console.log(chalk.red('No valid session found.'));\n return;\n }\n\n // Check for duplicates\n if (sessionExists(sessionToSave.rawData)) {\n console.log(chalk.yellow('This session has already been saved.'));\n return;\n }\n\n // Generate title from first user message if not provided\n const firstUserMsg = sessionToSave.messages.find(m => m.role === 'user');\n const title = options.title || (firstUserMsg ? generateTitle(firstUserMsg.content) : 'Untitled Session');\n\n // Generate summary\n const summary = generateSummary(sessionToSave.messages);\n\n console.log(chalk.dim(`Title: ${title}`));\n console.log(chalk.dim(`Messages: ${sessionToSave.messages.length}`));\n console.log(chalk.dim(`Project: ${sessionToSave.projectPath || 'Unknown'}`));\n\n // Create session in database\n const sessionId = createSession({\n title,\n summary,\n projectPath: sessionToSave.projectPath || undefined,\n rawData: sessionToSave.rawData,\n messages: sessionToSave.messages,\n });\n\n console.log(chalk.green(`Session saved with ID: ${sessionId.slice(0, 8)}`));\n\n // Generate and store embedding if ready\n if (embeddingsReady) {\n console.log(chalk.dim('Generating embedding...'));\n try {\n const embeddingText = createEmbeddingText(title, summary, sessionToSave.messages);\n const embedding = await getEmbedding(embeddingText);\n storeEmbedding(sessionId, embedding);\n console.log(chalk.green('Embedding stored for semantic search.'));\n } catch (err) {\n console.log(chalk.yellow('Failed to generate embedding. Semantic search may not work for this session.'));\n }\n }\n\n console.log(chalk.green('\\nSession saved successfully!'));\n}\n","import chalk from 'chalk';\nimport { listHumanSessions, listSessions } from '../db/sessions.js';\nimport { formatTimeAgo, shortId, truncate } from '../utils/format.js';\n\ninterface ListOptions {\n all?: boolean;\n}\n\nexport async function listCommand(options: ListOptions = {}): Promise<void> {\n // Use listHumanSessions by default, listSessions with --all flag\n const sessions = options.all ? listSessions() : listHumanSessions();\n\n if (sessions.length === 0) {\n console.log(chalk.yellow('No saved sessions.'));\n console.log(chalk.dim('Run: cmem save --latest'));\n return;\n }\n\n console.log(chalk.cyan(`Saved Sessions (${sessions.length})\\n`));\n\n // Table header\n console.log(\n chalk.dim(\n 'ID'.padEnd(10) +\n 'Title'.padEnd(40) +\n 'Msgs'.padEnd(6) +\n 'Updated'.padEnd(10) +\n 'Project'\n )\n );\n console.log(chalk.dim('─'.repeat(90)));\n\n for (const session of sessions) {\n const id = shortId(session.id);\n const title = truncate(session.title, 38);\n const msgs = String(session.messageCount).padStart(4);\n const updated = formatTimeAgo(session.updatedAt);\n const project = session.projectPath ? truncate(session.projectPath, 25) : chalk.dim('—');\n\n console.log(\n chalk.white(id.padEnd(10)) +\n title.padEnd(40) +\n chalk.dim(msgs.padEnd(6)) +\n chalk.dim(updated.padEnd(10)) +\n chalk.dim(project)\n );\n }\n\n console.log(chalk.dim('\\n─'.repeat(90)));\n console.log(chalk.dim('Use: cmem restore <id> to restore a session'));\n}\n","import chalk from 'chalk';\nimport { searchSessions } from '../db/vectors.js';\nimport { getEmbedding, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { formatTimeAgo, shortId, truncate } from '../utils/format.js';\n\nexport async function searchCommand(query: string): Promise<void> {\n console.log(chalk.cyan(`Searching for: \"${query}\"...\\n`));\n\n // Initialize embeddings (downloads model if needed)\n if (!isReady()) {\n console.log(chalk.dim('Initializing embedding model...'));\n try {\n await initializeEmbeddings((progress) => {\n if (progress.status === 'downloading' && progress.progress !== undefined) {\n process.stdout.write(`\\r${chalk.dim(`Downloading model... ${Math.round(progress.progress)}%`)}`);\n }\n });\n console.log(chalk.green('\\r✓ Model ready \\n'));\n } catch (err) {\n console.log(chalk.red('Failed to initialize embedding model.'));\n console.log(chalk.dim(String(err)));\n return;\n }\n }\n\n try {\n // Generate query embedding\n const queryEmbedding = await getEmbedding(query);\n\n // Search for similar sessions\n const results = searchSessions(queryEmbedding, 10);\n\n if (results.length === 0) {\n console.log(chalk.yellow('No matching sessions found.'));\n console.log(chalk.dim('Try a different search query or save more sessions.'));\n return;\n }\n\n console.log(chalk.green(`Found ${results.length} matching session(s)\\n`));\n\n // Table header\n console.log(\n chalk.dim(\n 'ID'.padEnd(10) +\n 'Title'.padEnd(40) +\n 'Msgs'.padEnd(6) +\n 'Updated'\n )\n );\n console.log(chalk.dim('─'.repeat(70)));\n\n for (const session of results) {\n const id = shortId(session.id);\n const title = truncate(session.title, 38);\n const msgs = String(session.messageCount).padStart(4);\n const updated = formatTimeAgo(session.updatedAt);\n\n console.log(\n chalk.white(id.padEnd(10)) +\n title.padEnd(40) +\n chalk.dim(msgs.padEnd(6)) +\n chalk.dim(updated)\n );\n\n // Show summary snippet\n if (session.summary) {\n console.log(chalk.dim(' ' + truncate(session.summary, 65)));\n }\n }\n\n console.log(chalk.dim('\\n─'.repeat(70)));\n console.log(chalk.dim('Use: cmem restore <id> to restore a session'));\n } catch (err) {\n console.log(chalk.red('Search failed.'));\n console.log(chalk.dim(String(err)));\n }\n}\n","import chalk from 'chalk';\nimport { getSession, getSessionMessages, listSessions } from '../db/sessions.js';\nimport { copyToClipboard } from '../utils/clipboard.js';\nimport { MAX_MESSAGES_FOR_CONTEXT } from '../utils/config.js';\n\ninterface RestoreOptions {\n copy?: boolean;\n format?: 'context' | 'json' | 'markdown';\n}\n\nexport async function restoreCommand(id: string, options: RestoreOptions): Promise<void> {\n // Support partial ID matching\n let session = getSession(id);\n\n if (!session) {\n // Try partial match\n const sessions = listSessions();\n const match = sessions.find(s => s.id.startsWith(id));\n if (match) {\n session = match;\n }\n }\n\n if (!session) {\n console.log(chalk.red(`Session not found: ${id}`));\n console.log(chalk.dim('Run: cmem list to see available sessions'));\n return;\n }\n\n const messages = getSessionMessages(session.id);\n const format = options.format || 'context';\n\n let output: string;\n\n switch (format) {\n case 'json':\n output = formatAsJson(session, messages);\n break;\n case 'markdown':\n output = formatAsMarkdown(session, messages);\n break;\n case 'context':\n default:\n output = formatAsContext(session, messages);\n break;\n }\n\n if (options.copy) {\n await copyToClipboard(output);\n console.log(chalk.green('Session context copied to clipboard!'));\n console.log(chalk.dim(`Session: ${session.title}`));\n console.log(chalk.dim(`Messages: ${messages.length}`));\n } else {\n console.log(output);\n }\n}\n\nfunction formatAsContext(\n session: { title: string; projectPath: string | null },\n messages: Array<{ role: string; content: string }>\n): string {\n const lines: string[] = [];\n\n lines.push('# Previous Session Context');\n lines.push('');\n lines.push(`**Session:** ${session.title}`);\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n }\n lines.push(`**Messages:** ${messages.length} total (showing last ${Math.min(messages.length, MAX_MESSAGES_FOR_CONTEXT)})`);\n lines.push('');\n lines.push('---');\n lines.push('');\n lines.push('## Conversation History');\n lines.push('');\n\n // Show last N messages\n const recentMessages = messages.slice(-MAX_MESSAGES_FOR_CONTEXT);\n\n for (const msg of recentMessages) {\n const roleLabel = msg.role === 'user' ? '**User:**' : '**Claude:**';\n lines.push(roleLabel);\n lines.push(msg.content);\n lines.push('');\n }\n\n lines.push('---');\n lines.push('');\n lines.push('*Continue this conversation in Claude Code*');\n\n return lines.join('\\n');\n}\n\nfunction formatAsMarkdown(\n session: { title: string; projectPath: string | null; summary: string | null },\n messages: Array<{ role: string; content: string; timestamp: string }>\n): string {\n const lines: string[] = [];\n\n lines.push(`# ${session.title}`);\n lines.push('');\n\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n lines.push('');\n }\n\n if (session.summary) {\n lines.push('## Summary');\n lines.push(session.summary);\n lines.push('');\n }\n\n lines.push('## Conversation');\n lines.push('');\n\n for (const msg of messages) {\n lines.push(`### ${msg.role === 'user' ? 'User' : 'Claude'}`);\n lines.push(`*${msg.timestamp}*`);\n lines.push('');\n lines.push(msg.content);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction formatAsJson(\n session: { id: string; title: string; projectPath: string | null; summary: string | null; createdAt: string; updatedAt: string },\n messages: Array<{ role: string; content: string; timestamp: string }>\n): string {\n return JSON.stringify(\n {\n session: {\n id: session.id,\n title: session.title,\n projectPath: session.projectPath,\n summary: session.summary,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt,\n },\n messages: messages.map(m => ({\n role: m.role,\n content: m.content,\n timestamp: m.timestamp,\n })),\n },\n null,\n 2\n );\n}\n","import clipboard from 'clipboardy';\n\n/**\n * Copy text to clipboard\n */\nexport async function copyToClipboard(text: string): Promise<void> {\n await clipboard.write(text);\n}\n\n/**\n * Read text from clipboard\n */\nexport async function readFromClipboard(): Promise<string> {\n return await clipboard.read();\n}\n","import chalk from 'chalk';\nimport { getSession, deleteSession, listSessions } from '../db/sessions.js';\nimport { shortId } from '../utils/format.js';\n\nexport async function deleteCommand(id: string): Promise<void> {\n // Support partial ID matching\n let session = getSession(id);\n\n if (!session) {\n // Try partial match\n const sessions = listSessions();\n const match = sessions.find(s => s.id.startsWith(id));\n if (match) {\n session = match;\n }\n }\n\n if (!session) {\n console.log(chalk.red(`Session not found: ${id}`));\n console.log(chalk.dim('Run: cmem list to see available sessions'));\n return;\n }\n\n const deleted = deleteSession(session.id);\n\n if (deleted) {\n console.log(chalk.green(`Deleted session: ${shortId(session.id)} - ${session.title}`));\n } else {\n console.log(chalk.red('Failed to delete session.'));\n }\n}\n","import chalk from 'chalk';\nimport { statSync, existsSync } from 'fs';\nimport { getStats } from '../db/sessions.js';\nimport { isModelCached } from '../embeddings/index.js';\nimport { DB_PATH, CMEM_DIR, EMBEDDING_MODEL, MODELS_DIR } from '../utils/config.js';\nimport { formatBytes, formatNumber } from '../utils/format.js';\n\nexport async function statsCommand(): Promise<void> {\n console.log(chalk.cyan('cmem Storage Statistics\\n'));\n\n // Database stats\n const stats = getStats();\n\n console.log(chalk.white('Database:'));\n console.log(` Sessions: ${formatNumber(stats.sessionCount)}`);\n console.log(` Messages: ${formatNumber(stats.messageCount)}`);\n console.log(` Embeddings: ${formatNumber(stats.embeddingCount)}`);\n\n // Storage size\n if (existsSync(DB_PATH)) {\n const dbStats = statSync(DB_PATH);\n console.log(` DB Size: ${formatBytes(dbStats.size)}`);\n }\n\n console.log(` Location: ${CMEM_DIR}`);\n\n // Embedding model status\n console.log('');\n console.log(chalk.white('Embeddings:'));\n\n const modelCached = isModelCached();\n if (modelCached) {\n console.log(` Model: ${chalk.green(EMBEDDING_MODEL)}`);\n console.log(` Location: ${MODELS_DIR}`);\n } else {\n console.log(` Model: ${chalk.yellow('Not downloaded')}`);\n console.log(chalk.dim(' Run cmem setup to download the embedding model'));\n }\n\n // Coverage\n console.log('');\n console.log(chalk.white('Coverage:'));\n const coveragePercent = stats.sessionCount > 0\n ? Math.round((stats.embeddingCount / stats.sessionCount) * 100)\n : 0;\n console.log(` Semantic: ${coveragePercent}% of sessions have embeddings`);\n\n if (coveragePercent < 100 && stats.sessionCount > 0) {\n console.log(chalk.dim(' Run cmem watch to generate missing embeddings'));\n }\n}\n","import chalk from 'chalk';\nimport chokidar from 'chokidar';\nimport { statSync, existsSync, readFileSync, readdirSync } from 'fs';\nimport { join, dirname, basename } from 'path';\nimport { CLAUDE_DIR } from '../utils/config.js';\nimport { parseSessionFile, generateSummary, ParsedMessage, extractSessionMetadata, isAutomatedByContent } from '../parser/index.js';\nimport {\n createSession,\n getSessionBySourceFile,\n updateSession,\n needsReembedding,\n updateEmbeddingState,\n getStats,\n} from '../db/sessions.js';\nimport { storeEmbedding } from '../db/vectors.js';\nimport { getEmbedding, createEmbeddingText, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { generateTitle } from '../utils/format.js';\n\n// Spinner animation frames\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nclass Spinner {\n private interval: NodeJS.Timeout | null = null;\n private frameIndex = 0;\n private message: string;\n\n constructor(message: string) {\n this.message = message;\n }\n\n start(): void {\n process.stdout.write(` ${spinnerFrames[0]} ${this.message}`);\n this.interval = setInterval(() => {\n this.frameIndex = (this.frameIndex + 1) % spinnerFrames.length;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message}`);\n }, 80);\n }\n\n update(message: string): void {\n this.message = message;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message} `);\n }\n\n succeed(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.green('✓')} ${message || this.message} `);\n }\n\n fail(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.red('✗')} ${message || this.message} `);\n }\n\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n}\n\ninterface SessionIndexEntry {\n sessionId: string;\n projectPath: string;\n}\n\ninterface WatchOptions {\n verbose?: boolean;\n embedThreshold?: number;\n}\n\n// Debounce map to prevent rapid re-processing\nconst processingDebounce = new Map<string, NodeJS.Timeout>();\nconst DEBOUNCE_MS = 2000; // Wait 2 seconds after last change before processing\n\nexport async function watchCommand(options: WatchOptions): Promise<void> {\n const verbose = options.verbose ?? false;\n const embedThreshold = options.embedThreshold ?? 500;\n\n console.log(chalk.cyan('🔍 cmem watch - Monitoring Claude Code sessions\\n'));\n\n // Initialize embeddings (downloads model if needed)\n const modelSpinner = new Spinner('Initializing embedding model...');\n modelSpinner.start();\n\n try {\n await initializeEmbeddings((progress) => {\n if (progress.status === 'downloading' && progress.progress !== undefined) {\n const fileName = progress.file ? progress.file.split('/').pop() : 'model';\n modelSpinner.update(`Downloading ${fileName}... ${Math.round(progress.progress)}%`);\n } else if (progress.status === 'loading') {\n modelSpinner.update('Loading model...');\n }\n });\n modelSpinner.succeed('Embedding model ready');\n } catch (err) {\n modelSpinner.fail('Could not initialize embeddings');\n console.log(chalk.yellow(' Sessions will be saved but not vectorized.\\n'));\n }\n\n const embeddingsReady = isReady();\n console.log('');\n\n // First, do an initial scan to find and index all existing sessions\n const scanSpinner = new Spinner('Scanning for existing sessions...');\n scanSpinner.start();\n\n const existingFiles = findAllSessionFiles(CLAUDE_DIR);\n const totalFiles = existingFiles.length;\n\n // Get current stats to see how many are already indexed\n const statsBefore = getStats();\n const alreadyIndexed = statsBefore.sessionCount;\n const needsIndexing = totalFiles - alreadyIndexed;\n\n if (totalFiles === 0) {\n scanSpinner.succeed('No Claude Code sessions found yet');\n } else if (needsIndexing <= 0) {\n scanSpinner.succeed(`Found ${totalFiles} sessions (all indexed)`);\n } else {\n scanSpinner.update(`Found ${totalFiles} sessions, indexing ${needsIndexing} new...`);\n\n let processed = 0;\n let newlyIndexed = 0;\n\n for (const filePath of existingFiles) {\n processed++;\n // Force metadata update during initial scan to migrate existing sessions\n const wasNew = await processSessionFile(filePath, embeddingsReady, embedThreshold, false, true);\n if (wasNew) newlyIndexed++;\n\n // Update spinner with progress\n const percent = Math.round((processed / totalFiles) * 100);\n scanSpinner.update(`Indexing sessions... ${percent}% (${processed}/${totalFiles})`);\n }\n\n scanSpinner.succeed(`Indexed ${totalFiles} sessions (${newlyIndexed} new, ${totalFiles - newlyIndexed} updated)`);\n }\n\n console.log('');\n console.log(chalk.dim(`Watching: ${CLAUDE_DIR}`));\n console.log(chalk.dim(`Embed threshold: ${embedThreshold} chars\\n`));\n\n // Now watch for changes (ignore initial since we already processed)\n const watcher = chokidar.watch(CLAUDE_DIR, {\n persistent: true,\n ignoreInitial: true, // We already processed existing files above\n depth: 10,\n awaitWriteFinish: {\n stabilityThreshold: 1000,\n pollInterval: 100,\n },\n });\n\n watcher.on('add', (filePath) => {\n if (!filePath.endsWith('.jsonl')) return;\n if (filePath.includes('/subagents/')) {\n if (verbose) console.log(chalk.dim(`[skip agent] ${filePath}`));\n return;\n }\n if (verbose) console.log(chalk.dim(`[new] ${filePath}`));\n debouncedProcess(filePath, embeddingsReady, embedThreshold, verbose);\n });\n\n watcher.on('change', (filePath) => {\n if (!filePath.endsWith('.jsonl')) return;\n if (filePath.includes('/subagents/')) {\n if (verbose) console.log(chalk.dim(`[skip agent] ${filePath}`));\n return;\n }\n if (verbose) console.log(chalk.dim(`[changed] ${filePath}`));\n debouncedProcess(filePath, embeddingsReady, embedThreshold, verbose);\n });\n\n watcher.on('error', (error) => {\n console.error(chalk.red('Watcher error:'), error);\n });\n\n watcher.on('ready', () => {\n console.log(chalk.green('✓ Watching for session changes...'));\n console.log(chalk.dim('Press Ctrl+C to stop\\n'));\n });\n\n process.on('SIGINT', () => {\n console.log(chalk.dim('\\nShutting down watcher...'));\n watcher.close();\n process.exit(0);\n });\n\n process.on('SIGTERM', () => {\n watcher.close();\n process.exit(0);\n });\n}\n\n/**\n * Find all .jsonl session files in the Claude directory\n */\nfunction findAllSessionFiles(dir: string): string[] {\n const files: string[] = [];\n\n if (!existsSync(dir)) return files;\n\n function scanDir(currentDir: string, depth: number = 0): void {\n if (depth > 10) return; // Max depth\n\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(currentDir, entry.name);\n\n if (entry.isDirectory()) {\n // Skip subagents folder\n if (entry.name === 'subagents') continue;\n scanDir(fullPath, depth + 1);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n files.push(fullPath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n scanDir(dir);\n return files;\n}\n\nfunction debouncedProcess(\n filePath: string,\n embeddingsReady: boolean,\n embedThreshold: number,\n verbose: boolean\n): void {\n // Clear any existing debounce timer for this file\n const existing = processingDebounce.get(filePath);\n if (existing) {\n clearTimeout(existing);\n }\n\n // Set new debounce timer\n const timer = setTimeout(async () => {\n processingDebounce.delete(filePath);\n await processSessionFile(filePath, embeddingsReady, embedThreshold, verbose);\n }, DEBOUNCE_MS);\n\n processingDebounce.set(filePath, timer);\n}\n\nasync function processSessionFile(\n filePath: string,\n embeddingsReady: boolean,\n embedThreshold: number,\n verbose: boolean,\n forceMetadataUpdate = false\n): Promise<boolean> {\n try {\n // Parse the session file\n const messages = parseSessionFile(filePath);\n\n if (messages.length === 0) {\n if (verbose) console.log(chalk.dim(` Skipping empty session: ${filePath}`));\n return false;\n }\n\n // Get file stats\n const stats = statSync(filePath);\n const fileMtime = stats.mtime.toISOString();\n\n // Check if we already have this session\n const existingSession = getSessionBySourceFile(filePath);\n\n // Get session ID from filename\n const sessionId_from_file = basename(filePath, '.jsonl');\n\n // Load agent messages for this session (for embeddings)\n const agentMessages = loadSubagentMessages(dirname(filePath), sessionId_from_file);\n const allMessages = [...messages, ...agentMessages];\n\n // Calculate content length for embedding decisions (including agent messages)\n const contentLength = allMessages.reduce((sum, m) => sum + m.content.length, 0);\n\n // Generate title from first user message\n const firstUserMsg = messages.find(m => m.role === 'user');\n const title = firstUserMsg ? generateTitle(firstUserMsg.content) : 'Untitled Session';\n\n // Generate summary\n const summary = generateSummary(messages);\n\n // Build raw data for storage\n const rawData = JSON.stringify({ filePath, messages, mtime: fileMtime });\n\n // Get project path from sessions-index.json\n const projectPath = getProjectPathFromIndex(filePath, sessionId_from_file);\n\n // Extract metadata (isSidechain, agentId, isMeta) from JSONL\n const metadata = extractSessionMetadata(filePath);\n // Mark as automated if: JSONL metadata says so, OR title matches automated patterns\n const isAutomated = metadata.isSidechain || metadata.isMeta || isAutomatedByContent(title);\n\n let sessionId: string;\n let isNew = false;\n\n if (existingSession) {\n // Update existing session\n sessionId = existingSession.id;\n\n // Update metadata if it needs to be set (for sessions created before metadata tracking)\n // forceMetadataUpdate is true during initial scan to migrate existing sessions\n const needsMetadataUpdate = forceMetadataUpdate ||\n (!existingSession.isSidechain && !existingSession.isAutomated && isAutomated);\n\n // Update if content has changed OR metadata needs updating OR projectPath is missing\n const needsProjectPathUpdate = !existingSession.projectPath && projectPath;\n if (existingSession.messageCount !== messages.length || needsMetadataUpdate || needsProjectPathUpdate) {\n updateSession(sessionId, {\n title,\n summary,\n rawData,\n messages,\n isSidechain: metadata.isSidechain,\n isAutomated,\n projectPath: projectPath || undefined,\n });\n\n if (verbose) {\n const automatedTag = isAutomated ? chalk.dim(' [auto]') : '';\n console.log(chalk.blue(`↻ Updated: ${title} (${messages.length} msgs)${automatedTag}`));\n }\n }\n } else {\n // Create new session\n isNew = true;\n sessionId = createSession({\n title,\n summary,\n projectPath,\n sourceFile: filePath,\n rawData,\n messages,\n isSidechain: metadata.isSidechain,\n isAutomated,\n });\n\n if (verbose) {\n const automatedTag = isAutomated ? chalk.dim(' [auto]') : '';\n console.log(chalk.green(`✓ Saved: ${title} (${messages.length} msgs)${automatedTag}`));\n }\n }\n\n // Handle embedding (include agent messages for better search)\n if (embeddingsReady) {\n const shouldEmbed = needsReembedding(sessionId, contentLength, embedThreshold);\n\n if (shouldEmbed) {\n try {\n // Use all messages including agents for richer embeddings\n const embeddingText = createEmbeddingText(title, summary, allMessages);\n const embedding = await getEmbedding(embeddingText);\n storeEmbedding(sessionId, embedding);\n updateEmbeddingState(sessionId, contentLength, fileMtime);\n\n if (verbose) {\n const agentCount = agentMessages.length;\n const agentInfo = agentCount > 0 ? ` (+${agentCount} agent msgs)` : '';\n console.log(chalk.dim(` Embedded: ${title}${agentInfo}`));\n }\n } catch (err) {\n if (verbose) {\n console.log(chalk.yellow(` Failed to embed: ${title}`));\n console.log(chalk.dim(` ${err}`));\n }\n }\n }\n }\n\n return isNew;\n } catch (err) {\n if (verbose) console.log(chalk.red(`Error processing ${filePath}:`), err);\n return false;\n }\n}\n\n/**\n * Load messages from all subagent sessions for a parent session\n */\nfunction loadSubagentMessages(projectDirPath: string, parentSessionId: string): ParsedMessage[] {\n const subagentsDir = join(projectDirPath, parentSessionId, 'subagents');\n if (!existsSync(subagentsDir)) return [];\n\n const messages: ParsedMessage[] = [];\n\n try {\n const agentFiles = readdirSync(subagentsDir).filter(f => f.endsWith('.jsonl'));\n for (const agentFile of agentFiles) {\n const agentPath = join(subagentsDir, agentFile);\n const agentMessages = parseSessionFile(agentPath);\n messages.push(...agentMessages);\n }\n } catch {\n // Ignore errors reading subagent files\n }\n\n return messages;\n}\n\n/**\n * Get project path from sessions-index.json\n */\nfunction getProjectPathFromIndex(filePath: string, sessionId: string): string | null {\n const projectDir = dirname(filePath);\n const indexPath = join(projectDir, 'sessions-index.json');\n\n if (!existsSync(indexPath)) return null;\n\n try {\n const content = readFileSync(indexPath, 'utf-8');\n const index = JSON.parse(content) as { entries: SessionIndexEntry[] };\n const entry = index.entries.find(e => e.sessionId === sessionId);\n return entry?.projectPath || null;\n } catch {\n return null;\n }\n}\n","import chalk from 'chalk';\nimport { startMcpServer } from '../mcp/server.js';\n\nexport async function mcpCommand(): Promise<void> {\n // When running as MCP server, we don't want to log to stdout\n // as it's used for JSON-RPC communication\n // Instead, log to stderr for debugging\n console.error(chalk.cyan('Starting cmem MCP server...'));\n\n try {\n await startMcpServer();\n } catch (err) {\n console.error(chalk.red('MCP server error:'), err);\n process.exit(1);\n }\n}\n","import { 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 {\n listSessions,\n getSession,\n getSessionMessages,\n getSessionBySourceFile,\n getSessionByIdPrefix,\n} from '../db/sessions.js';\nimport { searchSessions } from '../db/vectors.js';\nimport { getEmbedding, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { formatTimeAgo, truncate } from '../utils/format.js';\nimport { runClaudePrompt, isClaudeCliAvailable } from '../utils/claude-cli.js';\n\n/**\n * Create and configure the MCP server\n */\nexport function createMcpServer(): Server {\n const server = new Server(\n {\n name: 'cmem',\n version: '0.1.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n // List available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: 'search_sessions',\n description:\n 'Semantic search across all saved Claude Code conversation sessions. Use this to find past conversations about specific topics, projects, or problems. Returns matching sessions ranked by relevance.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description:\n 'Natural language search query. Examples: \"React hooks discussion\", \"database migration\", \"authentication implementation\"',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 5)',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'list_sessions',\n description:\n 'List all saved Claude Code conversation sessions, ordered by most recently updated. Use this to browse available sessions or find recent conversations.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'number',\n description: 'Maximum number of sessions to return (default: 10)',\n },\n },\n },\n },\n {\n name: 'get_session',\n description:\n 'Get detailed information about a specific conversation session, including its full message history. Use this after finding a session via search or list.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID to retrieve',\n },\n includeMessages: {\n type: 'boolean',\n description: 'Whether to include the full message history (default: true)',\n },\n messageLimit: {\n type: 'number',\n description: 'Maximum number of messages to include (default: 50, from most recent)',\n },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'get_session_context',\n description:\n 'Get a formatted context summary from a past session that can be used to continue or reference that conversation. Returns key information and recent messages in a readable format.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID to get context from',\n },\n messageCount: {\n type: 'number',\n description: 'Number of recent messages to include (default: 10)',\n },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'search_and_summarize',\n description:\n 'Search past Claude Code sessions and get an AI-generated summary tailored to your specific question. This spawns a separate Claude instance to read and synthesize the relevant sessions, keeping your main context clean. Use this when you need insights from past conversations.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description:\n 'Your question or topic to search for. Examples: \"What did we decide about the database schema?\", \"How did we implement authentication?\", \"What was the bug fix for the login issue?\"',\n },\n sessionLimit: {\n type: 'number',\n description: 'Maximum number of sessions to analyze (default: 3)',\n },\n model: {\n type: 'string',\n enum: ['haiku', 'sonnet', 'opus'],\n description: 'Model to use for summarization (default: haiku for speed)',\n },\n },\n required: ['query'],\n },\n },\n ],\n };\n });\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n switch (name) {\n case 'search_sessions':\n return await handleSearchSessions(args as { query: string; limit?: number });\n\n case 'list_sessions':\n return await handleListSessions(args as { limit?: number });\n\n case 'get_session':\n return await handleGetSession(\n args as { sessionId: string; includeMessages?: boolean; messageLimit?: number }\n );\n\n case 'get_session_context':\n return await handleGetSessionContext(\n args as { sessionId: string; messageCount?: number }\n );\n\n case 'search_and_summarize':\n return await handleSearchAndSummarize(\n args as { query: string; sessionLimit?: number; model?: 'haiku' | 'sonnet' | 'opus' }\n );\n\n default:\n return {\n content: [{ type: 'text', text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${String(error)}` }],\n isError: true,\n };\n }\n });\n\n return server;\n}\n\nasync function handleSearchSessions(args: { query: string; limit?: number }) {\n const { query, limit = 5 } = args;\n\n // Initialize embeddings if needed\n if (!isReady()) {\n try {\n await initializeEmbeddings();\n } catch {\n // Fall back to simple text search\n const allSessions = listSessions(100);\n const queryLower = query.toLowerCase();\n const filtered = allSessions\n .filter(\n (s) =>\n s.title.toLowerCase().includes(queryLower) ||\n (s.summary && s.summary.toLowerCase().includes(queryLower))\n )\n .slice(0, limit);\n\n return {\n content: [\n {\n type: 'text',\n text: formatSessionList(filtered, `Text search results for \"${query}\" (embeddings unavailable)`),\n },\n ],\n };\n }\n }\n\n // Semantic search\n const queryEmbedding = await getEmbedding(query);\n const results = searchSessions(queryEmbedding, limit);\n\n return {\n content: [\n {\n type: 'text',\n text: formatSessionList(results, `Semantic search results for \"${query}\"`),\n },\n ],\n };\n}\n\nasync function handleListSessions(args: { limit?: number }) {\n const { limit = 10 } = args;\n const sessions = listSessions(limit);\n\n return {\n content: [\n {\n type: 'text',\n text: formatSessionList(sessions, 'Recent sessions'),\n },\n ],\n };\n}\n\nasync function handleGetSession(args: {\n sessionId: string;\n includeMessages?: boolean;\n messageLimit?: number;\n}) {\n const { sessionId, includeMessages = true, messageLimit = 50 } = args;\n\n // Support partial ID matching - try exact match first, then prefix match\n let session = getSession(sessionId) || getSessionByIdPrefix(sessionId);\n\n if (!session) {\n return {\n content: [{ type: 'text', text: `Session not found: ${sessionId}` }],\n isError: true,\n };\n }\n\n const lines: string[] = [\n `# Session: ${session.title}`,\n '',\n `**ID:** ${session.id}`,\n `**Created:** ${session.createdAt}`,\n `**Updated:** ${session.updatedAt} (${formatTimeAgo(session.updatedAt)})`,\n `**Messages:** ${session.messageCount}`,\n ];\n\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n }\n\n if (session.summary) {\n lines.push('', '## Summary', session.summary);\n }\n\n if (includeMessages) {\n const messages = getSessionMessages(session.id);\n const recentMessages = messages.slice(-messageLimit);\n\n lines.push('', '## Messages', '');\n\n for (const msg of recentMessages) {\n lines.push(`### ${msg.role === 'user' ? 'User' : 'Assistant'}`);\n lines.push(msg.content);\n lines.push('');\n }\n\n if (messages.length > messageLimit) {\n lines.push(`_...${messages.length - messageLimit} earlier messages omitted_`);\n }\n }\n\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n };\n}\n\nasync function handleGetSessionContext(args: { sessionId: string; messageCount?: number }) {\n const { sessionId, messageCount = 10 } = args;\n\n // Support partial ID matching - try exact match first, then prefix match\n let session = getSession(sessionId) || getSessionByIdPrefix(sessionId);\n\n if (!session) {\n return {\n content: [{ type: 'text', text: `Session not found: ${sessionId}` }],\n isError: true,\n };\n }\n\n const messages = getSessionMessages(session.id);\n const recentMessages = messages.slice(-messageCount);\n\n const lines: string[] = [\n '# Context from Previous Session',\n '',\n `**Topic:** ${session.title}`,\n ];\n\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n }\n\n if (session.summary) {\n lines.push('', '## Summary', session.summary);\n }\n\n lines.push(\n '',\n '## Recent Conversation',\n `_Last ${recentMessages.length} of ${messages.length} messages_`,\n ''\n );\n\n for (const msg of recentMessages) {\n const role = msg.role === 'user' ? '**User:**' : '**Assistant:**';\n lines.push(role);\n // Truncate very long messages in context\n lines.push(truncate(msg.content, 2000));\n lines.push('');\n }\n\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n };\n}\n\nasync function handleSearchAndSummarize(args: {\n query: string;\n sessionLimit?: number;\n model?: 'haiku' | 'sonnet' | 'opus';\n}) {\n const { query, sessionLimit = 3, model = 'haiku' } = args;\n\n // Check if Claude CLI is available\n if (!isClaudeCliAvailable()) {\n return {\n content: [\n {\n type: 'text',\n text: 'Claude CLI not found. This tool requires Claude Code CLI to be installed.',\n },\n ],\n isError: true,\n };\n }\n\n // Initialize embeddings if needed\n if (!isReady()) {\n try {\n await initializeEmbeddings();\n } catch {\n return {\n content: [\n {\n type: 'text',\n text: 'Embedding model not available. Please run `cmem setup` first.',\n },\n ],\n isError: true,\n };\n }\n }\n\n // Semantic search for relevant sessions\n const queryEmbedding = await getEmbedding(query);\n const sessions = searchSessions(queryEmbedding, sessionLimit);\n\n if (sessions.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: `No relevant sessions found for: \"${query}\"`,\n },\n ],\n };\n }\n\n // Gather content from matching sessions\n const sessionContents: string[] = [];\n for (const session of sessions) {\n const messages = getSessionMessages(session.id);\n if (messages.length === 0) continue;\n\n // Format session content\n const sessionText = [\n `## Session: ${session.title}`,\n `Project: ${session.projectPath || 'Unknown'}`,\n `Date: ${session.updatedAt}`,\n '',\n ...messages.slice(-20).map((m) => `**${m.role}:** ${truncate(m.content, 1500)}`),\n ].join('\\n');\n\n sessionContents.push(sessionText);\n }\n\n if (sessionContents.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: `Found ${sessions.length} sessions but they appear to be empty.`,\n },\n ],\n };\n }\n\n // Build prompt for Claude to summarize\n const prompt = `You are analyzing past Claude Code conversation sessions to answer a user's question.\n\n<user_question>\n${query}\n</user_question>\n\n<past_sessions>\n${sessionContents.join('\\n\\n---\\n\\n')}\n</past_sessions>\n\nBased on the past sessions above, provide a concise and helpful answer to the user's question. Focus on:\n1. Directly answering their question with specific details from the conversations\n2. Mentioning which session(s) the information came from\n3. Highlighting any relevant decisions, code snippets, or conclusions\n\nIf the sessions don't contain relevant information to answer the question, say so clearly.\n\nKeep your response concise but complete.`;\n\n // Spawn Claude CLI to generate the summary\n const response = await runClaudePrompt(prompt, { model });\n\n if (!response.success) {\n return {\n content: [\n {\n type: 'text',\n text: `Error generating summary: ${response.error || 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n\n // Format the response with metadata\n const resultLines = [\n response.content,\n '',\n '---',\n `*Analyzed ${sessions.length} session(s) | Model: ${model}${response.durationMs ? ` | ${(response.durationMs / 1000).toFixed(1)}s` : ''}${response.outputTokens ? ` | ${response.outputTokens} tokens` : ''}*`,\n ];\n\n return {\n content: [{ type: 'text', text: resultLines.join('\\n') }],\n };\n}\n\nfunction formatSessionList(\n sessions: Array<{\n id: string;\n title: string;\n summary: string | null;\n messageCount: number;\n updatedAt: string;\n projectPath: string | null;\n }>,\n header: string\n): string {\n if (sessions.length === 0) {\n return `${header}\\n\\nNo sessions found.`;\n }\n\n const lines: string[] = [header, ''];\n\n for (const session of sessions) {\n lines.push(`### ${session.title}`);\n lines.push(`- **ID:** \\`${session.id.slice(0, 8)}\\` (use this to get full session)`);\n lines.push(`- **Messages:** ${session.messageCount}`);\n lines.push(`- **Updated:** ${formatTimeAgo(session.updatedAt)}`);\n if (session.projectPath) {\n lines.push(`- **Project:** ${session.projectPath}`);\n }\n if (session.summary) {\n lines.push(`- **Summary:** ${truncate(session.summary, 150)}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Start the MCP server\n */\nexport async function startMcpServer(): Promise<void> {\n const server = createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","import { spawn } from 'child_process';\nimport { execSync } from 'child_process';\n\nexport interface ClaudeResponse {\n success: boolean;\n content: string;\n error?: string;\n inputTokens?: number;\n outputTokens?: number;\n costUsd?: number;\n durationMs?: number;\n}\n\n/**\n * Get the path to the Claude CLI\n */\nfunction getClaudePath(): string | null {\n try {\n const result = execSync('which claude', { encoding: 'utf-8' }).trim();\n return result || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Parse a single line of NDJSON from Claude's stream-json output\n */\ninterface ParsedChunk {\n type: 'text' | 'done' | 'error' | 'skip';\n content?: string;\n inputTokens?: number;\n outputTokens?: number;\n costUsd?: number;\n durationMs?: number;\n}\n\nfunction parseStreamJsonLine(line: string): ParsedChunk | null {\n if (!line.trim()) return null;\n\n try {\n const data = JSON.parse(line);\n\n if (data.type === 'assistant') {\n // Assistant message with content blocks\n if (data.message?.content && Array.isArray(data.message.content)) {\n const textBlocks: string[] = [];\n\n for (const block of data.message.content) {\n if (block.type === 'text' && block.text) {\n textBlocks.push(block.text);\n }\n }\n\n if (textBlocks.length > 0) {\n return { type: 'text', content: textBlocks.join('\\n') };\n }\n }\n } else if (data.type === 'content_block_delta') {\n // Streaming text delta\n if (data.delta?.type === 'text_delta' && data.delta.text) {\n return { type: 'text', content: data.delta.text };\n }\n } else if (data.type === 'result') {\n // Final result\n if (data.is_error) {\n return { type: 'error', content: data.result || 'Unknown error' };\n }\n const usage = data.usage || {};\n const inputTokens = (usage.input_tokens || 0) + (usage.cache_read_input_tokens || 0);\n const outputTokens = usage.output_tokens || 0;\n return {\n type: 'done',\n inputTokens,\n outputTokens,\n costUsd: data.total_cost_usd,\n durationMs: data.duration_ms,\n };\n } else if (data.type === 'error') {\n return {\n type: 'error',\n content: data.error?.message || JSON.stringify(data.error) || 'Unknown error',\n };\n }\n\n // Skip other message types (system, message_start, etc.)\n return { type: 'skip' };\n } catch {\n return null;\n }\n}\n\n/**\n * Run a prompt through Claude CLI and return the response\n * Uses print mode (-p) with stream-json output for structured responses\n */\nexport async function runClaudePrompt(\n prompt: string,\n options: {\n model?: 'opus' | 'sonnet' | 'haiku';\n maxTokens?: number;\n } = {}\n): Promise<ClaudeResponse> {\n const claudePath = getClaudePath();\n if (!claudePath) {\n return {\n success: false,\n content: '',\n error: 'Claude CLI not found. Please install Claude Code CLI.',\n };\n }\n\n const { model = 'haiku' } = options;\n\n const args = [\n '-p', prompt,\n '--output-format', 'stream-json',\n '--verbose', // Required when using stream-json with -p\n '--model', model,\n '--permission-mode', 'plan', // Read-only, no tools needed for summarization\n ];\n\n return new Promise((resolve) => {\n const childProcess = spawn(claudePath, args, {\n env: {\n ...process.env,\n CI: 'true', // Prevent interactive prompts\n },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Close stdin since we're using -p flag\n childProcess.stdin?.end();\n\n let buffer = '';\n const textChunks: string[] = [];\n let finalResult: ParsedChunk | null = null;\n let errorContent = '';\n\n childProcess.stdout?.on('data', (data: Buffer) => {\n buffer += data.toString();\n\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.trim()) continue;\n\n const chunk = parseStreamJsonLine(line);\n if (chunk) {\n if (chunk.type === 'text' && chunk.content) {\n textChunks.push(chunk.content);\n } else if (chunk.type === 'done') {\n finalResult = chunk;\n } else if (chunk.type === 'error' && chunk.content) {\n errorContent = chunk.content;\n }\n }\n }\n });\n\n childProcess.stderr?.on('data', (data: Buffer) => {\n const text = data.toString().toLowerCase();\n if (text.includes('error') || text.includes('failed')) {\n errorContent = data.toString().trim();\n }\n });\n\n childProcess.on('close', (code) => {\n // Process remaining buffer\n if (buffer.trim()) {\n const chunk = parseStreamJsonLine(buffer);\n if (chunk) {\n if (chunk.type === 'text' && chunk.content) {\n textChunks.push(chunk.content);\n } else if (chunk.type === 'done') {\n finalResult = chunk;\n } else if (chunk.type === 'error' && chunk.content) {\n errorContent = chunk.content;\n }\n }\n }\n\n const content = textChunks.join('');\n\n if (errorContent && !content) {\n resolve({\n success: false,\n content: '',\n error: errorContent,\n });\n } else {\n resolve({\n success: code === 0 && content.length > 0,\n content,\n error: errorContent || undefined,\n inputTokens: finalResult?.inputTokens,\n outputTokens: finalResult?.outputTokens,\n costUsd: finalResult?.costUsd,\n durationMs: finalResult?.durationMs,\n });\n }\n });\n\n childProcess.on('error', (err) => {\n resolve({\n success: false,\n content: '',\n error: err.message,\n });\n });\n\n // Timeout after 60 seconds\n setTimeout(() => {\n childProcess.kill('SIGTERM');\n resolve({\n success: false,\n content: textChunks.join(''),\n error: 'Request timed out after 60 seconds',\n });\n }, 60000);\n });\n}\n\n/**\n * Check if Claude CLI is available\n */\nexport function isClaudeCliAvailable(): boolean {\n return getClaudePath() !== null;\n}\n","import chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from 'fs';\nimport { homedir } from 'os';\nimport { join, dirname, basename } from 'path';\nimport { fileURLToPath } from 'url';\nimport { createInterface } from 'readline';\nimport { initializeEmbeddings, isModelCached, isReady, getEmbedding, createEmbeddingText, type InitProgress } from '../embeddings/index.js';\nimport { EMBEDDING_MODEL, CLAUDE_DIR } from '../utils/config.js';\nimport { parseSessionFile, generateSummary } from '../parser/index.js';\nimport { createSession, getSessionBySourceFile, needsReembedding, updateEmbeddingState, getStats } from '../db/sessions.js';\nimport { storeEmbedding } from '../db/vectors.js';\nimport { generateTitle } from '../utils/format.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst CLAUDE_JSON_PATH = join(homedir(), '.claude.json');\nconst CLAUDE_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json');\nconst CMEM_DIR = join(homedir(), '.cmem');\nconst SETUP_MARKER = join(CMEM_DIR, '.setup-complete');\n\ninterface ClaudeJson {\n mcpServers?: Record<string, { type?: string; command: string; args?: string[] }>;\n [key: string]: unknown;\n}\n\ninterface ClaudeSettings {\n permissions?: {\n allow?: string[];\n deny?: string[];\n };\n [key: string]: unknown;\n}\n\n// cmem MCP tool permissions\nconst CMEM_PERMISSIONS = [\n 'mcp__cmem__search_sessions',\n 'mcp__cmem__list_sessions',\n 'mcp__cmem__get_session',\n 'mcp__cmem__get_session_context',\n 'mcp__cmem__search_and_summarize',\n];\n\n// Spinner animation frames\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nclass Spinner {\n private interval: NodeJS.Timeout | null = null;\n private frameIndex = 0;\n private message: string;\n\n constructor(message: string) {\n this.message = message;\n }\n\n start(): void {\n process.stdout.write(` ${spinnerFrames[0]} ${this.message}`);\n this.interval = setInterval(() => {\n this.frameIndex = (this.frameIndex + 1) % spinnerFrames.length;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message}`);\n }, 80);\n }\n\n update(message: string): void {\n this.message = message;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message} `);\n }\n\n succeed(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.green('✓')} ${message || this.message} `);\n }\n\n fail(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.red('✗')} ${message || this.message} `);\n }\n\n warn(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.yellow('!')} ${message || this.message} `);\n }\n\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n}\n\n// Beautiful ASCII art banner\nfunction printBanner(version: string): void {\n const magenta = chalk.magenta;\n const cyan = chalk.cyan;\n const dim = chalk.dim;\n\n console.log('');\n console.log(magenta(' ██████╗ ███╗ ███╗ ███████╗ ███╗ ███╗'));\n console.log(magenta(' ██╔════╝ ████╗ ████║ ██╔════╝ ████╗ ████║'));\n console.log(magenta(' ██║ ██╔████╔██║ █████╗ ██╔████╔██║'));\n console.log(magenta(' ██║ ██║╚██╔╝██║ ██╔══╝ ██║╚██╔╝██║'));\n console.log(magenta(' ╚██████╗ ██║ ╚═╝ ██║ ███████╗ ██║ ╚═╝ ██║'));\n console.log(magenta(' ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝'));\n console.log('');\n console.log(cyan(` cmem v${version}`));\n console.log(dim(' Persistent memory & semantic search for Claude Code'));\n console.log(dim(' Created by Colby McHenry'));\n console.log('');\n}\n\nasync function promptChoice(question: string, options: string[], defaultChoice = 1): Promise<number> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n // Print options\n options.forEach((opt, i) => {\n console.log(chalk.dim(` ${i + 1}) ${opt}`));\n });\n console.log('');\n\n return new Promise((resolve) => {\n rl.question(chalk.white(` Choice [${defaultChoice}]: `), (answer) => {\n rl.close();\n const num = parseInt(answer.trim(), 10);\n if (isNaN(num) || num < 1 || num > options.length) {\n resolve(defaultChoice);\n } else {\n resolve(num);\n }\n });\n });\n}\n\nasync function promptYesNo(question: string, defaultYes = true): Promise<boolean> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const hint = defaultYes ? '[Y/n]' : '[y/N]';\n\n return new Promise((resolve) => {\n rl.question(chalk.white(` ${question} ${chalk.dim(hint)} `), (answer) => {\n rl.close();\n const normalized = answer.toLowerCase().trim();\n if (normalized === '') {\n resolve(defaultYes);\n } else {\n resolve(normalized === 'y' || normalized === 'yes');\n }\n });\n });\n}\n\nfunction isRunningViaNpx(): boolean {\n const execPath = process.argv[1] || '';\n return execPath.includes('_npx') || execPath.includes('.npm/_cacache');\n}\n\nfunction isGloballyInstalled(): boolean {\n try {\n const result = execSync('which cmem 2>/dev/null || where cmem 2>/dev/null', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n return result.length > 0 && !result.includes('_npx');\n } catch {\n return false;\n }\n}\n\nfunction getCmemVersion(): string {\n try {\n // From dist/cli.js, package.json is one level up\n const packagePath = join(__dirname, '..', 'package.json');\n if (existsSync(packagePath)) {\n const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));\n return pkg.version || '0.1.0';\n }\n } catch {\n // Ignore\n }\n return '0.1.0';\n}\n\nfunction getInstalledVersion(): string | null {\n try {\n const result = execSync('cmem --version 2>/dev/null', {\n encoding: 'utf-8',\n }).trim();\n return result;\n } catch {\n return null;\n }\n}\n\nexport async function setupCommand(): Promise<void> {\n const currentVersion = getCmemVersion();\n const installedVersion = getInstalledVersion();\n const isGlobal = isGloballyInstalled();\n const isNpx = isRunningViaNpx();\n\n // Print beautiful banner\n printBanner(currentVersion);\n\n // Step 1: Global installation\n if (!isGlobal || isNpx) {\n console.log(chalk.yellow(' Install cmem globally?'));\n console.log(chalk.dim(' Makes the `cmem` command available everywhere\\n'));\n\n const choice = await promptChoice('', [\n 'Yes - install globally via npm',\n 'No - I\\'ll use npx each time',\n ], 1);\n\n if (choice === 1) {\n console.log(chalk.dim('\\n Installing @colbymchenry/cmem globally...\\n'));\n try {\n execSync('npm install -g @colbymchenry/cmem', { stdio: 'inherit' });\n console.log(chalk.green('\\n ✓ Installed globally\\n'));\n } catch {\n console.log(chalk.red('\\n ✗ Failed to install. Try: sudo npm install -g @colbymchenry/cmem\\n'));\n }\n } else {\n console.log(chalk.dim('\\n Skipped. Use `npx @colbymchenry/cmem` to run.\\n'));\n }\n } else if (installedVersion && installedVersion !== currentVersion) {\n console.log(chalk.yellow(` Update available: ${installedVersion} → ${currentVersion}`));\n\n const shouldUpdate = await promptYesNo('Update to latest version?');\n\n if (shouldUpdate) {\n console.log(chalk.dim('\\n Updating @colbymchenry/cmem...\\n'));\n try {\n execSync('npm install -g @colbymchenry/cmem', { stdio: 'inherit' });\n console.log(chalk.green('\\n ✓ Updated\\n'));\n } catch {\n console.log(chalk.red('\\n ✗ Failed to update\\n'));\n }\n } else {\n console.log('');\n }\n } else {\n console.log(chalk.green(' ✓ cmem is installed globally\\n'));\n }\n\n // Step 2: Download embedding model for semantic search\n console.log(chalk.yellow(' Semantic search setup'));\n console.log(chalk.dim(' Enables searching conversations by meaning\\n'));\n\n const modelSpinner = new Spinner('Checking embedding model...');\n modelSpinner.start();\n\n const cached = isModelCached();\n\n if (cached) {\n modelSpinner.succeed('Embedding model ready');\n } else {\n modelSpinner.update('Downloading embedding model (~130MB)...');\n\n try {\n await initializeEmbeddings((progress: InitProgress) => {\n if (progress.status === 'downloading' && progress.progress !== undefined) {\n const percent = Math.round(progress.progress);\n const fileName = progress.file ? progress.file.split('/').pop() : '';\n modelSpinner.update(`Downloading ${fileName}... ${percent}%`);\n } else if (progress.status === 'loading') {\n modelSpinner.update('Loading model...');\n }\n });\n modelSpinner.succeed('Embedding model ready');\n } catch (err) {\n modelSpinner.fail('Failed to download embedding model');\n console.log(chalk.dim(` Error: ${err}\\n`));\n }\n }\n\n console.log('');\n\n // Step 3: Auto-start daemon\n const daemonInstalled = existsSync(\n join(homedir(), 'Library', 'LaunchAgents', 'com.cmem.watch.plist')\n );\n\n // Check if we're updating (need to reinstall daemon to pick up new binary)\n const isUpdating = installedVersion && installedVersion !== currentVersion;\n\n if (daemonInstalled && !isUpdating) {\n console.log(chalk.green(' ✓ Auto-start daemon is installed'));\n // Make sure it's actually running\n try {\n execSync('launchctl load ~/Library/LaunchAgents/com.cmem.watch.plist 2>/dev/null', { stdio: 'ignore' });\n } catch {\n // Already loaded, that's fine\n }\n console.log('');\n } else if (daemonInstalled && isUpdating && process.platform === 'darwin') {\n // Reinstall daemon to pick up updated binary\n console.log(chalk.yellow(' Updating daemon...'));\n try {\n const { installCommand } = await import('./install.js');\n await installCommand();\n } catch {\n console.log(chalk.red(' ✗ Failed to update daemon'));\n console.log(chalk.dim(' Try manually: cmem install\\n'));\n }\n } else if (process.platform === 'darwin') {\n console.log(chalk.yellow(' Auto-start daemon?'));\n console.log(chalk.dim(' Syncs Claude Code sessions in the background\\n'));\n\n const choice = await promptChoice('', [\n 'Yes - start on login (recommended)',\n 'No - I\\'ll run `cmem watch` manually',\n ], 1);\n\n if (choice === 1) {\n try {\n const { installCommand } = await import('./install.js');\n await installCommand();\n } catch (err) {\n console.log(chalk.red(' ✗ Failed to install daemon'));\n console.log(chalk.dim(' Try manually: cmem install\\n'));\n }\n } else {\n console.log(chalk.dim('\\n Skipped. Run `cmem watch` when needed.\\n'));\n }\n }\n\n // Step 4: Claude Code MCP integration\n const mcpConfigured = isMcpConfigured();\n\n if (mcpConfigured) {\n console.log(chalk.green(' ✓ MCP server configured in Claude Code\\n'));\n } else {\n console.log(chalk.yellow(' Add MCP server to Claude Code?'));\n console.log(chalk.dim(' Lets Claude search your past conversations\\n'));\n\n const choice = await promptChoice('', [\n 'Yes - configure automatically (recommended)',\n 'No - I\\'ll configure it manually',\n ], 1);\n\n if (choice === 1) {\n const success = configureMcpServer();\n if (success) {\n console.log(chalk.green('\\n ✓ Added MCP server to ~/.claude.json'));\n console.log(chalk.green(' ✓ Added permissions to ~/.claude/settings.json'));\n console.log(chalk.dim(' Restart Claude Code or run /mcp to connect\\n'));\n } else {\n console.log(chalk.red('\\n ✗ Failed to configure MCP server\\n'));\n }\n } else {\n console.log(chalk.dim('\\n Skipped.\\n'));\n }\n }\n\n // Step 5: Index existing sessions\n console.log(chalk.yellow(' Initial session indexing'));\n console.log(chalk.dim(' Scanning and indexing your existing Claude Code conversations\\n'));\n\n await indexExistingSessions();\n\n // Mark setup as complete\n if (!existsSync(CMEM_DIR)) {\n mkdirSync(CMEM_DIR, { recursive: true });\n }\n writeFileSync(SETUP_MARKER, new Date().toISOString());\n\n // Done - show summary\n console.log(chalk.magenta(' ════════════════════════════════════════════'));\n console.log(chalk.green.bold('\\n ✓ Setup complete!\\n'));\n\n console.log(chalk.white(' Commands:'));\n console.log(chalk.dim(' cmem Browse sessions (TUI)'));\n console.log(chalk.dim(' cmem search \"X\" Semantic search'));\n console.log(chalk.dim(' cmem watch Start sync daemon'));\n console.log(chalk.dim(' cmem stats Storage statistics'));\n console.log(chalk.dim(' cmem --help All commands'));\n\n console.log(chalk.white('\\n MCP Tools (available to Claude):'));\n console.log(chalk.dim(' search_sessions Find past conversations'));\n console.log(chalk.dim(' get_session Retrieve full history'));\n console.log(chalk.dim(' list_sessions Browse recent sessions'));\n\n // Check if daemon is running and inform user\n if (process.platform === 'darwin') {\n const plistExists = existsSync(join(homedir(), 'Library', 'LaunchAgents', 'com.cmem.watch.plist'));\n if (plistExists) {\n console.log(chalk.green('\\n 🚀 Daemon is now syncing your sessions in the background!'));\n }\n }\n\n console.log('');\n}\n\nfunction isMcpConfigured(): boolean {\n // Check if MCP server exists in ~/.claude.json\n if (!existsSync(CLAUDE_JSON_PATH)) {\n return false;\n }\n\n try {\n const config: ClaudeJson = JSON.parse(readFileSync(CLAUDE_JSON_PATH, 'utf-8'));\n return !!config.mcpServers?.cmem;\n } catch {\n return false;\n }\n}\n\nfunction configureMcpServer(): boolean {\n try {\n // Step 1: Add MCP server to ~/.claude.json\n let claudeJson: ClaudeJson = {};\n if (existsSync(CLAUDE_JSON_PATH)) {\n try {\n claudeJson = JSON.parse(readFileSync(CLAUDE_JSON_PATH, 'utf-8'));\n } catch {\n claudeJson = {};\n }\n }\n\n if (!claudeJson.mcpServers) {\n claudeJson.mcpServers = {};\n }\n\n claudeJson.mcpServers.cmem = {\n type: 'stdio',\n command: 'cmem',\n args: ['mcp'],\n };\n\n writeFileSync(CLAUDE_JSON_PATH, JSON.stringify(claudeJson, null, 2) + '\\n');\n\n // Step 2: Add permissions to ~/.claude/settings.json\n const claudeDir = dirname(CLAUDE_SETTINGS_PATH);\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n\n let settings: ClaudeSettings = {};\n if (existsSync(CLAUDE_SETTINGS_PATH)) {\n try {\n settings = JSON.parse(readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8'));\n } catch {\n settings = {};\n }\n }\n\n if (!settings.permissions) {\n settings.permissions = {};\n }\n if (!settings.permissions.allow) {\n settings.permissions.allow = [];\n }\n\n // Add any missing cmem permissions\n for (const perm of CMEM_PERMISSIONS) {\n if (!settings.permissions.allow.includes(perm)) {\n settings.permissions.allow.push(perm);\n }\n }\n\n writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\\n');\n\n return true;\n } catch (err) {\n console.error(chalk.red('Error configuring MCP:'), err);\n return false;\n }\n}\n\nexport function shouldRunSetup(): boolean {\n const isNpx = isRunningViaNpx();\n const setupComplete = existsSync(SETUP_MARKER);\n const isGlobal = isGloballyInstalled();\n\n // Always run setup when invoked via npx\n if (isNpx) return true;\n\n // Run setup if not installed globally and setup hasn't been completed\n if (!isGlobal && !setupComplete) return true;\n\n // Check for version mismatch (update available)\n const currentVersion = getCmemVersion();\n const installedVersion = getInstalledVersion();\n if (installedVersion && installedVersion !== currentVersion) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Find all .jsonl session files in the Claude directory\n */\nfunction findAllSessionFiles(dir: string): string[] {\n const files: string[] = [];\n\n if (!existsSync(dir)) return files;\n\n function scanDir(currentDir: string, depth: number = 0): void {\n if (depth > 10) return;\n\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(currentDir, entry.name);\n\n if (entry.isDirectory()) {\n if (entry.name === 'subagents') continue;\n scanDir(fullPath, depth + 1);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n files.push(fullPath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n scanDir(dir);\n return files;\n}\n\n/**\n * Index a single session file\n */\nasync function indexSessionFile(filePath: string, embeddingsReady: boolean): Promise<boolean> {\n try {\n const messages = parseSessionFile(filePath);\n if (messages.length === 0) return false;\n\n // Check if already indexed\n const existing = getSessionBySourceFile(filePath);\n if (existing) return false;\n\n // Get file stats\n const stats = statSync(filePath);\n const fileMtime = stats.mtime.toISOString();\n\n // Generate title and summary\n const firstUserMsg = messages.find(m => m.role === 'user');\n const title = firstUserMsg ? generateTitle(firstUserMsg.content) : 'Untitled Session';\n const summary = generateSummary(messages);\n\n // Build raw data\n const rawData = JSON.stringify({ filePath, messages, mtime: fileMtime });\n const sessionId_from_file = basename(filePath, '.jsonl');\n\n // Create session\n const sessionId = createSession({\n title,\n summary,\n projectPath: null,\n sourceFile: filePath,\n rawData,\n messages,\n });\n\n // Generate embedding if ready\n if (embeddingsReady) {\n const contentLength = messages.reduce((sum, m) => sum + m.content.length, 0);\n const shouldEmbed = needsReembedding(sessionId, contentLength, 500);\n\n if (shouldEmbed) {\n try {\n const embeddingText = createEmbeddingText(title, summary, messages);\n const embedding = await getEmbedding(embeddingText);\n storeEmbedding(sessionId, embedding);\n updateEmbeddingState(sessionId, contentLength, fileMtime);\n } catch {\n // Ignore embedding errors\n }\n }\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Index all existing Claude Code sessions\n */\nasync function indexExistingSessions(): Promise<void> {\n const spinner = new Spinner('Scanning for sessions...');\n spinner.start();\n\n // Find all session files\n const sessionFiles = findAllSessionFiles(CLAUDE_DIR);\n const totalFiles = sessionFiles.length;\n\n if (totalFiles === 0) {\n spinner.succeed('No Claude Code sessions found yet');\n console.log(chalk.dim(' Start using Claude Code, then run cmem to see your sessions\\n'));\n return;\n }\n\n // Check how many are already indexed\n const statsBefore = getStats();\n const alreadyIndexed = statsBefore.sessionCount;\n\n if (alreadyIndexed >= totalFiles) {\n spinner.succeed(`Found ${totalFiles} sessions (all indexed)`);\n console.log('');\n return;\n }\n\n spinner.update(`Found ${totalFiles} sessions, indexing...`);\n\n // Check if embeddings are ready\n const embeddingsReady = isReady();\n\n let processed = 0;\n let newlyIndexed = 0;\n\n for (const filePath of sessionFiles) {\n processed++;\n const wasNew = await indexSessionFile(filePath, embeddingsReady);\n if (wasNew) newlyIndexed++;\n\n // Update progress\n const percent = Math.round((processed / totalFiles) * 100);\n spinner.update(`Indexing sessions... ${percent}% (${processed}/${totalFiles})`);\n }\n\n spinner.succeed(`Indexed ${totalFiles} sessions (${newlyIndexed} new)`);\n\n // Show stats\n const statsAfter = getStats();\n console.log(chalk.dim(` ${statsAfter.sessionCount} sessions, ${statsAfter.embeddingCount} with embeddings\\n`));\n}\n"],"mappings":"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","names":["chalk","existsSync","mkdirSync","homedir","join","dirname","execSync","React","existsSync","readFileSync","join","dirname","fileURLToPath","spawn","useState","useEffect","useCallback","Box","Text","TextInput","basename","dirname","existsSync","Box","Text","jsx","jsxs","Box","Text","basename","jsx","jsxs","Box","Text","basename","Box","Text","jsx","jsxs","Box","Text","existsSync","existsSync","join","content","existsSync","join","existsSync","db","db","db","db","db","existsSync","join","join","existsSync","jsx","jsxs","deleteSession","useState","useEffect","useCallback","basename","dirname","existsSync","Box","Text","TextInput","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","statSync","existsSync","chalk","existsSync","statSync","chalk","statSync","existsSync","readFileSync","readdirSync","join","dirname","basename","Spinner","chalk","existsSync","readdirSync","join","statSync","basename","loadSubagentMessages","dirname","readFileSync","chalk","chalk","chalk","execSync","existsSync","readFileSync","writeFileSync","mkdirSync","readdirSync","statSync","homedir","join","dirname","basename","dirname","join","homedir","CMEM_DIR","spinnerFrames","Spinner","chalk","execSync","existsSync","readFileSync","installCommand","mkdirSync","writeFileSync","findAllSessionFiles","readdirSync","statSync","basename","__filename","fileURLToPath","__dirname","dirname","join","existsSync","readFileSync","React","spawn"]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/install.ts","../src/cli.ts","../src/ui/App.tsx","../src/ui/components/Header.tsx","../src/ui/components/SearchInput.tsx","../src/ui/components/SessionList.tsx","../src/utils/format.ts","../src/ui/components/ProjectList.tsx","../src/ui/components/Preview.tsx","../src/ui/hooks/useSessions.ts","../src/db/index.ts","../src/utils/config.ts","../src/parser/index.ts","../src/db/sessions.ts","../src/db/vectors.ts","../src/embeddings/index.ts","../src/commands/save.ts","../src/commands/list.ts","../src/commands/search.ts","../src/commands/restore.ts","../src/utils/clipboard.ts","../src/commands/delete.ts","../src/commands/stats.ts","../src/commands/watch.ts","../src/commands/mcp.ts","../src/mcp/server.ts","../src/utils/claude-cli.ts","../src/commands/setup.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { writeFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';\nimport { homedir } from 'os';\nimport { join, dirname } from 'path';\nimport { execSync } from 'child_process';\n\nconst LAUNCH_AGENTS_DIR = join(homedir(), 'Library', 'LaunchAgents');\nconst PLIST_NAME = 'com.cmem.watch.plist';\nconst PLIST_PATH = join(LAUNCH_AGENTS_DIR, PLIST_NAME);\n\nfunction getCmemPath(): string {\n try {\n // Find the actual cmem binary path\n const result = execSync('which cmem', { encoding: 'utf-8' }).trim();\n return result;\n } catch {\n // Fallback to npx\n return '/usr/local/bin/cmem';\n }\n}\n\nfunction getNodeBinDir(): string {\n try {\n // Get the directory containing node (for nvm, homebrew, etc.)\n const nodePath = execSync('which node', { encoding: 'utf-8' }).trim();\n return dirname(nodePath); // Return the bin directory\n } catch {\n return '/usr/local/bin';\n }\n}\n\nfunction generatePlist(cmemPath: string): string {\n const nodeBinDir = getNodeBinDir();\n // Build PATH with node's bin directory first, then standard paths\n const pathValue = `${nodeBinDir}:/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin`;\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>com.cmem.watch</string>\n\n <key>ProgramArguments</key>\n <array>\n <string>${cmemPath}</string>\n <string>watch</string>\n </array>\n\n <key>RunAtLoad</key>\n <true/>\n\n <key>KeepAlive</key>\n <true/>\n\n <key>StandardOutPath</key>\n <string>${homedir()}/.cmem/watch.log</string>\n\n <key>StandardErrorPath</key>\n <string>${homedir()}/.cmem/watch.error.log</string>\n\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>${pathValue}</string>\n </dict>\n</dict>\n</plist>`;\n}\n\nexport async function installCommand(): Promise<void> {\n const platform = process.platform;\n\n if (platform !== 'darwin') {\n console.log(chalk.yellow('Auto-install is currently only supported on macOS.'));\n console.log(chalk.dim('\\nFor Linux, create a systemd service:'));\n console.log(chalk.dim(' ~/.config/systemd/user/cmem-watch.service'));\n console.log(chalk.dim('\\nFor manual background run:'));\n console.log(chalk.dim(' nohup cmem watch > ~/.cmem/watch.log 2>&1 &'));\n return;\n }\n\n console.log(chalk.cyan('Installing cmem watch daemon...\\n'));\n\n // Ensure LaunchAgents directory exists\n if (!existsSync(LAUNCH_AGENTS_DIR)) {\n mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });\n }\n\n // Ensure .cmem directory exists for logs\n const cmemDir = join(homedir(), '.cmem');\n if (!existsSync(cmemDir)) {\n mkdirSync(cmemDir, { recursive: true });\n }\n\n // Get cmem path\n const cmemPath = getCmemPath();\n console.log(chalk.dim(`Using cmem at: ${cmemPath}`));\n\n // Check if already installed\n if (existsSync(PLIST_PATH)) {\n console.log(chalk.yellow('LaunchAgent already exists. Unloading first...'));\n try {\n execSync(`launchctl unload \"${PLIST_PATH}\"`, { stdio: 'ignore' });\n } catch {\n // May not be loaded\n }\n }\n\n // Write plist\n const plistContent = generatePlist(cmemPath);\n writeFileSync(PLIST_PATH, plistContent);\n console.log(chalk.green(`✓ Created ${PLIST_PATH}`));\n\n // Load the LaunchAgent\n try {\n execSync(`launchctl load \"${PLIST_PATH}\"`);\n console.log(chalk.green('✓ LaunchAgent loaded'));\n } catch (err) {\n console.log(chalk.red('Failed to load LaunchAgent:'), err);\n return;\n }\n\n console.log(chalk.green('\\n✓ cmem watch daemon installed and running!'));\n console.log(chalk.dim('\\nThe daemon will:'));\n console.log(chalk.dim(' • Start automatically on login'));\n console.log(chalk.dim(' • Restart if it crashes'));\n console.log(chalk.dim(` • Log to ~/.cmem/watch.log`));\n console.log(chalk.dim('\\nCommands:'));\n console.log(chalk.dim(' cmem uninstall Stop and remove the daemon'));\n console.log(chalk.dim(' cmem status Check daemon status'));\n}\n\nexport async function uninstallCommand(): Promise<void> {\n const platform = process.platform;\n\n if (platform !== 'darwin') {\n console.log(chalk.yellow('Auto-uninstall is currently only supported on macOS.'));\n return;\n }\n\n console.log(chalk.cyan('Uninstalling cmem watch daemon...\\n'));\n\n if (!existsSync(PLIST_PATH)) {\n console.log(chalk.yellow('LaunchAgent not found. Nothing to uninstall.'));\n return;\n }\n\n // Unload the LaunchAgent\n try {\n execSync(`launchctl unload \"${PLIST_PATH}\"`);\n console.log(chalk.green('✓ LaunchAgent unloaded'));\n } catch {\n console.log(chalk.yellow('LaunchAgent was not loaded'));\n }\n\n // Remove plist file\n try {\n unlinkSync(PLIST_PATH);\n console.log(chalk.green(`✓ Removed ${PLIST_PATH}`));\n } catch (err) {\n console.log(chalk.red('Failed to remove plist:'), err);\n return;\n }\n\n console.log(chalk.green('\\n✓ cmem watch daemon uninstalled'));\n}\n\nexport async function statusCommand(): Promise<void> {\n const platform = process.platform;\n\n if (platform !== 'darwin') {\n console.log(chalk.yellow('Status check is currently only supported on macOS.'));\n return;\n }\n\n console.log(chalk.cyan('cmem watch daemon status\\n'));\n\n if (!existsSync(PLIST_PATH)) {\n console.log(chalk.yellow('Status: Not installed'));\n console.log(chalk.dim('Run: cmem install'));\n return;\n }\n\n try {\n const result = execSync(`launchctl list | grep com.cmem.watch`, {\n encoding: 'utf-8',\n });\n\n const parts = result.trim().split(/\\s+/);\n const pid = parts[0];\n const exitCode = parts[1];\n\n if (pid && pid !== '-') {\n console.log(chalk.green(`Status: Running (PID ${pid})`));\n } else if (exitCode === '0') {\n console.log(chalk.yellow('Status: Stopped (exit code 0)'));\n } else {\n console.log(chalk.red(`Status: Crashed (exit code ${exitCode})`));\n console.log(chalk.dim('Check ~/.cmem/watch.error.log for details'));\n }\n } catch {\n console.log(chalk.yellow('Status: Not running'));\n console.log(chalk.dim('The daemon is installed but not currently running.'));\n console.log(chalk.dim('It will start on next login, or run: launchctl load ~/Library/LaunchAgents/com.cmem.watch.plist'));\n }\n\n console.log(chalk.dim(`\\nPlist: ${PLIST_PATH}`));\n console.log(chalk.dim('Logs: ~/.cmem/watch.log'));\n}\n","import { program } from 'commander';\nimport { render } from 'ink';\nimport React from 'react';\nimport { existsSync, readFileSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { spawn } from 'child_process';\nimport { App } from './ui/App.js';\nimport { saveCommand } from './commands/save.js';\nimport { listCommand } from './commands/list.js';\nimport { searchCommand } from './commands/search.js';\nimport { restoreCommand } from './commands/restore.js';\nimport { deleteCommand } from './commands/delete.js';\nimport { statsCommand } from './commands/stats.js';\nimport { watchCommand } from './commands/watch.js';\nimport { mcpCommand } from './commands/mcp.js';\nimport { installCommand, uninstallCommand, statusCommand } from './commands/install.js';\nimport { setupCommand, shouldRunSetup } from './commands/setup.js';\n\n// Store session to resume after TUI exits\nlet sessionToResume: { sessionId: string; projectPath: string | null } | null = null;\n\n// Get version from package.json\nfunction getVersion(): string {\n try {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n const packagePath = join(__dirname, '..', 'package.json');\n if (existsSync(packagePath)) {\n const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));\n return pkg.version || '0.1.0';\n }\n } catch {\n // Ignore\n }\n return '0.1.0';\n}\n\nprogram\n .name('cmem')\n .description('Persistent session storage for Claude Code CLI')\n .version(getVersion())\n .option('-l, --local', 'Filter to sessions from current directory')\n .action(async (options) => {\n // Check if we should run setup (first run via npx)\n if (shouldRunSetup()) {\n await setupCommand();\n return;\n }\n\n // Handle resume callback from TUI\n const handleResume = (sessionId: string, projectPath: string | null) => {\n sessionToResume = { sessionId, projectPath };\n };\n\n // Determine project filter\n const projectFilter = options.local ? process.cwd() : null;\n\n // Default action: launch TUI\n const { waitUntilExit } = render(React.createElement(App, { onResume: handleResume, projectFilter }));\n await waitUntilExit();\n\n // If user selected a session to resume, spawn Claude\n if (sessionToResume) {\n const args = ['--resume', sessionToResume.sessionId];\n\n // Use project path if available, otherwise current directory\n const cwd = sessionToResume.projectPath || process.cwd();\n\n console.log(`\\nResuming session in: ${cwd}\\n`);\n\n // Spawn Claude with inherited stdio so it takes over the terminal\n const child = spawn('claude', args, {\n cwd,\n stdio: 'inherit',\n shell: true,\n });\n\n child.on('error', (err) => {\n console.error('Failed to start Claude:', err.message);\n process.exit(1);\n });\n\n child.on('exit', (code) => {\n process.exit(code || 0);\n });\n }\n });\n\nprogram\n .command('setup')\n .description('Run interactive setup wizard')\n .action(async () => {\n await setupCommand();\n });\n\nprogram\n .command('save')\n .description('Save a Claude Code session')\n .option('-t, --title <title>', 'Custom title')\n .option('--latest', 'Auto-save most recent session')\n .action(async (options) => {\n await saveCommand(options);\n });\n\nprogram\n .command('list')\n .description('List saved sessions (human sessions only by default)')\n .option('-a, --all', 'Show all sessions including automated ones')\n .action(async (options) => {\n await listCommand(options);\n });\n\nprogram\n .command('search <query>')\n .description('Semantic search across sessions')\n .action(async (query) => {\n await searchCommand(query);\n });\n\nprogram\n .command('restore <id>')\n .description('Restore a session')\n .option('--copy', 'Copy to clipboard')\n .option('--format <format>', 'Output format: context|json|markdown', 'context')\n .action(async (id, options) => {\n await restoreCommand(id, options);\n });\n\nprogram\n .command('delete <id>')\n .description('Delete a session')\n .action(async (id) => {\n await deleteCommand(id);\n });\n\nprogram\n .command('stats')\n .description('Show storage statistics')\n .action(async () => {\n await statsCommand();\n });\n\nprogram\n .command('watch')\n .description('Watch for Claude Code session changes and auto-sync')\n .option('-v, --verbose', 'Show detailed output')\n .option('--embed-threshold <chars>', 'Re-embed after this many new chars', '500')\n .action(async (options) => {\n await watchCommand({\n verbose: options.verbose,\n embedThreshold: parseInt(options.embedThreshold, 10),\n });\n });\n\nprogram\n .command('mcp')\n .description('Start MCP server for Claude Code integration')\n .action(async () => {\n await mcpCommand();\n });\n\nprogram\n .command('install')\n .description('Install watch daemon to run at system startup (macOS)')\n .action(async () => {\n await installCommand();\n });\n\nprogram\n .command('uninstall')\n .description('Remove watch daemon from system startup')\n .action(async () => {\n await uninstallCommand();\n });\n\nprogram\n .command('status')\n .description('Check watch daemon status')\n .action(async () => {\n await statusCommand();\n });\n\nprogram.parse();\n","import React, { useState, useEffect, useCallback } from 'react';\nimport { Box, Text, useInput, useApp } from 'ink';\nimport TextInput from 'ink-text-input';\nimport Spinner from 'ink-spinner';\nimport { basename, dirname } from 'path';\nimport { existsSync } from 'fs';\nimport { Header } from './components/Header.js';\nimport { SearchInput } from './components/SearchInput.js';\nimport { SessionList } from './components/SessionList.js';\nimport { ProjectList } from './components/ProjectList.js';\nimport { Preview } from './components/Preview.js';\nimport { useSessions } from './hooks/useSessions.js';\nimport { renameSession } from '../db/sessions.js';\n\ntype Mode = 'list' | 'search' | 'confirm-delete' | 'rename' | 'sort-project';\ntype TabType = 'global' | 'projects';\ntype ViewType = 'sessions' | 'projects' | 'project-sessions'; // What we're currently viewing\n\nexport interface AppProps {\n onResume?: (sessionId: string, projectPath: string | null) => void;\n projectFilter?: string | null;\n}\n\nexport const App: React.FC<AppProps> = ({ onResume, projectFilter: initialProjectFilter }) => {\n const { exit } = useApp();\n const {\n sessions,\n projects,\n loading,\n embeddingsReady,\n projectFilter,\n setProjectFilter,\n search,\n clearSearch,\n deleteSession,\n refresh,\n toggleFavorite,\n moveProject,\n } = useSessions({ projectFilter: initialProjectFilter });\n\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [searchQuery, setSearchQuery] = useState('');\n const [mode, setMode] = useState<Mode>('list');\n const [statusMessage, setStatusMessage] = useState<string | null>(null);\n const [renameValue, setRenameValue] = useState('');\n const [currentTab, setCurrentTab] = useState<TabType>('global');\n const [selectedProjectPath, setSelectedProjectPath] = useState<string | null>(null);\n\n // Determine current view based on tab and whether we've drilled into a project\n const getCurrentView = useCallback((): ViewType => {\n if (currentTab === 'projects') {\n return selectedProjectPath ? 'project-sessions' : 'projects';\n }\n return 'sessions';\n }, [currentTab, selectedProjectPath]);\n\n const currentView = getCurrentView();\n\n // Get sessions for current project (when viewing project-sessions)\n const projectSessions = selectedProjectPath\n ? sessions.filter(s => s.projectPath === selectedProjectPath)\n : [];\n\n // Reset selection when view changes\n useEffect(() => {\n setSelectedIndex(0);\n }, [currentTab, selectedProjectPath]);\n\n // Bound check for selected index\n useEffect(() => {\n const maxIndex = currentView === 'projects'\n ? projects.length - 1\n : currentView === 'project-sessions'\n ? projectSessions.length - 1\n : sessions.length - 1;\n if (selectedIndex > maxIndex) {\n setSelectedIndex(Math.max(0, maxIndex));\n }\n }, [currentView, projects.length, projectSessions.length, sessions.length, selectedIndex]);\n\n // Debounced search\n useEffect(() => {\n if (mode === 'search' && searchQuery.length > 2) {\n const timer = setTimeout(() => {\n search(searchQuery);\n }, 300);\n return () => clearTimeout(timer);\n } else if (mode === 'search' && searchQuery.length === 0) {\n clearSearch();\n }\n }, [searchQuery, mode, search, clearSearch]);\n\n // Clear status message after 3 seconds\n useEffect(() => {\n if (statusMessage) {\n const timer = setTimeout(() => setStatusMessage(null), 3000);\n return () => clearTimeout(timer);\n }\n }, [statusMessage]);\n\n const getCurrentSessions = useCallback(() => {\n if (currentView === 'project-sessions') {\n return projectSessions;\n }\n return sessions;\n }, [currentView, projectSessions, sessions]);\n\n const handleRestore = useCallback(() => {\n const currentSessions = getCurrentSessions();\n const session = currentSessions[selectedIndex];\n if (!session) return;\n\n if (session.sourceFile) {\n const filename = basename(session.sourceFile);\n const claudeSessionId = filename.replace('.jsonl', '');\n\n const projectDirName = basename(dirname(session.sourceFile));\n let projectPath: string | null = null;\n\n if (projectDirName.startsWith('-')) {\n const segments = projectDirName.substring(1).split('-');\n let currentPath = '';\n let remainingSegments = [...segments];\n\n while (remainingSegments.length > 0) {\n let found = false;\n for (let i = remainingSegments.length; i > 0; i--) {\n const testSegment = remainingSegments.slice(0, i).join('-');\n const testPath = currentPath + '/' + testSegment;\n\n if (existsSync(testPath)) {\n currentPath = testPath;\n remainingSegments = remainingSegments.slice(i);\n found = true;\n break;\n }\n }\n\n if (!found) {\n currentPath = currentPath + '/' + remainingSegments.join('-');\n break;\n }\n }\n\n if (currentPath && existsSync(currentPath)) {\n projectPath = currentPath;\n }\n }\n\n if (onResume) {\n onResume(claudeSessionId, projectPath);\n exit();\n }\n } else {\n setStatusMessage('No source file - cannot resume this session');\n }\n }, [getCurrentSessions, selectedIndex, onResume, exit]);\n\n const handleEnterProject = useCallback(() => {\n const project = projects[selectedIndex];\n if (project) {\n setSelectedProjectPath(project.path);\n setSelectedIndex(0);\n }\n }, [projects, selectedIndex]);\n\n const handleBackToProjects = useCallback(() => {\n setSelectedProjectPath(null);\n setSelectedIndex(0);\n }, []);\n\n const handleDelete = useCallback(() => {\n const currentSessions = getCurrentSessions();\n const session = currentSessions[selectedIndex];\n if (session) {\n deleteSession(session.id);\n setStatusMessage(`Deleted: ${session.customTitle || session.title}`);\n setMode('list');\n }\n }, [getCurrentSessions, selectedIndex, deleteSession]);\n\n const handleRename = useCallback(() => {\n const currentSessions = getCurrentSessions();\n const session = currentSessions[selectedIndex];\n if (session && renameValue.trim()) {\n renameSession(session.id, renameValue.trim());\n setStatusMessage(`Renamed to: ${renameValue.trim()}`);\n refresh();\n }\n setMode('list');\n setRenameValue('');\n }, [getCurrentSessions, selectedIndex, renameValue, refresh]);\n\n const handleClearRename = useCallback(() => {\n const currentSessions = getCurrentSessions();\n const session = currentSessions[selectedIndex];\n if (session && session.customTitle) {\n renameSession(session.id, null);\n setStatusMessage(`Cleared custom name`);\n refresh();\n }\n setMode('list');\n }, [getCurrentSessions, selectedIndex, refresh]);\n\n // Handle keyboard input\n useInput((input, key) => {\n // Global quit\n if (input === 'q' && mode !== 'search' && mode !== 'rename' && mode !== 'sort-project') {\n exit();\n return;\n }\n\n // Mode-specific handling\n if (mode === 'confirm-delete') {\n if (input === 'y' || input === 'Y') {\n handleDelete();\n } else {\n setMode('list');\n }\n return;\n }\n\n if (mode === 'rename') {\n if (key.escape) {\n setMode('list');\n setRenameValue('');\n return;\n }\n if (key.return) {\n handleRename();\n return;\n }\n return;\n }\n\n if (mode === 'search') {\n if (key.escape) {\n setMode('list');\n setSearchQuery('');\n clearSearch();\n return;\n }\n if (key.return) {\n setMode('list');\n return;\n }\n return;\n }\n\n if (mode === 'sort-project') {\n if (key.escape || key.return) {\n setMode('list');\n return;\n }\n if (key.upArrow || input === 'k') {\n if (selectedIndex > 0) {\n moveProject(selectedIndex, selectedIndex - 1);\n setSelectedIndex(selectedIndex - 1);\n }\n return;\n }\n if (key.downArrow || input === 'j') {\n if (selectedIndex < projects.length - 1) {\n moveProject(selectedIndex, selectedIndex + 1);\n setSelectedIndex(selectedIndex + 1);\n }\n return;\n }\n return;\n }\n\n // List mode\n if (input === '/') {\n setMode('search');\n return;\n }\n\n // Back navigation (Escape or Backspace when in project-sessions)\n if ((key.escape || key.backspace || key.delete) && currentView === 'project-sessions') {\n handleBackToProjects();\n return;\n }\n\n if (input === 'r' && currentView !== 'projects') {\n const currentSessions = getCurrentSessions();\n if (currentSessions.length > 0) {\n const session = currentSessions[selectedIndex];\n setRenameValue(session?.customTitle || '');\n setMode('rename');\n }\n return;\n }\n\n if (input === 'R' && currentView !== 'projects') {\n handleClearRename();\n return;\n }\n\n // Tab navigation with left/right arrows\n if (key.leftArrow || input === 'h') {\n if (currentTab === 'projects') {\n setCurrentTab('global');\n setSelectedProjectPath(null);\n }\n return;\n }\n\n if (key.rightArrow || input === 'l') {\n if (currentTab === 'global') {\n setCurrentTab('projects');\n }\n return;\n }\n\n if (key.upArrow || input === 'k') {\n setSelectedIndex(prev => Math.max(0, prev - 1));\n return;\n }\n\n if (key.downArrow || input === 'j') {\n const maxIndex = currentView === 'projects'\n ? projects.length - 1\n : currentView === 'project-sessions'\n ? projectSessions.length - 1\n : sessions.length - 1;\n setSelectedIndex(prev => Math.min(maxIndex, prev + 1));\n return;\n }\n\n if (key.return) {\n if (currentView === 'projects') {\n handleEnterProject();\n } else {\n handleRestore();\n }\n return;\n }\n\n if (input === 'd' && currentView !== 'projects') {\n const currentSessions = getCurrentSessions();\n if (currentSessions.length > 0) {\n setMode('confirm-delete');\n }\n return;\n }\n\n if (input === 's') {\n if (currentView === 'projects') {\n // Enter sort mode for projects\n if (projects.length > 0) {\n setMode('sort-project');\n setStatusMessage('Sort mode: use ↑↓ to move, Enter to confirm');\n }\n } else {\n // Star/unstar session\n const currentSessions = getCurrentSessions();\n const session = currentSessions[selectedIndex];\n if (session) {\n const isNowFavorite = toggleFavorite(session.id);\n setStatusMessage(isNowFavorite ? '⭐ Added to favorites' : 'Removed from favorites');\n }\n }\n return;\n }\n });\n\n const handleSearchChange = useCallback((value: string) => {\n setSearchQuery(value);\n setSelectedIndex(0);\n }, []);\n\n if (loading && sessions.length === 0) {\n return (\n <Box padding={1}>\n <Spinner type=\"dots\" />\n <Text> Loading sessions...</Text>\n </Box>\n );\n }\n\n const currentSessions = getCurrentSessions();\n const selectedSession = currentView !== 'projects' ? currentSessions[selectedIndex] || null : null;\n const selectedProject = currentView === 'projects' ? projects[selectedIndex] || null : null;\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header embeddingsReady={embeddingsReady} projectFilter={selectedProjectPath} />\n\n {/* Breadcrumb for project-sessions */}\n {currentView === 'project-sessions' && selectedProjectPath && (\n <Box marginBottom={0}>\n <Text dimColor>Projects → </Text>\n <Text color=\"blue\">{basename(selectedProjectPath)}</Text>\n </Box>\n )}\n\n {currentTab === 'global' && (\n <SearchInput\n value={searchQuery}\n onChange={handleSearchChange}\n isFocused={mode === 'search'}\n />\n )}\n\n {currentView === 'projects' ? (\n <ProjectList\n projects={projects}\n selectedIndex={selectedIndex}\n onSelect={setSelectedIndex}\n />\n ) : (\n <SessionList\n sessions={currentSessions}\n selectedIndex={selectedIndex}\n onSelect={setSelectedIndex}\n />\n )}\n\n {selectedSession && <Preview session={selectedSession} />}\n\n {selectedProject && (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n marginTop={1}\n >\n <Box>\n <Text bold>Project Preview</Text>\n {selectedProject.sortOrder !== null && <Text dimColor> (#{selectedProject.sortOrder + 1})</Text>}\n </Box>\n <Text color=\"blue\">📁 {selectedProject.path}</Text>\n <Text dimColor>\n {selectedProject.sessionCount} session{selectedProject.sessionCount !== 1 ? 's' : ''} • {selectedProject.totalMessages} messages\n </Text>\n </Box>\n )}\n\n {/* Footer - Controls */}\n <Box marginTop={1}>\n {mode === 'confirm-delete' ? (\n <Text color=\"yellow\">\n Delete \"{selectedSession?.customTitle || selectedSession?.title}\"? [y/n]\n </Text>\n ) : mode === 'rename' ? (\n <Box>\n <Text color=\"magenta\">Rename: </Text>\n <TextInput\n value={renameValue}\n onChange={setRenameValue}\n placeholder=\"Enter new name...\"\n />\n <Text dimColor> [Enter] Save [Esc] Cancel</Text>\n </Box>\n ) : mode === 'sort-project' ? (\n <Text color=\"cyan\">\n Sort mode: [↑↓] Move project [Enter/Esc] Done\n </Text>\n ) : statusMessage ? (\n <Text color=\"green\">{statusMessage}</Text>\n ) : currentView === 'projects' ? (\n <Text dimColor>\n [↑↓] Navigate [Enter] Open [s] Sort [←→] Switch tabs [q] Quit\n </Text>\n ) : currentView === 'project-sessions' ? (\n <Text dimColor>\n [↑↓] Navigate [Enter] Resume [s] Star [Esc] Back [r] Rename [d] Delete [q] Quit\n </Text>\n ) : (\n <Text dimColor>\n [↑↓] Navigate [Enter] Resume [s] Star [r] Rename [d] Delete [/] Search [q] Quit\n </Text>\n )}\n </Box>\n\n {/* Tab bar at bottom */}\n <Box marginTop={1}>\n <Text\n backgroundColor={currentTab === 'global' ? 'green' : undefined}\n color={currentTab === 'global' ? 'white' : undefined}\n bold={currentTab === 'global'}\n dimColor={currentTab !== 'global'}\n >\n {currentTab === 'global' ? ' Global ' : 'Global'}\n </Text>\n <Text> </Text>\n <Text\n backgroundColor={currentTab === 'projects' ? 'magenta' : undefined}\n color={currentTab === 'projects' ? 'white' : undefined}\n bold={currentTab === 'projects'}\n dimColor={currentTab !== 'projects'}\n >\n {currentTab === 'projects' ? ' Projects ' : 'Projects'}\n </Text>\n <Text dimColor> [←→] switch</Text>\n </Box>\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport { basename } from 'path';\n\ninterface HeaderProps {\n embeddingsReady: boolean;\n projectFilter?: string | null;\n}\n\nexport const Header: React.FC<HeaderProps> = ({ embeddingsReady, projectFilter }) => {\n return (\n <Box marginBottom={1} justifyContent=\"space-between\">\n <Box>\n <Text bold color=\"cyan\">cmem</Text>\n {projectFilter && (\n <Text color=\"yellow\"> 📁 {basename(projectFilter)}</Text>\n )}\n {!embeddingsReady && (\n <Text color=\"yellow\" dimColor> (loading model...)</Text>\n )}\n </Box>\n <Text dimColor>[q] quit</Text>\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport TextInput from 'ink-text-input';\n\ninterface SearchInputProps {\n value: string;\n onChange: (value: string) => void;\n isFocused: boolean;\n}\n\nexport const SearchInput: React.FC<SearchInputProps> = ({\n value,\n onChange,\n isFocused,\n}) => {\n return (\n <Box marginBottom={1}>\n <Text>Search: </Text>\n {isFocused ? (\n <TextInput\n value={value}\n onChange={onChange}\n placeholder=\"type to search...\"\n focus={true}\n />\n ) : (\n <Text dimColor>{value || 'press / to search'}</Text>\n )}\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport { basename } from 'path';\nimport type { SessionWithFavorite } from '../hooks/useSessions.js';\nimport { formatTimeAgo, truncate } from '../../utils/format.js';\n\ninterface SessionListProps {\n sessions: SessionWithFavorite[];\n selectedIndex: number;\n onSelect: (index: number) => void;\n}\n\nexport const SessionList: React.FC<SessionListProps> = ({\n sessions,\n selectedIndex,\n}) => {\n if (sessions.length === 0) {\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n >\n <Text bold>Sessions</Text>\n <Text dimColor>No sessions found</Text>\n <Text dimColor>Run: cmem save --latest</Text>\n </Box>\n );\n }\n\n // Show max 8 sessions, centered around selected\n const visibleCount = 8;\n let startIndex = Math.max(0, selectedIndex - Math.floor(visibleCount / 2));\n const endIndex = Math.min(sessions.length, startIndex + visibleCount);\n if (endIndex - startIndex < visibleCount) {\n startIndex = Math.max(0, endIndex - visibleCount);\n }\n\n const visibleSessions = sessions.slice(startIndex, endIndex);\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n >\n <Text bold>Sessions ({sessions.length})</Text>\n {visibleSessions.map((session, i) => {\n const actualIndex = startIndex + i;\n const isSelected = actualIndex === selectedIndex;\n\n return (\n <SessionItem\n key={session.id}\n session={session}\n isSelected={isSelected}\n />\n );\n })}\n {sessions.length > visibleCount && (\n <Text dimColor>\n {startIndex > 0 ? '↑ more above' : ''}\n {startIndex > 0 && endIndex < sessions.length ? ' | ' : ''}\n {endIndex < sessions.length ? '↓ more below' : ''}\n </Text>\n )}\n </Box>\n );\n};\n\ninterface SessionItemProps {\n session: SessionWithFavorite;\n isSelected: boolean;\n}\n\nconst SessionItem: React.FC<SessionItemProps> = ({ session, isSelected }) => {\n const hasCustomTitle = !!session.customTitle;\n const displayTitle = truncate(session.customTitle || session.title, 38);\n const folderName = session.projectPath ? truncate(basename(session.projectPath), 38) : '';\n const msgs = String(session.messageCount).padStart(3);\n const updated = formatTimeAgo(session.updatedAt);\n\n // Determine title color: cyan if selected, magenta if renamed, yellow if favorite, undefined otherwise\n const getTitleColor = () => {\n if (isSelected) return 'cyan';\n if (session.isFavorite) return 'yellow';\n if (hasCustomTitle) return 'magenta';\n return undefined;\n };\n\n return (\n <Box>\n <Text color={isSelected ? 'cyan' : undefined}>\n {isSelected ? '▸ ' : ' '}\n </Text>\n <Text color=\"yellow\">{session.isFavorite ? '⭐' : ' '}</Text>\n <Text bold={isSelected} color={getTitleColor()} wrap=\"truncate\">\n {displayTitle.padEnd(38)}\n </Text>\n <Text color=\"blue\"> {folderName.padEnd(38)}</Text>\n <Text dimColor> {msgs} </Text>\n <Text dimColor>{updated.padStart(8)}</Text>\n </Box>\n );\n};\n","/**\n * Format a timestamp into a human-readable relative time\n */\nexport function formatTimeAgo(timestamp: string): string {\n const date = new Date(timestamp);\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffSecs = Math.floor(diffMs / 1000);\n const diffMins = Math.floor(diffSecs / 60);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n const diffWeeks = Math.floor(diffDays / 7);\n const diffMonths = Math.floor(diffDays / 30);\n\n if (diffSecs < 60) return 'just now';\n if (diffMins < 60) return `${diffMins}m ago`;\n if (diffHours < 24) return `${diffHours}h ago`;\n if (diffDays < 7) return `${diffDays}d ago`;\n if (diffWeeks < 4) return `${diffWeeks}w ago`;\n return `${diffMonths}mo ago`;\n}\n\n/**\n * Truncate text to a maximum length with ellipsis\n */\nexport function truncate(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return text.slice(0, maxLength - 3) + '...';\n}\n\n/**\n * Generate a short ID from a longer string\n */\nexport function shortId(id: string): string {\n return id.slice(0, 8);\n}\n\n/**\n * Format a number with thousands separator\n */\nexport function formatNumber(num: number): string {\n return num.toLocaleString();\n}\n\n/**\n * Format bytes into human-readable size\n */\nexport function formatBytes(bytes: number): string {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n}\n\n/**\n * Generate a title from message content\n */\nexport function generateTitle(content: string): string {\n // Take first line or first 50 chars\n const firstLine = content.split('\\n')[0].trim();\n const title = truncate(firstLine, 50);\n return title || 'Untitled Session';\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { Project } from '../hooks/useSessions.js';\nimport { formatTimeAgo, truncate } from '../../utils/format.js';\n\ninterface ProjectListProps {\n projects: Project[];\n selectedIndex: number;\n onSelect: (index: number) => void;\n}\n\nexport const ProjectList: React.FC<ProjectListProps> = ({\n projects,\n selectedIndex,\n}) => {\n if (projects.length === 0) {\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n >\n <Text bold>Projects</Text>\n <Text dimColor>No projects found</Text>\n <Text dimColor>Start using Claude Code in a project directory</Text>\n </Box>\n );\n }\n\n // Show max 8 projects, centered around selected\n const visibleCount = 8;\n let startIndex = Math.max(0, selectedIndex - Math.floor(visibleCount / 2));\n const endIndex = Math.min(projects.length, startIndex + visibleCount);\n if (endIndex - startIndex < visibleCount) {\n startIndex = Math.max(0, endIndex - visibleCount);\n }\n\n const visibleProjects = projects.slice(startIndex, endIndex);\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n >\n <Text bold>Projects ({projects.length})</Text>\n {visibleProjects.map((project, i) => {\n const actualIndex = startIndex + i;\n const isSelected = actualIndex === selectedIndex;\n\n return (\n <ProjectItem\n key={project.path}\n project={project}\n isSelected={isSelected}\n />\n );\n })}\n {projects.length > visibleCount && (\n <Text dimColor>\n {startIndex > 0 ? '↑ more above' : ''}\n {startIndex > 0 && endIndex < projects.length ? ' | ' : ''}\n {endIndex < projects.length ? '↓ more below' : ''}\n </Text>\n )}\n </Box>\n );\n};\n\ninterface ProjectItemProps {\n project: Project;\n isSelected: boolean;\n}\n\nconst ProjectItem: React.FC<ProjectItemProps> = ({ project, isSelected }) => {\n const displayName = truncate(project.name, 40);\n const sessions = `${project.sessionCount} session${project.sessionCount !== 1 ? 's' : ''}`;\n const messages = `${project.totalMessages} msgs`;\n const updated = formatTimeAgo(project.lastUpdated);\n // Show position number if manually sorted\n const orderBadge = project.sortOrder !== null ? `${project.sortOrder + 1}.` : ' ';\n\n return (\n <Box>\n <Text color={isSelected ? 'cyan' : undefined}>\n {isSelected ? '▸ ' : ' '}\n </Text>\n <Text dimColor>{orderBadge.padStart(3)} </Text>\n <Text color=\"blue\">📁 </Text>\n <Text bold={isSelected} color={isSelected ? 'cyan' : undefined} wrap=\"truncate\">\n {displayName.padEnd(35)}\n </Text>\n <Text dimColor> {sessions.padEnd(12)}</Text>\n <Text dimColor> {messages.padEnd(10)}</Text>\n <Text dimColor>{updated.padStart(10)}</Text>\n </Box>\n );\n};\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { SessionWithFavorite } from '../hooks/useSessions.js';\nimport { truncate } from '../../utils/format.js';\n\ninterface PreviewProps {\n session: SessionWithFavorite | null;\n}\n\nexport const Preview: React.FC<PreviewProps> = ({ session }) => {\n if (!session) {\n return null;\n }\n\n const summary = session.summary\n ? truncate(session.summary, 200)\n : 'No summary available';\n\n return (\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor=\"gray\"\n paddingX={1}\n paddingY={0}\n marginTop={1}\n >\n <Box>\n <Text bold>Preview</Text>\n {session.isFavorite && <Text color=\"yellow\"> ⭐</Text>}\n {session.projectPath && (\n <Text bold color=\"blue\"> 📁 {session.projectPath}</Text>\n )}\n </Box>\n <Text wrap=\"wrap\">{summary}</Text>\n <Text dimColor>Messages: {session.messageCount}</Text>\n </Box>\n );\n};\n","import { useState, useEffect, useCallback } from 'react';\nimport {\n listHumanSessions,\n listHumanSessionsByProject,\n deleteSession as dbDeleteSession,\n getSession,\n getFavoriteSessionIds,\n toggleFavorite as dbToggleFavorite,\n hasFavoriteSessions,\n getProjectOrders,\n updateProjectOrders,\n hasCustomProjectOrder,\n} from '../../db/sessions.js';\nimport { searchSessions } from '../../db/vectors.js';\nimport { getEmbedding, initializeEmbeddings, isReady } from '../../embeddings/index.js';\nimport type { Session } from '../../db/sessions.js';\n\nexport interface SessionWithFavorite extends Session {\n isFavorite: boolean;\n}\n\nexport interface Project {\n path: string;\n name: string;\n sessionCount: number;\n totalMessages: number;\n lastUpdated: string;\n sortOrder: number | null; // null = auto-sorted, number = manually positioned\n}\n\nexport interface UseSessionsOptions {\n projectFilter?: string | null;\n}\n\nexport interface UseSessionsResult {\n sessions: SessionWithFavorite[];\n projects: Project[];\n loading: boolean;\n error: string | null;\n embeddingsReady: boolean;\n projectFilter: string | null;\n setProjectFilter: (filter: string | null) => void;\n refresh: () => void;\n search: (query: string) => Promise<void>;\n clearSearch: () => void;\n deleteSession: (id: string) => void;\n getSessionById: (id: string) => Session | null;\n toggleFavorite: (sessionId: string) => boolean;\n favoriteSessionIds: Set<string>;\n hasFavoriteSessions: boolean;\n moveProject: (fromIndex: number, toIndex: number) => void;\n hasCustomProjectOrder: boolean;\n}\n\nexport function useSessions(options: UseSessionsOptions = {}): UseSessionsResult {\n const [sessions, setSessions] = useState<SessionWithFavorite[]>([]);\n const [allSessions, setAllSessions] = useState<SessionWithFavorite[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [embeddingsReady, setEmbeddingsReady] = useState(false);\n const [isSearching, setIsSearching] = useState(false);\n const [projectFilter, setProjectFilter] = useState<string | null>(options.projectFilter ?? null);\n const [favoriteSessionIds, setFavoriteSessionIds] = useState<Set<string>>(new Set());\n const [hasFavSessions, setHasFavSessions] = useState(false);\n const [projectOrderMap, setProjectOrderMap] = useState<Map<string, number>>(new Map());\n const [hasCustomOrder, setHasCustomOrder] = useState(false);\n\n // Smart sort: favorites (by messages) → custom named (by messages) → rest (by messages)\n const smartSort = useCallback((sessionList: Session[], favIds: Set<string>): SessionWithFavorite[] => {\n const withFavorites = sessionList.map(s => ({\n ...s,\n isFavorite: favIds.has(s.id),\n }));\n return withFavorites.sort((a, b) => {\n const aHasCustom = !!a.customTitle;\n const bHasCustom = !!b.customTitle;\n\n // Determine tier: 0 = favorite, 1 = custom name, 2 = rest\n const aTier = a.isFavorite ? 0 : aHasCustom ? 1 : 2;\n const bTier = b.isFavorite ? 0 : bHasCustom ? 1 : 2;\n\n // Different tiers: sort by tier\n if (aTier !== bTier) return aTier - bTier;\n\n // Same tier: sort by message count (most first)\n if (a.messageCount !== b.messageCount) return b.messageCount - a.messageCount;\n\n // Same message count: sort by most recent\n return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();\n });\n }, []);\n\n const [projects, setProjects] = useState<Project[]>([]);\n\n // Calculate projects from all sessions\n const calculateProjects = useCallback((sessionList: SessionWithFavorite[], orderMap: Map<string, number>): Project[] => {\n const projectMap = new Map<string, Project>();\n\n for (const session of sessionList) {\n if (!session.projectPath) continue;\n\n const existing = projectMap.get(session.projectPath);\n if (existing) {\n existing.sessionCount++;\n existing.totalMessages += session.messageCount;\n if (new Date(session.updatedAt) > new Date(existing.lastUpdated)) {\n existing.lastUpdated = session.updatedAt;\n }\n } else {\n const pathParts = session.projectPath.split('/');\n projectMap.set(session.projectPath, {\n path: session.projectPath,\n name: pathParts[pathParts.length - 1] || session.projectPath,\n sessionCount: 1,\n totalMessages: session.messageCount,\n sortOrder: orderMap.get(session.projectPath) ?? null,\n lastUpdated: session.updatedAt,\n });\n }\n }\n\n // Sort projects: manually ordered first (by sortOrder), then auto-sorted by messages → last updated\n return Array.from(projectMap.values()).sort((a, b) => {\n // Both have manual order: sort by order\n if (a.sortOrder !== null && b.sortOrder !== null) {\n return a.sortOrder - b.sortOrder;\n }\n // Only one has manual order: manual first\n if (a.sortOrder !== null && b.sortOrder === null) return -1;\n if (a.sortOrder === null && b.sortOrder !== null) return 1;\n // Neither has manual order: sort by messages → last updated\n if (a.totalMessages !== b.totalMessages) return b.totalMessages - a.totalMessages;\n return new Date(b.lastUpdated).getTime() - new Date(a.lastUpdated).getTime();\n });\n }, []);\n\n const loadSessions = useCallback(() => {\n try {\n const loaded = projectFilter\n ? listHumanSessionsByProject(projectFilter)\n : listHumanSessions();\n const favIds = getFavoriteSessionIds();\n const orderMap = getProjectOrders();\n setFavoriteSessionIds(favIds);\n setProjectOrderMap(orderMap);\n setHasFavSessions(hasFavoriteSessions());\n setHasCustomOrder(hasCustomProjectOrder());\n\n const sorted = smartSort(loaded, favIds);\n setAllSessions(sorted);\n setSessions(sorted);\n\n // Calculate projects from ALL sessions (not filtered)\n if (!projectFilter) {\n setProjects(calculateProjects(sorted, orderMap));\n }\n\n setError(null);\n } catch (err) {\n setError(String(err));\n } finally {\n setLoading(false);\n }\n }, [projectFilter, smartSort, calculateProjects]);\n\n const initEmbeddings = useCallback(async () => {\n if (isReady()) {\n setEmbeddingsReady(true);\n return;\n }\n try {\n await initializeEmbeddings();\n setEmbeddingsReady(true);\n } catch {\n setEmbeddingsReady(false);\n }\n }, []);\n\n useEffect(() => {\n loadSessions();\n initEmbeddings();\n }, [loadSessions, initEmbeddings]);\n\n // Reload when project filter changes\n useEffect(() => {\n loadSessions();\n }, [projectFilter, loadSessions]);\n\n const search = useCallback(async (query: string) => {\n if (!query.trim()) {\n setSessions(allSessions);\n setIsSearching(false);\n return;\n }\n\n if (!embeddingsReady) {\n // Fall back to simple text search\n const filtered = allSessions.filter(s =>\n s.title.toLowerCase().includes(query.toLowerCase()) ||\n (s.summary && s.summary.toLowerCase().includes(query.toLowerCase()))\n );\n setSessions(smartSort(filtered, favoriteSessionIds));\n setIsSearching(true);\n return;\n }\n\n try {\n setLoading(true);\n const queryEmbedding = await getEmbedding(query);\n const results = searchSessions(queryEmbedding, 20);\n setSessions(smartSort(results, favoriteSessionIds));\n setIsSearching(true);\n } catch (err) {\n setError(String(err));\n // Fall back to text search on error\n const filtered = allSessions.filter(s =>\n s.title.toLowerCase().includes(query.toLowerCase()) ||\n (s.summary && s.summary.toLowerCase().includes(query.toLowerCase()))\n );\n setSessions(smartSort(filtered, favoriteSessionIds));\n } finally {\n setLoading(false);\n }\n }, [allSessions, embeddingsReady, favoriteSessionIds, smartSort]);\n\n const clearSearch = useCallback(() => {\n setSessions(allSessions);\n setIsSearching(false);\n }, [allSessions]);\n\n const deleteSessionHandler = useCallback((id: string) => {\n const deleted = dbDeleteSession(id);\n if (deleted) {\n setAllSessions(prev => prev.filter(s => s.id !== id));\n setSessions(prev => prev.filter(s => s.id !== id));\n }\n }, []);\n\n const getSessionById = useCallback((id: string) => {\n return getSession(id);\n }, []);\n\n const toggleFavoriteHandler = useCallback((sessionId: string): boolean => {\n const isNowFavorite = dbToggleFavorite('session', sessionId);\n // Update local state\n const newFavIds = new Set(favoriteSessionIds);\n if (isNowFavorite) {\n newFavIds.add(sessionId);\n } else {\n newFavIds.delete(sessionId);\n }\n setFavoriteSessionIds(newFavIds);\n setHasFavSessions(newFavIds.size > 0);\n // Re-sort sessions\n setAllSessions(prev => smartSort(prev, newFavIds));\n setSessions(prev => smartSort(prev, newFavIds));\n return isNowFavorite;\n }, [favoriteSessionIds, smartSort]);\n\n // Move a project from one position to another\n const moveProject = useCallback((fromIndex: number, toIndex: number) => {\n if (fromIndex === toIndex) return;\n if (fromIndex < 0 || toIndex < 0) return;\n if (fromIndex >= projects.length || toIndex >= projects.length) return;\n\n // Create a new array with the project moved\n const newProjects = [...projects];\n const [movedProject] = newProjects.splice(fromIndex, 1);\n newProjects.splice(toIndex, 0, movedProject);\n\n // Update sort orders for all projects\n const orders = newProjects.map((project, index) => ({\n path: project.path,\n sortOrder: index,\n }));\n\n // Persist to database\n updateProjectOrders(orders);\n\n // Update local state\n const newOrderMap = new Map<string, number>();\n for (const order of orders) {\n newOrderMap.set(order.path, order.sortOrder);\n }\n setProjectOrderMap(newOrderMap);\n setHasCustomOrder(true);\n\n // Update projects with new sort orders\n setProjects(newProjects.map((p, i) => ({ ...p, sortOrder: i })));\n }, [projects]);\n\n return {\n sessions,\n projects,\n loading,\n error,\n embeddingsReady,\n projectFilter,\n setProjectFilter,\n refresh: loadSessions,\n search,\n clearSearch,\n deleteSession: deleteSessionHandler,\n getSessionById,\n toggleFavorite: toggleFavoriteHandler,\n favoriteSessionIds,\n hasFavoriteSessions: hasFavSessions,\n moveProject,\n hasCustomProjectOrder: hasCustomOrder,\n };\n}\n","import Database from 'better-sqlite3';\nimport * as sqliteVec from 'sqlite-vec';\nimport { existsSync } from 'fs';\nimport { DB_PATH, ensureCmemDir, EMBEDDING_DIMENSIONS } from '../utils/config.js';\nimport { extractSessionMetadata } from '../parser/index.js';\n\nlet db: Database.Database | null = null;\n\n/**\n * Get or create the database connection\n */\nexport function getDatabase(): Database.Database {\n if (db) return db;\n\n ensureCmemDir();\n\n db = new Database(DB_PATH);\n db.pragma('journal_mode = WAL');\n\n // Load sqlite-vec extension\n sqliteVec.load(db);\n\n // Initialize schema\n initSchema(db);\n\n return db;\n}\n\n/**\n * Initialize database schema\n */\nfunction initSchema(database: Database.Database): void {\n // Migrations tracking table\n database.exec(`\n CREATE TABLE IF NOT EXISTS migrations (\n name TEXT PRIMARY KEY,\n applied_at TEXT NOT NULL\n );\n `);\n\n // Sessions table\n database.exec(`\n CREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n title TEXT NOT NULL,\n summary TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n message_count INTEGER DEFAULT 0,\n project_path TEXT,\n source_file TEXT,\n raw_data TEXT NOT NULL\n );\n `);\n\n // Add source_file column if it doesn't exist (migration)\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN source_file TEXT`);\n } catch {\n // Column already exists\n }\n\n // Add is_sidechain column if it doesn't exist (migration)\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN is_sidechain INTEGER DEFAULT 0`);\n } catch {\n // Column already exists\n }\n\n // Add is_automated column if it doesn't exist (migration)\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN is_automated INTEGER DEFAULT 0`);\n } catch {\n // Column already exists\n }\n\n // Add custom_title column if it doesn't exist (migration)\n // Used for user-renamed sessions\n try {\n database.exec(`ALTER TABLE sessions ADD COLUMN custom_title TEXT`);\n } catch {\n // Column already exists\n }\n\n // Messages table\n database.exec(`\n CREATE TABLE IF NOT EXISTS messages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n role TEXT NOT NULL CHECK (role IN ('user', 'assistant')),\n content TEXT NOT NULL,\n timestamp TEXT NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n `);\n\n // Embedding state tracking for incremental updates\n database.exec(`\n CREATE TABLE IF NOT EXISTS embedding_state (\n session_id TEXT PRIMARY KEY,\n content_length INTEGER NOT NULL,\n file_mtime TEXT,\n last_embedded_at TEXT NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(id) ON DELETE CASCADE\n );\n `);\n\n // Vector embeddings table (768 dimensions for nomic-embed-text)\n database.exec(`\n CREATE VIRTUAL TABLE IF NOT EXISTS session_embeddings USING vec0(\n session_id TEXT PRIMARY KEY,\n embedding FLOAT[${EMBEDDING_DIMENSIONS}]\n );\n `);\n\n // Favorites table for starred sessions\n database.exec(`\n CREATE TABLE IF NOT EXISTS favorites (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n type TEXT NOT NULL CHECK (type IN ('session', 'folder')),\n value TEXT NOT NULL,\n created_at TEXT NOT NULL,\n UNIQUE(type, value)\n );\n `);\n\n // Project order table for manual sorting\n database.exec(`\n CREATE TABLE IF NOT EXISTS project_order (\n path TEXT PRIMARY KEY,\n sort_order INTEGER NOT NULL,\n updated_at TEXT NOT NULL\n );\n `);\n\n // Indexes\n database.exec(`\n CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id);\n `);\n database.exec(`\n CREATE INDEX IF NOT EXISTS idx_sessions_updated ON sessions(updated_at DESC);\n `);\n database.exec(`\n CREATE INDEX IF NOT EXISTS idx_sessions_source ON sessions(source_file);\n `);\n database.exec(`\n CREATE INDEX IF NOT EXISTS idx_favorites_type ON favorites(type);\n `);\n\n // Run data migrations\n runMigrations(database);\n}\n\n/**\n * Run data migrations (separate from schema migrations)\n */\nfunction runMigrations(database: Database.Database): void {\n // Migration: Populate is_sidechain and is_automated from JSONL metadata\n const migrationName = 'populate_session_metadata_v1';\n\n const existing = database.prepare(\n 'SELECT 1 FROM migrations WHERE name = ?'\n ).get(migrationName);\n\n if (existing) return; // Already applied\n\n // Get all sessions with source files\n const sessions = database.prepare(`\n SELECT id, source_file FROM sessions WHERE source_file IS NOT NULL\n `).all() as { id: string; source_file: string }[];\n\n const updateStmt = database.prepare(`\n UPDATE sessions SET is_sidechain = ?, is_automated = ? WHERE id = ?\n `);\n\n const transaction = database.transaction(() => {\n for (const session of sessions) {\n if (!existsSync(session.source_file)) continue;\n\n try {\n const metadata = extractSessionMetadata(session.source_file);\n const isAutomated = metadata.isSidechain || metadata.isMeta;\n updateStmt.run(\n metadata.isSidechain ? 1 : 0,\n isAutomated ? 1 : 0,\n session.id\n );\n } catch {\n // Skip files that can't be parsed\n }\n }\n\n // Mark migration as complete\n database.prepare(\n 'INSERT INTO migrations (name, applied_at) VALUES (?, ?)'\n ).run(migrationName, new Date().toISOString());\n });\n\n transaction();\n}\n\n/**\n * Close the database connection\n */\nexport function closeDatabase(): void {\n if (db) {\n db.close();\n db = null;\n }\n}\n","import { homedir } from 'os';\nimport { join } from 'path';\nimport { mkdirSync, existsSync } from 'fs';\n\n// Data storage paths\nexport const CMEM_DIR = join(homedir(), '.cmem');\nexport const DB_PATH = join(CMEM_DIR, 'sessions.db');\nexport const MODELS_DIR = join(CMEM_DIR, 'models');\n\n// Claude Code paths\nexport const CLAUDE_DIR = join(homedir(), '.claude');\nexport const CLAUDE_PROJECTS_DIR = join(CLAUDE_DIR, 'projects');\nexport const CLAUDE_SESSIONS_DIR = join(CLAUDE_DIR, 'sessions');\n\n// Embedding model settings (transformers.js)\nexport const EMBEDDING_MODEL = 'nomic-ai/nomic-embed-text-v1.5';\nexport const EMBEDDING_DIMENSIONS = 768;\n\n// Text limits\nexport const MAX_EMBEDDING_CHARS = 8000;\nexport const MAX_MESSAGE_PREVIEW_CHARS = 500;\nexport const MAX_MESSAGES_FOR_CONTEXT = 20;\n\n// Ensure cmem directory exists\nexport function ensureCmemDir(): void {\n if (!existsSync(CMEM_DIR)) {\n mkdirSync(CMEM_DIR, { recursive: true });\n }\n}\n\n// Ensure models directory exists\nexport function ensureModelsDir(): void {\n ensureCmemDir();\n if (!existsSync(MODELS_DIR)) {\n mkdirSync(MODELS_DIR, { recursive: true });\n }\n}\n","import { readFileSync, readdirSync, existsSync, statSync } from 'fs';\nimport { join, basename, dirname } from 'path';\nimport { CLAUDE_PROJECTS_DIR, CLAUDE_SESSIONS_DIR } from '../utils/config.js';\n\nexport interface ParsedMessage {\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n}\n\nexport interface SessionMetadata {\n isSidechain: boolean;\n isMeta: boolean;\n}\n\n// Patterns that indicate automated/system sessions based on title\nconst AUTOMATED_TITLE_PATTERNS = [\n /^<[a-z-]+>/i, // XML-like tags: <project-instructions>, <command-message>, etc.\n /^<[A-Z_]+>/, // Uppercase tags: <SYSTEM>, <TOOL_USE>, etc.\n /^\\[system\\]/i, // [system] prefix\n /^\\/[a-z]+$/i, // Slash commands: /init, /help, etc.\n];\n\n/**\n * Check if a title/first message indicates an automated session\n */\nexport function isAutomatedByContent(title: string): boolean {\n for (const pattern of AUTOMATED_TITLE_PATTERNS) {\n if (pattern.test(title.trim())) {\n return true;\n }\n }\n return false;\n}\n\nexport interface ParsedSession {\n filePath: string;\n projectPath: string | null;\n messages: ParsedMessage[];\n rawData: string;\n modifiedAt: Date;\n agentMessages?: ParsedMessage[]; // Messages from subagents linked to this session\n}\n\ninterface SessionIndexEntry {\n sessionId: string;\n fullPath: string;\n fileMtime: number;\n firstPrompt: string;\n messageCount: number;\n created: string;\n modified: string;\n gitBranch?: string;\n projectPath: string;\n isSidechain: boolean;\n}\n\ninterface SessionsIndex {\n version: number;\n entries: SessionIndexEntry[];\n}\n\n/**\n * Extract session metadata from JSONL file (isSidechain, agentId, isMeta, etc.)\n * Only uses reliable JSONL metadata fields, not content-based heuristics\n */\nexport function extractSessionMetadata(filepath: string): SessionMetadata {\n const content = readFileSync(filepath, 'utf-8');\n\n const metadata: SessionMetadata = {\n isSidechain: false,\n isMeta: false,\n };\n\n // Find the first user message to check metadata\n for (const line of content.split('\\n')) {\n if (!line.trim()) continue;\n\n try {\n const parsed = JSON.parse(line);\n\n // Look for the first user message\n if (parsed.type === 'user' && parsed.message) {\n // Check isSidechain field (present in all Claude Code JSONL entries)\n // This is true for subagent/automated sessions\n if (parsed.isSidechain === true) {\n metadata.isSidechain = true;\n }\n\n // Check if this has an agentId (subagent session)\n if (parsed.agentId) {\n metadata.isSidechain = true;\n }\n\n // Check isMeta field - true for local command sessions\n if (parsed.isMeta === true) {\n metadata.isMeta = true;\n }\n\n break; // Only need first user message\n }\n } catch {\n // Skip malformed lines\n }\n }\n\n return metadata;\n}\n\n/**\n * Parse a Claude Code session JSONL file\n */\nexport function parseSessionFile(filepath: string): ParsedMessage[] {\n const content = readFileSync(filepath, 'utf-8');\n const messages: ParsedMessage[] = [];\n\n for (const line of content.split('\\n')) {\n if (!line.trim()) continue;\n\n try {\n const parsed = JSON.parse(line);\n\n // Handle different Claude Code JSONL formats\n if ((parsed.type === 'user' || parsed.type === 'assistant') && parsed.message) {\n // Claude Code format: type is 'user'/'assistant', message contains the actual content\n const msg = parsed.message;\n if (msg.role && msg.content) {\n const content = Array.isArray(msg.content)\n ? msg.content\n .filter((c: { type: string }) => c.type === 'text')\n .map((c: { text: string }) => c.text)\n .join('\\n')\n : typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content);\n\n if (content) {\n messages.push({\n role: msg.role as 'user' | 'assistant',\n content,\n timestamp: parsed.timestamp || new Date().toISOString(),\n });\n }\n }\n } else if (parsed.type === 'message' && parsed.role && parsed.content) {\n // Standard message format\n messages.push({\n role: parsed.role as 'user' | 'assistant',\n content: typeof parsed.content === 'string'\n ? parsed.content\n : JSON.stringify(parsed.content),\n timestamp: parsed.timestamp || new Date().toISOString(),\n });\n } else if (parsed.role && parsed.content && !parsed.type) {\n // Simplified format without type field\n messages.push({\n role: parsed.role as 'user' | 'assistant',\n content: typeof parsed.content === 'string'\n ? parsed.content\n : JSON.stringify(parsed.content),\n timestamp: parsed.timestamp || new Date().toISOString(),\n });\n }\n // Skip tool_use, tool_result, and other non-message entries\n } catch {\n // Skip malformed lines\n }\n }\n\n return messages;\n}\n\n/**\n * Find all Claude Code session files (excluding subagent sessions)\n */\nexport function findSessionFiles(): ParsedSession[] {\n const sessions: ParsedSession[] = [];\n\n // Search in ~/.claude/projects/<hash>/\n if (existsSync(CLAUDE_PROJECTS_DIR)) {\n const projectDirs = readdirSync(CLAUDE_PROJECTS_DIR);\n for (const projectDir of projectDirs) {\n const projectDirPath = join(CLAUDE_PROJECTS_DIR, projectDir);\n const stat = statSync(projectDirPath);\n if (!stat.isDirectory()) continue;\n\n // Try to read sessions-index.json for metadata\n const indexPath = join(projectDirPath, 'sessions-index.json');\n const sessionIndex = loadSessionIndex(indexPath);\n\n // Build a map of session IDs to their metadata\n const indexedSessions = new Map<string, SessionIndexEntry>();\n if (sessionIndex) {\n for (const entry of sessionIndex.entries) {\n indexedSessions.set(entry.sessionId, entry);\n }\n }\n\n // Only load .jsonl files directly in the project directory (not in subfolders)\n const entries = readdirSync(projectDirPath, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.isFile() || !entry.name.endsWith('.jsonl')) continue;\n\n const filePath = join(projectDirPath, entry.name);\n const sessionId = entry.name.replace('.jsonl', '');\n\n try {\n const session = loadSession(filePath);\n if (session) {\n // Use metadata from sessions-index.json if available\n const indexEntry = indexedSessions.get(sessionId);\n if (indexEntry) {\n session.projectPath = indexEntry.projectPath;\n }\n\n // Load any subagent messages for this session\n const agentMessages = loadSubagentMessages(projectDirPath, sessionId);\n if (agentMessages.length > 0) {\n session.agentMessages = agentMessages;\n }\n\n sessions.push(session);\n }\n } catch {\n // Skip unreadable files\n }\n }\n }\n }\n\n // Search in ~/.claude/sessions/ (no subagents here)\n if (existsSync(CLAUDE_SESSIONS_DIR)) {\n const sessionFiles = readdirSync(CLAUDE_SESSIONS_DIR).filter(f => f.endsWith('.jsonl'));\n for (const sessionFile of sessionFiles) {\n const filePath = join(CLAUDE_SESSIONS_DIR, sessionFile);\n try {\n const session = loadSession(filePath);\n if (session) {\n sessions.push(session);\n }\n } catch {\n // Skip unreadable files\n }\n }\n }\n\n // Sort by modification time (newest first)\n sessions.sort((a, b) => b.modifiedAt.getTime() - a.modifiedAt.getTime());\n\n return sessions;\n}\n\n/**\n * Load sessions-index.json if it exists\n */\nfunction loadSessionIndex(indexPath: string): SessionsIndex | null {\n if (!existsSync(indexPath)) return null;\n\n try {\n const content = readFileSync(indexPath, 'utf-8');\n return JSON.parse(content) as SessionsIndex;\n } catch {\n return null;\n }\n}\n\n/**\n * Load messages from all subagent sessions for a parent session\n */\nfunction loadSubagentMessages(projectDirPath: string, parentSessionId: string): ParsedMessage[] {\n const subagentsDir = join(projectDirPath, parentSessionId, 'subagents');\n if (!existsSync(subagentsDir)) return [];\n\n const messages: ParsedMessage[] = [];\n\n try {\n const agentFiles = readdirSync(subagentsDir).filter(f => f.endsWith('.jsonl'));\n for (const agentFile of agentFiles) {\n const agentPath = join(subagentsDir, agentFile);\n const agentMessages = parseSessionFile(agentPath);\n messages.push(...agentMessages);\n }\n } catch {\n // Ignore errors reading subagent files\n }\n\n return messages;\n}\n\n/**\n * Load a session from a file path\n */\nfunction loadSession(filePath: string): ParsedSession | null {\n const rawData = readFileSync(filePath, 'utf-8');\n const messages = parseSessionFile(filePath);\n\n // Skip empty sessions\n if (messages.length === 0) {\n return null;\n }\n\n const stats = statSync(filePath);\n\n return {\n filePath,\n projectPath: null,\n messages,\n rawData,\n modifiedAt: stats.mtime,\n };\n}\n\n\n/**\n * Get the most recent session file\n */\nexport function getMostRecentSession(): ParsedSession | null {\n const sessions = findSessionFiles();\n return sessions.length > 0 ? sessions[0] : null;\n}\n\n/**\n * Generate a summary from session messages\n */\nexport function generateSummary(messages: ParsedMessage[]): string {\n // Take first user message as the main topic\n const firstUserMessage = messages.find(m => m.role === 'user');\n if (!firstUserMessage) {\n return 'No user messages found';\n }\n\n // Truncate to reasonable summary length\n const summary = firstUserMessage.content.slice(0, 300);\n return summary.length < firstUserMessage.content.length ? summary + '...' : summary;\n}\n","import { getDatabase } from './index.js';\nimport { randomUUID } from 'crypto';\n\nexport interface Session {\n id: string;\n title: string;\n customTitle: string | null;\n summary: string | null;\n createdAt: string;\n updatedAt: string;\n messageCount: number;\n projectPath: string | null;\n sourceFile: string | null;\n rawData: string;\n isSidechain: boolean;\n isAutomated: boolean;\n}\n\nexport interface Message {\n id: number;\n sessionId: string;\n role: 'user' | 'assistant';\n content: string;\n timestamp: string;\n}\n\nexport interface SessionInput {\n title: string;\n summary?: string;\n projectPath?: string;\n sourceFile?: string;\n rawData: string;\n messages: Omit<Message, 'id' | 'sessionId'>[];\n isSidechain?: boolean;\n isAutomated?: boolean;\n}\n\nexport interface EmbeddingState {\n sessionId: string;\n contentLength: number;\n fileMtime: string | null;\n lastEmbeddedAt: string;\n}\n\n/**\n * Create a new session\n */\nexport function createSession(input: SessionInput): string {\n const db = getDatabase();\n const id = randomUUID();\n const now = new Date().toISOString();\n\n const insertSession = db.prepare(`\n INSERT INTO sessions (id, title, summary, created_at, updated_at, message_count, project_path, source_file, raw_data, is_sidechain, is_automated)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n const insertMessage = db.prepare(`\n INSERT INTO messages (session_id, role, content, timestamp)\n VALUES (?, ?, ?, ?)\n `);\n\n const transaction = db.transaction(() => {\n insertSession.run(\n id,\n input.title,\n input.summary || null,\n now,\n now,\n input.messages.length,\n input.projectPath || null,\n input.sourceFile || null,\n input.rawData,\n input.isSidechain ? 1 : 0,\n input.isAutomated ? 1 : 0\n );\n\n for (const msg of input.messages) {\n insertMessage.run(id, msg.role, msg.content, msg.timestamp);\n }\n });\n\n transaction();\n return id;\n}\n\n/**\n * Update an existing session with new data\n */\nexport function updateSession(id: string, input: Partial<SessionInput>): void {\n const db = getDatabase();\n const now = new Date().toISOString();\n\n const updates: string[] = ['updated_at = ?'];\n const values: unknown[] = [now];\n\n if (input.title !== undefined) {\n updates.push('title = ?');\n values.push(input.title);\n }\n if (input.summary !== undefined) {\n updates.push('summary = ?');\n values.push(input.summary);\n }\n if (input.rawData !== undefined) {\n updates.push('raw_data = ?');\n values.push(input.rawData);\n }\n if (input.messages !== undefined) {\n updates.push('message_count = ?');\n values.push(input.messages.length);\n }\n if (input.isSidechain !== undefined) {\n updates.push('is_sidechain = ?');\n values.push(input.isSidechain ? 1 : 0);\n }\n if (input.isAutomated !== undefined) {\n updates.push('is_automated = ?');\n values.push(input.isAutomated ? 1 : 0);\n }\n if (input.projectPath !== undefined) {\n updates.push('project_path = ?');\n values.push(input.projectPath);\n }\n\n values.push(id);\n\n const transaction = db.transaction(() => {\n db.prepare(`UPDATE sessions SET ${updates.join(', ')} WHERE id = ?`).run(...values);\n\n // If messages provided, replace them\n if (input.messages !== undefined) {\n db.prepare('DELETE FROM messages WHERE session_id = ?').run(id);\n const insertMessage = db.prepare(`\n INSERT INTO messages (session_id, role, content, timestamp)\n VALUES (?, ?, ?, ?)\n `);\n for (const msg of input.messages) {\n insertMessage.run(id, msg.role, msg.content, msg.timestamp);\n }\n }\n });\n\n transaction();\n}\n\n/**\n * Get a session by ID\n */\nexport function getSession(id: string): Session | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions WHERE id = ?\n `).get(id) as SessionRow | undefined;\n\n if (!row) return null;\n return mapSessionRow(row);\n}\n\n/**\n * Get a session by ID prefix (for partial ID matching)\n */\nexport function getSessionByIdPrefix(idPrefix: string): Session | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions WHERE id LIKE ? || '%'\n LIMIT 1\n `).get(idPrefix) as SessionRow | undefined;\n\n if (!row) return null;\n return mapSessionRow(row);\n}\n\n/**\n * Get a session by source file path\n */\nexport function getSessionBySourceFile(sourceFile: string): Session | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions WHERE source_file = ?\n `).get(sourceFile) as SessionRow | undefined;\n\n if (!row) return null;\n return mapSessionRow(row);\n}\n\n/**\n * Get messages for a session\n */\nexport function getSessionMessages(sessionId: string): Message[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT id, session_id as sessionId, role, content, timestamp\n FROM messages WHERE session_id = ?\n ORDER BY timestamp ASC\n `).all(sessionId) as Message[];\n\n return rows;\n}\n\ntype SessionRow = {\n isSidechain: number;\n isAutomated: number;\n customTitle: string | null;\n} & Omit<Session, 'isSidechain' | 'isAutomated' | 'customTitle'>;\n\nfunction mapSessionRow(row: SessionRow): Session {\n return {\n ...row,\n customTitle: row.customTitle,\n isSidechain: row.isSidechain === 1,\n isAutomated: row.isAutomated === 1,\n };\n}\n\n/**\n * List all sessions ordered by updated_at desc\n */\nexport function listSessions(limit = 100): Session[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions\n ORDER BY updated_at DESC\n LIMIT ?\n `).all(limit) as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n\n/**\n * Check if a session appears to be an automated/system session rather than a real human conversation\n * Uses metadata stored in the database (isSidechain, isAutomated) which was extracted from the JSONL\n */\nexport function isAutomatedSession(session: Session): boolean {\n // Use the metadata fields from the database\n if (session.isSidechain || session.isAutomated) {\n return true;\n }\n\n return false;\n}\n\n/**\n * List human sessions (filters out automated/system sessions)\n * Filters directly in SQL for better performance\n */\nexport function listHumanSessions(limit = 100): Session[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions\n WHERE is_sidechain = 0 AND is_automated = 0\n ORDER BY updated_at DESC\n LIMIT ?\n `).all(limit) as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n\n/**\n * List human sessions filtered by project path\n * Uses LIKE to match sessions where the project_path starts with the given path\n */\nexport function listHumanSessionsByProject(projectPath: string, limit = 100): Session[] {\n const db = getDatabase();\n // Use LIKE to match sessions in this folder or subfolders\n const rows = db.prepare(`\n SELECT id, title, custom_title as customTitle, summary,\n created_at as createdAt, updated_at as updatedAt,\n message_count as messageCount, project_path as projectPath,\n source_file as sourceFile, raw_data as rawData,\n is_sidechain as isSidechain, is_automated as isAutomated\n FROM sessions\n WHERE is_sidechain = 0 AND is_automated = 0\n AND project_path LIKE ? || '%'\n ORDER BY updated_at DESC\n LIMIT ?\n `).all(projectPath, limit) as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n\n/**\n * Delete a session\n */\nexport function deleteSession(id: string): boolean {\n const db = getDatabase();\n\n const transaction = db.transaction(() => {\n // Delete from vector table first\n db.prepare('DELETE FROM session_embeddings WHERE session_id = ?').run(id);\n // Delete embedding state\n db.prepare('DELETE FROM embedding_state WHERE session_id = ?').run(id);\n // Delete messages (cascade should handle this, but explicit is safer)\n db.prepare('DELETE FROM messages WHERE session_id = ?').run(id);\n // Delete session\n const result = db.prepare('DELETE FROM sessions WHERE id = ?').run(id);\n return result.changes > 0;\n });\n\n return transaction();\n}\n\n/**\n * Update session summary\n */\nexport function updateSessionSummary(id: string, summary: string): void {\n const db = getDatabase();\n db.prepare(`\n UPDATE sessions SET summary = ?, updated_at = ? WHERE id = ?\n `).run(summary, new Date().toISOString(), id);\n}\n\n/**\n * Rename a session (set custom title)\n */\nexport function renameSession(id: string, customTitle: string | null): void {\n const db = getDatabase();\n db.prepare(`\n UPDATE sessions SET custom_title = ?, updated_at = ? WHERE id = ?\n `).run(customTitle, new Date().toISOString(), id);\n}\n\n/**\n * Get storage statistics\n */\nexport function getStats(): {\n sessionCount: number;\n messageCount: number;\n embeddingCount: number;\n} {\n const db = getDatabase();\n\n const sessionCount = (db.prepare('SELECT COUNT(*) as count FROM sessions').get() as { count: number }).count;\n const messageCount = (db.prepare('SELECT COUNT(*) as count FROM messages').get() as { count: number }).count;\n const embeddingCount = (db.prepare('SELECT COUNT(*) as count FROM session_embeddings').get() as { count: number }).count;\n\n return { sessionCount, messageCount, embeddingCount };\n}\n\n/**\n * Check if a session exists by its raw data hash (to avoid duplicates)\n */\nexport function sessionExists(rawData: string): boolean {\n const db = getDatabase();\n const row = db.prepare('SELECT 1 FROM sessions WHERE raw_data = ? LIMIT 1').get(rawData);\n return !!row;\n}\n\n/**\n * Get embedding state for a session\n */\nexport function getEmbeddingState(sessionId: string): EmbeddingState | null {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT session_id as sessionId, content_length as contentLength,\n file_mtime as fileMtime, last_embedded_at as lastEmbeddedAt\n FROM embedding_state WHERE session_id = ?\n `).get(sessionId) as EmbeddingState | undefined;\n\n return row || null;\n}\n\n/**\n * Update embedding state for a session\n */\nexport function updateEmbeddingState(\n sessionId: string,\n contentLength: number,\n fileMtime?: string\n): void {\n const db = getDatabase();\n const now = new Date().toISOString();\n\n db.prepare(`\n INSERT OR REPLACE INTO embedding_state (session_id, content_length, file_mtime, last_embedded_at)\n VALUES (?, ?, ?, ?)\n `).run(sessionId, contentLength, fileMtime || null, now);\n}\n\n/**\n * Check if session needs re-embedding based on content growth\n * Returns true if content has grown by more than threshold chars\n */\nexport function needsReembedding(sessionId: string, currentContentLength: number, threshold = 500): boolean {\n const state = getEmbeddingState(sessionId);\n if (!state) return true; // Never embedded\n return currentContentLength - state.contentLength >= threshold;\n}\n\n/**\n * Get all sessions that need embedding\n */\nexport function getSessionsNeedingEmbedding(): Session[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT s.id, s.title, s.custom_title as customTitle, s.summary,\n s.created_at as createdAt, s.updated_at as updatedAt,\n s.message_count as messageCount, s.project_path as projectPath,\n s.source_file as sourceFile, s.raw_data as rawData,\n s.is_sidechain as isSidechain, s.is_automated as isAutomated\n FROM sessions s\n LEFT JOIN embedding_state e ON s.id = e.session_id\n WHERE e.session_id IS NULL\n ORDER BY s.updated_at DESC\n `).all() as SessionRow[];\n\n return rows.map(mapSessionRow);\n}\n\n// ==================== FAVORITES ====================\n\nexport type FavoriteType = 'session' | 'folder';\n\nexport interface Favorite {\n id: number;\n type: FavoriteType;\n value: string;\n createdAt: string;\n}\n\n/**\n * Add a favorite (session or folder)\n */\nexport function addFavorite(type: FavoriteType, value: string): boolean {\n const db = getDatabase();\n try {\n db.prepare(`\n INSERT OR IGNORE INTO favorites (type, value, created_at)\n VALUES (?, ?, ?)\n `).run(type, value, new Date().toISOString());\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Remove a favorite\n */\nexport function removeFavorite(type: FavoriteType, value: string): boolean {\n const db = getDatabase();\n const result = db.prepare(`\n DELETE FROM favorites WHERE type = ? AND value = ?\n `).run(type, value);\n return result.changes > 0;\n}\n\n/**\n * Toggle a favorite (add if not exists, remove if exists)\n */\nexport function toggleFavorite(type: FavoriteType, value: string): boolean {\n if (isFavorite(type, value)) {\n removeFavorite(type, value);\n return false; // No longer a favorite\n } else {\n addFavorite(type, value);\n return true; // Now a favorite\n }\n}\n\n/**\n * Check if something is a favorite\n */\nexport function isFavorite(type: FavoriteType, value: string): boolean {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT 1 FROM favorites WHERE type = ? AND value = ?\n `).get(type, value);\n return !!row;\n}\n\n/**\n * Get all favorites of a type\n */\nexport function getFavorites(type: FavoriteType): Favorite[] {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT id, type, value, created_at as createdAt\n FROM favorites\n WHERE type = ?\n ORDER BY created_at DESC\n `).all(type) as Favorite[];\n return rows;\n}\n\n/**\n * Get all favorite session IDs\n */\nexport function getFavoriteSessionIds(): Set<string> {\n const favorites = getFavorites('session');\n return new Set(favorites.map(f => f.value));\n}\n\n/**\n * Get all favorite folder paths\n */\nexport function getFavoriteFolderPaths(): Set<string> {\n const favorites = getFavorites('folder');\n return new Set(favorites.map(f => f.value));\n}\n\n/**\n * Check if there are any favorite folders\n */\nexport function hasFavoriteFolders(): boolean {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT 1 FROM favorites WHERE type = 'folder' LIMIT 1\n `).get();\n return !!row;\n}\n\n/**\n * Check if there are any favorite sessions\n */\nexport function hasFavoriteSessions(): boolean {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT 1 FROM favorites WHERE type = 'session' LIMIT 1\n `).get();\n return !!row;\n}\n\n// ==================== PROJECT ORDER ====================\n\nexport interface ProjectOrder {\n path: string;\n sortOrder: number;\n updatedAt: string;\n}\n\n/**\n * Get the sort order for all projects\n * Returns a map of project path -> sort order\n */\nexport function getProjectOrders(): Map<string, number> {\n const db = getDatabase();\n const rows = db.prepare(`\n SELECT path, sort_order as sortOrder\n FROM project_order\n ORDER BY sort_order ASC\n `).all() as { path: string; sortOrder: number }[];\n\n const map = new Map<string, number>();\n for (const row of rows) {\n map.set(row.path, row.sortOrder);\n }\n return map;\n}\n\n/**\n * Set the sort order for a project\n */\nexport function setProjectOrder(path: string, sortOrder: number): void {\n const db = getDatabase();\n const now = new Date().toISOString();\n\n db.prepare(`\n INSERT OR REPLACE INTO project_order (path, sort_order, updated_at)\n VALUES (?, ?, ?)\n `).run(path, sortOrder, now);\n}\n\n/**\n * Update project orders for multiple projects at once (for reordering)\n */\nexport function updateProjectOrders(orders: { path: string; sortOrder: number }[]): void {\n const db = getDatabase();\n const now = new Date().toISOString();\n\n const stmt = db.prepare(`\n INSERT OR REPLACE INTO project_order (path, sort_order, updated_at)\n VALUES (?, ?, ?)\n `);\n\n const transaction = db.transaction(() => {\n for (const order of orders) {\n stmt.run(order.path, order.sortOrder, now);\n }\n });\n\n transaction();\n}\n\n/**\n * Remove project order (revert to default sorting for this project)\n */\nexport function removeProjectOrder(path: string): void {\n const db = getDatabase();\n db.prepare('DELETE FROM project_order WHERE path = ?').run(path);\n}\n\n/**\n * Check if any custom project orders exist\n */\nexport function hasCustomProjectOrder(): boolean {\n const db = getDatabase();\n const row = db.prepare(`\n SELECT 1 FROM project_order LIMIT 1\n `).get();\n return !!row;\n}\n","import { getDatabase } from './index.js';\nimport type { Session } from './sessions.js';\n\n/**\n * Store an embedding for a session\n */\nexport function storeEmbedding(sessionId: string, embedding: number[]): void {\n const db = getDatabase();\n\n // sqlite-vec expects JSON array format\n const embeddingJson = JSON.stringify(embedding);\n\n db.prepare(`\n INSERT OR REPLACE INTO session_embeddings (session_id, embedding)\n VALUES (?, ?)\n `).run(sessionId, embeddingJson);\n}\n\n/**\n * Search for similar sessions using vector similarity\n */\nexport function searchSimilar(queryEmbedding: number[], limit = 10): Array<{ sessionId: string; distance: number }> {\n const db = getDatabase();\n\n const embeddingJson = JSON.stringify(queryEmbedding);\n\n // Use vec_distance_L2 for Euclidean distance (lower = more similar)\n const rows = db.prepare(`\n SELECT session_id as sessionId, vec_distance_L2(embedding, ?) as distance\n FROM session_embeddings\n ORDER BY distance ASC\n LIMIT ?\n `).all(embeddingJson, limit) as Array<{ sessionId: string; distance: number }>;\n\n return rows;\n}\n\n/**\n * Search sessions and return full session objects\n */\nexport function searchSessions(queryEmbedding: number[], limit = 10): Session[] {\n const db = getDatabase();\n\n const embeddingJson = JSON.stringify(queryEmbedding);\n\n const rows = db.prepare(`\n SELECT s.id, s.title, s.summary, s.created_at as createdAt, s.updated_at as updatedAt,\n s.message_count as messageCount, s.project_path as projectPath, s.raw_data as rawData,\n vec_distance_L2(e.embedding, ?) as distance\n FROM session_embeddings e\n JOIN sessions s ON e.session_id = s.id\n ORDER BY distance ASC\n LIMIT ?\n `).all(embeddingJson, limit) as Session[];\n\n return rows;\n}\n\n/**\n * Delete embedding for a session\n */\nexport function deleteEmbedding(sessionId: string): void {\n const db = getDatabase();\n db.prepare('DELETE FROM session_embeddings WHERE session_id = ?').run(sessionId);\n}\n\n/**\n * Check if session has an embedding\n */\nexport function hasEmbedding(sessionId: string): boolean {\n const db = getDatabase();\n const row = db.prepare('SELECT 1 FROM session_embeddings WHERE session_id = ? LIMIT 1').get(sessionId);\n return !!row;\n}\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport {\n EMBEDDING_MODEL,\n MODELS_DIR,\n MAX_EMBEDDING_CHARS,\n MAX_MESSAGE_PREVIEW_CHARS,\n ensureModelsDir,\n} from '../utils/config.js';\n\n// Lazy load transformers.js\nlet transformersModule: typeof import('@xenova/transformers') | null = null;\nlet pipeline: any = null;\nlet initialized = false;\n\nasync function getTransformers() {\n if (!transformersModule) {\n transformersModule = await import('@xenova/transformers');\n }\n return transformersModule;\n}\n\nexport interface InitProgress {\n status: 'checking' | 'downloading' | 'loading' | 'ready';\n file?: string;\n progress?: number;\n}\n\n/**\n * Check if the model is already cached locally\n */\nexport function isModelCached(): boolean {\n // Transformers.js stores models at models/org/model-name/\n const modelCachePath = join(MODELS_DIR, EMBEDDING_MODEL);\n return existsSync(modelCachePath);\n}\n\n/**\n * Initialize the embedding pipeline\n * Downloads the model on first use with progress callback\n */\nexport async function initializeEmbeddings(\n onProgress?: (progress: InitProgress) => void\n): Promise<void> {\n if (initialized && pipeline) {\n return;\n }\n\n ensureModelsDir();\n\n const { pipeline: createPipeline, env } = await getTransformers();\n\n // Configure cache directory\n env.cacheDir = MODELS_DIR;\n\n // Check if model is cached\n const cached = isModelCached();\n if (cached) {\n env.allowRemoteModels = false; // Use local cache only\n onProgress?.({ status: 'loading' });\n } else {\n onProgress?.({ status: 'downloading' });\n }\n\n // Create the pipeline with progress callback\n pipeline = await createPipeline('feature-extraction', EMBEDDING_MODEL, {\n progress_callback: onProgress\n ? (progress: { status: string; file?: string; progress?: number }) => {\n if (progress.status === 'progress' && progress.file && progress.progress !== undefined) {\n onProgress({\n status: 'downloading',\n file: progress.file,\n progress: progress.progress,\n });\n }\n }\n : undefined,\n });\n\n initialized = true;\n onProgress?.({ status: 'ready' });\n}\n\n/**\n * Check if embeddings are ready to use\n */\nexport function isReady(): boolean {\n return initialized && pipeline !== null;\n}\n\n/**\n * Generate an embedding vector for text\n */\nexport async function getEmbedding(text: string): Promise<number[]> {\n // Initialize if needed (will use cached model if available)\n if (!initialized) {\n await initializeEmbeddings();\n }\n\n // Truncate to max chars\n const truncated = text.slice(0, MAX_EMBEDDING_CHARS);\n\n // Generate embedding\n const output = await pipeline(truncated, {\n pooling: 'mean',\n normalize: true,\n });\n\n // Convert to regular array\n return Array.from(output.data);\n}\n\n/**\n * Create embedding text from session data\n * Combines title, summary, and key messages for semantic search\n */\nexport function createEmbeddingText(\n title: string,\n summary: string | undefined,\n messages: Array<{ role: string; content: string }>\n): string {\n const parts: string[] = [];\n\n // Add title\n parts.push(`Title: ${title}`);\n\n // Add summary if available\n if (summary) {\n parts.push(`Summary: ${summary}`);\n }\n\n // Add first 5 user messages (truncated)\n const userMessages = messages\n .filter((m) => m.role === 'user')\n .slice(0, 5)\n .map((m) => m.content.slice(0, MAX_MESSAGE_PREVIEW_CHARS));\n\n if (userMessages.length > 0) {\n parts.push('User messages:');\n parts.push(...userMessages);\n }\n\n // Add first 3 assistant responses (truncated) for context\n const assistantMessages = messages\n .filter((m) => m.role === 'assistant')\n .slice(0, 3)\n .map((m) => m.content.slice(0, MAX_MESSAGE_PREVIEW_CHARS));\n\n if (assistantMessages.length > 0) {\n parts.push('Assistant responses:');\n parts.push(...assistantMessages);\n }\n\n return parts.join('\\n\\n');\n}\n","import chalk from 'chalk';\nimport { findSessionFiles, getMostRecentSession, generateSummary } from '../parser/index.js';\nimport { createSession, sessionExists } from '../db/sessions.js';\nimport { storeEmbedding } from '../db/vectors.js';\nimport { getEmbedding, createEmbeddingText, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { generateTitle } from '../utils/format.js';\n\ninterface SaveOptions {\n title?: string;\n latest?: boolean;\n}\n\nexport async function saveCommand(options: SaveOptions): Promise<void> {\n console.log(chalk.cyan('Scanning for Claude Code sessions...'));\n\n // Initialize embeddings (downloads model if needed)\n let embeddingsReady = isReady();\n if (!embeddingsReady) {\n console.log(chalk.dim('Initializing embedding model...'));\n try {\n await initializeEmbeddings();\n embeddingsReady = true;\n } catch (err) {\n console.log(chalk.yellow('Warning: Could not initialize embeddings.'));\n console.log(chalk.yellow('Semantic search will not be available.'));\n }\n }\n\n // Find sessions\n const sessions = findSessionFiles();\n\n if (sessions.length === 0) {\n console.log(chalk.red('No Claude Code sessions found.'));\n console.log(chalk.dim('Looking in:'));\n console.log(chalk.dim(' ~/.claude/projects/'));\n console.log(chalk.dim(' ~/.claude/sessions/'));\n console.log(chalk.dim('\\nUse Claude Code first, then run: cmem save --latest'));\n return;\n }\n\n console.log(chalk.green(`Found ${sessions.length} session(s)`));\n\n // Select session to save\n let sessionToSave = options.latest ? getMostRecentSession() : sessions[0];\n\n if (!sessionToSave) {\n console.log(chalk.red('No valid session found.'));\n return;\n }\n\n // Check for duplicates\n if (sessionExists(sessionToSave.rawData)) {\n console.log(chalk.yellow('This session has already been saved.'));\n return;\n }\n\n // Generate title from first user message if not provided\n const firstUserMsg = sessionToSave.messages.find(m => m.role === 'user');\n const title = options.title || (firstUserMsg ? generateTitle(firstUserMsg.content) : 'Untitled Session');\n\n // Generate summary\n const summary = generateSummary(sessionToSave.messages);\n\n console.log(chalk.dim(`Title: ${title}`));\n console.log(chalk.dim(`Messages: ${sessionToSave.messages.length}`));\n console.log(chalk.dim(`Project: ${sessionToSave.projectPath || 'Unknown'}`));\n\n // Create session in database\n const sessionId = createSession({\n title,\n summary,\n projectPath: sessionToSave.projectPath || undefined,\n rawData: sessionToSave.rawData,\n messages: sessionToSave.messages,\n });\n\n console.log(chalk.green(`Session saved with ID: ${sessionId.slice(0, 8)}`));\n\n // Generate and store embedding if ready\n if (embeddingsReady) {\n console.log(chalk.dim('Generating embedding...'));\n try {\n const embeddingText = createEmbeddingText(title, summary, sessionToSave.messages);\n const embedding = await getEmbedding(embeddingText);\n storeEmbedding(sessionId, embedding);\n console.log(chalk.green('Embedding stored for semantic search.'));\n } catch (err) {\n console.log(chalk.yellow('Failed to generate embedding. Semantic search may not work for this session.'));\n }\n }\n\n console.log(chalk.green('\\nSession saved successfully!'));\n}\n","import chalk from 'chalk';\nimport { listHumanSessions, listSessions } from '../db/sessions.js';\nimport { formatTimeAgo, shortId, truncate } from '../utils/format.js';\n\ninterface ListOptions {\n all?: boolean;\n}\n\nexport async function listCommand(options: ListOptions = {}): Promise<void> {\n // Use listHumanSessions by default, listSessions with --all flag\n const sessions = options.all ? listSessions() : listHumanSessions();\n\n if (sessions.length === 0) {\n console.log(chalk.yellow('No saved sessions.'));\n console.log(chalk.dim('Run: cmem save --latest'));\n return;\n }\n\n console.log(chalk.cyan(`Saved Sessions (${sessions.length})\\n`));\n\n // Table header\n console.log(\n chalk.dim(\n 'ID'.padEnd(10) +\n 'Title'.padEnd(40) +\n 'Msgs'.padEnd(6) +\n 'Updated'.padEnd(10) +\n 'Project'\n )\n );\n console.log(chalk.dim('─'.repeat(90)));\n\n for (const session of sessions) {\n const id = shortId(session.id);\n const title = truncate(session.title, 38);\n const msgs = String(session.messageCount).padStart(4);\n const updated = formatTimeAgo(session.updatedAt);\n const project = session.projectPath ? truncate(session.projectPath, 25) : chalk.dim('—');\n\n console.log(\n chalk.white(id.padEnd(10)) +\n title.padEnd(40) +\n chalk.dim(msgs.padEnd(6)) +\n chalk.dim(updated.padEnd(10)) +\n chalk.dim(project)\n );\n }\n\n console.log(chalk.dim('\\n─'.repeat(90)));\n console.log(chalk.dim('Use: cmem restore <id> to restore a session'));\n}\n","import chalk from 'chalk';\nimport { searchSessions } from '../db/vectors.js';\nimport { getEmbedding, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { formatTimeAgo, shortId, truncate } from '../utils/format.js';\n\nexport async function searchCommand(query: string): Promise<void> {\n console.log(chalk.cyan(`Searching for: \"${query}\"...\\n`));\n\n // Initialize embeddings (downloads model if needed)\n if (!isReady()) {\n console.log(chalk.dim('Initializing embedding model...'));\n try {\n await initializeEmbeddings((progress) => {\n if (progress.status === 'downloading' && progress.progress !== undefined) {\n process.stdout.write(`\\r${chalk.dim(`Downloading model... ${Math.round(progress.progress)}%`)}`);\n }\n });\n console.log(chalk.green('\\r✓ Model ready \\n'));\n } catch (err) {\n console.log(chalk.red('Failed to initialize embedding model.'));\n console.log(chalk.dim(String(err)));\n return;\n }\n }\n\n try {\n // Generate query embedding\n const queryEmbedding = await getEmbedding(query);\n\n // Search for similar sessions\n const results = searchSessions(queryEmbedding, 10);\n\n if (results.length === 0) {\n console.log(chalk.yellow('No matching sessions found.'));\n console.log(chalk.dim('Try a different search query or save more sessions.'));\n return;\n }\n\n console.log(chalk.green(`Found ${results.length} matching session(s)\\n`));\n\n // Table header\n console.log(\n chalk.dim(\n 'ID'.padEnd(10) +\n 'Title'.padEnd(40) +\n 'Msgs'.padEnd(6) +\n 'Updated'\n )\n );\n console.log(chalk.dim('─'.repeat(70)));\n\n for (const session of results) {\n const id = shortId(session.id);\n const title = truncate(session.title, 38);\n const msgs = String(session.messageCount).padStart(4);\n const updated = formatTimeAgo(session.updatedAt);\n\n console.log(\n chalk.white(id.padEnd(10)) +\n title.padEnd(40) +\n chalk.dim(msgs.padEnd(6)) +\n chalk.dim(updated)\n );\n\n // Show summary snippet\n if (session.summary) {\n console.log(chalk.dim(' ' + truncate(session.summary, 65)));\n }\n }\n\n console.log(chalk.dim('\\n─'.repeat(70)));\n console.log(chalk.dim('Use: cmem restore <id> to restore a session'));\n } catch (err) {\n console.log(chalk.red('Search failed.'));\n console.log(chalk.dim(String(err)));\n }\n}\n","import chalk from 'chalk';\nimport { getSession, getSessionMessages, listSessions } from '../db/sessions.js';\nimport { copyToClipboard } from '../utils/clipboard.js';\nimport { MAX_MESSAGES_FOR_CONTEXT } from '../utils/config.js';\n\ninterface RestoreOptions {\n copy?: boolean;\n format?: 'context' | 'json' | 'markdown';\n}\n\nexport async function restoreCommand(id: string, options: RestoreOptions): Promise<void> {\n // Support partial ID matching\n let session = getSession(id);\n\n if (!session) {\n // Try partial match\n const sessions = listSessions();\n const match = sessions.find(s => s.id.startsWith(id));\n if (match) {\n session = match;\n }\n }\n\n if (!session) {\n console.log(chalk.red(`Session not found: ${id}`));\n console.log(chalk.dim('Run: cmem list to see available sessions'));\n return;\n }\n\n const messages = getSessionMessages(session.id);\n const format = options.format || 'context';\n\n let output: string;\n\n switch (format) {\n case 'json':\n output = formatAsJson(session, messages);\n break;\n case 'markdown':\n output = formatAsMarkdown(session, messages);\n break;\n case 'context':\n default:\n output = formatAsContext(session, messages);\n break;\n }\n\n if (options.copy) {\n await copyToClipboard(output);\n console.log(chalk.green('Session context copied to clipboard!'));\n console.log(chalk.dim(`Session: ${session.title}`));\n console.log(chalk.dim(`Messages: ${messages.length}`));\n } else {\n console.log(output);\n }\n}\n\nfunction formatAsContext(\n session: { title: string; projectPath: string | null },\n messages: Array<{ role: string; content: string }>\n): string {\n const lines: string[] = [];\n\n lines.push('# Previous Session Context');\n lines.push('');\n lines.push(`**Session:** ${session.title}`);\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n }\n lines.push(`**Messages:** ${messages.length} total (showing last ${Math.min(messages.length, MAX_MESSAGES_FOR_CONTEXT)})`);\n lines.push('');\n lines.push('---');\n lines.push('');\n lines.push('## Conversation History');\n lines.push('');\n\n // Show last N messages\n const recentMessages = messages.slice(-MAX_MESSAGES_FOR_CONTEXT);\n\n for (const msg of recentMessages) {\n const roleLabel = msg.role === 'user' ? '**User:**' : '**Claude:**';\n lines.push(roleLabel);\n lines.push(msg.content);\n lines.push('');\n }\n\n lines.push('---');\n lines.push('');\n lines.push('*Continue this conversation in Claude Code*');\n\n return lines.join('\\n');\n}\n\nfunction formatAsMarkdown(\n session: { title: string; projectPath: string | null; summary: string | null },\n messages: Array<{ role: string; content: string; timestamp: string }>\n): string {\n const lines: string[] = [];\n\n lines.push(`# ${session.title}`);\n lines.push('');\n\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n lines.push('');\n }\n\n if (session.summary) {\n lines.push('## Summary');\n lines.push(session.summary);\n lines.push('');\n }\n\n lines.push('## Conversation');\n lines.push('');\n\n for (const msg of messages) {\n lines.push(`### ${msg.role === 'user' ? 'User' : 'Claude'}`);\n lines.push(`*${msg.timestamp}*`);\n lines.push('');\n lines.push(msg.content);\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction formatAsJson(\n session: { id: string; title: string; projectPath: string | null; summary: string | null; createdAt: string; updatedAt: string },\n messages: Array<{ role: string; content: string; timestamp: string }>\n): string {\n return JSON.stringify(\n {\n session: {\n id: session.id,\n title: session.title,\n projectPath: session.projectPath,\n summary: session.summary,\n createdAt: session.createdAt,\n updatedAt: session.updatedAt,\n },\n messages: messages.map(m => ({\n role: m.role,\n content: m.content,\n timestamp: m.timestamp,\n })),\n },\n null,\n 2\n );\n}\n","import clipboard from 'clipboardy';\n\n/**\n * Copy text to clipboard\n */\nexport async function copyToClipboard(text: string): Promise<void> {\n await clipboard.write(text);\n}\n\n/**\n * Read text from clipboard\n */\nexport async function readFromClipboard(): Promise<string> {\n return await clipboard.read();\n}\n","import chalk from 'chalk';\nimport { getSession, deleteSession, listSessions } from '../db/sessions.js';\nimport { shortId } from '../utils/format.js';\n\nexport async function deleteCommand(id: string): Promise<void> {\n // Support partial ID matching\n let session = getSession(id);\n\n if (!session) {\n // Try partial match\n const sessions = listSessions();\n const match = sessions.find(s => s.id.startsWith(id));\n if (match) {\n session = match;\n }\n }\n\n if (!session) {\n console.log(chalk.red(`Session not found: ${id}`));\n console.log(chalk.dim('Run: cmem list to see available sessions'));\n return;\n }\n\n const deleted = deleteSession(session.id);\n\n if (deleted) {\n console.log(chalk.green(`Deleted session: ${shortId(session.id)} - ${session.title}`));\n } else {\n console.log(chalk.red('Failed to delete session.'));\n }\n}\n","import chalk from 'chalk';\nimport { statSync, existsSync } from 'fs';\nimport { getStats } from '../db/sessions.js';\nimport { isModelCached } from '../embeddings/index.js';\nimport { DB_PATH, CMEM_DIR, EMBEDDING_MODEL, MODELS_DIR } from '../utils/config.js';\nimport { formatBytes, formatNumber } from '../utils/format.js';\n\nexport async function statsCommand(): Promise<void> {\n console.log(chalk.cyan('cmem Storage Statistics\\n'));\n\n // Database stats\n const stats = getStats();\n\n console.log(chalk.white('Database:'));\n console.log(` Sessions: ${formatNumber(stats.sessionCount)}`);\n console.log(` Messages: ${formatNumber(stats.messageCount)}`);\n console.log(` Embeddings: ${formatNumber(stats.embeddingCount)}`);\n\n // Storage size\n if (existsSync(DB_PATH)) {\n const dbStats = statSync(DB_PATH);\n console.log(` DB Size: ${formatBytes(dbStats.size)}`);\n }\n\n console.log(` Location: ${CMEM_DIR}`);\n\n // Embedding model status\n console.log('');\n console.log(chalk.white('Embeddings:'));\n\n const modelCached = isModelCached();\n if (modelCached) {\n console.log(` Model: ${chalk.green(EMBEDDING_MODEL)}`);\n console.log(` Location: ${MODELS_DIR}`);\n } else {\n console.log(` Model: ${chalk.yellow('Not downloaded')}`);\n console.log(chalk.dim(' Run cmem setup to download the embedding model'));\n }\n\n // Coverage\n console.log('');\n console.log(chalk.white('Coverage:'));\n const coveragePercent = stats.sessionCount > 0\n ? Math.round((stats.embeddingCount / stats.sessionCount) * 100)\n : 0;\n console.log(` Semantic: ${coveragePercent}% of sessions have embeddings`);\n\n if (coveragePercent < 100 && stats.sessionCount > 0) {\n console.log(chalk.dim(' Run cmem watch to generate missing embeddings'));\n }\n}\n","import chalk from 'chalk';\nimport chokidar from 'chokidar';\nimport { statSync, existsSync, readFileSync, readdirSync } from 'fs';\nimport { join, dirname, basename } from 'path';\nimport { CLAUDE_DIR } from '../utils/config.js';\nimport { parseSessionFile, generateSummary, ParsedMessage, extractSessionMetadata, isAutomatedByContent } from '../parser/index.js';\nimport {\n createSession,\n getSessionBySourceFile,\n updateSession,\n needsReembedding,\n updateEmbeddingState,\n getStats,\n} from '../db/sessions.js';\nimport { storeEmbedding } from '../db/vectors.js';\nimport { getEmbedding, createEmbeddingText, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { generateTitle } from '../utils/format.js';\n\n// Spinner animation frames\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nclass Spinner {\n private interval: NodeJS.Timeout | null = null;\n private frameIndex = 0;\n private message: string;\n\n constructor(message: string) {\n this.message = message;\n }\n\n start(): void {\n process.stdout.write(` ${spinnerFrames[0]} ${this.message}`);\n this.interval = setInterval(() => {\n this.frameIndex = (this.frameIndex + 1) % spinnerFrames.length;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message}`);\n }, 80);\n }\n\n update(message: string): void {\n this.message = message;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message} `);\n }\n\n succeed(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.green('✓')} ${message || this.message} `);\n }\n\n fail(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.red('✗')} ${message || this.message} `);\n }\n\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n}\n\ninterface SessionIndexEntry {\n sessionId: string;\n projectPath: string;\n}\n\ninterface WatchOptions {\n verbose?: boolean;\n embedThreshold?: number;\n}\n\n// Debounce map to prevent rapid re-processing\nconst processingDebounce = new Map<string, NodeJS.Timeout>();\nconst DEBOUNCE_MS = 2000; // Wait 2 seconds after last change before processing\n\nexport async function watchCommand(options: WatchOptions): Promise<void> {\n const verbose = options.verbose ?? false;\n const embedThreshold = options.embedThreshold ?? 500;\n\n console.log(chalk.cyan('🔍 cmem watch - Monitoring Claude Code sessions\\n'));\n\n // Initialize embeddings (downloads model if needed)\n const modelSpinner = new Spinner('Initializing embedding model...');\n modelSpinner.start();\n\n try {\n await initializeEmbeddings((progress) => {\n if (progress.status === 'downloading' && progress.progress !== undefined) {\n const fileName = progress.file ? progress.file.split('/').pop() : 'model';\n modelSpinner.update(`Downloading ${fileName}... ${Math.round(progress.progress)}%`);\n } else if (progress.status === 'loading') {\n modelSpinner.update('Loading model...');\n }\n });\n modelSpinner.succeed('Embedding model ready');\n } catch (err) {\n modelSpinner.fail('Could not initialize embeddings');\n console.log(chalk.yellow(' Sessions will be saved but not vectorized.\\n'));\n }\n\n const embeddingsReady = isReady();\n console.log('');\n\n // First, do an initial scan to find and index all existing sessions\n const scanSpinner = new Spinner('Scanning for existing sessions...');\n scanSpinner.start();\n\n const existingFiles = findAllSessionFiles(CLAUDE_DIR);\n const totalFiles = existingFiles.length;\n\n // Get current stats to see how many are already indexed\n const statsBefore = getStats();\n const alreadyIndexed = statsBefore.sessionCount;\n const needsIndexing = totalFiles - alreadyIndexed;\n\n if (totalFiles === 0) {\n scanSpinner.succeed('No Claude Code sessions found yet');\n } else if (needsIndexing <= 0) {\n scanSpinner.succeed(`Found ${totalFiles} sessions (all indexed)`);\n } else {\n scanSpinner.update(`Found ${totalFiles} sessions, indexing ${needsIndexing} new...`);\n\n let processed = 0;\n let newlyIndexed = 0;\n\n for (const filePath of existingFiles) {\n processed++;\n // Force metadata update during initial scan to migrate existing sessions\n const wasNew = await processSessionFile(filePath, embeddingsReady, embedThreshold, false, true);\n if (wasNew) newlyIndexed++;\n\n // Update spinner with progress\n const percent = Math.round((processed / totalFiles) * 100);\n scanSpinner.update(`Indexing sessions... ${percent}% (${processed}/${totalFiles})`);\n }\n\n scanSpinner.succeed(`Indexed ${totalFiles} sessions (${newlyIndexed} new, ${totalFiles - newlyIndexed} updated)`);\n }\n\n console.log('');\n console.log(chalk.dim(`Watching: ${CLAUDE_DIR}`));\n console.log(chalk.dim(`Embed threshold: ${embedThreshold} chars\\n`));\n\n // Now watch for changes (ignore initial since we already processed)\n const watcher = chokidar.watch(CLAUDE_DIR, {\n persistent: true,\n ignoreInitial: true, // We already processed existing files above\n depth: 10,\n awaitWriteFinish: {\n stabilityThreshold: 1000,\n pollInterval: 100,\n },\n });\n\n watcher.on('add', (filePath) => {\n if (!filePath.endsWith('.jsonl')) return;\n if (filePath.includes('/subagents/')) {\n if (verbose) console.log(chalk.dim(`[skip agent] ${filePath}`));\n return;\n }\n if (verbose) console.log(chalk.dim(`[new] ${filePath}`));\n debouncedProcess(filePath, embeddingsReady, embedThreshold, verbose);\n });\n\n watcher.on('change', (filePath) => {\n if (!filePath.endsWith('.jsonl')) return;\n if (filePath.includes('/subagents/')) {\n if (verbose) console.log(chalk.dim(`[skip agent] ${filePath}`));\n return;\n }\n if (verbose) console.log(chalk.dim(`[changed] ${filePath}`));\n debouncedProcess(filePath, embeddingsReady, embedThreshold, verbose);\n });\n\n watcher.on('error', (error) => {\n console.error(chalk.red('Watcher error:'), error);\n });\n\n watcher.on('ready', () => {\n console.log(chalk.green('✓ Watching for session changes...'));\n console.log(chalk.dim('Press Ctrl+C to stop\\n'));\n });\n\n process.on('SIGINT', () => {\n console.log(chalk.dim('\\nShutting down watcher...'));\n watcher.close();\n process.exit(0);\n });\n\n process.on('SIGTERM', () => {\n watcher.close();\n process.exit(0);\n });\n}\n\n/**\n * Find all .jsonl session files in the Claude directory\n */\nfunction findAllSessionFiles(dir: string): string[] {\n const files: string[] = [];\n\n if (!existsSync(dir)) return files;\n\n function scanDir(currentDir: string, depth: number = 0): void {\n if (depth > 10) return; // Max depth\n\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(currentDir, entry.name);\n\n if (entry.isDirectory()) {\n // Skip subagents folder\n if (entry.name === 'subagents') continue;\n scanDir(fullPath, depth + 1);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n files.push(fullPath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n scanDir(dir);\n return files;\n}\n\nfunction debouncedProcess(\n filePath: string,\n embeddingsReady: boolean,\n embedThreshold: number,\n verbose: boolean\n): void {\n // Clear any existing debounce timer for this file\n const existing = processingDebounce.get(filePath);\n if (existing) {\n clearTimeout(existing);\n }\n\n // Set new debounce timer\n const timer = setTimeout(async () => {\n processingDebounce.delete(filePath);\n await processSessionFile(filePath, embeddingsReady, embedThreshold, verbose);\n }, DEBOUNCE_MS);\n\n processingDebounce.set(filePath, timer);\n}\n\nasync function processSessionFile(\n filePath: string,\n embeddingsReady: boolean,\n embedThreshold: number,\n verbose: boolean,\n forceMetadataUpdate = false\n): Promise<boolean> {\n try {\n // Parse the session file\n const messages = parseSessionFile(filePath);\n\n if (messages.length === 0) {\n if (verbose) console.log(chalk.dim(` Skipping empty session: ${filePath}`));\n return false;\n }\n\n // Get file stats\n const stats = statSync(filePath);\n const fileMtime = stats.mtime.toISOString();\n\n // Check if we already have this session\n const existingSession = getSessionBySourceFile(filePath);\n\n // Get session ID from filename\n const sessionId_from_file = basename(filePath, '.jsonl');\n\n // Load agent messages for this session (for embeddings)\n const agentMessages = loadSubagentMessages(dirname(filePath), sessionId_from_file);\n const allMessages = [...messages, ...agentMessages];\n\n // Calculate content length for embedding decisions (including agent messages)\n const contentLength = allMessages.reduce((sum, m) => sum + m.content.length, 0);\n\n // Generate title from first user message\n const firstUserMsg = messages.find(m => m.role === 'user');\n const title = firstUserMsg ? generateTitle(firstUserMsg.content) : 'Untitled Session';\n\n // Generate summary\n const summary = generateSummary(messages);\n\n // Build raw data for storage\n const rawData = JSON.stringify({ filePath, messages, mtime: fileMtime });\n\n // Get project path from sessions-index.json\n const projectPath = getProjectPathFromIndex(filePath, sessionId_from_file);\n\n // Extract metadata (isSidechain, agentId, isMeta) from JSONL\n const metadata = extractSessionMetadata(filePath);\n // Mark as automated if: JSONL metadata says so, OR title matches automated patterns\n const isAutomated = metadata.isSidechain || metadata.isMeta || isAutomatedByContent(title);\n\n let sessionId: string;\n let isNew = false;\n\n if (existingSession) {\n // Update existing session\n sessionId = existingSession.id;\n\n // Update metadata if it needs to be set (for sessions created before metadata tracking)\n // forceMetadataUpdate is true during initial scan to migrate existing sessions\n const needsMetadataUpdate = forceMetadataUpdate ||\n (!existingSession.isSidechain && !existingSession.isAutomated && isAutomated);\n\n // Update if content has changed OR metadata needs updating OR projectPath is missing\n const needsProjectPathUpdate = !existingSession.projectPath && projectPath;\n if (existingSession.messageCount !== messages.length || needsMetadataUpdate || needsProjectPathUpdate) {\n updateSession(sessionId, {\n title,\n summary,\n rawData,\n messages,\n isSidechain: metadata.isSidechain,\n isAutomated,\n projectPath: projectPath || undefined,\n });\n\n if (verbose) {\n const automatedTag = isAutomated ? chalk.dim(' [auto]') : '';\n console.log(chalk.blue(`↻ Updated: ${title} (${messages.length} msgs)${automatedTag}`));\n }\n }\n } else {\n // Create new session\n isNew = true;\n sessionId = createSession({\n title,\n summary,\n projectPath,\n sourceFile: filePath,\n rawData,\n messages,\n isSidechain: metadata.isSidechain,\n isAutomated,\n });\n\n if (verbose) {\n const automatedTag = isAutomated ? chalk.dim(' [auto]') : '';\n console.log(chalk.green(`✓ Saved: ${title} (${messages.length} msgs)${automatedTag}`));\n }\n }\n\n // Handle embedding (include agent messages for better search)\n if (embeddingsReady) {\n const shouldEmbed = needsReembedding(sessionId, contentLength, embedThreshold);\n\n if (shouldEmbed) {\n try {\n // Use all messages including agents for richer embeddings\n const embeddingText = createEmbeddingText(title, summary, allMessages);\n const embedding = await getEmbedding(embeddingText);\n storeEmbedding(sessionId, embedding);\n updateEmbeddingState(sessionId, contentLength, fileMtime);\n\n if (verbose) {\n const agentCount = agentMessages.length;\n const agentInfo = agentCount > 0 ? ` (+${agentCount} agent msgs)` : '';\n console.log(chalk.dim(` Embedded: ${title}${agentInfo}`));\n }\n } catch (err) {\n if (verbose) {\n console.log(chalk.yellow(` Failed to embed: ${title}`));\n console.log(chalk.dim(` ${err}`));\n }\n }\n }\n }\n\n return isNew;\n } catch (err) {\n if (verbose) console.log(chalk.red(`Error processing ${filePath}:`), err);\n return false;\n }\n}\n\n/**\n * Load messages from all subagent sessions for a parent session\n */\nfunction loadSubagentMessages(projectDirPath: string, parentSessionId: string): ParsedMessage[] {\n const subagentsDir = join(projectDirPath, parentSessionId, 'subagents');\n if (!existsSync(subagentsDir)) return [];\n\n const messages: ParsedMessage[] = [];\n\n try {\n const agentFiles = readdirSync(subagentsDir).filter(f => f.endsWith('.jsonl'));\n for (const agentFile of agentFiles) {\n const agentPath = join(subagentsDir, agentFile);\n const agentMessages = parseSessionFile(agentPath);\n messages.push(...agentMessages);\n }\n } catch {\n // Ignore errors reading subagent files\n }\n\n return messages;\n}\n\n/**\n * Get project path from sessions-index.json\n */\nfunction getProjectPathFromIndex(filePath: string, sessionId: string): string | null {\n const projectDir = dirname(filePath);\n const indexPath = join(projectDir, 'sessions-index.json');\n\n if (!existsSync(indexPath)) return null;\n\n try {\n const content = readFileSync(indexPath, 'utf-8');\n const index = JSON.parse(content) as { entries: SessionIndexEntry[] };\n const entry = index.entries.find(e => e.sessionId === sessionId);\n return entry?.projectPath || null;\n } catch {\n return null;\n }\n}\n","import chalk from 'chalk';\nimport { startMcpServer } from '../mcp/server.js';\n\nexport async function mcpCommand(): Promise<void> {\n // When running as MCP server, we don't want to log to stdout\n // as it's used for JSON-RPC communication\n // Instead, log to stderr for debugging\n console.error(chalk.cyan('Starting cmem MCP server...'));\n\n try {\n await startMcpServer();\n } catch (err) {\n console.error(chalk.red('MCP server error:'), err);\n process.exit(1);\n }\n}\n","import { 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 {\n listSessions,\n getSession,\n getSessionMessages,\n getSessionBySourceFile,\n getSessionByIdPrefix,\n} from '../db/sessions.js';\nimport { searchSessions } from '../db/vectors.js';\nimport { getEmbedding, initializeEmbeddings, isReady } from '../embeddings/index.js';\nimport { formatTimeAgo, truncate } from '../utils/format.js';\nimport { runClaudePrompt, isClaudeCliAvailable } from '../utils/claude-cli.js';\n\n/**\n * Create and configure the MCP server\n */\nexport function createMcpServer(): Server {\n const server = new Server(\n {\n name: 'cmem',\n version: '0.1.0',\n },\n {\n capabilities: {\n tools: {},\n },\n }\n );\n\n // List available tools\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: 'search_sessions',\n description:\n 'Semantic search across all saved Claude Code conversation sessions. Use this to find past conversations about specific topics, projects, or problems. Returns matching sessions ranked by relevance.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description:\n 'Natural language search query. Examples: \"React hooks discussion\", \"database migration\", \"authentication implementation\"',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 5)',\n },\n },\n required: ['query'],\n },\n },\n {\n name: 'list_sessions',\n description:\n 'List all saved Claude Code conversation sessions, ordered by most recently updated. Use this to browse available sessions or find recent conversations.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n limit: {\n type: 'number',\n description: 'Maximum number of sessions to return (default: 10)',\n },\n },\n },\n },\n {\n name: 'get_session',\n description:\n 'Get detailed information about a specific conversation session, including its full message history. Use this after finding a session via search or list.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID to retrieve',\n },\n includeMessages: {\n type: 'boolean',\n description: 'Whether to include the full message history (default: true)',\n },\n messageLimit: {\n type: 'number',\n description: 'Maximum number of messages to include (default: 50, from most recent)',\n },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'get_session_context',\n description:\n 'Get a formatted context summary from a past session that can be used to continue or reference that conversation. Returns key information and recent messages in a readable format.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID to get context from',\n },\n messageCount: {\n type: 'number',\n description: 'Number of recent messages to include (default: 10)',\n },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'search_and_summarize',\n description:\n 'Search past Claude Code sessions and get an AI-generated summary tailored to your specific question. This spawns a separate Claude instance to read and synthesize the relevant sessions, keeping your main context clean. Use this when you need insights from past conversations.',\n inputSchema: {\n type: 'object' as const,\n properties: {\n query: {\n type: 'string',\n description:\n 'Your question or topic to search for. Examples: \"What did we decide about the database schema?\", \"How did we implement authentication?\", \"What was the bug fix for the login issue?\"',\n },\n sessionLimit: {\n type: 'number',\n description: 'Maximum number of sessions to analyze (default: 3)',\n },\n model: {\n type: 'string',\n enum: ['haiku', 'sonnet', 'opus'],\n description: 'Model to use for summarization (default: haiku for speed)',\n },\n },\n required: ['query'],\n },\n },\n ],\n };\n });\n\n // Handle tool calls\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n\n try {\n switch (name) {\n case 'search_sessions':\n return await handleSearchSessions(args as { query: string; limit?: number });\n\n case 'list_sessions':\n return await handleListSessions(args as { limit?: number });\n\n case 'get_session':\n return await handleGetSession(\n args as { sessionId: string; includeMessages?: boolean; messageLimit?: number }\n );\n\n case 'get_session_context':\n return await handleGetSessionContext(\n args as { sessionId: string; messageCount?: number }\n );\n\n case 'search_and_summarize':\n return await handleSearchAndSummarize(\n args as { query: string; sessionLimit?: number; model?: 'haiku' | 'sonnet' | 'opus' }\n );\n\n default:\n return {\n content: [{ type: 'text', text: `Unknown tool: ${name}` }],\n isError: true,\n };\n }\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${String(error)}` }],\n isError: true,\n };\n }\n });\n\n return server;\n}\n\nasync function handleSearchSessions(args: { query: string; limit?: number }) {\n const { query, limit = 5 } = args;\n\n // Initialize embeddings if needed\n if (!isReady()) {\n try {\n await initializeEmbeddings();\n } catch {\n // Fall back to simple text search\n const allSessions = listSessions(100);\n const queryLower = query.toLowerCase();\n const filtered = allSessions\n .filter(\n (s) =>\n s.title.toLowerCase().includes(queryLower) ||\n (s.summary && s.summary.toLowerCase().includes(queryLower))\n )\n .slice(0, limit);\n\n return {\n content: [\n {\n type: 'text',\n text: formatSessionList(filtered, `Text search results for \"${query}\" (embeddings unavailable)`),\n },\n ],\n };\n }\n }\n\n // Semantic search\n const queryEmbedding = await getEmbedding(query);\n const results = searchSessions(queryEmbedding, limit);\n\n return {\n content: [\n {\n type: 'text',\n text: formatSessionList(results, `Semantic search results for \"${query}\"`),\n },\n ],\n };\n}\n\nasync function handleListSessions(args: { limit?: number }) {\n const { limit = 10 } = args;\n const sessions = listSessions(limit);\n\n return {\n content: [\n {\n type: 'text',\n text: formatSessionList(sessions, 'Recent sessions'),\n },\n ],\n };\n}\n\nasync function handleGetSession(args: {\n sessionId: string;\n includeMessages?: boolean;\n messageLimit?: number;\n}) {\n const { sessionId, includeMessages = true, messageLimit = 50 } = args;\n\n // Support partial ID matching - try exact match first, then prefix match\n let session = getSession(sessionId) || getSessionByIdPrefix(sessionId);\n\n if (!session) {\n return {\n content: [{ type: 'text', text: `Session not found: ${sessionId}` }],\n isError: true,\n };\n }\n\n const lines: string[] = [\n `# Session: ${session.title}`,\n '',\n `**ID:** ${session.id}`,\n `**Created:** ${session.createdAt}`,\n `**Updated:** ${session.updatedAt} (${formatTimeAgo(session.updatedAt)})`,\n `**Messages:** ${session.messageCount}`,\n ];\n\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n }\n\n if (session.summary) {\n lines.push('', '## Summary', session.summary);\n }\n\n if (includeMessages) {\n const messages = getSessionMessages(session.id);\n const recentMessages = messages.slice(-messageLimit);\n\n lines.push('', '## Messages', '');\n\n for (const msg of recentMessages) {\n lines.push(`### ${msg.role === 'user' ? 'User' : 'Assistant'}`);\n lines.push(msg.content);\n lines.push('');\n }\n\n if (messages.length > messageLimit) {\n lines.push(`_...${messages.length - messageLimit} earlier messages omitted_`);\n }\n }\n\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n };\n}\n\nasync function handleGetSessionContext(args: { sessionId: string; messageCount?: number }) {\n const { sessionId, messageCount = 10 } = args;\n\n // Support partial ID matching - try exact match first, then prefix match\n let session = getSession(sessionId) || getSessionByIdPrefix(sessionId);\n\n if (!session) {\n return {\n content: [{ type: 'text', text: `Session not found: ${sessionId}` }],\n isError: true,\n };\n }\n\n const messages = getSessionMessages(session.id);\n const recentMessages = messages.slice(-messageCount);\n\n const lines: string[] = [\n '# Context from Previous Session',\n '',\n `**Topic:** ${session.title}`,\n ];\n\n if (session.projectPath) {\n lines.push(`**Project:** ${session.projectPath}`);\n }\n\n if (session.summary) {\n lines.push('', '## Summary', session.summary);\n }\n\n lines.push(\n '',\n '## Recent Conversation',\n `_Last ${recentMessages.length} of ${messages.length} messages_`,\n ''\n );\n\n for (const msg of recentMessages) {\n const role = msg.role === 'user' ? '**User:**' : '**Assistant:**';\n lines.push(role);\n // Truncate very long messages in context\n lines.push(truncate(msg.content, 2000));\n lines.push('');\n }\n\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n };\n}\n\nasync function handleSearchAndSummarize(args: {\n query: string;\n sessionLimit?: number;\n model?: 'haiku' | 'sonnet' | 'opus';\n}) {\n const { query, sessionLimit = 3, model = 'haiku' } = args;\n\n // Check if Claude CLI is available\n if (!isClaudeCliAvailable()) {\n return {\n content: [\n {\n type: 'text',\n text: 'Claude CLI not found. This tool requires Claude Code CLI to be installed.',\n },\n ],\n isError: true,\n };\n }\n\n // Initialize embeddings if needed\n if (!isReady()) {\n try {\n await initializeEmbeddings();\n } catch {\n return {\n content: [\n {\n type: 'text',\n text: 'Embedding model not available. Please run `cmem setup` first.',\n },\n ],\n isError: true,\n };\n }\n }\n\n // Semantic search for relevant sessions\n const queryEmbedding = await getEmbedding(query);\n const sessions = searchSessions(queryEmbedding, sessionLimit);\n\n if (sessions.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: `No relevant sessions found for: \"${query}\"`,\n },\n ],\n };\n }\n\n // Gather content from matching sessions\n const sessionContents: string[] = [];\n for (const session of sessions) {\n const messages = getSessionMessages(session.id);\n if (messages.length === 0) continue;\n\n // Format session content\n const sessionText = [\n `## Session: ${session.title}`,\n `Project: ${session.projectPath || 'Unknown'}`,\n `Date: ${session.updatedAt}`,\n '',\n ...messages.slice(-20).map((m) => `**${m.role}:** ${truncate(m.content, 1500)}`),\n ].join('\\n');\n\n sessionContents.push(sessionText);\n }\n\n if (sessionContents.length === 0) {\n return {\n content: [\n {\n type: 'text',\n text: `Found ${sessions.length} sessions but they appear to be empty.`,\n },\n ],\n };\n }\n\n // Build prompt for Claude to summarize\n const prompt = `You are analyzing past Claude Code conversation sessions to answer a user's question.\n\n<user_question>\n${query}\n</user_question>\n\n<past_sessions>\n${sessionContents.join('\\n\\n---\\n\\n')}\n</past_sessions>\n\nBased on the past sessions above, provide a concise and helpful answer to the user's question. Focus on:\n1. Directly answering their question with specific details from the conversations\n2. Mentioning which session(s) the information came from\n3. Highlighting any relevant decisions, code snippets, or conclusions\n\nIf the sessions don't contain relevant information to answer the question, say so clearly.\n\nKeep your response concise but complete.`;\n\n // Spawn Claude CLI to generate the summary\n const response = await runClaudePrompt(prompt, { model });\n\n if (!response.success) {\n return {\n content: [\n {\n type: 'text',\n text: `Error generating summary: ${response.error || 'Unknown error'}`,\n },\n ],\n isError: true,\n };\n }\n\n // Format the response with metadata\n const resultLines = [\n response.content,\n '',\n '---',\n `*Analyzed ${sessions.length} session(s) | Model: ${model}${response.durationMs ? ` | ${(response.durationMs / 1000).toFixed(1)}s` : ''}${response.outputTokens ? ` | ${response.outputTokens} tokens` : ''}*`,\n ];\n\n return {\n content: [{ type: 'text', text: resultLines.join('\\n') }],\n };\n}\n\nfunction formatSessionList(\n sessions: Array<{\n id: string;\n title: string;\n summary: string | null;\n messageCount: number;\n updatedAt: string;\n projectPath: string | null;\n }>,\n header: string\n): string {\n if (sessions.length === 0) {\n return `${header}\\n\\nNo sessions found.`;\n }\n\n const lines: string[] = [header, ''];\n\n for (const session of sessions) {\n lines.push(`### ${session.title}`);\n lines.push(`- **ID:** \\`${session.id.slice(0, 8)}\\` (use this to get full session)`);\n lines.push(`- **Messages:** ${session.messageCount}`);\n lines.push(`- **Updated:** ${formatTimeAgo(session.updatedAt)}`);\n if (session.projectPath) {\n lines.push(`- **Project:** ${session.projectPath}`);\n }\n if (session.summary) {\n lines.push(`- **Summary:** ${truncate(session.summary, 150)}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Start the MCP server\n */\nexport async function startMcpServer(): Promise<void> {\n const server = createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","import { spawn } from 'child_process';\nimport { execSync } from 'child_process';\n\nexport interface ClaudeResponse {\n success: boolean;\n content: string;\n error?: string;\n inputTokens?: number;\n outputTokens?: number;\n costUsd?: number;\n durationMs?: number;\n}\n\n/**\n * Get the path to the Claude CLI\n */\nfunction getClaudePath(): string | null {\n try {\n const result = execSync('which claude', { encoding: 'utf-8' }).trim();\n return result || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Parse a single line of NDJSON from Claude's stream-json output\n */\ninterface ParsedChunk {\n type: 'text' | 'done' | 'error' | 'skip';\n content?: string;\n inputTokens?: number;\n outputTokens?: number;\n costUsd?: number;\n durationMs?: number;\n}\n\nfunction parseStreamJsonLine(line: string): ParsedChunk | null {\n if (!line.trim()) return null;\n\n try {\n const data = JSON.parse(line);\n\n if (data.type === 'assistant') {\n // Assistant message with content blocks\n if (data.message?.content && Array.isArray(data.message.content)) {\n const textBlocks: string[] = [];\n\n for (const block of data.message.content) {\n if (block.type === 'text' && block.text) {\n textBlocks.push(block.text);\n }\n }\n\n if (textBlocks.length > 0) {\n return { type: 'text', content: textBlocks.join('\\n') };\n }\n }\n } else if (data.type === 'content_block_delta') {\n // Streaming text delta\n if (data.delta?.type === 'text_delta' && data.delta.text) {\n return { type: 'text', content: data.delta.text };\n }\n } else if (data.type === 'result') {\n // Final result\n if (data.is_error) {\n return { type: 'error', content: data.result || 'Unknown error' };\n }\n const usage = data.usage || {};\n const inputTokens = (usage.input_tokens || 0) + (usage.cache_read_input_tokens || 0);\n const outputTokens = usage.output_tokens || 0;\n return {\n type: 'done',\n inputTokens,\n outputTokens,\n costUsd: data.total_cost_usd,\n durationMs: data.duration_ms,\n };\n } else if (data.type === 'error') {\n return {\n type: 'error',\n content: data.error?.message || JSON.stringify(data.error) || 'Unknown error',\n };\n }\n\n // Skip other message types (system, message_start, etc.)\n return { type: 'skip' };\n } catch {\n return null;\n }\n}\n\n/**\n * Run a prompt through Claude CLI and return the response\n * Uses print mode (-p) with stream-json output for structured responses\n */\nexport async function runClaudePrompt(\n prompt: string,\n options: {\n model?: 'opus' | 'sonnet' | 'haiku';\n maxTokens?: number;\n } = {}\n): Promise<ClaudeResponse> {\n const claudePath = getClaudePath();\n if (!claudePath) {\n return {\n success: false,\n content: '',\n error: 'Claude CLI not found. Please install Claude Code CLI.',\n };\n }\n\n const { model = 'haiku' } = options;\n\n const args = [\n '-p', prompt,\n '--output-format', 'stream-json',\n '--verbose', // Required when using stream-json with -p\n '--model', model,\n '--permission-mode', 'plan', // Read-only, no tools needed for summarization\n ];\n\n return new Promise((resolve) => {\n const childProcess = spawn(claudePath, args, {\n env: {\n ...process.env,\n CI: 'true', // Prevent interactive prompts\n },\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n // Close stdin since we're using -p flag\n childProcess.stdin?.end();\n\n let buffer = '';\n const textChunks: string[] = [];\n let finalResult: ParsedChunk | null = null;\n let errorContent = '';\n\n childProcess.stdout?.on('data', (data: Buffer) => {\n buffer += data.toString();\n\n const lines = buffer.split('\\n');\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n if (!line.trim()) continue;\n\n const chunk = parseStreamJsonLine(line);\n if (chunk) {\n if (chunk.type === 'text' && chunk.content) {\n textChunks.push(chunk.content);\n } else if (chunk.type === 'done') {\n finalResult = chunk;\n } else if (chunk.type === 'error' && chunk.content) {\n errorContent = chunk.content;\n }\n }\n }\n });\n\n childProcess.stderr?.on('data', (data: Buffer) => {\n const text = data.toString().toLowerCase();\n if (text.includes('error') || text.includes('failed')) {\n errorContent = data.toString().trim();\n }\n });\n\n childProcess.on('close', (code) => {\n // Process remaining buffer\n if (buffer.trim()) {\n const chunk = parseStreamJsonLine(buffer);\n if (chunk) {\n if (chunk.type === 'text' && chunk.content) {\n textChunks.push(chunk.content);\n } else if (chunk.type === 'done') {\n finalResult = chunk;\n } else if (chunk.type === 'error' && chunk.content) {\n errorContent = chunk.content;\n }\n }\n }\n\n const content = textChunks.join('');\n\n if (errorContent && !content) {\n resolve({\n success: false,\n content: '',\n error: errorContent,\n });\n } else {\n resolve({\n success: code === 0 && content.length > 0,\n content,\n error: errorContent || undefined,\n inputTokens: finalResult?.inputTokens,\n outputTokens: finalResult?.outputTokens,\n costUsd: finalResult?.costUsd,\n durationMs: finalResult?.durationMs,\n });\n }\n });\n\n childProcess.on('error', (err) => {\n resolve({\n success: false,\n content: '',\n error: err.message,\n });\n });\n\n // Timeout after 60 seconds\n setTimeout(() => {\n childProcess.kill('SIGTERM');\n resolve({\n success: false,\n content: textChunks.join(''),\n error: 'Request timed out after 60 seconds',\n });\n }, 60000);\n });\n}\n\n/**\n * Check if Claude CLI is available\n */\nexport function isClaudeCliAvailable(): boolean {\n return getClaudePath() !== null;\n}\n","import chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, statSync } from 'fs';\nimport { homedir } from 'os';\nimport { join, dirname, basename } from 'path';\nimport { fileURLToPath } from 'url';\nimport { createInterface } from 'readline';\nimport { initializeEmbeddings, isModelCached, isReady, getEmbedding, createEmbeddingText, type InitProgress } from '../embeddings/index.js';\nimport { EMBEDDING_MODEL, CLAUDE_DIR } from '../utils/config.js';\nimport { parseSessionFile, generateSummary } from '../parser/index.js';\nimport { createSession, getSessionBySourceFile, needsReembedding, updateEmbeddingState, getStats } from '../db/sessions.js';\nimport { storeEmbedding } from '../db/vectors.js';\nimport { generateTitle } from '../utils/format.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\nconst CLAUDE_JSON_PATH = join(homedir(), '.claude.json');\nconst CLAUDE_SETTINGS_PATH = join(homedir(), '.claude', 'settings.json');\nconst CMEM_DIR = join(homedir(), '.cmem');\nconst SETUP_MARKER = join(CMEM_DIR, '.setup-complete');\n\ninterface ClaudeJson {\n mcpServers?: Record<string, { type?: string; command: string; args?: string[] }>;\n [key: string]: unknown;\n}\n\ninterface ClaudeSettings {\n permissions?: {\n allow?: string[];\n deny?: string[];\n };\n [key: string]: unknown;\n}\n\n// cmem MCP tool permissions\nconst CMEM_PERMISSIONS = [\n 'mcp__cmem__search_sessions',\n 'mcp__cmem__list_sessions',\n 'mcp__cmem__get_session',\n 'mcp__cmem__get_session_context',\n 'mcp__cmem__search_and_summarize',\n];\n\n// Spinner animation frames\nconst spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nclass Spinner {\n private interval: NodeJS.Timeout | null = null;\n private frameIndex = 0;\n private message: string;\n\n constructor(message: string) {\n this.message = message;\n }\n\n start(): void {\n process.stdout.write(` ${spinnerFrames[0]} ${this.message}`);\n this.interval = setInterval(() => {\n this.frameIndex = (this.frameIndex + 1) % spinnerFrames.length;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message}`);\n }, 80);\n }\n\n update(message: string): void {\n this.message = message;\n process.stdout.write(`\\r ${chalk.cyan(spinnerFrames[this.frameIndex])} ${this.message} `);\n }\n\n succeed(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.green('✓')} ${message || this.message} `);\n }\n\n fail(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.red('✗')} ${message || this.message} `);\n }\n\n warn(message?: string): void {\n this.stop();\n console.log(`\\r ${chalk.yellow('!')} ${message || this.message} `);\n }\n\n stop(): void {\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n }\n}\n\n// Beautiful ASCII art banner\nfunction printBanner(version: string): void {\n const magenta = chalk.magenta;\n const cyan = chalk.cyan;\n const dim = chalk.dim;\n\n console.log('');\n console.log(magenta(' ██████╗ ███╗ ███╗ ███████╗ ███╗ ███╗'));\n console.log(magenta(' ██╔════╝ ████╗ ████║ ██╔════╝ ████╗ ████║'));\n console.log(magenta(' ██║ ██╔████╔██║ █████╗ ██╔████╔██║'));\n console.log(magenta(' ██║ ██║╚██╔╝██║ ██╔══╝ ██║╚██╔╝██║'));\n console.log(magenta(' ╚██████╗ ██║ ╚═╝ ██║ ███████╗ ██║ ╚═╝ ██║'));\n console.log(magenta(' ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝'));\n console.log('');\n console.log(cyan(` cmem v${version}`));\n console.log(dim(' Persistent memory & semantic search for Claude Code'));\n console.log(dim(' Created by Colby McHenry'));\n console.log('');\n}\n\nasync function promptChoice(question: string, options: string[], defaultChoice = 1): Promise<number> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n // Print options\n options.forEach((opt, i) => {\n console.log(chalk.dim(` ${i + 1}) ${opt}`));\n });\n console.log('');\n\n return new Promise((resolve) => {\n rl.question(chalk.white(` Choice [${defaultChoice}]: `), (answer) => {\n rl.close();\n const num = parseInt(answer.trim(), 10);\n if (isNaN(num) || num < 1 || num > options.length) {\n resolve(defaultChoice);\n } else {\n resolve(num);\n }\n });\n });\n}\n\nasync function promptYesNo(question: string, defaultYes = true): Promise<boolean> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const hint = defaultYes ? '[Y/n]' : '[y/N]';\n\n return new Promise((resolve) => {\n rl.question(chalk.white(` ${question} ${chalk.dim(hint)} `), (answer) => {\n rl.close();\n const normalized = answer.toLowerCase().trim();\n if (normalized === '') {\n resolve(defaultYes);\n } else {\n resolve(normalized === 'y' || normalized === 'yes');\n }\n });\n });\n}\n\nfunction isRunningViaNpx(): boolean {\n const execPath = process.argv[1] || '';\n return execPath.includes('_npx') || execPath.includes('.npm/_cacache');\n}\n\nfunction isGloballyInstalled(): boolean {\n try {\n const result = execSync('which cmem 2>/dev/null || where cmem 2>/dev/null', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n return result.length > 0 && !result.includes('_npx');\n } catch {\n return false;\n }\n}\n\nfunction getCmemVersion(): string {\n try {\n // From dist/cli.js, package.json is one level up\n const packagePath = join(__dirname, '..', 'package.json');\n if (existsSync(packagePath)) {\n const pkg = JSON.parse(readFileSync(packagePath, 'utf-8'));\n return pkg.version || '0.1.0';\n }\n } catch {\n // Ignore\n }\n return '0.1.0';\n}\n\nfunction getInstalledVersion(): string | null {\n try {\n const result = execSync('cmem --version 2>/dev/null', {\n encoding: 'utf-8',\n }).trim();\n return result;\n } catch {\n return null;\n }\n}\n\nexport async function setupCommand(): Promise<void> {\n const currentVersion = getCmemVersion();\n const installedVersion = getInstalledVersion();\n const isGlobal = isGloballyInstalled();\n const isNpx = isRunningViaNpx();\n\n // Print beautiful banner\n printBanner(currentVersion);\n\n // Step 1: Global installation\n if (!isGlobal || isNpx) {\n console.log(chalk.yellow(' Install cmem globally?'));\n console.log(chalk.dim(' Makes the `cmem` command available everywhere\\n'));\n\n const choice = await promptChoice('', [\n 'Yes - install globally via npm',\n 'No - I\\'ll use npx each time',\n ], 1);\n\n if (choice === 1) {\n console.log(chalk.dim('\\n Installing @colbymchenry/cmem globally...\\n'));\n try {\n execSync('npm install -g @colbymchenry/cmem', { stdio: 'inherit' });\n console.log(chalk.green('\\n ✓ Installed globally\\n'));\n } catch {\n console.log(chalk.red('\\n ✗ Failed to install. Try: sudo npm install -g @colbymchenry/cmem\\n'));\n }\n } else {\n console.log(chalk.dim('\\n Skipped. Use `npx @colbymchenry/cmem` to run.\\n'));\n }\n } else if (installedVersion && installedVersion !== currentVersion) {\n console.log(chalk.yellow(` Update available: ${installedVersion} → ${currentVersion}`));\n\n const shouldUpdate = await promptYesNo('Update to latest version?');\n\n if (shouldUpdate) {\n console.log(chalk.dim('\\n Updating @colbymchenry/cmem...\\n'));\n try {\n execSync('npm install -g @colbymchenry/cmem', { stdio: 'inherit' });\n console.log(chalk.green('\\n ✓ Updated\\n'));\n } catch {\n console.log(chalk.red('\\n ✗ Failed to update\\n'));\n }\n } else {\n console.log('');\n }\n } else {\n console.log(chalk.green(' ✓ cmem is installed globally\\n'));\n }\n\n // Step 2: Download embedding model for semantic search\n console.log(chalk.yellow(' Semantic search setup'));\n console.log(chalk.dim(' Enables searching conversations by meaning\\n'));\n\n const modelSpinner = new Spinner('Checking embedding model...');\n modelSpinner.start();\n\n const cached = isModelCached();\n\n if (cached) {\n modelSpinner.succeed('Embedding model ready');\n } else {\n modelSpinner.update('Downloading embedding model (~130MB)...');\n\n try {\n await initializeEmbeddings((progress: InitProgress) => {\n if (progress.status === 'downloading' && progress.progress !== undefined) {\n const percent = Math.round(progress.progress);\n const fileName = progress.file ? progress.file.split('/').pop() : '';\n modelSpinner.update(`Downloading ${fileName}... ${percent}%`);\n } else if (progress.status === 'loading') {\n modelSpinner.update('Loading model...');\n }\n });\n modelSpinner.succeed('Embedding model ready');\n } catch (err) {\n modelSpinner.fail('Failed to download embedding model');\n console.log(chalk.dim(` Error: ${err}\\n`));\n }\n }\n\n console.log('');\n\n // Step 3: Auto-start daemon\n const daemonInstalled = existsSync(\n join(homedir(), 'Library', 'LaunchAgents', 'com.cmem.watch.plist')\n );\n\n // Check if we're updating (need to reinstall daemon to pick up new binary)\n const isUpdating = installedVersion && installedVersion !== currentVersion;\n\n if (daemonInstalled && !isUpdating) {\n console.log(chalk.green(' ✓ Auto-start daemon is installed'));\n // Make sure it's actually running\n try {\n execSync('launchctl load ~/Library/LaunchAgents/com.cmem.watch.plist 2>/dev/null', { stdio: 'ignore' });\n } catch {\n // Already loaded, that's fine\n }\n console.log('');\n } else if (daemonInstalled && isUpdating && process.platform === 'darwin') {\n // Reinstall daemon to pick up updated binary\n console.log(chalk.yellow(' Updating daemon...'));\n try {\n const { installCommand } = await import('./install.js');\n await installCommand();\n } catch {\n console.log(chalk.red(' ✗ Failed to update daemon'));\n console.log(chalk.dim(' Try manually: cmem install\\n'));\n }\n } else if (process.platform === 'darwin') {\n console.log(chalk.yellow(' Auto-start daemon?'));\n console.log(chalk.dim(' Syncs Claude Code sessions in the background\\n'));\n\n const choice = await promptChoice('', [\n 'Yes - start on login (recommended)',\n 'No - I\\'ll run `cmem watch` manually',\n ], 1);\n\n if (choice === 1) {\n try {\n const { installCommand } = await import('./install.js');\n await installCommand();\n } catch (err) {\n console.log(chalk.red(' ✗ Failed to install daemon'));\n console.log(chalk.dim(' Try manually: cmem install\\n'));\n }\n } else {\n console.log(chalk.dim('\\n Skipped. Run `cmem watch` when needed.\\n'));\n }\n }\n\n // Step 4: Claude Code MCP integration\n const mcpConfigured = isMcpConfigured();\n\n if (mcpConfigured) {\n console.log(chalk.green(' ✓ MCP server configured in Claude Code\\n'));\n } else {\n console.log(chalk.yellow(' Add MCP server to Claude Code?'));\n console.log(chalk.dim(' Lets Claude search your past conversations\\n'));\n\n const choice = await promptChoice('', [\n 'Yes - configure automatically (recommended)',\n 'No - I\\'ll configure it manually',\n ], 1);\n\n if (choice === 1) {\n const success = configureMcpServer();\n if (success) {\n console.log(chalk.green('\\n ✓ Added MCP server to ~/.claude.json'));\n console.log(chalk.green(' ✓ Added permissions to ~/.claude/settings.json'));\n console.log(chalk.dim(' Restart Claude Code or run /mcp to connect\\n'));\n } else {\n console.log(chalk.red('\\n ✗ Failed to configure MCP server\\n'));\n }\n } else {\n console.log(chalk.dim('\\n Skipped.\\n'));\n }\n }\n\n // Step 5: Index existing sessions\n console.log(chalk.yellow(' Initial session indexing'));\n console.log(chalk.dim(' Scanning and indexing your existing Claude Code conversations\\n'));\n\n await indexExistingSessions();\n\n // Mark setup as complete\n if (!existsSync(CMEM_DIR)) {\n mkdirSync(CMEM_DIR, { recursive: true });\n }\n writeFileSync(SETUP_MARKER, new Date().toISOString());\n\n // Done - show summary\n console.log(chalk.magenta(' ════════════════════════════════════════════'));\n console.log(chalk.green.bold('\\n ✓ Setup complete!\\n'));\n\n console.log(chalk.white(' Commands:'));\n console.log(chalk.dim(' cmem Browse sessions (TUI)'));\n console.log(chalk.dim(' cmem search \"X\" Semantic search'));\n console.log(chalk.dim(' cmem watch Start sync daemon'));\n console.log(chalk.dim(' cmem stats Storage statistics'));\n console.log(chalk.dim(' cmem --help All commands'));\n\n console.log(chalk.white('\\n MCP Tools (available to Claude):'));\n console.log(chalk.dim(' search_sessions Find past conversations'));\n console.log(chalk.dim(' get_session Retrieve full history'));\n console.log(chalk.dim(' list_sessions Browse recent sessions'));\n\n // Check if daemon is running and inform user\n if (process.platform === 'darwin') {\n const plistExists = existsSync(join(homedir(), 'Library', 'LaunchAgents', 'com.cmem.watch.plist'));\n if (plistExists) {\n console.log(chalk.green('\\n 🚀 Daemon is now syncing your sessions in the background!'));\n }\n }\n\n console.log('');\n}\n\nfunction isMcpConfigured(): boolean {\n // Check if MCP server exists in ~/.claude.json\n if (!existsSync(CLAUDE_JSON_PATH)) {\n return false;\n }\n\n try {\n const config: ClaudeJson = JSON.parse(readFileSync(CLAUDE_JSON_PATH, 'utf-8'));\n return !!config.mcpServers?.cmem;\n } catch {\n return false;\n }\n}\n\nfunction configureMcpServer(): boolean {\n try {\n // Step 1: Add MCP server to ~/.claude.json\n let claudeJson: ClaudeJson = {};\n if (existsSync(CLAUDE_JSON_PATH)) {\n try {\n claudeJson = JSON.parse(readFileSync(CLAUDE_JSON_PATH, 'utf-8'));\n } catch {\n claudeJson = {};\n }\n }\n\n if (!claudeJson.mcpServers) {\n claudeJson.mcpServers = {};\n }\n\n claudeJson.mcpServers.cmem = {\n type: 'stdio',\n command: 'cmem',\n args: ['mcp'],\n };\n\n writeFileSync(CLAUDE_JSON_PATH, JSON.stringify(claudeJson, null, 2) + '\\n');\n\n // Step 2: Add permissions to ~/.claude/settings.json\n const claudeDir = dirname(CLAUDE_SETTINGS_PATH);\n if (!existsSync(claudeDir)) {\n mkdirSync(claudeDir, { recursive: true });\n }\n\n let settings: ClaudeSettings = {};\n if (existsSync(CLAUDE_SETTINGS_PATH)) {\n try {\n settings = JSON.parse(readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8'));\n } catch {\n settings = {};\n }\n }\n\n if (!settings.permissions) {\n settings.permissions = {};\n }\n if (!settings.permissions.allow) {\n settings.permissions.allow = [];\n }\n\n // Add any missing cmem permissions\n for (const perm of CMEM_PERMISSIONS) {\n if (!settings.permissions.allow.includes(perm)) {\n settings.permissions.allow.push(perm);\n }\n }\n\n writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2) + '\\n');\n\n return true;\n } catch (err) {\n console.error(chalk.red('Error configuring MCP:'), err);\n return false;\n }\n}\n\nexport function shouldRunSetup(): boolean {\n const isNpx = isRunningViaNpx();\n const setupComplete = existsSync(SETUP_MARKER);\n const isGlobal = isGloballyInstalled();\n\n // Always run setup when invoked via npx\n if (isNpx) return true;\n\n // Run setup if not installed globally and setup hasn't been completed\n if (!isGlobal && !setupComplete) return true;\n\n // Check for version mismatch (update available)\n const currentVersion = getCmemVersion();\n const installedVersion = getInstalledVersion();\n if (installedVersion && installedVersion !== currentVersion) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Find all .jsonl session files in the Claude directory\n */\nfunction findAllSessionFiles(dir: string): string[] {\n const files: string[] = [];\n\n if (!existsSync(dir)) return files;\n\n function scanDir(currentDir: string, depth: number = 0): void {\n if (depth > 10) return;\n\n try {\n const entries = readdirSync(currentDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = join(currentDir, entry.name);\n\n if (entry.isDirectory()) {\n if (entry.name === 'subagents') continue;\n scanDir(fullPath, depth + 1);\n } else if (entry.isFile() && entry.name.endsWith('.jsonl')) {\n files.push(fullPath);\n }\n }\n } catch {\n // Ignore permission errors\n }\n }\n\n scanDir(dir);\n return files;\n}\n\n/**\n * Index a single session file\n */\nasync function indexSessionFile(filePath: string, embeddingsReady: boolean): Promise<boolean> {\n try {\n const messages = parseSessionFile(filePath);\n if (messages.length === 0) return false;\n\n // Check if already indexed\n const existing = getSessionBySourceFile(filePath);\n if (existing) return false;\n\n // Get file stats\n const stats = statSync(filePath);\n const fileMtime = stats.mtime.toISOString();\n\n // Generate title and summary\n const firstUserMsg = messages.find(m => m.role === 'user');\n const title = firstUserMsg ? generateTitle(firstUserMsg.content) : 'Untitled Session';\n const summary = generateSummary(messages);\n\n // Build raw data\n const rawData = JSON.stringify({ filePath, messages, mtime: fileMtime });\n const sessionId_from_file = basename(filePath, '.jsonl');\n\n // Create session\n const sessionId = createSession({\n title,\n summary,\n projectPath: null,\n sourceFile: filePath,\n rawData,\n messages,\n });\n\n // Generate embedding if ready\n if (embeddingsReady) {\n const contentLength = messages.reduce((sum, m) => sum + m.content.length, 0);\n const shouldEmbed = needsReembedding(sessionId, contentLength, 500);\n\n if (shouldEmbed) {\n try {\n const embeddingText = createEmbeddingText(title, summary, messages);\n const embedding = await getEmbedding(embeddingText);\n storeEmbedding(sessionId, embedding);\n updateEmbeddingState(sessionId, contentLength, fileMtime);\n } catch {\n // Ignore embedding errors\n }\n }\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Index all existing Claude Code sessions\n */\nasync function indexExistingSessions(): Promise<void> {\n const spinner = new Spinner('Scanning for sessions...');\n spinner.start();\n\n // Find all session files\n const sessionFiles = findAllSessionFiles(CLAUDE_DIR);\n const totalFiles = sessionFiles.length;\n\n if (totalFiles === 0) {\n spinner.succeed('No Claude Code sessions found yet');\n console.log(chalk.dim(' Start using Claude Code, then run cmem to see your sessions\\n'));\n return;\n }\n\n // Check how many are already indexed\n const statsBefore = getStats();\n const alreadyIndexed = statsBefore.sessionCount;\n\n if (alreadyIndexed >= totalFiles) {\n spinner.succeed(`Found ${totalFiles} sessions (all indexed)`);\n console.log('');\n return;\n }\n\n spinner.update(`Found ${totalFiles} sessions, indexing...`);\n\n // Check if embeddings are ready\n const embeddingsReady = isReady();\n\n let processed = 0;\n let newlyIndexed = 0;\n\n for (const filePath of sessionFiles) {\n processed++;\n const wasNew = await indexSessionFile(filePath, embeddingsReady);\n if (wasNew) newlyIndexed++;\n\n // Update progress\n const percent = Math.round((processed / totalFiles) * 100);\n spinner.update(`Indexing sessions... ${percent}% (${processed}/${totalFiles})`);\n }\n\n spinner.succeed(`Indexed ${totalFiles} sessions (${newlyIndexed} new)`);\n\n // Show stats\n const statsAfter = getStats();\n console.log(chalk.dim(` ${statsAfter.sessionCount} sessions, ${statsAfter.embeddingCount} with embeddings\\n`));\n}\n"],"mappings":"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","names":["chalk","existsSync","mkdirSync","homedir","join","dirname","execSync","React","existsSync","readFileSync","join","dirname","fileURLToPath","spawn","useState","useEffect","useCallback","Box","Text","TextInput","basename","dirname","existsSync","Box","Text","jsx","jsxs","Box","Text","basename","jsx","jsxs","Box","Text","basename","Box","Text","jsx","jsxs","Box","Text","Box","Text","jsx","jsxs","Box","Text","existsSync","existsSync","join","content","existsSync","join","existsSync","db","db","db","db","db","db","db","db","db","existsSync","join","join","existsSync","jsx","jsxs","deleteSession","toggleFavorite","useState","useCallback","useEffect","currentSessions","basename","dirname","existsSync","Box","Text","TextInput","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","chalk","statSync","existsSync","chalk","existsSync","statSync","chalk","statSync","existsSync","readFileSync","readdirSync","join","dirname","basename","Spinner","chalk","existsSync","readdirSync","join","statSync","basename","loadSubagentMessages","dirname","readFileSync","chalk","chalk","chalk","execSync","existsSync","readFileSync","writeFileSync","mkdirSync","readdirSync","statSync","homedir","join","dirname","basename","dirname","join","homedir","CMEM_DIR","spinnerFrames","Spinner","chalk","execSync","existsSync","readFileSync","installCommand","mkdirSync","writeFileSync","findAllSessionFiles","readdirSync","statSync","basename","__filename","fileURLToPath","__dirname","dirname","join","existsSync","readFileSync","React","spawn"]}
|